1 /** 2 * Contents of this file are snippets from node.cc 3 * see http://www.nodejs.org/ 4 * 5 * Node's license follows: 6 * 7 * Copyright 2009, 2010 Ryan Lienhart Dahl. All rights reserved. 8 * Permission is hereby granted, free of charge, to any person obtaining a copy 9 * of this software and associated documentation files (the "Software"), to 10 * deal in the Software without restriction, including without limitation the 11 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 12 * sell copies of the Software, and to permit persons to whom the Software is 13 * furnished to do so, subject to the following conditions: 14 */ 15 #include <v8.h> 16 #include <string.h> 17 18 #include "logging.h" 19 #include "node_object_wrap.h" 20 21 #include "node_util.h" 22 23 enum encoding ParseEncoding(v8::Handle<v8::Value> encoding_v, enum encoding _default) { 24 v8::HandleScope scope; 25 26 if (!encoding_v->IsString()) return _default; 27 28 v8::String::Utf8Value encoding(encoding_v->ToString()); 29 30 if (strcasecmp(*encoding, "utf8") == 0) { 31 return UTF8; 32 } else if (strcasecmp(*encoding, "utf-8") == 0) { 33 return UTF8; 34 } else if (strcasecmp(*encoding, "ascii") == 0) { 35 return ASCII; 36 } else if (strcasecmp(*encoding, "binary") == 0) { 37 return BINARY; 38 } else if (strcasecmp(*encoding, "raw") == 0) { 39 fprintf(stderr, "'raw' (array of integers) has been removed. " 40 "Use 'binary'.\n"); 41 return BINARY; 42 } else if (strcasecmp(*encoding, "raws") == 0) { 43 fprintf(stderr, "'raws' encoding has been renamed to 'binary'. " 44 "Please update your code.\n"); 45 return BINARY; 46 } else { 47 return _default; 48 } 49 } 50 51 v8::Local<v8::Value> Encode(const void *buf, size_t len, enum encoding encoding) { 52 v8::HandleScope scope; 53 54 if (!len) return scope.Close(v8::String::Empty()); 55 56 if (encoding == BINARY) { 57 const unsigned char *cbuf = static_cast<const unsigned char*>(buf); 58 uint16_t * twobytebuf = new uint16_t[len]; 59 for (size_t i = 0; i < len; i++) { 60 // XXX is the following line platform independent? 61 twobytebuf[i] = cbuf[i]; 62 } 63 v8::Local<v8::String> chunk = v8::String::New(twobytebuf, len); 64 delete [] twobytebuf; // TODO use ExternalTwoBytev8::String? 65 return scope.Close(chunk); 66 } 67 68 // utf8 or ascii encoding 69 v8::Local<v8::String> chunk = v8::String::New((const char*)buf, len); 70 return scope.Close(chunk); 71 } 72 73 // Returns -1 if the handle was not valid for decoding 74 ssize_t DecodeBytes(v8::Handle<v8::Value> val, enum encoding encoding) { 75 v8::HandleScope scope; 76 77 if (val->IsArray()) { 78 fprintf(stderr, "'raw' encoding (array of integers) has been removed. " 79 "Use 'binary'.\n"); 80 assert(0); 81 return -1; 82 } 83 84 v8::Local<v8::String> str = val->ToString(); 85 86 if (encoding == UTF8) return str->Utf8Length(); 87 88 return str->Length(); 89 } 90 91 #ifndef MIN 92 # define MIN(a, b) ((a) < (b) ? (a) : (b)) 93 #endif 94 95 // Returns number of bytes written. 96 ssize_t DecodeWrite(char *buf, 97 size_t buflen, 98 v8::Handle<v8::Value> val, 99 enum encoding encoding) { 100 v8::HandleScope scope; 101 102 // XXX 103 // A lot of improvement can be made here. See: 104 // http://code.google.com/p/v8/issues/detail?id=270 105 // http://groups.google.com/group/v8-dev/browse_thread/thread/dba28a81d9215291/ece2b50a3b4022c 106 // http://groups.google.com/group/v8-users/browse_thread/thread/1f83b0ba1f0a611 107 108 if (val->IsArray()) { 109 fprintf(stderr, "'raw' encoding (array of integers) has been removed. " 110 "Use 'binary'.\n"); 111 assert(0); 112 return -1; 113 } 114 115 v8::Local<v8::String> str = val->ToString(); 116 117 if (encoding == UTF8) { 118 str->WriteUtf8(buf, buflen, NULL, v8::String::HINT_MANY_WRITES_EXPECTED); 119 return buflen; 120 } 121 122 if (encoding == ASCII) { 123 str->WriteAscii(buf, 0, buflen, v8::String::HINT_MANY_WRITES_EXPECTED); 124 return buflen; 125 } 126 127 // THIS IS AWFUL!!! FIXME 128 129 assert(encoding == BINARY); 130 131 uint16_t * twobytebuf = new uint16_t[buflen]; 132 133 str->Write(twobytebuf, 0, buflen, v8::String::HINT_MANY_WRITES_EXPECTED); 134 135 for (size_t i = 0; i < buflen; i++) { 136 unsigned char *b = reinterpret_cast<unsigned char*>(&twobytebuf[i]); 137 assert(b[1] == 0); 138 buf[i] = b[0]; 139 } 140 141 delete [] twobytebuf; 142 143 return buflen; 144 } 145