• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/inspector/string-16.h"
6 
7 #include <algorithm>
8 #include <cctype>
9 #include <cinttypes>
10 #include <cstdlib>
11 #include <cstring>
12 #include <limits>
13 #include <string>
14 
15 #include "../../third_party/inspector_protocol/crdtp/cbor.h"
16 #include "src/base/platform/platform.h"
17 #include "src/inspector/v8-string-conversions.h"
18 #include "src/numbers/conversions.h"
19 
20 namespace v8_inspector {
21 
22 namespace {
23 
isASCII(UChar c)24 bool isASCII(UChar c) { return !(c & ~0x7F); }
25 
isSpaceOrNewLine(UChar c)26 bool isSpaceOrNewLine(UChar c) {
27   return isASCII(c) && c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9));
28 }
29 
charactersToInteger(const UChar * characters,size_t length,bool * ok=nullptr)30 int64_t charactersToInteger(const UChar* characters, size_t length,
31                             bool* ok = nullptr) {
32   std::vector<char> buffer;
33   buffer.reserve(length + 1);
34   for (size_t i = 0; i < length; ++i) {
35     if (!isASCII(characters[i])) {
36       if (ok) *ok = false;
37       return 0;
38     }
39     buffer.push_back(static_cast<char>(characters[i]));
40   }
41   buffer.push_back('\0');
42 
43   char* endptr;
44   int64_t result =
45       static_cast<int64_t>(std::strtoll(buffer.data(), &endptr, 10));
46   if (ok) *ok = !(*endptr);
47   return result;
48 }
49 }  // namespace
50 
String16(const UChar * characters,size_t size)51 String16::String16(const UChar* characters, size_t size)
52     : m_impl(characters, size) {}
53 
String16(const UChar * characters)54 String16::String16(const UChar* characters) : m_impl(characters) {}
55 
String16(const char * characters)56 String16::String16(const char* characters)
57     : String16(characters, std::strlen(characters)) {}
58 
String16(const char * characters,size_t size)59 String16::String16(const char* characters, size_t size) {
60   m_impl.resize(size);
61   for (size_t i = 0; i < size; ++i) m_impl[i] = characters[i];
62 }
63 
String16(const std::basic_string<UChar> & impl)64 String16::String16(const std::basic_string<UChar>& impl) : m_impl(impl) {}
65 
String16(std::basic_string<UChar> && impl)66 String16::String16(std::basic_string<UChar>&& impl) : m_impl(impl) {}
67 
68 // static
fromInteger(int number)69 String16 String16::fromInteger(int number) {
70   char arr[50];
71   v8::internal::Vector<char> buffer(arr, arraysize(arr));
72   return String16(IntToCString(number, buffer));
73 }
74 
75 // static
fromInteger(size_t number)76 String16 String16::fromInteger(size_t number) {
77   const size_t kBufferSize = 50;
78   char buffer[kBufferSize];
79 #if !defined(_WIN32) && !defined(_WIN64)
80   v8::base::OS::SNPrintF(buffer, kBufferSize, "%zu", number);
81 #else
82   v8::base::OS::SNPrintF(buffer, kBufferSize, "%Iu", number);
83 #endif
84   return String16(buffer);
85 }
86 
87 // static
fromInteger64(int64_t number)88 String16 String16::fromInteger64(int64_t number) {
89   char buffer[50];
90   v8::base::OS::SNPrintF(buffer, arraysize(buffer), "%" PRId64 "", number);
91   return String16(buffer);
92 }
93 
94 // static
fromDouble(double number)95 String16 String16::fromDouble(double number) {
96   char arr[50];
97   v8::internal::Vector<char> buffer(arr, arraysize(arr));
98   return String16(DoubleToCString(number, buffer));
99 }
100 
101 // static
fromDouble(double number,int precision)102 String16 String16::fromDouble(double number, int precision) {
103   std::unique_ptr<char[]> str(
104       v8::internal::DoubleToPrecisionCString(number, precision));
105   return String16(str.get());
106 }
107 
toInteger64(bool * ok) const108 int64_t String16::toInteger64(bool* ok) const {
109   return charactersToInteger(characters16(), length(), ok);
110 }
111 
toInteger(bool * ok) const112 int String16::toInteger(bool* ok) const {
113   int64_t result = toInteger64(ok);
114   if (ok && *ok) {
115     *ok = result <= std::numeric_limits<int>::max() &&
116           result >= std::numeric_limits<int>::min();
117   }
118   return static_cast<int>(result);
119 }
120 
stripWhiteSpace() const121 String16 String16::stripWhiteSpace() const {
122   if (!length()) return String16();
123 
124   size_t start = 0;
125   size_t end = length() - 1;
126 
127   // skip white space from start
128   while (start <= end && isSpaceOrNewLine(characters16()[start])) ++start;
129 
130   // only white space
131   if (start > end) return String16();
132 
133   // skip white space from end
134   while (end && isSpaceOrNewLine(characters16()[end])) --end;
135 
136   if (!start && end == length() - 1) return *this;
137   return String16(characters16() + start, end + 1 - start);
138 }
139 
140 String16Builder::String16Builder() = default;
141 
append(const String16 & s)142 void String16Builder::append(const String16& s) {
143   m_buffer.insert(m_buffer.end(), s.characters16(),
144                   s.characters16() + s.length());
145 }
146 
append(UChar c)147 void String16Builder::append(UChar c) { m_buffer.push_back(c); }
148 
append(char c)149 void String16Builder::append(char c) {
150   UChar u = c;
151   m_buffer.push_back(u);
152 }
153 
append(const UChar * characters,size_t length)154 void String16Builder::append(const UChar* characters, size_t length) {
155   m_buffer.insert(m_buffer.end(), characters, characters + length);
156 }
157 
append(const char * characters,size_t length)158 void String16Builder::append(const char* characters, size_t length) {
159   m_buffer.insert(m_buffer.end(), characters, characters + length);
160 }
161 
appendNumber(int number)162 void String16Builder::appendNumber(int number) {
163   constexpr int kBufferSize = 11;
164   char buffer[kBufferSize];
165   int chars = v8::base::OS::SNPrintF(buffer, kBufferSize, "%d", number);
166   DCHECK_LE(0, chars);
167   m_buffer.insert(m_buffer.end(), buffer, buffer + chars);
168 }
169 
appendNumber(size_t number)170 void String16Builder::appendNumber(size_t number) {
171   constexpr int kBufferSize = 20;
172   char buffer[kBufferSize];
173 #if !defined(_WIN32) && !defined(_WIN64)
174   int chars = v8::base::OS::SNPrintF(buffer, kBufferSize, "%zu", number);
175 #else
176   int chars = v8::base::OS::SNPrintF(buffer, kBufferSize, "%Iu", number);
177 #endif
178   DCHECK_LE(0, chars);
179   m_buffer.insert(m_buffer.end(), buffer, buffer + chars);
180 }
181 
appendUnsignedAsHex(uint64_t number)182 void String16Builder::appendUnsignedAsHex(uint64_t number) {
183   constexpr int kBufferSize = 17;
184   char buffer[kBufferSize];
185   int chars =
186       v8::base::OS::SNPrintF(buffer, kBufferSize, "%016" PRIx64, number);
187   DCHECK_LE(0, chars);
188   m_buffer.insert(m_buffer.end(), buffer, buffer + chars);
189 }
190 
appendUnsignedAsHex(uint32_t number)191 void String16Builder::appendUnsignedAsHex(uint32_t number) {
192   constexpr int kBufferSize = 9;
193   char buffer[kBufferSize];
194   int chars = v8::base::OS::SNPrintF(buffer, kBufferSize, "%08" PRIx32, number);
195   DCHECK_LE(0, chars);
196   m_buffer.insert(m_buffer.end(), buffer, buffer + chars);
197 }
198 
appendUnsignedAsHex(uint8_t number)199 void String16Builder::appendUnsignedAsHex(uint8_t number) {
200   constexpr int kBufferSize = 3;
201   char buffer[kBufferSize];
202   int chars = v8::base::OS::SNPrintF(buffer, kBufferSize, "%02" PRIx8, number);
203   DCHECK_LE(0, chars);
204   m_buffer.insert(m_buffer.end(), buffer, buffer + chars);
205 }
206 
toString()207 String16 String16Builder::toString() {
208   return String16(m_buffer.data(), m_buffer.size());
209 }
210 
reserveCapacity(size_t capacity)211 void String16Builder::reserveCapacity(size_t capacity) {
212   m_buffer.reserve(capacity);
213 }
214 
fromUTF8(const char * stringStart,size_t length)215 String16 String16::fromUTF8(const char* stringStart, size_t length) {
216   return String16(UTF8ToUTF16(stringStart, length));
217 }
218 
fromUTF16LE(const UChar * stringStart,size_t length)219 String16 String16::fromUTF16LE(const UChar* stringStart, size_t length) {
220 #ifdef V8_TARGET_BIG_ENDIAN
221   // Need to flip the byte order on big endian machines.
222   String16Builder builder;
223   builder.reserveCapacity(length);
224   for (size_t i = 0; i < length; i++) {
225     const UChar utf16be_char =
226         stringStart[i] << 8 | (stringStart[i] >> 8 & 0x00FF);
227     builder.append(utf16be_char);
228   }
229   return builder.toString();
230 #else
231   // No need to do anything on little endian machines.
232   return String16(stringStart, length);
233 #endif  // V8_TARGET_BIG_ENDIAN
234 }
235 
utf8() const236 std::string String16::utf8() const {
237   return UTF16ToUTF8(m_impl.data(), m_impl.size());
238 }
239 
240 }  // namespace v8_inspector
241 
242 namespace v8_crdtp {
Serialize(const v8_inspector::String16 & str,std::vector<uint8_t> * out)243 void SerializerTraits<v8_inspector::String16>::Serialize(
244     const v8_inspector::String16& str, std::vector<uint8_t>* out) {
245   cbor::EncodeFromUTF16(
246       span<uint16_t>(reinterpret_cast<const uint16_t*>(str.characters16()),
247                      str.length()),
248       out);
249 }
250 }  // namespace v8_crdtp
251