1 #include "node_string.h"
2 #include "node/inspector/protocol/Protocol.h"
3 #include "node_util.h"
4 #include "simdutf.h"
5 #include "util-inl.h"
6
7 namespace node {
8 namespace inspector {
9 namespace protocol {
10 namespace StringUtil {
11
12 size_t kNotFound = std::string::npos;
13
14 // NOLINTNEXTLINE(runtime/references) V8 API requirement
builderAppendQuotedString(StringBuilder & builder,const std::string_view string)15 void builderAppendQuotedString(StringBuilder& builder,
16 const std::string_view string) {
17 builder.put('"');
18 if (!string.empty()) {
19 size_t expected_utf16_length =
20 simdutf::utf16_length_from_utf8(string.data(), string.length());
21 MaybeStackBuffer<char16_t> buffer(expected_utf16_length);
22 // simdutf::convert_utf8_to_utf16 returns zero in case of error.
23 size_t utf16_length = simdutf::convert_utf8_to_utf16(
24 string.data(), string.length(), buffer.out());
25 // We have that utf16_length == expected_utf16_length if and only
26 // if the input was a valid UTF-8 string.
27 if (utf16_length != 0) {
28 CHECK_EQ(expected_utf16_length, utf16_length);
29 escapeWideStringForJSON(reinterpret_cast<const uint16_t*>(buffer.out()),
30 utf16_length,
31 &builder);
32 } // Otherwise, we had an invalid UTF-8 input.
33 }
34 builder.put('"');
35 }
36
parseJSON(const std::string_view string)37 std::unique_ptr<Value> parseJSON(const std::string_view string) {
38 if (string.empty())
39 return nullptr;
40 size_t expected_utf16_length =
41 simdutf::utf16_length_from_utf8(string.data(), string.length());
42 MaybeStackBuffer<char16_t> buffer(expected_utf16_length);
43 // simdutf::convert_utf8_to_utf16 returns zero in case of error.
44 size_t utf16_length = simdutf::convert_utf8_to_utf16(
45 string.data(), string.length(), buffer.out());
46 // We have that utf16_length == expected_utf16_length if and only
47 // if the input was a valid UTF-8 string.
48 if (utf16_length == 0) return nullptr; // We had an invalid UTF-8 input.
49 CHECK_EQ(expected_utf16_length, utf16_length);
50 return parseJSONCharacters(reinterpret_cast<const uint16_t*>(buffer.out()),
51 utf16_length);
52 }
53
parseJSON(v8_inspector::StringView string)54 std::unique_ptr<Value> parseJSON(v8_inspector::StringView string) {
55 if (string.length() == 0)
56 return nullptr;
57 if (string.is8Bit())
58 return parseJSONCharacters(string.characters8(), string.length());
59 return parseJSONCharacters(string.characters16(), string.length());
60 }
61
StringViewToUtf8(v8_inspector::StringView view)62 String StringViewToUtf8(v8_inspector::StringView view) {
63 if (view.length() == 0)
64 return "";
65 if (view.is8Bit()) {
66 return std::string(reinterpret_cast<const char*>(view.characters8()),
67 view.length());
68 }
69 const char16_t* source =
70 reinterpret_cast<const char16_t*>(view.characters16());
71 size_t expected_utf8_length =
72 simdutf::utf8_length_from_utf16(source, view.length());
73 MaybeStackBuffer<char> buffer(expected_utf8_length);
74 // convert_utf16_to_utf8 returns zero in case of error.
75 size_t utf8_length =
76 simdutf::convert_utf16_to_utf8(source, view.length(), buffer.out());
77 // We have that utf8_length == expected_utf8_length if and only
78 // if the input was a valid UTF-16 string. Otherwise, utf8_length
79 // must be zero.
80 CHECK(utf8_length == 0 || utf8_length == expected_utf8_length);
81 // An invalid UTF-16 input will generate the empty string:
82 return String(buffer.out(), utf8_length);
83 }
84
fromDouble(double d)85 String fromDouble(double d) {
86 std::ostringstream stream;
87 stream.imbue(std::locale::classic()); // Ignore current locale
88 stream << d;
89 return stream.str();
90 }
91
toDouble(const char * buffer,size_t length,bool * ok)92 double toDouble(const char* buffer, size_t length, bool* ok) {
93 std::istringstream stream(std::string(buffer, length));
94 stream.imbue(std::locale::classic()); // Ignore current locale
95 double d;
96 stream >> d;
97 *ok = !stream.fail();
98 return d;
99 }
100
parseMessage(const std::string_view message,bool binary)101 std::unique_ptr<Value> parseMessage(const std::string_view message,
102 bool binary) {
103 if (binary) {
104 return Value::parseBinary(
105 reinterpret_cast<const uint8_t*>(message.data()),
106 message.length());
107 }
108 return parseJSON(message);
109 }
110
jsonToMessage(String message)111 ProtocolMessage jsonToMessage(String message) {
112 return message;
113 }
114
binaryToMessage(std::vector<uint8_t> message)115 ProtocolMessage binaryToMessage(std::vector<uint8_t> message) {
116 return std::string(reinterpret_cast<const char*>(message.data()),
117 message.size());
118 }
119
fromUTF8(const uint8_t * data,size_t length)120 String fromUTF8(const uint8_t* data, size_t length) {
121 return std::string(reinterpret_cast<const char*>(data), length);
122 }
123
fromUTF16(const uint16_t * data,size_t length)124 String fromUTF16(const uint16_t* data, size_t length) {
125 auto casted_data = reinterpret_cast<const char16_t*>(data);
126 size_t expected_utf8_length =
127 simdutf::utf8_length_from_utf16(casted_data, length);
128 MaybeStackBuffer<char> buffer(expected_utf8_length);
129 // simdutf::convert_utf16_to_utf8 returns zero in case of error.
130 size_t utf8_length =
131 simdutf::convert_utf16_to_utf8(casted_data, length, buffer.out());
132 // We have that utf8_length == expected_utf8_length if and only
133 // if the input was a valid UTF-16 string. Otherwise, utf8_length
134 // must be zero.
135 CHECK(utf8_length == 0 || utf8_length == expected_utf8_length);
136 // An invalid UTF-16 input will generate the empty string:
137 return String(buffer.out(), utf8_length);
138 }
139
CharactersUTF8(const std::string_view s)140 const uint8_t* CharactersUTF8(const std::string_view s) {
141 return reinterpret_cast<const uint8_t*>(s.data());
142 }
143
CharacterCount(const std::string_view s)144 size_t CharacterCount(const std::string_view s) {
145 // The utf32_length_from_utf8 function calls count_utf8.
146 // The count_utf8 function counts the number of code points
147 // (characters) in the string, assuming that the string is valid Unicode.
148 // TODO(@anonrig): Test to make sure CharacterCount returns correctly.
149 return simdutf::utf32_length_from_utf8(s.data(), s.length());
150 }
151
152 } // namespace StringUtil
153 } // namespace protocol
154 } // namespace inspector
155 } // namespace node
156
157