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
ParseEncoding(v8::Handle<v8::Value> encoding_v,enum encoding _default)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
Encode(const void * buf,size_t len,enum encoding encoding)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
DecodeBytes(v8::Handle<v8::Value> val,enum encoding encoding)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.
DecodeWrite(char * buf,size_t buflen,v8::Handle<v8::Value> val,enum encoding encoding)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