1 #include "node.h"
2 #include "string_bytes.h"
3 #include "util-inl.h"
4 #include "v8.h"
5
6 namespace node {
7
8 using v8::HandleScope;
9 using v8::Isolate;
10 using v8::Local;
11 using v8::Value;
12
ParseEncoding(const char * encoding,enum encoding default_encoding)13 enum encoding ParseEncoding(const char* encoding,
14 enum encoding default_encoding) {
15 switch (encoding[0]) {
16 case 'u':
17 case 'U':
18 // Note: the two first conditions are needed for performance reasons
19 // as "utf8"/"utf-8" is a common case.
20 // (same for other cases below)
21
22 // utf8, utf16le
23 if (encoding[1] == 't' && encoding[2] == 'f') {
24 // Skip `-`
25 const size_t skip = encoding[3] == '-' ? 4 : 3;
26 if (encoding[skip] == '8' && encoding[skip + 1] == '\0')
27 return UTF8;
28 if (strncmp(encoding + skip, "16le", 5) == 0)
29 return UCS2;
30 // ucs2
31 } else if (encoding[1] == 'c' && encoding[2] == 's') {
32 const size_t skip = encoding[3] == '-' ? 4 : 3;
33 if (encoding[skip] == '2' && encoding[skip + 1] == '\0')
34 return UCS2;
35 }
36 if (StringEqualNoCase(encoding, "utf8"))
37 return UTF8;
38 if (StringEqualNoCase(encoding, "utf-8"))
39 return UTF8;
40 if (StringEqualNoCase(encoding, "ucs2"))
41 return UCS2;
42 if (StringEqualNoCase(encoding, "ucs-2"))
43 return UCS2;
44 if (StringEqualNoCase(encoding, "utf16le"))
45 return UCS2;
46 if (StringEqualNoCase(encoding, "utf-16le"))
47 return UCS2;
48 break;
49
50 case 'l':
51 case 'L':
52 // latin1
53 if (encoding[1] == 'a') {
54 if (strncmp(encoding + 2, "tin1", 5) == 0)
55 return LATIN1;
56 }
57 if (StringEqualNoCase(encoding, "latin1"))
58 return LATIN1;
59 break;
60
61 case 'b':
62 case 'B':
63 // binary is a deprecated alias of latin1
64 if (encoding[1] == 'i') {
65 if (strncmp(encoding + 2, "nary", 5) == 0)
66 return LATIN1;
67 // buffer
68 } else if (encoding[1] == 'u') {
69 if (strncmp(encoding + 2, "ffer", 5) == 0)
70 return BUFFER;
71 // base64
72 } else if (encoding[1] == 'a') {
73 if (strncmp(encoding + 2, "se64", 5) == 0)
74 return BASE64;
75 if (strncmp(encoding + 2, "se64url", 8) == 0)
76 return BASE64URL;
77 }
78 if (StringEqualNoCase(encoding, "binary"))
79 return LATIN1; // BINARY is a deprecated alias of LATIN1.
80 if (StringEqualNoCase(encoding, "buffer"))
81 return BUFFER;
82 if (StringEqualNoCase(encoding, "base64"))
83 return BASE64;
84 if (StringEqualNoCase(encoding, "base64url"))
85 return BASE64URL;
86 break;
87
88 case 'a':
89 case 'A':
90 // ascii
91 if (encoding[1] == 's') {
92 if (strncmp(encoding + 2, "cii", 4) == 0)
93 return ASCII;
94 }
95 if (StringEqualNoCase(encoding, "ascii"))
96 return ASCII;
97 break;
98
99 case 'h':
100 case 'H':
101 // hex
102 if (encoding[1] == 'e')
103 if (encoding[2] == 'x' && encoding[3] == '\0')
104 return HEX;
105 if (StringEqualNoCase(encoding, "hex"))
106 return HEX;
107 break;
108 }
109 return default_encoding;
110 }
111
112
ParseEncoding(Isolate * isolate,Local<Value> encoding_v,enum encoding default_encoding)113 enum encoding ParseEncoding(Isolate* isolate,
114 Local<Value> encoding_v,
115 enum encoding default_encoding) {
116 CHECK(!encoding_v.IsEmpty());
117
118 if (!encoding_v->IsString())
119 return default_encoding;
120
121 Utf8Value encoding(isolate, encoding_v);
122
123 return ParseEncoding(*encoding, default_encoding);
124 }
125
Encode(Isolate * isolate,const char * buf,size_t len,enum encoding encoding)126 Local<Value> Encode(Isolate* isolate,
127 const char* buf,
128 size_t len,
129 enum encoding encoding) {
130 CHECK_NE(encoding, UCS2);
131 Local<Value> error;
132 return StringBytes::Encode(isolate, buf, len, encoding, &error)
133 .ToLocalChecked();
134 }
135
Encode(Isolate * isolate,const uint16_t * buf,size_t len)136 Local<Value> Encode(Isolate* isolate, const uint16_t* buf, size_t len) {
137 Local<Value> error;
138 return StringBytes::Encode(isolate, buf, len, &error)
139 .ToLocalChecked();
140 }
141
142 // Returns -1 if the handle was not valid for decoding
DecodeBytes(Isolate * isolate,Local<Value> val,enum encoding encoding)143 ssize_t DecodeBytes(Isolate* isolate,
144 Local<Value> val,
145 enum encoding encoding) {
146 HandleScope scope(isolate);
147
148 return StringBytes::Size(isolate, val, encoding).FromMaybe(-1);
149 }
150
151 // Returns number of bytes written.
DecodeWrite(Isolate * isolate,char * buf,size_t buflen,Local<Value> val,enum encoding encoding)152 ssize_t DecodeWrite(Isolate* isolate,
153 char* buf,
154 size_t buflen,
155 Local<Value> val,
156 enum encoding encoding) {
157 return StringBytes::Write(isolate, buf, buflen, val, encoding);
158 }
159
160 } // namespace node
161