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