Coverage Report

Created: 2025-08-28 09:57

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