11cb0ef41Sopenharmony_ci// Copyright 2019 The Chromium 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 "encoding.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <algorithm>
81cb0ef41Sopenharmony_ci#include <cassert>
91cb0ef41Sopenharmony_ci#include <cmath>
101cb0ef41Sopenharmony_ci#include <cstring>
111cb0ef41Sopenharmony_ci#include <limits>
121cb0ef41Sopenharmony_ci#include <stack>
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_cinamespace v8_inspector_protocol_encoding {
151cb0ef41Sopenharmony_ci// =============================================================================
161cb0ef41Sopenharmony_ci// Status and Error codes
171cb0ef41Sopenharmony_ci// =============================================================================
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_cistd::string Status::ToASCIIString() const {
201cb0ef41Sopenharmony_ci  switch (error) {
211cb0ef41Sopenharmony_ci    case Error::OK:
221cb0ef41Sopenharmony_ci      return "OK";
231cb0ef41Sopenharmony_ci    case Error::JSON_PARSER_UNPROCESSED_INPUT_REMAINS:
241cb0ef41Sopenharmony_ci      return ToASCIIString("JSON: unprocessed input remains");
251cb0ef41Sopenharmony_ci    case Error::JSON_PARSER_STACK_LIMIT_EXCEEDED:
261cb0ef41Sopenharmony_ci      return ToASCIIString("JSON: stack limit exceeded");
271cb0ef41Sopenharmony_ci    case Error::JSON_PARSER_NO_INPUT:
281cb0ef41Sopenharmony_ci      return ToASCIIString("JSON: no input");
291cb0ef41Sopenharmony_ci    case Error::JSON_PARSER_INVALID_TOKEN:
301cb0ef41Sopenharmony_ci      return ToASCIIString("JSON: invalid token");
311cb0ef41Sopenharmony_ci    case Error::JSON_PARSER_INVALID_NUMBER:
321cb0ef41Sopenharmony_ci      return ToASCIIString("JSON: invalid number");
331cb0ef41Sopenharmony_ci    case Error::JSON_PARSER_INVALID_STRING:
341cb0ef41Sopenharmony_ci      return ToASCIIString("JSON: invalid string");
351cb0ef41Sopenharmony_ci    case Error::JSON_PARSER_UNEXPECTED_ARRAY_END:
361cb0ef41Sopenharmony_ci      return ToASCIIString("JSON: unexpected array end");
371cb0ef41Sopenharmony_ci    case Error::JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED:
381cb0ef41Sopenharmony_ci      return ToASCIIString("JSON: comma or array end expected");
391cb0ef41Sopenharmony_ci    case Error::JSON_PARSER_STRING_LITERAL_EXPECTED:
401cb0ef41Sopenharmony_ci      return ToASCIIString("JSON: string literal expected");
411cb0ef41Sopenharmony_ci    case Error::JSON_PARSER_COLON_EXPECTED:
421cb0ef41Sopenharmony_ci      return ToASCIIString("JSON: colon expected");
431cb0ef41Sopenharmony_ci    case Error::JSON_PARSER_UNEXPECTED_MAP_END:
441cb0ef41Sopenharmony_ci      return ToASCIIString("JSON: unexpected map end");
451cb0ef41Sopenharmony_ci    case Error::JSON_PARSER_COMMA_OR_MAP_END_EXPECTED:
461cb0ef41Sopenharmony_ci      return ToASCIIString("JSON: comma or map end expected");
471cb0ef41Sopenharmony_ci    case Error::JSON_PARSER_VALUE_EXPECTED:
481cb0ef41Sopenharmony_ci      return ToASCIIString("JSON: value expected");
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci    case Error::CBOR_INVALID_INT32:
511cb0ef41Sopenharmony_ci      return ToASCIIString("CBOR: invalid int32");
521cb0ef41Sopenharmony_ci    case Error::CBOR_INVALID_DOUBLE:
531cb0ef41Sopenharmony_ci      return ToASCIIString("CBOR: invalid double");
541cb0ef41Sopenharmony_ci    case Error::CBOR_INVALID_ENVELOPE:
551cb0ef41Sopenharmony_ci      return ToASCIIString("CBOR: invalid envelope");
561cb0ef41Sopenharmony_ci    case Error::CBOR_INVALID_STRING8:
571cb0ef41Sopenharmony_ci      return ToASCIIString("CBOR: invalid string8");
581cb0ef41Sopenharmony_ci    case Error::CBOR_INVALID_STRING16:
591cb0ef41Sopenharmony_ci      return ToASCIIString("CBOR: invalid string16");
601cb0ef41Sopenharmony_ci    case Error::CBOR_INVALID_BINARY:
611cb0ef41Sopenharmony_ci      return ToASCIIString("CBOR: invalid binary");
621cb0ef41Sopenharmony_ci    case Error::CBOR_UNSUPPORTED_VALUE:
631cb0ef41Sopenharmony_ci      return ToASCIIString("CBOR: unsupported value");
641cb0ef41Sopenharmony_ci    case Error::CBOR_NO_INPUT:
651cb0ef41Sopenharmony_ci      return ToASCIIString("CBOR: no input");
661cb0ef41Sopenharmony_ci    case Error::CBOR_INVALID_START_BYTE:
671cb0ef41Sopenharmony_ci      return ToASCIIString("CBOR: invalid start byte");
681cb0ef41Sopenharmony_ci    case Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE:
691cb0ef41Sopenharmony_ci      return ToASCIIString("CBOR: unexpected eof expected value");
701cb0ef41Sopenharmony_ci    case Error::CBOR_UNEXPECTED_EOF_IN_ARRAY:
711cb0ef41Sopenharmony_ci      return ToASCIIString("CBOR: unexpected eof in array");
721cb0ef41Sopenharmony_ci    case Error::CBOR_UNEXPECTED_EOF_IN_MAP:
731cb0ef41Sopenharmony_ci      return ToASCIIString("CBOR: unexpected eof in map");
741cb0ef41Sopenharmony_ci    case Error::CBOR_INVALID_MAP_KEY:
751cb0ef41Sopenharmony_ci      return ToASCIIString("CBOR: invalid map key");
761cb0ef41Sopenharmony_ci    case Error::CBOR_STACK_LIMIT_EXCEEDED:
771cb0ef41Sopenharmony_ci      return ToASCIIString("CBOR: stack limit exceeded");
781cb0ef41Sopenharmony_ci    case Error::CBOR_TRAILING_JUNK:
791cb0ef41Sopenharmony_ci      return ToASCIIString("CBOR: trailing junk");
801cb0ef41Sopenharmony_ci    case Error::CBOR_MAP_START_EXPECTED:
811cb0ef41Sopenharmony_ci      return ToASCIIString("CBOR: map start expected");
821cb0ef41Sopenharmony_ci    case Error::CBOR_MAP_STOP_EXPECTED:
831cb0ef41Sopenharmony_ci      return ToASCIIString("CBOR: map stop expected");
841cb0ef41Sopenharmony_ci    case Error::CBOR_ENVELOPE_SIZE_LIMIT_EXCEEDED:
851cb0ef41Sopenharmony_ci      return ToASCIIString("CBOR: envelope size limit exceeded");
861cb0ef41Sopenharmony_ci  }
871cb0ef41Sopenharmony_ci  // Some compilers can't figure out that we can't get here.
881cb0ef41Sopenharmony_ci  return "INVALID ERROR CODE";
891cb0ef41Sopenharmony_ci}
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_cistd::string Status::ToASCIIString(const char* msg) const {
921cb0ef41Sopenharmony_ci  return std::string(msg) + " at position " + std::to_string(pos);
931cb0ef41Sopenharmony_ci}
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_cinamespace cbor {
961cb0ef41Sopenharmony_cinamespace {
971cb0ef41Sopenharmony_ci// Indicates the number of bits the "initial byte" needs to be shifted to the
981cb0ef41Sopenharmony_ci// right after applying |kMajorTypeMask| to produce the major type in the
991cb0ef41Sopenharmony_ci// lowermost bits.
1001cb0ef41Sopenharmony_cistatic constexpr uint8_t kMajorTypeBitShift = 5u;
1011cb0ef41Sopenharmony_ci// Mask selecting the low-order 5 bits of the "initial byte", which is where
1021cb0ef41Sopenharmony_ci// the additional information is encoded.
1031cb0ef41Sopenharmony_cistatic constexpr uint8_t kAdditionalInformationMask = 0x1f;
1041cb0ef41Sopenharmony_ci// Mask selecting the high-order 3 bits of the "initial byte", which indicates
1051cb0ef41Sopenharmony_ci// the major type of the encoded value.
1061cb0ef41Sopenharmony_cistatic constexpr uint8_t kMajorTypeMask = 0xe0;
1071cb0ef41Sopenharmony_ci// Indicates the integer is in the following byte.
1081cb0ef41Sopenharmony_cistatic constexpr uint8_t kAdditionalInformation1Byte = 24u;
1091cb0ef41Sopenharmony_ci// Indicates the integer is in the next 2 bytes.
1101cb0ef41Sopenharmony_cistatic constexpr uint8_t kAdditionalInformation2Bytes = 25u;
1111cb0ef41Sopenharmony_ci// Indicates the integer is in the next 4 bytes.
1121cb0ef41Sopenharmony_cistatic constexpr uint8_t kAdditionalInformation4Bytes = 26u;
1131cb0ef41Sopenharmony_ci// Indicates the integer is in the next 8 bytes.
1141cb0ef41Sopenharmony_cistatic constexpr uint8_t kAdditionalInformation8Bytes = 27u;
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci// Encodes the initial byte, consisting of the |type| in the first 3 bits
1171cb0ef41Sopenharmony_ci// followed by 5 bits of |additional_info|.
1181cb0ef41Sopenharmony_ciconstexpr uint8_t EncodeInitialByte(MajorType type, uint8_t additional_info) {
1191cb0ef41Sopenharmony_ci  return (static_cast<uint8_t>(type) << kMajorTypeBitShift) |
1201cb0ef41Sopenharmony_ci         (additional_info & kAdditionalInformationMask);
1211cb0ef41Sopenharmony_ci}
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci// TAG 24 indicates that what follows is a byte string which is
1241cb0ef41Sopenharmony_ci// encoded in CBOR format. We use this as a wrapper for
1251cb0ef41Sopenharmony_ci// maps and arrays, allowing us to skip them, because the
1261cb0ef41Sopenharmony_ci// byte string carries its size (byte length).
1271cb0ef41Sopenharmony_ci// https://tools.ietf.org/html/rfc7049#section-2.4.4.1
1281cb0ef41Sopenharmony_cistatic constexpr uint8_t kInitialByteForEnvelope =
1291cb0ef41Sopenharmony_ci    EncodeInitialByte(MajorType::TAG, 24);
1301cb0ef41Sopenharmony_ci// The initial byte for a byte string with at most 2^32 bytes
1311cb0ef41Sopenharmony_ci// of payload. This is used for envelope encoding, even if
1321cb0ef41Sopenharmony_ci// the byte string is shorter.
1331cb0ef41Sopenharmony_cistatic constexpr uint8_t kInitialByteFor32BitLengthByteString =
1341cb0ef41Sopenharmony_ci    EncodeInitialByte(MajorType::BYTE_STRING, 26);
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci// See RFC 7049 Section 2.2.1, indefinite length arrays / maps have additional
1371cb0ef41Sopenharmony_ci// info = 31.
1381cb0ef41Sopenharmony_cistatic constexpr uint8_t kInitialByteIndefiniteLengthArray =
1391cb0ef41Sopenharmony_ci    EncodeInitialByte(MajorType::ARRAY, 31);
1401cb0ef41Sopenharmony_cistatic constexpr uint8_t kInitialByteIndefiniteLengthMap =
1411cb0ef41Sopenharmony_ci    EncodeInitialByte(MajorType::MAP, 31);
1421cb0ef41Sopenharmony_ci// See RFC 7049 Section 2.3, Table 1; this is used for finishing indefinite
1431cb0ef41Sopenharmony_ci// length maps / arrays.
1441cb0ef41Sopenharmony_cistatic constexpr uint8_t kStopByte =
1451cb0ef41Sopenharmony_ci    EncodeInitialByte(MajorType::SIMPLE_VALUE, 31);
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci// See RFC 7049 Section 2.3, Table 2.
1481cb0ef41Sopenharmony_cistatic constexpr uint8_t kEncodedTrue =
1491cb0ef41Sopenharmony_ci    EncodeInitialByte(MajorType::SIMPLE_VALUE, 21);
1501cb0ef41Sopenharmony_cistatic constexpr uint8_t kEncodedFalse =
1511cb0ef41Sopenharmony_ci    EncodeInitialByte(MajorType::SIMPLE_VALUE, 20);
1521cb0ef41Sopenharmony_cistatic constexpr uint8_t kEncodedNull =
1531cb0ef41Sopenharmony_ci    EncodeInitialByte(MajorType::SIMPLE_VALUE, 22);
1541cb0ef41Sopenharmony_cistatic constexpr uint8_t kInitialByteForDouble =
1551cb0ef41Sopenharmony_ci    EncodeInitialByte(MajorType::SIMPLE_VALUE, 27);
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci// See RFC 7049 Table 3 and Section 2.4.4.2. This is used as a prefix for
1581cb0ef41Sopenharmony_ci// arbitrary binary data encoded as BYTE_STRING.
1591cb0ef41Sopenharmony_cistatic constexpr uint8_t kExpectedConversionToBase64Tag =
1601cb0ef41Sopenharmony_ci    EncodeInitialByte(MajorType::TAG, 22);
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci// Writes the bytes for |v| to |out|, starting with the most significant byte.
1631cb0ef41Sopenharmony_ci// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
1641cb0ef41Sopenharmony_citemplate <typename T, class C>
1651cb0ef41Sopenharmony_civoid WriteBytesMostSignificantByteFirst(T v, C* out) {
1661cb0ef41Sopenharmony_ci  for (int shift_bytes = sizeof(T) - 1; shift_bytes >= 0; --shift_bytes)
1671cb0ef41Sopenharmony_ci    out->push_back(0xff & (v >> (shift_bytes * 8)));
1681cb0ef41Sopenharmony_ci}
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci// Extracts sizeof(T) bytes from |in| to extract a value of type T
1711cb0ef41Sopenharmony_ci// (e.g. uint64_t, uint32_t, ...), most significant byte first.
1721cb0ef41Sopenharmony_ci// See also: https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
1731cb0ef41Sopenharmony_citemplate <typename T>
1741cb0ef41Sopenharmony_ciT ReadBytesMostSignificantByteFirst(span<uint8_t> in) {
1751cb0ef41Sopenharmony_ci  assert(in.size() >= sizeof(T));
1761cb0ef41Sopenharmony_ci  T result = 0;
1771cb0ef41Sopenharmony_ci  for (size_t shift_bytes = 0; shift_bytes < sizeof(T); ++shift_bytes)
1781cb0ef41Sopenharmony_ci    result |= T(in[sizeof(T) - 1 - shift_bytes]) << (shift_bytes * 8);
1791cb0ef41Sopenharmony_ci  return result;
1801cb0ef41Sopenharmony_ci}
1811cb0ef41Sopenharmony_ci}  // namespace
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_cinamespace internals {
1841cb0ef41Sopenharmony_ci// Reads the start of a token with definitive size from |bytes|.
1851cb0ef41Sopenharmony_ci// |type| is the major type as specified in RFC 7049 Section 2.1.
1861cb0ef41Sopenharmony_ci// |value| is the payload (e.g. for MajorType::UNSIGNED) or is the size
1871cb0ef41Sopenharmony_ci// (e.g. for BYTE_STRING).
1881cb0ef41Sopenharmony_ci// If successful, returns the number of bytes read. Otherwise returns 0.
1891cb0ef41Sopenharmony_cisize_t ReadTokenStart(span<uint8_t> bytes, MajorType* type, uint64_t* value) {
1901cb0ef41Sopenharmony_ci  if (bytes.empty())
1911cb0ef41Sopenharmony_ci    return 0;
1921cb0ef41Sopenharmony_ci  uint8_t initial_byte = bytes[0];
1931cb0ef41Sopenharmony_ci  *type = MajorType((initial_byte & kMajorTypeMask) >> kMajorTypeBitShift);
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci  uint8_t additional_information = initial_byte & kAdditionalInformationMask;
1961cb0ef41Sopenharmony_ci  if (additional_information < 24) {
1971cb0ef41Sopenharmony_ci    // Values 0-23 are encoded directly into the additional info of the
1981cb0ef41Sopenharmony_ci    // initial byte.
1991cb0ef41Sopenharmony_ci    *value = additional_information;
2001cb0ef41Sopenharmony_ci    return 1;
2011cb0ef41Sopenharmony_ci  }
2021cb0ef41Sopenharmony_ci  if (additional_information == kAdditionalInformation1Byte) {
2031cb0ef41Sopenharmony_ci    // Values 24-255 are encoded with one initial byte, followed by the value.
2041cb0ef41Sopenharmony_ci    if (bytes.size() < 2)
2051cb0ef41Sopenharmony_ci      return 0;
2061cb0ef41Sopenharmony_ci    *value = ReadBytesMostSignificantByteFirst<uint8_t>(bytes.subspan(1));
2071cb0ef41Sopenharmony_ci    return 2;
2081cb0ef41Sopenharmony_ci  }
2091cb0ef41Sopenharmony_ci  if (additional_information == kAdditionalInformation2Bytes) {
2101cb0ef41Sopenharmony_ci    // Values 256-65535: 1 initial byte + 2 bytes payload.
2111cb0ef41Sopenharmony_ci    if (bytes.size() < 1 + sizeof(uint16_t))
2121cb0ef41Sopenharmony_ci      return 0;
2131cb0ef41Sopenharmony_ci    *value = ReadBytesMostSignificantByteFirst<uint16_t>(bytes.subspan(1));
2141cb0ef41Sopenharmony_ci    return 3;
2151cb0ef41Sopenharmony_ci  }
2161cb0ef41Sopenharmony_ci  if (additional_information == kAdditionalInformation4Bytes) {
2171cb0ef41Sopenharmony_ci    // 32 bit uint: 1 initial byte + 4 bytes payload.
2181cb0ef41Sopenharmony_ci    if (bytes.size() < 1 + sizeof(uint32_t))
2191cb0ef41Sopenharmony_ci      return 0;
2201cb0ef41Sopenharmony_ci    *value = ReadBytesMostSignificantByteFirst<uint32_t>(bytes.subspan(1));
2211cb0ef41Sopenharmony_ci    return 5;
2221cb0ef41Sopenharmony_ci  }
2231cb0ef41Sopenharmony_ci  if (additional_information == kAdditionalInformation8Bytes) {
2241cb0ef41Sopenharmony_ci    // 64 bit uint: 1 initial byte + 8 bytes payload.
2251cb0ef41Sopenharmony_ci    if (bytes.size() < 1 + sizeof(uint64_t))
2261cb0ef41Sopenharmony_ci      return 0;
2271cb0ef41Sopenharmony_ci    *value = ReadBytesMostSignificantByteFirst<uint64_t>(bytes.subspan(1));
2281cb0ef41Sopenharmony_ci    return 9;
2291cb0ef41Sopenharmony_ci  }
2301cb0ef41Sopenharmony_ci  return 0;
2311cb0ef41Sopenharmony_ci}
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_ci// Writes the start of a token with |type|. The |value| may indicate the size,
2341cb0ef41Sopenharmony_ci// or it may be the payload if the value is an unsigned integer.
2351cb0ef41Sopenharmony_citemplate <typename C>
2361cb0ef41Sopenharmony_civoid WriteTokenStartTmpl(MajorType type, uint64_t value, C* encoded) {
2371cb0ef41Sopenharmony_ci  if (value < 24) {
2381cb0ef41Sopenharmony_ci    // Values 0-23 are encoded directly into the additional info of the
2391cb0ef41Sopenharmony_ci    // initial byte.
2401cb0ef41Sopenharmony_ci    encoded->push_back(EncodeInitialByte(type, /*additional_info=*/value));
2411cb0ef41Sopenharmony_ci    return;
2421cb0ef41Sopenharmony_ci  }
2431cb0ef41Sopenharmony_ci  if (value <= std::numeric_limits<uint8_t>::max()) {
2441cb0ef41Sopenharmony_ci    // Values 24-255 are encoded with one initial byte, followed by the value.
2451cb0ef41Sopenharmony_ci    encoded->push_back(EncodeInitialByte(type, kAdditionalInformation1Byte));
2461cb0ef41Sopenharmony_ci    encoded->push_back(value);
2471cb0ef41Sopenharmony_ci    return;
2481cb0ef41Sopenharmony_ci  }
2491cb0ef41Sopenharmony_ci  if (value <= std::numeric_limits<uint16_t>::max()) {
2501cb0ef41Sopenharmony_ci    // Values 256-65535: 1 initial byte + 2 bytes payload.
2511cb0ef41Sopenharmony_ci    encoded->push_back(EncodeInitialByte(type, kAdditionalInformation2Bytes));
2521cb0ef41Sopenharmony_ci    WriteBytesMostSignificantByteFirst<uint16_t>(value, encoded);
2531cb0ef41Sopenharmony_ci    return;
2541cb0ef41Sopenharmony_ci  }
2551cb0ef41Sopenharmony_ci  if (value <= std::numeric_limits<uint32_t>::max()) {
2561cb0ef41Sopenharmony_ci    // 32 bit uint: 1 initial byte + 4 bytes payload.
2571cb0ef41Sopenharmony_ci    encoded->push_back(EncodeInitialByte(type, kAdditionalInformation4Bytes));
2581cb0ef41Sopenharmony_ci    WriteBytesMostSignificantByteFirst<uint32_t>(static_cast<uint32_t>(value),
2591cb0ef41Sopenharmony_ci                                                 encoded);
2601cb0ef41Sopenharmony_ci    return;
2611cb0ef41Sopenharmony_ci  }
2621cb0ef41Sopenharmony_ci  // 64 bit uint: 1 initial byte + 8 bytes payload.
2631cb0ef41Sopenharmony_ci  encoded->push_back(EncodeInitialByte(type, kAdditionalInformation8Bytes));
2641cb0ef41Sopenharmony_ci  WriteBytesMostSignificantByteFirst<uint64_t>(value, encoded);
2651cb0ef41Sopenharmony_ci}
2661cb0ef41Sopenharmony_civoid WriteTokenStart(MajorType type,
2671cb0ef41Sopenharmony_ci                     uint64_t value,
2681cb0ef41Sopenharmony_ci                     std::vector<uint8_t>* encoded) {
2691cb0ef41Sopenharmony_ci  WriteTokenStartTmpl(type, value, encoded);
2701cb0ef41Sopenharmony_ci}
2711cb0ef41Sopenharmony_civoid WriteTokenStart(MajorType type, uint64_t value, std::string* encoded) {
2721cb0ef41Sopenharmony_ci  WriteTokenStartTmpl(type, value, encoded);
2731cb0ef41Sopenharmony_ci}
2741cb0ef41Sopenharmony_ci}  // namespace internals
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_ci// =============================================================================
2771cb0ef41Sopenharmony_ci// Detecting CBOR content
2781cb0ef41Sopenharmony_ci// =============================================================================
2791cb0ef41Sopenharmony_ci
2801cb0ef41Sopenharmony_ciuint8_t InitialByteForEnvelope() {
2811cb0ef41Sopenharmony_ci  return kInitialByteForEnvelope;
2821cb0ef41Sopenharmony_ci}
2831cb0ef41Sopenharmony_ciuint8_t InitialByteFor32BitLengthByteString() {
2841cb0ef41Sopenharmony_ci  return kInitialByteFor32BitLengthByteString;
2851cb0ef41Sopenharmony_ci}
2861cb0ef41Sopenharmony_cibool IsCBORMessage(span<uint8_t> msg) {
2871cb0ef41Sopenharmony_ci  return msg.size() >= 6 && msg[0] == InitialByteForEnvelope() &&
2881cb0ef41Sopenharmony_ci         msg[1] == InitialByteFor32BitLengthByteString();
2891cb0ef41Sopenharmony_ci}
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_ci// =============================================================================
2921cb0ef41Sopenharmony_ci// Encoding invidiual CBOR items
2931cb0ef41Sopenharmony_ci// =============================================================================
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ciuint8_t EncodeTrue() {
2961cb0ef41Sopenharmony_ci  return kEncodedTrue;
2971cb0ef41Sopenharmony_ci}
2981cb0ef41Sopenharmony_ciuint8_t EncodeFalse() {
2991cb0ef41Sopenharmony_ci  return kEncodedFalse;
3001cb0ef41Sopenharmony_ci}
3011cb0ef41Sopenharmony_ciuint8_t EncodeNull() {
3021cb0ef41Sopenharmony_ci  return kEncodedNull;
3031cb0ef41Sopenharmony_ci}
3041cb0ef41Sopenharmony_ci
3051cb0ef41Sopenharmony_ciuint8_t EncodeIndefiniteLengthArrayStart() {
3061cb0ef41Sopenharmony_ci  return kInitialByteIndefiniteLengthArray;
3071cb0ef41Sopenharmony_ci}
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ciuint8_t EncodeIndefiniteLengthMapStart() {
3101cb0ef41Sopenharmony_ci  return kInitialByteIndefiniteLengthMap;
3111cb0ef41Sopenharmony_ci}
3121cb0ef41Sopenharmony_ci
3131cb0ef41Sopenharmony_ciuint8_t EncodeStop() {
3141cb0ef41Sopenharmony_ci  return kStopByte;
3151cb0ef41Sopenharmony_ci}
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_citemplate <typename C>
3181cb0ef41Sopenharmony_civoid EncodeInt32Tmpl(int32_t value, C* out) {
3191cb0ef41Sopenharmony_ci  if (value >= 0) {
3201cb0ef41Sopenharmony_ci    internals::WriteTokenStart(MajorType::UNSIGNED, value, out);
3211cb0ef41Sopenharmony_ci  } else {
3221cb0ef41Sopenharmony_ci    uint64_t representation = static_cast<uint64_t>(-(value + 1));
3231cb0ef41Sopenharmony_ci    internals::WriteTokenStart(MajorType::NEGATIVE, representation, out);
3241cb0ef41Sopenharmony_ci  }
3251cb0ef41Sopenharmony_ci}
3261cb0ef41Sopenharmony_civoid EncodeInt32(int32_t value, std::vector<uint8_t>* out) {
3271cb0ef41Sopenharmony_ci  EncodeInt32Tmpl(value, out);
3281cb0ef41Sopenharmony_ci}
3291cb0ef41Sopenharmony_civoid EncodeInt32(int32_t value, std::string* out) {
3301cb0ef41Sopenharmony_ci  EncodeInt32Tmpl(value, out);
3311cb0ef41Sopenharmony_ci}
3321cb0ef41Sopenharmony_ci
3331cb0ef41Sopenharmony_citemplate <typename C>
3341cb0ef41Sopenharmony_civoid EncodeString16Tmpl(span<uint16_t> in, C* out) {
3351cb0ef41Sopenharmony_ci  uint64_t byte_length = static_cast<uint64_t>(in.size_bytes());
3361cb0ef41Sopenharmony_ci  internals::WriteTokenStart(MajorType::BYTE_STRING, byte_length, out);
3371cb0ef41Sopenharmony_ci  // When emitting UTF16 characters, we always write the least significant byte
3381cb0ef41Sopenharmony_ci  // first; this is because it's the native representation for X86.
3391cb0ef41Sopenharmony_ci  // TODO(johannes): Implement a more efficient thing here later, e.g.
3401cb0ef41Sopenharmony_ci  // casting *iff* the machine has this byte order.
3411cb0ef41Sopenharmony_ci  // The wire format for UTF16 chars will probably remain the same
3421cb0ef41Sopenharmony_ci  // (least significant byte first) since this way we can have
3431cb0ef41Sopenharmony_ci  // golden files, unittests, etc. that port easily and universally.
3441cb0ef41Sopenharmony_ci  // See also:
3451cb0ef41Sopenharmony_ci  // https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
3461cb0ef41Sopenharmony_ci  for (const uint16_t two_bytes : in) {
3471cb0ef41Sopenharmony_ci    out->push_back(two_bytes);
3481cb0ef41Sopenharmony_ci    out->push_back(two_bytes >> 8);
3491cb0ef41Sopenharmony_ci  }
3501cb0ef41Sopenharmony_ci}
3511cb0ef41Sopenharmony_civoid EncodeString16(span<uint16_t> in, std::vector<uint8_t>* out) {
3521cb0ef41Sopenharmony_ci  EncodeString16Tmpl(in, out);
3531cb0ef41Sopenharmony_ci}
3541cb0ef41Sopenharmony_civoid EncodeString16(span<uint16_t> in, std::string* out) {
3551cb0ef41Sopenharmony_ci  EncodeString16Tmpl(in, out);
3561cb0ef41Sopenharmony_ci}
3571cb0ef41Sopenharmony_ci
3581cb0ef41Sopenharmony_citemplate <typename C>
3591cb0ef41Sopenharmony_civoid EncodeString8Tmpl(span<uint8_t> in, C* out) {
3601cb0ef41Sopenharmony_ci  internals::WriteTokenStart(MajorType::STRING,
3611cb0ef41Sopenharmony_ci                             static_cast<uint64_t>(in.size_bytes()), out);
3621cb0ef41Sopenharmony_ci  out->insert(out->end(), in.begin(), in.end());
3631cb0ef41Sopenharmony_ci}
3641cb0ef41Sopenharmony_civoid EncodeString8(span<uint8_t> in, std::vector<uint8_t>* out) {
3651cb0ef41Sopenharmony_ci  EncodeString8Tmpl(in, out);
3661cb0ef41Sopenharmony_ci}
3671cb0ef41Sopenharmony_civoid EncodeString8(span<uint8_t> in, std::string* out) {
3681cb0ef41Sopenharmony_ci  EncodeString8Tmpl(in, out);
3691cb0ef41Sopenharmony_ci}
3701cb0ef41Sopenharmony_ci
3711cb0ef41Sopenharmony_citemplate <typename C>
3721cb0ef41Sopenharmony_civoid EncodeFromLatin1Tmpl(span<uint8_t> latin1, C* out) {
3731cb0ef41Sopenharmony_ci  for (size_t ii = 0; ii < latin1.size(); ++ii) {
3741cb0ef41Sopenharmony_ci    if (latin1[ii] <= 127)
3751cb0ef41Sopenharmony_ci      continue;
3761cb0ef41Sopenharmony_ci    // If there's at least one non-ASCII char, convert to UTF8.
3771cb0ef41Sopenharmony_ci    std::vector<uint8_t> utf8(latin1.begin(), latin1.begin() + ii);
3781cb0ef41Sopenharmony_ci    for (; ii < latin1.size(); ++ii) {
3791cb0ef41Sopenharmony_ci      if (latin1[ii] <= 127) {
3801cb0ef41Sopenharmony_ci        utf8.push_back(latin1[ii]);
3811cb0ef41Sopenharmony_ci      } else {
3821cb0ef41Sopenharmony_ci        // 0xC0 means it's a UTF8 sequence with 2 bytes.
3831cb0ef41Sopenharmony_ci        utf8.push_back((latin1[ii] >> 6) | 0xc0);
3841cb0ef41Sopenharmony_ci        utf8.push_back((latin1[ii] | 0x80) & 0xbf);
3851cb0ef41Sopenharmony_ci      }
3861cb0ef41Sopenharmony_ci    }
3871cb0ef41Sopenharmony_ci    EncodeString8(SpanFrom(utf8), out);
3881cb0ef41Sopenharmony_ci    return;
3891cb0ef41Sopenharmony_ci  }
3901cb0ef41Sopenharmony_ci  EncodeString8(latin1, out);
3911cb0ef41Sopenharmony_ci}
3921cb0ef41Sopenharmony_civoid EncodeFromLatin1(span<uint8_t> latin1, std::vector<uint8_t>* out) {
3931cb0ef41Sopenharmony_ci  EncodeFromLatin1Tmpl(latin1, out);
3941cb0ef41Sopenharmony_ci}
3951cb0ef41Sopenharmony_civoid EncodeFromLatin1(span<uint8_t> latin1, std::string* out) {
3961cb0ef41Sopenharmony_ci  EncodeFromLatin1Tmpl(latin1, out);
3971cb0ef41Sopenharmony_ci}
3981cb0ef41Sopenharmony_ci
3991cb0ef41Sopenharmony_citemplate <typename C>
4001cb0ef41Sopenharmony_civoid EncodeFromUTF16Tmpl(span<uint16_t> utf16, C* out) {
4011cb0ef41Sopenharmony_ci  // If there's at least one non-ASCII char, encode as STRING16 (UTF16).
4021cb0ef41Sopenharmony_ci  for (uint16_t ch : utf16) {
4031cb0ef41Sopenharmony_ci    if (ch <= 127)
4041cb0ef41Sopenharmony_ci      continue;
4051cb0ef41Sopenharmony_ci    EncodeString16(utf16, out);
4061cb0ef41Sopenharmony_ci    return;
4071cb0ef41Sopenharmony_ci  }
4081cb0ef41Sopenharmony_ci  // It's all US-ASCII, strip out every second byte and encode as UTF8.
4091cb0ef41Sopenharmony_ci  internals::WriteTokenStart(MajorType::STRING,
4101cb0ef41Sopenharmony_ci                             static_cast<uint64_t>(utf16.size()), out);
4111cb0ef41Sopenharmony_ci  out->insert(out->end(), utf16.begin(), utf16.end());
4121cb0ef41Sopenharmony_ci}
4131cb0ef41Sopenharmony_civoid EncodeFromUTF16(span<uint16_t> utf16, std::vector<uint8_t>* out) {
4141cb0ef41Sopenharmony_ci  EncodeFromUTF16Tmpl(utf16, out);
4151cb0ef41Sopenharmony_ci}
4161cb0ef41Sopenharmony_civoid EncodeFromUTF16(span<uint16_t> utf16, std::string* out) {
4171cb0ef41Sopenharmony_ci  EncodeFromUTF16Tmpl(utf16, out);
4181cb0ef41Sopenharmony_ci}
4191cb0ef41Sopenharmony_ci
4201cb0ef41Sopenharmony_citemplate <typename C>
4211cb0ef41Sopenharmony_civoid EncodeBinaryTmpl(span<uint8_t> in, C* out) {
4221cb0ef41Sopenharmony_ci  out->push_back(kExpectedConversionToBase64Tag);
4231cb0ef41Sopenharmony_ci  uint64_t byte_length = static_cast<uint64_t>(in.size_bytes());
4241cb0ef41Sopenharmony_ci  internals::WriteTokenStart(MajorType::BYTE_STRING, byte_length, out);
4251cb0ef41Sopenharmony_ci  out->insert(out->end(), in.begin(), in.end());
4261cb0ef41Sopenharmony_ci}
4271cb0ef41Sopenharmony_civoid EncodeBinary(span<uint8_t> in, std::vector<uint8_t>* out) {
4281cb0ef41Sopenharmony_ci  EncodeBinaryTmpl(in, out);
4291cb0ef41Sopenharmony_ci}
4301cb0ef41Sopenharmony_civoid EncodeBinary(span<uint8_t> in, std::string* out) {
4311cb0ef41Sopenharmony_ci  EncodeBinaryTmpl(in, out);
4321cb0ef41Sopenharmony_ci}
4331cb0ef41Sopenharmony_ci
4341cb0ef41Sopenharmony_ci// A double is encoded with a specific initial byte
4351cb0ef41Sopenharmony_ci// (kInitialByteForDouble) plus the 64 bits of payload for its value.
4361cb0ef41Sopenharmony_ciconstexpr size_t kEncodedDoubleSize = 1 + sizeof(uint64_t);
4371cb0ef41Sopenharmony_ci
4381cb0ef41Sopenharmony_ci// An envelope is encoded with a specific initial byte
4391cb0ef41Sopenharmony_ci// (kInitialByteForEnvelope), plus the start byte for a BYTE_STRING with a 32
4401cb0ef41Sopenharmony_ci// bit wide length, plus a 32 bit length for that string.
4411cb0ef41Sopenharmony_ciconstexpr size_t kEncodedEnvelopeHeaderSize = 1 + 1 + sizeof(uint32_t);
4421cb0ef41Sopenharmony_ci
4431cb0ef41Sopenharmony_citemplate <typename C>
4441cb0ef41Sopenharmony_civoid EncodeDoubleTmpl(double value, C* out) {
4451cb0ef41Sopenharmony_ci  // The additional_info=27 indicates 64 bits for the double follow.
4461cb0ef41Sopenharmony_ci  // See RFC 7049 Section 2.3, Table 1.
4471cb0ef41Sopenharmony_ci  out->push_back(kInitialByteForDouble);
4481cb0ef41Sopenharmony_ci  union {
4491cb0ef41Sopenharmony_ci    double from_double;
4501cb0ef41Sopenharmony_ci    uint64_t to_uint64;
4511cb0ef41Sopenharmony_ci  } reinterpret;
4521cb0ef41Sopenharmony_ci  reinterpret.from_double = value;
4531cb0ef41Sopenharmony_ci  WriteBytesMostSignificantByteFirst<uint64_t>(reinterpret.to_uint64, out);
4541cb0ef41Sopenharmony_ci}
4551cb0ef41Sopenharmony_civoid EncodeDouble(double value, std::vector<uint8_t>* out) {
4561cb0ef41Sopenharmony_ci  EncodeDoubleTmpl(value, out);
4571cb0ef41Sopenharmony_ci}
4581cb0ef41Sopenharmony_civoid EncodeDouble(double value, std::string* out) {
4591cb0ef41Sopenharmony_ci  EncodeDoubleTmpl(value, out);
4601cb0ef41Sopenharmony_ci}
4611cb0ef41Sopenharmony_ci
4621cb0ef41Sopenharmony_ci// =============================================================================
4631cb0ef41Sopenharmony_ci// cbor::EnvelopeEncoder - for wrapping submessages
4641cb0ef41Sopenharmony_ci// =============================================================================
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_citemplate <typename C>
4671cb0ef41Sopenharmony_civoid EncodeStartTmpl(C* out, size_t* byte_size_pos) {
4681cb0ef41Sopenharmony_ci  assert(*byte_size_pos == 0);
4691cb0ef41Sopenharmony_ci  out->push_back(kInitialByteForEnvelope);
4701cb0ef41Sopenharmony_ci  out->push_back(kInitialByteFor32BitLengthByteString);
4711cb0ef41Sopenharmony_ci  *byte_size_pos = out->size();
4721cb0ef41Sopenharmony_ci  out->resize(out->size() + sizeof(uint32_t));
4731cb0ef41Sopenharmony_ci}
4741cb0ef41Sopenharmony_ci
4751cb0ef41Sopenharmony_civoid EnvelopeEncoder::EncodeStart(std::vector<uint8_t>* out) {
4761cb0ef41Sopenharmony_ci  EncodeStartTmpl<std::vector<uint8_t>>(out, &byte_size_pos_);
4771cb0ef41Sopenharmony_ci}
4781cb0ef41Sopenharmony_ci
4791cb0ef41Sopenharmony_civoid EnvelopeEncoder::EncodeStart(std::string* out) {
4801cb0ef41Sopenharmony_ci  EncodeStartTmpl<std::string>(out, &byte_size_pos_);
4811cb0ef41Sopenharmony_ci}
4821cb0ef41Sopenharmony_ci
4831cb0ef41Sopenharmony_citemplate <typename C>
4841cb0ef41Sopenharmony_cibool EncodeStopTmpl(C* out, size_t* byte_size_pos) {
4851cb0ef41Sopenharmony_ci  assert(*byte_size_pos != 0);
4861cb0ef41Sopenharmony_ci  // The byte size is the size of the payload, that is, all the
4871cb0ef41Sopenharmony_ci  // bytes that were written past the byte size position itself.
4881cb0ef41Sopenharmony_ci  uint64_t byte_size = out->size() - (*byte_size_pos + sizeof(uint32_t));
4891cb0ef41Sopenharmony_ci  // We store exactly 4 bytes, so at most INT32MAX, with most significant
4901cb0ef41Sopenharmony_ci  // byte first.
4911cb0ef41Sopenharmony_ci  if (byte_size > std::numeric_limits<uint32_t>::max())
4921cb0ef41Sopenharmony_ci    return false;
4931cb0ef41Sopenharmony_ci  for (int shift_bytes = sizeof(uint32_t) - 1; shift_bytes >= 0;
4941cb0ef41Sopenharmony_ci       --shift_bytes) {
4951cb0ef41Sopenharmony_ci    (*out)[(*byte_size_pos)++] = 0xff & (byte_size >> (shift_bytes * 8));
4961cb0ef41Sopenharmony_ci  }
4971cb0ef41Sopenharmony_ci  return true;
4981cb0ef41Sopenharmony_ci}
4991cb0ef41Sopenharmony_ci
5001cb0ef41Sopenharmony_cibool EnvelopeEncoder::EncodeStop(std::vector<uint8_t>* out) {
5011cb0ef41Sopenharmony_ci  return EncodeStopTmpl(out, &byte_size_pos_);
5021cb0ef41Sopenharmony_ci}
5031cb0ef41Sopenharmony_ci
5041cb0ef41Sopenharmony_cibool EnvelopeEncoder::EncodeStop(std::string* out) {
5051cb0ef41Sopenharmony_ci  return EncodeStopTmpl(out, &byte_size_pos_);
5061cb0ef41Sopenharmony_ci}
5071cb0ef41Sopenharmony_ci
5081cb0ef41Sopenharmony_ci// =============================================================================
5091cb0ef41Sopenharmony_ci// cbor::NewCBOREncoder - for encoding from a streaming parser
5101cb0ef41Sopenharmony_ci// =============================================================================
5111cb0ef41Sopenharmony_ci
5121cb0ef41Sopenharmony_cinamespace {
5131cb0ef41Sopenharmony_citemplate <typename C>
5141cb0ef41Sopenharmony_ciclass CBOREncoder : public StreamingParserHandler {
5151cb0ef41Sopenharmony_ci public:
5161cb0ef41Sopenharmony_ci  CBOREncoder(C* out, Status* status) : out_(out), status_(status) {
5171cb0ef41Sopenharmony_ci    *status_ = Status();
5181cb0ef41Sopenharmony_ci  }
5191cb0ef41Sopenharmony_ci
5201cb0ef41Sopenharmony_ci  void HandleMapBegin() override {
5211cb0ef41Sopenharmony_ci    if (!status_->ok())
5221cb0ef41Sopenharmony_ci      return;
5231cb0ef41Sopenharmony_ci    envelopes_.emplace_back();
5241cb0ef41Sopenharmony_ci    envelopes_.back().EncodeStart(out_);
5251cb0ef41Sopenharmony_ci    out_->push_back(kInitialByteIndefiniteLengthMap);
5261cb0ef41Sopenharmony_ci  }
5271cb0ef41Sopenharmony_ci
5281cb0ef41Sopenharmony_ci  void HandleMapEnd() override {
5291cb0ef41Sopenharmony_ci    if (!status_->ok())
5301cb0ef41Sopenharmony_ci      return;
5311cb0ef41Sopenharmony_ci    out_->push_back(kStopByte);
5321cb0ef41Sopenharmony_ci    assert(!envelopes_.empty());
5331cb0ef41Sopenharmony_ci    if (!envelopes_.back().EncodeStop(out_)) {
5341cb0ef41Sopenharmony_ci      HandleError(
5351cb0ef41Sopenharmony_ci          Status(Error::CBOR_ENVELOPE_SIZE_LIMIT_EXCEEDED, out_->size()));
5361cb0ef41Sopenharmony_ci      return;
5371cb0ef41Sopenharmony_ci    }
5381cb0ef41Sopenharmony_ci    envelopes_.pop_back();
5391cb0ef41Sopenharmony_ci  }
5401cb0ef41Sopenharmony_ci
5411cb0ef41Sopenharmony_ci  void HandleArrayBegin() override {
5421cb0ef41Sopenharmony_ci    if (!status_->ok())
5431cb0ef41Sopenharmony_ci      return;
5441cb0ef41Sopenharmony_ci    envelopes_.emplace_back();
5451cb0ef41Sopenharmony_ci    envelopes_.back().EncodeStart(out_);
5461cb0ef41Sopenharmony_ci    out_->push_back(kInitialByteIndefiniteLengthArray);
5471cb0ef41Sopenharmony_ci  }
5481cb0ef41Sopenharmony_ci
5491cb0ef41Sopenharmony_ci  void HandleArrayEnd() override {
5501cb0ef41Sopenharmony_ci    if (!status_->ok())
5511cb0ef41Sopenharmony_ci      return;
5521cb0ef41Sopenharmony_ci    out_->push_back(kStopByte);
5531cb0ef41Sopenharmony_ci    assert(!envelopes_.empty());
5541cb0ef41Sopenharmony_ci    if (!envelopes_.back().EncodeStop(out_)) {
5551cb0ef41Sopenharmony_ci      HandleError(
5561cb0ef41Sopenharmony_ci          Status(Error::CBOR_ENVELOPE_SIZE_LIMIT_EXCEEDED, out_->size()));
5571cb0ef41Sopenharmony_ci      return;
5581cb0ef41Sopenharmony_ci    }
5591cb0ef41Sopenharmony_ci    envelopes_.pop_back();
5601cb0ef41Sopenharmony_ci  }
5611cb0ef41Sopenharmony_ci
5621cb0ef41Sopenharmony_ci  void HandleString8(span<uint8_t> chars) override {
5631cb0ef41Sopenharmony_ci    if (!status_->ok())
5641cb0ef41Sopenharmony_ci      return;
5651cb0ef41Sopenharmony_ci    EncodeString8(chars, out_);
5661cb0ef41Sopenharmony_ci  }
5671cb0ef41Sopenharmony_ci
5681cb0ef41Sopenharmony_ci  void HandleString16(span<uint16_t> chars) override {
5691cb0ef41Sopenharmony_ci    if (!status_->ok())
5701cb0ef41Sopenharmony_ci      return;
5711cb0ef41Sopenharmony_ci    EncodeFromUTF16(chars, out_);
5721cb0ef41Sopenharmony_ci  }
5731cb0ef41Sopenharmony_ci
5741cb0ef41Sopenharmony_ci  void HandleBinary(span<uint8_t> bytes) override {
5751cb0ef41Sopenharmony_ci    if (!status_->ok())
5761cb0ef41Sopenharmony_ci      return;
5771cb0ef41Sopenharmony_ci    EncodeBinary(bytes, out_);
5781cb0ef41Sopenharmony_ci  }
5791cb0ef41Sopenharmony_ci
5801cb0ef41Sopenharmony_ci  void HandleDouble(double value) override {
5811cb0ef41Sopenharmony_ci    if (!status_->ok())
5821cb0ef41Sopenharmony_ci      return;
5831cb0ef41Sopenharmony_ci    EncodeDouble(value, out_);
5841cb0ef41Sopenharmony_ci  }
5851cb0ef41Sopenharmony_ci
5861cb0ef41Sopenharmony_ci  void HandleInt32(int32_t value) override {
5871cb0ef41Sopenharmony_ci    if (!status_->ok())
5881cb0ef41Sopenharmony_ci      return;
5891cb0ef41Sopenharmony_ci    EncodeInt32(value, out_);
5901cb0ef41Sopenharmony_ci  }
5911cb0ef41Sopenharmony_ci
5921cb0ef41Sopenharmony_ci  void HandleBool(bool value) override {
5931cb0ef41Sopenharmony_ci    if (!status_->ok())
5941cb0ef41Sopenharmony_ci      return;
5951cb0ef41Sopenharmony_ci    // See RFC 7049 Section 2.3, Table 2.
5961cb0ef41Sopenharmony_ci    out_->push_back(value ? kEncodedTrue : kEncodedFalse);
5971cb0ef41Sopenharmony_ci  }
5981cb0ef41Sopenharmony_ci
5991cb0ef41Sopenharmony_ci  void HandleNull() override {
6001cb0ef41Sopenharmony_ci    if (!status_->ok())
6011cb0ef41Sopenharmony_ci      return;
6021cb0ef41Sopenharmony_ci    // See RFC 7049 Section 2.3, Table 2.
6031cb0ef41Sopenharmony_ci    out_->push_back(kEncodedNull);
6041cb0ef41Sopenharmony_ci  }
6051cb0ef41Sopenharmony_ci
6061cb0ef41Sopenharmony_ci  void HandleError(Status error) override {
6071cb0ef41Sopenharmony_ci    if (!status_->ok())
6081cb0ef41Sopenharmony_ci      return;
6091cb0ef41Sopenharmony_ci    *status_ = error;
6101cb0ef41Sopenharmony_ci    out_->clear();
6111cb0ef41Sopenharmony_ci  }
6121cb0ef41Sopenharmony_ci
6131cb0ef41Sopenharmony_ci private:
6141cb0ef41Sopenharmony_ci  C* out_;
6151cb0ef41Sopenharmony_ci  std::vector<EnvelopeEncoder> envelopes_;
6161cb0ef41Sopenharmony_ci  Status* status_;
6171cb0ef41Sopenharmony_ci};
6181cb0ef41Sopenharmony_ci}  // namespace
6191cb0ef41Sopenharmony_ci
6201cb0ef41Sopenharmony_cistd::unique_ptr<StreamingParserHandler> NewCBOREncoder(
6211cb0ef41Sopenharmony_ci    std::vector<uint8_t>* out,
6221cb0ef41Sopenharmony_ci    Status* status) {
6231cb0ef41Sopenharmony_ci  return std::unique_ptr<StreamingParserHandler>(
6241cb0ef41Sopenharmony_ci      new CBOREncoder<std::vector<uint8_t>>(out, status));
6251cb0ef41Sopenharmony_ci}
6261cb0ef41Sopenharmony_cistd::unique_ptr<StreamingParserHandler> NewCBOREncoder(std::string* out,
6271cb0ef41Sopenharmony_ci                                                       Status* status) {
6281cb0ef41Sopenharmony_ci  return std::unique_ptr<StreamingParserHandler>(
6291cb0ef41Sopenharmony_ci      new CBOREncoder<std::string>(out, status));
6301cb0ef41Sopenharmony_ci}
6311cb0ef41Sopenharmony_ci
6321cb0ef41Sopenharmony_ci// =============================================================================
6331cb0ef41Sopenharmony_ci// cbor::CBORTokenizer - for parsing individual CBOR items
6341cb0ef41Sopenharmony_ci// =============================================================================
6351cb0ef41Sopenharmony_ci
6361cb0ef41Sopenharmony_ciCBORTokenizer::CBORTokenizer(span<uint8_t> bytes) : bytes_(bytes) {
6371cb0ef41Sopenharmony_ci  ReadNextToken(/*enter_envelope=*/false);
6381cb0ef41Sopenharmony_ci}
6391cb0ef41Sopenharmony_ciCBORTokenizer::~CBORTokenizer() {}
6401cb0ef41Sopenharmony_ci
6411cb0ef41Sopenharmony_ciCBORTokenTag CBORTokenizer::TokenTag() const {
6421cb0ef41Sopenharmony_ci  return token_tag_;
6431cb0ef41Sopenharmony_ci}
6441cb0ef41Sopenharmony_ci
6451cb0ef41Sopenharmony_civoid CBORTokenizer::Next() {
6461cb0ef41Sopenharmony_ci  if (token_tag_ == CBORTokenTag::ERROR_VALUE ||
6471cb0ef41Sopenharmony_ci      token_tag_ == CBORTokenTag::DONE)
6481cb0ef41Sopenharmony_ci    return;
6491cb0ef41Sopenharmony_ci  ReadNextToken(/*enter_envelope=*/false);
6501cb0ef41Sopenharmony_ci}
6511cb0ef41Sopenharmony_ci
6521cb0ef41Sopenharmony_civoid CBORTokenizer::EnterEnvelope() {
6531cb0ef41Sopenharmony_ci  assert(token_tag_ == CBORTokenTag::ENVELOPE);
6541cb0ef41Sopenharmony_ci  ReadNextToken(/*enter_envelope=*/true);
6551cb0ef41Sopenharmony_ci}
6561cb0ef41Sopenharmony_ci
6571cb0ef41Sopenharmony_ciStatus CBORTokenizer::Status() const {
6581cb0ef41Sopenharmony_ci  return status_;
6591cb0ef41Sopenharmony_ci}
6601cb0ef41Sopenharmony_ci
6611cb0ef41Sopenharmony_ci// The following accessor functions ::GetInt32, ::GetDouble,
6621cb0ef41Sopenharmony_ci// ::GetString8, ::GetString16WireRep, ::GetBinary, ::GetEnvelopeContents
6631cb0ef41Sopenharmony_ci// assume that a particular token was recognized in ::ReadNextToken.
6641cb0ef41Sopenharmony_ci// That's where all the error checking is done. By design,
6651cb0ef41Sopenharmony_ci// the accessors (assuming the token was recognized) never produce
6661cb0ef41Sopenharmony_ci// an error.
6671cb0ef41Sopenharmony_ci
6681cb0ef41Sopenharmony_ciint32_t CBORTokenizer::GetInt32() const {
6691cb0ef41Sopenharmony_ci  assert(token_tag_ == CBORTokenTag::INT32);
6701cb0ef41Sopenharmony_ci  // The range checks happen in ::ReadNextToken().
6711cb0ef41Sopenharmony_ci  return static_cast<int32_t>(
6721cb0ef41Sopenharmony_ci      token_start_type_ == MajorType::UNSIGNED
6731cb0ef41Sopenharmony_ci          ? token_start_internal_value_
6741cb0ef41Sopenharmony_ci          : -static_cast<int64_t>(token_start_internal_value_) - 1);
6751cb0ef41Sopenharmony_ci}
6761cb0ef41Sopenharmony_ci
6771cb0ef41Sopenharmony_cidouble CBORTokenizer::GetDouble() const {
6781cb0ef41Sopenharmony_ci  assert(token_tag_ == CBORTokenTag::DOUBLE);
6791cb0ef41Sopenharmony_ci  union {
6801cb0ef41Sopenharmony_ci    uint64_t from_uint64;
6811cb0ef41Sopenharmony_ci    double to_double;
6821cb0ef41Sopenharmony_ci  } reinterpret;
6831cb0ef41Sopenharmony_ci  reinterpret.from_uint64 = ReadBytesMostSignificantByteFirst<uint64_t>(
6841cb0ef41Sopenharmony_ci      bytes_.subspan(status_.pos + 1));
6851cb0ef41Sopenharmony_ci  return reinterpret.to_double;
6861cb0ef41Sopenharmony_ci}
6871cb0ef41Sopenharmony_ci
6881cb0ef41Sopenharmony_cispan<uint8_t> CBORTokenizer::GetString8() const {
6891cb0ef41Sopenharmony_ci  assert(token_tag_ == CBORTokenTag::STRING8);
6901cb0ef41Sopenharmony_ci  auto length = static_cast<size_t>(token_start_internal_value_);
6911cb0ef41Sopenharmony_ci  return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
6921cb0ef41Sopenharmony_ci}
6931cb0ef41Sopenharmony_ci
6941cb0ef41Sopenharmony_cispan<uint8_t> CBORTokenizer::GetString16WireRep() const {
6951cb0ef41Sopenharmony_ci  assert(token_tag_ == CBORTokenTag::STRING16);
6961cb0ef41Sopenharmony_ci  auto length = static_cast<size_t>(token_start_internal_value_);
6971cb0ef41Sopenharmony_ci  return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
6981cb0ef41Sopenharmony_ci}
6991cb0ef41Sopenharmony_ci
7001cb0ef41Sopenharmony_cispan<uint8_t> CBORTokenizer::GetBinary() const {
7011cb0ef41Sopenharmony_ci  assert(token_tag_ == CBORTokenTag::BINARY);
7021cb0ef41Sopenharmony_ci  auto length = static_cast<size_t>(token_start_internal_value_);
7031cb0ef41Sopenharmony_ci  return bytes_.subspan(status_.pos + (token_byte_length_ - length), length);
7041cb0ef41Sopenharmony_ci}
7051cb0ef41Sopenharmony_ci
7061cb0ef41Sopenharmony_cispan<uint8_t> CBORTokenizer::GetEnvelopeContents() const {
7071cb0ef41Sopenharmony_ci  assert(token_tag_ == CBORTokenTag::ENVELOPE);
7081cb0ef41Sopenharmony_ci  auto length = static_cast<size_t>(token_start_internal_value_);
7091cb0ef41Sopenharmony_ci  return bytes_.subspan(status_.pos + kEncodedEnvelopeHeaderSize, length);
7101cb0ef41Sopenharmony_ci}
7111cb0ef41Sopenharmony_ci
7121cb0ef41Sopenharmony_ci// All error checking happens in ::ReadNextToken, so that the accessors
7131cb0ef41Sopenharmony_ci// can avoid having to carry an error return value.
7141cb0ef41Sopenharmony_ci//
7151cb0ef41Sopenharmony_ci// With respect to checking the encoded lengths of strings, arrays, etc:
7161cb0ef41Sopenharmony_ci// On the wire, CBOR uses 1,2,4, and 8 byte unsigned integers, so
7171cb0ef41Sopenharmony_ci// we initially read them as uint64_t, usually into token_start_internal_value_.
7181cb0ef41Sopenharmony_ci//
7191cb0ef41Sopenharmony_ci// However, since these containers have a representation on the machine,
7201cb0ef41Sopenharmony_ci// we need to do corresponding size computations on the input byte array,
7211cb0ef41Sopenharmony_ci// output span (e.g. the payload for a string), etc., and size_t is
7221cb0ef41Sopenharmony_ci// machine specific (in practice either 32 bit or 64 bit).
7231cb0ef41Sopenharmony_ci//
7241cb0ef41Sopenharmony_ci// Further, we must avoid overflowing size_t. Therefore, we use this
7251cb0ef41Sopenharmony_ci// kMaxValidLength constant to:
7261cb0ef41Sopenharmony_ci// - Reject values that are larger than the architecture specific
7271cb0ef41Sopenharmony_ci//   max size_t (differs between 32 bit and 64 bit arch).
7281cb0ef41Sopenharmony_ci// - Reserve at least one bit so that we can check against overflows
7291cb0ef41Sopenharmony_ci//   when adding lengths (array / string length / etc.); we do this by
7301cb0ef41Sopenharmony_ci//   ensuring that the inputs to an addition are <= kMaxValidLength,
7311cb0ef41Sopenharmony_ci//   and then checking whether the sum went past it.
7321cb0ef41Sopenharmony_ci//
7331cb0ef41Sopenharmony_ci// See also
7341cb0ef41Sopenharmony_ci// https://chromium.googlesource.com/chromium/src/+/master/docs/security/integer-semantics.md
7351cb0ef41Sopenharmony_cistatic const uint64_t kMaxValidLength =
7361cb0ef41Sopenharmony_ci    std::min<uint64_t>(std::numeric_limits<uint64_t>::max() >> 2,
7371cb0ef41Sopenharmony_ci                       std::numeric_limits<size_t>::max());
7381cb0ef41Sopenharmony_ci
7391cb0ef41Sopenharmony_civoid CBORTokenizer::ReadNextToken(bool enter_envelope) {
7401cb0ef41Sopenharmony_ci  if (enter_envelope) {
7411cb0ef41Sopenharmony_ci    status_.pos += kEncodedEnvelopeHeaderSize;
7421cb0ef41Sopenharmony_ci  } else {
7431cb0ef41Sopenharmony_ci    status_.pos =
7441cb0ef41Sopenharmony_ci        status_.pos == Status::npos() ? 0 : status_.pos + token_byte_length_;
7451cb0ef41Sopenharmony_ci  }
7461cb0ef41Sopenharmony_ci  status_.error = Error::OK;
7471cb0ef41Sopenharmony_ci  if (status_.pos >= bytes_.size()) {
7481cb0ef41Sopenharmony_ci    token_tag_ = CBORTokenTag::DONE;
7491cb0ef41Sopenharmony_ci    return;
7501cb0ef41Sopenharmony_ci  }
7511cb0ef41Sopenharmony_ci  const size_t remaining_bytes = bytes_.size() - status_.pos;
7521cb0ef41Sopenharmony_ci  switch (bytes_[status_.pos]) {
7531cb0ef41Sopenharmony_ci    case kStopByte:
7541cb0ef41Sopenharmony_ci      SetToken(CBORTokenTag::STOP, 1);
7551cb0ef41Sopenharmony_ci      return;
7561cb0ef41Sopenharmony_ci    case kInitialByteIndefiniteLengthMap:
7571cb0ef41Sopenharmony_ci      SetToken(CBORTokenTag::MAP_START, 1);
7581cb0ef41Sopenharmony_ci      return;
7591cb0ef41Sopenharmony_ci    case kInitialByteIndefiniteLengthArray:
7601cb0ef41Sopenharmony_ci      SetToken(CBORTokenTag::ARRAY_START, 1);
7611cb0ef41Sopenharmony_ci      return;
7621cb0ef41Sopenharmony_ci    case kEncodedTrue:
7631cb0ef41Sopenharmony_ci      SetToken(CBORTokenTag::TRUE_VALUE, 1);
7641cb0ef41Sopenharmony_ci      return;
7651cb0ef41Sopenharmony_ci    case kEncodedFalse:
7661cb0ef41Sopenharmony_ci      SetToken(CBORTokenTag::FALSE_VALUE, 1);
7671cb0ef41Sopenharmony_ci      return;
7681cb0ef41Sopenharmony_ci    case kEncodedNull:
7691cb0ef41Sopenharmony_ci      SetToken(CBORTokenTag::NULL_VALUE, 1);
7701cb0ef41Sopenharmony_ci      return;
7711cb0ef41Sopenharmony_ci    case kExpectedConversionToBase64Tag: {  // BINARY
7721cb0ef41Sopenharmony_ci      const size_t bytes_read = internals::ReadTokenStart(
7731cb0ef41Sopenharmony_ci          bytes_.subspan(status_.pos + 1), &token_start_type_,
7741cb0ef41Sopenharmony_ci          &token_start_internal_value_);
7751cb0ef41Sopenharmony_ci      if (!bytes_read || token_start_type_ != MajorType::BYTE_STRING ||
7761cb0ef41Sopenharmony_ci          token_start_internal_value_ > kMaxValidLength) {
7771cb0ef41Sopenharmony_ci        SetError(Error::CBOR_INVALID_BINARY);
7781cb0ef41Sopenharmony_ci        return;
7791cb0ef41Sopenharmony_ci      }
7801cb0ef41Sopenharmony_ci      const uint64_t token_byte_length = token_start_internal_value_ +
7811cb0ef41Sopenharmony_ci                                         /* tag before token start: */ 1 +
7821cb0ef41Sopenharmony_ci                                         /* token start: */ bytes_read;
7831cb0ef41Sopenharmony_ci      if (token_byte_length > remaining_bytes) {
7841cb0ef41Sopenharmony_ci        SetError(Error::CBOR_INVALID_BINARY);
7851cb0ef41Sopenharmony_ci        return;
7861cb0ef41Sopenharmony_ci      }
7871cb0ef41Sopenharmony_ci      SetToken(CBORTokenTag::BINARY, static_cast<size_t>(token_byte_length));
7881cb0ef41Sopenharmony_ci      return;
7891cb0ef41Sopenharmony_ci    }
7901cb0ef41Sopenharmony_ci    case kInitialByteForDouble: {  // DOUBLE
7911cb0ef41Sopenharmony_ci      if (kEncodedDoubleSize > remaining_bytes) {
7921cb0ef41Sopenharmony_ci        SetError(Error::CBOR_INVALID_DOUBLE);
7931cb0ef41Sopenharmony_ci        return;
7941cb0ef41Sopenharmony_ci      }
7951cb0ef41Sopenharmony_ci      SetToken(CBORTokenTag::DOUBLE, kEncodedDoubleSize);
7961cb0ef41Sopenharmony_ci      return;
7971cb0ef41Sopenharmony_ci    }
7981cb0ef41Sopenharmony_ci    case kInitialByteForEnvelope: {  // ENVELOPE
7991cb0ef41Sopenharmony_ci      if (kEncodedEnvelopeHeaderSize > remaining_bytes) {
8001cb0ef41Sopenharmony_ci        SetError(Error::CBOR_INVALID_ENVELOPE);
8011cb0ef41Sopenharmony_ci        return;
8021cb0ef41Sopenharmony_ci      }
8031cb0ef41Sopenharmony_ci      // The envelope must be a byte string with 32 bit length.
8041cb0ef41Sopenharmony_ci      if (bytes_[status_.pos + 1] != kInitialByteFor32BitLengthByteString) {
8051cb0ef41Sopenharmony_ci        SetError(Error::CBOR_INVALID_ENVELOPE);
8061cb0ef41Sopenharmony_ci        return;
8071cb0ef41Sopenharmony_ci      }
8081cb0ef41Sopenharmony_ci      // Read the length of the byte string.
8091cb0ef41Sopenharmony_ci      token_start_internal_value_ = ReadBytesMostSignificantByteFirst<uint32_t>(
8101cb0ef41Sopenharmony_ci          bytes_.subspan(status_.pos + 2));
8111cb0ef41Sopenharmony_ci      if (token_start_internal_value_ > kMaxValidLength) {
8121cb0ef41Sopenharmony_ci        SetError(Error::CBOR_INVALID_ENVELOPE);
8131cb0ef41Sopenharmony_ci        return;
8141cb0ef41Sopenharmony_ci      }
8151cb0ef41Sopenharmony_ci      uint64_t token_byte_length =
8161cb0ef41Sopenharmony_ci          token_start_internal_value_ + kEncodedEnvelopeHeaderSize;
8171cb0ef41Sopenharmony_ci      if (token_byte_length > remaining_bytes) {
8181cb0ef41Sopenharmony_ci        SetError(Error::CBOR_INVALID_ENVELOPE);
8191cb0ef41Sopenharmony_ci        return;
8201cb0ef41Sopenharmony_ci      }
8211cb0ef41Sopenharmony_ci      SetToken(CBORTokenTag::ENVELOPE, static_cast<size_t>(token_byte_length));
8221cb0ef41Sopenharmony_ci      return;
8231cb0ef41Sopenharmony_ci    }
8241cb0ef41Sopenharmony_ci    default: {
8251cb0ef41Sopenharmony_ci      const size_t bytes_read = internals::ReadTokenStart(
8261cb0ef41Sopenharmony_ci          bytes_.subspan(status_.pos), &token_start_type_,
8271cb0ef41Sopenharmony_ci          &token_start_internal_value_);
8281cb0ef41Sopenharmony_ci      switch (token_start_type_) {
8291cb0ef41Sopenharmony_ci        case MajorType::UNSIGNED:  // INT32.
8301cb0ef41Sopenharmony_ci          // INT32 is a signed int32 (int32 makes sense for the
8311cb0ef41Sopenharmony_ci          // inspector_protocol, it's not a CBOR limitation), so we check
8321cb0ef41Sopenharmony_ci          // against the signed max, so that the allowable values are
8331cb0ef41Sopenharmony_ci          // 0, 1, 2, ... 2^31 - 1.
8341cb0ef41Sopenharmony_ci          if (!bytes_read ||
8351cb0ef41Sopenharmony_ci                static_cast<int64_t>(std::numeric_limits<int32_t>::max()) <
8361cb0ef41Sopenharmony_ci                  static_cast<int64_t>(token_start_internal_value_)) {
8371cb0ef41Sopenharmony_ci            SetError(Error::CBOR_INVALID_INT32);
8381cb0ef41Sopenharmony_ci            return;
8391cb0ef41Sopenharmony_ci          }
8401cb0ef41Sopenharmony_ci          SetToken(CBORTokenTag::INT32, bytes_read);
8411cb0ef41Sopenharmony_ci          return;
8421cb0ef41Sopenharmony_ci        case MajorType::NEGATIVE: {  // INT32.
8431cb0ef41Sopenharmony_ci          // INT32 is a signed int32 (int32 makes sense for the
8441cb0ef41Sopenharmony_ci          // inspector_protocol, it's not a CBOR limitation); in CBOR, the
8451cb0ef41Sopenharmony_ci          // negative values for INT32 are represented as NEGATIVE, that is, -1
8461cb0ef41Sopenharmony_ci          // INT32 is represented as 1 << 5 | 0 (major type 1, additional info
8471cb0ef41Sopenharmony_ci          // value 0).
8481cb0ef41Sopenharmony_ci          // The represented allowed values range is -1 to -2^31.
8491cb0ef41Sopenharmony_ci          // They are mapped into the encoded range of 0 to 2^31-1.
8501cb0ef41Sopenharmony_ci          // We check the the payload in token_start_internal_value_ against
8511cb0ef41Sopenharmony_ci          // that range (2^31-1 is also known as
8521cb0ef41Sopenharmony_ci          // std::numeric_limits<int32_t>::max()).
8531cb0ef41Sopenharmony_ci          if (!bytes_read ||
8541cb0ef41Sopenharmony_ci	      static_cast<int64_t>(token_start_internal_value_) >
8551cb0ef41Sopenharmony_ci                static_cast<int64_t>(std::numeric_limits<int32_t>::max())) {
8561cb0ef41Sopenharmony_ci            SetError(Error::CBOR_INVALID_INT32);
8571cb0ef41Sopenharmony_ci            return;
8581cb0ef41Sopenharmony_ci          }
8591cb0ef41Sopenharmony_ci          SetToken(CBORTokenTag::INT32, bytes_read);
8601cb0ef41Sopenharmony_ci          return;
8611cb0ef41Sopenharmony_ci        }
8621cb0ef41Sopenharmony_ci        case MajorType::STRING: {  // STRING8.
8631cb0ef41Sopenharmony_ci          if (!bytes_read || token_start_internal_value_ > kMaxValidLength) {
8641cb0ef41Sopenharmony_ci            SetError(Error::CBOR_INVALID_STRING8);
8651cb0ef41Sopenharmony_ci            return;
8661cb0ef41Sopenharmony_ci          }
8671cb0ef41Sopenharmony_ci          uint64_t token_byte_length = token_start_internal_value_ + bytes_read;
8681cb0ef41Sopenharmony_ci          if (token_byte_length > remaining_bytes) {
8691cb0ef41Sopenharmony_ci            SetError(Error::CBOR_INVALID_STRING8);
8701cb0ef41Sopenharmony_ci            return;
8711cb0ef41Sopenharmony_ci          }
8721cb0ef41Sopenharmony_ci          SetToken(CBORTokenTag::STRING8,
8731cb0ef41Sopenharmony_ci                   static_cast<size_t>(token_byte_length));
8741cb0ef41Sopenharmony_ci          return;
8751cb0ef41Sopenharmony_ci        }
8761cb0ef41Sopenharmony_ci        case MajorType::BYTE_STRING: {  // STRING16.
8771cb0ef41Sopenharmony_ci          // Length must be divisible by 2 since UTF16 is 2 bytes per
8781cb0ef41Sopenharmony_ci          // character, hence the &1 check.
8791cb0ef41Sopenharmony_ci          if (!bytes_read || token_start_internal_value_ > kMaxValidLength ||
8801cb0ef41Sopenharmony_ci              token_start_internal_value_ & 1) {
8811cb0ef41Sopenharmony_ci            SetError(Error::CBOR_INVALID_STRING16);
8821cb0ef41Sopenharmony_ci            return;
8831cb0ef41Sopenharmony_ci          }
8841cb0ef41Sopenharmony_ci          uint64_t token_byte_length = token_start_internal_value_ + bytes_read;
8851cb0ef41Sopenharmony_ci          if (token_byte_length > remaining_bytes) {
8861cb0ef41Sopenharmony_ci            SetError(Error::CBOR_INVALID_STRING16);
8871cb0ef41Sopenharmony_ci            return;
8881cb0ef41Sopenharmony_ci          }
8891cb0ef41Sopenharmony_ci          SetToken(CBORTokenTag::STRING16,
8901cb0ef41Sopenharmony_ci                   static_cast<size_t>(token_byte_length));
8911cb0ef41Sopenharmony_ci          return;
8921cb0ef41Sopenharmony_ci        }
8931cb0ef41Sopenharmony_ci        case MajorType::ARRAY:
8941cb0ef41Sopenharmony_ci        case MajorType::MAP:
8951cb0ef41Sopenharmony_ci        case MajorType::TAG:
8961cb0ef41Sopenharmony_ci        case MajorType::SIMPLE_VALUE:
8971cb0ef41Sopenharmony_ci          SetError(Error::CBOR_UNSUPPORTED_VALUE);
8981cb0ef41Sopenharmony_ci          return;
8991cb0ef41Sopenharmony_ci      }
9001cb0ef41Sopenharmony_ci    }
9011cb0ef41Sopenharmony_ci  }
9021cb0ef41Sopenharmony_ci}
9031cb0ef41Sopenharmony_ci
9041cb0ef41Sopenharmony_civoid CBORTokenizer::SetToken(CBORTokenTag token_tag, size_t token_byte_length) {
9051cb0ef41Sopenharmony_ci  token_tag_ = token_tag;
9061cb0ef41Sopenharmony_ci  token_byte_length_ = token_byte_length;
9071cb0ef41Sopenharmony_ci}
9081cb0ef41Sopenharmony_ci
9091cb0ef41Sopenharmony_civoid CBORTokenizer::SetError(Error error) {
9101cb0ef41Sopenharmony_ci  token_tag_ = CBORTokenTag::ERROR_VALUE;
9111cb0ef41Sopenharmony_ci  status_.error = error;
9121cb0ef41Sopenharmony_ci}
9131cb0ef41Sopenharmony_ci
9141cb0ef41Sopenharmony_ci// =============================================================================
9151cb0ef41Sopenharmony_ci// cbor::ParseCBOR - for receiving streaming parser events for CBOR messages
9161cb0ef41Sopenharmony_ci// =============================================================================
9171cb0ef41Sopenharmony_ci
9181cb0ef41Sopenharmony_cinamespace {
9191cb0ef41Sopenharmony_ci// When parsing CBOR, we limit recursion depth for objects and arrays
9201cb0ef41Sopenharmony_ci// to this constant.
9211cb0ef41Sopenharmony_cistatic constexpr int kStackLimit = 300;
9221cb0ef41Sopenharmony_ci
9231cb0ef41Sopenharmony_ci// Below are three parsing routines for CBOR, which cover enough
9241cb0ef41Sopenharmony_ci// to roundtrip JSON messages.
9251cb0ef41Sopenharmony_cibool ParseMap(int32_t stack_depth,
9261cb0ef41Sopenharmony_ci              CBORTokenizer* tokenizer,
9271cb0ef41Sopenharmony_ci              StreamingParserHandler* out);
9281cb0ef41Sopenharmony_cibool ParseArray(int32_t stack_depth,
9291cb0ef41Sopenharmony_ci                CBORTokenizer* tokenizer,
9301cb0ef41Sopenharmony_ci                StreamingParserHandler* out);
9311cb0ef41Sopenharmony_cibool ParseValue(int32_t stack_depth,
9321cb0ef41Sopenharmony_ci                CBORTokenizer* tokenizer,
9331cb0ef41Sopenharmony_ci                StreamingParserHandler* out);
9341cb0ef41Sopenharmony_ci
9351cb0ef41Sopenharmony_civoid ParseUTF16String(CBORTokenizer* tokenizer, StreamingParserHandler* out) {
9361cb0ef41Sopenharmony_ci  std::vector<uint16_t> value;
9371cb0ef41Sopenharmony_ci  span<uint8_t> rep = tokenizer->GetString16WireRep();
9381cb0ef41Sopenharmony_ci  for (size_t ii = 0; ii < rep.size(); ii += 2)
9391cb0ef41Sopenharmony_ci    value.push_back((rep[ii + 1] << 8) | rep[ii]);
9401cb0ef41Sopenharmony_ci  out->HandleString16(span<uint16_t>(value.data(), value.size()));
9411cb0ef41Sopenharmony_ci  tokenizer->Next();
9421cb0ef41Sopenharmony_ci}
9431cb0ef41Sopenharmony_ci
9441cb0ef41Sopenharmony_cibool ParseUTF8String(CBORTokenizer* tokenizer, StreamingParserHandler* out) {
9451cb0ef41Sopenharmony_ci  assert(tokenizer->TokenTag() == CBORTokenTag::STRING8);
9461cb0ef41Sopenharmony_ci  out->HandleString8(tokenizer->GetString8());
9471cb0ef41Sopenharmony_ci  tokenizer->Next();
9481cb0ef41Sopenharmony_ci  return true;
9491cb0ef41Sopenharmony_ci}
9501cb0ef41Sopenharmony_ci
9511cb0ef41Sopenharmony_cibool ParseValue(int32_t stack_depth,
9521cb0ef41Sopenharmony_ci                CBORTokenizer* tokenizer,
9531cb0ef41Sopenharmony_ci                StreamingParserHandler* out) {
9541cb0ef41Sopenharmony_ci  if (stack_depth > kStackLimit) {
9551cb0ef41Sopenharmony_ci    out->HandleError(
9561cb0ef41Sopenharmony_ci        Status{Error::CBOR_STACK_LIMIT_EXCEEDED, tokenizer->Status().pos});
9571cb0ef41Sopenharmony_ci    return false;
9581cb0ef41Sopenharmony_ci  }
9591cb0ef41Sopenharmony_ci  // Skip past the envelope to get to what's inside.
9601cb0ef41Sopenharmony_ci  if (tokenizer->TokenTag() == CBORTokenTag::ENVELOPE)
9611cb0ef41Sopenharmony_ci    tokenizer->EnterEnvelope();
9621cb0ef41Sopenharmony_ci  switch (tokenizer->TokenTag()) {
9631cb0ef41Sopenharmony_ci    case CBORTokenTag::ERROR_VALUE:
9641cb0ef41Sopenharmony_ci      out->HandleError(tokenizer->Status());
9651cb0ef41Sopenharmony_ci      return false;
9661cb0ef41Sopenharmony_ci    case CBORTokenTag::DONE:
9671cb0ef41Sopenharmony_ci      out->HandleError(Status{Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE,
9681cb0ef41Sopenharmony_ci                              tokenizer->Status().pos});
9691cb0ef41Sopenharmony_ci      return false;
9701cb0ef41Sopenharmony_ci    case CBORTokenTag::TRUE_VALUE:
9711cb0ef41Sopenharmony_ci      out->HandleBool(true);
9721cb0ef41Sopenharmony_ci      tokenizer->Next();
9731cb0ef41Sopenharmony_ci      return true;
9741cb0ef41Sopenharmony_ci    case CBORTokenTag::FALSE_VALUE:
9751cb0ef41Sopenharmony_ci      out->HandleBool(false);
9761cb0ef41Sopenharmony_ci      tokenizer->Next();
9771cb0ef41Sopenharmony_ci      return true;
9781cb0ef41Sopenharmony_ci    case CBORTokenTag::NULL_VALUE:
9791cb0ef41Sopenharmony_ci      out->HandleNull();
9801cb0ef41Sopenharmony_ci      tokenizer->Next();
9811cb0ef41Sopenharmony_ci      return true;
9821cb0ef41Sopenharmony_ci    case CBORTokenTag::INT32:
9831cb0ef41Sopenharmony_ci      out->HandleInt32(tokenizer->GetInt32());
9841cb0ef41Sopenharmony_ci      tokenizer->Next();
9851cb0ef41Sopenharmony_ci      return true;
9861cb0ef41Sopenharmony_ci    case CBORTokenTag::DOUBLE:
9871cb0ef41Sopenharmony_ci      out->HandleDouble(tokenizer->GetDouble());
9881cb0ef41Sopenharmony_ci      tokenizer->Next();
9891cb0ef41Sopenharmony_ci      return true;
9901cb0ef41Sopenharmony_ci    case CBORTokenTag::STRING8:
9911cb0ef41Sopenharmony_ci      return ParseUTF8String(tokenizer, out);
9921cb0ef41Sopenharmony_ci    case CBORTokenTag::STRING16:
9931cb0ef41Sopenharmony_ci      ParseUTF16String(tokenizer, out);
9941cb0ef41Sopenharmony_ci      return true;
9951cb0ef41Sopenharmony_ci    case CBORTokenTag::BINARY: {
9961cb0ef41Sopenharmony_ci      out->HandleBinary(tokenizer->GetBinary());
9971cb0ef41Sopenharmony_ci      tokenizer->Next();
9981cb0ef41Sopenharmony_ci      return true;
9991cb0ef41Sopenharmony_ci    }
10001cb0ef41Sopenharmony_ci    case CBORTokenTag::MAP_START:
10011cb0ef41Sopenharmony_ci      return ParseMap(stack_depth + 1, tokenizer, out);
10021cb0ef41Sopenharmony_ci    case CBORTokenTag::ARRAY_START:
10031cb0ef41Sopenharmony_ci      return ParseArray(stack_depth + 1, tokenizer, out);
10041cb0ef41Sopenharmony_ci    default:
10051cb0ef41Sopenharmony_ci      out->HandleError(
10061cb0ef41Sopenharmony_ci          Status{Error::CBOR_UNSUPPORTED_VALUE, tokenizer->Status().pos});
10071cb0ef41Sopenharmony_ci      return false;
10081cb0ef41Sopenharmony_ci  }
10091cb0ef41Sopenharmony_ci}
10101cb0ef41Sopenharmony_ci
10111cb0ef41Sopenharmony_ci// |bytes| must start with the indefinite length array byte, so basically,
10121cb0ef41Sopenharmony_ci// ParseArray may only be called after an indefinite length array has been
10131cb0ef41Sopenharmony_ci// detected.
10141cb0ef41Sopenharmony_cibool ParseArray(int32_t stack_depth,
10151cb0ef41Sopenharmony_ci                CBORTokenizer* tokenizer,
10161cb0ef41Sopenharmony_ci                StreamingParserHandler* out) {
10171cb0ef41Sopenharmony_ci  assert(tokenizer->TokenTag() == CBORTokenTag::ARRAY_START);
10181cb0ef41Sopenharmony_ci  tokenizer->Next();
10191cb0ef41Sopenharmony_ci  out->HandleArrayBegin();
10201cb0ef41Sopenharmony_ci  while (tokenizer->TokenTag() != CBORTokenTag::STOP) {
10211cb0ef41Sopenharmony_ci    if (tokenizer->TokenTag() == CBORTokenTag::DONE) {
10221cb0ef41Sopenharmony_ci      out->HandleError(
10231cb0ef41Sopenharmony_ci          Status{Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, tokenizer->Status().pos});
10241cb0ef41Sopenharmony_ci      return false;
10251cb0ef41Sopenharmony_ci    }
10261cb0ef41Sopenharmony_ci    if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) {
10271cb0ef41Sopenharmony_ci      out->HandleError(tokenizer->Status());
10281cb0ef41Sopenharmony_ci      return false;
10291cb0ef41Sopenharmony_ci    }
10301cb0ef41Sopenharmony_ci    // Parse value.
10311cb0ef41Sopenharmony_ci    if (!ParseValue(stack_depth, tokenizer, out))
10321cb0ef41Sopenharmony_ci      return false;
10331cb0ef41Sopenharmony_ci  }
10341cb0ef41Sopenharmony_ci  out->HandleArrayEnd();
10351cb0ef41Sopenharmony_ci  tokenizer->Next();
10361cb0ef41Sopenharmony_ci  return true;
10371cb0ef41Sopenharmony_ci}
10381cb0ef41Sopenharmony_ci
10391cb0ef41Sopenharmony_ci// |bytes| must start with the indefinite length array byte, so basically,
10401cb0ef41Sopenharmony_ci// ParseArray may only be called after an indefinite length array has been
10411cb0ef41Sopenharmony_ci// detected.
10421cb0ef41Sopenharmony_cibool ParseMap(int32_t stack_depth,
10431cb0ef41Sopenharmony_ci              CBORTokenizer* tokenizer,
10441cb0ef41Sopenharmony_ci              StreamingParserHandler* out) {
10451cb0ef41Sopenharmony_ci  assert(tokenizer->TokenTag() == CBORTokenTag::MAP_START);
10461cb0ef41Sopenharmony_ci  out->HandleMapBegin();
10471cb0ef41Sopenharmony_ci  tokenizer->Next();
10481cb0ef41Sopenharmony_ci  while (tokenizer->TokenTag() != CBORTokenTag::STOP) {
10491cb0ef41Sopenharmony_ci    if (tokenizer->TokenTag() == CBORTokenTag::DONE) {
10501cb0ef41Sopenharmony_ci      out->HandleError(
10511cb0ef41Sopenharmony_ci          Status{Error::CBOR_UNEXPECTED_EOF_IN_MAP, tokenizer->Status().pos});
10521cb0ef41Sopenharmony_ci      return false;
10531cb0ef41Sopenharmony_ci    }
10541cb0ef41Sopenharmony_ci    if (tokenizer->TokenTag() == CBORTokenTag::ERROR_VALUE) {
10551cb0ef41Sopenharmony_ci      out->HandleError(tokenizer->Status());
10561cb0ef41Sopenharmony_ci      return false;
10571cb0ef41Sopenharmony_ci    }
10581cb0ef41Sopenharmony_ci    // Parse key.
10591cb0ef41Sopenharmony_ci    if (tokenizer->TokenTag() == CBORTokenTag::STRING8) {
10601cb0ef41Sopenharmony_ci      if (!ParseUTF8String(tokenizer, out))
10611cb0ef41Sopenharmony_ci        return false;
10621cb0ef41Sopenharmony_ci    } else if (tokenizer->TokenTag() == CBORTokenTag::STRING16) {
10631cb0ef41Sopenharmony_ci      ParseUTF16String(tokenizer, out);
10641cb0ef41Sopenharmony_ci    } else {
10651cb0ef41Sopenharmony_ci      out->HandleError(
10661cb0ef41Sopenharmony_ci          Status{Error::CBOR_INVALID_MAP_KEY, tokenizer->Status().pos});
10671cb0ef41Sopenharmony_ci      return false;
10681cb0ef41Sopenharmony_ci    }
10691cb0ef41Sopenharmony_ci    // Parse value.
10701cb0ef41Sopenharmony_ci    if (!ParseValue(stack_depth, tokenizer, out))
10711cb0ef41Sopenharmony_ci      return false;
10721cb0ef41Sopenharmony_ci  }
10731cb0ef41Sopenharmony_ci  out->HandleMapEnd();
10741cb0ef41Sopenharmony_ci  tokenizer->Next();
10751cb0ef41Sopenharmony_ci  return true;
10761cb0ef41Sopenharmony_ci}
10771cb0ef41Sopenharmony_ci}  // namespace
10781cb0ef41Sopenharmony_ci
10791cb0ef41Sopenharmony_civoid ParseCBOR(span<uint8_t> bytes, StreamingParserHandler* out) {
10801cb0ef41Sopenharmony_ci  if (bytes.empty()) {
10811cb0ef41Sopenharmony_ci    out->HandleError(Status{Error::CBOR_NO_INPUT, 0});
10821cb0ef41Sopenharmony_ci    return;
10831cb0ef41Sopenharmony_ci  }
10841cb0ef41Sopenharmony_ci  if (bytes[0] != kInitialByteForEnvelope) {
10851cb0ef41Sopenharmony_ci    out->HandleError(Status{Error::CBOR_INVALID_START_BYTE, 0});
10861cb0ef41Sopenharmony_ci    return;
10871cb0ef41Sopenharmony_ci  }
10881cb0ef41Sopenharmony_ci  CBORTokenizer tokenizer(bytes);
10891cb0ef41Sopenharmony_ci  if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) {
10901cb0ef41Sopenharmony_ci    out->HandleError(tokenizer.Status());
10911cb0ef41Sopenharmony_ci    return;
10921cb0ef41Sopenharmony_ci  }
10931cb0ef41Sopenharmony_ci  // We checked for the envelope start byte above, so the tokenizer
10941cb0ef41Sopenharmony_ci  // must agree here, since it's not an error.
10951cb0ef41Sopenharmony_ci  assert(tokenizer.TokenTag() == CBORTokenTag::ENVELOPE);
10961cb0ef41Sopenharmony_ci  tokenizer.EnterEnvelope();
10971cb0ef41Sopenharmony_ci  if (tokenizer.TokenTag() != CBORTokenTag::MAP_START) {
10981cb0ef41Sopenharmony_ci    out->HandleError(
10991cb0ef41Sopenharmony_ci        Status{Error::CBOR_MAP_START_EXPECTED, tokenizer.Status().pos});
11001cb0ef41Sopenharmony_ci    return;
11011cb0ef41Sopenharmony_ci  }
11021cb0ef41Sopenharmony_ci  if (!ParseMap(/*stack_depth=*/1, &tokenizer, out))
11031cb0ef41Sopenharmony_ci    return;
11041cb0ef41Sopenharmony_ci  if (tokenizer.TokenTag() == CBORTokenTag::DONE)
11051cb0ef41Sopenharmony_ci    return;
11061cb0ef41Sopenharmony_ci  if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE) {
11071cb0ef41Sopenharmony_ci    out->HandleError(tokenizer.Status());
11081cb0ef41Sopenharmony_ci    return;
11091cb0ef41Sopenharmony_ci  }
11101cb0ef41Sopenharmony_ci  out->HandleError(Status{Error::CBOR_TRAILING_JUNK, tokenizer.Status().pos});
11111cb0ef41Sopenharmony_ci}
11121cb0ef41Sopenharmony_ci
11131cb0ef41Sopenharmony_ci// =============================================================================
11141cb0ef41Sopenharmony_ci// cbor::AppendString8EntryToMap - for limited in-place editing of messages
11151cb0ef41Sopenharmony_ci// =============================================================================
11161cb0ef41Sopenharmony_ci
11171cb0ef41Sopenharmony_citemplate <typename C>
11181cb0ef41Sopenharmony_ciStatus AppendString8EntryToCBORMapTmpl(span<uint8_t> string8_key,
11191cb0ef41Sopenharmony_ci                                       span<uint8_t> string8_value,
11201cb0ef41Sopenharmony_ci                                       C* cbor) {
11211cb0ef41Sopenharmony_ci  // Careful below: Don't compare (*cbor)[idx] with a uint8_t, since
11221cb0ef41Sopenharmony_ci  // it could be a char (signed!). Instead, use bytes.
11231cb0ef41Sopenharmony_ci  span<uint8_t> bytes(reinterpret_cast<const uint8_t*>(cbor->data()),
11241cb0ef41Sopenharmony_ci                      cbor->size());
11251cb0ef41Sopenharmony_ci  CBORTokenizer tokenizer(bytes);
11261cb0ef41Sopenharmony_ci  if (tokenizer.TokenTag() == CBORTokenTag::ERROR_VALUE)
11271cb0ef41Sopenharmony_ci    return tokenizer.Status();
11281cb0ef41Sopenharmony_ci  if (tokenizer.TokenTag() != CBORTokenTag::ENVELOPE)
11291cb0ef41Sopenharmony_ci    return Status(Error::CBOR_INVALID_ENVELOPE, 0);
11301cb0ef41Sopenharmony_ci  size_t envelope_size = tokenizer.GetEnvelopeContents().size();
11311cb0ef41Sopenharmony_ci  size_t old_size = cbor->size();
11321cb0ef41Sopenharmony_ci  if (old_size != envelope_size + kEncodedEnvelopeHeaderSize)
11331cb0ef41Sopenharmony_ci    return Status(Error::CBOR_INVALID_ENVELOPE, 0);
11341cb0ef41Sopenharmony_ci  if (envelope_size == 0 ||
11351cb0ef41Sopenharmony_ci      (tokenizer.GetEnvelopeContents()[0] != EncodeIndefiniteLengthMapStart()))
11361cb0ef41Sopenharmony_ci    return Status(Error::CBOR_MAP_START_EXPECTED, kEncodedEnvelopeHeaderSize);
11371cb0ef41Sopenharmony_ci  if (bytes[bytes.size() - 1] != EncodeStop())
11381cb0ef41Sopenharmony_ci    return Status(Error::CBOR_MAP_STOP_EXPECTED, cbor->size() - 1);
11391cb0ef41Sopenharmony_ci  cbor->pop_back();
11401cb0ef41Sopenharmony_ci  EncodeString8(string8_key, cbor);
11411cb0ef41Sopenharmony_ci  EncodeString8(string8_value, cbor);
11421cb0ef41Sopenharmony_ci  cbor->push_back(EncodeStop());
11431cb0ef41Sopenharmony_ci  size_t new_envelope_size = envelope_size + (cbor->size() - old_size);
11441cb0ef41Sopenharmony_ci  if (new_envelope_size > std::numeric_limits<uint32_t>::max())
11451cb0ef41Sopenharmony_ci    return Status(Error::CBOR_ENVELOPE_SIZE_LIMIT_EXCEEDED, 0);
11461cb0ef41Sopenharmony_ci  size_t size_pos = cbor->size() - new_envelope_size - sizeof(uint32_t);
11471cb0ef41Sopenharmony_ci  uint8_t* out = reinterpret_cast<uint8_t*>(&cbor->at(size_pos));
11481cb0ef41Sopenharmony_ci  *(out++) = (new_envelope_size >> 24) & 0xff;
11491cb0ef41Sopenharmony_ci  *(out++) = (new_envelope_size >> 16) & 0xff;
11501cb0ef41Sopenharmony_ci  *(out++) = (new_envelope_size >> 8) & 0xff;
11511cb0ef41Sopenharmony_ci  *(out) = new_envelope_size & 0xff;
11521cb0ef41Sopenharmony_ci  return Status();
11531cb0ef41Sopenharmony_ci}
11541cb0ef41Sopenharmony_ciStatus AppendString8EntryToCBORMap(span<uint8_t> string8_key,
11551cb0ef41Sopenharmony_ci                                   span<uint8_t> string8_value,
11561cb0ef41Sopenharmony_ci                                   std::vector<uint8_t>* cbor) {
11571cb0ef41Sopenharmony_ci  return AppendString8EntryToCBORMapTmpl(string8_key, string8_value, cbor);
11581cb0ef41Sopenharmony_ci}
11591cb0ef41Sopenharmony_ciStatus AppendString8EntryToCBORMap(span<uint8_t> string8_key,
11601cb0ef41Sopenharmony_ci                                   span<uint8_t> string8_value,
11611cb0ef41Sopenharmony_ci                                   std::string* cbor) {
11621cb0ef41Sopenharmony_ci  return AppendString8EntryToCBORMapTmpl(string8_key, string8_value, cbor);
11631cb0ef41Sopenharmony_ci}
11641cb0ef41Sopenharmony_ci}  // namespace cbor
11651cb0ef41Sopenharmony_ci
11661cb0ef41Sopenharmony_cinamespace json {
11671cb0ef41Sopenharmony_ci
11681cb0ef41Sopenharmony_ci// =============================================================================
11691cb0ef41Sopenharmony_ci// json::NewJSONEncoder - for encoding streaming parser events as JSON
11701cb0ef41Sopenharmony_ci// =============================================================================
11711cb0ef41Sopenharmony_ci
11721cb0ef41Sopenharmony_cinamespace {
11731cb0ef41Sopenharmony_ci// Prints |value| to |out| with 4 hex digits, most significant chunk first.
11741cb0ef41Sopenharmony_citemplate <typename C>
11751cb0ef41Sopenharmony_civoid PrintHex(uint16_t value, C* out) {
11761cb0ef41Sopenharmony_ci  for (int ii = 3; ii >= 0; --ii) {
11771cb0ef41Sopenharmony_ci    int four_bits = 0xf & (value >> (4 * ii));
11781cb0ef41Sopenharmony_ci    out->push_back(four_bits + ((four_bits <= 9) ? '0' : ('a' - 10)));
11791cb0ef41Sopenharmony_ci  }
11801cb0ef41Sopenharmony_ci}
11811cb0ef41Sopenharmony_ci
11821cb0ef41Sopenharmony_ci// In the writer below, we maintain a stack of State instances.
11831cb0ef41Sopenharmony_ci// It is just enough to emit the appropriate delimiters and brackets
11841cb0ef41Sopenharmony_ci// in JSON.
11851cb0ef41Sopenharmony_cienum class Container {
11861cb0ef41Sopenharmony_ci  // Used for the top-level, initial state.
11871cb0ef41Sopenharmony_ci  NONE,
11881cb0ef41Sopenharmony_ci  // Inside a JSON object.
11891cb0ef41Sopenharmony_ci  MAP,
11901cb0ef41Sopenharmony_ci  // Inside a JSON array.
11911cb0ef41Sopenharmony_ci  ARRAY
11921cb0ef41Sopenharmony_ci};
11931cb0ef41Sopenharmony_ciclass State {
11941cb0ef41Sopenharmony_ci public:
11951cb0ef41Sopenharmony_ci  explicit State(Container container) : container_(container) {}
11961cb0ef41Sopenharmony_ci  void StartElement(std::vector<uint8_t>* out) { StartElementTmpl(out); }
11971cb0ef41Sopenharmony_ci  void StartElement(std::string* out) { StartElementTmpl(out); }
11981cb0ef41Sopenharmony_ci  Container container() const { return container_; }
11991cb0ef41Sopenharmony_ci
12001cb0ef41Sopenharmony_ci private:
12011cb0ef41Sopenharmony_ci  template <typename C>
12021cb0ef41Sopenharmony_ci  void StartElementTmpl(C* out) {
12031cb0ef41Sopenharmony_ci    assert(container_ != Container::NONE || size_ == 0);
12041cb0ef41Sopenharmony_ci    if (size_ != 0) {
12051cb0ef41Sopenharmony_ci      char delim = (!(size_ & 1) || container_ == Container::ARRAY) ? ',' : ':';
12061cb0ef41Sopenharmony_ci      out->push_back(delim);
12071cb0ef41Sopenharmony_ci    }
12081cb0ef41Sopenharmony_ci    ++size_;
12091cb0ef41Sopenharmony_ci  }
12101cb0ef41Sopenharmony_ci
12111cb0ef41Sopenharmony_ci  Container container_ = Container::NONE;
12121cb0ef41Sopenharmony_ci  int size_ = 0;
12131cb0ef41Sopenharmony_ci};
12141cb0ef41Sopenharmony_ci
12151cb0ef41Sopenharmony_ciconstexpr char kBase64Table[] =
12161cb0ef41Sopenharmony_ci    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
12171cb0ef41Sopenharmony_ci    "abcdefghijklmnopqrstuvwxyz0123456789+/";
12181cb0ef41Sopenharmony_ci
12191cb0ef41Sopenharmony_citemplate <typename C>
12201cb0ef41Sopenharmony_civoid Base64Encode(const span<uint8_t>& in, C* out) {
12211cb0ef41Sopenharmony_ci  // The following three cases are based on the tables in the example
12221cb0ef41Sopenharmony_ci  // section in https://en.wikipedia.org/wiki/Base64. We process three
12231cb0ef41Sopenharmony_ci  // input bytes at a time, emitting 4 output bytes at a time.
12241cb0ef41Sopenharmony_ci  size_t ii = 0;
12251cb0ef41Sopenharmony_ci
12261cb0ef41Sopenharmony_ci  // While possible, process three input bytes.
12271cb0ef41Sopenharmony_ci  for (; ii + 3 <= in.size(); ii += 3) {
12281cb0ef41Sopenharmony_ci    uint32_t twentyfour_bits = (in[ii] << 16) | (in[ii + 1] << 8) | in[ii + 2];
12291cb0ef41Sopenharmony_ci    out->push_back(kBase64Table[(twentyfour_bits >> 18)]);
12301cb0ef41Sopenharmony_ci    out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]);
12311cb0ef41Sopenharmony_ci    out->push_back(kBase64Table[(twentyfour_bits >> 6) & 0x3f]);
12321cb0ef41Sopenharmony_ci    out->push_back(kBase64Table[twentyfour_bits & 0x3f]);
12331cb0ef41Sopenharmony_ci  }
12341cb0ef41Sopenharmony_ci  if (ii + 2 <= in.size()) {  // Process two input bytes.
12351cb0ef41Sopenharmony_ci    uint32_t twentyfour_bits = (in[ii] << 16) | (in[ii + 1] << 8);
12361cb0ef41Sopenharmony_ci    out->push_back(kBase64Table[(twentyfour_bits >> 18)]);
12371cb0ef41Sopenharmony_ci    out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]);
12381cb0ef41Sopenharmony_ci    out->push_back(kBase64Table[(twentyfour_bits >> 6) & 0x3f]);
12391cb0ef41Sopenharmony_ci    out->push_back('=');  // Emit padding.
12401cb0ef41Sopenharmony_ci    return;
12411cb0ef41Sopenharmony_ci  }
12421cb0ef41Sopenharmony_ci  if (ii + 1 <= in.size()) {  // Process a single input byte.
12431cb0ef41Sopenharmony_ci    uint32_t twentyfour_bits = (in[ii] << 16);
12441cb0ef41Sopenharmony_ci    out->push_back(kBase64Table[(twentyfour_bits >> 18)]);
12451cb0ef41Sopenharmony_ci    out->push_back(kBase64Table[(twentyfour_bits >> 12) & 0x3f]);
12461cb0ef41Sopenharmony_ci    out->push_back('=');  // Emit padding.
12471cb0ef41Sopenharmony_ci    out->push_back('=');  // Emit padding.
12481cb0ef41Sopenharmony_ci  }
12491cb0ef41Sopenharmony_ci}
12501cb0ef41Sopenharmony_ci
12511cb0ef41Sopenharmony_ci// Implements a handler for JSON parser events to emit a JSON string.
12521cb0ef41Sopenharmony_citemplate <typename C>
12531cb0ef41Sopenharmony_ciclass JSONEncoder : public StreamingParserHandler {
12541cb0ef41Sopenharmony_ci public:
12551cb0ef41Sopenharmony_ci  JSONEncoder(const Platform* platform, C* out, Status* status)
12561cb0ef41Sopenharmony_ci      : platform_(platform), out_(out), status_(status) {
12571cb0ef41Sopenharmony_ci    *status_ = Status();
12581cb0ef41Sopenharmony_ci    state_.emplace(Container::NONE);
12591cb0ef41Sopenharmony_ci  }
12601cb0ef41Sopenharmony_ci
12611cb0ef41Sopenharmony_ci  void HandleMapBegin() override {
12621cb0ef41Sopenharmony_ci    if (!status_->ok())
12631cb0ef41Sopenharmony_ci      return;
12641cb0ef41Sopenharmony_ci    assert(!state_.empty());
12651cb0ef41Sopenharmony_ci    state_.top().StartElement(out_);
12661cb0ef41Sopenharmony_ci    state_.emplace(Container::MAP);
12671cb0ef41Sopenharmony_ci    Emit('{');
12681cb0ef41Sopenharmony_ci  }
12691cb0ef41Sopenharmony_ci
12701cb0ef41Sopenharmony_ci  void HandleMapEnd() override {
12711cb0ef41Sopenharmony_ci    if (!status_->ok())
12721cb0ef41Sopenharmony_ci      return;
12731cb0ef41Sopenharmony_ci    assert(state_.size() >= 2 && state_.top().container() == Container::MAP);
12741cb0ef41Sopenharmony_ci    state_.pop();
12751cb0ef41Sopenharmony_ci    Emit('}');
12761cb0ef41Sopenharmony_ci  }
12771cb0ef41Sopenharmony_ci
12781cb0ef41Sopenharmony_ci  void HandleArrayBegin() override {
12791cb0ef41Sopenharmony_ci    if (!status_->ok())
12801cb0ef41Sopenharmony_ci      return;
12811cb0ef41Sopenharmony_ci    state_.top().StartElement(out_);
12821cb0ef41Sopenharmony_ci    state_.emplace(Container::ARRAY);
12831cb0ef41Sopenharmony_ci    Emit('[');
12841cb0ef41Sopenharmony_ci  }
12851cb0ef41Sopenharmony_ci
12861cb0ef41Sopenharmony_ci  void HandleArrayEnd() override {
12871cb0ef41Sopenharmony_ci    if (!status_->ok())
12881cb0ef41Sopenharmony_ci      return;
12891cb0ef41Sopenharmony_ci    assert(state_.size() >= 2 && state_.top().container() == Container::ARRAY);
12901cb0ef41Sopenharmony_ci    state_.pop();
12911cb0ef41Sopenharmony_ci    Emit(']');
12921cb0ef41Sopenharmony_ci  }
12931cb0ef41Sopenharmony_ci
12941cb0ef41Sopenharmony_ci  void HandleString16(span<uint16_t> chars) override {
12951cb0ef41Sopenharmony_ci    if (!status_->ok())
12961cb0ef41Sopenharmony_ci      return;
12971cb0ef41Sopenharmony_ci    state_.top().StartElement(out_);
12981cb0ef41Sopenharmony_ci    Emit('"');
12991cb0ef41Sopenharmony_ci    for (const uint16_t ch : chars) {
13001cb0ef41Sopenharmony_ci      if (ch == '"') {
13011cb0ef41Sopenharmony_ci        Emit("\\\"");
13021cb0ef41Sopenharmony_ci      } else if (ch == '\\') {
13031cb0ef41Sopenharmony_ci        Emit("\\\\");
13041cb0ef41Sopenharmony_ci      } else if (ch == '\b') {
13051cb0ef41Sopenharmony_ci        Emit("\\b");
13061cb0ef41Sopenharmony_ci      } else if (ch == '\f') {
13071cb0ef41Sopenharmony_ci        Emit("\\f");
13081cb0ef41Sopenharmony_ci      } else if (ch == '\n') {
13091cb0ef41Sopenharmony_ci        Emit("\\n");
13101cb0ef41Sopenharmony_ci      } else if (ch == '\r') {
13111cb0ef41Sopenharmony_ci        Emit("\\r");
13121cb0ef41Sopenharmony_ci      } else if (ch == '\t') {
13131cb0ef41Sopenharmony_ci        Emit("\\t");
13141cb0ef41Sopenharmony_ci      } else if (ch >= 32 && ch <= 126) {
13151cb0ef41Sopenharmony_ci        Emit(ch);
13161cb0ef41Sopenharmony_ci      } else {
13171cb0ef41Sopenharmony_ci        Emit("\\u");
13181cb0ef41Sopenharmony_ci        PrintHex(ch, out_);
13191cb0ef41Sopenharmony_ci      }
13201cb0ef41Sopenharmony_ci    }
13211cb0ef41Sopenharmony_ci    Emit('"');
13221cb0ef41Sopenharmony_ci  }
13231cb0ef41Sopenharmony_ci
13241cb0ef41Sopenharmony_ci  void HandleString8(span<uint8_t> chars) override {
13251cb0ef41Sopenharmony_ci    if (!status_->ok())
13261cb0ef41Sopenharmony_ci      return;
13271cb0ef41Sopenharmony_ci    state_.top().StartElement(out_);
13281cb0ef41Sopenharmony_ci    Emit('"');
13291cb0ef41Sopenharmony_ci    for (size_t ii = 0; ii < chars.size(); ++ii) {
13301cb0ef41Sopenharmony_ci      uint8_t c = chars[ii];
13311cb0ef41Sopenharmony_ci      if (c == '"') {
13321cb0ef41Sopenharmony_ci        Emit("\\\"");
13331cb0ef41Sopenharmony_ci      } else if (c == '\\') {
13341cb0ef41Sopenharmony_ci        Emit("\\\\");
13351cb0ef41Sopenharmony_ci      } else if (c == '\b') {
13361cb0ef41Sopenharmony_ci        Emit("\\b");
13371cb0ef41Sopenharmony_ci      } else if (c == '\f') {
13381cb0ef41Sopenharmony_ci        Emit("\\f");
13391cb0ef41Sopenharmony_ci      } else if (c == '\n') {
13401cb0ef41Sopenharmony_ci        Emit("\\n");
13411cb0ef41Sopenharmony_ci      } else if (c == '\r') {
13421cb0ef41Sopenharmony_ci        Emit("\\r");
13431cb0ef41Sopenharmony_ci      } else if (c == '\t') {
13441cb0ef41Sopenharmony_ci        Emit("\\t");
13451cb0ef41Sopenharmony_ci      } else if (c >= 32 && c <= 126) {
13461cb0ef41Sopenharmony_ci        Emit(c);
13471cb0ef41Sopenharmony_ci      } else if (c < 32) {
13481cb0ef41Sopenharmony_ci        Emit("\\u");
13491cb0ef41Sopenharmony_ci        PrintHex(static_cast<uint16_t>(c), out_);
13501cb0ef41Sopenharmony_ci      } else {
13511cb0ef41Sopenharmony_ci        // Inspect the leading byte to figure out how long the utf8
13521cb0ef41Sopenharmony_ci        // byte sequence is; while doing this initialize |codepoint|
13531cb0ef41Sopenharmony_ci        // with the first few bits.
13541cb0ef41Sopenharmony_ci        // See table in: https://en.wikipedia.org/wiki/UTF-8
13551cb0ef41Sopenharmony_ci        // byte one is 110x xxxx -> 2 byte utf8 sequence
13561cb0ef41Sopenharmony_ci        // byte one is 1110 xxxx -> 3 byte utf8 sequence
13571cb0ef41Sopenharmony_ci        // byte one is 1111 0xxx -> 4 byte utf8 sequence
13581cb0ef41Sopenharmony_ci        uint32_t codepoint;
13591cb0ef41Sopenharmony_ci        int num_bytes_left;
13601cb0ef41Sopenharmony_ci        if ((c & 0xe0) == 0xc0) {  // 2 byte utf8 sequence
13611cb0ef41Sopenharmony_ci          num_bytes_left = 1;
13621cb0ef41Sopenharmony_ci          codepoint = c & 0x1f;
13631cb0ef41Sopenharmony_ci        } else if ((c & 0xf0) == 0xe0) {  // 3 byte utf8 sequence
13641cb0ef41Sopenharmony_ci          num_bytes_left = 2;
13651cb0ef41Sopenharmony_ci          codepoint = c & 0x0f;
13661cb0ef41Sopenharmony_ci        } else if ((c & 0xf8) == 0xf0) {  // 4 byte utf8 sequence
13671cb0ef41Sopenharmony_ci          codepoint = c & 0x07;
13681cb0ef41Sopenharmony_ci          num_bytes_left = 3;
13691cb0ef41Sopenharmony_ci        } else {
13701cb0ef41Sopenharmony_ci          continue;  // invalid leading byte
13711cb0ef41Sopenharmony_ci        }
13721cb0ef41Sopenharmony_ci
13731cb0ef41Sopenharmony_ci        // If we have enough bytes in our input, decode the remaining ones
13741cb0ef41Sopenharmony_ci        // belonging to this Unicode character into |codepoint|.
13751cb0ef41Sopenharmony_ci        if (ii + num_bytes_left > chars.size())
13761cb0ef41Sopenharmony_ci          continue;
13771cb0ef41Sopenharmony_ci        while (num_bytes_left > 0) {
13781cb0ef41Sopenharmony_ci          c = chars[++ii];
13791cb0ef41Sopenharmony_ci          --num_bytes_left;
13801cb0ef41Sopenharmony_ci          // Check the next byte is a continuation byte, that is 10xx xxxx.
13811cb0ef41Sopenharmony_ci          if ((c & 0xc0) != 0x80)
13821cb0ef41Sopenharmony_ci            continue;
13831cb0ef41Sopenharmony_ci          codepoint = (codepoint << 6) | (c & 0x3f);
13841cb0ef41Sopenharmony_ci        }
13851cb0ef41Sopenharmony_ci
13861cb0ef41Sopenharmony_ci        // Disallow overlong encodings for ascii characters, as these
13871cb0ef41Sopenharmony_ci        // would include " and other characters significant to JSON
13881cb0ef41Sopenharmony_ci        // string termination / control.
13891cb0ef41Sopenharmony_ci        if (codepoint < 0x7f)
13901cb0ef41Sopenharmony_ci          continue;
13911cb0ef41Sopenharmony_ci        // Invalid in UTF8, and can't be represented in UTF16 anyway.
13921cb0ef41Sopenharmony_ci        if (codepoint > 0x10ffff)
13931cb0ef41Sopenharmony_ci          continue;
13941cb0ef41Sopenharmony_ci
13951cb0ef41Sopenharmony_ci        // So, now we transcode to UTF16,
13961cb0ef41Sopenharmony_ci        // using the math described at https://en.wikipedia.org/wiki/UTF-16,
13971cb0ef41Sopenharmony_ci        // for either one or two 16 bit characters.
13981cb0ef41Sopenharmony_ci        if (codepoint < 0xffff) {
13991cb0ef41Sopenharmony_ci          Emit("\\u");
14001cb0ef41Sopenharmony_ci          PrintHex(static_cast<uint16_t>(codepoint), out_);
14011cb0ef41Sopenharmony_ci          continue;
14021cb0ef41Sopenharmony_ci        }
14031cb0ef41Sopenharmony_ci        codepoint -= 0x10000;
14041cb0ef41Sopenharmony_ci        // high surrogate
14051cb0ef41Sopenharmony_ci        Emit("\\u");
14061cb0ef41Sopenharmony_ci        PrintHex(static_cast<uint16_t>((codepoint >> 10) + 0xd800), out_);
14071cb0ef41Sopenharmony_ci        // low surrogate
14081cb0ef41Sopenharmony_ci        Emit("\\u");
14091cb0ef41Sopenharmony_ci        PrintHex(static_cast<uint16_t>((codepoint & 0x3ff) + 0xdc00), out_);
14101cb0ef41Sopenharmony_ci      }
14111cb0ef41Sopenharmony_ci    }
14121cb0ef41Sopenharmony_ci    Emit('"');
14131cb0ef41Sopenharmony_ci  }
14141cb0ef41Sopenharmony_ci
14151cb0ef41Sopenharmony_ci  void HandleBinary(span<uint8_t> bytes) override {
14161cb0ef41Sopenharmony_ci    if (!status_->ok())
14171cb0ef41Sopenharmony_ci      return;
14181cb0ef41Sopenharmony_ci    state_.top().StartElement(out_);
14191cb0ef41Sopenharmony_ci    Emit('"');
14201cb0ef41Sopenharmony_ci    Base64Encode(bytes, out_);
14211cb0ef41Sopenharmony_ci    Emit('"');
14221cb0ef41Sopenharmony_ci  }
14231cb0ef41Sopenharmony_ci
14241cb0ef41Sopenharmony_ci  void HandleDouble(double value) override {
14251cb0ef41Sopenharmony_ci    if (!status_->ok())
14261cb0ef41Sopenharmony_ci      return;
14271cb0ef41Sopenharmony_ci    state_.top().StartElement(out_);
14281cb0ef41Sopenharmony_ci    // JSON cannot represent NaN or Infinity. So, for compatibility,
14291cb0ef41Sopenharmony_ci    // we behave like the JSON object in web browsers: emit 'null'.
14301cb0ef41Sopenharmony_ci    if (!std::isfinite(value)) {
14311cb0ef41Sopenharmony_ci      Emit("null");
14321cb0ef41Sopenharmony_ci      return;
14331cb0ef41Sopenharmony_ci    }
14341cb0ef41Sopenharmony_ci    std::unique_ptr<char[]> str_value = platform_->DToStr(value);
14351cb0ef41Sopenharmony_ci
14361cb0ef41Sopenharmony_ci    // DToStr may fail to emit a 0 before the decimal dot. E.g. this is
14371cb0ef41Sopenharmony_ci    // the case in base::NumberToString in Chromium (which is based on
14381cb0ef41Sopenharmony_ci    // dmg_fp). So, much like
14391cb0ef41Sopenharmony_ci    // https://cs.chromium.org/chromium/src/base/json/json_writer.cc
14401cb0ef41Sopenharmony_ci    // we probe for this and emit the leading 0 anyway if necessary.
14411cb0ef41Sopenharmony_ci    const char* chars = str_value.get();
14421cb0ef41Sopenharmony_ci    if (chars[0] == '.') {
14431cb0ef41Sopenharmony_ci      Emit('0');
14441cb0ef41Sopenharmony_ci    } else if (chars[0] == '-' && chars[1] == '.') {
14451cb0ef41Sopenharmony_ci      Emit("-0");
14461cb0ef41Sopenharmony_ci      ++chars;
14471cb0ef41Sopenharmony_ci    }
14481cb0ef41Sopenharmony_ci    Emit(chars);
14491cb0ef41Sopenharmony_ci  }
14501cb0ef41Sopenharmony_ci
14511cb0ef41Sopenharmony_ci  void HandleInt32(int32_t value) override {
14521cb0ef41Sopenharmony_ci    if (!status_->ok())
14531cb0ef41Sopenharmony_ci      return;
14541cb0ef41Sopenharmony_ci    state_.top().StartElement(out_);
14551cb0ef41Sopenharmony_ci    Emit(std::to_string(value));
14561cb0ef41Sopenharmony_ci  }
14571cb0ef41Sopenharmony_ci
14581cb0ef41Sopenharmony_ci  void HandleBool(bool value) override {
14591cb0ef41Sopenharmony_ci    if (!status_->ok())
14601cb0ef41Sopenharmony_ci      return;
14611cb0ef41Sopenharmony_ci    state_.top().StartElement(out_);
14621cb0ef41Sopenharmony_ci    Emit(value ? "true" : "false");
14631cb0ef41Sopenharmony_ci  }
14641cb0ef41Sopenharmony_ci
14651cb0ef41Sopenharmony_ci  void HandleNull() override {
14661cb0ef41Sopenharmony_ci    if (!status_->ok())
14671cb0ef41Sopenharmony_ci      return;
14681cb0ef41Sopenharmony_ci    state_.top().StartElement(out_);
14691cb0ef41Sopenharmony_ci    Emit("null");
14701cb0ef41Sopenharmony_ci  }
14711cb0ef41Sopenharmony_ci
14721cb0ef41Sopenharmony_ci  void HandleError(Status error) override {
14731cb0ef41Sopenharmony_ci    assert(!error.ok());
14741cb0ef41Sopenharmony_ci    *status_ = error;
14751cb0ef41Sopenharmony_ci    out_->clear();
14761cb0ef41Sopenharmony_ci  }
14771cb0ef41Sopenharmony_ci
14781cb0ef41Sopenharmony_ci private:
14791cb0ef41Sopenharmony_ci  void Emit(char c) { out_->push_back(c); }
14801cb0ef41Sopenharmony_ci  void Emit(const char* str) {
14811cb0ef41Sopenharmony_ci    out_->insert(out_->end(), str, str + strlen(str));
14821cb0ef41Sopenharmony_ci  }
14831cb0ef41Sopenharmony_ci  void Emit(const std::string& str) {
14841cb0ef41Sopenharmony_ci    out_->insert(out_->end(), str.begin(), str.end());
14851cb0ef41Sopenharmony_ci  }
14861cb0ef41Sopenharmony_ci
14871cb0ef41Sopenharmony_ci  const Platform* platform_;
14881cb0ef41Sopenharmony_ci  C* out_;
14891cb0ef41Sopenharmony_ci  Status* status_;
14901cb0ef41Sopenharmony_ci  std::stack<State> state_;
14911cb0ef41Sopenharmony_ci};
14921cb0ef41Sopenharmony_ci}  // namespace
14931cb0ef41Sopenharmony_ci
14941cb0ef41Sopenharmony_cistd::unique_ptr<StreamingParserHandler> NewJSONEncoder(
14951cb0ef41Sopenharmony_ci    const Platform* platform,
14961cb0ef41Sopenharmony_ci    std::vector<uint8_t>* out,
14971cb0ef41Sopenharmony_ci    Status* status) {
14981cb0ef41Sopenharmony_ci  return std::unique_ptr<StreamingParserHandler>(
14991cb0ef41Sopenharmony_ci      new JSONEncoder<std::vector<uint8_t>>(platform, out, status));
15001cb0ef41Sopenharmony_ci}
15011cb0ef41Sopenharmony_cistd::unique_ptr<StreamingParserHandler> NewJSONEncoder(const Platform* platform,
15021cb0ef41Sopenharmony_ci                                                       std::string* out,
15031cb0ef41Sopenharmony_ci                                                       Status* status) {
15041cb0ef41Sopenharmony_ci  return std::unique_ptr<StreamingParserHandler>(
15051cb0ef41Sopenharmony_ci      new JSONEncoder<std::string>(platform, out, status));
15061cb0ef41Sopenharmony_ci}
15071cb0ef41Sopenharmony_ci
15081cb0ef41Sopenharmony_ci// =============================================================================
15091cb0ef41Sopenharmony_ci// json::ParseJSON - for receiving streaming parser events for JSON.
15101cb0ef41Sopenharmony_ci// =============================================================================
15111cb0ef41Sopenharmony_ci
15121cb0ef41Sopenharmony_cinamespace {
15131cb0ef41Sopenharmony_ciconst int kStackLimit = 300;
15141cb0ef41Sopenharmony_ci
15151cb0ef41Sopenharmony_cienum Token {
15161cb0ef41Sopenharmony_ci  ObjectBegin,
15171cb0ef41Sopenharmony_ci  ObjectEnd,
15181cb0ef41Sopenharmony_ci  ArrayBegin,
15191cb0ef41Sopenharmony_ci  ArrayEnd,
15201cb0ef41Sopenharmony_ci  StringLiteral,
15211cb0ef41Sopenharmony_ci  Number,
15221cb0ef41Sopenharmony_ci  BoolTrue,
15231cb0ef41Sopenharmony_ci  BoolFalse,
15241cb0ef41Sopenharmony_ci  NullToken,
15251cb0ef41Sopenharmony_ci  ListSeparator,
15261cb0ef41Sopenharmony_ci  ObjectPairSeparator,
15271cb0ef41Sopenharmony_ci  InvalidToken,
15281cb0ef41Sopenharmony_ci  NoInput
15291cb0ef41Sopenharmony_ci};
15301cb0ef41Sopenharmony_ci
15311cb0ef41Sopenharmony_ciconst char* const kNullString = "null";
15321cb0ef41Sopenharmony_ciconst char* const kTrueString = "true";
15331cb0ef41Sopenharmony_ciconst char* const kFalseString = "false";
15341cb0ef41Sopenharmony_ci
15351cb0ef41Sopenharmony_citemplate <typename Char>
15361cb0ef41Sopenharmony_ciclass JsonParser {
15371cb0ef41Sopenharmony_ci public:
15381cb0ef41Sopenharmony_ci  JsonParser(const Platform* platform, StreamingParserHandler* handler)
15391cb0ef41Sopenharmony_ci      : platform_(platform), handler_(handler) {}
15401cb0ef41Sopenharmony_ci
15411cb0ef41Sopenharmony_ci  void Parse(const Char* start, size_t length) {
15421cb0ef41Sopenharmony_ci    start_pos_ = start;
15431cb0ef41Sopenharmony_ci    const Char* end = start + length;
15441cb0ef41Sopenharmony_ci    const Char* tokenEnd = nullptr;
15451cb0ef41Sopenharmony_ci    ParseValue(start, end, &tokenEnd, 0);
15461cb0ef41Sopenharmony_ci    if (error_)
15471cb0ef41Sopenharmony_ci      return;
15481cb0ef41Sopenharmony_ci    if (tokenEnd != end) {
15491cb0ef41Sopenharmony_ci      HandleError(Error::JSON_PARSER_UNPROCESSED_INPUT_REMAINS, tokenEnd);
15501cb0ef41Sopenharmony_ci    }
15511cb0ef41Sopenharmony_ci  }
15521cb0ef41Sopenharmony_ci
15531cb0ef41Sopenharmony_ci private:
15541cb0ef41Sopenharmony_ci  bool CharsToDouble(const uint16_t* chars, size_t length, double* result) {
15551cb0ef41Sopenharmony_ci    std::string buffer;
15561cb0ef41Sopenharmony_ci    buffer.reserve(length + 1);
15571cb0ef41Sopenharmony_ci    for (size_t ii = 0; ii < length; ++ii) {
15581cb0ef41Sopenharmony_ci      bool is_ascii = !(chars[ii] & ~0x7F);
15591cb0ef41Sopenharmony_ci      if (!is_ascii)
15601cb0ef41Sopenharmony_ci        return false;
15611cb0ef41Sopenharmony_ci      buffer.push_back(static_cast<char>(chars[ii]));
15621cb0ef41Sopenharmony_ci    }
15631cb0ef41Sopenharmony_ci    return platform_->StrToD(buffer.c_str(), result);
15641cb0ef41Sopenharmony_ci  }
15651cb0ef41Sopenharmony_ci
15661cb0ef41Sopenharmony_ci  bool CharsToDouble(const uint8_t* chars, size_t length, double* result) {
15671cb0ef41Sopenharmony_ci    std::string buffer(reinterpret_cast<const char*>(chars), length);
15681cb0ef41Sopenharmony_ci    return platform_->StrToD(buffer.c_str(), result);
15691cb0ef41Sopenharmony_ci  }
15701cb0ef41Sopenharmony_ci
15711cb0ef41Sopenharmony_ci  static bool ParseConstToken(const Char* start,
15721cb0ef41Sopenharmony_ci                              const Char* end,
15731cb0ef41Sopenharmony_ci                              const Char** token_end,
15741cb0ef41Sopenharmony_ci                              const char* token) {
15751cb0ef41Sopenharmony_ci    // |token| is \0 terminated, it's one of the constants at top of the file.
15761cb0ef41Sopenharmony_ci    while (start < end && *token != '\0' && *start++ == *token++) {
15771cb0ef41Sopenharmony_ci    }
15781cb0ef41Sopenharmony_ci    if (*token != '\0')
15791cb0ef41Sopenharmony_ci      return false;
15801cb0ef41Sopenharmony_ci    *token_end = start;
15811cb0ef41Sopenharmony_ci    return true;
15821cb0ef41Sopenharmony_ci  }
15831cb0ef41Sopenharmony_ci
15841cb0ef41Sopenharmony_ci  static bool ReadInt(const Char* start,
15851cb0ef41Sopenharmony_ci                      const Char* end,
15861cb0ef41Sopenharmony_ci                      const Char** token_end,
15871cb0ef41Sopenharmony_ci                      bool allow_leading_zeros) {
15881cb0ef41Sopenharmony_ci    if (start == end)
15891cb0ef41Sopenharmony_ci      return false;
15901cb0ef41Sopenharmony_ci    bool has_leading_zero = '0' == *start;
15911cb0ef41Sopenharmony_ci    int length = 0;
15921cb0ef41Sopenharmony_ci    while (start < end && '0' <= *start && *start <= '9') {
15931cb0ef41Sopenharmony_ci      ++start;
15941cb0ef41Sopenharmony_ci      ++length;
15951cb0ef41Sopenharmony_ci    }
15961cb0ef41Sopenharmony_ci    if (!length)
15971cb0ef41Sopenharmony_ci      return false;
15981cb0ef41Sopenharmony_ci    if (!allow_leading_zeros && length > 1 && has_leading_zero)
15991cb0ef41Sopenharmony_ci      return false;
16001cb0ef41Sopenharmony_ci    *token_end = start;
16011cb0ef41Sopenharmony_ci    return true;
16021cb0ef41Sopenharmony_ci  }
16031cb0ef41Sopenharmony_ci
16041cb0ef41Sopenharmony_ci  static bool ParseNumberToken(const Char* start,
16051cb0ef41Sopenharmony_ci                               const Char* end,
16061cb0ef41Sopenharmony_ci                               const Char** token_end) {
16071cb0ef41Sopenharmony_ci    // We just grab the number here. We validate the size in DecodeNumber.
16081cb0ef41Sopenharmony_ci    // According to RFC4627, a valid number is: [minus] int [frac] [exp]
16091cb0ef41Sopenharmony_ci    if (start == end)
16101cb0ef41Sopenharmony_ci      return false;
16111cb0ef41Sopenharmony_ci    Char c = *start;
16121cb0ef41Sopenharmony_ci    if ('-' == c)
16131cb0ef41Sopenharmony_ci      ++start;
16141cb0ef41Sopenharmony_ci
16151cb0ef41Sopenharmony_ci    if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/false))
16161cb0ef41Sopenharmony_ci      return false;
16171cb0ef41Sopenharmony_ci    if (start == end) {
16181cb0ef41Sopenharmony_ci      *token_end = start;
16191cb0ef41Sopenharmony_ci      return true;
16201cb0ef41Sopenharmony_ci    }
16211cb0ef41Sopenharmony_ci
16221cb0ef41Sopenharmony_ci    // Optional fraction part
16231cb0ef41Sopenharmony_ci    c = *start;
16241cb0ef41Sopenharmony_ci    if ('.' == c) {
16251cb0ef41Sopenharmony_ci      ++start;
16261cb0ef41Sopenharmony_ci      if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/true))
16271cb0ef41Sopenharmony_ci        return false;
16281cb0ef41Sopenharmony_ci      if (start == end) {
16291cb0ef41Sopenharmony_ci        *token_end = start;
16301cb0ef41Sopenharmony_ci        return true;
16311cb0ef41Sopenharmony_ci      }
16321cb0ef41Sopenharmony_ci      c = *start;
16331cb0ef41Sopenharmony_ci    }
16341cb0ef41Sopenharmony_ci
16351cb0ef41Sopenharmony_ci    // Optional exponent part
16361cb0ef41Sopenharmony_ci    if ('e' == c || 'E' == c) {
16371cb0ef41Sopenharmony_ci      ++start;
16381cb0ef41Sopenharmony_ci      if (start == end)
16391cb0ef41Sopenharmony_ci        return false;
16401cb0ef41Sopenharmony_ci      c = *start;
16411cb0ef41Sopenharmony_ci      if ('-' == c || '+' == c) {
16421cb0ef41Sopenharmony_ci        ++start;
16431cb0ef41Sopenharmony_ci        if (start == end)
16441cb0ef41Sopenharmony_ci          return false;
16451cb0ef41Sopenharmony_ci      }
16461cb0ef41Sopenharmony_ci      if (!ReadInt(start, end, &start, /*allow_leading_zeros=*/true))
16471cb0ef41Sopenharmony_ci        return false;
16481cb0ef41Sopenharmony_ci    }
16491cb0ef41Sopenharmony_ci
16501cb0ef41Sopenharmony_ci    *token_end = start;
16511cb0ef41Sopenharmony_ci    return true;
16521cb0ef41Sopenharmony_ci  }
16531cb0ef41Sopenharmony_ci
16541cb0ef41Sopenharmony_ci  static bool ReadHexDigits(const Char* start,
16551cb0ef41Sopenharmony_ci                            const Char* end,
16561cb0ef41Sopenharmony_ci                            const Char** token_end,
16571cb0ef41Sopenharmony_ci                            int digits) {
16581cb0ef41Sopenharmony_ci    if (end - start < digits)
16591cb0ef41Sopenharmony_ci      return false;
16601cb0ef41Sopenharmony_ci    for (int i = 0; i < digits; ++i) {
16611cb0ef41Sopenharmony_ci      Char c = *start++;
16621cb0ef41Sopenharmony_ci      if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') ||
16631cb0ef41Sopenharmony_ci            ('A' <= c && c <= 'F')))
16641cb0ef41Sopenharmony_ci        return false;
16651cb0ef41Sopenharmony_ci    }
16661cb0ef41Sopenharmony_ci    *token_end = start;
16671cb0ef41Sopenharmony_ci    return true;
16681cb0ef41Sopenharmony_ci  }
16691cb0ef41Sopenharmony_ci
16701cb0ef41Sopenharmony_ci  static bool ParseStringToken(const Char* start,
16711cb0ef41Sopenharmony_ci                               const Char* end,
16721cb0ef41Sopenharmony_ci                               const Char** token_end) {
16731cb0ef41Sopenharmony_ci    while (start < end) {
16741cb0ef41Sopenharmony_ci      Char c = *start++;
16751cb0ef41Sopenharmony_ci      if ('\\' == c) {
16761cb0ef41Sopenharmony_ci        if (start == end)
16771cb0ef41Sopenharmony_ci          return false;
16781cb0ef41Sopenharmony_ci        c = *start++;
16791cb0ef41Sopenharmony_ci        // Make sure the escaped char is valid.
16801cb0ef41Sopenharmony_ci        switch (c) {
16811cb0ef41Sopenharmony_ci          case 'x':
16821cb0ef41Sopenharmony_ci            if (!ReadHexDigits(start, end, &start, 2))
16831cb0ef41Sopenharmony_ci              return false;
16841cb0ef41Sopenharmony_ci            break;
16851cb0ef41Sopenharmony_ci          case 'u':
16861cb0ef41Sopenharmony_ci            if (!ReadHexDigits(start, end, &start, 4))
16871cb0ef41Sopenharmony_ci              return false;
16881cb0ef41Sopenharmony_ci            break;
16891cb0ef41Sopenharmony_ci          case '\\':
16901cb0ef41Sopenharmony_ci          case '/':
16911cb0ef41Sopenharmony_ci          case 'b':
16921cb0ef41Sopenharmony_ci          case 'f':
16931cb0ef41Sopenharmony_ci          case 'n':
16941cb0ef41Sopenharmony_ci          case 'r':
16951cb0ef41Sopenharmony_ci          case 't':
16961cb0ef41Sopenharmony_ci          case 'v':
16971cb0ef41Sopenharmony_ci          case '"':
16981cb0ef41Sopenharmony_ci            break;
16991cb0ef41Sopenharmony_ci          default:
17001cb0ef41Sopenharmony_ci            return false;
17011cb0ef41Sopenharmony_ci        }
17021cb0ef41Sopenharmony_ci      } else if ('"' == c) {
17031cb0ef41Sopenharmony_ci        *token_end = start;
17041cb0ef41Sopenharmony_ci        return true;
17051cb0ef41Sopenharmony_ci      }
17061cb0ef41Sopenharmony_ci    }
17071cb0ef41Sopenharmony_ci    return false;
17081cb0ef41Sopenharmony_ci  }
17091cb0ef41Sopenharmony_ci
17101cb0ef41Sopenharmony_ci  static bool SkipComment(const Char* start,
17111cb0ef41Sopenharmony_ci                          const Char* end,
17121cb0ef41Sopenharmony_ci                          const Char** comment_end) {
17131cb0ef41Sopenharmony_ci    if (start == end)
17141cb0ef41Sopenharmony_ci      return false;
17151cb0ef41Sopenharmony_ci
17161cb0ef41Sopenharmony_ci    if (*start != '/' || start + 1 >= end)
17171cb0ef41Sopenharmony_ci      return false;
17181cb0ef41Sopenharmony_ci    ++start;
17191cb0ef41Sopenharmony_ci
17201cb0ef41Sopenharmony_ci    if (*start == '/') {
17211cb0ef41Sopenharmony_ci      // Single line comment, read to newline.
17221cb0ef41Sopenharmony_ci      for (++start; start < end; ++start) {
17231cb0ef41Sopenharmony_ci        if (*start == '\n' || *start == '\r') {
17241cb0ef41Sopenharmony_ci          *comment_end = start + 1;
17251cb0ef41Sopenharmony_ci          return true;
17261cb0ef41Sopenharmony_ci        }
17271cb0ef41Sopenharmony_ci      }
17281cb0ef41Sopenharmony_ci      *comment_end = end;
17291cb0ef41Sopenharmony_ci      // Comment reaches end-of-input, which is fine.
17301cb0ef41Sopenharmony_ci      return true;
17311cb0ef41Sopenharmony_ci    }
17321cb0ef41Sopenharmony_ci
17331cb0ef41Sopenharmony_ci    if (*start == '*') {
17341cb0ef41Sopenharmony_ci      Char previous = '\0';
17351cb0ef41Sopenharmony_ci      // Block comment, read until end marker.
17361cb0ef41Sopenharmony_ci      for (++start; start < end; previous = *start++) {
17371cb0ef41Sopenharmony_ci        if (previous == '*' && *start == '/') {
17381cb0ef41Sopenharmony_ci          *comment_end = start + 1;
17391cb0ef41Sopenharmony_ci          return true;
17401cb0ef41Sopenharmony_ci        }
17411cb0ef41Sopenharmony_ci      }
17421cb0ef41Sopenharmony_ci      // Block comment must close before end-of-input.
17431cb0ef41Sopenharmony_ci      return false;
17441cb0ef41Sopenharmony_ci    }
17451cb0ef41Sopenharmony_ci
17461cb0ef41Sopenharmony_ci    return false;
17471cb0ef41Sopenharmony_ci  }
17481cb0ef41Sopenharmony_ci
17491cb0ef41Sopenharmony_ci  static bool IsSpaceOrNewLine(Char c) {
17501cb0ef41Sopenharmony_ci    // \v = vertial tab; \f = form feed page break.
17511cb0ef41Sopenharmony_ci    return c == ' ' || c == '\n' || c == '\v' || c == '\f' || c == '\r' ||
17521cb0ef41Sopenharmony_ci           c == '\t';
17531cb0ef41Sopenharmony_ci  }
17541cb0ef41Sopenharmony_ci
17551cb0ef41Sopenharmony_ci  static void SkipWhitespaceAndComments(const Char* start,
17561cb0ef41Sopenharmony_ci                                        const Char* end,
17571cb0ef41Sopenharmony_ci                                        const Char** whitespace_end) {
17581cb0ef41Sopenharmony_ci    while (start < end) {
17591cb0ef41Sopenharmony_ci      if (IsSpaceOrNewLine(*start)) {
17601cb0ef41Sopenharmony_ci        ++start;
17611cb0ef41Sopenharmony_ci      } else if (*start == '/') {
17621cb0ef41Sopenharmony_ci        const Char* comment_end = nullptr;
17631cb0ef41Sopenharmony_ci        if (!SkipComment(start, end, &comment_end))
17641cb0ef41Sopenharmony_ci          break;
17651cb0ef41Sopenharmony_ci        start = comment_end;
17661cb0ef41Sopenharmony_ci      } else {
17671cb0ef41Sopenharmony_ci        break;
17681cb0ef41Sopenharmony_ci      }
17691cb0ef41Sopenharmony_ci    }
17701cb0ef41Sopenharmony_ci    *whitespace_end = start;
17711cb0ef41Sopenharmony_ci  }
17721cb0ef41Sopenharmony_ci
17731cb0ef41Sopenharmony_ci  static Token ParseToken(const Char* start,
17741cb0ef41Sopenharmony_ci                          const Char* end,
17751cb0ef41Sopenharmony_ci                          const Char** tokenStart,
17761cb0ef41Sopenharmony_ci                          const Char** token_end) {
17771cb0ef41Sopenharmony_ci    SkipWhitespaceAndComments(start, end, tokenStart);
17781cb0ef41Sopenharmony_ci    start = *tokenStart;
17791cb0ef41Sopenharmony_ci
17801cb0ef41Sopenharmony_ci    if (start == end)
17811cb0ef41Sopenharmony_ci      return NoInput;
17821cb0ef41Sopenharmony_ci
17831cb0ef41Sopenharmony_ci    switch (*start) {
17841cb0ef41Sopenharmony_ci      case 'n':
17851cb0ef41Sopenharmony_ci        if (ParseConstToken(start, end, token_end, kNullString))
17861cb0ef41Sopenharmony_ci          return NullToken;
17871cb0ef41Sopenharmony_ci        break;
17881cb0ef41Sopenharmony_ci      case 't':
17891cb0ef41Sopenharmony_ci        if (ParseConstToken(start, end, token_end, kTrueString))
17901cb0ef41Sopenharmony_ci          return BoolTrue;
17911cb0ef41Sopenharmony_ci        break;
17921cb0ef41Sopenharmony_ci      case 'f':
17931cb0ef41Sopenharmony_ci        if (ParseConstToken(start, end, token_end, kFalseString))
17941cb0ef41Sopenharmony_ci          return BoolFalse;
17951cb0ef41Sopenharmony_ci        break;
17961cb0ef41Sopenharmony_ci      case '[':
17971cb0ef41Sopenharmony_ci        *token_end = start + 1;
17981cb0ef41Sopenharmony_ci        return ArrayBegin;
17991cb0ef41Sopenharmony_ci      case ']':
18001cb0ef41Sopenharmony_ci        *token_end = start + 1;
18011cb0ef41Sopenharmony_ci        return ArrayEnd;
18021cb0ef41Sopenharmony_ci      case ',':
18031cb0ef41Sopenharmony_ci        *token_end = start + 1;
18041cb0ef41Sopenharmony_ci        return ListSeparator;
18051cb0ef41Sopenharmony_ci      case '{':
18061cb0ef41Sopenharmony_ci        *token_end = start + 1;
18071cb0ef41Sopenharmony_ci        return ObjectBegin;
18081cb0ef41Sopenharmony_ci      case '}':
18091cb0ef41Sopenharmony_ci        *token_end = start + 1;
18101cb0ef41Sopenharmony_ci        return ObjectEnd;
18111cb0ef41Sopenharmony_ci      case ':':
18121cb0ef41Sopenharmony_ci        *token_end = start + 1;
18131cb0ef41Sopenharmony_ci        return ObjectPairSeparator;
18141cb0ef41Sopenharmony_ci      case '0':
18151cb0ef41Sopenharmony_ci      case '1':
18161cb0ef41Sopenharmony_ci      case '2':
18171cb0ef41Sopenharmony_ci      case '3':
18181cb0ef41Sopenharmony_ci      case '4':
18191cb0ef41Sopenharmony_ci      case '5':
18201cb0ef41Sopenharmony_ci      case '6':
18211cb0ef41Sopenharmony_ci      case '7':
18221cb0ef41Sopenharmony_ci      case '8':
18231cb0ef41Sopenharmony_ci      case '9':
18241cb0ef41Sopenharmony_ci      case '-':
18251cb0ef41Sopenharmony_ci        if (ParseNumberToken(start, end, token_end))
18261cb0ef41Sopenharmony_ci          return Number;
18271cb0ef41Sopenharmony_ci        break;
18281cb0ef41Sopenharmony_ci      case '"':
18291cb0ef41Sopenharmony_ci        if (ParseStringToken(start + 1, end, token_end))
18301cb0ef41Sopenharmony_ci          return StringLiteral;
18311cb0ef41Sopenharmony_ci        break;
18321cb0ef41Sopenharmony_ci    }
18331cb0ef41Sopenharmony_ci    return InvalidToken;
18341cb0ef41Sopenharmony_ci  }
18351cb0ef41Sopenharmony_ci
18361cb0ef41Sopenharmony_ci  static int HexToInt(Char c) {
18371cb0ef41Sopenharmony_ci    if ('0' <= c && c <= '9')
18381cb0ef41Sopenharmony_ci      return c - '0';
18391cb0ef41Sopenharmony_ci    if ('A' <= c && c <= 'F')
18401cb0ef41Sopenharmony_ci      return c - 'A' + 10;
18411cb0ef41Sopenharmony_ci    if ('a' <= c && c <= 'f')
18421cb0ef41Sopenharmony_ci      return c - 'a' + 10;
18431cb0ef41Sopenharmony_ci    assert(false);  // Unreachable.
18441cb0ef41Sopenharmony_ci    return 0;
18451cb0ef41Sopenharmony_ci  }
18461cb0ef41Sopenharmony_ci
18471cb0ef41Sopenharmony_ci  static bool DecodeString(const Char* start,
18481cb0ef41Sopenharmony_ci                           const Char* end,
18491cb0ef41Sopenharmony_ci                           std::vector<uint16_t>* output) {
18501cb0ef41Sopenharmony_ci    if (start == end)
18511cb0ef41Sopenharmony_ci      return true;
18521cb0ef41Sopenharmony_ci    if (start > end)
18531cb0ef41Sopenharmony_ci      return false;
18541cb0ef41Sopenharmony_ci    output->reserve(end - start);
18551cb0ef41Sopenharmony_ci    while (start < end) {
18561cb0ef41Sopenharmony_ci      uint16_t c = *start++;
18571cb0ef41Sopenharmony_ci      // If the |Char| we're dealing with is really a byte, then
18581cb0ef41Sopenharmony_ci      // we have utf8 here, and we need to check for multibyte characters
18591cb0ef41Sopenharmony_ci      // and transcode them to utf16 (either one or two utf16 chars).
18601cb0ef41Sopenharmony_ci      if (sizeof(Char) == sizeof(uint8_t) && c > 0x7f) {
18611cb0ef41Sopenharmony_ci        // Inspect the leading byte to figure out how long the utf8
18621cb0ef41Sopenharmony_ci        // byte sequence is; while doing this initialize |codepoint|
18631cb0ef41Sopenharmony_ci        // with the first few bits.
18641cb0ef41Sopenharmony_ci        // See table in: https://en.wikipedia.org/wiki/UTF-8
18651cb0ef41Sopenharmony_ci        // byte one is 110x xxxx -> 2 byte utf8 sequence
18661cb0ef41Sopenharmony_ci        // byte one is 1110 xxxx -> 3 byte utf8 sequence
18671cb0ef41Sopenharmony_ci        // byte one is 1111 0xxx -> 4 byte utf8 sequence
18681cb0ef41Sopenharmony_ci        uint32_t codepoint;
18691cb0ef41Sopenharmony_ci        int num_bytes_left;
18701cb0ef41Sopenharmony_ci        if ((c & 0xe0) == 0xc0) {  // 2 byte utf8 sequence
18711cb0ef41Sopenharmony_ci          num_bytes_left = 1;
18721cb0ef41Sopenharmony_ci          codepoint = c & 0x1f;
18731cb0ef41Sopenharmony_ci        } else if ((c & 0xf0) == 0xe0) {  // 3 byte utf8 sequence
18741cb0ef41Sopenharmony_ci          num_bytes_left = 2;
18751cb0ef41Sopenharmony_ci          codepoint = c & 0x0f;
18761cb0ef41Sopenharmony_ci        } else if ((c & 0xf8) == 0xf0) {  // 4 byte utf8 sequence
18771cb0ef41Sopenharmony_ci          codepoint = c & 0x07;
18781cb0ef41Sopenharmony_ci          num_bytes_left = 3;
18791cb0ef41Sopenharmony_ci        } else {
18801cb0ef41Sopenharmony_ci          return false;  // invalid leading byte
18811cb0ef41Sopenharmony_ci        }
18821cb0ef41Sopenharmony_ci
18831cb0ef41Sopenharmony_ci        // If we have enough bytes in our inpput, decode the remaining ones
18841cb0ef41Sopenharmony_ci        // belonging to this Unicode character into |codepoint|.
18851cb0ef41Sopenharmony_ci        if (start + num_bytes_left > end)
18861cb0ef41Sopenharmony_ci          return false;
18871cb0ef41Sopenharmony_ci        while (num_bytes_left > 0) {
18881cb0ef41Sopenharmony_ci          c = *start++;
18891cb0ef41Sopenharmony_ci          --num_bytes_left;
18901cb0ef41Sopenharmony_ci          // Check the next byte is a continuation byte, that is 10xx xxxx.
18911cb0ef41Sopenharmony_ci          if ((c & 0xc0) != 0x80)
18921cb0ef41Sopenharmony_ci            return false;
18931cb0ef41Sopenharmony_ci          codepoint = (codepoint << 6) | (c & 0x3f);
18941cb0ef41Sopenharmony_ci        }
18951cb0ef41Sopenharmony_ci
18961cb0ef41Sopenharmony_ci        // Disallow overlong encodings for ascii characters, as these
18971cb0ef41Sopenharmony_ci        // would include " and other characters significant to JSON
18981cb0ef41Sopenharmony_ci        // string termination / control.
18991cb0ef41Sopenharmony_ci        if (codepoint <= 0x7f)
19001cb0ef41Sopenharmony_ci          return false;
19011cb0ef41Sopenharmony_ci        // Invalid in UTF8, and can't be represented in UTF16 anyway.
19021cb0ef41Sopenharmony_ci        if (codepoint > 0x10ffff)
19031cb0ef41Sopenharmony_ci          return false;
19041cb0ef41Sopenharmony_ci
19051cb0ef41Sopenharmony_ci        // So, now we transcode to UTF16,
19061cb0ef41Sopenharmony_ci        // using the math described at https://en.wikipedia.org/wiki/UTF-16,
19071cb0ef41Sopenharmony_ci        // for either one or two 16 bit characters.
19081cb0ef41Sopenharmony_ci        if (codepoint < 0xffff) {
19091cb0ef41Sopenharmony_ci          output->push_back(codepoint);
19101cb0ef41Sopenharmony_ci          continue;
19111cb0ef41Sopenharmony_ci        }
19121cb0ef41Sopenharmony_ci        codepoint -= 0x10000;
19131cb0ef41Sopenharmony_ci        output->push_back((codepoint >> 10) + 0xd800);    // high surrogate
19141cb0ef41Sopenharmony_ci        output->push_back((codepoint & 0x3ff) + 0xdc00);  // low surrogate
19151cb0ef41Sopenharmony_ci        continue;
19161cb0ef41Sopenharmony_ci      }
19171cb0ef41Sopenharmony_ci      if ('\\' != c) {
19181cb0ef41Sopenharmony_ci        output->push_back(c);
19191cb0ef41Sopenharmony_ci        continue;
19201cb0ef41Sopenharmony_ci      }
19211cb0ef41Sopenharmony_ci      if (start == end)
19221cb0ef41Sopenharmony_ci        return false;
19231cb0ef41Sopenharmony_ci      c = *start++;
19241cb0ef41Sopenharmony_ci
19251cb0ef41Sopenharmony_ci      if (c == 'x') {
19261cb0ef41Sopenharmony_ci        // \x is not supported.
19271cb0ef41Sopenharmony_ci        return false;
19281cb0ef41Sopenharmony_ci      }
19291cb0ef41Sopenharmony_ci
19301cb0ef41Sopenharmony_ci      switch (c) {
19311cb0ef41Sopenharmony_ci        case '"':
19321cb0ef41Sopenharmony_ci        case '/':
19331cb0ef41Sopenharmony_ci        case '\\':
19341cb0ef41Sopenharmony_ci          break;
19351cb0ef41Sopenharmony_ci        case 'b':
19361cb0ef41Sopenharmony_ci          c = '\b';
19371cb0ef41Sopenharmony_ci          break;
19381cb0ef41Sopenharmony_ci        case 'f':
19391cb0ef41Sopenharmony_ci          c = '\f';
19401cb0ef41Sopenharmony_ci          break;
19411cb0ef41Sopenharmony_ci        case 'n':
19421cb0ef41Sopenharmony_ci          c = '\n';
19431cb0ef41Sopenharmony_ci          break;
19441cb0ef41Sopenharmony_ci        case 'r':
19451cb0ef41Sopenharmony_ci          c = '\r';
19461cb0ef41Sopenharmony_ci          break;
19471cb0ef41Sopenharmony_ci        case 't':
19481cb0ef41Sopenharmony_ci          c = '\t';
19491cb0ef41Sopenharmony_ci          break;
19501cb0ef41Sopenharmony_ci        case 'v':
19511cb0ef41Sopenharmony_ci          c = '\v';
19521cb0ef41Sopenharmony_ci          break;
19531cb0ef41Sopenharmony_ci        case 'u':
19541cb0ef41Sopenharmony_ci          c = (HexToInt(*start) << 12) + (HexToInt(*(start + 1)) << 8) +
19551cb0ef41Sopenharmony_ci              (HexToInt(*(start + 2)) << 4) + HexToInt(*(start + 3));
19561cb0ef41Sopenharmony_ci          start += 4;
19571cb0ef41Sopenharmony_ci          break;
19581cb0ef41Sopenharmony_ci        default:
19591cb0ef41Sopenharmony_ci          return false;
19601cb0ef41Sopenharmony_ci      }
19611cb0ef41Sopenharmony_ci      output->push_back(c);
19621cb0ef41Sopenharmony_ci    }
19631cb0ef41Sopenharmony_ci    return true;
19641cb0ef41Sopenharmony_ci  }
19651cb0ef41Sopenharmony_ci
19661cb0ef41Sopenharmony_ci  void ParseValue(const Char* start,
19671cb0ef41Sopenharmony_ci                  const Char* end,
19681cb0ef41Sopenharmony_ci                  const Char** value_token_end,
19691cb0ef41Sopenharmony_ci                  int depth) {
19701cb0ef41Sopenharmony_ci    if (depth > kStackLimit) {
19711cb0ef41Sopenharmony_ci      HandleError(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, start);
19721cb0ef41Sopenharmony_ci      return;
19731cb0ef41Sopenharmony_ci    }
19741cb0ef41Sopenharmony_ci    const Char* token_start = nullptr;
19751cb0ef41Sopenharmony_ci    const Char* token_end = nullptr;
19761cb0ef41Sopenharmony_ci    Token token = ParseToken(start, end, &token_start, &token_end);
19771cb0ef41Sopenharmony_ci    switch (token) {
19781cb0ef41Sopenharmony_ci      case NoInput:
19791cb0ef41Sopenharmony_ci        HandleError(Error::JSON_PARSER_NO_INPUT, token_start);
19801cb0ef41Sopenharmony_ci        return;
19811cb0ef41Sopenharmony_ci      case InvalidToken:
19821cb0ef41Sopenharmony_ci        HandleError(Error::JSON_PARSER_INVALID_TOKEN, token_start);
19831cb0ef41Sopenharmony_ci        return;
19841cb0ef41Sopenharmony_ci      case NullToken:
19851cb0ef41Sopenharmony_ci        handler_->HandleNull();
19861cb0ef41Sopenharmony_ci        break;
19871cb0ef41Sopenharmony_ci      case BoolTrue:
19881cb0ef41Sopenharmony_ci        handler_->HandleBool(true);
19891cb0ef41Sopenharmony_ci        break;
19901cb0ef41Sopenharmony_ci      case BoolFalse:
19911cb0ef41Sopenharmony_ci        handler_->HandleBool(false);
19921cb0ef41Sopenharmony_ci        break;
19931cb0ef41Sopenharmony_ci      case Number: {
19941cb0ef41Sopenharmony_ci        double value;
19951cb0ef41Sopenharmony_ci        if (!CharsToDouble(token_start, token_end - token_start, &value)) {
19961cb0ef41Sopenharmony_ci          HandleError(Error::JSON_PARSER_INVALID_NUMBER, token_start);
19971cb0ef41Sopenharmony_ci          return;
19981cb0ef41Sopenharmony_ci        }
19991cb0ef41Sopenharmony_ci        if (value >= std::numeric_limits<int32_t>::min() &&
20001cb0ef41Sopenharmony_ci            value <= std::numeric_limits<int32_t>::max() &&
20011cb0ef41Sopenharmony_ci            static_cast<int32_t>(value) == value)
20021cb0ef41Sopenharmony_ci          handler_->HandleInt32(static_cast<int32_t>(value));
20031cb0ef41Sopenharmony_ci        else
20041cb0ef41Sopenharmony_ci          handler_->HandleDouble(value);
20051cb0ef41Sopenharmony_ci        break;
20061cb0ef41Sopenharmony_ci      }
20071cb0ef41Sopenharmony_ci      case StringLiteral: {
20081cb0ef41Sopenharmony_ci        std::vector<uint16_t> value;
20091cb0ef41Sopenharmony_ci        bool ok = DecodeString(token_start + 1, token_end - 1, &value);
20101cb0ef41Sopenharmony_ci        if (!ok) {
20111cb0ef41Sopenharmony_ci          HandleError(Error::JSON_PARSER_INVALID_STRING, token_start);
20121cb0ef41Sopenharmony_ci          return;
20131cb0ef41Sopenharmony_ci        }
20141cb0ef41Sopenharmony_ci        handler_->HandleString16(span<uint16_t>(value.data(), value.size()));
20151cb0ef41Sopenharmony_ci        break;
20161cb0ef41Sopenharmony_ci      }
20171cb0ef41Sopenharmony_ci      case ArrayBegin: {
20181cb0ef41Sopenharmony_ci        handler_->HandleArrayBegin();
20191cb0ef41Sopenharmony_ci        start = token_end;
20201cb0ef41Sopenharmony_ci        token = ParseToken(start, end, &token_start, &token_end);
20211cb0ef41Sopenharmony_ci        while (token != ArrayEnd) {
20221cb0ef41Sopenharmony_ci          ParseValue(start, end, &token_end, depth + 1);
20231cb0ef41Sopenharmony_ci          if (error_)
20241cb0ef41Sopenharmony_ci            return;
20251cb0ef41Sopenharmony_ci
20261cb0ef41Sopenharmony_ci          // After a list value, we expect a comma or the end of the list.
20271cb0ef41Sopenharmony_ci          start = token_end;
20281cb0ef41Sopenharmony_ci          token = ParseToken(start, end, &token_start, &token_end);
20291cb0ef41Sopenharmony_ci          if (token == ListSeparator) {
20301cb0ef41Sopenharmony_ci            start = token_end;
20311cb0ef41Sopenharmony_ci            token = ParseToken(start, end, &token_start, &token_end);
20321cb0ef41Sopenharmony_ci            if (token == ArrayEnd) {
20331cb0ef41Sopenharmony_ci              HandleError(Error::JSON_PARSER_UNEXPECTED_ARRAY_END, token_start);
20341cb0ef41Sopenharmony_ci              return;
20351cb0ef41Sopenharmony_ci            }
20361cb0ef41Sopenharmony_ci          } else if (token != ArrayEnd) {
20371cb0ef41Sopenharmony_ci            // Unexpected value after list value. Bail out.
20381cb0ef41Sopenharmony_ci            HandleError(Error::JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED,
20391cb0ef41Sopenharmony_ci                        token_start);
20401cb0ef41Sopenharmony_ci            return;
20411cb0ef41Sopenharmony_ci          }
20421cb0ef41Sopenharmony_ci        }
20431cb0ef41Sopenharmony_ci        handler_->HandleArrayEnd();
20441cb0ef41Sopenharmony_ci        break;
20451cb0ef41Sopenharmony_ci      }
20461cb0ef41Sopenharmony_ci      case ObjectBegin: {
20471cb0ef41Sopenharmony_ci        handler_->HandleMapBegin();
20481cb0ef41Sopenharmony_ci        start = token_end;
20491cb0ef41Sopenharmony_ci        token = ParseToken(start, end, &token_start, &token_end);
20501cb0ef41Sopenharmony_ci        while (token != ObjectEnd) {
20511cb0ef41Sopenharmony_ci          if (token != StringLiteral) {
20521cb0ef41Sopenharmony_ci            HandleError(Error::JSON_PARSER_STRING_LITERAL_EXPECTED,
20531cb0ef41Sopenharmony_ci                        token_start);
20541cb0ef41Sopenharmony_ci            return;
20551cb0ef41Sopenharmony_ci          }
20561cb0ef41Sopenharmony_ci          std::vector<uint16_t> key;
20571cb0ef41Sopenharmony_ci          if (!DecodeString(token_start + 1, token_end - 1, &key)) {
20581cb0ef41Sopenharmony_ci            HandleError(Error::JSON_PARSER_INVALID_STRING, token_start);
20591cb0ef41Sopenharmony_ci            return;
20601cb0ef41Sopenharmony_ci          }
20611cb0ef41Sopenharmony_ci          handler_->HandleString16(span<uint16_t>(key.data(), key.size()));
20621cb0ef41Sopenharmony_ci          start = token_end;
20631cb0ef41Sopenharmony_ci
20641cb0ef41Sopenharmony_ci          token = ParseToken(start, end, &token_start, &token_end);
20651cb0ef41Sopenharmony_ci          if (token != ObjectPairSeparator) {
20661cb0ef41Sopenharmony_ci            HandleError(Error::JSON_PARSER_COLON_EXPECTED, token_start);
20671cb0ef41Sopenharmony_ci            return;
20681cb0ef41Sopenharmony_ci          }
20691cb0ef41Sopenharmony_ci          start = token_end;
20701cb0ef41Sopenharmony_ci
20711cb0ef41Sopenharmony_ci          ParseValue(start, end, &token_end, depth + 1);
20721cb0ef41Sopenharmony_ci          if (error_)
20731cb0ef41Sopenharmony_ci            return;
20741cb0ef41Sopenharmony_ci          start = token_end;
20751cb0ef41Sopenharmony_ci
20761cb0ef41Sopenharmony_ci          // After a key/value pair, we expect a comma or the end of the
20771cb0ef41Sopenharmony_ci          // object.
20781cb0ef41Sopenharmony_ci          token = ParseToken(start, end, &token_start, &token_end);
20791cb0ef41Sopenharmony_ci          if (token == ListSeparator) {
20801cb0ef41Sopenharmony_ci            start = token_end;
20811cb0ef41Sopenharmony_ci            token = ParseToken(start, end, &token_start, &token_end);
20821cb0ef41Sopenharmony_ci            if (token == ObjectEnd) {
20831cb0ef41Sopenharmony_ci              HandleError(Error::JSON_PARSER_UNEXPECTED_MAP_END, token_start);
20841cb0ef41Sopenharmony_ci              return;
20851cb0ef41Sopenharmony_ci            }
20861cb0ef41Sopenharmony_ci          } else if (token != ObjectEnd) {
20871cb0ef41Sopenharmony_ci            // Unexpected value after last object value. Bail out.
20881cb0ef41Sopenharmony_ci            HandleError(Error::JSON_PARSER_COMMA_OR_MAP_END_EXPECTED,
20891cb0ef41Sopenharmony_ci                        token_start);
20901cb0ef41Sopenharmony_ci            return;
20911cb0ef41Sopenharmony_ci          }
20921cb0ef41Sopenharmony_ci        }
20931cb0ef41Sopenharmony_ci        handler_->HandleMapEnd();
20941cb0ef41Sopenharmony_ci        break;
20951cb0ef41Sopenharmony_ci      }
20961cb0ef41Sopenharmony_ci
20971cb0ef41Sopenharmony_ci      default:
20981cb0ef41Sopenharmony_ci        // We got a token that's not a value.
20991cb0ef41Sopenharmony_ci        HandleError(Error::JSON_PARSER_VALUE_EXPECTED, token_start);
21001cb0ef41Sopenharmony_ci        return;
21011cb0ef41Sopenharmony_ci    }
21021cb0ef41Sopenharmony_ci
21031cb0ef41Sopenharmony_ci    SkipWhitespaceAndComments(token_end, end, value_token_end);
21041cb0ef41Sopenharmony_ci  }
21051cb0ef41Sopenharmony_ci
21061cb0ef41Sopenharmony_ci  void HandleError(Error error, const Char* pos) {
21071cb0ef41Sopenharmony_ci    assert(error != Error::OK);
21081cb0ef41Sopenharmony_ci    if (!error_) {
21091cb0ef41Sopenharmony_ci      handler_->HandleError(
21101cb0ef41Sopenharmony_ci          Status{error, static_cast<size_t>(pos - start_pos_)});
21111cb0ef41Sopenharmony_ci      error_ = true;
21121cb0ef41Sopenharmony_ci    }
21131cb0ef41Sopenharmony_ci  }
21141cb0ef41Sopenharmony_ci
21151cb0ef41Sopenharmony_ci  const Char* start_pos_ = nullptr;
21161cb0ef41Sopenharmony_ci  bool error_ = false;
21171cb0ef41Sopenharmony_ci  const Platform* platform_;
21181cb0ef41Sopenharmony_ci  StreamingParserHandler* handler_;
21191cb0ef41Sopenharmony_ci};
21201cb0ef41Sopenharmony_ci}  // namespace
21211cb0ef41Sopenharmony_ci
21221cb0ef41Sopenharmony_civoid ParseJSON(const Platform& platform,
21231cb0ef41Sopenharmony_ci               span<uint8_t> chars,
21241cb0ef41Sopenharmony_ci               StreamingParserHandler* handler) {
21251cb0ef41Sopenharmony_ci  JsonParser<uint8_t> parser(&platform, handler);
21261cb0ef41Sopenharmony_ci  parser.Parse(chars.data(), chars.size());
21271cb0ef41Sopenharmony_ci}
21281cb0ef41Sopenharmony_ci
21291cb0ef41Sopenharmony_civoid ParseJSON(const Platform& platform,
21301cb0ef41Sopenharmony_ci               span<uint16_t> chars,
21311cb0ef41Sopenharmony_ci               StreamingParserHandler* handler) {
21321cb0ef41Sopenharmony_ci  JsonParser<uint16_t> parser(&platform, handler);
21331cb0ef41Sopenharmony_ci  parser.Parse(chars.data(), chars.size());
21341cb0ef41Sopenharmony_ci}
21351cb0ef41Sopenharmony_ci
21361cb0ef41Sopenharmony_ci// =============================================================================
21371cb0ef41Sopenharmony_ci// json::ConvertCBORToJSON, json::ConvertJSONToCBOR - for transcoding
21381cb0ef41Sopenharmony_ci// =============================================================================
21391cb0ef41Sopenharmony_citemplate <typename C>
21401cb0ef41Sopenharmony_ciStatus ConvertCBORToJSONTmpl(const Platform& platform,
21411cb0ef41Sopenharmony_ci                             span<uint8_t> cbor,
21421cb0ef41Sopenharmony_ci                             C* json) {
21431cb0ef41Sopenharmony_ci  Status status;
21441cb0ef41Sopenharmony_ci  std::unique_ptr<StreamingParserHandler> json_writer =
21451cb0ef41Sopenharmony_ci      NewJSONEncoder(&platform, json, &status);
21461cb0ef41Sopenharmony_ci  cbor::ParseCBOR(cbor, json_writer.get());
21471cb0ef41Sopenharmony_ci  return status;
21481cb0ef41Sopenharmony_ci}
21491cb0ef41Sopenharmony_ci
21501cb0ef41Sopenharmony_ciStatus ConvertCBORToJSON(const Platform& platform,
21511cb0ef41Sopenharmony_ci                         span<uint8_t> cbor,
21521cb0ef41Sopenharmony_ci                         std::vector<uint8_t>* json) {
21531cb0ef41Sopenharmony_ci  return ConvertCBORToJSONTmpl(platform, cbor, json);
21541cb0ef41Sopenharmony_ci}
21551cb0ef41Sopenharmony_ciStatus ConvertCBORToJSON(const Platform& platform,
21561cb0ef41Sopenharmony_ci                         span<uint8_t> cbor,
21571cb0ef41Sopenharmony_ci                         std::string* json) {
21581cb0ef41Sopenharmony_ci  return ConvertCBORToJSONTmpl(platform, cbor, json);
21591cb0ef41Sopenharmony_ci}
21601cb0ef41Sopenharmony_ci
21611cb0ef41Sopenharmony_citemplate <typename T, typename C>
21621cb0ef41Sopenharmony_ciStatus ConvertJSONToCBORTmpl(const Platform& platform, span<T> json, C* cbor) {
21631cb0ef41Sopenharmony_ci  Status status;
21641cb0ef41Sopenharmony_ci  std::unique_ptr<StreamingParserHandler> encoder =
21651cb0ef41Sopenharmony_ci      cbor::NewCBOREncoder(cbor, &status);
21661cb0ef41Sopenharmony_ci  ParseJSON(platform, json, encoder.get());
21671cb0ef41Sopenharmony_ci  return status;
21681cb0ef41Sopenharmony_ci}
21691cb0ef41Sopenharmony_ciStatus ConvertJSONToCBOR(const Platform& platform,
21701cb0ef41Sopenharmony_ci                         span<uint8_t> json,
21711cb0ef41Sopenharmony_ci                         std::string* cbor) {
21721cb0ef41Sopenharmony_ci  return ConvertJSONToCBORTmpl(platform, json, cbor);
21731cb0ef41Sopenharmony_ci}
21741cb0ef41Sopenharmony_ciStatus ConvertJSONToCBOR(const Platform& platform,
21751cb0ef41Sopenharmony_ci                         span<uint16_t> json,
21761cb0ef41Sopenharmony_ci                         std::string* cbor) {
21771cb0ef41Sopenharmony_ci  return ConvertJSONToCBORTmpl(platform, json, cbor);
21781cb0ef41Sopenharmony_ci}
21791cb0ef41Sopenharmony_ciStatus ConvertJSONToCBOR(const Platform& platform,
21801cb0ef41Sopenharmony_ci                         span<uint8_t> json,
21811cb0ef41Sopenharmony_ci                         std::vector<uint8_t>* cbor) {
21821cb0ef41Sopenharmony_ci  return ConvertJSONToCBORTmpl(platform, json, cbor);
21831cb0ef41Sopenharmony_ci}
21841cb0ef41Sopenharmony_ciStatus ConvertJSONToCBOR(const Platform& platform,
21851cb0ef41Sopenharmony_ci                         span<uint16_t> json,
21861cb0ef41Sopenharmony_ci                         std::vector<uint8_t>* cbor) {
21871cb0ef41Sopenharmony_ci  return ConvertJSONToCBORTmpl(platform, json, cbor);
21881cb0ef41Sopenharmony_ci}
21891cb0ef41Sopenharmony_ci}  // namespace json
21901cb0ef41Sopenharmony_ci}  // namespace v8_inspector_protocol_encoding
2191