16d528ed9Sopenharmony_ci// Copyright (c) 2012 The Chromium Authors. All rights reserved.
26d528ed9Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
36d528ed9Sopenharmony_ci// found in the LICENSE file.
46d528ed9Sopenharmony_ci
56d528ed9Sopenharmony_ci#include "base/json/json_parser.h"
66d528ed9Sopenharmony_ci
76d528ed9Sopenharmony_ci#include <cmath>
86d528ed9Sopenharmony_ci#include <string_view>
96d528ed9Sopenharmony_ci#include <utility>
106d528ed9Sopenharmony_ci#include <vector>
116d528ed9Sopenharmony_ci
126d528ed9Sopenharmony_ci#include "base/logging.h"
136d528ed9Sopenharmony_ci#include "base/numerics/safe_conversions.h"
146d528ed9Sopenharmony_ci#include "base/strings/string_number_conversions.h"
156d528ed9Sopenharmony_ci#include "base/strings/string_util.h"
166d528ed9Sopenharmony_ci#include "base/strings/stringprintf.h"
176d528ed9Sopenharmony_ci#include "base/strings/utf_string_conversion_utils.h"
186d528ed9Sopenharmony_ci#include "base/strings/utf_string_conversions.h"
196d528ed9Sopenharmony_ci#include "base/third_party/icu/icu_utf.h"
206d528ed9Sopenharmony_ci#include "base/values.h"
216d528ed9Sopenharmony_ci
226d528ed9Sopenharmony_cinamespace base {
236d528ed9Sopenharmony_cinamespace internal {
246d528ed9Sopenharmony_ci
256d528ed9Sopenharmony_cinamespace {
266d528ed9Sopenharmony_ci
276d528ed9Sopenharmony_ciconst int32_t kExtendedASCIIStart = 0x80;
286d528ed9Sopenharmony_ci
296d528ed9Sopenharmony_ci// Simple class that checks for maximum recursion/"stack overflow."
306d528ed9Sopenharmony_ciclass StackMarker {
316d528ed9Sopenharmony_ci public:
326d528ed9Sopenharmony_ci  StackMarker(int max_depth, int* depth)
336d528ed9Sopenharmony_ci      : max_depth_(max_depth), depth_(depth) {
346d528ed9Sopenharmony_ci    ++(*depth_);
356d528ed9Sopenharmony_ci    DCHECK_LE(*depth_, max_depth_);
366d528ed9Sopenharmony_ci  }
376d528ed9Sopenharmony_ci  ~StackMarker() { --(*depth_); }
386d528ed9Sopenharmony_ci
396d528ed9Sopenharmony_ci  bool IsTooDeep() const { return *depth_ >= max_depth_; }
406d528ed9Sopenharmony_ci
416d528ed9Sopenharmony_ci private:
426d528ed9Sopenharmony_ci  const int max_depth_;
436d528ed9Sopenharmony_ci  int* const depth_;
446d528ed9Sopenharmony_ci
456d528ed9Sopenharmony_ci  StackMarker(const StackMarker&) = delete;
466d528ed9Sopenharmony_ci  StackMarker& operator=(const StackMarker&) = delete;
476d528ed9Sopenharmony_ci};
486d528ed9Sopenharmony_ci
496d528ed9Sopenharmony_ciconstexpr uint32_t kUnicodeReplacementPoint = 0xFFFD;
506d528ed9Sopenharmony_ci
516d528ed9Sopenharmony_ci}  // namespace
526d528ed9Sopenharmony_ci
536d528ed9Sopenharmony_ci// This is U+FFFD.
546d528ed9Sopenharmony_ciconst char kUnicodeReplacementString[] = "\xEF\xBF\xBD";
556d528ed9Sopenharmony_ci
566d528ed9Sopenharmony_ciJSONParser::JSONParser(int options, int max_depth)
576d528ed9Sopenharmony_ci    : options_(options),
586d528ed9Sopenharmony_ci      max_depth_(max_depth),
596d528ed9Sopenharmony_ci      index_(0),
606d528ed9Sopenharmony_ci      stack_depth_(0),
616d528ed9Sopenharmony_ci      line_number_(0),
626d528ed9Sopenharmony_ci      index_last_line_(0),
636d528ed9Sopenharmony_ci      error_code_(JSONReader::JSON_NO_ERROR),
646d528ed9Sopenharmony_ci      error_line_(0),
656d528ed9Sopenharmony_ci      error_column_(0) {
666d528ed9Sopenharmony_ci  CHECK_LE(max_depth, JSONReader::kStackMaxDepth);
676d528ed9Sopenharmony_ci}
686d528ed9Sopenharmony_ci
696d528ed9Sopenharmony_ciJSONParser::~JSONParser() = default;
706d528ed9Sopenharmony_ci
716d528ed9Sopenharmony_cistd::optional<Value> JSONParser::Parse(std::string_view input) {
726d528ed9Sopenharmony_ci  input_ = input;
736d528ed9Sopenharmony_ci  index_ = 0;
746d528ed9Sopenharmony_ci  line_number_ = 1;
756d528ed9Sopenharmony_ci  index_last_line_ = 0;
766d528ed9Sopenharmony_ci
776d528ed9Sopenharmony_ci  error_code_ = JSONReader::JSON_NO_ERROR;
786d528ed9Sopenharmony_ci  error_line_ = 0;
796d528ed9Sopenharmony_ci  error_column_ = 0;
806d528ed9Sopenharmony_ci
816d528ed9Sopenharmony_ci  // ICU and ReadUnicodeCharacter() use int32_t for lengths, so ensure
826d528ed9Sopenharmony_ci  // that the index_ will not overflow when parsing.
836d528ed9Sopenharmony_ci  if (!base::IsValueInRangeForNumericType<int32_t>(input.length())) {
846d528ed9Sopenharmony_ci    ReportError(JSONReader::JSON_TOO_LARGE, 0);
856d528ed9Sopenharmony_ci    return std::nullopt;
866d528ed9Sopenharmony_ci  }
876d528ed9Sopenharmony_ci
886d528ed9Sopenharmony_ci  // When the input JSON string starts with a UTF-8 Byte-Order-Mark,
896d528ed9Sopenharmony_ci  // advance the start position to avoid the ParseNextToken function mis-
906d528ed9Sopenharmony_ci  // treating a Unicode BOM as an invalid character and returning NULL.
916d528ed9Sopenharmony_ci  ConsumeIfMatch("\xEF\xBB\xBF");
926d528ed9Sopenharmony_ci
936d528ed9Sopenharmony_ci  // Parse the first and any nested tokens.
946d528ed9Sopenharmony_ci  std::optional<Value> root(ParseNextToken());
956d528ed9Sopenharmony_ci  if (!root)
966d528ed9Sopenharmony_ci    return std::nullopt;
976d528ed9Sopenharmony_ci
986d528ed9Sopenharmony_ci  // Make sure the input stream is at an end.
996d528ed9Sopenharmony_ci  if (GetNextToken() != T_END_OF_INPUT) {
1006d528ed9Sopenharmony_ci    ReportError(JSONReader::JSON_UNEXPECTED_DATA_AFTER_ROOT, 1);
1016d528ed9Sopenharmony_ci    return std::nullopt;
1026d528ed9Sopenharmony_ci  }
1036d528ed9Sopenharmony_ci
1046d528ed9Sopenharmony_ci  return root;
1056d528ed9Sopenharmony_ci}
1066d528ed9Sopenharmony_ci
1076d528ed9Sopenharmony_ciJSONReader::JsonParseError JSONParser::error_code() const {
1086d528ed9Sopenharmony_ci  return error_code_;
1096d528ed9Sopenharmony_ci}
1106d528ed9Sopenharmony_ci
1116d528ed9Sopenharmony_cistd::string JSONParser::GetErrorMessage() const {
1126d528ed9Sopenharmony_ci  return FormatErrorMessage(error_line_, error_column_,
1136d528ed9Sopenharmony_ci                            JSONReader::ErrorCodeToString(error_code_));
1146d528ed9Sopenharmony_ci}
1156d528ed9Sopenharmony_ci
1166d528ed9Sopenharmony_ciint JSONParser::error_line() const {
1176d528ed9Sopenharmony_ci  return error_line_;
1186d528ed9Sopenharmony_ci}
1196d528ed9Sopenharmony_ci
1206d528ed9Sopenharmony_ciint JSONParser::error_column() const {
1216d528ed9Sopenharmony_ci  return error_column_;
1226d528ed9Sopenharmony_ci}
1236d528ed9Sopenharmony_ci
1246d528ed9Sopenharmony_ci// StringBuilder ///////////////////////////////////////////////////////////////
1256d528ed9Sopenharmony_ci
1266d528ed9Sopenharmony_ciJSONParser::StringBuilder::StringBuilder() : StringBuilder(nullptr) {}
1276d528ed9Sopenharmony_ci
1286d528ed9Sopenharmony_ciJSONParser::StringBuilder::StringBuilder(const char* pos)
1296d528ed9Sopenharmony_ci    : pos_(pos), length_(0) {}
1306d528ed9Sopenharmony_ci
1316d528ed9Sopenharmony_ciJSONParser::StringBuilder::~StringBuilder() = default;
1326d528ed9Sopenharmony_ci
1336d528ed9Sopenharmony_ciJSONParser::StringBuilder& JSONParser::StringBuilder::operator=(
1346d528ed9Sopenharmony_ci    StringBuilder&& other) = default;
1356d528ed9Sopenharmony_ci
1366d528ed9Sopenharmony_civoid JSONParser::StringBuilder::Append(uint32_t point) {
1376d528ed9Sopenharmony_ci  DCHECK(IsValidCharacter(point));
1386d528ed9Sopenharmony_ci
1396d528ed9Sopenharmony_ci  if (point < kExtendedASCIIStart && !string_) {
1406d528ed9Sopenharmony_ci    DCHECK_EQ(static_cast<char>(point), pos_[length_]);
1416d528ed9Sopenharmony_ci    ++length_;
1426d528ed9Sopenharmony_ci  } else {
1436d528ed9Sopenharmony_ci    Convert();
1446d528ed9Sopenharmony_ci    if (UNLIKELY(point == kUnicodeReplacementPoint)) {
1456d528ed9Sopenharmony_ci      string_->append(kUnicodeReplacementString);
1466d528ed9Sopenharmony_ci    } else {
1476d528ed9Sopenharmony_ci      WriteUnicodeCharacter(point, &*string_);
1486d528ed9Sopenharmony_ci    }
1496d528ed9Sopenharmony_ci  }
1506d528ed9Sopenharmony_ci}
1516d528ed9Sopenharmony_ci
1526d528ed9Sopenharmony_civoid JSONParser::StringBuilder::Convert() {
1536d528ed9Sopenharmony_ci  if (string_)
1546d528ed9Sopenharmony_ci    return;
1556d528ed9Sopenharmony_ci  string_.emplace(pos_, length_);
1566d528ed9Sopenharmony_ci}
1576d528ed9Sopenharmony_ci
1586d528ed9Sopenharmony_cistd::string JSONParser::StringBuilder::DestructiveAsString() {
1596d528ed9Sopenharmony_ci  if (string_)
1606d528ed9Sopenharmony_ci    return std::move(*string_);
1616d528ed9Sopenharmony_ci  return std::string(pos_, length_);
1626d528ed9Sopenharmony_ci}
1636d528ed9Sopenharmony_ci
1646d528ed9Sopenharmony_ci// JSONParser private //////////////////////////////////////////////////////////
1656d528ed9Sopenharmony_ci
1666d528ed9Sopenharmony_cistd::optional<std::string_view> JSONParser::PeekChars(int count) {
1676d528ed9Sopenharmony_ci  if (static_cast<size_t>(index_) + count > input_.length())
1686d528ed9Sopenharmony_ci    return std::nullopt;
1696d528ed9Sopenharmony_ci  // Using std::string_view::substr() is significantly slower (according to
1706d528ed9Sopenharmony_ci  // base_perftests) than constructing a substring manually.
1716d528ed9Sopenharmony_ci  return std::string_view(input_.data() + index_, count);
1726d528ed9Sopenharmony_ci}
1736d528ed9Sopenharmony_ci
1746d528ed9Sopenharmony_cistd::optional<char> JSONParser::PeekChar() {
1756d528ed9Sopenharmony_ci  std::optional<std::string_view> chars = PeekChars(1);
1766d528ed9Sopenharmony_ci  if (chars)
1776d528ed9Sopenharmony_ci    return (*chars)[0];
1786d528ed9Sopenharmony_ci  return std::nullopt;
1796d528ed9Sopenharmony_ci}
1806d528ed9Sopenharmony_ci
1816d528ed9Sopenharmony_cistd::optional<std::string_view> JSONParser::ConsumeChars(int count) {
1826d528ed9Sopenharmony_ci  std::optional<std::string_view> chars = PeekChars(count);
1836d528ed9Sopenharmony_ci  if (chars)
1846d528ed9Sopenharmony_ci    index_ += count;
1856d528ed9Sopenharmony_ci  return chars;
1866d528ed9Sopenharmony_ci}
1876d528ed9Sopenharmony_ci
1886d528ed9Sopenharmony_cistd::optional<char> JSONParser::ConsumeChar() {
1896d528ed9Sopenharmony_ci  std::optional<std::string_view> chars = ConsumeChars(1);
1906d528ed9Sopenharmony_ci  if (chars)
1916d528ed9Sopenharmony_ci    return (*chars)[0];
1926d528ed9Sopenharmony_ci  return std::nullopt;
1936d528ed9Sopenharmony_ci}
1946d528ed9Sopenharmony_ci
1956d528ed9Sopenharmony_ciconst char* JSONParser::pos() {
1966d528ed9Sopenharmony_ci  CHECK_LE(static_cast<size_t>(index_), input_.length());
1976d528ed9Sopenharmony_ci  return input_.data() + index_;
1986d528ed9Sopenharmony_ci}
1996d528ed9Sopenharmony_ci
2006d528ed9Sopenharmony_ciJSONParser::Token JSONParser::GetNextToken() {
2016d528ed9Sopenharmony_ci  EatWhitespaceAndComments();
2026d528ed9Sopenharmony_ci
2036d528ed9Sopenharmony_ci  std::optional<char> c = PeekChar();
2046d528ed9Sopenharmony_ci  if (!c)
2056d528ed9Sopenharmony_ci    return T_END_OF_INPUT;
2066d528ed9Sopenharmony_ci
2076d528ed9Sopenharmony_ci  switch (*c) {
2086d528ed9Sopenharmony_ci    case '{':
2096d528ed9Sopenharmony_ci      return T_OBJECT_BEGIN;
2106d528ed9Sopenharmony_ci    case '}':
2116d528ed9Sopenharmony_ci      return T_OBJECT_END;
2126d528ed9Sopenharmony_ci    case '[':
2136d528ed9Sopenharmony_ci      return T_ARRAY_BEGIN;
2146d528ed9Sopenharmony_ci    case ']':
2156d528ed9Sopenharmony_ci      return T_ARRAY_END;
2166d528ed9Sopenharmony_ci    case '"':
2176d528ed9Sopenharmony_ci      return T_STRING;
2186d528ed9Sopenharmony_ci    case '0':
2196d528ed9Sopenharmony_ci    case '1':
2206d528ed9Sopenharmony_ci    case '2':
2216d528ed9Sopenharmony_ci    case '3':
2226d528ed9Sopenharmony_ci    case '4':
2236d528ed9Sopenharmony_ci    case '5':
2246d528ed9Sopenharmony_ci    case '6':
2256d528ed9Sopenharmony_ci    case '7':
2266d528ed9Sopenharmony_ci    case '8':
2276d528ed9Sopenharmony_ci    case '9':
2286d528ed9Sopenharmony_ci    case '-':
2296d528ed9Sopenharmony_ci      return T_NUMBER;
2306d528ed9Sopenharmony_ci    case 't':
2316d528ed9Sopenharmony_ci      return T_BOOL_TRUE;
2326d528ed9Sopenharmony_ci    case 'f':
2336d528ed9Sopenharmony_ci      return T_BOOL_FALSE;
2346d528ed9Sopenharmony_ci    case 'n':
2356d528ed9Sopenharmony_ci      return T_NULL;
2366d528ed9Sopenharmony_ci    case ',':
2376d528ed9Sopenharmony_ci      return T_LIST_SEPARATOR;
2386d528ed9Sopenharmony_ci    case ':':
2396d528ed9Sopenharmony_ci      return T_OBJECT_PAIR_SEPARATOR;
2406d528ed9Sopenharmony_ci    default:
2416d528ed9Sopenharmony_ci      return T_INVALID_TOKEN;
2426d528ed9Sopenharmony_ci  }
2436d528ed9Sopenharmony_ci}
2446d528ed9Sopenharmony_ci
2456d528ed9Sopenharmony_civoid JSONParser::EatWhitespaceAndComments() {
2466d528ed9Sopenharmony_ci  while (std::optional<char> c = PeekChar()) {
2476d528ed9Sopenharmony_ci    switch (*c) {
2486d528ed9Sopenharmony_ci      case '\r':
2496d528ed9Sopenharmony_ci      case '\n':
2506d528ed9Sopenharmony_ci        index_last_line_ = index_;
2516d528ed9Sopenharmony_ci        // Don't increment line_number_ twice for "\r\n".
2526d528ed9Sopenharmony_ci        if (!(c == '\n' && index_ > 0 && input_[index_ - 1] == '\r')) {
2536d528ed9Sopenharmony_ci          ++line_number_;
2546d528ed9Sopenharmony_ci        }
2556d528ed9Sopenharmony_ci        FALLTHROUGH;
2566d528ed9Sopenharmony_ci      case ' ':
2576d528ed9Sopenharmony_ci      case '\t':
2586d528ed9Sopenharmony_ci        ConsumeChar();
2596d528ed9Sopenharmony_ci        break;
2606d528ed9Sopenharmony_ci      case '/':
2616d528ed9Sopenharmony_ci        if (!EatComment())
2626d528ed9Sopenharmony_ci          return;
2636d528ed9Sopenharmony_ci        break;
2646d528ed9Sopenharmony_ci      default:
2656d528ed9Sopenharmony_ci        return;
2666d528ed9Sopenharmony_ci    }
2676d528ed9Sopenharmony_ci  }
2686d528ed9Sopenharmony_ci}
2696d528ed9Sopenharmony_ci
2706d528ed9Sopenharmony_cibool JSONParser::EatComment() {
2716d528ed9Sopenharmony_ci  std::optional<std::string_view> comment_start = ConsumeChars(2);
2726d528ed9Sopenharmony_ci  if (!comment_start)
2736d528ed9Sopenharmony_ci    return false;
2746d528ed9Sopenharmony_ci
2756d528ed9Sopenharmony_ci  if (comment_start == "//") {
2766d528ed9Sopenharmony_ci    // Single line comment, read to newline.
2776d528ed9Sopenharmony_ci    while (std::optional<char> c = PeekChar()) {
2786d528ed9Sopenharmony_ci      if (c == '\n' || c == '\r')
2796d528ed9Sopenharmony_ci        return true;
2806d528ed9Sopenharmony_ci      ConsumeChar();
2816d528ed9Sopenharmony_ci    }
2826d528ed9Sopenharmony_ci  } else if (comment_start == "/*") {
2836d528ed9Sopenharmony_ci    char previous_char = '\0';
2846d528ed9Sopenharmony_ci    // Block comment, read until end marker.
2856d528ed9Sopenharmony_ci    while (std::optional<char> c = PeekChar()) {
2866d528ed9Sopenharmony_ci      if (previous_char == '*' && c == '/') {
2876d528ed9Sopenharmony_ci        // EatWhitespaceAndComments will inspect pos(), which will still be on
2886d528ed9Sopenharmony_ci        // the last / of the comment, so advance once more (which may also be
2896d528ed9Sopenharmony_ci        // end of input).
2906d528ed9Sopenharmony_ci        ConsumeChar();
2916d528ed9Sopenharmony_ci        return true;
2926d528ed9Sopenharmony_ci      }
2936d528ed9Sopenharmony_ci      previous_char = *ConsumeChar();
2946d528ed9Sopenharmony_ci    }
2956d528ed9Sopenharmony_ci
2966d528ed9Sopenharmony_ci    // If the comment is unterminated, GetNextToken will report T_END_OF_INPUT.
2976d528ed9Sopenharmony_ci  }
2986d528ed9Sopenharmony_ci
2996d528ed9Sopenharmony_ci  return false;
3006d528ed9Sopenharmony_ci}
3016d528ed9Sopenharmony_ci
3026d528ed9Sopenharmony_cistd::optional<Value> JSONParser::ParseNextToken() {
3036d528ed9Sopenharmony_ci  return ParseToken(GetNextToken());
3046d528ed9Sopenharmony_ci}
3056d528ed9Sopenharmony_ci
3066d528ed9Sopenharmony_cistd::optional<Value> JSONParser::ParseToken(Token token) {
3076d528ed9Sopenharmony_ci  switch (token) {
3086d528ed9Sopenharmony_ci    case T_OBJECT_BEGIN:
3096d528ed9Sopenharmony_ci      return ConsumeDictionary();
3106d528ed9Sopenharmony_ci    case T_ARRAY_BEGIN:
3116d528ed9Sopenharmony_ci      return ConsumeList();
3126d528ed9Sopenharmony_ci    case T_STRING:
3136d528ed9Sopenharmony_ci      return ConsumeString();
3146d528ed9Sopenharmony_ci    case T_NUMBER:
3156d528ed9Sopenharmony_ci      return ConsumeNumber();
3166d528ed9Sopenharmony_ci    case T_BOOL_TRUE:
3176d528ed9Sopenharmony_ci    case T_BOOL_FALSE:
3186d528ed9Sopenharmony_ci    case T_NULL:
3196d528ed9Sopenharmony_ci      return ConsumeLiteral();
3206d528ed9Sopenharmony_ci    default:
3216d528ed9Sopenharmony_ci      ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1);
3226d528ed9Sopenharmony_ci      return std::nullopt;
3236d528ed9Sopenharmony_ci  }
3246d528ed9Sopenharmony_ci}
3256d528ed9Sopenharmony_ci
3266d528ed9Sopenharmony_cistd::optional<Value> JSONParser::ConsumeDictionary() {
3276d528ed9Sopenharmony_ci  if (ConsumeChar() != '{') {
3286d528ed9Sopenharmony_ci    ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1);
3296d528ed9Sopenharmony_ci    return std::nullopt;
3306d528ed9Sopenharmony_ci  }
3316d528ed9Sopenharmony_ci
3326d528ed9Sopenharmony_ci  StackMarker depth_check(max_depth_, &stack_depth_);
3336d528ed9Sopenharmony_ci  if (depth_check.IsTooDeep()) {
3346d528ed9Sopenharmony_ci    ReportError(JSONReader::JSON_TOO_MUCH_NESTING, 0);
3356d528ed9Sopenharmony_ci    return std::nullopt;
3366d528ed9Sopenharmony_ci  }
3376d528ed9Sopenharmony_ci
3386d528ed9Sopenharmony_ci  std::vector<Value::DictStorage::value_type> dict_storage;
3396d528ed9Sopenharmony_ci
3406d528ed9Sopenharmony_ci  Token token = GetNextToken();
3416d528ed9Sopenharmony_ci  while (token != T_OBJECT_END) {
3426d528ed9Sopenharmony_ci    if (token != T_STRING) {
3436d528ed9Sopenharmony_ci      ReportError(JSONReader::JSON_UNQUOTED_DICTIONARY_KEY, 1);
3446d528ed9Sopenharmony_ci      return std::nullopt;
3456d528ed9Sopenharmony_ci    }
3466d528ed9Sopenharmony_ci
3476d528ed9Sopenharmony_ci    // First consume the key.
3486d528ed9Sopenharmony_ci    StringBuilder key;
3496d528ed9Sopenharmony_ci    if (!ConsumeStringRaw(&key)) {
3506d528ed9Sopenharmony_ci      return std::nullopt;
3516d528ed9Sopenharmony_ci    }
3526d528ed9Sopenharmony_ci
3536d528ed9Sopenharmony_ci    // Read the separator.
3546d528ed9Sopenharmony_ci    token = GetNextToken();
3556d528ed9Sopenharmony_ci    if (token != T_OBJECT_PAIR_SEPARATOR) {
3566d528ed9Sopenharmony_ci      ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
3576d528ed9Sopenharmony_ci      return std::nullopt;
3586d528ed9Sopenharmony_ci    }
3596d528ed9Sopenharmony_ci
3606d528ed9Sopenharmony_ci    // The next token is the value. Ownership transfers to |dict|.
3616d528ed9Sopenharmony_ci    ConsumeChar();
3626d528ed9Sopenharmony_ci    std::optional<Value> value = ParseNextToken();
3636d528ed9Sopenharmony_ci    if (!value) {
3646d528ed9Sopenharmony_ci      // ReportError from deeper level.
3656d528ed9Sopenharmony_ci      return std::nullopt;
3666d528ed9Sopenharmony_ci    }
3676d528ed9Sopenharmony_ci
3686d528ed9Sopenharmony_ci    dict_storage.emplace_back(key.DestructiveAsString(),
3696d528ed9Sopenharmony_ci                              std::make_unique<Value>(std::move(*value)));
3706d528ed9Sopenharmony_ci
3716d528ed9Sopenharmony_ci    token = GetNextToken();
3726d528ed9Sopenharmony_ci    if (token == T_LIST_SEPARATOR) {
3736d528ed9Sopenharmony_ci      ConsumeChar();
3746d528ed9Sopenharmony_ci      token = GetNextToken();
3756d528ed9Sopenharmony_ci      if (token == T_OBJECT_END && !(options_ & JSON_ALLOW_TRAILING_COMMAS)) {
3766d528ed9Sopenharmony_ci        ReportError(JSONReader::JSON_TRAILING_COMMA, 1);
3776d528ed9Sopenharmony_ci        return std::nullopt;
3786d528ed9Sopenharmony_ci      }
3796d528ed9Sopenharmony_ci    } else if (token != T_OBJECT_END) {
3806d528ed9Sopenharmony_ci      ReportError(JSONReader::JSON_SYNTAX_ERROR, 0);
3816d528ed9Sopenharmony_ci      return std::nullopt;
3826d528ed9Sopenharmony_ci    }
3836d528ed9Sopenharmony_ci  }
3846d528ed9Sopenharmony_ci
3856d528ed9Sopenharmony_ci  ConsumeChar();  // Closing '}'.
3866d528ed9Sopenharmony_ci
3876d528ed9Sopenharmony_ci  return Value(Value::DictStorage(std::move(dict_storage), KEEP_LAST_OF_DUPES));
3886d528ed9Sopenharmony_ci}
3896d528ed9Sopenharmony_ci
3906d528ed9Sopenharmony_cistd::optional<Value> JSONParser::ConsumeList() {
3916d528ed9Sopenharmony_ci  if (ConsumeChar() != '[') {
3926d528ed9Sopenharmony_ci    ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1);
3936d528ed9Sopenharmony_ci    return std::nullopt;
3946d528ed9Sopenharmony_ci  }
3956d528ed9Sopenharmony_ci
3966d528ed9Sopenharmony_ci  StackMarker depth_check(max_depth_, &stack_depth_);
3976d528ed9Sopenharmony_ci  if (depth_check.IsTooDeep()) {
3986d528ed9Sopenharmony_ci    ReportError(JSONReader::JSON_TOO_MUCH_NESTING, 0);
3996d528ed9Sopenharmony_ci    return std::nullopt;
4006d528ed9Sopenharmony_ci  }
4016d528ed9Sopenharmony_ci
4026d528ed9Sopenharmony_ci  Value::ListStorage list_storage;
4036d528ed9Sopenharmony_ci
4046d528ed9Sopenharmony_ci  Token token = GetNextToken();
4056d528ed9Sopenharmony_ci  while (token != T_ARRAY_END) {
4066d528ed9Sopenharmony_ci    std::optional<Value> item = ParseToken(token);
4076d528ed9Sopenharmony_ci    if (!item) {
4086d528ed9Sopenharmony_ci      // ReportError from deeper level.
4096d528ed9Sopenharmony_ci      return std::nullopt;
4106d528ed9Sopenharmony_ci    }
4116d528ed9Sopenharmony_ci
4126d528ed9Sopenharmony_ci    list_storage.push_back(std::move(*item));
4136d528ed9Sopenharmony_ci
4146d528ed9Sopenharmony_ci    token = GetNextToken();
4156d528ed9Sopenharmony_ci    if (token == T_LIST_SEPARATOR) {
4166d528ed9Sopenharmony_ci      ConsumeChar();
4176d528ed9Sopenharmony_ci      token = GetNextToken();
4186d528ed9Sopenharmony_ci      if (token == T_ARRAY_END && !(options_ & JSON_ALLOW_TRAILING_COMMAS)) {
4196d528ed9Sopenharmony_ci        ReportError(JSONReader::JSON_TRAILING_COMMA, 1);
4206d528ed9Sopenharmony_ci        return std::nullopt;
4216d528ed9Sopenharmony_ci      }
4226d528ed9Sopenharmony_ci    } else if (token != T_ARRAY_END) {
4236d528ed9Sopenharmony_ci      ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
4246d528ed9Sopenharmony_ci      return std::nullopt;
4256d528ed9Sopenharmony_ci    }
4266d528ed9Sopenharmony_ci  }
4276d528ed9Sopenharmony_ci
4286d528ed9Sopenharmony_ci  ConsumeChar();  // Closing ']'.
4296d528ed9Sopenharmony_ci
4306d528ed9Sopenharmony_ci  return Value(std::move(list_storage));
4316d528ed9Sopenharmony_ci}
4326d528ed9Sopenharmony_ci
4336d528ed9Sopenharmony_cistd::optional<Value> JSONParser::ConsumeString() {
4346d528ed9Sopenharmony_ci  StringBuilder string;
4356d528ed9Sopenharmony_ci  if (!ConsumeStringRaw(&string))
4366d528ed9Sopenharmony_ci    return std::nullopt;
4376d528ed9Sopenharmony_ci
4386d528ed9Sopenharmony_ci  return Value(string.DestructiveAsString());
4396d528ed9Sopenharmony_ci}
4406d528ed9Sopenharmony_ci
4416d528ed9Sopenharmony_cibool JSONParser::ConsumeStringRaw(StringBuilder* out) {
4426d528ed9Sopenharmony_ci  if (ConsumeChar() != '"') {
4436d528ed9Sopenharmony_ci    ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1);
4446d528ed9Sopenharmony_ci    return false;
4456d528ed9Sopenharmony_ci  }
4466d528ed9Sopenharmony_ci
4476d528ed9Sopenharmony_ci  // StringBuilder will internally build a std::string_view unless a UTF-16
4486d528ed9Sopenharmony_ci  // conversion occurs, at which point it will perform a copy into a
4496d528ed9Sopenharmony_ci  // std::string.
4506d528ed9Sopenharmony_ci  StringBuilder string(pos());
4516d528ed9Sopenharmony_ci
4526d528ed9Sopenharmony_ci  while (PeekChar()) {
4536d528ed9Sopenharmony_ci    uint32_t next_char = 0;
4546d528ed9Sopenharmony_ci    if (!ReadUnicodeCharacter(input_.data(),
4556d528ed9Sopenharmony_ci                              static_cast<int32_t>(input_.length()), &index_,
4566d528ed9Sopenharmony_ci                              &next_char) ||
4576d528ed9Sopenharmony_ci        !IsValidCharacter(next_char)) {
4586d528ed9Sopenharmony_ci      if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0) {
4596d528ed9Sopenharmony_ci        ReportError(JSONReader::JSON_UNSUPPORTED_ENCODING, 1);
4606d528ed9Sopenharmony_ci        return false;
4616d528ed9Sopenharmony_ci      }
4626d528ed9Sopenharmony_ci      ConsumeChar();
4636d528ed9Sopenharmony_ci      string.Append(kUnicodeReplacementPoint);
4646d528ed9Sopenharmony_ci      continue;
4656d528ed9Sopenharmony_ci    }
4666d528ed9Sopenharmony_ci
4676d528ed9Sopenharmony_ci    if (next_char == '"') {
4686d528ed9Sopenharmony_ci      ConsumeChar();
4696d528ed9Sopenharmony_ci      *out = std::move(string);
4706d528ed9Sopenharmony_ci      return true;
4716d528ed9Sopenharmony_ci    } else if (next_char != '\\') {
4726d528ed9Sopenharmony_ci      // If this character is not an escape sequence...
4736d528ed9Sopenharmony_ci      ConsumeChar();
4746d528ed9Sopenharmony_ci      string.Append(next_char);
4756d528ed9Sopenharmony_ci    } else {
4766d528ed9Sopenharmony_ci      // And if it is an escape sequence, the input string will be adjusted
4776d528ed9Sopenharmony_ci      // (either by combining the two characters of an encoded escape sequence,
4786d528ed9Sopenharmony_ci      // or with a UTF conversion), so using std::string_view isn't possible --
4796d528ed9Sopenharmony_ci      // force a conversion.
4806d528ed9Sopenharmony_ci      string.Convert();
4816d528ed9Sopenharmony_ci
4826d528ed9Sopenharmony_ci      // Read past the escape '\' and ensure there's a character following.
4836d528ed9Sopenharmony_ci      std::optional<std::string_view> escape_sequence = ConsumeChars(2);
4846d528ed9Sopenharmony_ci      if (!escape_sequence) {
4856d528ed9Sopenharmony_ci        ReportError(JSONReader::JSON_INVALID_ESCAPE, 0);
4866d528ed9Sopenharmony_ci        return false;
4876d528ed9Sopenharmony_ci      }
4886d528ed9Sopenharmony_ci
4896d528ed9Sopenharmony_ci      switch ((*escape_sequence)[1]) {
4906d528ed9Sopenharmony_ci        // Allowed esape sequences:
4916d528ed9Sopenharmony_ci        case 'x': {  // UTF-8 sequence.
4926d528ed9Sopenharmony_ci          // UTF-8 \x escape sequences are not allowed in the spec, but they
4936d528ed9Sopenharmony_ci          // are supported here for backwards-compatiblity with the old parser.
4946d528ed9Sopenharmony_ci          escape_sequence = ConsumeChars(2);
4956d528ed9Sopenharmony_ci          if (!escape_sequence) {
4966d528ed9Sopenharmony_ci            ReportError(JSONReader::JSON_INVALID_ESCAPE, -2);
4976d528ed9Sopenharmony_ci            return false;
4986d528ed9Sopenharmony_ci          }
4996d528ed9Sopenharmony_ci
5006d528ed9Sopenharmony_ci          int hex_digit = 0;
5016d528ed9Sopenharmony_ci          if (!HexStringToInt(*escape_sequence, &hex_digit) ||
5026d528ed9Sopenharmony_ci              !IsValidCharacter(hex_digit)) {
5036d528ed9Sopenharmony_ci            ReportError(JSONReader::JSON_INVALID_ESCAPE, -2);
5046d528ed9Sopenharmony_ci            return false;
5056d528ed9Sopenharmony_ci          }
5066d528ed9Sopenharmony_ci
5076d528ed9Sopenharmony_ci          string.Append(hex_digit);
5086d528ed9Sopenharmony_ci          break;
5096d528ed9Sopenharmony_ci        }
5106d528ed9Sopenharmony_ci        case 'u': {  // UTF-16 sequence.
5116d528ed9Sopenharmony_ci          // UTF units are of the form \uXXXX.
5126d528ed9Sopenharmony_ci          uint32_t code_point;
5136d528ed9Sopenharmony_ci          if (!DecodeUTF16(&code_point)) {
5146d528ed9Sopenharmony_ci            ReportError(JSONReader::JSON_INVALID_ESCAPE, 0);
5156d528ed9Sopenharmony_ci            return false;
5166d528ed9Sopenharmony_ci          }
5176d528ed9Sopenharmony_ci          string.Append(code_point);
5186d528ed9Sopenharmony_ci          break;
5196d528ed9Sopenharmony_ci        }
5206d528ed9Sopenharmony_ci        case '"':
5216d528ed9Sopenharmony_ci          string.Append('"');
5226d528ed9Sopenharmony_ci          break;
5236d528ed9Sopenharmony_ci        case '\\':
5246d528ed9Sopenharmony_ci          string.Append('\\');
5256d528ed9Sopenharmony_ci          break;
5266d528ed9Sopenharmony_ci        case '/':
5276d528ed9Sopenharmony_ci          string.Append('/');
5286d528ed9Sopenharmony_ci          break;
5296d528ed9Sopenharmony_ci        case 'b':
5306d528ed9Sopenharmony_ci          string.Append('\b');
5316d528ed9Sopenharmony_ci          break;
5326d528ed9Sopenharmony_ci        case 'f':
5336d528ed9Sopenharmony_ci          string.Append('\f');
5346d528ed9Sopenharmony_ci          break;
5356d528ed9Sopenharmony_ci        case 'n':
5366d528ed9Sopenharmony_ci          string.Append('\n');
5376d528ed9Sopenharmony_ci          break;
5386d528ed9Sopenharmony_ci        case 'r':
5396d528ed9Sopenharmony_ci          string.Append('\r');
5406d528ed9Sopenharmony_ci          break;
5416d528ed9Sopenharmony_ci        case 't':
5426d528ed9Sopenharmony_ci          string.Append('\t');
5436d528ed9Sopenharmony_ci          break;
5446d528ed9Sopenharmony_ci        case 'v':  // Not listed as valid escape sequence in the RFC.
5456d528ed9Sopenharmony_ci          string.Append('\v');
5466d528ed9Sopenharmony_ci          break;
5476d528ed9Sopenharmony_ci        // All other escape squences are illegal.
5486d528ed9Sopenharmony_ci        default:
5496d528ed9Sopenharmony_ci          ReportError(JSONReader::JSON_INVALID_ESCAPE, 0);
5506d528ed9Sopenharmony_ci          return false;
5516d528ed9Sopenharmony_ci      }
5526d528ed9Sopenharmony_ci    }
5536d528ed9Sopenharmony_ci  }
5546d528ed9Sopenharmony_ci
5556d528ed9Sopenharmony_ci  ReportError(JSONReader::JSON_SYNTAX_ERROR, 0);
5566d528ed9Sopenharmony_ci  return false;
5576d528ed9Sopenharmony_ci}
5586d528ed9Sopenharmony_ci
5596d528ed9Sopenharmony_ci// Entry is at the first X in \uXXXX.
5606d528ed9Sopenharmony_cibool JSONParser::DecodeUTF16(uint32_t* out_code_point) {
5616d528ed9Sopenharmony_ci  std::optional<std::string_view> escape_sequence = ConsumeChars(4);
5626d528ed9Sopenharmony_ci  if (!escape_sequence)
5636d528ed9Sopenharmony_ci    return false;
5646d528ed9Sopenharmony_ci
5656d528ed9Sopenharmony_ci  // Consume the UTF-16 code unit, which may be a high surrogate.
5666d528ed9Sopenharmony_ci  int code_unit16_high = 0;
5676d528ed9Sopenharmony_ci  if (!HexStringToInt(*escape_sequence, &code_unit16_high))
5686d528ed9Sopenharmony_ci    return false;
5696d528ed9Sopenharmony_ci
5706d528ed9Sopenharmony_ci  // If this is a high surrogate, consume the next code unit to get the
5716d528ed9Sopenharmony_ci  // low surrogate.
5726d528ed9Sopenharmony_ci  if (CBU16_IS_SURROGATE(code_unit16_high)) {
5736d528ed9Sopenharmony_ci    // Make sure this is the high surrogate. If not, it's an encoding
5746d528ed9Sopenharmony_ci    // error.
5756d528ed9Sopenharmony_ci    if (!CBU16_IS_SURROGATE_LEAD(code_unit16_high))
5766d528ed9Sopenharmony_ci      return false;
5776d528ed9Sopenharmony_ci
5786d528ed9Sopenharmony_ci    // Make sure that the token has more characters to consume the
5796d528ed9Sopenharmony_ci    // lower surrogate.
5806d528ed9Sopenharmony_ci    if (!ConsumeIfMatch("\\u"))
5816d528ed9Sopenharmony_ci      return false;
5826d528ed9Sopenharmony_ci
5836d528ed9Sopenharmony_ci    escape_sequence = ConsumeChars(4);
5846d528ed9Sopenharmony_ci    if (!escape_sequence)
5856d528ed9Sopenharmony_ci      return false;
5866d528ed9Sopenharmony_ci
5876d528ed9Sopenharmony_ci    int code_unit16_low = 0;
5886d528ed9Sopenharmony_ci    if (!HexStringToInt(*escape_sequence, &code_unit16_low))
5896d528ed9Sopenharmony_ci      return false;
5906d528ed9Sopenharmony_ci
5916d528ed9Sopenharmony_ci    if (!CBU16_IS_TRAIL(code_unit16_low))
5926d528ed9Sopenharmony_ci      return false;
5936d528ed9Sopenharmony_ci
5946d528ed9Sopenharmony_ci    uint32_t code_point =
5956d528ed9Sopenharmony_ci        CBU16_GET_SUPPLEMENTARY(code_unit16_high, code_unit16_low);
5966d528ed9Sopenharmony_ci    if (!IsValidCharacter(code_point))
5976d528ed9Sopenharmony_ci      return false;
5986d528ed9Sopenharmony_ci
5996d528ed9Sopenharmony_ci    *out_code_point = code_point;
6006d528ed9Sopenharmony_ci  } else {
6016d528ed9Sopenharmony_ci    // Not a surrogate.
6026d528ed9Sopenharmony_ci    DCHECK(CBU16_IS_SINGLE(code_unit16_high));
6036d528ed9Sopenharmony_ci    if (!IsValidCharacter(code_unit16_high)) {
6046d528ed9Sopenharmony_ci      if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0) {
6056d528ed9Sopenharmony_ci        return false;
6066d528ed9Sopenharmony_ci      }
6076d528ed9Sopenharmony_ci      *out_code_point = kUnicodeReplacementPoint;
6086d528ed9Sopenharmony_ci      return true;
6096d528ed9Sopenharmony_ci    }
6106d528ed9Sopenharmony_ci
6116d528ed9Sopenharmony_ci    *out_code_point = code_unit16_high;
6126d528ed9Sopenharmony_ci  }
6136d528ed9Sopenharmony_ci
6146d528ed9Sopenharmony_ci  return true;
6156d528ed9Sopenharmony_ci}
6166d528ed9Sopenharmony_ci
6176d528ed9Sopenharmony_cistd::optional<Value> JSONParser::ConsumeNumber() {
6186d528ed9Sopenharmony_ci  const char* num_start = pos();
6196d528ed9Sopenharmony_ci  const int start_index = index_;
6206d528ed9Sopenharmony_ci  int end_index = start_index;
6216d528ed9Sopenharmony_ci
6226d528ed9Sopenharmony_ci  if (PeekChar() == '-')
6236d528ed9Sopenharmony_ci    ConsumeChar();
6246d528ed9Sopenharmony_ci
6256d528ed9Sopenharmony_ci  if (!ReadInt(false)) {
6266d528ed9Sopenharmony_ci    ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
6276d528ed9Sopenharmony_ci    return std::nullopt;
6286d528ed9Sopenharmony_ci  }
6296d528ed9Sopenharmony_ci  end_index = index_;
6306d528ed9Sopenharmony_ci
6316d528ed9Sopenharmony_ci  // The optional fraction part.
6326d528ed9Sopenharmony_ci  if (PeekChar() == '.') {
6336d528ed9Sopenharmony_ci    ConsumeChar();
6346d528ed9Sopenharmony_ci    if (!ReadInt(true)) {
6356d528ed9Sopenharmony_ci      ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
6366d528ed9Sopenharmony_ci      return std::nullopt;
6376d528ed9Sopenharmony_ci    }
6386d528ed9Sopenharmony_ci    end_index = index_;
6396d528ed9Sopenharmony_ci  }
6406d528ed9Sopenharmony_ci
6416d528ed9Sopenharmony_ci  // Optional exponent part.
6426d528ed9Sopenharmony_ci  std::optional<char> c = PeekChar();
6436d528ed9Sopenharmony_ci  if (c == 'e' || c == 'E') {
6446d528ed9Sopenharmony_ci    ConsumeChar();
6456d528ed9Sopenharmony_ci    if (PeekChar() == '-' || PeekChar() == '+') {
6466d528ed9Sopenharmony_ci      ConsumeChar();
6476d528ed9Sopenharmony_ci    }
6486d528ed9Sopenharmony_ci    if (!ReadInt(true)) {
6496d528ed9Sopenharmony_ci      ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
6506d528ed9Sopenharmony_ci      return std::nullopt;
6516d528ed9Sopenharmony_ci    }
6526d528ed9Sopenharmony_ci    end_index = index_;
6536d528ed9Sopenharmony_ci  }
6546d528ed9Sopenharmony_ci
6556d528ed9Sopenharmony_ci  // ReadInt is greedy because numbers have no easily detectable sentinel,
6566d528ed9Sopenharmony_ci  // so save off where the parser should be on exit (see Consume invariant at
6576d528ed9Sopenharmony_ci  // the top of the header), then make sure the next token is one which is
6586d528ed9Sopenharmony_ci  // valid.
6596d528ed9Sopenharmony_ci  int exit_index = index_;
6606d528ed9Sopenharmony_ci
6616d528ed9Sopenharmony_ci  switch (GetNextToken()) {
6626d528ed9Sopenharmony_ci    case T_OBJECT_END:
6636d528ed9Sopenharmony_ci    case T_ARRAY_END:
6646d528ed9Sopenharmony_ci    case T_LIST_SEPARATOR:
6656d528ed9Sopenharmony_ci    case T_END_OF_INPUT:
6666d528ed9Sopenharmony_ci      break;
6676d528ed9Sopenharmony_ci    default:
6686d528ed9Sopenharmony_ci      ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
6696d528ed9Sopenharmony_ci      return std::nullopt;
6706d528ed9Sopenharmony_ci  }
6716d528ed9Sopenharmony_ci
6726d528ed9Sopenharmony_ci  index_ = exit_index;
6736d528ed9Sopenharmony_ci
6746d528ed9Sopenharmony_ci  std::string_view num_string(num_start, end_index - start_index);
6756d528ed9Sopenharmony_ci
6766d528ed9Sopenharmony_ci  int num_int;
6776d528ed9Sopenharmony_ci  if (StringToInt(num_string, &num_int))
6786d528ed9Sopenharmony_ci    return Value(num_int);
6796d528ed9Sopenharmony_ci
6806d528ed9Sopenharmony_ci  return std::nullopt;
6816d528ed9Sopenharmony_ci}
6826d528ed9Sopenharmony_ci
6836d528ed9Sopenharmony_cibool JSONParser::ReadInt(bool allow_leading_zeros) {
6846d528ed9Sopenharmony_ci  size_t len = 0;
6856d528ed9Sopenharmony_ci  char first = 0;
6866d528ed9Sopenharmony_ci
6876d528ed9Sopenharmony_ci  while (std::optional<char> c = PeekChar()) {
6886d528ed9Sopenharmony_ci    if (!IsAsciiDigit(c))
6896d528ed9Sopenharmony_ci      break;
6906d528ed9Sopenharmony_ci
6916d528ed9Sopenharmony_ci    if (len == 0)
6926d528ed9Sopenharmony_ci      first = *c;
6936d528ed9Sopenharmony_ci
6946d528ed9Sopenharmony_ci    ++len;
6956d528ed9Sopenharmony_ci    ConsumeChar();
6966d528ed9Sopenharmony_ci  }
6976d528ed9Sopenharmony_ci
6986d528ed9Sopenharmony_ci  if (len == 0)
6996d528ed9Sopenharmony_ci    return false;
7006d528ed9Sopenharmony_ci
7016d528ed9Sopenharmony_ci  if (!allow_leading_zeros && len > 1 && first == '0')
7026d528ed9Sopenharmony_ci    return false;
7036d528ed9Sopenharmony_ci
7046d528ed9Sopenharmony_ci  return true;
7056d528ed9Sopenharmony_ci}
7066d528ed9Sopenharmony_ci
7076d528ed9Sopenharmony_cistd::optional<Value> JSONParser::ConsumeLiteral() {
7086d528ed9Sopenharmony_ci  if (ConsumeIfMatch("true")) {
7096d528ed9Sopenharmony_ci    return Value(true);
7106d528ed9Sopenharmony_ci  } else if (ConsumeIfMatch("false")) {
7116d528ed9Sopenharmony_ci    return Value(false);
7126d528ed9Sopenharmony_ci  } else if (ConsumeIfMatch("null")) {
7136d528ed9Sopenharmony_ci    return Value(Value::Type::NONE);
7146d528ed9Sopenharmony_ci  } else {
7156d528ed9Sopenharmony_ci    ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
7166d528ed9Sopenharmony_ci    return std::nullopt;
7176d528ed9Sopenharmony_ci  }
7186d528ed9Sopenharmony_ci}
7196d528ed9Sopenharmony_ci
7206d528ed9Sopenharmony_cibool JSONParser::ConsumeIfMatch(std::string_view match) {
7216d528ed9Sopenharmony_ci  if (match == PeekChars(match.size())) {
7226d528ed9Sopenharmony_ci    ConsumeChars(match.size());
7236d528ed9Sopenharmony_ci    return true;
7246d528ed9Sopenharmony_ci  }
7256d528ed9Sopenharmony_ci  return false;
7266d528ed9Sopenharmony_ci}
7276d528ed9Sopenharmony_ci
7286d528ed9Sopenharmony_civoid JSONParser::ReportError(JSONReader::JsonParseError code,
7296d528ed9Sopenharmony_ci                             int column_adjust) {
7306d528ed9Sopenharmony_ci  error_code_ = code;
7316d528ed9Sopenharmony_ci  error_line_ = line_number_;
7326d528ed9Sopenharmony_ci  error_column_ = index_ - index_last_line_ + column_adjust;
7336d528ed9Sopenharmony_ci}
7346d528ed9Sopenharmony_ci
7356d528ed9Sopenharmony_ci// static
7366d528ed9Sopenharmony_cistd::string JSONParser::FormatErrorMessage(int line,
7376d528ed9Sopenharmony_ci                                           int column,
7386d528ed9Sopenharmony_ci                                           const std::string& description) {
7396d528ed9Sopenharmony_ci  if (line || column) {
7406d528ed9Sopenharmony_ci    return StringPrintf("Line: %i, column: %i, %s", line, column,
7416d528ed9Sopenharmony_ci                        description.c_str());
7426d528ed9Sopenharmony_ci  }
7436d528ed9Sopenharmony_ci  return description;
7446d528ed9Sopenharmony_ci}
7456d528ed9Sopenharmony_ci
7466d528ed9Sopenharmony_ci}  // namespace internal
7476d528ed9Sopenharmony_ci}  // namespace base
748