1c5f01b2fSopenharmony_ci// __ _____ _____ _____ 2c5f01b2fSopenharmony_ci// __| | __| | | | JSON for Modern C++ 3c5f01b2fSopenharmony_ci// | | |__ | | | | | | version 3.11.2 4c5f01b2fSopenharmony_ci// |_____|_____|_____|_|___| https://github.com/nlohmann/json 5c5f01b2fSopenharmony_ci// 6c5f01b2fSopenharmony_ci// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 7c5f01b2fSopenharmony_ci// SPDX-License-Identifier: MIT 8c5f01b2fSopenharmony_ci 9c5f01b2fSopenharmony_ci#pragma once 10c5f01b2fSopenharmony_ci 11c5f01b2fSopenharmony_ci#include <cmath> // isfinite 12c5f01b2fSopenharmony_ci#include <cstdint> // uint8_t 13c5f01b2fSopenharmony_ci#include <functional> // function 14c5f01b2fSopenharmony_ci#include <string> // string 15c5f01b2fSopenharmony_ci#include <utility> // move 16c5f01b2fSopenharmony_ci#include <vector> // vector 17c5f01b2fSopenharmony_ci 18c5f01b2fSopenharmony_ci#include <nlohmann/detail/exceptions.hpp> 19c5f01b2fSopenharmony_ci#include <nlohmann/detail/input/input_adapters.hpp> 20c5f01b2fSopenharmony_ci#include <nlohmann/detail/input/json_sax.hpp> 21c5f01b2fSopenharmony_ci#include <nlohmann/detail/input/lexer.hpp> 22c5f01b2fSopenharmony_ci#include <nlohmann/detail/macro_scope.hpp> 23c5f01b2fSopenharmony_ci#include <nlohmann/detail/meta/is_sax.hpp> 24c5f01b2fSopenharmony_ci#include <nlohmann/detail/string_concat.hpp> 25c5f01b2fSopenharmony_ci#include <nlohmann/detail/value_t.hpp> 26c5f01b2fSopenharmony_ci 27c5f01b2fSopenharmony_ciNLOHMANN_JSON_NAMESPACE_BEGIN 28c5f01b2fSopenharmony_cinamespace detail 29c5f01b2fSopenharmony_ci{ 30c5f01b2fSopenharmony_ci//////////// 31c5f01b2fSopenharmony_ci// parser // 32c5f01b2fSopenharmony_ci//////////// 33c5f01b2fSopenharmony_ci 34c5f01b2fSopenharmony_cienum class parse_event_t : std::uint8_t 35c5f01b2fSopenharmony_ci{ 36c5f01b2fSopenharmony_ci /// the parser read `{` and started to process a JSON object 37c5f01b2fSopenharmony_ci object_start, 38c5f01b2fSopenharmony_ci /// the parser read `}` and finished processing a JSON object 39c5f01b2fSopenharmony_ci object_end, 40c5f01b2fSopenharmony_ci /// the parser read `[` and started to process a JSON array 41c5f01b2fSopenharmony_ci array_start, 42c5f01b2fSopenharmony_ci /// the parser read `]` and finished processing a JSON array 43c5f01b2fSopenharmony_ci array_end, 44c5f01b2fSopenharmony_ci /// the parser read a key of a value in an object 45c5f01b2fSopenharmony_ci key, 46c5f01b2fSopenharmony_ci /// the parser finished reading a JSON value 47c5f01b2fSopenharmony_ci value 48c5f01b2fSopenharmony_ci}; 49c5f01b2fSopenharmony_ci 50c5f01b2fSopenharmony_citemplate<typename BasicJsonType> 51c5f01b2fSopenharmony_ciusing parser_callback_t = 52c5f01b2fSopenharmony_ci std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>; 53c5f01b2fSopenharmony_ci 54c5f01b2fSopenharmony_ci/*! 55c5f01b2fSopenharmony_ci@brief syntax analysis 56c5f01b2fSopenharmony_ci 57c5f01b2fSopenharmony_ciThis class implements a recursive descent parser. 58c5f01b2fSopenharmony_ci*/ 59c5f01b2fSopenharmony_citemplate<typename BasicJsonType, typename InputAdapterType> 60c5f01b2fSopenharmony_ciclass parser 61c5f01b2fSopenharmony_ci{ 62c5f01b2fSopenharmony_ci using number_integer_t = typename BasicJsonType::number_integer_t; 63c5f01b2fSopenharmony_ci using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 64c5f01b2fSopenharmony_ci using number_float_t = typename BasicJsonType::number_float_t; 65c5f01b2fSopenharmony_ci using string_t = typename BasicJsonType::string_t; 66c5f01b2fSopenharmony_ci using lexer_t = lexer<BasicJsonType, InputAdapterType>; 67c5f01b2fSopenharmony_ci using token_type = typename lexer_t::token_type; 68c5f01b2fSopenharmony_ci 69c5f01b2fSopenharmony_ci public: 70c5f01b2fSopenharmony_ci /// a parser reading from an input adapter 71c5f01b2fSopenharmony_ci explicit parser(InputAdapterType&& adapter, 72c5f01b2fSopenharmony_ci const parser_callback_t<BasicJsonType> cb = nullptr, 73c5f01b2fSopenharmony_ci const bool allow_exceptions_ = true, 74c5f01b2fSopenharmony_ci const bool skip_comments = false) 75c5f01b2fSopenharmony_ci : callback(cb) 76c5f01b2fSopenharmony_ci , m_lexer(std::move(adapter), skip_comments) 77c5f01b2fSopenharmony_ci , allow_exceptions(allow_exceptions_) 78c5f01b2fSopenharmony_ci { 79c5f01b2fSopenharmony_ci // read first token 80c5f01b2fSopenharmony_ci get_token(); 81c5f01b2fSopenharmony_ci } 82c5f01b2fSopenharmony_ci 83c5f01b2fSopenharmony_ci /*! 84c5f01b2fSopenharmony_ci @brief public parser interface 85c5f01b2fSopenharmony_ci 86c5f01b2fSopenharmony_ci @param[in] strict whether to expect the last token to be EOF 87c5f01b2fSopenharmony_ci @param[in,out] result parsed JSON value 88c5f01b2fSopenharmony_ci 89c5f01b2fSopenharmony_ci @throw parse_error.101 in case of an unexpected token 90c5f01b2fSopenharmony_ci @throw parse_error.102 if to_unicode fails or surrogate error 91c5f01b2fSopenharmony_ci @throw parse_error.103 if to_unicode fails 92c5f01b2fSopenharmony_ci */ 93c5f01b2fSopenharmony_ci void parse(const bool strict, BasicJsonType& result) 94c5f01b2fSopenharmony_ci { 95c5f01b2fSopenharmony_ci if (callback) 96c5f01b2fSopenharmony_ci { 97c5f01b2fSopenharmony_ci json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions); 98c5f01b2fSopenharmony_ci sax_parse_internal(&sdp); 99c5f01b2fSopenharmony_ci 100c5f01b2fSopenharmony_ci // in strict mode, input must be completely read 101c5f01b2fSopenharmony_ci if (strict && (get_token() != token_type::end_of_input)) 102c5f01b2fSopenharmony_ci { 103c5f01b2fSopenharmony_ci sdp.parse_error(m_lexer.get_position(), 104c5f01b2fSopenharmony_ci m_lexer.get_token_string(), 105c5f01b2fSopenharmony_ci parse_error::create(101, m_lexer.get_position(), 106c5f01b2fSopenharmony_ci exception_message(token_type::end_of_input, "value"), nullptr)); 107c5f01b2fSopenharmony_ci } 108c5f01b2fSopenharmony_ci 109c5f01b2fSopenharmony_ci // in case of an error, return discarded value 110c5f01b2fSopenharmony_ci if (sdp.is_errored()) 111c5f01b2fSopenharmony_ci { 112c5f01b2fSopenharmony_ci result = value_t::discarded; 113c5f01b2fSopenharmony_ci return; 114c5f01b2fSopenharmony_ci } 115c5f01b2fSopenharmony_ci 116c5f01b2fSopenharmony_ci // set top-level value to null if it was discarded by the callback 117c5f01b2fSopenharmony_ci // function 118c5f01b2fSopenharmony_ci if (result.is_discarded()) 119c5f01b2fSopenharmony_ci { 120c5f01b2fSopenharmony_ci result = nullptr; 121c5f01b2fSopenharmony_ci } 122c5f01b2fSopenharmony_ci } 123c5f01b2fSopenharmony_ci else 124c5f01b2fSopenharmony_ci { 125c5f01b2fSopenharmony_ci json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions); 126c5f01b2fSopenharmony_ci sax_parse_internal(&sdp); 127c5f01b2fSopenharmony_ci 128c5f01b2fSopenharmony_ci // in strict mode, input must be completely read 129c5f01b2fSopenharmony_ci if (strict && (get_token() != token_type::end_of_input)) 130c5f01b2fSopenharmony_ci { 131c5f01b2fSopenharmony_ci sdp.parse_error(m_lexer.get_position(), 132c5f01b2fSopenharmony_ci m_lexer.get_token_string(), 133c5f01b2fSopenharmony_ci parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); 134c5f01b2fSopenharmony_ci } 135c5f01b2fSopenharmony_ci 136c5f01b2fSopenharmony_ci // in case of an error, return discarded value 137c5f01b2fSopenharmony_ci if (sdp.is_errored()) 138c5f01b2fSopenharmony_ci { 139c5f01b2fSopenharmony_ci result = value_t::discarded; 140c5f01b2fSopenharmony_ci return; 141c5f01b2fSopenharmony_ci } 142c5f01b2fSopenharmony_ci } 143c5f01b2fSopenharmony_ci 144c5f01b2fSopenharmony_ci result.assert_invariant(); 145c5f01b2fSopenharmony_ci } 146c5f01b2fSopenharmony_ci 147c5f01b2fSopenharmony_ci /*! 148c5f01b2fSopenharmony_ci @brief public accept interface 149c5f01b2fSopenharmony_ci 150c5f01b2fSopenharmony_ci @param[in] strict whether to expect the last token to be EOF 151c5f01b2fSopenharmony_ci @return whether the input is a proper JSON text 152c5f01b2fSopenharmony_ci */ 153c5f01b2fSopenharmony_ci bool accept(const bool strict = true) 154c5f01b2fSopenharmony_ci { 155c5f01b2fSopenharmony_ci json_sax_acceptor<BasicJsonType> sax_acceptor; 156c5f01b2fSopenharmony_ci return sax_parse(&sax_acceptor, strict); 157c5f01b2fSopenharmony_ci } 158c5f01b2fSopenharmony_ci 159c5f01b2fSopenharmony_ci template<typename SAX> 160c5f01b2fSopenharmony_ci JSON_HEDLEY_NON_NULL(2) 161c5f01b2fSopenharmony_ci bool sax_parse(SAX* sax, const bool strict = true) 162c5f01b2fSopenharmony_ci { 163c5f01b2fSopenharmony_ci (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {}; 164c5f01b2fSopenharmony_ci const bool result = sax_parse_internal(sax); 165c5f01b2fSopenharmony_ci 166c5f01b2fSopenharmony_ci // strict mode: next byte must be EOF 167c5f01b2fSopenharmony_ci if (result && strict && (get_token() != token_type::end_of_input)) 168c5f01b2fSopenharmony_ci { 169c5f01b2fSopenharmony_ci return sax->parse_error(m_lexer.get_position(), 170c5f01b2fSopenharmony_ci m_lexer.get_token_string(), 171c5f01b2fSopenharmony_ci parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); 172c5f01b2fSopenharmony_ci } 173c5f01b2fSopenharmony_ci 174c5f01b2fSopenharmony_ci return result; 175c5f01b2fSopenharmony_ci } 176c5f01b2fSopenharmony_ci 177c5f01b2fSopenharmony_ci private: 178c5f01b2fSopenharmony_ci template<typename SAX> 179c5f01b2fSopenharmony_ci JSON_HEDLEY_NON_NULL(2) 180c5f01b2fSopenharmony_ci bool sax_parse_internal(SAX* sax) 181c5f01b2fSopenharmony_ci { 182c5f01b2fSopenharmony_ci // stack to remember the hierarchy of structured values we are parsing 183c5f01b2fSopenharmony_ci // true = array; false = object 184c5f01b2fSopenharmony_ci std::vector<bool> states; 185c5f01b2fSopenharmony_ci // value to avoid a goto (see comment where set to true) 186c5f01b2fSopenharmony_ci bool skip_to_state_evaluation = false; 187c5f01b2fSopenharmony_ci 188c5f01b2fSopenharmony_ci while (true) 189c5f01b2fSopenharmony_ci { 190c5f01b2fSopenharmony_ci if (!skip_to_state_evaluation) 191c5f01b2fSopenharmony_ci { 192c5f01b2fSopenharmony_ci // invariant: get_token() was called before each iteration 193c5f01b2fSopenharmony_ci switch (last_token) 194c5f01b2fSopenharmony_ci { 195c5f01b2fSopenharmony_ci case token_type::begin_object: 196c5f01b2fSopenharmony_ci { 197c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) 198c5f01b2fSopenharmony_ci { 199c5f01b2fSopenharmony_ci return false; 200c5f01b2fSopenharmony_ci } 201c5f01b2fSopenharmony_ci 202c5f01b2fSopenharmony_ci // closing } -> we are done 203c5f01b2fSopenharmony_ci if (get_token() == token_type::end_object) 204c5f01b2fSopenharmony_ci { 205c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) 206c5f01b2fSopenharmony_ci { 207c5f01b2fSopenharmony_ci return false; 208c5f01b2fSopenharmony_ci } 209c5f01b2fSopenharmony_ci break; 210c5f01b2fSopenharmony_ci } 211c5f01b2fSopenharmony_ci 212c5f01b2fSopenharmony_ci // parse key 213c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) 214c5f01b2fSopenharmony_ci { 215c5f01b2fSopenharmony_ci return sax->parse_error(m_lexer.get_position(), 216c5f01b2fSopenharmony_ci m_lexer.get_token_string(), 217c5f01b2fSopenharmony_ci parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); 218c5f01b2fSopenharmony_ci } 219c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) 220c5f01b2fSopenharmony_ci { 221c5f01b2fSopenharmony_ci return false; 222c5f01b2fSopenharmony_ci } 223c5f01b2fSopenharmony_ci 224c5f01b2fSopenharmony_ci // parse separator (:) 225c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) 226c5f01b2fSopenharmony_ci { 227c5f01b2fSopenharmony_ci return sax->parse_error(m_lexer.get_position(), 228c5f01b2fSopenharmony_ci m_lexer.get_token_string(), 229c5f01b2fSopenharmony_ci parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); 230c5f01b2fSopenharmony_ci } 231c5f01b2fSopenharmony_ci 232c5f01b2fSopenharmony_ci // remember we are now inside an object 233c5f01b2fSopenharmony_ci states.push_back(false); 234c5f01b2fSopenharmony_ci 235c5f01b2fSopenharmony_ci // parse values 236c5f01b2fSopenharmony_ci get_token(); 237c5f01b2fSopenharmony_ci continue; 238c5f01b2fSopenharmony_ci } 239c5f01b2fSopenharmony_ci 240c5f01b2fSopenharmony_ci case token_type::begin_array: 241c5f01b2fSopenharmony_ci { 242c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) 243c5f01b2fSopenharmony_ci { 244c5f01b2fSopenharmony_ci return false; 245c5f01b2fSopenharmony_ci } 246c5f01b2fSopenharmony_ci 247c5f01b2fSopenharmony_ci // closing ] -> we are done 248c5f01b2fSopenharmony_ci if (get_token() == token_type::end_array) 249c5f01b2fSopenharmony_ci { 250c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) 251c5f01b2fSopenharmony_ci { 252c5f01b2fSopenharmony_ci return false; 253c5f01b2fSopenharmony_ci } 254c5f01b2fSopenharmony_ci break; 255c5f01b2fSopenharmony_ci } 256c5f01b2fSopenharmony_ci 257c5f01b2fSopenharmony_ci // remember we are now inside an array 258c5f01b2fSopenharmony_ci states.push_back(true); 259c5f01b2fSopenharmony_ci 260c5f01b2fSopenharmony_ci // parse values (no need to call get_token) 261c5f01b2fSopenharmony_ci continue; 262c5f01b2fSopenharmony_ci } 263c5f01b2fSopenharmony_ci 264c5f01b2fSopenharmony_ci case token_type::value_float: 265c5f01b2fSopenharmony_ci { 266c5f01b2fSopenharmony_ci const auto res = m_lexer.get_number_float(); 267c5f01b2fSopenharmony_ci 268c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) 269c5f01b2fSopenharmony_ci { 270c5f01b2fSopenharmony_ci return sax->parse_error(m_lexer.get_position(), 271c5f01b2fSopenharmony_ci m_lexer.get_token_string(), 272c5f01b2fSopenharmony_ci out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr)); 273c5f01b2fSopenharmony_ci } 274c5f01b2fSopenharmony_ci 275c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) 276c5f01b2fSopenharmony_ci { 277c5f01b2fSopenharmony_ci return false; 278c5f01b2fSopenharmony_ci } 279c5f01b2fSopenharmony_ci 280c5f01b2fSopenharmony_ci break; 281c5f01b2fSopenharmony_ci } 282c5f01b2fSopenharmony_ci 283c5f01b2fSopenharmony_ci case token_type::literal_false: 284c5f01b2fSopenharmony_ci { 285c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) 286c5f01b2fSopenharmony_ci { 287c5f01b2fSopenharmony_ci return false; 288c5f01b2fSopenharmony_ci } 289c5f01b2fSopenharmony_ci break; 290c5f01b2fSopenharmony_ci } 291c5f01b2fSopenharmony_ci 292c5f01b2fSopenharmony_ci case token_type::literal_null: 293c5f01b2fSopenharmony_ci { 294c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(!sax->null())) 295c5f01b2fSopenharmony_ci { 296c5f01b2fSopenharmony_ci return false; 297c5f01b2fSopenharmony_ci } 298c5f01b2fSopenharmony_ci break; 299c5f01b2fSopenharmony_ci } 300c5f01b2fSopenharmony_ci 301c5f01b2fSopenharmony_ci case token_type::literal_true: 302c5f01b2fSopenharmony_ci { 303c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) 304c5f01b2fSopenharmony_ci { 305c5f01b2fSopenharmony_ci return false; 306c5f01b2fSopenharmony_ci } 307c5f01b2fSopenharmony_ci break; 308c5f01b2fSopenharmony_ci } 309c5f01b2fSopenharmony_ci 310c5f01b2fSopenharmony_ci case token_type::value_integer: 311c5f01b2fSopenharmony_ci { 312c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) 313c5f01b2fSopenharmony_ci { 314c5f01b2fSopenharmony_ci return false; 315c5f01b2fSopenharmony_ci } 316c5f01b2fSopenharmony_ci break; 317c5f01b2fSopenharmony_ci } 318c5f01b2fSopenharmony_ci 319c5f01b2fSopenharmony_ci case token_type::value_string: 320c5f01b2fSopenharmony_ci { 321c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) 322c5f01b2fSopenharmony_ci { 323c5f01b2fSopenharmony_ci return false; 324c5f01b2fSopenharmony_ci } 325c5f01b2fSopenharmony_ci break; 326c5f01b2fSopenharmony_ci } 327c5f01b2fSopenharmony_ci 328c5f01b2fSopenharmony_ci case token_type::value_unsigned: 329c5f01b2fSopenharmony_ci { 330c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) 331c5f01b2fSopenharmony_ci { 332c5f01b2fSopenharmony_ci return false; 333c5f01b2fSopenharmony_ci } 334c5f01b2fSopenharmony_ci break; 335c5f01b2fSopenharmony_ci } 336c5f01b2fSopenharmony_ci 337c5f01b2fSopenharmony_ci case token_type::parse_error: 338c5f01b2fSopenharmony_ci { 339c5f01b2fSopenharmony_ci // using "uninitialized" to avoid "expected" message 340c5f01b2fSopenharmony_ci return sax->parse_error(m_lexer.get_position(), 341c5f01b2fSopenharmony_ci m_lexer.get_token_string(), 342c5f01b2fSopenharmony_ci parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr)); 343c5f01b2fSopenharmony_ci } 344c5f01b2fSopenharmony_ci 345c5f01b2fSopenharmony_ci case token_type::uninitialized: 346c5f01b2fSopenharmony_ci case token_type::end_array: 347c5f01b2fSopenharmony_ci case token_type::end_object: 348c5f01b2fSopenharmony_ci case token_type::name_separator: 349c5f01b2fSopenharmony_ci case token_type::value_separator: 350c5f01b2fSopenharmony_ci case token_type::end_of_input: 351c5f01b2fSopenharmony_ci case token_type::literal_or_value: 352c5f01b2fSopenharmony_ci default: // the last token was unexpected 353c5f01b2fSopenharmony_ci { 354c5f01b2fSopenharmony_ci return sax->parse_error(m_lexer.get_position(), 355c5f01b2fSopenharmony_ci m_lexer.get_token_string(), 356c5f01b2fSopenharmony_ci parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); 357c5f01b2fSopenharmony_ci } 358c5f01b2fSopenharmony_ci } 359c5f01b2fSopenharmony_ci } 360c5f01b2fSopenharmony_ci else 361c5f01b2fSopenharmony_ci { 362c5f01b2fSopenharmony_ci skip_to_state_evaluation = false; 363c5f01b2fSopenharmony_ci } 364c5f01b2fSopenharmony_ci 365c5f01b2fSopenharmony_ci // we reached this line after we successfully parsed a value 366c5f01b2fSopenharmony_ci if (states.empty()) 367c5f01b2fSopenharmony_ci { 368c5f01b2fSopenharmony_ci // empty stack: we reached the end of the hierarchy: done 369c5f01b2fSopenharmony_ci return true; 370c5f01b2fSopenharmony_ci } 371c5f01b2fSopenharmony_ci 372c5f01b2fSopenharmony_ci if (states.back()) // array 373c5f01b2fSopenharmony_ci { 374c5f01b2fSopenharmony_ci // comma -> next value 375c5f01b2fSopenharmony_ci if (get_token() == token_type::value_separator) 376c5f01b2fSopenharmony_ci { 377c5f01b2fSopenharmony_ci // parse a new value 378c5f01b2fSopenharmony_ci get_token(); 379c5f01b2fSopenharmony_ci continue; 380c5f01b2fSopenharmony_ci } 381c5f01b2fSopenharmony_ci 382c5f01b2fSopenharmony_ci // closing ] 383c5f01b2fSopenharmony_ci if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) 384c5f01b2fSopenharmony_ci { 385c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) 386c5f01b2fSopenharmony_ci { 387c5f01b2fSopenharmony_ci return false; 388c5f01b2fSopenharmony_ci } 389c5f01b2fSopenharmony_ci 390c5f01b2fSopenharmony_ci // We are done with this array. Before we can parse a 391c5f01b2fSopenharmony_ci // new value, we need to evaluate the new state first. 392c5f01b2fSopenharmony_ci // By setting skip_to_state_evaluation to false, we 393c5f01b2fSopenharmony_ci // are effectively jumping to the beginning of this if. 394c5f01b2fSopenharmony_ci JSON_ASSERT(!states.empty()); 395c5f01b2fSopenharmony_ci states.pop_back(); 396c5f01b2fSopenharmony_ci skip_to_state_evaluation = true; 397c5f01b2fSopenharmony_ci continue; 398c5f01b2fSopenharmony_ci } 399c5f01b2fSopenharmony_ci 400c5f01b2fSopenharmony_ci return sax->parse_error(m_lexer.get_position(), 401c5f01b2fSopenharmony_ci m_lexer.get_token_string(), 402c5f01b2fSopenharmony_ci parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr)); 403c5f01b2fSopenharmony_ci } 404c5f01b2fSopenharmony_ci 405c5f01b2fSopenharmony_ci // states.back() is false -> object 406c5f01b2fSopenharmony_ci 407c5f01b2fSopenharmony_ci // comma -> next value 408c5f01b2fSopenharmony_ci if (get_token() == token_type::value_separator) 409c5f01b2fSopenharmony_ci { 410c5f01b2fSopenharmony_ci // parse key 411c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) 412c5f01b2fSopenharmony_ci { 413c5f01b2fSopenharmony_ci return sax->parse_error(m_lexer.get_position(), 414c5f01b2fSopenharmony_ci m_lexer.get_token_string(), 415c5f01b2fSopenharmony_ci parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); 416c5f01b2fSopenharmony_ci } 417c5f01b2fSopenharmony_ci 418c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) 419c5f01b2fSopenharmony_ci { 420c5f01b2fSopenharmony_ci return false; 421c5f01b2fSopenharmony_ci } 422c5f01b2fSopenharmony_ci 423c5f01b2fSopenharmony_ci // parse separator (:) 424c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) 425c5f01b2fSopenharmony_ci { 426c5f01b2fSopenharmony_ci return sax->parse_error(m_lexer.get_position(), 427c5f01b2fSopenharmony_ci m_lexer.get_token_string(), 428c5f01b2fSopenharmony_ci parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); 429c5f01b2fSopenharmony_ci } 430c5f01b2fSopenharmony_ci 431c5f01b2fSopenharmony_ci // parse values 432c5f01b2fSopenharmony_ci get_token(); 433c5f01b2fSopenharmony_ci continue; 434c5f01b2fSopenharmony_ci } 435c5f01b2fSopenharmony_ci 436c5f01b2fSopenharmony_ci // closing } 437c5f01b2fSopenharmony_ci if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) 438c5f01b2fSopenharmony_ci { 439c5f01b2fSopenharmony_ci if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) 440c5f01b2fSopenharmony_ci { 441c5f01b2fSopenharmony_ci return false; 442c5f01b2fSopenharmony_ci } 443c5f01b2fSopenharmony_ci 444c5f01b2fSopenharmony_ci // We are done with this object. Before we can parse a 445c5f01b2fSopenharmony_ci // new value, we need to evaluate the new state first. 446c5f01b2fSopenharmony_ci // By setting skip_to_state_evaluation to false, we 447c5f01b2fSopenharmony_ci // are effectively jumping to the beginning of this if. 448c5f01b2fSopenharmony_ci JSON_ASSERT(!states.empty()); 449c5f01b2fSopenharmony_ci states.pop_back(); 450c5f01b2fSopenharmony_ci skip_to_state_evaluation = true; 451c5f01b2fSopenharmony_ci continue; 452c5f01b2fSopenharmony_ci } 453c5f01b2fSopenharmony_ci 454c5f01b2fSopenharmony_ci return sax->parse_error(m_lexer.get_position(), 455c5f01b2fSopenharmony_ci m_lexer.get_token_string(), 456c5f01b2fSopenharmony_ci parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr)); 457c5f01b2fSopenharmony_ci } 458c5f01b2fSopenharmony_ci } 459c5f01b2fSopenharmony_ci 460c5f01b2fSopenharmony_ci /// get next token from lexer 461c5f01b2fSopenharmony_ci token_type get_token() 462c5f01b2fSopenharmony_ci { 463c5f01b2fSopenharmony_ci return last_token = m_lexer.scan(); 464c5f01b2fSopenharmony_ci } 465c5f01b2fSopenharmony_ci 466c5f01b2fSopenharmony_ci std::string exception_message(const token_type expected, const std::string& context) 467c5f01b2fSopenharmony_ci { 468c5f01b2fSopenharmony_ci std::string error_msg = "syntax error "; 469c5f01b2fSopenharmony_ci 470c5f01b2fSopenharmony_ci if (!context.empty()) 471c5f01b2fSopenharmony_ci { 472c5f01b2fSopenharmony_ci error_msg += concat("while parsing ", context, ' '); 473c5f01b2fSopenharmony_ci } 474c5f01b2fSopenharmony_ci 475c5f01b2fSopenharmony_ci error_msg += "- "; 476c5f01b2fSopenharmony_ci 477c5f01b2fSopenharmony_ci if (last_token == token_type::parse_error) 478c5f01b2fSopenharmony_ci { 479c5f01b2fSopenharmony_ci error_msg += concat(m_lexer.get_error_message(), "; last read: '", 480c5f01b2fSopenharmony_ci m_lexer.get_token_string(), '\''); 481c5f01b2fSopenharmony_ci } 482c5f01b2fSopenharmony_ci else 483c5f01b2fSopenharmony_ci { 484c5f01b2fSopenharmony_ci error_msg += concat("unexpected ", lexer_t::token_type_name(last_token)); 485c5f01b2fSopenharmony_ci } 486c5f01b2fSopenharmony_ci 487c5f01b2fSopenharmony_ci if (expected != token_type::uninitialized) 488c5f01b2fSopenharmony_ci { 489c5f01b2fSopenharmony_ci error_msg += concat("; expected ", lexer_t::token_type_name(expected)); 490c5f01b2fSopenharmony_ci } 491c5f01b2fSopenharmony_ci 492c5f01b2fSopenharmony_ci return error_msg; 493c5f01b2fSopenharmony_ci } 494c5f01b2fSopenharmony_ci 495c5f01b2fSopenharmony_ci private: 496c5f01b2fSopenharmony_ci /// callback function 497c5f01b2fSopenharmony_ci const parser_callback_t<BasicJsonType> callback = nullptr; 498c5f01b2fSopenharmony_ci /// the type of the last read token 499c5f01b2fSopenharmony_ci token_type last_token = token_type::uninitialized; 500c5f01b2fSopenharmony_ci /// the lexer 501c5f01b2fSopenharmony_ci lexer_t m_lexer; 502c5f01b2fSopenharmony_ci /// whether to throw exceptions in case of errors 503c5f01b2fSopenharmony_ci const bool allow_exceptions = true; 504c5f01b2fSopenharmony_ci}; 505c5f01b2fSopenharmony_ci 506c5f01b2fSopenharmony_ci} // namespace detail 507c5f01b2fSopenharmony_ciNLOHMANN_JSON_NAMESPACE_END 508