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 20namespace v8_inspector { 21 22namespace { 23 24bool isASCII(UChar c) { return !(c & ~0x7F); } 25 26bool isSpaceOrNewLine(UChar c) { 27 return isASCII(c) && c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); 28} 29 30int64_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 51String16::String16(const UChar* characters, size_t size) 52 : m_impl(characters, size) {} 53 54String16::String16(const UChar* characters) : m_impl(characters) {} 55 56String16::String16(const char* characters) 57 : String16(characters, std::strlen(characters)) {} 58 59String16::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 64String16::String16(const std::basic_string<UChar>& impl) : m_impl(impl) {} 65 66String16::String16(std::basic_string<UChar>&& impl) : m_impl(impl) {} 67 68// static 69String16 String16::fromInteger(int number) { 70 char arr[50]; 71 v8::base::Vector<char> buffer(arr, arraysize(arr)); 72 return String16(v8::internal::IntToCString(number, buffer)); 73} 74 75// static 76String16 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 88String16 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 95String16 String16::fromDouble(double number) { 96 char arr[50]; 97 v8::base::Vector<char> buffer(arr, arraysize(arr)); 98 return String16(v8::internal::DoubleToCString(number, buffer)); 99} 100 101// static 102String16 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 108int64_t String16::toInteger64(bool* ok) const { 109 return charactersToInteger(characters16(), length(), ok); 110} 111 112int 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 121String16 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 140String16Builder::String16Builder() = default; 141 142void String16Builder::append(const String16& s) { 143 m_buffer.insert(m_buffer.end(), s.characters16(), 144 s.characters16() + s.length()); 145} 146 147void String16Builder::append(UChar c) { m_buffer.push_back(c); } 148 149void String16Builder::append(char c) { 150 UChar u = c; 151 m_buffer.push_back(u); 152} 153 154void String16Builder::append(const UChar* characters, size_t length) { 155 m_buffer.insert(m_buffer.end(), characters, characters + length); 156} 157 158void String16Builder::append(const char* characters, size_t length) { 159 m_buffer.insert(m_buffer.end(), characters, characters + length); 160} 161 162void 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 170void 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 182void 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 191void 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 199void 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 207String16 String16Builder::toString() { 208 return String16(m_buffer.data(), m_buffer.size()); 209} 210 211void String16Builder::reserveCapacity(size_t capacity) { 212 m_buffer.reserve(capacity); 213} 214 215String16 String16::fromUTF8(const char* stringStart, size_t length) { 216 return String16(UTF8ToUTF16(stringStart, length)); 217} 218 219String16 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 236std::string String16::utf8() const { 237 return UTF16ToUTF8(m_impl.data(), m_impl.size()); 238} 239 240} // namespace v8_inspector 241