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