xref: /third_party/node/src/api/encoding.cc (revision 1cb0ef41)
1#include "node.h"
2#include "string_bytes.h"
3#include "util-inl.h"
4#include "v8.h"
5
6namespace node {
7
8using v8::HandleScope;
9using v8::Isolate;
10using v8::Local;
11using v8::Value;
12
13enum 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
113enum 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
126Local<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
136Local<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
143ssize_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.
152ssize_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