11cb0ef41Sopenharmony_ci// Copyright 2016 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/inspector/string-util.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <cinttypes>
81cb0ef41Sopenharmony_ci#include <cmath>
91cb0ef41Sopenharmony_ci#include <cstddef>
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci#include "src/base/platform/platform.h"
121cb0ef41Sopenharmony_ci#include "src/inspector/protocol/Protocol.h"
131cb0ef41Sopenharmony_ci#include "src/numbers/conversions.h"
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_cinamespace v8_inspector {
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_cinamespace protocol {
181cb0ef41Sopenharmony_cinamespace {
191cb0ef41Sopenharmony_cistd::pair<uint8_t, uint8_t> SplitByte(uint8_t byte, uint8_t split) {
201cb0ef41Sopenharmony_ci  return {byte >> split, (byte & ((1 << split) - 1)) << (6 - split)};
211cb0ef41Sopenharmony_ci}
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_civ8::Maybe<uint8_t> DecodeByte(char byte) {
241cb0ef41Sopenharmony_ci  if ('A' <= byte && byte <= 'Z') return v8::Just<uint8_t>(byte - 'A');
251cb0ef41Sopenharmony_ci  if ('a' <= byte && byte <= 'z') return v8::Just<uint8_t>(byte - 'a' + 26);
261cb0ef41Sopenharmony_ci  if ('0' <= byte && byte <= '9')
271cb0ef41Sopenharmony_ci    return v8::Just<uint8_t>(byte - '0' + 26 + 26);
281cb0ef41Sopenharmony_ci  if (byte == '+') return v8::Just<uint8_t>(62);
291cb0ef41Sopenharmony_ci  if (byte == '/') return v8::Just<uint8_t>(63);
301cb0ef41Sopenharmony_ci  return v8::Nothing<uint8_t>();
311cb0ef41Sopenharmony_ci}
321cb0ef41Sopenharmony_ci}  // namespace
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ciString Binary::toBase64() const {
351cb0ef41Sopenharmony_ci  const char* table =
361cb0ef41Sopenharmony_ci      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
371cb0ef41Sopenharmony_ci  if (size() == 0) return {};
381cb0ef41Sopenharmony_ci  std::basic_string<UChar> result;
391cb0ef41Sopenharmony_ci  result.reserve(4 * ((size() + 2) / 3));
401cb0ef41Sopenharmony_ci  uint8_t last = 0;
411cb0ef41Sopenharmony_ci  for (size_t n = 0; n < size();) {
421cb0ef41Sopenharmony_ci    auto split = SplitByte((*bytes_)[n], 2 + 2 * (n % 3));
431cb0ef41Sopenharmony_ci    result.push_back(table[split.first | last]);
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci    ++n;
461cb0ef41Sopenharmony_ci    if (n < size() && n % 3 == 0) {
471cb0ef41Sopenharmony_ci      result.push_back(table[split.second]);
481cb0ef41Sopenharmony_ci      last = 0;
491cb0ef41Sopenharmony_ci    } else {
501cb0ef41Sopenharmony_ci      last = split.second;
511cb0ef41Sopenharmony_ci    }
521cb0ef41Sopenharmony_ci  }
531cb0ef41Sopenharmony_ci  result.push_back(table[last]);
541cb0ef41Sopenharmony_ci  while (result.size() % 4 > 0) result.push_back('=');
551cb0ef41Sopenharmony_ci  return String16(std::move(result));
561cb0ef41Sopenharmony_ci}
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci/* static */
591cb0ef41Sopenharmony_ciBinary Binary::fromBase64(const String& base64, bool* success) {
601cb0ef41Sopenharmony_ci  if (base64.isEmpty()) {
611cb0ef41Sopenharmony_ci    *success = true;
621cb0ef41Sopenharmony_ci    return Binary::fromSpan(nullptr, 0);
631cb0ef41Sopenharmony_ci  }
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci  *success = false;
661cb0ef41Sopenharmony_ci  // Fail if the length is invalid or decoding would overflow.
671cb0ef41Sopenharmony_ci  if (base64.length() % 4 != 0 || base64.length() + 4 < base64.length()) {
681cb0ef41Sopenharmony_ci    return Binary::fromSpan(nullptr, 0);
691cb0ef41Sopenharmony_ci  }
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci  std::vector<uint8_t> result;
721cb0ef41Sopenharmony_ci  result.reserve(3 * base64.length() / 4);
731cb0ef41Sopenharmony_ci  char pad = '=';
741cb0ef41Sopenharmony_ci  // Iterate groups of four
751cb0ef41Sopenharmony_ci  for (size_t i = 0; i < base64.length(); i += 4) {
761cb0ef41Sopenharmony_ci    uint8_t a = 0, b = 0, c = 0, d = 0;
771cb0ef41Sopenharmony_ci    if (!DecodeByte(base64[i + 0]).To(&a)) return Binary::fromSpan(nullptr, 0);
781cb0ef41Sopenharmony_ci    if (!DecodeByte(base64[i + 1]).To(&b)) return Binary::fromSpan(nullptr, 0);
791cb0ef41Sopenharmony_ci    if (!DecodeByte(base64[i + 2]).To(&c)) {
801cb0ef41Sopenharmony_ci      // Padding is allowed only in the group on the last two positions
811cb0ef41Sopenharmony_ci      if (i + 4 < base64.length() || base64[i + 2] != pad ||
821cb0ef41Sopenharmony_ci          base64[i + 3] != pad) {
831cb0ef41Sopenharmony_ci        return Binary::fromSpan(nullptr, 0);
841cb0ef41Sopenharmony_ci      }
851cb0ef41Sopenharmony_ci    }
861cb0ef41Sopenharmony_ci    if (!DecodeByte(base64[i + 3]).To(&d)) {
871cb0ef41Sopenharmony_ci      // Padding is allowed only in the group on the last two positions
881cb0ef41Sopenharmony_ci      if (i + 4 < base64.length() || base64[i + 3] != pad) {
891cb0ef41Sopenharmony_ci        return Binary::fromSpan(nullptr, 0);
901cb0ef41Sopenharmony_ci      }
911cb0ef41Sopenharmony_ci    }
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci    result.push_back((a << 2) | (b >> 4));
941cb0ef41Sopenharmony_ci    if (base64[i + 2] != '=') result.push_back((0xFF & (b << 4)) | (c >> 2));
951cb0ef41Sopenharmony_ci    if (base64[i + 3] != '=') result.push_back((0xFF & (c << 6)) | d);
961cb0ef41Sopenharmony_ci  }
971cb0ef41Sopenharmony_ci  *success = true;
981cb0ef41Sopenharmony_ci  return Binary(std::make_shared<std::vector<uint8_t>>(std::move(result)));
991cb0ef41Sopenharmony_ci}
1001cb0ef41Sopenharmony_ci}  // namespace protocol
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_civ8::Local<v8::String> toV8String(v8::Isolate* isolate, const String16& string) {
1031cb0ef41Sopenharmony_ci  if (string.isEmpty()) return v8::String::Empty(isolate);
1041cb0ef41Sopenharmony_ci  DCHECK_GT(v8::String::kMaxLength, string.length());
1051cb0ef41Sopenharmony_ci  return v8::String::NewFromTwoByte(
1061cb0ef41Sopenharmony_ci             isolate, reinterpret_cast<const uint16_t*>(string.characters16()),
1071cb0ef41Sopenharmony_ci             v8::NewStringType::kNormal, static_cast<int>(string.length()))
1081cb0ef41Sopenharmony_ci      .ToLocalChecked();
1091cb0ef41Sopenharmony_ci}
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_civ8::Local<v8::String> toV8StringInternalized(v8::Isolate* isolate,
1121cb0ef41Sopenharmony_ci                                             const String16& string) {
1131cb0ef41Sopenharmony_ci  if (string.isEmpty()) return v8::String::Empty(isolate);
1141cb0ef41Sopenharmony_ci  DCHECK_GT(v8::String::kMaxLength, string.length());
1151cb0ef41Sopenharmony_ci  return v8::String::NewFromTwoByte(
1161cb0ef41Sopenharmony_ci             isolate, reinterpret_cast<const uint16_t*>(string.characters16()),
1171cb0ef41Sopenharmony_ci             v8::NewStringType::kInternalized,
1181cb0ef41Sopenharmony_ci             static_cast<int>(string.length()))
1191cb0ef41Sopenharmony_ci      .ToLocalChecked();
1201cb0ef41Sopenharmony_ci}
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_civ8::Local<v8::String> toV8StringInternalized(v8::Isolate* isolate,
1231cb0ef41Sopenharmony_ci                                             const char* str) {
1241cb0ef41Sopenharmony_ci  return v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kInternalized)
1251cb0ef41Sopenharmony_ci      .ToLocalChecked();
1261cb0ef41Sopenharmony_ci}
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_civ8::Local<v8::String> toV8String(v8::Isolate* isolate,
1291cb0ef41Sopenharmony_ci                                 const StringView& string) {
1301cb0ef41Sopenharmony_ci  if (!string.length()) return v8::String::Empty(isolate);
1311cb0ef41Sopenharmony_ci  DCHECK_GT(v8::String::kMaxLength, string.length());
1321cb0ef41Sopenharmony_ci  if (string.is8Bit())
1331cb0ef41Sopenharmony_ci    return v8::String::NewFromOneByte(
1341cb0ef41Sopenharmony_ci               isolate, reinterpret_cast<const uint8_t*>(string.characters8()),
1351cb0ef41Sopenharmony_ci               v8::NewStringType::kNormal, static_cast<int>(string.length()))
1361cb0ef41Sopenharmony_ci        .ToLocalChecked();
1371cb0ef41Sopenharmony_ci  return v8::String::NewFromTwoByte(
1381cb0ef41Sopenharmony_ci             isolate, reinterpret_cast<const uint16_t*>(string.characters16()),
1391cb0ef41Sopenharmony_ci             v8::NewStringType::kNormal, static_cast<int>(string.length()))
1401cb0ef41Sopenharmony_ci      .ToLocalChecked();
1411cb0ef41Sopenharmony_ci}
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ciString16 toProtocolString(v8::Isolate* isolate, v8::Local<v8::String> value) {
1441cb0ef41Sopenharmony_ci  if (value.IsEmpty() || value->IsNullOrUndefined()) return String16();
1451cb0ef41Sopenharmony_ci  std::unique_ptr<UChar[]> buffer(new UChar[value->Length()]);
1461cb0ef41Sopenharmony_ci  value->Write(isolate, reinterpret_cast<uint16_t*>(buffer.get()), 0,
1471cb0ef41Sopenharmony_ci               value->Length());
1481cb0ef41Sopenharmony_ci  return String16(buffer.get(), value->Length());
1491cb0ef41Sopenharmony_ci}
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ciString16 toProtocolStringWithTypeCheck(v8::Isolate* isolate,
1521cb0ef41Sopenharmony_ci                                       v8::Local<v8::Value> value) {
1531cb0ef41Sopenharmony_ci  if (value.IsEmpty() || !value->IsString()) return String16();
1541cb0ef41Sopenharmony_ci  return toProtocolString(isolate, value.As<v8::String>());
1551cb0ef41Sopenharmony_ci}
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ciString16 toString16(const StringView& string) {
1581cb0ef41Sopenharmony_ci  if (!string.length()) return String16();
1591cb0ef41Sopenharmony_ci  if (string.is8Bit())
1601cb0ef41Sopenharmony_ci    return String16(reinterpret_cast<const char*>(string.characters8()),
1611cb0ef41Sopenharmony_ci                    string.length());
1621cb0ef41Sopenharmony_ci  return String16(string.characters16(), string.length());
1631cb0ef41Sopenharmony_ci}
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ciStringView toStringView(const String16& string) {
1661cb0ef41Sopenharmony_ci  if (string.isEmpty()) return StringView();
1671cb0ef41Sopenharmony_ci  return StringView(string.characters16(), string.length());
1681cb0ef41Sopenharmony_ci}
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_cibool stringViewStartsWith(const StringView& string, const char* prefix) {
1711cb0ef41Sopenharmony_ci  if (!string.length()) return !(*prefix);
1721cb0ef41Sopenharmony_ci  if (string.is8Bit()) {
1731cb0ef41Sopenharmony_ci    for (size_t i = 0, j = 0; prefix[j] && i < string.length(); ++i, ++j) {
1741cb0ef41Sopenharmony_ci      if (string.characters8()[i] != prefix[j]) return false;
1751cb0ef41Sopenharmony_ci    }
1761cb0ef41Sopenharmony_ci  } else {
1771cb0ef41Sopenharmony_ci    for (size_t i = 0, j = 0; prefix[j] && i < string.length(); ++i, ++j) {
1781cb0ef41Sopenharmony_ci      if (string.characters16()[i] != prefix[j]) return false;
1791cb0ef41Sopenharmony_ci    }
1801cb0ef41Sopenharmony_ci  }
1811cb0ef41Sopenharmony_ci  return true;
1821cb0ef41Sopenharmony_ci}
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_cinamespace {
1851cb0ef41Sopenharmony_ci// An empty string buffer doesn't own any string data; its ::string() returns a
1861cb0ef41Sopenharmony_ci// default-constructed StringView instance.
1871cb0ef41Sopenharmony_ciclass EmptyStringBuffer : public StringBuffer {
1881cb0ef41Sopenharmony_ci public:
1891cb0ef41Sopenharmony_ci  StringView string() const override { return StringView(); }
1901cb0ef41Sopenharmony_ci};
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci// Contains LATIN1 text data or CBOR encoded binary data in a vector.
1931cb0ef41Sopenharmony_ciclass StringBuffer8 : public StringBuffer {
1941cb0ef41Sopenharmony_ci public:
1951cb0ef41Sopenharmony_ci  explicit StringBuffer8(std::vector<uint8_t> data) : data_(std::move(data)) {}
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci  StringView string() const override {
1981cb0ef41Sopenharmony_ci    return StringView(data_.data(), data_.size());
1991cb0ef41Sopenharmony_ci  }
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_ci private:
2021cb0ef41Sopenharmony_ci  std::vector<uint8_t> data_;
2031cb0ef41Sopenharmony_ci};
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci// Contains a 16 bit string (String16).
2061cb0ef41Sopenharmony_ciclass StringBuffer16 : public StringBuffer {
2071cb0ef41Sopenharmony_ci public:
2081cb0ef41Sopenharmony_ci  explicit StringBuffer16(String16 data) : data_(std::move(data)) {}
2091cb0ef41Sopenharmony_ci
2101cb0ef41Sopenharmony_ci  StringView string() const override {
2111cb0ef41Sopenharmony_ci    return StringView(data_.characters16(), data_.length());
2121cb0ef41Sopenharmony_ci  }
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci private:
2151cb0ef41Sopenharmony_ci  String16 data_;
2161cb0ef41Sopenharmony_ci};
2171cb0ef41Sopenharmony_ci}  // namespace
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ci// static
2201cb0ef41Sopenharmony_cistd::unique_ptr<StringBuffer> StringBuffer::create(StringView string) {
2211cb0ef41Sopenharmony_ci  if (string.length() == 0) return std::make_unique<EmptyStringBuffer>();
2221cb0ef41Sopenharmony_ci  if (string.is8Bit()) {
2231cb0ef41Sopenharmony_ci    return std::make_unique<StringBuffer8>(std::vector<uint8_t>(
2241cb0ef41Sopenharmony_ci        string.characters8(), string.characters8() + string.length()));
2251cb0ef41Sopenharmony_ci  }
2261cb0ef41Sopenharmony_ci  return std::make_unique<StringBuffer16>(
2271cb0ef41Sopenharmony_ci      String16(string.characters16(), string.length()));
2281cb0ef41Sopenharmony_ci}
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_cistd::unique_ptr<StringBuffer> StringBufferFrom(String16 str) {
2311cb0ef41Sopenharmony_ci  if (str.isEmpty()) return std::make_unique<EmptyStringBuffer>();
2321cb0ef41Sopenharmony_ci  return std::make_unique<StringBuffer16>(std::move(str));
2331cb0ef41Sopenharmony_ci}
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_cistd::unique_ptr<StringBuffer> StringBufferFrom(std::vector<uint8_t> str) {
2361cb0ef41Sopenharmony_ci  if (str.empty()) return std::make_unique<EmptyStringBuffer>();
2371cb0ef41Sopenharmony_ci  return std::make_unique<StringBuffer8>(std::move(str));
2381cb0ef41Sopenharmony_ci}
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ciString16 stackTraceIdToString(uintptr_t id) {
2411cb0ef41Sopenharmony_ci  String16Builder builder;
2421cb0ef41Sopenharmony_ci  builder.appendNumber(static_cast<size_t>(id));
2431cb0ef41Sopenharmony_ci  return builder.toString();
2441cb0ef41Sopenharmony_ci}
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ci}  // namespace v8_inspector
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_cinamespace v8_crdtp {
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ciusing v8_inspector::String16;
2511cb0ef41Sopenharmony_ciusing v8_inspector::protocol::Binary;
2521cb0ef41Sopenharmony_ciusing v8_inspector::protocol::StringUtil;
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ci// static
2551cb0ef41Sopenharmony_cibool ProtocolTypeTraits<String16>::Deserialize(DeserializerState* state,
2561cb0ef41Sopenharmony_ci                                               String16* value) {
2571cb0ef41Sopenharmony_ci  auto* tokenizer = state->tokenizer();
2581cb0ef41Sopenharmony_ci  if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING8) {
2591cb0ef41Sopenharmony_ci    const auto str = tokenizer->GetString8();
2601cb0ef41Sopenharmony_ci    *value = StringUtil::fromUTF8(str.data(), str.size());
2611cb0ef41Sopenharmony_ci    return true;
2621cb0ef41Sopenharmony_ci  }
2631cb0ef41Sopenharmony_ci  if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING16) {
2641cb0ef41Sopenharmony_ci    const auto str = tokenizer->GetString16WireRep();
2651cb0ef41Sopenharmony_ci    *value = StringUtil::fromUTF16LE(
2661cb0ef41Sopenharmony_ci        reinterpret_cast<const uint16_t*>(str.data()), str.size() / 2);
2671cb0ef41Sopenharmony_ci    return true;
2681cb0ef41Sopenharmony_ci  }
2691cb0ef41Sopenharmony_ci  state->RegisterError(Error::BINDINGS_STRING_VALUE_EXPECTED);
2701cb0ef41Sopenharmony_ci  return false;
2711cb0ef41Sopenharmony_ci}
2721cb0ef41Sopenharmony_ci
2731cb0ef41Sopenharmony_ci// static
2741cb0ef41Sopenharmony_civoid ProtocolTypeTraits<String16>::Serialize(const String16& value,
2751cb0ef41Sopenharmony_ci                                             std::vector<uint8_t>* bytes) {
2761cb0ef41Sopenharmony_ci  cbor::EncodeFromUTF16(
2771cb0ef41Sopenharmony_ci      span<uint16_t>(reinterpret_cast<const uint16_t*>(value.characters16()),
2781cb0ef41Sopenharmony_ci                     value.length()),
2791cb0ef41Sopenharmony_ci      bytes);
2801cb0ef41Sopenharmony_ci}
2811cb0ef41Sopenharmony_ci
2821cb0ef41Sopenharmony_ci// static
2831cb0ef41Sopenharmony_cibool ProtocolTypeTraits<Binary>::Deserialize(DeserializerState* state,
2841cb0ef41Sopenharmony_ci                                             Binary* value) {
2851cb0ef41Sopenharmony_ci  auto* tokenizer = state->tokenizer();
2861cb0ef41Sopenharmony_ci  if (tokenizer->TokenTag() == cbor::CBORTokenTag::BINARY) {
2871cb0ef41Sopenharmony_ci    const span<uint8_t> bin = tokenizer->GetBinary();
2881cb0ef41Sopenharmony_ci    *value = Binary::fromSpan(bin.data(), bin.size());
2891cb0ef41Sopenharmony_ci    return true;
2901cb0ef41Sopenharmony_ci  }
2911cb0ef41Sopenharmony_ci  if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING8) {
2921cb0ef41Sopenharmony_ci    const auto str_span = tokenizer->GetString8();
2931cb0ef41Sopenharmony_ci    auto str = StringUtil::fromUTF8(str_span.data(), str_span.size());
2941cb0ef41Sopenharmony_ci    bool success = false;
2951cb0ef41Sopenharmony_ci    *value = Binary::fromBase64(str, &success);
2961cb0ef41Sopenharmony_ci    return success;
2971cb0ef41Sopenharmony_ci  }
2981cb0ef41Sopenharmony_ci  state->RegisterError(Error::BINDINGS_BINARY_VALUE_EXPECTED);
2991cb0ef41Sopenharmony_ci  return false;
3001cb0ef41Sopenharmony_ci}
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ci// static
3031cb0ef41Sopenharmony_civoid ProtocolTypeTraits<Binary>::Serialize(const Binary& value,
3041cb0ef41Sopenharmony_ci                                           std::vector<uint8_t>* bytes) {
3051cb0ef41Sopenharmony_ci  cbor::EncodeBinary(span<uint8_t>(value.data(), value.size()), bytes);
3061cb0ef41Sopenharmony_ci}
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci}  // namespace v8_crdtp
309