1ffe3c632Sopenharmony_ci/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/). 2ffe3c632Sopenharmony_ci/// It is intended to be used with #include "json/json.h" 3ffe3c632Sopenharmony_ci 4ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 5ffe3c632Sopenharmony_ci// Beginning of content of file: LICENSE 6ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 7ffe3c632Sopenharmony_ci 8ffe3c632Sopenharmony_ci/* 9ffe3c632Sopenharmony_ciThe JsonCpp library's source code, including accompanying documentation, 10ffe3c632Sopenharmony_citests and demonstration applications, are licensed under the following 11ffe3c632Sopenharmony_ciconditions... 12ffe3c632Sopenharmony_ci 13ffe3c632Sopenharmony_ciThe author (Baptiste Lepilleur) explicitly disclaims copyright in all 14ffe3c632Sopenharmony_cijurisdictions which recognize such a disclaimer. In such jurisdictions, 15ffe3c632Sopenharmony_cithis software is released into the Public Domain. 16ffe3c632Sopenharmony_ci 17ffe3c632Sopenharmony_ciIn jurisdictions which do not recognize Public Domain property (e.g. Germany as of 18ffe3c632Sopenharmony_ci2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is 19ffe3c632Sopenharmony_cireleased under the terms of the MIT License (see below). 20ffe3c632Sopenharmony_ci 21ffe3c632Sopenharmony_ciIn jurisdictions which recognize Public Domain property, the user of this 22ffe3c632Sopenharmony_cisoftware may choose to accept it either as 1) Public Domain, 2) under the 23ffe3c632Sopenharmony_ciconditions of the MIT License (see below), or 3) under the terms of dual 24ffe3c632Sopenharmony_ciPublic Domain/MIT License conditions described here, as they choose. 25ffe3c632Sopenharmony_ci 26ffe3c632Sopenharmony_ciThe MIT License is about as close to Public Domain as a license can get, and is 27ffe3c632Sopenharmony_cidescribed in clear, concise terms at: 28ffe3c632Sopenharmony_ci 29ffe3c632Sopenharmony_ci http://en.wikipedia.org/wiki/MIT_License 30ffe3c632Sopenharmony_ci 31ffe3c632Sopenharmony_ciThe full text of the MIT License follows: 32ffe3c632Sopenharmony_ci 33ffe3c632Sopenharmony_ci======================================================================== 34ffe3c632Sopenharmony_ciCopyright (c) 2007-2010 Baptiste Lepilleur 35ffe3c632Sopenharmony_ci 36ffe3c632Sopenharmony_ciPermission is hereby granted, free of charge, to any person 37ffe3c632Sopenharmony_ciobtaining a copy of this software and associated documentation 38ffe3c632Sopenharmony_cifiles (the "Software"), to deal in the Software without 39ffe3c632Sopenharmony_cirestriction, including without limitation the rights to use, copy, 40ffe3c632Sopenharmony_cimodify, merge, publish, distribute, sublicense, and/or sell copies 41ffe3c632Sopenharmony_ciof the Software, and to permit persons to whom the Software is 42ffe3c632Sopenharmony_cifurnished to do so, subject to the following conditions: 43ffe3c632Sopenharmony_ci 44ffe3c632Sopenharmony_ciThe above copyright notice and this permission notice shall be 45ffe3c632Sopenharmony_ciincluded in all copies or substantial portions of the Software. 46ffe3c632Sopenharmony_ci 47ffe3c632Sopenharmony_ciTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 48ffe3c632Sopenharmony_ciEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 49ffe3c632Sopenharmony_ciMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 50ffe3c632Sopenharmony_ciNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 51ffe3c632Sopenharmony_ciBE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 52ffe3c632Sopenharmony_ciACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 53ffe3c632Sopenharmony_ciCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 54ffe3c632Sopenharmony_ciSOFTWARE. 55ffe3c632Sopenharmony_ci======================================================================== 56ffe3c632Sopenharmony_ci(END LICENSE TEXT) 57ffe3c632Sopenharmony_ci 58ffe3c632Sopenharmony_ciThe MIT license is compatible with both the GPL and commercial 59ffe3c632Sopenharmony_cisoftware, affording one all of the rights of Public Domain with the 60ffe3c632Sopenharmony_ciminor nuisance of being required to keep the above copyright notice 61ffe3c632Sopenharmony_ciand license text in the source code. Note also that by accepting the 62ffe3c632Sopenharmony_ciPublic Domain "license" you can re-license your copy using whatever 63ffe3c632Sopenharmony_cilicense you like. 64ffe3c632Sopenharmony_ci 65ffe3c632Sopenharmony_ci*/ 66ffe3c632Sopenharmony_ci 67ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 68ffe3c632Sopenharmony_ci// End of content of file: LICENSE 69ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 70ffe3c632Sopenharmony_ci 71ffe3c632Sopenharmony_ci 72ffe3c632Sopenharmony_ci 73ffe3c632Sopenharmony_ci 74ffe3c632Sopenharmony_ci 75ffe3c632Sopenharmony_ci 76ffe3c632Sopenharmony_ci#include "third_party/jsoncpp/json.h" 77ffe3c632Sopenharmony_ci 78ffe3c632Sopenharmony_ci#ifndef JSON_IS_AMALGAMATION 79ffe3c632Sopenharmony_ci#error "Compile with -I PATH_TO_JSON_DIRECTORY" 80ffe3c632Sopenharmony_ci#endif 81ffe3c632Sopenharmony_ci 82ffe3c632Sopenharmony_ci 83ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 84ffe3c632Sopenharmony_ci// Beginning of content of file: src/lib_json/json_tool.h 85ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 86ffe3c632Sopenharmony_ci 87ffe3c632Sopenharmony_ci// Copyright 2007-2010 Baptiste Lepilleur 88ffe3c632Sopenharmony_ci// Distributed under MIT license, or public domain if desired and 89ffe3c632Sopenharmony_ci// recognized in your jurisdiction. 90ffe3c632Sopenharmony_ci// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 91ffe3c632Sopenharmony_ci 92ffe3c632Sopenharmony_ci#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED 93ffe3c632Sopenharmony_ci#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED 94ffe3c632Sopenharmony_ci 95ffe3c632Sopenharmony_ci/* This header provides common string manipulation support, such as UTF-8, 96ffe3c632Sopenharmony_ci * portable conversion from/to string... 97ffe3c632Sopenharmony_ci * 98ffe3c632Sopenharmony_ci * It is an internal header that must not be exposed. 99ffe3c632Sopenharmony_ci */ 100ffe3c632Sopenharmony_ci 101ffe3c632Sopenharmony_cinamespace Json { 102ffe3c632Sopenharmony_ci 103ffe3c632Sopenharmony_ci/// Converts a unicode code-point to UTF-8. 104ffe3c632Sopenharmony_cistatic inline std::string codePointToUTF8(unsigned int cp) { 105ffe3c632Sopenharmony_ci std::string result; 106ffe3c632Sopenharmony_ci 107ffe3c632Sopenharmony_ci // based on description from http://en.wikipedia.org/wiki/UTF-8 108ffe3c632Sopenharmony_ci 109ffe3c632Sopenharmony_ci if (cp <= 0x7f) { 110ffe3c632Sopenharmony_ci result.resize(1); 111ffe3c632Sopenharmony_ci result[0] = static_cast<char>(cp); 112ffe3c632Sopenharmony_ci } else if (cp <= 0x7FF) { 113ffe3c632Sopenharmony_ci result.resize(2); 114ffe3c632Sopenharmony_ci result[1] = static_cast<char>(0x80 | (0x3f & cp)); 115ffe3c632Sopenharmony_ci result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6))); 116ffe3c632Sopenharmony_ci } else if (cp <= 0xFFFF) { 117ffe3c632Sopenharmony_ci result.resize(3); 118ffe3c632Sopenharmony_ci result[2] = static_cast<char>(0x80 | (0x3f & cp)); 119ffe3c632Sopenharmony_ci result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6))); 120ffe3c632Sopenharmony_ci result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12))); 121ffe3c632Sopenharmony_ci } else if (cp <= 0x10FFFF) { 122ffe3c632Sopenharmony_ci result.resize(4); 123ffe3c632Sopenharmony_ci result[3] = static_cast<char>(0x80 | (0x3f & cp)); 124ffe3c632Sopenharmony_ci result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6))); 125ffe3c632Sopenharmony_ci result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12))); 126ffe3c632Sopenharmony_ci result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18))); 127ffe3c632Sopenharmony_ci } 128ffe3c632Sopenharmony_ci 129ffe3c632Sopenharmony_ci return result; 130ffe3c632Sopenharmony_ci} 131ffe3c632Sopenharmony_ci 132ffe3c632Sopenharmony_ci/// Returns true if ch is a control character (in range [1,31]). 133ffe3c632Sopenharmony_cistatic inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } 134ffe3c632Sopenharmony_ci 135ffe3c632Sopenharmony_cienum { 136ffe3c632Sopenharmony_ci /// Constant that specify the size of the buffer that must be passed to 137ffe3c632Sopenharmony_ci /// uintToString. 138ffe3c632Sopenharmony_ci uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 139ffe3c632Sopenharmony_ci}; 140ffe3c632Sopenharmony_ci 141ffe3c632Sopenharmony_ci// Defines a char buffer for use with uintToString(). 142ffe3c632Sopenharmony_citypedef char UIntToStringBuffer[uintToStringBufferSize]; 143ffe3c632Sopenharmony_ci 144ffe3c632Sopenharmony_ci/** Converts an unsigned integer to string. 145ffe3c632Sopenharmony_ci * @param value Unsigned interger to convert to string 146ffe3c632Sopenharmony_ci * @param current Input/Output string buffer. 147ffe3c632Sopenharmony_ci * Must have at least uintToStringBufferSize chars free. 148ffe3c632Sopenharmony_ci */ 149ffe3c632Sopenharmony_cistatic inline void uintToString(LargestUInt value, char*& current) { 150ffe3c632Sopenharmony_ci *--current = 0; 151ffe3c632Sopenharmony_ci do { 152ffe3c632Sopenharmony_ci *--current = static_cast<signed char>(value % 10U + static_cast<unsigned>('0')); 153ffe3c632Sopenharmony_ci value /= 10; 154ffe3c632Sopenharmony_ci } while (value != 0); 155ffe3c632Sopenharmony_ci} 156ffe3c632Sopenharmony_ci 157ffe3c632Sopenharmony_ci/** Change ',' to '.' everywhere in buffer. 158ffe3c632Sopenharmony_ci * 159ffe3c632Sopenharmony_ci * We had a sophisticated way, but it did not work in WinCE. 160ffe3c632Sopenharmony_ci * @see https://github.com/open-source-parsers/jsoncpp/pull/9 161ffe3c632Sopenharmony_ci */ 162ffe3c632Sopenharmony_cistatic inline void fixNumericLocale(char* begin, char* end) { 163ffe3c632Sopenharmony_ci while (begin < end) { 164ffe3c632Sopenharmony_ci if (*begin == ',') { 165ffe3c632Sopenharmony_ci *begin = '.'; 166ffe3c632Sopenharmony_ci } 167ffe3c632Sopenharmony_ci ++begin; 168ffe3c632Sopenharmony_ci } 169ffe3c632Sopenharmony_ci} 170ffe3c632Sopenharmony_ci 171ffe3c632Sopenharmony_ci} // namespace Json { 172ffe3c632Sopenharmony_ci 173ffe3c632Sopenharmony_ci#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED 174ffe3c632Sopenharmony_ci 175ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 176ffe3c632Sopenharmony_ci// End of content of file: src/lib_json/json_tool.h 177ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 178ffe3c632Sopenharmony_ci 179ffe3c632Sopenharmony_ci 180ffe3c632Sopenharmony_ci 181ffe3c632Sopenharmony_ci 182ffe3c632Sopenharmony_ci 183ffe3c632Sopenharmony_ci 184ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 185ffe3c632Sopenharmony_ci// Beginning of content of file: src/lib_json/json_reader.cpp 186ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 187ffe3c632Sopenharmony_ci 188ffe3c632Sopenharmony_ci// Copyright 2007-2011 Baptiste Lepilleur 189ffe3c632Sopenharmony_ci// Distributed under MIT license, or public domain if desired and 190ffe3c632Sopenharmony_ci// recognized in your jurisdiction. 191ffe3c632Sopenharmony_ci// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 192ffe3c632Sopenharmony_ci 193ffe3c632Sopenharmony_ci#if !defined(JSON_IS_AMALGAMATION) 194ffe3c632Sopenharmony_ci#include <json/assertions.h> 195ffe3c632Sopenharmony_ci#include <json/reader.h> 196ffe3c632Sopenharmony_ci#include <json/value.h> 197ffe3c632Sopenharmony_ci#include "json_tool.h" 198ffe3c632Sopenharmony_ci#endif // if !defined(JSON_IS_AMALGAMATION) 199ffe3c632Sopenharmony_ci#include <utility> 200ffe3c632Sopenharmony_ci#include <cstdio> 201ffe3c632Sopenharmony_ci#include <cassert> 202ffe3c632Sopenharmony_ci#include <cstring> 203ffe3c632Sopenharmony_ci#include <istream> 204ffe3c632Sopenharmony_ci#include <sstream> 205ffe3c632Sopenharmony_ci#include <memory> 206ffe3c632Sopenharmony_ci#include <set> 207ffe3c632Sopenharmony_ci#include <limits> 208ffe3c632Sopenharmony_ci 209ffe3c632Sopenharmony_ci#if defined(_MSC_VER) 210ffe3c632Sopenharmony_ci#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above 211ffe3c632Sopenharmony_ci#define snprintf sprintf_s 212ffe3c632Sopenharmony_ci#elif _MSC_VER >= 1900 // VC++ 14.0 and above 213ffe3c632Sopenharmony_ci#define snprintf std::snprintf 214ffe3c632Sopenharmony_ci#else 215ffe3c632Sopenharmony_ci#define snprintf _snprintf 216ffe3c632Sopenharmony_ci#endif 217ffe3c632Sopenharmony_ci#elif defined(__ANDROID__) || defined(__QNXNTO__) 218ffe3c632Sopenharmony_ci#define snprintf snprintf 219ffe3c632Sopenharmony_ci#elif __cplusplus >= 201103L 220ffe3c632Sopenharmony_ci#define snprintf std::snprintf 221ffe3c632Sopenharmony_ci#endif 222ffe3c632Sopenharmony_ci 223ffe3c632Sopenharmony_ci#if defined(__QNXNTO__) 224ffe3c632Sopenharmony_ci#define sscanf std::sscanf 225ffe3c632Sopenharmony_ci#endif 226ffe3c632Sopenharmony_ci 227ffe3c632Sopenharmony_ci#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 228ffe3c632Sopenharmony_ci// Disable warning about strdup being deprecated. 229ffe3c632Sopenharmony_ci#pragma warning(disable : 4996) 230ffe3c632Sopenharmony_ci#endif 231ffe3c632Sopenharmony_ci 232ffe3c632Sopenharmony_cistatic int const stackLimit_g = 1000; 233ffe3c632Sopenharmony_cistatic int stackDepth_g = 0; // see readValue() 234ffe3c632Sopenharmony_ci 235ffe3c632Sopenharmony_cinamespace Json { 236ffe3c632Sopenharmony_ci 237ffe3c632Sopenharmony_ci#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) 238ffe3c632Sopenharmony_citypedef std::unique_ptr<CharReader> CharReaderPtr; 239ffe3c632Sopenharmony_ci#else 240ffe3c632Sopenharmony_citypedef std::auto_ptr<CharReader> CharReaderPtr; 241ffe3c632Sopenharmony_ci#endif 242ffe3c632Sopenharmony_ci 243ffe3c632Sopenharmony_ci// Implementation of class Features 244ffe3c632Sopenharmony_ci// //////////////////////////////// 245ffe3c632Sopenharmony_ci 246ffe3c632Sopenharmony_ciFeatures::Features() 247ffe3c632Sopenharmony_ci : allowComments_(true), strictRoot_(false), 248ffe3c632Sopenharmony_ci allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {} 249ffe3c632Sopenharmony_ci 250ffe3c632Sopenharmony_ciFeatures Features::all() { return Features(); } 251ffe3c632Sopenharmony_ci 252ffe3c632Sopenharmony_ciFeatures Features::strictMode() { 253ffe3c632Sopenharmony_ci Features features; 254ffe3c632Sopenharmony_ci features.allowComments_ = false; 255ffe3c632Sopenharmony_ci features.strictRoot_ = true; 256ffe3c632Sopenharmony_ci features.allowDroppedNullPlaceholders_ = false; 257ffe3c632Sopenharmony_ci features.allowNumericKeys_ = false; 258ffe3c632Sopenharmony_ci return features; 259ffe3c632Sopenharmony_ci} 260ffe3c632Sopenharmony_ci 261ffe3c632Sopenharmony_ci// Implementation of class Reader 262ffe3c632Sopenharmony_ci// //////////////////////////////// 263ffe3c632Sopenharmony_ci 264ffe3c632Sopenharmony_cistatic bool containsNewLine(Reader::Location begin, Reader::Location end) { 265ffe3c632Sopenharmony_ci for (; begin < end; ++begin) 266ffe3c632Sopenharmony_ci if (*begin == '\n' || *begin == '\r') 267ffe3c632Sopenharmony_ci return true; 268ffe3c632Sopenharmony_ci return false; 269ffe3c632Sopenharmony_ci} 270ffe3c632Sopenharmony_ci 271ffe3c632Sopenharmony_ci// Class Reader 272ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 273ffe3c632Sopenharmony_ci 274ffe3c632Sopenharmony_ciReader::Reader() 275ffe3c632Sopenharmony_ci : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), 276ffe3c632Sopenharmony_ci lastValue_(), commentsBefore_(), features_(Features::all()), 277ffe3c632Sopenharmony_ci collectComments_() {} 278ffe3c632Sopenharmony_ci 279ffe3c632Sopenharmony_ciReader::Reader(const Features& features) 280ffe3c632Sopenharmony_ci : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), 281ffe3c632Sopenharmony_ci lastValue_(), commentsBefore_(), features_(features), collectComments_() { 282ffe3c632Sopenharmony_ci} 283ffe3c632Sopenharmony_ci 284ffe3c632Sopenharmony_cibool 285ffe3c632Sopenharmony_ciReader::parse(const std::string& document, Value& root, bool collectComments) { 286ffe3c632Sopenharmony_ci document_ = document; 287ffe3c632Sopenharmony_ci const char* begin = document_.c_str(); 288ffe3c632Sopenharmony_ci const char* end = begin + document_.length(); 289ffe3c632Sopenharmony_ci return parse(begin, end, root, collectComments); 290ffe3c632Sopenharmony_ci} 291ffe3c632Sopenharmony_ci 292ffe3c632Sopenharmony_cibool Reader::parse(std::istream& sin, Value& root, bool collectComments) { 293ffe3c632Sopenharmony_ci // std::istream_iterator<char> begin(sin); 294ffe3c632Sopenharmony_ci // std::istream_iterator<char> end; 295ffe3c632Sopenharmony_ci // Those would allow streamed input from a file, if parse() were a 296ffe3c632Sopenharmony_ci // template function. 297ffe3c632Sopenharmony_ci 298ffe3c632Sopenharmony_ci // Since std::string is reference-counted, this at least does not 299ffe3c632Sopenharmony_ci // create an extra copy. 300ffe3c632Sopenharmony_ci std::string doc; 301ffe3c632Sopenharmony_ci std::getline(sin, doc, (char)EOF); 302ffe3c632Sopenharmony_ci return parse(doc, root, collectComments); 303ffe3c632Sopenharmony_ci} 304ffe3c632Sopenharmony_ci 305ffe3c632Sopenharmony_cibool Reader::parse(const char* beginDoc, 306ffe3c632Sopenharmony_ci const char* endDoc, 307ffe3c632Sopenharmony_ci Value& root, 308ffe3c632Sopenharmony_ci bool collectComments) { 309ffe3c632Sopenharmony_ci if (!features_.allowComments_) { 310ffe3c632Sopenharmony_ci collectComments = false; 311ffe3c632Sopenharmony_ci } 312ffe3c632Sopenharmony_ci 313ffe3c632Sopenharmony_ci begin_ = beginDoc; 314ffe3c632Sopenharmony_ci end_ = endDoc; 315ffe3c632Sopenharmony_ci collectComments_ = collectComments; 316ffe3c632Sopenharmony_ci current_ = begin_; 317ffe3c632Sopenharmony_ci lastValueEnd_ = 0; 318ffe3c632Sopenharmony_ci lastValue_ = 0; 319ffe3c632Sopenharmony_ci commentsBefore_ = ""; 320ffe3c632Sopenharmony_ci errors_.clear(); 321ffe3c632Sopenharmony_ci while (!nodes_.empty()) 322ffe3c632Sopenharmony_ci nodes_.pop(); 323ffe3c632Sopenharmony_ci nodes_.push(&root); 324ffe3c632Sopenharmony_ci 325ffe3c632Sopenharmony_ci stackDepth_g = 0; // Yes, this is bad coding, but options are limited. 326ffe3c632Sopenharmony_ci bool successful = readValue(); 327ffe3c632Sopenharmony_ci Token token; 328ffe3c632Sopenharmony_ci skipCommentTokens(token); 329ffe3c632Sopenharmony_ci if (collectComments_ && !commentsBefore_.empty()) 330ffe3c632Sopenharmony_ci root.setComment(commentsBefore_, commentAfter); 331ffe3c632Sopenharmony_ci if (features_.strictRoot_) { 332ffe3c632Sopenharmony_ci if (!root.isArray() && !root.isObject()) { 333ffe3c632Sopenharmony_ci // Set error location to start of doc, ideally should be first token found 334ffe3c632Sopenharmony_ci // in doc 335ffe3c632Sopenharmony_ci token.type_ = tokenError; 336ffe3c632Sopenharmony_ci token.start_ = beginDoc; 337ffe3c632Sopenharmony_ci token.end_ = endDoc; 338ffe3c632Sopenharmony_ci addError( 339ffe3c632Sopenharmony_ci "A valid JSON document must be either an array or an object value.", 340ffe3c632Sopenharmony_ci token); 341ffe3c632Sopenharmony_ci return false; 342ffe3c632Sopenharmony_ci } 343ffe3c632Sopenharmony_ci } 344ffe3c632Sopenharmony_ci return successful; 345ffe3c632Sopenharmony_ci} 346ffe3c632Sopenharmony_ci 347ffe3c632Sopenharmony_cibool Reader::readValue() { 348ffe3c632Sopenharmony_ci // This is a non-reentrant way to support a stackLimit. Terrible! 349ffe3c632Sopenharmony_ci // But this deprecated class has a security problem: Bad input can 350ffe3c632Sopenharmony_ci // cause a seg-fault. This seems like a fair, binary-compatible way 351ffe3c632Sopenharmony_ci // to prevent the problem. 352ffe3c632Sopenharmony_ci if (stackDepth_g >= stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue()."); 353ffe3c632Sopenharmony_ci ++stackDepth_g; 354ffe3c632Sopenharmony_ci 355ffe3c632Sopenharmony_ci Token token; 356ffe3c632Sopenharmony_ci skipCommentTokens(token); 357ffe3c632Sopenharmony_ci bool successful = true; 358ffe3c632Sopenharmony_ci 359ffe3c632Sopenharmony_ci if (collectComments_ && !commentsBefore_.empty()) { 360ffe3c632Sopenharmony_ci currentValue().setComment(commentsBefore_, commentBefore); 361ffe3c632Sopenharmony_ci commentsBefore_ = ""; 362ffe3c632Sopenharmony_ci } 363ffe3c632Sopenharmony_ci 364ffe3c632Sopenharmony_ci switch (token.type_) { 365ffe3c632Sopenharmony_ci case tokenObjectBegin: 366ffe3c632Sopenharmony_ci successful = readObject(token); 367ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(current_ - begin_); 368ffe3c632Sopenharmony_ci break; 369ffe3c632Sopenharmony_ci case tokenArrayBegin: 370ffe3c632Sopenharmony_ci successful = readArray(token); 371ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(current_ - begin_); 372ffe3c632Sopenharmony_ci break; 373ffe3c632Sopenharmony_ci case tokenNumber: 374ffe3c632Sopenharmony_ci successful = decodeNumber(token); 375ffe3c632Sopenharmony_ci break; 376ffe3c632Sopenharmony_ci case tokenString: 377ffe3c632Sopenharmony_ci successful = decodeString(token); 378ffe3c632Sopenharmony_ci break; 379ffe3c632Sopenharmony_ci case tokenTrue: 380ffe3c632Sopenharmony_ci { 381ffe3c632Sopenharmony_ci Value v(true); 382ffe3c632Sopenharmony_ci currentValue().swapPayload(v); 383ffe3c632Sopenharmony_ci currentValue().setOffsetStart(token.start_ - begin_); 384ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(token.end_ - begin_); 385ffe3c632Sopenharmony_ci } 386ffe3c632Sopenharmony_ci break; 387ffe3c632Sopenharmony_ci case tokenFalse: 388ffe3c632Sopenharmony_ci { 389ffe3c632Sopenharmony_ci Value v(false); 390ffe3c632Sopenharmony_ci currentValue().swapPayload(v); 391ffe3c632Sopenharmony_ci currentValue().setOffsetStart(token.start_ - begin_); 392ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(token.end_ - begin_); 393ffe3c632Sopenharmony_ci } 394ffe3c632Sopenharmony_ci break; 395ffe3c632Sopenharmony_ci case tokenNull: 396ffe3c632Sopenharmony_ci { 397ffe3c632Sopenharmony_ci Value v; 398ffe3c632Sopenharmony_ci currentValue().swapPayload(v); 399ffe3c632Sopenharmony_ci currentValue().setOffsetStart(token.start_ - begin_); 400ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(token.end_ - begin_); 401ffe3c632Sopenharmony_ci } 402ffe3c632Sopenharmony_ci break; 403ffe3c632Sopenharmony_ci case tokenArraySeparator: 404ffe3c632Sopenharmony_ci case tokenObjectEnd: 405ffe3c632Sopenharmony_ci case tokenArrayEnd: 406ffe3c632Sopenharmony_ci if (features_.allowDroppedNullPlaceholders_) { 407ffe3c632Sopenharmony_ci // "Un-read" the current token and mark the current value as a null 408ffe3c632Sopenharmony_ci // token. 409ffe3c632Sopenharmony_ci current_--; 410ffe3c632Sopenharmony_ci Value v; 411ffe3c632Sopenharmony_ci currentValue().swapPayload(v); 412ffe3c632Sopenharmony_ci currentValue().setOffsetStart(current_ - begin_ - 1); 413ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(current_ - begin_); 414ffe3c632Sopenharmony_ci break; 415ffe3c632Sopenharmony_ci } // Else, fall through... 416ffe3c632Sopenharmony_ci default: 417ffe3c632Sopenharmony_ci currentValue().setOffsetStart(token.start_ - begin_); 418ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(token.end_ - begin_); 419ffe3c632Sopenharmony_ci return addError("Syntax error: value, object or array expected.", token); 420ffe3c632Sopenharmony_ci } 421ffe3c632Sopenharmony_ci 422ffe3c632Sopenharmony_ci if (collectComments_) { 423ffe3c632Sopenharmony_ci lastValueEnd_ = current_; 424ffe3c632Sopenharmony_ci lastValue_ = ¤tValue(); 425ffe3c632Sopenharmony_ci } 426ffe3c632Sopenharmony_ci 427ffe3c632Sopenharmony_ci --stackDepth_g; 428ffe3c632Sopenharmony_ci return successful; 429ffe3c632Sopenharmony_ci} 430ffe3c632Sopenharmony_ci 431ffe3c632Sopenharmony_civoid Reader::skipCommentTokens(Token& token) { 432ffe3c632Sopenharmony_ci if (features_.allowComments_) { 433ffe3c632Sopenharmony_ci do { 434ffe3c632Sopenharmony_ci readToken(token); 435ffe3c632Sopenharmony_ci } while (token.type_ == tokenComment); 436ffe3c632Sopenharmony_ci } else { 437ffe3c632Sopenharmony_ci readToken(token); 438ffe3c632Sopenharmony_ci } 439ffe3c632Sopenharmony_ci} 440ffe3c632Sopenharmony_ci 441ffe3c632Sopenharmony_cibool Reader::readToken(Token& token) { 442ffe3c632Sopenharmony_ci skipSpaces(); 443ffe3c632Sopenharmony_ci token.start_ = current_; 444ffe3c632Sopenharmony_ci Char c = getNextChar(); 445ffe3c632Sopenharmony_ci bool ok = true; 446ffe3c632Sopenharmony_ci switch (c) { 447ffe3c632Sopenharmony_ci case '{': 448ffe3c632Sopenharmony_ci token.type_ = tokenObjectBegin; 449ffe3c632Sopenharmony_ci break; 450ffe3c632Sopenharmony_ci case '}': 451ffe3c632Sopenharmony_ci token.type_ = tokenObjectEnd; 452ffe3c632Sopenharmony_ci break; 453ffe3c632Sopenharmony_ci case '[': 454ffe3c632Sopenharmony_ci token.type_ = tokenArrayBegin; 455ffe3c632Sopenharmony_ci break; 456ffe3c632Sopenharmony_ci case ']': 457ffe3c632Sopenharmony_ci token.type_ = tokenArrayEnd; 458ffe3c632Sopenharmony_ci break; 459ffe3c632Sopenharmony_ci case '"': 460ffe3c632Sopenharmony_ci token.type_ = tokenString; 461ffe3c632Sopenharmony_ci ok = readString(); 462ffe3c632Sopenharmony_ci break; 463ffe3c632Sopenharmony_ci case '/': 464ffe3c632Sopenharmony_ci token.type_ = tokenComment; 465ffe3c632Sopenharmony_ci ok = readComment(); 466ffe3c632Sopenharmony_ci break; 467ffe3c632Sopenharmony_ci case '0': 468ffe3c632Sopenharmony_ci case '1': 469ffe3c632Sopenharmony_ci case '2': 470ffe3c632Sopenharmony_ci case '3': 471ffe3c632Sopenharmony_ci case '4': 472ffe3c632Sopenharmony_ci case '5': 473ffe3c632Sopenharmony_ci case '6': 474ffe3c632Sopenharmony_ci case '7': 475ffe3c632Sopenharmony_ci case '8': 476ffe3c632Sopenharmony_ci case '9': 477ffe3c632Sopenharmony_ci case '-': 478ffe3c632Sopenharmony_ci token.type_ = tokenNumber; 479ffe3c632Sopenharmony_ci readNumber(); 480ffe3c632Sopenharmony_ci break; 481ffe3c632Sopenharmony_ci case 't': 482ffe3c632Sopenharmony_ci token.type_ = tokenTrue; 483ffe3c632Sopenharmony_ci ok = match("rue", 3); 484ffe3c632Sopenharmony_ci break; 485ffe3c632Sopenharmony_ci case 'f': 486ffe3c632Sopenharmony_ci token.type_ = tokenFalse; 487ffe3c632Sopenharmony_ci ok = match("alse", 4); 488ffe3c632Sopenharmony_ci break; 489ffe3c632Sopenharmony_ci case 'n': 490ffe3c632Sopenharmony_ci token.type_ = tokenNull; 491ffe3c632Sopenharmony_ci ok = match("ull", 3); 492ffe3c632Sopenharmony_ci break; 493ffe3c632Sopenharmony_ci case ',': 494ffe3c632Sopenharmony_ci token.type_ = tokenArraySeparator; 495ffe3c632Sopenharmony_ci break; 496ffe3c632Sopenharmony_ci case ':': 497ffe3c632Sopenharmony_ci token.type_ = tokenMemberSeparator; 498ffe3c632Sopenharmony_ci break; 499ffe3c632Sopenharmony_ci case 0: 500ffe3c632Sopenharmony_ci token.type_ = tokenEndOfStream; 501ffe3c632Sopenharmony_ci break; 502ffe3c632Sopenharmony_ci default: 503ffe3c632Sopenharmony_ci ok = false; 504ffe3c632Sopenharmony_ci break; 505ffe3c632Sopenharmony_ci } 506ffe3c632Sopenharmony_ci if (!ok) 507ffe3c632Sopenharmony_ci token.type_ = tokenError; 508ffe3c632Sopenharmony_ci token.end_ = current_; 509ffe3c632Sopenharmony_ci return true; 510ffe3c632Sopenharmony_ci} 511ffe3c632Sopenharmony_ci 512ffe3c632Sopenharmony_civoid Reader::skipSpaces() { 513ffe3c632Sopenharmony_ci while (current_ != end_) { 514ffe3c632Sopenharmony_ci Char c = *current_; 515ffe3c632Sopenharmony_ci if (c == ' ' || c == '\t' || c == '\r' || c == '\n') 516ffe3c632Sopenharmony_ci ++current_; 517ffe3c632Sopenharmony_ci else 518ffe3c632Sopenharmony_ci break; 519ffe3c632Sopenharmony_ci } 520ffe3c632Sopenharmony_ci} 521ffe3c632Sopenharmony_ci 522ffe3c632Sopenharmony_cibool Reader::match(Location pattern, int patternLength) { 523ffe3c632Sopenharmony_ci if (end_ - current_ < patternLength) 524ffe3c632Sopenharmony_ci return false; 525ffe3c632Sopenharmony_ci int index = patternLength; 526ffe3c632Sopenharmony_ci while (index--) 527ffe3c632Sopenharmony_ci if (current_[index] != pattern[index]) 528ffe3c632Sopenharmony_ci return false; 529ffe3c632Sopenharmony_ci current_ += patternLength; 530ffe3c632Sopenharmony_ci return true; 531ffe3c632Sopenharmony_ci} 532ffe3c632Sopenharmony_ci 533ffe3c632Sopenharmony_cibool Reader::readComment() { 534ffe3c632Sopenharmony_ci Location commentBegin = current_ - 1; 535ffe3c632Sopenharmony_ci Char c = getNextChar(); 536ffe3c632Sopenharmony_ci bool successful = false; 537ffe3c632Sopenharmony_ci if (c == '*') 538ffe3c632Sopenharmony_ci successful = readCStyleComment(); 539ffe3c632Sopenharmony_ci else if (c == '/') 540ffe3c632Sopenharmony_ci successful = readCppStyleComment(); 541ffe3c632Sopenharmony_ci if (!successful) 542ffe3c632Sopenharmony_ci return false; 543ffe3c632Sopenharmony_ci 544ffe3c632Sopenharmony_ci if (collectComments_) { 545ffe3c632Sopenharmony_ci CommentPlacement placement = commentBefore; 546ffe3c632Sopenharmony_ci if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { 547ffe3c632Sopenharmony_ci if (c != '*' || !containsNewLine(commentBegin, current_)) 548ffe3c632Sopenharmony_ci placement = commentAfterOnSameLine; 549ffe3c632Sopenharmony_ci } 550ffe3c632Sopenharmony_ci 551ffe3c632Sopenharmony_ci addComment(commentBegin, current_, placement); 552ffe3c632Sopenharmony_ci } 553ffe3c632Sopenharmony_ci return true; 554ffe3c632Sopenharmony_ci} 555ffe3c632Sopenharmony_ci 556ffe3c632Sopenharmony_cistatic std::string normalizeEOL(Reader::Location begin, Reader::Location end) { 557ffe3c632Sopenharmony_ci std::string normalized; 558ffe3c632Sopenharmony_ci normalized.reserve(end - begin); 559ffe3c632Sopenharmony_ci Reader::Location current = begin; 560ffe3c632Sopenharmony_ci while (current != end) { 561ffe3c632Sopenharmony_ci char c = *current++; 562ffe3c632Sopenharmony_ci if (c == '\r') { 563ffe3c632Sopenharmony_ci if (current != end && *current == '\n') 564ffe3c632Sopenharmony_ci // convert dos EOL 565ffe3c632Sopenharmony_ci ++current; 566ffe3c632Sopenharmony_ci // convert Mac EOL 567ffe3c632Sopenharmony_ci normalized += '\n'; 568ffe3c632Sopenharmony_ci } else { 569ffe3c632Sopenharmony_ci normalized += c; 570ffe3c632Sopenharmony_ci } 571ffe3c632Sopenharmony_ci } 572ffe3c632Sopenharmony_ci return normalized; 573ffe3c632Sopenharmony_ci} 574ffe3c632Sopenharmony_ci 575ffe3c632Sopenharmony_civoid 576ffe3c632Sopenharmony_ciReader::addComment(Location begin, Location end, CommentPlacement placement) { 577ffe3c632Sopenharmony_ci assert(collectComments_); 578ffe3c632Sopenharmony_ci const std::string& normalized = normalizeEOL(begin, end); 579ffe3c632Sopenharmony_ci if (placement == commentAfterOnSameLine) { 580ffe3c632Sopenharmony_ci assert(lastValue_ != 0); 581ffe3c632Sopenharmony_ci lastValue_->setComment(normalized, placement); 582ffe3c632Sopenharmony_ci } else { 583ffe3c632Sopenharmony_ci commentsBefore_ += normalized; 584ffe3c632Sopenharmony_ci } 585ffe3c632Sopenharmony_ci} 586ffe3c632Sopenharmony_ci 587ffe3c632Sopenharmony_cibool Reader::readCStyleComment() { 588ffe3c632Sopenharmony_ci while (current_ != end_) { 589ffe3c632Sopenharmony_ci Char c = getNextChar(); 590ffe3c632Sopenharmony_ci if (c == '*' && *current_ == '/') 591ffe3c632Sopenharmony_ci break; 592ffe3c632Sopenharmony_ci } 593ffe3c632Sopenharmony_ci return getNextChar() == '/'; 594ffe3c632Sopenharmony_ci} 595ffe3c632Sopenharmony_ci 596ffe3c632Sopenharmony_cibool Reader::readCppStyleComment() { 597ffe3c632Sopenharmony_ci while (current_ != end_) { 598ffe3c632Sopenharmony_ci Char c = getNextChar(); 599ffe3c632Sopenharmony_ci if (c == '\n') 600ffe3c632Sopenharmony_ci break; 601ffe3c632Sopenharmony_ci if (c == '\r') { 602ffe3c632Sopenharmony_ci // Consume DOS EOL. It will be normalized in addComment. 603ffe3c632Sopenharmony_ci if (current_ != end_ && *current_ == '\n') 604ffe3c632Sopenharmony_ci getNextChar(); 605ffe3c632Sopenharmony_ci // Break on Moc OS 9 EOL. 606ffe3c632Sopenharmony_ci break; 607ffe3c632Sopenharmony_ci } 608ffe3c632Sopenharmony_ci } 609ffe3c632Sopenharmony_ci return true; 610ffe3c632Sopenharmony_ci} 611ffe3c632Sopenharmony_ci 612ffe3c632Sopenharmony_civoid Reader::readNumber() { 613ffe3c632Sopenharmony_ci const char *p = current_; 614ffe3c632Sopenharmony_ci char c = '0'; // stopgap for already consumed character 615ffe3c632Sopenharmony_ci // integral part 616ffe3c632Sopenharmony_ci while (c >= '0' && c <= '9') 617ffe3c632Sopenharmony_ci c = (current_ = p) < end_ ? *p++ : 0; 618ffe3c632Sopenharmony_ci // fractional part 619ffe3c632Sopenharmony_ci if (c == '.') { 620ffe3c632Sopenharmony_ci c = (current_ = p) < end_ ? *p++ : 0; 621ffe3c632Sopenharmony_ci while (c >= '0' && c <= '9') 622ffe3c632Sopenharmony_ci c = (current_ = p) < end_ ? *p++ : 0; 623ffe3c632Sopenharmony_ci } 624ffe3c632Sopenharmony_ci // exponential part 625ffe3c632Sopenharmony_ci if (c == 'e' || c == 'E') { 626ffe3c632Sopenharmony_ci c = (current_ = p) < end_ ? *p++ : 0; 627ffe3c632Sopenharmony_ci if (c == '+' || c == '-') 628ffe3c632Sopenharmony_ci c = (current_ = p) < end_ ? *p++ : 0; 629ffe3c632Sopenharmony_ci while (c >= '0' && c <= '9') 630ffe3c632Sopenharmony_ci c = (current_ = p) < end_ ? *p++ : 0; 631ffe3c632Sopenharmony_ci } 632ffe3c632Sopenharmony_ci} 633ffe3c632Sopenharmony_ci 634ffe3c632Sopenharmony_cibool Reader::readString() { 635ffe3c632Sopenharmony_ci Char c = 0; 636ffe3c632Sopenharmony_ci while (current_ != end_) { 637ffe3c632Sopenharmony_ci c = getNextChar(); 638ffe3c632Sopenharmony_ci if (c == '\\') 639ffe3c632Sopenharmony_ci getNextChar(); 640ffe3c632Sopenharmony_ci else if (c == '"') 641ffe3c632Sopenharmony_ci break; 642ffe3c632Sopenharmony_ci } 643ffe3c632Sopenharmony_ci return c == '"'; 644ffe3c632Sopenharmony_ci} 645ffe3c632Sopenharmony_ci 646ffe3c632Sopenharmony_cibool Reader::readObject(Token& tokenStart) { 647ffe3c632Sopenharmony_ci Token tokenName; 648ffe3c632Sopenharmony_ci std::string name; 649ffe3c632Sopenharmony_ci Value init(objectValue); 650ffe3c632Sopenharmony_ci currentValue().swapPayload(init); 651ffe3c632Sopenharmony_ci currentValue().setOffsetStart(tokenStart.start_ - begin_); 652ffe3c632Sopenharmony_ci while (readToken(tokenName)) { 653ffe3c632Sopenharmony_ci bool initialTokenOk = true; 654ffe3c632Sopenharmony_ci while (tokenName.type_ == tokenComment && initialTokenOk) 655ffe3c632Sopenharmony_ci initialTokenOk = readToken(tokenName); 656ffe3c632Sopenharmony_ci if (!initialTokenOk) 657ffe3c632Sopenharmony_ci break; 658ffe3c632Sopenharmony_ci if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object 659ffe3c632Sopenharmony_ci return true; 660ffe3c632Sopenharmony_ci name = ""; 661ffe3c632Sopenharmony_ci if (tokenName.type_ == tokenString) { 662ffe3c632Sopenharmony_ci if (!decodeString(tokenName, name)) 663ffe3c632Sopenharmony_ci return recoverFromError(tokenObjectEnd); 664ffe3c632Sopenharmony_ci } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { 665ffe3c632Sopenharmony_ci Value numberName; 666ffe3c632Sopenharmony_ci if (!decodeNumber(tokenName, numberName)) 667ffe3c632Sopenharmony_ci return recoverFromError(tokenObjectEnd); 668ffe3c632Sopenharmony_ci name = numberName.asString(); 669ffe3c632Sopenharmony_ci } else { 670ffe3c632Sopenharmony_ci break; 671ffe3c632Sopenharmony_ci } 672ffe3c632Sopenharmony_ci 673ffe3c632Sopenharmony_ci Token colon; 674ffe3c632Sopenharmony_ci if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { 675ffe3c632Sopenharmony_ci return addErrorAndRecover( 676ffe3c632Sopenharmony_ci "Missing ':' after object member name", colon, tokenObjectEnd); 677ffe3c632Sopenharmony_ci } 678ffe3c632Sopenharmony_ci Value& value = currentValue()[name]; 679ffe3c632Sopenharmony_ci nodes_.push(&value); 680ffe3c632Sopenharmony_ci bool ok = readValue(); 681ffe3c632Sopenharmony_ci nodes_.pop(); 682ffe3c632Sopenharmony_ci if (!ok) // error already set 683ffe3c632Sopenharmony_ci return recoverFromError(tokenObjectEnd); 684ffe3c632Sopenharmony_ci 685ffe3c632Sopenharmony_ci Token comma; 686ffe3c632Sopenharmony_ci if (!readToken(comma) || 687ffe3c632Sopenharmony_ci (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && 688ffe3c632Sopenharmony_ci comma.type_ != tokenComment)) { 689ffe3c632Sopenharmony_ci return addErrorAndRecover( 690ffe3c632Sopenharmony_ci "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); 691ffe3c632Sopenharmony_ci } 692ffe3c632Sopenharmony_ci bool finalizeTokenOk = true; 693ffe3c632Sopenharmony_ci while (comma.type_ == tokenComment && finalizeTokenOk) 694ffe3c632Sopenharmony_ci finalizeTokenOk = readToken(comma); 695ffe3c632Sopenharmony_ci if (comma.type_ == tokenObjectEnd) 696ffe3c632Sopenharmony_ci return true; 697ffe3c632Sopenharmony_ci } 698ffe3c632Sopenharmony_ci return addErrorAndRecover( 699ffe3c632Sopenharmony_ci "Missing '}' or object member name", tokenName, tokenObjectEnd); 700ffe3c632Sopenharmony_ci} 701ffe3c632Sopenharmony_ci 702ffe3c632Sopenharmony_cibool Reader::readArray(Token& tokenStart) { 703ffe3c632Sopenharmony_ci Value init(arrayValue); 704ffe3c632Sopenharmony_ci currentValue().swapPayload(init); 705ffe3c632Sopenharmony_ci currentValue().setOffsetStart(tokenStart.start_ - begin_); 706ffe3c632Sopenharmony_ci skipSpaces(); 707ffe3c632Sopenharmony_ci if (*current_ == ']') // empty array 708ffe3c632Sopenharmony_ci { 709ffe3c632Sopenharmony_ci Token endArray; 710ffe3c632Sopenharmony_ci readToken(endArray); 711ffe3c632Sopenharmony_ci return true; 712ffe3c632Sopenharmony_ci } 713ffe3c632Sopenharmony_ci int index = 0; 714ffe3c632Sopenharmony_ci for (;;) { 715ffe3c632Sopenharmony_ci Value& value = currentValue()[index++]; 716ffe3c632Sopenharmony_ci nodes_.push(&value); 717ffe3c632Sopenharmony_ci bool ok = readValue(); 718ffe3c632Sopenharmony_ci nodes_.pop(); 719ffe3c632Sopenharmony_ci if (!ok) // error already set 720ffe3c632Sopenharmony_ci return recoverFromError(tokenArrayEnd); 721ffe3c632Sopenharmony_ci 722ffe3c632Sopenharmony_ci Token token; 723ffe3c632Sopenharmony_ci // Accept Comment after last item in the array. 724ffe3c632Sopenharmony_ci ok = readToken(token); 725ffe3c632Sopenharmony_ci while (token.type_ == tokenComment && ok) { 726ffe3c632Sopenharmony_ci ok = readToken(token); 727ffe3c632Sopenharmony_ci } 728ffe3c632Sopenharmony_ci bool badTokenType = 729ffe3c632Sopenharmony_ci (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); 730ffe3c632Sopenharmony_ci if (!ok || badTokenType) { 731ffe3c632Sopenharmony_ci return addErrorAndRecover( 732ffe3c632Sopenharmony_ci "Missing ',' or ']' in array declaration", token, tokenArrayEnd); 733ffe3c632Sopenharmony_ci } 734ffe3c632Sopenharmony_ci if (token.type_ == tokenArrayEnd) 735ffe3c632Sopenharmony_ci break; 736ffe3c632Sopenharmony_ci } 737ffe3c632Sopenharmony_ci return true; 738ffe3c632Sopenharmony_ci} 739ffe3c632Sopenharmony_ci 740ffe3c632Sopenharmony_cibool Reader::decodeNumber(Token& token) { 741ffe3c632Sopenharmony_ci Value decoded; 742ffe3c632Sopenharmony_ci if (!decodeNumber(token, decoded)) 743ffe3c632Sopenharmony_ci return false; 744ffe3c632Sopenharmony_ci currentValue().swapPayload(decoded); 745ffe3c632Sopenharmony_ci currentValue().setOffsetStart(token.start_ - begin_); 746ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(token.end_ - begin_); 747ffe3c632Sopenharmony_ci return true; 748ffe3c632Sopenharmony_ci} 749ffe3c632Sopenharmony_ci 750ffe3c632Sopenharmony_cibool Reader::decodeNumber(Token& token, Value& decoded) { 751ffe3c632Sopenharmony_ci // Attempts to parse the number as an integer. If the number is 752ffe3c632Sopenharmony_ci // larger than the maximum supported value of an integer then 753ffe3c632Sopenharmony_ci // we decode the number as a double. 754ffe3c632Sopenharmony_ci Location current = token.start_; 755ffe3c632Sopenharmony_ci bool isNegative = *current == '-'; 756ffe3c632Sopenharmony_ci if (isNegative) 757ffe3c632Sopenharmony_ci ++current; 758ffe3c632Sopenharmony_ci // TODO: Help the compiler do the div and mod at compile time or get rid of them. 759ffe3c632Sopenharmony_ci Value::LargestUInt maxIntegerValue = 760ffe3c632Sopenharmony_ci isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1 761ffe3c632Sopenharmony_ci : Value::maxLargestUInt; 762ffe3c632Sopenharmony_ci Value::LargestUInt threshold = maxIntegerValue / 10; 763ffe3c632Sopenharmony_ci Value::LargestUInt value = 0; 764ffe3c632Sopenharmony_ci while (current < token.end_) { 765ffe3c632Sopenharmony_ci Char c = *current++; 766ffe3c632Sopenharmony_ci if (c < '0' || c > '9') 767ffe3c632Sopenharmony_ci return decodeDouble(token, decoded); 768ffe3c632Sopenharmony_ci Value::UInt digit(c - '0'); 769ffe3c632Sopenharmony_ci if (value >= threshold) { 770ffe3c632Sopenharmony_ci // We've hit or exceeded the max value divided by 10 (rounded down). If 771ffe3c632Sopenharmony_ci // a) we've only just touched the limit, b) this is the last digit, and 772ffe3c632Sopenharmony_ci // c) it's small enough to fit in that rounding delta, we're okay. 773ffe3c632Sopenharmony_ci // Otherwise treat this number as a double to avoid overflow. 774ffe3c632Sopenharmony_ci if (value > threshold || current != token.end_ || 775ffe3c632Sopenharmony_ci digit > maxIntegerValue % 10) { 776ffe3c632Sopenharmony_ci return decodeDouble(token, decoded); 777ffe3c632Sopenharmony_ci } 778ffe3c632Sopenharmony_ci } 779ffe3c632Sopenharmony_ci value = value * 10 + digit; 780ffe3c632Sopenharmony_ci } 781ffe3c632Sopenharmony_ci if (isNegative && value == maxIntegerValue) 782ffe3c632Sopenharmony_ci decoded = Value::minLargestInt; 783ffe3c632Sopenharmony_ci else if (isNegative) 784ffe3c632Sopenharmony_ci decoded = -Value::LargestInt(value); 785ffe3c632Sopenharmony_ci else if (value <= Value::LargestUInt(Value::maxInt)) 786ffe3c632Sopenharmony_ci decoded = Value::LargestInt(value); 787ffe3c632Sopenharmony_ci else 788ffe3c632Sopenharmony_ci decoded = value; 789ffe3c632Sopenharmony_ci return true; 790ffe3c632Sopenharmony_ci} 791ffe3c632Sopenharmony_ci 792ffe3c632Sopenharmony_cibool Reader::decodeDouble(Token& token) { 793ffe3c632Sopenharmony_ci Value decoded; 794ffe3c632Sopenharmony_ci if (!decodeDouble(token, decoded)) 795ffe3c632Sopenharmony_ci return false; 796ffe3c632Sopenharmony_ci currentValue().swapPayload(decoded); 797ffe3c632Sopenharmony_ci currentValue().setOffsetStart(token.start_ - begin_); 798ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(token.end_ - begin_); 799ffe3c632Sopenharmony_ci return true; 800ffe3c632Sopenharmony_ci} 801ffe3c632Sopenharmony_ci 802ffe3c632Sopenharmony_cibool Reader::decodeDouble(Token& token, Value& decoded) { 803ffe3c632Sopenharmony_ci double value = 0; 804ffe3c632Sopenharmony_ci std::string buffer(token.start_, token.end_); 805ffe3c632Sopenharmony_ci std::istringstream is(buffer); 806ffe3c632Sopenharmony_ci if (!(is >> value)) 807ffe3c632Sopenharmony_ci return addError("'" + std::string(token.start_, token.end_) + 808ffe3c632Sopenharmony_ci "' is not a number.", 809ffe3c632Sopenharmony_ci token); 810ffe3c632Sopenharmony_ci decoded = value; 811ffe3c632Sopenharmony_ci return true; 812ffe3c632Sopenharmony_ci} 813ffe3c632Sopenharmony_ci 814ffe3c632Sopenharmony_cibool Reader::decodeString(Token& token) { 815ffe3c632Sopenharmony_ci std::string decoded_string; 816ffe3c632Sopenharmony_ci if (!decodeString(token, decoded_string)) 817ffe3c632Sopenharmony_ci return false; 818ffe3c632Sopenharmony_ci Value decoded(decoded_string); 819ffe3c632Sopenharmony_ci currentValue().swapPayload(decoded); 820ffe3c632Sopenharmony_ci currentValue().setOffsetStart(token.start_ - begin_); 821ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(token.end_ - begin_); 822ffe3c632Sopenharmony_ci return true; 823ffe3c632Sopenharmony_ci} 824ffe3c632Sopenharmony_ci 825ffe3c632Sopenharmony_cibool Reader::decodeString(Token& token, std::string& decoded) { 826ffe3c632Sopenharmony_ci decoded.reserve(token.end_ - token.start_ - 2); 827ffe3c632Sopenharmony_ci Location current = token.start_ + 1; // skip '"' 828ffe3c632Sopenharmony_ci Location end = token.end_ - 1; // do not include '"' 829ffe3c632Sopenharmony_ci while (current != end) { 830ffe3c632Sopenharmony_ci Char c = *current++; 831ffe3c632Sopenharmony_ci if (c == '"') 832ffe3c632Sopenharmony_ci break; 833ffe3c632Sopenharmony_ci else if (c == '\\') { 834ffe3c632Sopenharmony_ci if (current == end) 835ffe3c632Sopenharmony_ci return addError("Empty escape sequence in string", token, current); 836ffe3c632Sopenharmony_ci Char escape = *current++; 837ffe3c632Sopenharmony_ci switch (escape) { 838ffe3c632Sopenharmony_ci case '"': 839ffe3c632Sopenharmony_ci decoded += '"'; 840ffe3c632Sopenharmony_ci break; 841ffe3c632Sopenharmony_ci case '/': 842ffe3c632Sopenharmony_ci decoded += '/'; 843ffe3c632Sopenharmony_ci break; 844ffe3c632Sopenharmony_ci case '\\': 845ffe3c632Sopenharmony_ci decoded += '\\'; 846ffe3c632Sopenharmony_ci break; 847ffe3c632Sopenharmony_ci case 'b': 848ffe3c632Sopenharmony_ci decoded += '\b'; 849ffe3c632Sopenharmony_ci break; 850ffe3c632Sopenharmony_ci case 'f': 851ffe3c632Sopenharmony_ci decoded += '\f'; 852ffe3c632Sopenharmony_ci break; 853ffe3c632Sopenharmony_ci case 'n': 854ffe3c632Sopenharmony_ci decoded += '\n'; 855ffe3c632Sopenharmony_ci break; 856ffe3c632Sopenharmony_ci case 'r': 857ffe3c632Sopenharmony_ci decoded += '\r'; 858ffe3c632Sopenharmony_ci break; 859ffe3c632Sopenharmony_ci case 't': 860ffe3c632Sopenharmony_ci decoded += '\t'; 861ffe3c632Sopenharmony_ci break; 862ffe3c632Sopenharmony_ci case 'u': { 863ffe3c632Sopenharmony_ci unsigned int unicode; 864ffe3c632Sopenharmony_ci if (!decodeUnicodeCodePoint(token, current, end, unicode)) 865ffe3c632Sopenharmony_ci return false; 866ffe3c632Sopenharmony_ci decoded += codePointToUTF8(unicode); 867ffe3c632Sopenharmony_ci } break; 868ffe3c632Sopenharmony_ci default: 869ffe3c632Sopenharmony_ci return addError("Bad escape sequence in string", token, current); 870ffe3c632Sopenharmony_ci } 871ffe3c632Sopenharmony_ci } else { 872ffe3c632Sopenharmony_ci decoded += c; 873ffe3c632Sopenharmony_ci } 874ffe3c632Sopenharmony_ci } 875ffe3c632Sopenharmony_ci return true; 876ffe3c632Sopenharmony_ci} 877ffe3c632Sopenharmony_ci 878ffe3c632Sopenharmony_cibool Reader::decodeUnicodeCodePoint(Token& token, 879ffe3c632Sopenharmony_ci Location& current, 880ffe3c632Sopenharmony_ci Location end, 881ffe3c632Sopenharmony_ci unsigned int& unicode) { 882ffe3c632Sopenharmony_ci 883ffe3c632Sopenharmony_ci if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) 884ffe3c632Sopenharmony_ci return false; 885ffe3c632Sopenharmony_ci if (unicode >= 0xD800 && unicode <= 0xDBFF) { 886ffe3c632Sopenharmony_ci // surrogate pairs 887ffe3c632Sopenharmony_ci if (end - current < 6) 888ffe3c632Sopenharmony_ci return addError( 889ffe3c632Sopenharmony_ci "additional six characters expected to parse unicode surrogate pair.", 890ffe3c632Sopenharmony_ci token, 891ffe3c632Sopenharmony_ci current); 892ffe3c632Sopenharmony_ci unsigned int surrogatePair; 893ffe3c632Sopenharmony_ci if (*(current++) == '\\' && *(current++) == 'u') { 894ffe3c632Sopenharmony_ci if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { 895ffe3c632Sopenharmony_ci unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); 896ffe3c632Sopenharmony_ci } else 897ffe3c632Sopenharmony_ci return false; 898ffe3c632Sopenharmony_ci } else 899ffe3c632Sopenharmony_ci return addError("expecting another \\u token to begin the second half of " 900ffe3c632Sopenharmony_ci "a unicode surrogate pair", 901ffe3c632Sopenharmony_ci token, 902ffe3c632Sopenharmony_ci current); 903ffe3c632Sopenharmony_ci } 904ffe3c632Sopenharmony_ci return true; 905ffe3c632Sopenharmony_ci} 906ffe3c632Sopenharmony_ci 907ffe3c632Sopenharmony_cibool Reader::decodeUnicodeEscapeSequence(Token& token, 908ffe3c632Sopenharmony_ci Location& current, 909ffe3c632Sopenharmony_ci Location end, 910ffe3c632Sopenharmony_ci unsigned int& unicode) { 911ffe3c632Sopenharmony_ci if (end - current < 4) 912ffe3c632Sopenharmony_ci return addError( 913ffe3c632Sopenharmony_ci "Bad unicode escape sequence in string: four digits expected.", 914ffe3c632Sopenharmony_ci token, 915ffe3c632Sopenharmony_ci current); 916ffe3c632Sopenharmony_ci unicode = 0; 917ffe3c632Sopenharmony_ci for (int index = 0; index < 4; ++index) { 918ffe3c632Sopenharmony_ci Char c = *current++; 919ffe3c632Sopenharmony_ci unicode *= 16; 920ffe3c632Sopenharmony_ci if (c >= '0' && c <= '9') 921ffe3c632Sopenharmony_ci unicode += c - '0'; 922ffe3c632Sopenharmony_ci else if (c >= 'a' && c <= 'f') 923ffe3c632Sopenharmony_ci unicode += c - 'a' + 10; 924ffe3c632Sopenharmony_ci else if (c >= 'A' && c <= 'F') 925ffe3c632Sopenharmony_ci unicode += c - 'A' + 10; 926ffe3c632Sopenharmony_ci else 927ffe3c632Sopenharmony_ci return addError( 928ffe3c632Sopenharmony_ci "Bad unicode escape sequence in string: hexadecimal digit expected.", 929ffe3c632Sopenharmony_ci token, 930ffe3c632Sopenharmony_ci current); 931ffe3c632Sopenharmony_ci } 932ffe3c632Sopenharmony_ci return true; 933ffe3c632Sopenharmony_ci} 934ffe3c632Sopenharmony_ci 935ffe3c632Sopenharmony_cibool 936ffe3c632Sopenharmony_ciReader::addError(const std::string& message, Token& token, Location extra) { 937ffe3c632Sopenharmony_ci ErrorInfo info; 938ffe3c632Sopenharmony_ci info.token_ = token; 939ffe3c632Sopenharmony_ci info.message_ = message; 940ffe3c632Sopenharmony_ci info.extra_ = extra; 941ffe3c632Sopenharmony_ci errors_.push_back(info); 942ffe3c632Sopenharmony_ci return false; 943ffe3c632Sopenharmony_ci} 944ffe3c632Sopenharmony_ci 945ffe3c632Sopenharmony_cibool Reader::recoverFromError(TokenType skipUntilToken) { 946ffe3c632Sopenharmony_ci int errorCount = int(errors_.size()); 947ffe3c632Sopenharmony_ci Token skip; 948ffe3c632Sopenharmony_ci for (;;) { 949ffe3c632Sopenharmony_ci if (!readToken(skip)) 950ffe3c632Sopenharmony_ci errors_.resize(errorCount); // discard errors caused by recovery 951ffe3c632Sopenharmony_ci if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) 952ffe3c632Sopenharmony_ci break; 953ffe3c632Sopenharmony_ci } 954ffe3c632Sopenharmony_ci errors_.resize(errorCount); 955ffe3c632Sopenharmony_ci return false; 956ffe3c632Sopenharmony_ci} 957ffe3c632Sopenharmony_ci 958ffe3c632Sopenharmony_cibool Reader::addErrorAndRecover(const std::string& message, 959ffe3c632Sopenharmony_ci Token& token, 960ffe3c632Sopenharmony_ci TokenType skipUntilToken) { 961ffe3c632Sopenharmony_ci addError(message, token); 962ffe3c632Sopenharmony_ci return recoverFromError(skipUntilToken); 963ffe3c632Sopenharmony_ci} 964ffe3c632Sopenharmony_ci 965ffe3c632Sopenharmony_ciValue& Reader::currentValue() { return *(nodes_.top()); } 966ffe3c632Sopenharmony_ci 967ffe3c632Sopenharmony_ciReader::Char Reader::getNextChar() { 968ffe3c632Sopenharmony_ci if (current_ == end_) 969ffe3c632Sopenharmony_ci return 0; 970ffe3c632Sopenharmony_ci return *current_++; 971ffe3c632Sopenharmony_ci} 972ffe3c632Sopenharmony_ci 973ffe3c632Sopenharmony_civoid Reader::getLocationLineAndColumn(Location location, 974ffe3c632Sopenharmony_ci int& line, 975ffe3c632Sopenharmony_ci int& column) const { 976ffe3c632Sopenharmony_ci Location current = begin_; 977ffe3c632Sopenharmony_ci Location lastLineStart = current; 978ffe3c632Sopenharmony_ci line = 0; 979ffe3c632Sopenharmony_ci while (current < location && current != end_) { 980ffe3c632Sopenharmony_ci Char c = *current++; 981ffe3c632Sopenharmony_ci if (c == '\r') { 982ffe3c632Sopenharmony_ci if (*current == '\n') 983ffe3c632Sopenharmony_ci ++current; 984ffe3c632Sopenharmony_ci lastLineStart = current; 985ffe3c632Sopenharmony_ci ++line; 986ffe3c632Sopenharmony_ci } else if (c == '\n') { 987ffe3c632Sopenharmony_ci lastLineStart = current; 988ffe3c632Sopenharmony_ci ++line; 989ffe3c632Sopenharmony_ci } 990ffe3c632Sopenharmony_ci } 991ffe3c632Sopenharmony_ci // column & line start at 1 992ffe3c632Sopenharmony_ci column = int(location - lastLineStart) + 1; 993ffe3c632Sopenharmony_ci ++line; 994ffe3c632Sopenharmony_ci} 995ffe3c632Sopenharmony_ci 996ffe3c632Sopenharmony_cistd::string Reader::getLocationLineAndColumn(Location location) const { 997ffe3c632Sopenharmony_ci int line, column; 998ffe3c632Sopenharmony_ci getLocationLineAndColumn(location, line, column); 999ffe3c632Sopenharmony_ci char buffer[18 + 16 + 16 + 1]; 1000ffe3c632Sopenharmony_ci snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); 1001ffe3c632Sopenharmony_ci return buffer; 1002ffe3c632Sopenharmony_ci} 1003ffe3c632Sopenharmony_ci 1004ffe3c632Sopenharmony_ci// Deprecated. Preserved for backward compatibility 1005ffe3c632Sopenharmony_cistd::string Reader::getFormatedErrorMessages() const { 1006ffe3c632Sopenharmony_ci return getFormattedErrorMessages(); 1007ffe3c632Sopenharmony_ci} 1008ffe3c632Sopenharmony_ci 1009ffe3c632Sopenharmony_cistd::string Reader::getFormattedErrorMessages() const { 1010ffe3c632Sopenharmony_ci std::string formattedMessage; 1011ffe3c632Sopenharmony_ci for (Errors::const_iterator itError = errors_.begin(); 1012ffe3c632Sopenharmony_ci itError != errors_.end(); 1013ffe3c632Sopenharmony_ci ++itError) { 1014ffe3c632Sopenharmony_ci const ErrorInfo& error = *itError; 1015ffe3c632Sopenharmony_ci formattedMessage += 1016ffe3c632Sopenharmony_ci "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; 1017ffe3c632Sopenharmony_ci formattedMessage += " " + error.message_ + "\n"; 1018ffe3c632Sopenharmony_ci if (error.extra_) 1019ffe3c632Sopenharmony_ci formattedMessage += 1020ffe3c632Sopenharmony_ci "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; 1021ffe3c632Sopenharmony_ci } 1022ffe3c632Sopenharmony_ci return formattedMessage; 1023ffe3c632Sopenharmony_ci} 1024ffe3c632Sopenharmony_ci 1025ffe3c632Sopenharmony_cistd::vector<Reader::StructuredError> Reader::getStructuredErrors() const { 1026ffe3c632Sopenharmony_ci std::vector<Reader::StructuredError> allErrors; 1027ffe3c632Sopenharmony_ci for (Errors::const_iterator itError = errors_.begin(); 1028ffe3c632Sopenharmony_ci itError != errors_.end(); 1029ffe3c632Sopenharmony_ci ++itError) { 1030ffe3c632Sopenharmony_ci const ErrorInfo& error = *itError; 1031ffe3c632Sopenharmony_ci Reader::StructuredError structured; 1032ffe3c632Sopenharmony_ci structured.offset_start = error.token_.start_ - begin_; 1033ffe3c632Sopenharmony_ci structured.offset_limit = error.token_.end_ - begin_; 1034ffe3c632Sopenharmony_ci structured.message = error.message_; 1035ffe3c632Sopenharmony_ci allErrors.push_back(structured); 1036ffe3c632Sopenharmony_ci } 1037ffe3c632Sopenharmony_ci return allErrors; 1038ffe3c632Sopenharmony_ci} 1039ffe3c632Sopenharmony_ci 1040ffe3c632Sopenharmony_cibool Reader::pushError(const Value& value, const std::string& message) { 1041ffe3c632Sopenharmony_ci size_t length = end_ - begin_; 1042ffe3c632Sopenharmony_ci if(value.getOffsetStart() > length 1043ffe3c632Sopenharmony_ci || value.getOffsetLimit() > length) 1044ffe3c632Sopenharmony_ci return false; 1045ffe3c632Sopenharmony_ci Token token; 1046ffe3c632Sopenharmony_ci token.type_ = tokenError; 1047ffe3c632Sopenharmony_ci token.start_ = begin_ + value.getOffsetStart(); 1048ffe3c632Sopenharmony_ci token.end_ = end_ + value.getOffsetLimit(); 1049ffe3c632Sopenharmony_ci ErrorInfo info; 1050ffe3c632Sopenharmony_ci info.token_ = token; 1051ffe3c632Sopenharmony_ci info.message_ = message; 1052ffe3c632Sopenharmony_ci info.extra_ = 0; 1053ffe3c632Sopenharmony_ci errors_.push_back(info); 1054ffe3c632Sopenharmony_ci return true; 1055ffe3c632Sopenharmony_ci} 1056ffe3c632Sopenharmony_ci 1057ffe3c632Sopenharmony_cibool Reader::pushError(const Value& value, const std::string& message, const Value& extra) { 1058ffe3c632Sopenharmony_ci size_t length = end_ - begin_; 1059ffe3c632Sopenharmony_ci if(value.getOffsetStart() > length 1060ffe3c632Sopenharmony_ci || value.getOffsetLimit() > length 1061ffe3c632Sopenharmony_ci || extra.getOffsetLimit() > length) 1062ffe3c632Sopenharmony_ci return false; 1063ffe3c632Sopenharmony_ci Token token; 1064ffe3c632Sopenharmony_ci token.type_ = tokenError; 1065ffe3c632Sopenharmony_ci token.start_ = begin_ + value.getOffsetStart(); 1066ffe3c632Sopenharmony_ci token.end_ = begin_ + value.getOffsetLimit(); 1067ffe3c632Sopenharmony_ci ErrorInfo info; 1068ffe3c632Sopenharmony_ci info.token_ = token; 1069ffe3c632Sopenharmony_ci info.message_ = message; 1070ffe3c632Sopenharmony_ci info.extra_ = begin_ + extra.getOffsetStart(); 1071ffe3c632Sopenharmony_ci errors_.push_back(info); 1072ffe3c632Sopenharmony_ci return true; 1073ffe3c632Sopenharmony_ci} 1074ffe3c632Sopenharmony_ci 1075ffe3c632Sopenharmony_cibool Reader::good() const { 1076ffe3c632Sopenharmony_ci return !errors_.size(); 1077ffe3c632Sopenharmony_ci} 1078ffe3c632Sopenharmony_ci 1079ffe3c632Sopenharmony_ci// exact copy of Features 1080ffe3c632Sopenharmony_ciclass OurFeatures { 1081ffe3c632Sopenharmony_cipublic: 1082ffe3c632Sopenharmony_ci static OurFeatures all(); 1083ffe3c632Sopenharmony_ci bool allowComments_; 1084ffe3c632Sopenharmony_ci bool strictRoot_; 1085ffe3c632Sopenharmony_ci bool allowDroppedNullPlaceholders_; 1086ffe3c632Sopenharmony_ci bool allowNumericKeys_; 1087ffe3c632Sopenharmony_ci bool allowSingleQuotes_; 1088ffe3c632Sopenharmony_ci bool failIfExtra_; 1089ffe3c632Sopenharmony_ci bool rejectDupKeys_; 1090ffe3c632Sopenharmony_ci bool allowSpecialFloats_; 1091ffe3c632Sopenharmony_ci int stackLimit_; 1092ffe3c632Sopenharmony_ci}; // OurFeatures 1093ffe3c632Sopenharmony_ci 1094ffe3c632Sopenharmony_ci// exact copy of Implementation of class Features 1095ffe3c632Sopenharmony_ci// //////////////////////////////// 1096ffe3c632Sopenharmony_ci 1097ffe3c632Sopenharmony_ciOurFeatures OurFeatures::all() { return OurFeatures(); } 1098ffe3c632Sopenharmony_ci 1099ffe3c632Sopenharmony_ci// Implementation of class Reader 1100ffe3c632Sopenharmony_ci// //////////////////////////////// 1101ffe3c632Sopenharmony_ci 1102ffe3c632Sopenharmony_ci// exact copy of Reader, renamed to OurReader 1103ffe3c632Sopenharmony_ciclass OurReader { 1104ffe3c632Sopenharmony_cipublic: 1105ffe3c632Sopenharmony_ci typedef char Char; 1106ffe3c632Sopenharmony_ci typedef const Char* Location; 1107ffe3c632Sopenharmony_ci struct StructuredError { 1108ffe3c632Sopenharmony_ci size_t offset_start; 1109ffe3c632Sopenharmony_ci size_t offset_limit; 1110ffe3c632Sopenharmony_ci std::string message; 1111ffe3c632Sopenharmony_ci }; 1112ffe3c632Sopenharmony_ci 1113ffe3c632Sopenharmony_ci OurReader(OurFeatures const& features); 1114ffe3c632Sopenharmony_ci bool parse(const char* beginDoc, 1115ffe3c632Sopenharmony_ci const char* endDoc, 1116ffe3c632Sopenharmony_ci Value& root, 1117ffe3c632Sopenharmony_ci bool collectComments = true); 1118ffe3c632Sopenharmony_ci std::string getFormattedErrorMessages() const; 1119ffe3c632Sopenharmony_ci std::vector<StructuredError> getStructuredErrors() const; 1120ffe3c632Sopenharmony_ci bool pushError(const Value& value, const std::string& message); 1121ffe3c632Sopenharmony_ci bool pushError(const Value& value, const std::string& message, const Value& extra); 1122ffe3c632Sopenharmony_ci bool good() const; 1123ffe3c632Sopenharmony_ci 1124ffe3c632Sopenharmony_ciprivate: 1125ffe3c632Sopenharmony_ci OurReader(OurReader const&); // no impl 1126ffe3c632Sopenharmony_ci void operator=(OurReader const&); // no impl 1127ffe3c632Sopenharmony_ci 1128ffe3c632Sopenharmony_ci enum TokenType { 1129ffe3c632Sopenharmony_ci tokenEndOfStream = 0, 1130ffe3c632Sopenharmony_ci tokenObjectBegin, 1131ffe3c632Sopenharmony_ci tokenObjectEnd, 1132ffe3c632Sopenharmony_ci tokenArrayBegin, 1133ffe3c632Sopenharmony_ci tokenArrayEnd, 1134ffe3c632Sopenharmony_ci tokenString, 1135ffe3c632Sopenharmony_ci tokenNumber, 1136ffe3c632Sopenharmony_ci tokenTrue, 1137ffe3c632Sopenharmony_ci tokenFalse, 1138ffe3c632Sopenharmony_ci tokenNull, 1139ffe3c632Sopenharmony_ci tokenNaN, 1140ffe3c632Sopenharmony_ci tokenPosInf, 1141ffe3c632Sopenharmony_ci tokenNegInf, 1142ffe3c632Sopenharmony_ci tokenArraySeparator, 1143ffe3c632Sopenharmony_ci tokenMemberSeparator, 1144ffe3c632Sopenharmony_ci tokenComment, 1145ffe3c632Sopenharmony_ci tokenError 1146ffe3c632Sopenharmony_ci }; 1147ffe3c632Sopenharmony_ci 1148ffe3c632Sopenharmony_ci class Token { 1149ffe3c632Sopenharmony_ci public: 1150ffe3c632Sopenharmony_ci TokenType type_; 1151ffe3c632Sopenharmony_ci Location start_; 1152ffe3c632Sopenharmony_ci Location end_; 1153ffe3c632Sopenharmony_ci }; 1154ffe3c632Sopenharmony_ci 1155ffe3c632Sopenharmony_ci class ErrorInfo { 1156ffe3c632Sopenharmony_ci public: 1157ffe3c632Sopenharmony_ci Token token_; 1158ffe3c632Sopenharmony_ci std::string message_; 1159ffe3c632Sopenharmony_ci Location extra_; 1160ffe3c632Sopenharmony_ci }; 1161ffe3c632Sopenharmony_ci 1162ffe3c632Sopenharmony_ci typedef std::deque<ErrorInfo> Errors; 1163ffe3c632Sopenharmony_ci 1164ffe3c632Sopenharmony_ci bool readToken(Token& token); 1165ffe3c632Sopenharmony_ci void skipSpaces(); 1166ffe3c632Sopenharmony_ci bool match(Location pattern, int patternLength); 1167ffe3c632Sopenharmony_ci bool readComment(); 1168ffe3c632Sopenharmony_ci bool readCStyleComment(); 1169ffe3c632Sopenharmony_ci bool readCppStyleComment(); 1170ffe3c632Sopenharmony_ci bool readString(); 1171ffe3c632Sopenharmony_ci bool readStringSingleQuote(); 1172ffe3c632Sopenharmony_ci bool readNumber(bool checkInf); 1173ffe3c632Sopenharmony_ci bool readValue(); 1174ffe3c632Sopenharmony_ci bool readObject(Token& token); 1175ffe3c632Sopenharmony_ci bool readArray(Token& token); 1176ffe3c632Sopenharmony_ci bool decodeNumber(Token& token); 1177ffe3c632Sopenharmony_ci bool decodeNumber(Token& token, Value& decoded); 1178ffe3c632Sopenharmony_ci bool decodeString(Token& token); 1179ffe3c632Sopenharmony_ci bool decodeString(Token& token, std::string& decoded); 1180ffe3c632Sopenharmony_ci bool decodeDouble(Token& token); 1181ffe3c632Sopenharmony_ci bool decodeDouble(Token& token, Value& decoded); 1182ffe3c632Sopenharmony_ci bool decodeUnicodeCodePoint(Token& token, 1183ffe3c632Sopenharmony_ci Location& current, 1184ffe3c632Sopenharmony_ci Location end, 1185ffe3c632Sopenharmony_ci unsigned int& unicode); 1186ffe3c632Sopenharmony_ci bool decodeUnicodeEscapeSequence(Token& token, 1187ffe3c632Sopenharmony_ci Location& current, 1188ffe3c632Sopenharmony_ci Location end, 1189ffe3c632Sopenharmony_ci unsigned int& unicode); 1190ffe3c632Sopenharmony_ci bool addError(const std::string& message, Token& token, Location extra = 0); 1191ffe3c632Sopenharmony_ci bool recoverFromError(TokenType skipUntilToken); 1192ffe3c632Sopenharmony_ci bool addErrorAndRecover(const std::string& message, 1193ffe3c632Sopenharmony_ci Token& token, 1194ffe3c632Sopenharmony_ci TokenType skipUntilToken); 1195ffe3c632Sopenharmony_ci void skipUntilSpace(); 1196ffe3c632Sopenharmony_ci Value& currentValue(); 1197ffe3c632Sopenharmony_ci Char getNextChar(); 1198ffe3c632Sopenharmony_ci void 1199ffe3c632Sopenharmony_ci getLocationLineAndColumn(Location location, int& line, int& column) const; 1200ffe3c632Sopenharmony_ci std::string getLocationLineAndColumn(Location location) const; 1201ffe3c632Sopenharmony_ci void addComment(Location begin, Location end, CommentPlacement placement); 1202ffe3c632Sopenharmony_ci void skipCommentTokens(Token& token); 1203ffe3c632Sopenharmony_ci 1204ffe3c632Sopenharmony_ci typedef std::stack<Value*> Nodes; 1205ffe3c632Sopenharmony_ci Nodes nodes_; 1206ffe3c632Sopenharmony_ci Errors errors_; 1207ffe3c632Sopenharmony_ci std::string document_; 1208ffe3c632Sopenharmony_ci Location begin_; 1209ffe3c632Sopenharmony_ci Location end_; 1210ffe3c632Sopenharmony_ci Location current_; 1211ffe3c632Sopenharmony_ci Location lastValueEnd_; 1212ffe3c632Sopenharmony_ci Value* lastValue_; 1213ffe3c632Sopenharmony_ci std::string commentsBefore_; 1214ffe3c632Sopenharmony_ci int stackDepth_; 1215ffe3c632Sopenharmony_ci 1216ffe3c632Sopenharmony_ci OurFeatures const features_; 1217ffe3c632Sopenharmony_ci bool collectComments_; 1218ffe3c632Sopenharmony_ci}; // OurReader 1219ffe3c632Sopenharmony_ci 1220ffe3c632Sopenharmony_ci// complete copy of Read impl, for OurReader 1221ffe3c632Sopenharmony_ci 1222ffe3c632Sopenharmony_ciOurReader::OurReader(OurFeatures const& features) 1223ffe3c632Sopenharmony_ci : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), 1224ffe3c632Sopenharmony_ci lastValue_(), commentsBefore_(), 1225ffe3c632Sopenharmony_ci stackDepth_(0), 1226ffe3c632Sopenharmony_ci features_(features), collectComments_() { 1227ffe3c632Sopenharmony_ci} 1228ffe3c632Sopenharmony_ci 1229ffe3c632Sopenharmony_cibool OurReader::parse(const char* beginDoc, 1230ffe3c632Sopenharmony_ci const char* endDoc, 1231ffe3c632Sopenharmony_ci Value& root, 1232ffe3c632Sopenharmony_ci bool collectComments) { 1233ffe3c632Sopenharmony_ci if (!features_.allowComments_) { 1234ffe3c632Sopenharmony_ci collectComments = false; 1235ffe3c632Sopenharmony_ci } 1236ffe3c632Sopenharmony_ci 1237ffe3c632Sopenharmony_ci begin_ = beginDoc; 1238ffe3c632Sopenharmony_ci end_ = endDoc; 1239ffe3c632Sopenharmony_ci collectComments_ = collectComments; 1240ffe3c632Sopenharmony_ci current_ = begin_; 1241ffe3c632Sopenharmony_ci lastValueEnd_ = 0; 1242ffe3c632Sopenharmony_ci lastValue_ = 0; 1243ffe3c632Sopenharmony_ci commentsBefore_ = ""; 1244ffe3c632Sopenharmony_ci errors_.clear(); 1245ffe3c632Sopenharmony_ci while (!nodes_.empty()) 1246ffe3c632Sopenharmony_ci nodes_.pop(); 1247ffe3c632Sopenharmony_ci nodes_.push(&root); 1248ffe3c632Sopenharmony_ci 1249ffe3c632Sopenharmony_ci stackDepth_ = 0; 1250ffe3c632Sopenharmony_ci bool successful = readValue(); 1251ffe3c632Sopenharmony_ci Token token; 1252ffe3c632Sopenharmony_ci skipCommentTokens(token); 1253ffe3c632Sopenharmony_ci if (features_.failIfExtra_) { 1254ffe3c632Sopenharmony_ci if (token.type_ != tokenError && token.type_ != tokenEndOfStream) { 1255ffe3c632Sopenharmony_ci addError("Extra non-whitespace after JSON value.", token); 1256ffe3c632Sopenharmony_ci return false; 1257ffe3c632Sopenharmony_ci } 1258ffe3c632Sopenharmony_ci } 1259ffe3c632Sopenharmony_ci if (collectComments_ && !commentsBefore_.empty()) 1260ffe3c632Sopenharmony_ci root.setComment(commentsBefore_, commentAfter); 1261ffe3c632Sopenharmony_ci if (features_.strictRoot_) { 1262ffe3c632Sopenharmony_ci if (!root.isArray() && !root.isObject()) { 1263ffe3c632Sopenharmony_ci // Set error location to start of doc, ideally should be first token found 1264ffe3c632Sopenharmony_ci // in doc 1265ffe3c632Sopenharmony_ci token.type_ = tokenError; 1266ffe3c632Sopenharmony_ci token.start_ = beginDoc; 1267ffe3c632Sopenharmony_ci token.end_ = endDoc; 1268ffe3c632Sopenharmony_ci addError( 1269ffe3c632Sopenharmony_ci "A valid JSON document must be either an array or an object value.", 1270ffe3c632Sopenharmony_ci token); 1271ffe3c632Sopenharmony_ci return false; 1272ffe3c632Sopenharmony_ci } 1273ffe3c632Sopenharmony_ci } 1274ffe3c632Sopenharmony_ci return successful; 1275ffe3c632Sopenharmony_ci} 1276ffe3c632Sopenharmony_ci 1277ffe3c632Sopenharmony_cibool OurReader::readValue() { 1278ffe3c632Sopenharmony_ci if (stackDepth_ >= features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue()."); 1279ffe3c632Sopenharmony_ci ++stackDepth_; 1280ffe3c632Sopenharmony_ci Token token; 1281ffe3c632Sopenharmony_ci skipCommentTokens(token); 1282ffe3c632Sopenharmony_ci bool successful = true; 1283ffe3c632Sopenharmony_ci 1284ffe3c632Sopenharmony_ci if (collectComments_ && !commentsBefore_.empty()) { 1285ffe3c632Sopenharmony_ci currentValue().setComment(commentsBefore_, commentBefore); 1286ffe3c632Sopenharmony_ci commentsBefore_ = ""; 1287ffe3c632Sopenharmony_ci } 1288ffe3c632Sopenharmony_ci 1289ffe3c632Sopenharmony_ci switch (token.type_) { 1290ffe3c632Sopenharmony_ci case tokenObjectBegin: 1291ffe3c632Sopenharmony_ci successful = readObject(token); 1292ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(current_ - begin_); 1293ffe3c632Sopenharmony_ci break; 1294ffe3c632Sopenharmony_ci case tokenArrayBegin: 1295ffe3c632Sopenharmony_ci successful = readArray(token); 1296ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(current_ - begin_); 1297ffe3c632Sopenharmony_ci break; 1298ffe3c632Sopenharmony_ci case tokenNumber: 1299ffe3c632Sopenharmony_ci successful = decodeNumber(token); 1300ffe3c632Sopenharmony_ci break; 1301ffe3c632Sopenharmony_ci case tokenString: 1302ffe3c632Sopenharmony_ci successful = decodeString(token); 1303ffe3c632Sopenharmony_ci break; 1304ffe3c632Sopenharmony_ci case tokenTrue: 1305ffe3c632Sopenharmony_ci { 1306ffe3c632Sopenharmony_ci Value v(true); 1307ffe3c632Sopenharmony_ci currentValue().swapPayload(v); 1308ffe3c632Sopenharmony_ci currentValue().setOffsetStart(token.start_ - begin_); 1309ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(token.end_ - begin_); 1310ffe3c632Sopenharmony_ci } 1311ffe3c632Sopenharmony_ci break; 1312ffe3c632Sopenharmony_ci case tokenFalse: 1313ffe3c632Sopenharmony_ci { 1314ffe3c632Sopenharmony_ci Value v(false); 1315ffe3c632Sopenharmony_ci currentValue().swapPayload(v); 1316ffe3c632Sopenharmony_ci currentValue().setOffsetStart(token.start_ - begin_); 1317ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(token.end_ - begin_); 1318ffe3c632Sopenharmony_ci } 1319ffe3c632Sopenharmony_ci break; 1320ffe3c632Sopenharmony_ci case tokenNull: 1321ffe3c632Sopenharmony_ci { 1322ffe3c632Sopenharmony_ci Value v; 1323ffe3c632Sopenharmony_ci currentValue().swapPayload(v); 1324ffe3c632Sopenharmony_ci currentValue().setOffsetStart(token.start_ - begin_); 1325ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(token.end_ - begin_); 1326ffe3c632Sopenharmony_ci } 1327ffe3c632Sopenharmony_ci break; 1328ffe3c632Sopenharmony_ci case tokenNaN: 1329ffe3c632Sopenharmony_ci { 1330ffe3c632Sopenharmony_ci Value v(std::numeric_limits<double>::quiet_NaN()); 1331ffe3c632Sopenharmony_ci currentValue().swapPayload(v); 1332ffe3c632Sopenharmony_ci currentValue().setOffsetStart(token.start_ - begin_); 1333ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(token.end_ - begin_); 1334ffe3c632Sopenharmony_ci } 1335ffe3c632Sopenharmony_ci break; 1336ffe3c632Sopenharmony_ci case tokenPosInf: 1337ffe3c632Sopenharmony_ci { 1338ffe3c632Sopenharmony_ci Value v(std::numeric_limits<double>::infinity()); 1339ffe3c632Sopenharmony_ci currentValue().swapPayload(v); 1340ffe3c632Sopenharmony_ci currentValue().setOffsetStart(token.start_ - begin_); 1341ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(token.end_ - begin_); 1342ffe3c632Sopenharmony_ci } 1343ffe3c632Sopenharmony_ci break; 1344ffe3c632Sopenharmony_ci case tokenNegInf: 1345ffe3c632Sopenharmony_ci { 1346ffe3c632Sopenharmony_ci Value v(-std::numeric_limits<double>::infinity()); 1347ffe3c632Sopenharmony_ci currentValue().swapPayload(v); 1348ffe3c632Sopenharmony_ci currentValue().setOffsetStart(token.start_ - begin_); 1349ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(token.end_ - begin_); 1350ffe3c632Sopenharmony_ci } 1351ffe3c632Sopenharmony_ci break; 1352ffe3c632Sopenharmony_ci case tokenArraySeparator: 1353ffe3c632Sopenharmony_ci case tokenObjectEnd: 1354ffe3c632Sopenharmony_ci case tokenArrayEnd: 1355ffe3c632Sopenharmony_ci if (features_.allowDroppedNullPlaceholders_) { 1356ffe3c632Sopenharmony_ci // "Un-read" the current token and mark the current value as a null 1357ffe3c632Sopenharmony_ci // token. 1358ffe3c632Sopenharmony_ci current_--; 1359ffe3c632Sopenharmony_ci Value v; 1360ffe3c632Sopenharmony_ci currentValue().swapPayload(v); 1361ffe3c632Sopenharmony_ci currentValue().setOffsetStart(current_ - begin_ - 1); 1362ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(current_ - begin_); 1363ffe3c632Sopenharmony_ci break; 1364ffe3c632Sopenharmony_ci } // else, fall through ... 1365ffe3c632Sopenharmony_ci default: 1366ffe3c632Sopenharmony_ci currentValue().setOffsetStart(token.start_ - begin_); 1367ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(token.end_ - begin_); 1368ffe3c632Sopenharmony_ci return addError("Syntax error: value, object or array expected.", token); 1369ffe3c632Sopenharmony_ci } 1370ffe3c632Sopenharmony_ci 1371ffe3c632Sopenharmony_ci if (collectComments_) { 1372ffe3c632Sopenharmony_ci lastValueEnd_ = current_; 1373ffe3c632Sopenharmony_ci lastValue_ = ¤tValue(); 1374ffe3c632Sopenharmony_ci } 1375ffe3c632Sopenharmony_ci 1376ffe3c632Sopenharmony_ci --stackDepth_; 1377ffe3c632Sopenharmony_ci return successful; 1378ffe3c632Sopenharmony_ci} 1379ffe3c632Sopenharmony_ci 1380ffe3c632Sopenharmony_civoid OurReader::skipCommentTokens(Token& token) { 1381ffe3c632Sopenharmony_ci if (features_.allowComments_) { 1382ffe3c632Sopenharmony_ci do { 1383ffe3c632Sopenharmony_ci readToken(token); 1384ffe3c632Sopenharmony_ci } while (token.type_ == tokenComment); 1385ffe3c632Sopenharmony_ci } else { 1386ffe3c632Sopenharmony_ci readToken(token); 1387ffe3c632Sopenharmony_ci } 1388ffe3c632Sopenharmony_ci} 1389ffe3c632Sopenharmony_ci 1390ffe3c632Sopenharmony_cibool OurReader::readToken(Token& token) { 1391ffe3c632Sopenharmony_ci skipSpaces(); 1392ffe3c632Sopenharmony_ci token.start_ = current_; 1393ffe3c632Sopenharmony_ci Char c = getNextChar(); 1394ffe3c632Sopenharmony_ci bool ok = true; 1395ffe3c632Sopenharmony_ci switch (c) { 1396ffe3c632Sopenharmony_ci case '{': 1397ffe3c632Sopenharmony_ci token.type_ = tokenObjectBegin; 1398ffe3c632Sopenharmony_ci break; 1399ffe3c632Sopenharmony_ci case '}': 1400ffe3c632Sopenharmony_ci token.type_ = tokenObjectEnd; 1401ffe3c632Sopenharmony_ci break; 1402ffe3c632Sopenharmony_ci case '[': 1403ffe3c632Sopenharmony_ci token.type_ = tokenArrayBegin; 1404ffe3c632Sopenharmony_ci break; 1405ffe3c632Sopenharmony_ci case ']': 1406ffe3c632Sopenharmony_ci token.type_ = tokenArrayEnd; 1407ffe3c632Sopenharmony_ci break; 1408ffe3c632Sopenharmony_ci case '"': 1409ffe3c632Sopenharmony_ci token.type_ = tokenString; 1410ffe3c632Sopenharmony_ci ok = readString(); 1411ffe3c632Sopenharmony_ci break; 1412ffe3c632Sopenharmony_ci case '\'': 1413ffe3c632Sopenharmony_ci if (features_.allowSingleQuotes_) { 1414ffe3c632Sopenharmony_ci token.type_ = tokenString; 1415ffe3c632Sopenharmony_ci ok = readStringSingleQuote(); 1416ffe3c632Sopenharmony_ci break; 1417ffe3c632Sopenharmony_ci } // else continue 1418ffe3c632Sopenharmony_ci case '/': 1419ffe3c632Sopenharmony_ci token.type_ = tokenComment; 1420ffe3c632Sopenharmony_ci ok = readComment(); 1421ffe3c632Sopenharmony_ci break; 1422ffe3c632Sopenharmony_ci case '0': 1423ffe3c632Sopenharmony_ci case '1': 1424ffe3c632Sopenharmony_ci case '2': 1425ffe3c632Sopenharmony_ci case '3': 1426ffe3c632Sopenharmony_ci case '4': 1427ffe3c632Sopenharmony_ci case '5': 1428ffe3c632Sopenharmony_ci case '6': 1429ffe3c632Sopenharmony_ci case '7': 1430ffe3c632Sopenharmony_ci case '8': 1431ffe3c632Sopenharmony_ci case '9': 1432ffe3c632Sopenharmony_ci token.type_ = tokenNumber; 1433ffe3c632Sopenharmony_ci readNumber(false); 1434ffe3c632Sopenharmony_ci break; 1435ffe3c632Sopenharmony_ci case '-': 1436ffe3c632Sopenharmony_ci if (readNumber(true)) { 1437ffe3c632Sopenharmony_ci token.type_ = tokenNumber; 1438ffe3c632Sopenharmony_ci } else { 1439ffe3c632Sopenharmony_ci token.type_ = tokenNegInf; 1440ffe3c632Sopenharmony_ci ok = features_.allowSpecialFloats_ && match("nfinity", 7); 1441ffe3c632Sopenharmony_ci } 1442ffe3c632Sopenharmony_ci break; 1443ffe3c632Sopenharmony_ci case 't': 1444ffe3c632Sopenharmony_ci token.type_ = tokenTrue; 1445ffe3c632Sopenharmony_ci ok = match("rue", 3); 1446ffe3c632Sopenharmony_ci break; 1447ffe3c632Sopenharmony_ci case 'f': 1448ffe3c632Sopenharmony_ci token.type_ = tokenFalse; 1449ffe3c632Sopenharmony_ci ok = match("alse", 4); 1450ffe3c632Sopenharmony_ci break; 1451ffe3c632Sopenharmony_ci case 'n': 1452ffe3c632Sopenharmony_ci token.type_ = tokenNull; 1453ffe3c632Sopenharmony_ci ok = match("ull", 3); 1454ffe3c632Sopenharmony_ci break; 1455ffe3c632Sopenharmony_ci case 'N': 1456ffe3c632Sopenharmony_ci if (features_.allowSpecialFloats_) { 1457ffe3c632Sopenharmony_ci token.type_ = tokenNaN; 1458ffe3c632Sopenharmony_ci ok = match("aN", 2); 1459ffe3c632Sopenharmony_ci } else { 1460ffe3c632Sopenharmony_ci ok = false; 1461ffe3c632Sopenharmony_ci } 1462ffe3c632Sopenharmony_ci break; 1463ffe3c632Sopenharmony_ci case 'I': 1464ffe3c632Sopenharmony_ci if (features_.allowSpecialFloats_) { 1465ffe3c632Sopenharmony_ci token.type_ = tokenPosInf; 1466ffe3c632Sopenharmony_ci ok = match("nfinity", 7); 1467ffe3c632Sopenharmony_ci } else { 1468ffe3c632Sopenharmony_ci ok = false; 1469ffe3c632Sopenharmony_ci } 1470ffe3c632Sopenharmony_ci break; 1471ffe3c632Sopenharmony_ci case ',': 1472ffe3c632Sopenharmony_ci token.type_ = tokenArraySeparator; 1473ffe3c632Sopenharmony_ci break; 1474ffe3c632Sopenharmony_ci case ':': 1475ffe3c632Sopenharmony_ci token.type_ = tokenMemberSeparator; 1476ffe3c632Sopenharmony_ci break; 1477ffe3c632Sopenharmony_ci case 0: 1478ffe3c632Sopenharmony_ci token.type_ = tokenEndOfStream; 1479ffe3c632Sopenharmony_ci break; 1480ffe3c632Sopenharmony_ci default: 1481ffe3c632Sopenharmony_ci ok = false; 1482ffe3c632Sopenharmony_ci break; 1483ffe3c632Sopenharmony_ci } 1484ffe3c632Sopenharmony_ci if (!ok) 1485ffe3c632Sopenharmony_ci token.type_ = tokenError; 1486ffe3c632Sopenharmony_ci token.end_ = current_; 1487ffe3c632Sopenharmony_ci return true; 1488ffe3c632Sopenharmony_ci} 1489ffe3c632Sopenharmony_ci 1490ffe3c632Sopenharmony_civoid OurReader::skipSpaces() { 1491ffe3c632Sopenharmony_ci while (current_ != end_) { 1492ffe3c632Sopenharmony_ci Char c = *current_; 1493ffe3c632Sopenharmony_ci if (c == ' ' || c == '\t' || c == '\r' || c == '\n') 1494ffe3c632Sopenharmony_ci ++current_; 1495ffe3c632Sopenharmony_ci else 1496ffe3c632Sopenharmony_ci break; 1497ffe3c632Sopenharmony_ci } 1498ffe3c632Sopenharmony_ci} 1499ffe3c632Sopenharmony_ci 1500ffe3c632Sopenharmony_cibool OurReader::match(Location pattern, int patternLength) { 1501ffe3c632Sopenharmony_ci if (end_ - current_ < patternLength) 1502ffe3c632Sopenharmony_ci return false; 1503ffe3c632Sopenharmony_ci int index = patternLength; 1504ffe3c632Sopenharmony_ci while (index--) 1505ffe3c632Sopenharmony_ci if (current_[index] != pattern[index]) 1506ffe3c632Sopenharmony_ci return false; 1507ffe3c632Sopenharmony_ci current_ += patternLength; 1508ffe3c632Sopenharmony_ci return true; 1509ffe3c632Sopenharmony_ci} 1510ffe3c632Sopenharmony_ci 1511ffe3c632Sopenharmony_cibool OurReader::readComment() { 1512ffe3c632Sopenharmony_ci Location commentBegin = current_ - 1; 1513ffe3c632Sopenharmony_ci Char c = getNextChar(); 1514ffe3c632Sopenharmony_ci bool successful = false; 1515ffe3c632Sopenharmony_ci if (c == '*') 1516ffe3c632Sopenharmony_ci successful = readCStyleComment(); 1517ffe3c632Sopenharmony_ci else if (c == '/') 1518ffe3c632Sopenharmony_ci successful = readCppStyleComment(); 1519ffe3c632Sopenharmony_ci if (!successful) 1520ffe3c632Sopenharmony_ci return false; 1521ffe3c632Sopenharmony_ci 1522ffe3c632Sopenharmony_ci if (collectComments_) { 1523ffe3c632Sopenharmony_ci CommentPlacement placement = commentBefore; 1524ffe3c632Sopenharmony_ci if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { 1525ffe3c632Sopenharmony_ci if (c != '*' || !containsNewLine(commentBegin, current_)) 1526ffe3c632Sopenharmony_ci placement = commentAfterOnSameLine; 1527ffe3c632Sopenharmony_ci } 1528ffe3c632Sopenharmony_ci 1529ffe3c632Sopenharmony_ci addComment(commentBegin, current_, placement); 1530ffe3c632Sopenharmony_ci } 1531ffe3c632Sopenharmony_ci return true; 1532ffe3c632Sopenharmony_ci} 1533ffe3c632Sopenharmony_ci 1534ffe3c632Sopenharmony_civoid 1535ffe3c632Sopenharmony_ciOurReader::addComment(Location begin, Location end, CommentPlacement placement) { 1536ffe3c632Sopenharmony_ci assert(collectComments_); 1537ffe3c632Sopenharmony_ci const std::string& normalized = normalizeEOL(begin, end); 1538ffe3c632Sopenharmony_ci if (placement == commentAfterOnSameLine) { 1539ffe3c632Sopenharmony_ci assert(lastValue_ != 0); 1540ffe3c632Sopenharmony_ci lastValue_->setComment(normalized, placement); 1541ffe3c632Sopenharmony_ci } else { 1542ffe3c632Sopenharmony_ci commentsBefore_ += normalized; 1543ffe3c632Sopenharmony_ci } 1544ffe3c632Sopenharmony_ci} 1545ffe3c632Sopenharmony_ci 1546ffe3c632Sopenharmony_cibool OurReader::readCStyleComment() { 1547ffe3c632Sopenharmony_ci while (current_ != end_) { 1548ffe3c632Sopenharmony_ci Char c = getNextChar(); 1549ffe3c632Sopenharmony_ci if (c == '*' && *current_ == '/') 1550ffe3c632Sopenharmony_ci break; 1551ffe3c632Sopenharmony_ci } 1552ffe3c632Sopenharmony_ci return getNextChar() == '/'; 1553ffe3c632Sopenharmony_ci} 1554ffe3c632Sopenharmony_ci 1555ffe3c632Sopenharmony_cibool OurReader::readCppStyleComment() { 1556ffe3c632Sopenharmony_ci while (current_ != end_) { 1557ffe3c632Sopenharmony_ci Char c = getNextChar(); 1558ffe3c632Sopenharmony_ci if (c == '\n') 1559ffe3c632Sopenharmony_ci break; 1560ffe3c632Sopenharmony_ci if (c == '\r') { 1561ffe3c632Sopenharmony_ci // Consume DOS EOL. It will be normalized in addComment. 1562ffe3c632Sopenharmony_ci if (current_ != end_ && *current_ == '\n') 1563ffe3c632Sopenharmony_ci getNextChar(); 1564ffe3c632Sopenharmony_ci // Break on Moc OS 9 EOL. 1565ffe3c632Sopenharmony_ci break; 1566ffe3c632Sopenharmony_ci } 1567ffe3c632Sopenharmony_ci } 1568ffe3c632Sopenharmony_ci return true; 1569ffe3c632Sopenharmony_ci} 1570ffe3c632Sopenharmony_ci 1571ffe3c632Sopenharmony_cibool OurReader::readNumber(bool checkInf) { 1572ffe3c632Sopenharmony_ci const char *p = current_; 1573ffe3c632Sopenharmony_ci if (checkInf && p != end_ && *p == 'I') { 1574ffe3c632Sopenharmony_ci current_ = ++p; 1575ffe3c632Sopenharmony_ci return false; 1576ffe3c632Sopenharmony_ci } 1577ffe3c632Sopenharmony_ci char c = '0'; // stopgap for already consumed character 1578ffe3c632Sopenharmony_ci // integral part 1579ffe3c632Sopenharmony_ci while (c >= '0' && c <= '9') 1580ffe3c632Sopenharmony_ci c = (current_ = p) < end_ ? *p++ : 0; 1581ffe3c632Sopenharmony_ci // fractional part 1582ffe3c632Sopenharmony_ci if (c == '.') { 1583ffe3c632Sopenharmony_ci c = (current_ = p) < end_ ? *p++ : 0; 1584ffe3c632Sopenharmony_ci while (c >= '0' && c <= '9') 1585ffe3c632Sopenharmony_ci c = (current_ = p) < end_ ? *p++ : 0; 1586ffe3c632Sopenharmony_ci } 1587ffe3c632Sopenharmony_ci // exponential part 1588ffe3c632Sopenharmony_ci if (c == 'e' || c == 'E') { 1589ffe3c632Sopenharmony_ci c = (current_ = p) < end_ ? *p++ : 0; 1590ffe3c632Sopenharmony_ci if (c == '+' || c == '-') 1591ffe3c632Sopenharmony_ci c = (current_ = p) < end_ ? *p++ : 0; 1592ffe3c632Sopenharmony_ci while (c >= '0' && c <= '9') 1593ffe3c632Sopenharmony_ci c = (current_ = p) < end_ ? *p++ : 0; 1594ffe3c632Sopenharmony_ci } 1595ffe3c632Sopenharmony_ci return true; 1596ffe3c632Sopenharmony_ci} 1597ffe3c632Sopenharmony_cibool OurReader::readString() { 1598ffe3c632Sopenharmony_ci Char c = 0; 1599ffe3c632Sopenharmony_ci while (current_ != end_) { 1600ffe3c632Sopenharmony_ci c = getNextChar(); 1601ffe3c632Sopenharmony_ci if (c == '\\') 1602ffe3c632Sopenharmony_ci getNextChar(); 1603ffe3c632Sopenharmony_ci else if (c == '"') 1604ffe3c632Sopenharmony_ci break; 1605ffe3c632Sopenharmony_ci } 1606ffe3c632Sopenharmony_ci return c == '"'; 1607ffe3c632Sopenharmony_ci} 1608ffe3c632Sopenharmony_ci 1609ffe3c632Sopenharmony_ci 1610ffe3c632Sopenharmony_cibool OurReader::readStringSingleQuote() { 1611ffe3c632Sopenharmony_ci Char c = 0; 1612ffe3c632Sopenharmony_ci while (current_ != end_) { 1613ffe3c632Sopenharmony_ci c = getNextChar(); 1614ffe3c632Sopenharmony_ci if (c == '\\') 1615ffe3c632Sopenharmony_ci getNextChar(); 1616ffe3c632Sopenharmony_ci else if (c == '\'') 1617ffe3c632Sopenharmony_ci break; 1618ffe3c632Sopenharmony_ci } 1619ffe3c632Sopenharmony_ci return c == '\''; 1620ffe3c632Sopenharmony_ci} 1621ffe3c632Sopenharmony_ci 1622ffe3c632Sopenharmony_cibool OurReader::readObject(Token& tokenStart) { 1623ffe3c632Sopenharmony_ci Token tokenName; 1624ffe3c632Sopenharmony_ci std::string name; 1625ffe3c632Sopenharmony_ci Value init(objectValue); 1626ffe3c632Sopenharmony_ci currentValue().swapPayload(init); 1627ffe3c632Sopenharmony_ci currentValue().setOffsetStart(tokenStart.start_ - begin_); 1628ffe3c632Sopenharmony_ci while (readToken(tokenName)) { 1629ffe3c632Sopenharmony_ci bool initialTokenOk = true; 1630ffe3c632Sopenharmony_ci while (tokenName.type_ == tokenComment && initialTokenOk) 1631ffe3c632Sopenharmony_ci initialTokenOk = readToken(tokenName); 1632ffe3c632Sopenharmony_ci if (!initialTokenOk) 1633ffe3c632Sopenharmony_ci break; 1634ffe3c632Sopenharmony_ci if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object 1635ffe3c632Sopenharmony_ci return true; 1636ffe3c632Sopenharmony_ci name = ""; 1637ffe3c632Sopenharmony_ci if (tokenName.type_ == tokenString) { 1638ffe3c632Sopenharmony_ci if (!decodeString(tokenName, name)) 1639ffe3c632Sopenharmony_ci return recoverFromError(tokenObjectEnd); 1640ffe3c632Sopenharmony_ci } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { 1641ffe3c632Sopenharmony_ci Value numberName; 1642ffe3c632Sopenharmony_ci if (!decodeNumber(tokenName, numberName)) 1643ffe3c632Sopenharmony_ci return recoverFromError(tokenObjectEnd); 1644ffe3c632Sopenharmony_ci name = numberName.asString(); 1645ffe3c632Sopenharmony_ci } else { 1646ffe3c632Sopenharmony_ci break; 1647ffe3c632Sopenharmony_ci } 1648ffe3c632Sopenharmony_ci 1649ffe3c632Sopenharmony_ci Token colon; 1650ffe3c632Sopenharmony_ci if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { 1651ffe3c632Sopenharmony_ci return addErrorAndRecover( 1652ffe3c632Sopenharmony_ci "Missing ':' after object member name", colon, tokenObjectEnd); 1653ffe3c632Sopenharmony_ci } 1654ffe3c632Sopenharmony_ci if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30"); 1655ffe3c632Sopenharmony_ci if (features_.rejectDupKeys_ && currentValue().isMember(name)) { 1656ffe3c632Sopenharmony_ci std::string msg = "Duplicate key: '" + name + "'"; 1657ffe3c632Sopenharmony_ci return addErrorAndRecover( 1658ffe3c632Sopenharmony_ci msg, tokenName, tokenObjectEnd); 1659ffe3c632Sopenharmony_ci } 1660ffe3c632Sopenharmony_ci Value& value = currentValue()[name]; 1661ffe3c632Sopenharmony_ci nodes_.push(&value); 1662ffe3c632Sopenharmony_ci bool ok = readValue(); 1663ffe3c632Sopenharmony_ci nodes_.pop(); 1664ffe3c632Sopenharmony_ci if (!ok) // error already set 1665ffe3c632Sopenharmony_ci return recoverFromError(tokenObjectEnd); 1666ffe3c632Sopenharmony_ci 1667ffe3c632Sopenharmony_ci Token comma; 1668ffe3c632Sopenharmony_ci if (!readToken(comma) || 1669ffe3c632Sopenharmony_ci (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && 1670ffe3c632Sopenharmony_ci comma.type_ != tokenComment)) { 1671ffe3c632Sopenharmony_ci return addErrorAndRecover( 1672ffe3c632Sopenharmony_ci "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); 1673ffe3c632Sopenharmony_ci } 1674ffe3c632Sopenharmony_ci bool finalizeTokenOk = true; 1675ffe3c632Sopenharmony_ci while (comma.type_ == tokenComment && finalizeTokenOk) 1676ffe3c632Sopenharmony_ci finalizeTokenOk = readToken(comma); 1677ffe3c632Sopenharmony_ci if (comma.type_ == tokenObjectEnd) 1678ffe3c632Sopenharmony_ci return true; 1679ffe3c632Sopenharmony_ci } 1680ffe3c632Sopenharmony_ci return addErrorAndRecover( 1681ffe3c632Sopenharmony_ci "Missing '}' or object member name", tokenName, tokenObjectEnd); 1682ffe3c632Sopenharmony_ci} 1683ffe3c632Sopenharmony_ci 1684ffe3c632Sopenharmony_cibool OurReader::readArray(Token& tokenStart) { 1685ffe3c632Sopenharmony_ci Value init(arrayValue); 1686ffe3c632Sopenharmony_ci currentValue().swapPayload(init); 1687ffe3c632Sopenharmony_ci currentValue().setOffsetStart(tokenStart.start_ - begin_); 1688ffe3c632Sopenharmony_ci skipSpaces(); 1689ffe3c632Sopenharmony_ci if (*current_ == ']') // empty array 1690ffe3c632Sopenharmony_ci { 1691ffe3c632Sopenharmony_ci Token endArray; 1692ffe3c632Sopenharmony_ci readToken(endArray); 1693ffe3c632Sopenharmony_ci return true; 1694ffe3c632Sopenharmony_ci } 1695ffe3c632Sopenharmony_ci int index = 0; 1696ffe3c632Sopenharmony_ci for (;;) { 1697ffe3c632Sopenharmony_ci Value& value = currentValue()[index++]; 1698ffe3c632Sopenharmony_ci nodes_.push(&value); 1699ffe3c632Sopenharmony_ci bool ok = readValue(); 1700ffe3c632Sopenharmony_ci nodes_.pop(); 1701ffe3c632Sopenharmony_ci if (!ok) // error already set 1702ffe3c632Sopenharmony_ci return recoverFromError(tokenArrayEnd); 1703ffe3c632Sopenharmony_ci 1704ffe3c632Sopenharmony_ci Token token; 1705ffe3c632Sopenharmony_ci // Accept Comment after last item in the array. 1706ffe3c632Sopenharmony_ci ok = readToken(token); 1707ffe3c632Sopenharmony_ci while (token.type_ == tokenComment && ok) { 1708ffe3c632Sopenharmony_ci ok = readToken(token); 1709ffe3c632Sopenharmony_ci } 1710ffe3c632Sopenharmony_ci bool badTokenType = 1711ffe3c632Sopenharmony_ci (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); 1712ffe3c632Sopenharmony_ci if (!ok || badTokenType) { 1713ffe3c632Sopenharmony_ci return addErrorAndRecover( 1714ffe3c632Sopenharmony_ci "Missing ',' or ']' in array declaration", token, tokenArrayEnd); 1715ffe3c632Sopenharmony_ci } 1716ffe3c632Sopenharmony_ci if (token.type_ == tokenArrayEnd) 1717ffe3c632Sopenharmony_ci break; 1718ffe3c632Sopenharmony_ci } 1719ffe3c632Sopenharmony_ci return true; 1720ffe3c632Sopenharmony_ci} 1721ffe3c632Sopenharmony_ci 1722ffe3c632Sopenharmony_cibool OurReader::decodeNumber(Token& token) { 1723ffe3c632Sopenharmony_ci Value decoded; 1724ffe3c632Sopenharmony_ci if (!decodeNumber(token, decoded)) 1725ffe3c632Sopenharmony_ci return false; 1726ffe3c632Sopenharmony_ci currentValue().swapPayload(decoded); 1727ffe3c632Sopenharmony_ci currentValue().setOffsetStart(token.start_ - begin_); 1728ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(token.end_ - begin_); 1729ffe3c632Sopenharmony_ci return true; 1730ffe3c632Sopenharmony_ci} 1731ffe3c632Sopenharmony_ci 1732ffe3c632Sopenharmony_cibool OurReader::decodeNumber(Token& token, Value& decoded) { 1733ffe3c632Sopenharmony_ci // Attempts to parse the number as an integer. If the number is 1734ffe3c632Sopenharmony_ci // larger than the maximum supported value of an integer then 1735ffe3c632Sopenharmony_ci // we decode the number as a double. 1736ffe3c632Sopenharmony_ci Location current = token.start_; 1737ffe3c632Sopenharmony_ci bool isNegative = *current == '-'; 1738ffe3c632Sopenharmony_ci if (isNegative) 1739ffe3c632Sopenharmony_ci ++current; 1740ffe3c632Sopenharmony_ci // TODO: Help the compiler do the div and mod at compile time or get rid of them. 1741ffe3c632Sopenharmony_ci Value::LargestUInt maxIntegerValue = 1742ffe3c632Sopenharmony_ci isNegative ? Value::LargestUInt(-Value::minLargestInt) 1743ffe3c632Sopenharmony_ci : Value::maxLargestUInt; 1744ffe3c632Sopenharmony_ci Value::LargestUInt threshold = maxIntegerValue / 10; 1745ffe3c632Sopenharmony_ci Value::LargestUInt value = 0; 1746ffe3c632Sopenharmony_ci while (current < token.end_) { 1747ffe3c632Sopenharmony_ci Char c = *current++; 1748ffe3c632Sopenharmony_ci if (c < '0' || c > '9') 1749ffe3c632Sopenharmony_ci return decodeDouble(token, decoded); 1750ffe3c632Sopenharmony_ci Value::UInt digit(c - '0'); 1751ffe3c632Sopenharmony_ci if (value >= threshold) { 1752ffe3c632Sopenharmony_ci // We've hit or exceeded the max value divided by 10 (rounded down). If 1753ffe3c632Sopenharmony_ci // a) we've only just touched the limit, b) this is the last digit, and 1754ffe3c632Sopenharmony_ci // c) it's small enough to fit in that rounding delta, we're okay. 1755ffe3c632Sopenharmony_ci // Otherwise treat this number as a double to avoid overflow. 1756ffe3c632Sopenharmony_ci if (value > threshold || current != token.end_ || 1757ffe3c632Sopenharmony_ci digit > maxIntegerValue % 10) { 1758ffe3c632Sopenharmony_ci return decodeDouble(token, decoded); 1759ffe3c632Sopenharmony_ci } 1760ffe3c632Sopenharmony_ci } 1761ffe3c632Sopenharmony_ci value = value * 10 + digit; 1762ffe3c632Sopenharmony_ci } 1763ffe3c632Sopenharmony_ci if (isNegative) 1764ffe3c632Sopenharmony_ci decoded = -Value::LargestInt(value); 1765ffe3c632Sopenharmony_ci else if (value <= Value::LargestUInt(Value::maxInt)) 1766ffe3c632Sopenharmony_ci decoded = Value::LargestInt(value); 1767ffe3c632Sopenharmony_ci else 1768ffe3c632Sopenharmony_ci decoded = value; 1769ffe3c632Sopenharmony_ci return true; 1770ffe3c632Sopenharmony_ci} 1771ffe3c632Sopenharmony_ci 1772ffe3c632Sopenharmony_cibool OurReader::decodeDouble(Token& token) { 1773ffe3c632Sopenharmony_ci Value decoded; 1774ffe3c632Sopenharmony_ci if (!decodeDouble(token, decoded)) 1775ffe3c632Sopenharmony_ci return false; 1776ffe3c632Sopenharmony_ci currentValue().swapPayload(decoded); 1777ffe3c632Sopenharmony_ci currentValue().setOffsetStart(token.start_ - begin_); 1778ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(token.end_ - begin_); 1779ffe3c632Sopenharmony_ci return true; 1780ffe3c632Sopenharmony_ci} 1781ffe3c632Sopenharmony_ci 1782ffe3c632Sopenharmony_cibool OurReader::decodeDouble(Token& token, Value& decoded) { 1783ffe3c632Sopenharmony_ci double value = 0; 1784ffe3c632Sopenharmony_ci const int bufferSize = 32; 1785ffe3c632Sopenharmony_ci int count; 1786ffe3c632Sopenharmony_ci int length = int(token.end_ - token.start_); 1787ffe3c632Sopenharmony_ci 1788ffe3c632Sopenharmony_ci // Sanity check to avoid buffer overflow exploits. 1789ffe3c632Sopenharmony_ci if (length < 0) { 1790ffe3c632Sopenharmony_ci return addError("Unable to parse token length", token); 1791ffe3c632Sopenharmony_ci } 1792ffe3c632Sopenharmony_ci 1793ffe3c632Sopenharmony_ci // Avoid using a string constant for the format control string given to 1794ffe3c632Sopenharmony_ci // sscanf, as this can cause hard to debug crashes on OS X. See here for more 1795ffe3c632Sopenharmony_ci // info: 1796ffe3c632Sopenharmony_ci // 1797ffe3c632Sopenharmony_ci // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html 1798ffe3c632Sopenharmony_ci char format[] = "%lf"; 1799ffe3c632Sopenharmony_ci 1800ffe3c632Sopenharmony_ci if (length <= bufferSize) { 1801ffe3c632Sopenharmony_ci Char buffer[bufferSize + 1]; 1802ffe3c632Sopenharmony_ci memcpy(buffer, token.start_, length); 1803ffe3c632Sopenharmony_ci buffer[length] = 0; 1804ffe3c632Sopenharmony_ci count = sscanf(buffer, format, &value); 1805ffe3c632Sopenharmony_ci } else { 1806ffe3c632Sopenharmony_ci std::string buffer(token.start_, token.end_); 1807ffe3c632Sopenharmony_ci count = sscanf(buffer.c_str(), format, &value); 1808ffe3c632Sopenharmony_ci } 1809ffe3c632Sopenharmony_ci 1810ffe3c632Sopenharmony_ci if (count != 1) 1811ffe3c632Sopenharmony_ci return addError("'" + std::string(token.start_, token.end_) + 1812ffe3c632Sopenharmony_ci "' is not a number.", 1813ffe3c632Sopenharmony_ci token); 1814ffe3c632Sopenharmony_ci decoded = value; 1815ffe3c632Sopenharmony_ci return true; 1816ffe3c632Sopenharmony_ci} 1817ffe3c632Sopenharmony_ci 1818ffe3c632Sopenharmony_cibool OurReader::decodeString(Token& token) { 1819ffe3c632Sopenharmony_ci std::string decoded_string; 1820ffe3c632Sopenharmony_ci if (!decodeString(token, decoded_string)) 1821ffe3c632Sopenharmony_ci return false; 1822ffe3c632Sopenharmony_ci Value decoded(decoded_string); 1823ffe3c632Sopenharmony_ci currentValue().swapPayload(decoded); 1824ffe3c632Sopenharmony_ci currentValue().setOffsetStart(token.start_ - begin_); 1825ffe3c632Sopenharmony_ci currentValue().setOffsetLimit(token.end_ - begin_); 1826ffe3c632Sopenharmony_ci return true; 1827ffe3c632Sopenharmony_ci} 1828ffe3c632Sopenharmony_ci 1829ffe3c632Sopenharmony_cibool OurReader::decodeString(Token& token, std::string& decoded) { 1830ffe3c632Sopenharmony_ci decoded.reserve(token.end_ - token.start_ - 2); 1831ffe3c632Sopenharmony_ci Location current = token.start_ + 1; // skip '"' 1832ffe3c632Sopenharmony_ci Location end = token.end_ - 1; // do not include '"' 1833ffe3c632Sopenharmony_ci while (current != end) { 1834ffe3c632Sopenharmony_ci Char c = *current++; 1835ffe3c632Sopenharmony_ci if (c == '"') 1836ffe3c632Sopenharmony_ci break; 1837ffe3c632Sopenharmony_ci else if (c == '\\') { 1838ffe3c632Sopenharmony_ci if (current == end) 1839ffe3c632Sopenharmony_ci return addError("Empty escape sequence in string", token, current); 1840ffe3c632Sopenharmony_ci Char escape = *current++; 1841ffe3c632Sopenharmony_ci switch (escape) { 1842ffe3c632Sopenharmony_ci case '"': 1843ffe3c632Sopenharmony_ci decoded += '"'; 1844ffe3c632Sopenharmony_ci break; 1845ffe3c632Sopenharmony_ci case '/': 1846ffe3c632Sopenharmony_ci decoded += '/'; 1847ffe3c632Sopenharmony_ci break; 1848ffe3c632Sopenharmony_ci case '\\': 1849ffe3c632Sopenharmony_ci decoded += '\\'; 1850ffe3c632Sopenharmony_ci break; 1851ffe3c632Sopenharmony_ci case 'b': 1852ffe3c632Sopenharmony_ci decoded += '\b'; 1853ffe3c632Sopenharmony_ci break; 1854ffe3c632Sopenharmony_ci case 'f': 1855ffe3c632Sopenharmony_ci decoded += '\f'; 1856ffe3c632Sopenharmony_ci break; 1857ffe3c632Sopenharmony_ci case 'n': 1858ffe3c632Sopenharmony_ci decoded += '\n'; 1859ffe3c632Sopenharmony_ci break; 1860ffe3c632Sopenharmony_ci case 'r': 1861ffe3c632Sopenharmony_ci decoded += '\r'; 1862ffe3c632Sopenharmony_ci break; 1863ffe3c632Sopenharmony_ci case 't': 1864ffe3c632Sopenharmony_ci decoded += '\t'; 1865ffe3c632Sopenharmony_ci break; 1866ffe3c632Sopenharmony_ci case 'u': { 1867ffe3c632Sopenharmony_ci unsigned int unicode; 1868ffe3c632Sopenharmony_ci if (!decodeUnicodeCodePoint(token, current, end, unicode)) 1869ffe3c632Sopenharmony_ci return false; 1870ffe3c632Sopenharmony_ci decoded += codePointToUTF8(unicode); 1871ffe3c632Sopenharmony_ci } break; 1872ffe3c632Sopenharmony_ci default: 1873ffe3c632Sopenharmony_ci return addError("Bad escape sequence in string", token, current); 1874ffe3c632Sopenharmony_ci } 1875ffe3c632Sopenharmony_ci } else { 1876ffe3c632Sopenharmony_ci decoded += c; 1877ffe3c632Sopenharmony_ci } 1878ffe3c632Sopenharmony_ci } 1879ffe3c632Sopenharmony_ci return true; 1880ffe3c632Sopenharmony_ci} 1881ffe3c632Sopenharmony_ci 1882ffe3c632Sopenharmony_cibool OurReader::decodeUnicodeCodePoint(Token& token, 1883ffe3c632Sopenharmony_ci Location& current, 1884ffe3c632Sopenharmony_ci Location end, 1885ffe3c632Sopenharmony_ci unsigned int& unicode) { 1886ffe3c632Sopenharmony_ci 1887ffe3c632Sopenharmony_ci if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) 1888ffe3c632Sopenharmony_ci return false; 1889ffe3c632Sopenharmony_ci if (unicode >= 0xD800 && unicode <= 0xDBFF) { 1890ffe3c632Sopenharmony_ci // surrogate pairs 1891ffe3c632Sopenharmony_ci if (end - current < 6) 1892ffe3c632Sopenharmony_ci return addError( 1893ffe3c632Sopenharmony_ci "additional six characters expected to parse unicode surrogate pair.", 1894ffe3c632Sopenharmony_ci token, 1895ffe3c632Sopenharmony_ci current); 1896ffe3c632Sopenharmony_ci unsigned int surrogatePair; 1897ffe3c632Sopenharmony_ci if (*(current++) == '\\' && *(current++) == 'u') { 1898ffe3c632Sopenharmony_ci if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { 1899ffe3c632Sopenharmony_ci unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); 1900ffe3c632Sopenharmony_ci } else 1901ffe3c632Sopenharmony_ci return false; 1902ffe3c632Sopenharmony_ci } else 1903ffe3c632Sopenharmony_ci return addError("expecting another \\u token to begin the second half of " 1904ffe3c632Sopenharmony_ci "a unicode surrogate pair", 1905ffe3c632Sopenharmony_ci token, 1906ffe3c632Sopenharmony_ci current); 1907ffe3c632Sopenharmony_ci } 1908ffe3c632Sopenharmony_ci return true; 1909ffe3c632Sopenharmony_ci} 1910ffe3c632Sopenharmony_ci 1911ffe3c632Sopenharmony_cibool OurReader::decodeUnicodeEscapeSequence(Token& token, 1912ffe3c632Sopenharmony_ci Location& current, 1913ffe3c632Sopenharmony_ci Location end, 1914ffe3c632Sopenharmony_ci unsigned int& unicode) { 1915ffe3c632Sopenharmony_ci if (end - current < 4) 1916ffe3c632Sopenharmony_ci return addError( 1917ffe3c632Sopenharmony_ci "Bad unicode escape sequence in string: four digits expected.", 1918ffe3c632Sopenharmony_ci token, 1919ffe3c632Sopenharmony_ci current); 1920ffe3c632Sopenharmony_ci unicode = 0; 1921ffe3c632Sopenharmony_ci for (int index = 0; index < 4; ++index) { 1922ffe3c632Sopenharmony_ci Char c = *current++; 1923ffe3c632Sopenharmony_ci unicode *= 16; 1924ffe3c632Sopenharmony_ci if (c >= '0' && c <= '9') 1925ffe3c632Sopenharmony_ci unicode += c - '0'; 1926ffe3c632Sopenharmony_ci else if (c >= 'a' && c <= 'f') 1927ffe3c632Sopenharmony_ci unicode += c - 'a' + 10; 1928ffe3c632Sopenharmony_ci else if (c >= 'A' && c <= 'F') 1929ffe3c632Sopenharmony_ci unicode += c - 'A' + 10; 1930ffe3c632Sopenharmony_ci else 1931ffe3c632Sopenharmony_ci return addError( 1932ffe3c632Sopenharmony_ci "Bad unicode escape sequence in string: hexadecimal digit expected.", 1933ffe3c632Sopenharmony_ci token, 1934ffe3c632Sopenharmony_ci current); 1935ffe3c632Sopenharmony_ci } 1936ffe3c632Sopenharmony_ci return true; 1937ffe3c632Sopenharmony_ci} 1938ffe3c632Sopenharmony_ci 1939ffe3c632Sopenharmony_cibool 1940ffe3c632Sopenharmony_ciOurReader::addError(const std::string& message, Token& token, Location extra) { 1941ffe3c632Sopenharmony_ci ErrorInfo info; 1942ffe3c632Sopenharmony_ci info.token_ = token; 1943ffe3c632Sopenharmony_ci info.message_ = message; 1944ffe3c632Sopenharmony_ci info.extra_ = extra; 1945ffe3c632Sopenharmony_ci errors_.push_back(info); 1946ffe3c632Sopenharmony_ci return false; 1947ffe3c632Sopenharmony_ci} 1948ffe3c632Sopenharmony_ci 1949ffe3c632Sopenharmony_cibool OurReader::recoverFromError(TokenType skipUntilToken) { 1950ffe3c632Sopenharmony_ci int errorCount = int(errors_.size()); 1951ffe3c632Sopenharmony_ci Token skip; 1952ffe3c632Sopenharmony_ci for (;;) { 1953ffe3c632Sopenharmony_ci if (!readToken(skip)) 1954ffe3c632Sopenharmony_ci errors_.resize(errorCount); // discard errors caused by recovery 1955ffe3c632Sopenharmony_ci if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) 1956ffe3c632Sopenharmony_ci break; 1957ffe3c632Sopenharmony_ci } 1958ffe3c632Sopenharmony_ci errors_.resize(errorCount); 1959ffe3c632Sopenharmony_ci return false; 1960ffe3c632Sopenharmony_ci} 1961ffe3c632Sopenharmony_ci 1962ffe3c632Sopenharmony_cibool OurReader::addErrorAndRecover(const std::string& message, 1963ffe3c632Sopenharmony_ci Token& token, 1964ffe3c632Sopenharmony_ci TokenType skipUntilToken) { 1965ffe3c632Sopenharmony_ci addError(message, token); 1966ffe3c632Sopenharmony_ci return recoverFromError(skipUntilToken); 1967ffe3c632Sopenharmony_ci} 1968ffe3c632Sopenharmony_ci 1969ffe3c632Sopenharmony_ciValue& OurReader::currentValue() { return *(nodes_.top()); } 1970ffe3c632Sopenharmony_ci 1971ffe3c632Sopenharmony_ciOurReader::Char OurReader::getNextChar() { 1972ffe3c632Sopenharmony_ci if (current_ == end_) 1973ffe3c632Sopenharmony_ci return 0; 1974ffe3c632Sopenharmony_ci return *current_++; 1975ffe3c632Sopenharmony_ci} 1976ffe3c632Sopenharmony_ci 1977ffe3c632Sopenharmony_civoid OurReader::getLocationLineAndColumn(Location location, 1978ffe3c632Sopenharmony_ci int& line, 1979ffe3c632Sopenharmony_ci int& column) const { 1980ffe3c632Sopenharmony_ci Location current = begin_; 1981ffe3c632Sopenharmony_ci Location lastLineStart = current; 1982ffe3c632Sopenharmony_ci line = 0; 1983ffe3c632Sopenharmony_ci while (current < location && current != end_) { 1984ffe3c632Sopenharmony_ci Char c = *current++; 1985ffe3c632Sopenharmony_ci if (c == '\r') { 1986ffe3c632Sopenharmony_ci if (*current == '\n') 1987ffe3c632Sopenharmony_ci ++current; 1988ffe3c632Sopenharmony_ci lastLineStart = current; 1989ffe3c632Sopenharmony_ci ++line; 1990ffe3c632Sopenharmony_ci } else if (c == '\n') { 1991ffe3c632Sopenharmony_ci lastLineStart = current; 1992ffe3c632Sopenharmony_ci ++line; 1993ffe3c632Sopenharmony_ci } 1994ffe3c632Sopenharmony_ci } 1995ffe3c632Sopenharmony_ci // column & line start at 1 1996ffe3c632Sopenharmony_ci column = int(location - lastLineStart) + 1; 1997ffe3c632Sopenharmony_ci ++line; 1998ffe3c632Sopenharmony_ci} 1999ffe3c632Sopenharmony_ci 2000ffe3c632Sopenharmony_cistd::string OurReader::getLocationLineAndColumn(Location location) const { 2001ffe3c632Sopenharmony_ci int line, column; 2002ffe3c632Sopenharmony_ci getLocationLineAndColumn(location, line, column); 2003ffe3c632Sopenharmony_ci char buffer[18 + 16 + 16 + 1]; 2004ffe3c632Sopenharmony_ci snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); 2005ffe3c632Sopenharmony_ci return buffer; 2006ffe3c632Sopenharmony_ci} 2007ffe3c632Sopenharmony_ci 2008ffe3c632Sopenharmony_cistd::string OurReader::getFormattedErrorMessages() const { 2009ffe3c632Sopenharmony_ci std::string formattedMessage; 2010ffe3c632Sopenharmony_ci for (Errors::const_iterator itError = errors_.begin(); 2011ffe3c632Sopenharmony_ci itError != errors_.end(); 2012ffe3c632Sopenharmony_ci ++itError) { 2013ffe3c632Sopenharmony_ci const ErrorInfo& error = *itError; 2014ffe3c632Sopenharmony_ci formattedMessage += 2015ffe3c632Sopenharmony_ci "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; 2016ffe3c632Sopenharmony_ci formattedMessage += " " + error.message_ + "\n"; 2017ffe3c632Sopenharmony_ci if (error.extra_) 2018ffe3c632Sopenharmony_ci formattedMessage += 2019ffe3c632Sopenharmony_ci "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; 2020ffe3c632Sopenharmony_ci } 2021ffe3c632Sopenharmony_ci return formattedMessage; 2022ffe3c632Sopenharmony_ci} 2023ffe3c632Sopenharmony_ci 2024ffe3c632Sopenharmony_cistd::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const { 2025ffe3c632Sopenharmony_ci std::vector<OurReader::StructuredError> allErrors; 2026ffe3c632Sopenharmony_ci for (Errors::const_iterator itError = errors_.begin(); 2027ffe3c632Sopenharmony_ci itError != errors_.end(); 2028ffe3c632Sopenharmony_ci ++itError) { 2029ffe3c632Sopenharmony_ci const ErrorInfo& error = *itError; 2030ffe3c632Sopenharmony_ci OurReader::StructuredError structured; 2031ffe3c632Sopenharmony_ci structured.offset_start = error.token_.start_ - begin_; 2032ffe3c632Sopenharmony_ci structured.offset_limit = error.token_.end_ - begin_; 2033ffe3c632Sopenharmony_ci structured.message = error.message_; 2034ffe3c632Sopenharmony_ci allErrors.push_back(structured); 2035ffe3c632Sopenharmony_ci } 2036ffe3c632Sopenharmony_ci return allErrors; 2037ffe3c632Sopenharmony_ci} 2038ffe3c632Sopenharmony_ci 2039ffe3c632Sopenharmony_cibool OurReader::pushError(const Value& value, const std::string& message) { 2040ffe3c632Sopenharmony_ci size_t length = end_ - begin_; 2041ffe3c632Sopenharmony_ci if(value.getOffsetStart() > length 2042ffe3c632Sopenharmony_ci || value.getOffsetLimit() > length) 2043ffe3c632Sopenharmony_ci return false; 2044ffe3c632Sopenharmony_ci Token token; 2045ffe3c632Sopenharmony_ci token.type_ = tokenError; 2046ffe3c632Sopenharmony_ci token.start_ = begin_ + value.getOffsetStart(); 2047ffe3c632Sopenharmony_ci token.end_ = end_ + value.getOffsetLimit(); 2048ffe3c632Sopenharmony_ci ErrorInfo info; 2049ffe3c632Sopenharmony_ci info.token_ = token; 2050ffe3c632Sopenharmony_ci info.message_ = message; 2051ffe3c632Sopenharmony_ci info.extra_ = 0; 2052ffe3c632Sopenharmony_ci errors_.push_back(info); 2053ffe3c632Sopenharmony_ci return true; 2054ffe3c632Sopenharmony_ci} 2055ffe3c632Sopenharmony_ci 2056ffe3c632Sopenharmony_cibool OurReader::pushError(const Value& value, const std::string& message, const Value& extra) { 2057ffe3c632Sopenharmony_ci size_t length = end_ - begin_; 2058ffe3c632Sopenharmony_ci if(value.getOffsetStart() > length 2059ffe3c632Sopenharmony_ci || value.getOffsetLimit() > length 2060ffe3c632Sopenharmony_ci || extra.getOffsetLimit() > length) 2061ffe3c632Sopenharmony_ci return false; 2062ffe3c632Sopenharmony_ci Token token; 2063ffe3c632Sopenharmony_ci token.type_ = tokenError; 2064ffe3c632Sopenharmony_ci token.start_ = begin_ + value.getOffsetStart(); 2065ffe3c632Sopenharmony_ci token.end_ = begin_ + value.getOffsetLimit(); 2066ffe3c632Sopenharmony_ci ErrorInfo info; 2067ffe3c632Sopenharmony_ci info.token_ = token; 2068ffe3c632Sopenharmony_ci info.message_ = message; 2069ffe3c632Sopenharmony_ci info.extra_ = begin_ + extra.getOffsetStart(); 2070ffe3c632Sopenharmony_ci errors_.push_back(info); 2071ffe3c632Sopenharmony_ci return true; 2072ffe3c632Sopenharmony_ci} 2073ffe3c632Sopenharmony_ci 2074ffe3c632Sopenharmony_cibool OurReader::good() const { 2075ffe3c632Sopenharmony_ci return !errors_.size(); 2076ffe3c632Sopenharmony_ci} 2077ffe3c632Sopenharmony_ci 2078ffe3c632Sopenharmony_ci 2079ffe3c632Sopenharmony_ciclass OurCharReader : public CharReader { 2080ffe3c632Sopenharmony_ci bool const collectComments_; 2081ffe3c632Sopenharmony_ci OurReader reader_; 2082ffe3c632Sopenharmony_cipublic: 2083ffe3c632Sopenharmony_ci OurCharReader( 2084ffe3c632Sopenharmony_ci bool collectComments, 2085ffe3c632Sopenharmony_ci OurFeatures const& features) 2086ffe3c632Sopenharmony_ci : collectComments_(collectComments) 2087ffe3c632Sopenharmony_ci , reader_(features) 2088ffe3c632Sopenharmony_ci {} 2089ffe3c632Sopenharmony_ci bool parse( 2090ffe3c632Sopenharmony_ci char const* beginDoc, char const* endDoc, 2091ffe3c632Sopenharmony_ci Value* root, std::string* errs) override { 2092ffe3c632Sopenharmony_ci bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_); 2093ffe3c632Sopenharmony_ci if (errs) { 2094ffe3c632Sopenharmony_ci *errs = reader_.getFormattedErrorMessages(); 2095ffe3c632Sopenharmony_ci } 2096ffe3c632Sopenharmony_ci return ok; 2097ffe3c632Sopenharmony_ci } 2098ffe3c632Sopenharmony_ci}; 2099ffe3c632Sopenharmony_ci 2100ffe3c632Sopenharmony_ciCharReaderBuilder::CharReaderBuilder() 2101ffe3c632Sopenharmony_ci{ 2102ffe3c632Sopenharmony_ci setDefaults(&settings_); 2103ffe3c632Sopenharmony_ci} 2104ffe3c632Sopenharmony_ciCharReaderBuilder::~CharReaderBuilder() 2105ffe3c632Sopenharmony_ci{} 2106ffe3c632Sopenharmony_ciCharReader* CharReaderBuilder::newCharReader() const 2107ffe3c632Sopenharmony_ci{ 2108ffe3c632Sopenharmony_ci bool collectComments = settings_["collectComments"].asBool(); 2109ffe3c632Sopenharmony_ci OurFeatures features = OurFeatures::all(); 2110ffe3c632Sopenharmony_ci features.allowComments_ = settings_["allowComments"].asBool(); 2111ffe3c632Sopenharmony_ci features.strictRoot_ = settings_["strictRoot"].asBool(); 2112ffe3c632Sopenharmony_ci features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool(); 2113ffe3c632Sopenharmony_ci features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool(); 2114ffe3c632Sopenharmony_ci features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool(); 2115ffe3c632Sopenharmony_ci features.stackLimit_ = settings_["stackLimit"].asInt(); 2116ffe3c632Sopenharmony_ci features.failIfExtra_ = settings_["failIfExtra"].asBool(); 2117ffe3c632Sopenharmony_ci features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool(); 2118ffe3c632Sopenharmony_ci features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool(); 2119ffe3c632Sopenharmony_ci return new OurCharReader(collectComments, features); 2120ffe3c632Sopenharmony_ci} 2121ffe3c632Sopenharmony_cistatic void getValidReaderKeys(std::set<std::string>* valid_keys) 2122ffe3c632Sopenharmony_ci{ 2123ffe3c632Sopenharmony_ci valid_keys->clear(); 2124ffe3c632Sopenharmony_ci valid_keys->insert("collectComments"); 2125ffe3c632Sopenharmony_ci valid_keys->insert("allowComments"); 2126ffe3c632Sopenharmony_ci valid_keys->insert("strictRoot"); 2127ffe3c632Sopenharmony_ci valid_keys->insert("allowDroppedNullPlaceholders"); 2128ffe3c632Sopenharmony_ci valid_keys->insert("allowNumericKeys"); 2129ffe3c632Sopenharmony_ci valid_keys->insert("allowSingleQuotes"); 2130ffe3c632Sopenharmony_ci valid_keys->insert("stackLimit"); 2131ffe3c632Sopenharmony_ci valid_keys->insert("failIfExtra"); 2132ffe3c632Sopenharmony_ci valid_keys->insert("rejectDupKeys"); 2133ffe3c632Sopenharmony_ci valid_keys->insert("allowSpecialFloats"); 2134ffe3c632Sopenharmony_ci} 2135ffe3c632Sopenharmony_cibool CharReaderBuilder::validate(Json::Value* invalid) const 2136ffe3c632Sopenharmony_ci{ 2137ffe3c632Sopenharmony_ci Json::Value my_invalid; 2138ffe3c632Sopenharmony_ci if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL 2139ffe3c632Sopenharmony_ci Json::Value& inv = *invalid; 2140ffe3c632Sopenharmony_ci std::set<std::string> valid_keys; 2141ffe3c632Sopenharmony_ci getValidReaderKeys(&valid_keys); 2142ffe3c632Sopenharmony_ci Value::Members keys = settings_.getMemberNames(); 2143ffe3c632Sopenharmony_ci size_t n = keys.size(); 2144ffe3c632Sopenharmony_ci for (size_t i = 0; i < n; ++i) { 2145ffe3c632Sopenharmony_ci std::string const& key = keys[i]; 2146ffe3c632Sopenharmony_ci if (valid_keys.find(key) == valid_keys.end()) { 2147ffe3c632Sopenharmony_ci inv[key] = settings_[key]; 2148ffe3c632Sopenharmony_ci } 2149ffe3c632Sopenharmony_ci } 2150ffe3c632Sopenharmony_ci return 0u == inv.size(); 2151ffe3c632Sopenharmony_ci} 2152ffe3c632Sopenharmony_ciValue& CharReaderBuilder::operator[](std::string key) 2153ffe3c632Sopenharmony_ci{ 2154ffe3c632Sopenharmony_ci return settings_[key]; 2155ffe3c632Sopenharmony_ci} 2156ffe3c632Sopenharmony_ci// static 2157ffe3c632Sopenharmony_civoid CharReaderBuilder::strictMode(Json::Value* settings) 2158ffe3c632Sopenharmony_ci{ 2159ffe3c632Sopenharmony_ci//! [CharReaderBuilderStrictMode] 2160ffe3c632Sopenharmony_ci (*settings)["allowComments"] = false; 2161ffe3c632Sopenharmony_ci (*settings)["strictRoot"] = true; 2162ffe3c632Sopenharmony_ci (*settings)["allowDroppedNullPlaceholders"] = false; 2163ffe3c632Sopenharmony_ci (*settings)["allowNumericKeys"] = false; 2164ffe3c632Sopenharmony_ci (*settings)["allowSingleQuotes"] = false; 2165ffe3c632Sopenharmony_ci (*settings)["stackLimit"] = 1000; 2166ffe3c632Sopenharmony_ci (*settings)["failIfExtra"] = true; 2167ffe3c632Sopenharmony_ci (*settings)["rejectDupKeys"] = true; 2168ffe3c632Sopenharmony_ci (*settings)["allowSpecialFloats"] = false; 2169ffe3c632Sopenharmony_ci//! [CharReaderBuilderStrictMode] 2170ffe3c632Sopenharmony_ci} 2171ffe3c632Sopenharmony_ci// static 2172ffe3c632Sopenharmony_civoid CharReaderBuilder::setDefaults(Json::Value* settings) 2173ffe3c632Sopenharmony_ci{ 2174ffe3c632Sopenharmony_ci//! [CharReaderBuilderDefaults] 2175ffe3c632Sopenharmony_ci (*settings)["collectComments"] = true; 2176ffe3c632Sopenharmony_ci (*settings)["allowComments"] = true; 2177ffe3c632Sopenharmony_ci (*settings)["strictRoot"] = false; 2178ffe3c632Sopenharmony_ci (*settings)["allowDroppedNullPlaceholders"] = false; 2179ffe3c632Sopenharmony_ci (*settings)["allowNumericKeys"] = false; 2180ffe3c632Sopenharmony_ci (*settings)["allowSingleQuotes"] = false; 2181ffe3c632Sopenharmony_ci (*settings)["stackLimit"] = 1000; 2182ffe3c632Sopenharmony_ci (*settings)["failIfExtra"] = false; 2183ffe3c632Sopenharmony_ci (*settings)["rejectDupKeys"] = false; 2184ffe3c632Sopenharmony_ci (*settings)["allowSpecialFloats"] = false; 2185ffe3c632Sopenharmony_ci//! [CharReaderBuilderDefaults] 2186ffe3c632Sopenharmony_ci} 2187ffe3c632Sopenharmony_ci 2188ffe3c632Sopenharmony_ci////////////////////////////////// 2189ffe3c632Sopenharmony_ci// global functions 2190ffe3c632Sopenharmony_ci 2191ffe3c632Sopenharmony_cibool parseFromStream( 2192ffe3c632Sopenharmony_ci CharReader::Factory const& fact, std::istream& sin, 2193ffe3c632Sopenharmony_ci Value* root, std::string* errs) 2194ffe3c632Sopenharmony_ci{ 2195ffe3c632Sopenharmony_ci std::ostringstream ssin; 2196ffe3c632Sopenharmony_ci ssin << sin.rdbuf(); 2197ffe3c632Sopenharmony_ci std::string doc = ssin.str(); 2198ffe3c632Sopenharmony_ci char const* begin = doc.data(); 2199ffe3c632Sopenharmony_ci char const* end = begin + doc.size(); 2200ffe3c632Sopenharmony_ci // Note that we do not actually need a null-terminator. 2201ffe3c632Sopenharmony_ci CharReaderPtr const reader(fact.newCharReader()); 2202ffe3c632Sopenharmony_ci return reader->parse(begin, end, root, errs); 2203ffe3c632Sopenharmony_ci} 2204ffe3c632Sopenharmony_ci 2205ffe3c632Sopenharmony_cistd::istream& operator>>(std::istream& sin, Value& root) { 2206ffe3c632Sopenharmony_ci CharReaderBuilder b; 2207ffe3c632Sopenharmony_ci std::string errs; 2208ffe3c632Sopenharmony_ci bool ok = parseFromStream(b, sin, &root, &errs); 2209ffe3c632Sopenharmony_ci if (!ok) { 2210ffe3c632Sopenharmony_ci fprintf(stderr, 2211ffe3c632Sopenharmony_ci "Error from reader: %s", 2212ffe3c632Sopenharmony_ci errs.c_str()); 2213ffe3c632Sopenharmony_ci 2214ffe3c632Sopenharmony_ci throwRuntimeError(errs); 2215ffe3c632Sopenharmony_ci } 2216ffe3c632Sopenharmony_ci return sin; 2217ffe3c632Sopenharmony_ci} 2218ffe3c632Sopenharmony_ci 2219ffe3c632Sopenharmony_ci} // namespace Json 2220ffe3c632Sopenharmony_ci 2221ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 2222ffe3c632Sopenharmony_ci// End of content of file: src/lib_json/json_reader.cpp 2223ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 2224ffe3c632Sopenharmony_ci 2225ffe3c632Sopenharmony_ci 2226ffe3c632Sopenharmony_ci 2227ffe3c632Sopenharmony_ci 2228ffe3c632Sopenharmony_ci 2229ffe3c632Sopenharmony_ci 2230ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 2231ffe3c632Sopenharmony_ci// Beginning of content of file: src/lib_json/json_valueiterator.inl 2232ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 2233ffe3c632Sopenharmony_ci 2234ffe3c632Sopenharmony_ci// Copyright 2007-2010 Baptiste Lepilleur 2235ffe3c632Sopenharmony_ci// Distributed under MIT license, or public domain if desired and 2236ffe3c632Sopenharmony_ci// recognized in your jurisdiction. 2237ffe3c632Sopenharmony_ci// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 2238ffe3c632Sopenharmony_ci 2239ffe3c632Sopenharmony_ci// included by json_value.cpp 2240ffe3c632Sopenharmony_ci 2241ffe3c632Sopenharmony_cinamespace Json { 2242ffe3c632Sopenharmony_ci 2243ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2244ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2245ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2246ffe3c632Sopenharmony_ci// class ValueIteratorBase 2247ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2248ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2249ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2250ffe3c632Sopenharmony_ci 2251ffe3c632Sopenharmony_ciValueIteratorBase::ValueIteratorBase() 2252ffe3c632Sopenharmony_ci : current_(), isNull_(true) { 2253ffe3c632Sopenharmony_ci} 2254ffe3c632Sopenharmony_ci 2255ffe3c632Sopenharmony_ciValueIteratorBase::ValueIteratorBase( 2256ffe3c632Sopenharmony_ci const Value::ObjectValues::iterator& current) 2257ffe3c632Sopenharmony_ci : current_(current), isNull_(false) {} 2258ffe3c632Sopenharmony_ci 2259ffe3c632Sopenharmony_ciValue& ValueIteratorBase::deref() const { 2260ffe3c632Sopenharmony_ci return current_->second; 2261ffe3c632Sopenharmony_ci} 2262ffe3c632Sopenharmony_ci 2263ffe3c632Sopenharmony_civoid ValueIteratorBase::increment() { 2264ffe3c632Sopenharmony_ci ++current_; 2265ffe3c632Sopenharmony_ci} 2266ffe3c632Sopenharmony_ci 2267ffe3c632Sopenharmony_civoid ValueIteratorBase::decrement() { 2268ffe3c632Sopenharmony_ci --current_; 2269ffe3c632Sopenharmony_ci} 2270ffe3c632Sopenharmony_ci 2271ffe3c632Sopenharmony_ciValueIteratorBase::difference_type 2272ffe3c632Sopenharmony_ciValueIteratorBase::computeDistance(const SelfType& other) const { 2273ffe3c632Sopenharmony_ci#ifdef JSON_USE_CPPTL_SMALLMAP 2274ffe3c632Sopenharmony_ci return other.current_ - current_; 2275ffe3c632Sopenharmony_ci#else 2276ffe3c632Sopenharmony_ci // Iterator for null value are initialized using the default 2277ffe3c632Sopenharmony_ci // constructor, which initialize current_ to the default 2278ffe3c632Sopenharmony_ci // std::map::iterator. As begin() and end() are two instance 2279ffe3c632Sopenharmony_ci // of the default std::map::iterator, they can not be compared. 2280ffe3c632Sopenharmony_ci // To allow this, we handle this comparison specifically. 2281ffe3c632Sopenharmony_ci if (isNull_ && other.isNull_) { 2282ffe3c632Sopenharmony_ci return 0; 2283ffe3c632Sopenharmony_ci } 2284ffe3c632Sopenharmony_ci 2285ffe3c632Sopenharmony_ci // Usage of std::distance is not portable (does not compile with Sun Studio 12 2286ffe3c632Sopenharmony_ci // RogueWave STL, 2287ffe3c632Sopenharmony_ci // which is the one used by default). 2288ffe3c632Sopenharmony_ci // Using a portable hand-made version for non random iterator instead: 2289ffe3c632Sopenharmony_ci // return difference_type( std::distance( current_, other.current_ ) ); 2290ffe3c632Sopenharmony_ci difference_type myDistance = 0; 2291ffe3c632Sopenharmony_ci for (Value::ObjectValues::iterator it = current_; it != other.current_; 2292ffe3c632Sopenharmony_ci ++it) { 2293ffe3c632Sopenharmony_ci ++myDistance; 2294ffe3c632Sopenharmony_ci } 2295ffe3c632Sopenharmony_ci return myDistance; 2296ffe3c632Sopenharmony_ci#endif 2297ffe3c632Sopenharmony_ci} 2298ffe3c632Sopenharmony_ci 2299ffe3c632Sopenharmony_cibool ValueIteratorBase::isEqual(const SelfType& other) const { 2300ffe3c632Sopenharmony_ci if (isNull_) { 2301ffe3c632Sopenharmony_ci return other.isNull_; 2302ffe3c632Sopenharmony_ci } 2303ffe3c632Sopenharmony_ci return current_ == other.current_; 2304ffe3c632Sopenharmony_ci} 2305ffe3c632Sopenharmony_ci 2306ffe3c632Sopenharmony_civoid ValueIteratorBase::copy(const SelfType& other) { 2307ffe3c632Sopenharmony_ci current_ = other.current_; 2308ffe3c632Sopenharmony_ci isNull_ = other.isNull_; 2309ffe3c632Sopenharmony_ci} 2310ffe3c632Sopenharmony_ci 2311ffe3c632Sopenharmony_ciValue ValueIteratorBase::key() const { 2312ffe3c632Sopenharmony_ci const Value::CZString czstring = (*current_).first; 2313ffe3c632Sopenharmony_ci if (czstring.data()) { 2314ffe3c632Sopenharmony_ci if (czstring.isStaticString()) 2315ffe3c632Sopenharmony_ci return Value(StaticString(czstring.data())); 2316ffe3c632Sopenharmony_ci return Value(czstring.data(), czstring.data() + czstring.length()); 2317ffe3c632Sopenharmony_ci } 2318ffe3c632Sopenharmony_ci return Value(czstring.index()); 2319ffe3c632Sopenharmony_ci} 2320ffe3c632Sopenharmony_ci 2321ffe3c632Sopenharmony_ciUInt ValueIteratorBase::index() const { 2322ffe3c632Sopenharmony_ci const Value::CZString czstring = (*current_).first; 2323ffe3c632Sopenharmony_ci if (!czstring.data()) 2324ffe3c632Sopenharmony_ci return czstring.index(); 2325ffe3c632Sopenharmony_ci return Value::UInt(-1); 2326ffe3c632Sopenharmony_ci} 2327ffe3c632Sopenharmony_ci 2328ffe3c632Sopenharmony_cistd::string ValueIteratorBase::name() const { 2329ffe3c632Sopenharmony_ci char const* keey; 2330ffe3c632Sopenharmony_ci char const* end; 2331ffe3c632Sopenharmony_ci keey = memberName(&end); 2332ffe3c632Sopenharmony_ci if (!keey) return std::string(); 2333ffe3c632Sopenharmony_ci return std::string(keey, end); 2334ffe3c632Sopenharmony_ci} 2335ffe3c632Sopenharmony_ci 2336ffe3c632Sopenharmony_cichar const* ValueIteratorBase::memberName() const { 2337ffe3c632Sopenharmony_ci const char* cname = (*current_).first.data(); 2338ffe3c632Sopenharmony_ci return cname ? cname : ""; 2339ffe3c632Sopenharmony_ci} 2340ffe3c632Sopenharmony_ci 2341ffe3c632Sopenharmony_cichar const* ValueIteratorBase::memberName(char const** end) const { 2342ffe3c632Sopenharmony_ci const char* cname = (*current_).first.data(); 2343ffe3c632Sopenharmony_ci if (!cname) { 2344ffe3c632Sopenharmony_ci *end = NULL; 2345ffe3c632Sopenharmony_ci return NULL; 2346ffe3c632Sopenharmony_ci } 2347ffe3c632Sopenharmony_ci *end = cname + (*current_).first.length(); 2348ffe3c632Sopenharmony_ci return cname; 2349ffe3c632Sopenharmony_ci} 2350ffe3c632Sopenharmony_ci 2351ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2352ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2353ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2354ffe3c632Sopenharmony_ci// class ValueConstIterator 2355ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2356ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2357ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2358ffe3c632Sopenharmony_ci 2359ffe3c632Sopenharmony_ciValueConstIterator::ValueConstIterator() {} 2360ffe3c632Sopenharmony_ci 2361ffe3c632Sopenharmony_ciValueConstIterator::ValueConstIterator( 2362ffe3c632Sopenharmony_ci const Value::ObjectValues::iterator& current) 2363ffe3c632Sopenharmony_ci : ValueIteratorBase(current) {} 2364ffe3c632Sopenharmony_ci 2365ffe3c632Sopenharmony_ciValueConstIterator::ValueConstIterator(ValueIterator const& other) 2366ffe3c632Sopenharmony_ci : ValueIteratorBase(other) {} 2367ffe3c632Sopenharmony_ci 2368ffe3c632Sopenharmony_ciValueConstIterator& ValueConstIterator:: 2369ffe3c632Sopenharmony_cioperator=(const ValueIteratorBase& other) { 2370ffe3c632Sopenharmony_ci copy(other); 2371ffe3c632Sopenharmony_ci return *this; 2372ffe3c632Sopenharmony_ci} 2373ffe3c632Sopenharmony_ci 2374ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2375ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2376ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2377ffe3c632Sopenharmony_ci// class ValueIterator 2378ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2379ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2380ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2381ffe3c632Sopenharmony_ci 2382ffe3c632Sopenharmony_ciValueIterator::ValueIterator() {} 2383ffe3c632Sopenharmony_ci 2384ffe3c632Sopenharmony_ciValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) 2385ffe3c632Sopenharmony_ci : ValueIteratorBase(current) {} 2386ffe3c632Sopenharmony_ci 2387ffe3c632Sopenharmony_ciValueIterator::ValueIterator(const ValueConstIterator& other) 2388ffe3c632Sopenharmony_ci : ValueIteratorBase(other) { 2389ffe3c632Sopenharmony_ci throwRuntimeError("ConstIterator to Iterator should never be allowed."); 2390ffe3c632Sopenharmony_ci} 2391ffe3c632Sopenharmony_ci 2392ffe3c632Sopenharmony_ciValueIterator::ValueIterator(const ValueIterator& other) 2393ffe3c632Sopenharmony_ci : ValueIteratorBase(other) {} 2394ffe3c632Sopenharmony_ci 2395ffe3c632Sopenharmony_ciValueIterator& ValueIterator::operator=(const SelfType& other) { 2396ffe3c632Sopenharmony_ci copy(other); 2397ffe3c632Sopenharmony_ci return *this; 2398ffe3c632Sopenharmony_ci} 2399ffe3c632Sopenharmony_ci 2400ffe3c632Sopenharmony_ci} // namespace Json 2401ffe3c632Sopenharmony_ci 2402ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 2403ffe3c632Sopenharmony_ci// End of content of file: src/lib_json/json_valueiterator.inl 2404ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 2405ffe3c632Sopenharmony_ci 2406ffe3c632Sopenharmony_ci 2407ffe3c632Sopenharmony_ci 2408ffe3c632Sopenharmony_ci 2409ffe3c632Sopenharmony_ci 2410ffe3c632Sopenharmony_ci 2411ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 2412ffe3c632Sopenharmony_ci// Beginning of content of file: src/lib_json/json_value.cpp 2413ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 2414ffe3c632Sopenharmony_ci 2415ffe3c632Sopenharmony_ci// Copyright 2011 Baptiste Lepilleur 2416ffe3c632Sopenharmony_ci// Distributed under MIT license, or public domain if desired and 2417ffe3c632Sopenharmony_ci// recognized in your jurisdiction. 2418ffe3c632Sopenharmony_ci// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 2419ffe3c632Sopenharmony_ci 2420ffe3c632Sopenharmony_ci#if !defined(JSON_IS_AMALGAMATION) 2421ffe3c632Sopenharmony_ci#include <json/assertions.h> 2422ffe3c632Sopenharmony_ci#include <json/value.h> 2423ffe3c632Sopenharmony_ci#include <json/writer.h> 2424ffe3c632Sopenharmony_ci#endif // if !defined(JSON_IS_AMALGAMATION) 2425ffe3c632Sopenharmony_ci#include <math.h> 2426ffe3c632Sopenharmony_ci#include <sstream> 2427ffe3c632Sopenharmony_ci#include <utility> 2428ffe3c632Sopenharmony_ci#include <cstring> 2429ffe3c632Sopenharmony_ci#include <cassert> 2430ffe3c632Sopenharmony_ci#ifdef JSON_USE_CPPTL 2431ffe3c632Sopenharmony_ci#include <cpptl/conststring.h> 2432ffe3c632Sopenharmony_ci#endif 2433ffe3c632Sopenharmony_ci#include <cstddef> // size_t 2434ffe3c632Sopenharmony_ci#include <algorithm> // min() 2435ffe3c632Sopenharmony_ci 2436ffe3c632Sopenharmony_ci#define JSON_ASSERT_UNREACHABLE assert(false) 2437ffe3c632Sopenharmony_ci 2438ffe3c632Sopenharmony_cinamespace Json { 2439ffe3c632Sopenharmony_ci 2440ffe3c632Sopenharmony_ci// This is a walkaround to avoid the static initialization of Value::null. 2441ffe3c632Sopenharmony_ci// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of 2442ffe3c632Sopenharmony_ci// 8 (instead of 4) as a bit of future-proofing. 2443ffe3c632Sopenharmony_ci#if defined(__ARMEL__) 2444ffe3c632Sopenharmony_ci#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) 2445ffe3c632Sopenharmony_ci#else 2446ffe3c632Sopenharmony_ci#define ALIGNAS(byte_alignment) 2447ffe3c632Sopenharmony_ci#endif 2448ffe3c632Sopenharmony_cistatic const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; 2449ffe3c632Sopenharmony_ciconst unsigned char& kNullRef = kNull[0]; 2450ffe3c632Sopenharmony_ciconst Value& Value::null = reinterpret_cast<const Value&>(kNullRef); 2451ffe3c632Sopenharmony_ciconst Value& Value::nullRef = null; 2452ffe3c632Sopenharmony_ci 2453ffe3c632Sopenharmony_ciconst Int Value::minInt = Int(~(UInt(-1) / 2)); 2454ffe3c632Sopenharmony_ciconst Int Value::maxInt = Int(UInt(-1) / 2); 2455ffe3c632Sopenharmony_ciconst UInt Value::maxUInt = UInt(-1); 2456ffe3c632Sopenharmony_ci#if defined(JSON_HAS_INT64) 2457ffe3c632Sopenharmony_ciconst Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2)); 2458ffe3c632Sopenharmony_ciconst Int64 Value::maxInt64 = Int64(UInt64(-1) / 2); 2459ffe3c632Sopenharmony_ciconst UInt64 Value::maxUInt64 = UInt64(-1); 2460ffe3c632Sopenharmony_ci// The constant is hard-coded because some compiler have trouble 2461ffe3c632Sopenharmony_ci// converting Value::maxUInt64 to a double correctly (AIX/xlC). 2462ffe3c632Sopenharmony_ci// Assumes that UInt64 is a 64 bits integer. 2463ffe3c632Sopenharmony_cistatic const double maxUInt64AsDouble = 18446744073709551615.0; 2464ffe3c632Sopenharmony_ci#endif // defined(JSON_HAS_INT64) 2465ffe3c632Sopenharmony_ciconst LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2)); 2466ffe3c632Sopenharmony_ciconst LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2); 2467ffe3c632Sopenharmony_ciconst LargestUInt Value::maxLargestUInt = LargestUInt(-1); 2468ffe3c632Sopenharmony_ci 2469ffe3c632Sopenharmony_ci#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 2470ffe3c632Sopenharmony_citemplate <typename T, typename U> 2471ffe3c632Sopenharmony_cistatic inline bool InRange(double d, T min, U max) { 2472ffe3c632Sopenharmony_ci return d >= min && d <= max; 2473ffe3c632Sopenharmony_ci} 2474ffe3c632Sopenharmony_ci#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 2475ffe3c632Sopenharmony_cistatic inline double integerToDouble(Json::UInt64 value) { 2476ffe3c632Sopenharmony_ci return static_cast<double>(Int64(value / 2)) * 2.0 + Int64(value & 1); 2477ffe3c632Sopenharmony_ci} 2478ffe3c632Sopenharmony_ci 2479ffe3c632Sopenharmony_citemplate <typename T> static inline double integerToDouble(T value) { 2480ffe3c632Sopenharmony_ci return static_cast<double>(value); 2481ffe3c632Sopenharmony_ci} 2482ffe3c632Sopenharmony_ci 2483ffe3c632Sopenharmony_citemplate <typename T, typename U> 2484ffe3c632Sopenharmony_cistatic inline bool InRange(double d, T min, U max) { 2485ffe3c632Sopenharmony_ci return d >= integerToDouble(min) && d <= integerToDouble(max); 2486ffe3c632Sopenharmony_ci} 2487ffe3c632Sopenharmony_ci#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 2488ffe3c632Sopenharmony_ci 2489ffe3c632Sopenharmony_ci/** Duplicates the specified string value. 2490ffe3c632Sopenharmony_ci * @param value Pointer to the string to duplicate. Must be zero-terminated if 2491ffe3c632Sopenharmony_ci * length is "unknown". 2492ffe3c632Sopenharmony_ci * @param length Length of the value. if equals to unknown, then it will be 2493ffe3c632Sopenharmony_ci * computed using strlen(value). 2494ffe3c632Sopenharmony_ci * @return Pointer on the duplicate instance of string. 2495ffe3c632Sopenharmony_ci */ 2496ffe3c632Sopenharmony_cistatic inline char* duplicateStringValue(const char* value, 2497ffe3c632Sopenharmony_ci size_t length) { 2498ffe3c632Sopenharmony_ci // Avoid an integer overflow in the call to malloc below by limiting length 2499ffe3c632Sopenharmony_ci // to a sane value. 2500ffe3c632Sopenharmony_ci if (length >= (size_t)Value::maxInt) 2501ffe3c632Sopenharmony_ci length = Value::maxInt - 1; 2502ffe3c632Sopenharmony_ci 2503ffe3c632Sopenharmony_ci char* newString = static_cast<char*>(malloc(length + 1)); 2504ffe3c632Sopenharmony_ci if (newString == NULL) { 2505ffe3c632Sopenharmony_ci throwRuntimeError( 2506ffe3c632Sopenharmony_ci "in Json::Value::duplicateStringValue(): " 2507ffe3c632Sopenharmony_ci "Failed to allocate string value buffer"); 2508ffe3c632Sopenharmony_ci } 2509ffe3c632Sopenharmony_ci memcpy(newString, value, length); 2510ffe3c632Sopenharmony_ci newString[length] = 0; 2511ffe3c632Sopenharmony_ci return newString; 2512ffe3c632Sopenharmony_ci} 2513ffe3c632Sopenharmony_ci 2514ffe3c632Sopenharmony_ci/* Record the length as a prefix. 2515ffe3c632Sopenharmony_ci */ 2516ffe3c632Sopenharmony_cistatic inline char* duplicateAndPrefixStringValue( 2517ffe3c632Sopenharmony_ci const char* value, 2518ffe3c632Sopenharmony_ci unsigned int length) 2519ffe3c632Sopenharmony_ci{ 2520ffe3c632Sopenharmony_ci // Avoid an integer overflow in the call to malloc below by limiting length 2521ffe3c632Sopenharmony_ci // to a sane value. 2522ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE(length <= (unsigned)Value::maxInt - sizeof(unsigned) - 1U, 2523ffe3c632Sopenharmony_ci "in Json::Value::duplicateAndPrefixStringValue(): " 2524ffe3c632Sopenharmony_ci "length too big for prefixing"); 2525ffe3c632Sopenharmony_ci unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U; 2526ffe3c632Sopenharmony_ci char* newString = static_cast<char*>(malloc(actualLength)); 2527ffe3c632Sopenharmony_ci if (newString == 0) { 2528ffe3c632Sopenharmony_ci throwRuntimeError( 2529ffe3c632Sopenharmony_ci "in Json::Value::duplicateAndPrefixStringValue(): " 2530ffe3c632Sopenharmony_ci "Failed to allocate string value buffer"); 2531ffe3c632Sopenharmony_ci } 2532ffe3c632Sopenharmony_ci *reinterpret_cast<unsigned*>(newString) = length; 2533ffe3c632Sopenharmony_ci memcpy(newString + sizeof(unsigned), value, length); 2534ffe3c632Sopenharmony_ci newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later 2535ffe3c632Sopenharmony_ci return newString; 2536ffe3c632Sopenharmony_ci} 2537ffe3c632Sopenharmony_ciinline static void decodePrefixedString( 2538ffe3c632Sopenharmony_ci bool isPrefixed, char const* prefixed, 2539ffe3c632Sopenharmony_ci unsigned* length, char const** value) 2540ffe3c632Sopenharmony_ci{ 2541ffe3c632Sopenharmony_ci if (!isPrefixed) { 2542ffe3c632Sopenharmony_ci *length = static_cast<unsigned>(strlen(prefixed)); 2543ffe3c632Sopenharmony_ci *value = prefixed; 2544ffe3c632Sopenharmony_ci } else { 2545ffe3c632Sopenharmony_ci *length = *reinterpret_cast<unsigned const*>(prefixed); 2546ffe3c632Sopenharmony_ci *value = prefixed + sizeof(unsigned); 2547ffe3c632Sopenharmony_ci } 2548ffe3c632Sopenharmony_ci} 2549ffe3c632Sopenharmony_ci/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue(). 2550ffe3c632Sopenharmony_ci */ 2551ffe3c632Sopenharmony_cistatic inline void releaseStringValue(char* value) { free(value); } 2552ffe3c632Sopenharmony_ci 2553ffe3c632Sopenharmony_ci} // namespace Json 2554ffe3c632Sopenharmony_ci 2555ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2556ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2557ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2558ffe3c632Sopenharmony_ci// ValueInternals... 2559ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2560ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2561ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2562ffe3c632Sopenharmony_ci#if !defined(JSON_IS_AMALGAMATION) 2563ffe3c632Sopenharmony_ci 2564ffe3c632Sopenharmony_ci#include "json_valueiterator.inl" 2565ffe3c632Sopenharmony_ci#endif // if !defined(JSON_IS_AMALGAMATION) 2566ffe3c632Sopenharmony_ci 2567ffe3c632Sopenharmony_cinamespace Json { 2568ffe3c632Sopenharmony_ci 2569ffe3c632Sopenharmony_ciException::Exception(std::string const& msg) 2570ffe3c632Sopenharmony_ci : msg_(msg) 2571ffe3c632Sopenharmony_ci{} 2572ffe3c632Sopenharmony_ciException::~Exception() throw() 2573ffe3c632Sopenharmony_ci{} 2574ffe3c632Sopenharmony_cichar const* Exception::what() const throw() 2575ffe3c632Sopenharmony_ci{ 2576ffe3c632Sopenharmony_ci return msg_.c_str(); 2577ffe3c632Sopenharmony_ci} 2578ffe3c632Sopenharmony_ciRuntimeError::RuntimeError(std::string const& msg) 2579ffe3c632Sopenharmony_ci : Exception(msg) 2580ffe3c632Sopenharmony_ci{} 2581ffe3c632Sopenharmony_ciLogicError::LogicError(std::string const& msg) 2582ffe3c632Sopenharmony_ci : Exception(msg) 2583ffe3c632Sopenharmony_ci{} 2584ffe3c632Sopenharmony_civoid throwRuntimeError(std::string const& msg) 2585ffe3c632Sopenharmony_ci{ 2586ffe3c632Sopenharmony_ci throw RuntimeError(msg); 2587ffe3c632Sopenharmony_ci} 2588ffe3c632Sopenharmony_civoid throwLogicError(std::string const& msg) 2589ffe3c632Sopenharmony_ci{ 2590ffe3c632Sopenharmony_ci throw LogicError(msg); 2591ffe3c632Sopenharmony_ci} 2592ffe3c632Sopenharmony_ci 2593ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2594ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2595ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2596ffe3c632Sopenharmony_ci// class Value::CommentInfo 2597ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2598ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2599ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2600ffe3c632Sopenharmony_ci 2601ffe3c632Sopenharmony_ciValue::CommentInfo::CommentInfo() : comment_(0) {} 2602ffe3c632Sopenharmony_ci 2603ffe3c632Sopenharmony_ciValue::CommentInfo::~CommentInfo() { 2604ffe3c632Sopenharmony_ci if (comment_) 2605ffe3c632Sopenharmony_ci releaseStringValue(comment_); 2606ffe3c632Sopenharmony_ci} 2607ffe3c632Sopenharmony_ci 2608ffe3c632Sopenharmony_civoid Value::CommentInfo::setComment(const char* text, size_t len) { 2609ffe3c632Sopenharmony_ci if (comment_) { 2610ffe3c632Sopenharmony_ci releaseStringValue(comment_); 2611ffe3c632Sopenharmony_ci comment_ = 0; 2612ffe3c632Sopenharmony_ci } 2613ffe3c632Sopenharmony_ci JSON_ASSERT(text != 0); 2614ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE( 2615ffe3c632Sopenharmony_ci text[0] == '\0' || text[0] == '/', 2616ffe3c632Sopenharmony_ci "in Json::Value::setComment(): Comments must start with /"); 2617ffe3c632Sopenharmony_ci // It seems that /**/ style comments are acceptable as well. 2618ffe3c632Sopenharmony_ci comment_ = duplicateStringValue(text, len); 2619ffe3c632Sopenharmony_ci} 2620ffe3c632Sopenharmony_ci 2621ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2622ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2623ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2624ffe3c632Sopenharmony_ci// class Value::CZString 2625ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2626ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2627ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2628ffe3c632Sopenharmony_ci 2629ffe3c632Sopenharmony_ci// Notes: policy_ indicates if the string was allocated when 2630ffe3c632Sopenharmony_ci// a string is stored. 2631ffe3c632Sopenharmony_ci 2632ffe3c632Sopenharmony_ciValue::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {} 2633ffe3c632Sopenharmony_ci 2634ffe3c632Sopenharmony_ciValue::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate) 2635ffe3c632Sopenharmony_ci : cstr_(str) { 2636ffe3c632Sopenharmony_ci // allocate != duplicate 2637ffe3c632Sopenharmony_ci storage_.policy_ = allocate & 0x3; 2638ffe3c632Sopenharmony_ci storage_.length_ = ulength & 0x3FFFFFFF; 2639ffe3c632Sopenharmony_ci} 2640ffe3c632Sopenharmony_ci 2641ffe3c632Sopenharmony_ciValue::CZString::CZString(const CZString& other) 2642ffe3c632Sopenharmony_ci : cstr_(other.storage_.policy_ != noDuplication && other.cstr_ != 0 2643ffe3c632Sopenharmony_ci ? duplicateStringValue(other.cstr_, other.storage_.length_) 2644ffe3c632Sopenharmony_ci : other.cstr_) { 2645ffe3c632Sopenharmony_ci storage_.policy_ = (other.cstr_ 2646ffe3c632Sopenharmony_ci ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication 2647ffe3c632Sopenharmony_ci ? noDuplication : duplicate) 2648ffe3c632Sopenharmony_ci : static_cast<DuplicationPolicy>(other.storage_.policy_)); 2649ffe3c632Sopenharmony_ci storage_.length_ = other.storage_.length_; 2650ffe3c632Sopenharmony_ci} 2651ffe3c632Sopenharmony_ci 2652ffe3c632Sopenharmony_ci#if JSON_HAS_RVALUE_REFERENCES 2653ffe3c632Sopenharmony_ciValue::CZString::CZString(CZString&& other) 2654ffe3c632Sopenharmony_ci : cstr_(other.cstr_), index_(other.index_) { 2655ffe3c632Sopenharmony_ci other.cstr_ = nullptr; 2656ffe3c632Sopenharmony_ci} 2657ffe3c632Sopenharmony_ci#endif 2658ffe3c632Sopenharmony_ci 2659ffe3c632Sopenharmony_ciValue::CZString::~CZString() { 2660ffe3c632Sopenharmony_ci if (cstr_ && storage_.policy_ == duplicate) 2661ffe3c632Sopenharmony_ci releaseStringValue(const_cast<char*>(cstr_)); 2662ffe3c632Sopenharmony_ci} 2663ffe3c632Sopenharmony_ci 2664ffe3c632Sopenharmony_civoid Value::CZString::swap(CZString& other) { 2665ffe3c632Sopenharmony_ci std::swap(cstr_, other.cstr_); 2666ffe3c632Sopenharmony_ci std::swap(index_, other.index_); 2667ffe3c632Sopenharmony_ci} 2668ffe3c632Sopenharmony_ci 2669ffe3c632Sopenharmony_ciValue::CZString& Value::CZString::operator=(CZString other) { 2670ffe3c632Sopenharmony_ci swap(other); 2671ffe3c632Sopenharmony_ci return *this; 2672ffe3c632Sopenharmony_ci} 2673ffe3c632Sopenharmony_ci 2674ffe3c632Sopenharmony_cibool Value::CZString::operator<(const CZString& other) const { 2675ffe3c632Sopenharmony_ci if (!cstr_) return index_ < other.index_; 2676ffe3c632Sopenharmony_ci //return strcmp(cstr_, other.cstr_) < 0; 2677ffe3c632Sopenharmony_ci // Assume both are strings. 2678ffe3c632Sopenharmony_ci unsigned this_len = this->storage_.length_; 2679ffe3c632Sopenharmony_ci unsigned other_len = other.storage_.length_; 2680ffe3c632Sopenharmony_ci unsigned min_len = std::min(this_len, other_len); 2681ffe3c632Sopenharmony_ci int comp = memcmp(this->cstr_, other.cstr_, min_len); 2682ffe3c632Sopenharmony_ci if (comp < 0) return true; 2683ffe3c632Sopenharmony_ci if (comp > 0) return false; 2684ffe3c632Sopenharmony_ci return (this_len < other_len); 2685ffe3c632Sopenharmony_ci} 2686ffe3c632Sopenharmony_ci 2687ffe3c632Sopenharmony_cibool Value::CZString::operator==(const CZString& other) const { 2688ffe3c632Sopenharmony_ci if (!cstr_) return index_ == other.index_; 2689ffe3c632Sopenharmony_ci //return strcmp(cstr_, other.cstr_) == 0; 2690ffe3c632Sopenharmony_ci // Assume both are strings. 2691ffe3c632Sopenharmony_ci unsigned this_len = this->storage_.length_; 2692ffe3c632Sopenharmony_ci unsigned other_len = other.storage_.length_; 2693ffe3c632Sopenharmony_ci if (this_len != other_len) return false; 2694ffe3c632Sopenharmony_ci int comp = memcmp(this->cstr_, other.cstr_, this_len); 2695ffe3c632Sopenharmony_ci return comp == 0; 2696ffe3c632Sopenharmony_ci} 2697ffe3c632Sopenharmony_ci 2698ffe3c632Sopenharmony_ciArrayIndex Value::CZString::index() const { return index_; } 2699ffe3c632Sopenharmony_ci 2700ffe3c632Sopenharmony_ci//const char* Value::CZString::c_str() const { return cstr_; } 2701ffe3c632Sopenharmony_ciconst char* Value::CZString::data() const { return cstr_; } 2702ffe3c632Sopenharmony_ciunsigned Value::CZString::length() const { return storage_.length_; } 2703ffe3c632Sopenharmony_cibool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; } 2704ffe3c632Sopenharmony_ci 2705ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2706ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2707ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2708ffe3c632Sopenharmony_ci// class Value::Value 2709ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2710ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2711ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 2712ffe3c632Sopenharmony_ci 2713ffe3c632Sopenharmony_ci/*! \internal Default constructor initialization must be equivalent to: 2714ffe3c632Sopenharmony_ci * memset( this, 0, sizeof(Value) ) 2715ffe3c632Sopenharmony_ci * This optimization is used in ValueInternalMap fast allocator. 2716ffe3c632Sopenharmony_ci */ 2717ffe3c632Sopenharmony_ciValue::Value(ValueType vtype) { 2718ffe3c632Sopenharmony_ci initBasic(vtype); 2719ffe3c632Sopenharmony_ci switch (vtype) { 2720ffe3c632Sopenharmony_ci case nullValue: 2721ffe3c632Sopenharmony_ci break; 2722ffe3c632Sopenharmony_ci case intValue: 2723ffe3c632Sopenharmony_ci case uintValue: 2724ffe3c632Sopenharmony_ci value_.int_ = 0; 2725ffe3c632Sopenharmony_ci break; 2726ffe3c632Sopenharmony_ci case realValue: 2727ffe3c632Sopenharmony_ci value_.real_ = 0.0; 2728ffe3c632Sopenharmony_ci break; 2729ffe3c632Sopenharmony_ci case stringValue: 2730ffe3c632Sopenharmony_ci value_.string_ = 0; 2731ffe3c632Sopenharmony_ci break; 2732ffe3c632Sopenharmony_ci case arrayValue: 2733ffe3c632Sopenharmony_ci case objectValue: 2734ffe3c632Sopenharmony_ci value_.map_ = new ObjectValues(); 2735ffe3c632Sopenharmony_ci break; 2736ffe3c632Sopenharmony_ci case booleanValue: 2737ffe3c632Sopenharmony_ci value_.bool_ = false; 2738ffe3c632Sopenharmony_ci break; 2739ffe3c632Sopenharmony_ci default: 2740ffe3c632Sopenharmony_ci JSON_ASSERT_UNREACHABLE; 2741ffe3c632Sopenharmony_ci } 2742ffe3c632Sopenharmony_ci} 2743ffe3c632Sopenharmony_ci 2744ffe3c632Sopenharmony_ciValue::Value(Int value) { 2745ffe3c632Sopenharmony_ci initBasic(intValue); 2746ffe3c632Sopenharmony_ci value_.int_ = value; 2747ffe3c632Sopenharmony_ci} 2748ffe3c632Sopenharmony_ci 2749ffe3c632Sopenharmony_ciValue::Value(UInt value) { 2750ffe3c632Sopenharmony_ci initBasic(uintValue); 2751ffe3c632Sopenharmony_ci value_.uint_ = value; 2752ffe3c632Sopenharmony_ci} 2753ffe3c632Sopenharmony_ci#if defined(JSON_HAS_INT64) 2754ffe3c632Sopenharmony_ciValue::Value(Int64 value) { 2755ffe3c632Sopenharmony_ci initBasic(intValue); 2756ffe3c632Sopenharmony_ci value_.int_ = value; 2757ffe3c632Sopenharmony_ci} 2758ffe3c632Sopenharmony_ciValue::Value(UInt64 value) { 2759ffe3c632Sopenharmony_ci initBasic(uintValue); 2760ffe3c632Sopenharmony_ci value_.uint_ = value; 2761ffe3c632Sopenharmony_ci} 2762ffe3c632Sopenharmony_ci#endif // defined(JSON_HAS_INT64) 2763ffe3c632Sopenharmony_ci 2764ffe3c632Sopenharmony_ciValue::Value(double value) { 2765ffe3c632Sopenharmony_ci initBasic(realValue); 2766ffe3c632Sopenharmony_ci value_.real_ = value; 2767ffe3c632Sopenharmony_ci} 2768ffe3c632Sopenharmony_ci 2769ffe3c632Sopenharmony_ciValue::Value(const char* value) { 2770ffe3c632Sopenharmony_ci initBasic(stringValue, true); 2771ffe3c632Sopenharmony_ci value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value))); 2772ffe3c632Sopenharmony_ci} 2773ffe3c632Sopenharmony_ci 2774ffe3c632Sopenharmony_ciValue::Value(const char* beginValue, const char* endValue) { 2775ffe3c632Sopenharmony_ci initBasic(stringValue, true); 2776ffe3c632Sopenharmony_ci value_.string_ = 2777ffe3c632Sopenharmony_ci duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue)); 2778ffe3c632Sopenharmony_ci} 2779ffe3c632Sopenharmony_ci 2780ffe3c632Sopenharmony_ciValue::Value(const std::string& value) { 2781ffe3c632Sopenharmony_ci initBasic(stringValue, true); 2782ffe3c632Sopenharmony_ci value_.string_ = 2783ffe3c632Sopenharmony_ci duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length())); 2784ffe3c632Sopenharmony_ci} 2785ffe3c632Sopenharmony_ci 2786ffe3c632Sopenharmony_ciValue::Value(const StaticString& value) { 2787ffe3c632Sopenharmony_ci initBasic(stringValue); 2788ffe3c632Sopenharmony_ci value_.string_ = const_cast<char*>(value.c_str()); 2789ffe3c632Sopenharmony_ci} 2790ffe3c632Sopenharmony_ci 2791ffe3c632Sopenharmony_ci#ifdef JSON_USE_CPPTL 2792ffe3c632Sopenharmony_ciValue::Value(const CppTL::ConstString& value) { 2793ffe3c632Sopenharmony_ci initBasic(stringValue, true); 2794ffe3c632Sopenharmony_ci value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length())); 2795ffe3c632Sopenharmony_ci} 2796ffe3c632Sopenharmony_ci#endif 2797ffe3c632Sopenharmony_ci 2798ffe3c632Sopenharmony_ciValue::Value(bool value) { 2799ffe3c632Sopenharmony_ci initBasic(booleanValue); 2800ffe3c632Sopenharmony_ci value_.bool_ = value; 2801ffe3c632Sopenharmony_ci} 2802ffe3c632Sopenharmony_ci 2803ffe3c632Sopenharmony_ciValue::Value(Value const& other) 2804ffe3c632Sopenharmony_ci : type_(other.type_), allocated_(false) 2805ffe3c632Sopenharmony_ci , 2806ffe3c632Sopenharmony_ci comments_(0), start_(other.start_), limit_(other.limit_) 2807ffe3c632Sopenharmony_ci{ 2808ffe3c632Sopenharmony_ci switch (type_) { 2809ffe3c632Sopenharmony_ci case nullValue: 2810ffe3c632Sopenharmony_ci case intValue: 2811ffe3c632Sopenharmony_ci case uintValue: 2812ffe3c632Sopenharmony_ci case realValue: 2813ffe3c632Sopenharmony_ci case booleanValue: 2814ffe3c632Sopenharmony_ci value_ = other.value_; 2815ffe3c632Sopenharmony_ci break; 2816ffe3c632Sopenharmony_ci case stringValue: 2817ffe3c632Sopenharmony_ci if (other.value_.string_ && other.allocated_) { 2818ffe3c632Sopenharmony_ci unsigned len; 2819ffe3c632Sopenharmony_ci char const* str; 2820ffe3c632Sopenharmony_ci decodePrefixedString(other.allocated_, other.value_.string_, 2821ffe3c632Sopenharmony_ci &len, &str); 2822ffe3c632Sopenharmony_ci value_.string_ = duplicateAndPrefixStringValue(str, len); 2823ffe3c632Sopenharmony_ci allocated_ = true; 2824ffe3c632Sopenharmony_ci } else { 2825ffe3c632Sopenharmony_ci value_.string_ = other.value_.string_; 2826ffe3c632Sopenharmony_ci allocated_ = false; 2827ffe3c632Sopenharmony_ci } 2828ffe3c632Sopenharmony_ci break; 2829ffe3c632Sopenharmony_ci case arrayValue: 2830ffe3c632Sopenharmony_ci case objectValue: 2831ffe3c632Sopenharmony_ci value_.map_ = new ObjectValues(*other.value_.map_); 2832ffe3c632Sopenharmony_ci break; 2833ffe3c632Sopenharmony_ci default: 2834ffe3c632Sopenharmony_ci JSON_ASSERT_UNREACHABLE; 2835ffe3c632Sopenharmony_ci } 2836ffe3c632Sopenharmony_ci if (other.comments_) { 2837ffe3c632Sopenharmony_ci comments_ = new CommentInfo[numberOfCommentPlacement]; 2838ffe3c632Sopenharmony_ci for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { 2839ffe3c632Sopenharmony_ci const CommentInfo& otherComment = other.comments_[comment]; 2840ffe3c632Sopenharmony_ci if (otherComment.comment_) 2841ffe3c632Sopenharmony_ci comments_[comment].setComment( 2842ffe3c632Sopenharmony_ci otherComment.comment_, strlen(otherComment.comment_)); 2843ffe3c632Sopenharmony_ci } 2844ffe3c632Sopenharmony_ci } 2845ffe3c632Sopenharmony_ci} 2846ffe3c632Sopenharmony_ci 2847ffe3c632Sopenharmony_ci#if JSON_HAS_RVALUE_REFERENCES 2848ffe3c632Sopenharmony_ci// Move constructor 2849ffe3c632Sopenharmony_ciValue::Value(Value&& other) { 2850ffe3c632Sopenharmony_ci initBasic(nullValue); 2851ffe3c632Sopenharmony_ci swap(other); 2852ffe3c632Sopenharmony_ci} 2853ffe3c632Sopenharmony_ci#endif 2854ffe3c632Sopenharmony_ci 2855ffe3c632Sopenharmony_ciValue::~Value() { 2856ffe3c632Sopenharmony_ci switch (type_) { 2857ffe3c632Sopenharmony_ci case nullValue: 2858ffe3c632Sopenharmony_ci case intValue: 2859ffe3c632Sopenharmony_ci case uintValue: 2860ffe3c632Sopenharmony_ci case realValue: 2861ffe3c632Sopenharmony_ci case booleanValue: 2862ffe3c632Sopenharmony_ci break; 2863ffe3c632Sopenharmony_ci case stringValue: 2864ffe3c632Sopenharmony_ci if (allocated_) 2865ffe3c632Sopenharmony_ci releaseStringValue(value_.string_); 2866ffe3c632Sopenharmony_ci break; 2867ffe3c632Sopenharmony_ci case arrayValue: 2868ffe3c632Sopenharmony_ci case objectValue: 2869ffe3c632Sopenharmony_ci delete value_.map_; 2870ffe3c632Sopenharmony_ci break; 2871ffe3c632Sopenharmony_ci default: 2872ffe3c632Sopenharmony_ci JSON_ASSERT_UNREACHABLE; 2873ffe3c632Sopenharmony_ci } 2874ffe3c632Sopenharmony_ci 2875ffe3c632Sopenharmony_ci if (comments_) 2876ffe3c632Sopenharmony_ci delete[] comments_; 2877ffe3c632Sopenharmony_ci} 2878ffe3c632Sopenharmony_ci 2879ffe3c632Sopenharmony_ciValue& Value::operator=(Value other) { 2880ffe3c632Sopenharmony_ci swap(other); 2881ffe3c632Sopenharmony_ci return *this; 2882ffe3c632Sopenharmony_ci} 2883ffe3c632Sopenharmony_ci 2884ffe3c632Sopenharmony_civoid Value::swapPayload(Value& other) { 2885ffe3c632Sopenharmony_ci ValueType temp = type_; 2886ffe3c632Sopenharmony_ci type_ = other.type_; 2887ffe3c632Sopenharmony_ci other.type_ = temp; 2888ffe3c632Sopenharmony_ci std::swap(value_, other.value_); 2889ffe3c632Sopenharmony_ci int temp2 = allocated_; 2890ffe3c632Sopenharmony_ci allocated_ = other.allocated_; 2891ffe3c632Sopenharmony_ci other.allocated_ = temp2 & 0x1; 2892ffe3c632Sopenharmony_ci} 2893ffe3c632Sopenharmony_ci 2894ffe3c632Sopenharmony_civoid Value::swap(Value& other) { 2895ffe3c632Sopenharmony_ci swapPayload(other); 2896ffe3c632Sopenharmony_ci std::swap(comments_, other.comments_); 2897ffe3c632Sopenharmony_ci std::swap(start_, other.start_); 2898ffe3c632Sopenharmony_ci std::swap(limit_, other.limit_); 2899ffe3c632Sopenharmony_ci} 2900ffe3c632Sopenharmony_ci 2901ffe3c632Sopenharmony_ciValueType Value::type() const { return type_; } 2902ffe3c632Sopenharmony_ci 2903ffe3c632Sopenharmony_ciint Value::compare(const Value& other) const { 2904ffe3c632Sopenharmony_ci if (*this < other) 2905ffe3c632Sopenharmony_ci return -1; 2906ffe3c632Sopenharmony_ci if (*this > other) 2907ffe3c632Sopenharmony_ci return 1; 2908ffe3c632Sopenharmony_ci return 0; 2909ffe3c632Sopenharmony_ci} 2910ffe3c632Sopenharmony_ci 2911ffe3c632Sopenharmony_cibool Value::operator<(const Value& other) const { 2912ffe3c632Sopenharmony_ci int typeDelta = type_ - other.type_; 2913ffe3c632Sopenharmony_ci if (typeDelta) 2914ffe3c632Sopenharmony_ci return typeDelta < 0 ? true : false; 2915ffe3c632Sopenharmony_ci switch (type_) { 2916ffe3c632Sopenharmony_ci case nullValue: 2917ffe3c632Sopenharmony_ci return false; 2918ffe3c632Sopenharmony_ci case intValue: 2919ffe3c632Sopenharmony_ci return value_.int_ < other.value_.int_; 2920ffe3c632Sopenharmony_ci case uintValue: 2921ffe3c632Sopenharmony_ci return value_.uint_ < other.value_.uint_; 2922ffe3c632Sopenharmony_ci case realValue: 2923ffe3c632Sopenharmony_ci return value_.real_ < other.value_.real_; 2924ffe3c632Sopenharmony_ci case booleanValue: 2925ffe3c632Sopenharmony_ci return value_.bool_ < other.value_.bool_; 2926ffe3c632Sopenharmony_ci case stringValue: 2927ffe3c632Sopenharmony_ci { 2928ffe3c632Sopenharmony_ci if ((value_.string_ == 0) || (other.value_.string_ == 0)) { 2929ffe3c632Sopenharmony_ci if (other.value_.string_) return true; 2930ffe3c632Sopenharmony_ci else return false; 2931ffe3c632Sopenharmony_ci } 2932ffe3c632Sopenharmony_ci unsigned this_len; 2933ffe3c632Sopenharmony_ci unsigned other_len; 2934ffe3c632Sopenharmony_ci char const* this_str; 2935ffe3c632Sopenharmony_ci char const* other_str; 2936ffe3c632Sopenharmony_ci decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); 2937ffe3c632Sopenharmony_ci decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str); 2938ffe3c632Sopenharmony_ci unsigned min_len = std::min(this_len, other_len); 2939ffe3c632Sopenharmony_ci int comp = memcmp(this_str, other_str, min_len); 2940ffe3c632Sopenharmony_ci if (comp < 0) return true; 2941ffe3c632Sopenharmony_ci if (comp > 0) return false; 2942ffe3c632Sopenharmony_ci return (this_len < other_len); 2943ffe3c632Sopenharmony_ci } 2944ffe3c632Sopenharmony_ci case arrayValue: 2945ffe3c632Sopenharmony_ci case objectValue: { 2946ffe3c632Sopenharmony_ci int delta = int(value_.map_->size() - other.value_.map_->size()); 2947ffe3c632Sopenharmony_ci if (delta) 2948ffe3c632Sopenharmony_ci return delta < 0; 2949ffe3c632Sopenharmony_ci return (*value_.map_) < (*other.value_.map_); 2950ffe3c632Sopenharmony_ci } 2951ffe3c632Sopenharmony_ci default: 2952ffe3c632Sopenharmony_ci JSON_ASSERT_UNREACHABLE; 2953ffe3c632Sopenharmony_ci } 2954ffe3c632Sopenharmony_ci return false; // unreachable 2955ffe3c632Sopenharmony_ci} 2956ffe3c632Sopenharmony_ci 2957ffe3c632Sopenharmony_cibool Value::operator<=(const Value& other) const { return !(other < *this); } 2958ffe3c632Sopenharmony_ci 2959ffe3c632Sopenharmony_cibool Value::operator>=(const Value& other) const { return !(*this < other); } 2960ffe3c632Sopenharmony_ci 2961ffe3c632Sopenharmony_cibool Value::operator>(const Value& other) const { return other < *this; } 2962ffe3c632Sopenharmony_ci 2963ffe3c632Sopenharmony_cibool Value::operator==(const Value& other) const { 2964ffe3c632Sopenharmony_ci // if ( type_ != other.type_ ) 2965ffe3c632Sopenharmony_ci // GCC 2.95.3 says: 2966ffe3c632Sopenharmony_ci // attempt to take address of bit-field structure member `Json::Value::type_' 2967ffe3c632Sopenharmony_ci // Beats me, but a temp solves the problem. 2968ffe3c632Sopenharmony_ci int temp = other.type_; 2969ffe3c632Sopenharmony_ci if (type_ != temp) 2970ffe3c632Sopenharmony_ci return false; 2971ffe3c632Sopenharmony_ci switch (type_) { 2972ffe3c632Sopenharmony_ci case nullValue: 2973ffe3c632Sopenharmony_ci return true; 2974ffe3c632Sopenharmony_ci case intValue: 2975ffe3c632Sopenharmony_ci return value_.int_ == other.value_.int_; 2976ffe3c632Sopenharmony_ci case uintValue: 2977ffe3c632Sopenharmony_ci return value_.uint_ == other.value_.uint_; 2978ffe3c632Sopenharmony_ci case realValue: 2979ffe3c632Sopenharmony_ci return value_.real_ == other.value_.real_; 2980ffe3c632Sopenharmony_ci case booleanValue: 2981ffe3c632Sopenharmony_ci return value_.bool_ == other.value_.bool_; 2982ffe3c632Sopenharmony_ci case stringValue: 2983ffe3c632Sopenharmony_ci { 2984ffe3c632Sopenharmony_ci if ((value_.string_ == 0) || (other.value_.string_ == 0)) { 2985ffe3c632Sopenharmony_ci return (value_.string_ == other.value_.string_); 2986ffe3c632Sopenharmony_ci } 2987ffe3c632Sopenharmony_ci unsigned this_len; 2988ffe3c632Sopenharmony_ci unsigned other_len; 2989ffe3c632Sopenharmony_ci char const* this_str; 2990ffe3c632Sopenharmony_ci char const* other_str; 2991ffe3c632Sopenharmony_ci decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); 2992ffe3c632Sopenharmony_ci decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str); 2993ffe3c632Sopenharmony_ci if (this_len != other_len) return false; 2994ffe3c632Sopenharmony_ci int comp = memcmp(this_str, other_str, this_len); 2995ffe3c632Sopenharmony_ci return comp == 0; 2996ffe3c632Sopenharmony_ci } 2997ffe3c632Sopenharmony_ci case arrayValue: 2998ffe3c632Sopenharmony_ci case objectValue: 2999ffe3c632Sopenharmony_ci return value_.map_->size() == other.value_.map_->size() && 3000ffe3c632Sopenharmony_ci (*value_.map_) == (*other.value_.map_); 3001ffe3c632Sopenharmony_ci default: 3002ffe3c632Sopenharmony_ci JSON_ASSERT_UNREACHABLE; 3003ffe3c632Sopenharmony_ci } 3004ffe3c632Sopenharmony_ci return false; // unreachable 3005ffe3c632Sopenharmony_ci} 3006ffe3c632Sopenharmony_ci 3007ffe3c632Sopenharmony_cibool Value::operator!=(const Value& other) const { return !(*this == other); } 3008ffe3c632Sopenharmony_ci 3009ffe3c632Sopenharmony_ciconst char* Value::asCString() const { 3010ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE(type_ == stringValue, 3011ffe3c632Sopenharmony_ci "in Json::Value::asCString(): requires stringValue"); 3012ffe3c632Sopenharmony_ci if (value_.string_ == 0) return 0; 3013ffe3c632Sopenharmony_ci unsigned this_len; 3014ffe3c632Sopenharmony_ci char const* this_str; 3015ffe3c632Sopenharmony_ci decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); 3016ffe3c632Sopenharmony_ci return this_str; 3017ffe3c632Sopenharmony_ci} 3018ffe3c632Sopenharmony_ci 3019ffe3c632Sopenharmony_cibool Value::getString(char const** str, char const** cend) const { 3020ffe3c632Sopenharmony_ci if (type_ != stringValue) return false; 3021ffe3c632Sopenharmony_ci if (value_.string_ == 0) return false; 3022ffe3c632Sopenharmony_ci unsigned length; 3023ffe3c632Sopenharmony_ci decodePrefixedString(this->allocated_, this->value_.string_, &length, str); 3024ffe3c632Sopenharmony_ci *cend = *str + length; 3025ffe3c632Sopenharmony_ci return true; 3026ffe3c632Sopenharmony_ci} 3027ffe3c632Sopenharmony_ci 3028ffe3c632Sopenharmony_cistd::string Value::asString() const { 3029ffe3c632Sopenharmony_ci switch (type_) { 3030ffe3c632Sopenharmony_ci case nullValue: 3031ffe3c632Sopenharmony_ci return ""; 3032ffe3c632Sopenharmony_ci case stringValue: 3033ffe3c632Sopenharmony_ci { 3034ffe3c632Sopenharmony_ci if (value_.string_ == 0) return ""; 3035ffe3c632Sopenharmony_ci unsigned this_len; 3036ffe3c632Sopenharmony_ci char const* this_str; 3037ffe3c632Sopenharmony_ci decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); 3038ffe3c632Sopenharmony_ci return std::string(this_str, this_len); 3039ffe3c632Sopenharmony_ci } 3040ffe3c632Sopenharmony_ci case booleanValue: 3041ffe3c632Sopenharmony_ci return value_.bool_ ? "true" : "false"; 3042ffe3c632Sopenharmony_ci case intValue: 3043ffe3c632Sopenharmony_ci return valueToString(value_.int_); 3044ffe3c632Sopenharmony_ci case uintValue: 3045ffe3c632Sopenharmony_ci return valueToString(value_.uint_); 3046ffe3c632Sopenharmony_ci case realValue: 3047ffe3c632Sopenharmony_ci return valueToString(value_.real_); 3048ffe3c632Sopenharmony_ci default: 3049ffe3c632Sopenharmony_ci JSON_FAIL_MESSAGE("Type is not convertible to string"); 3050ffe3c632Sopenharmony_ci } 3051ffe3c632Sopenharmony_ci} 3052ffe3c632Sopenharmony_ci 3053ffe3c632Sopenharmony_ci#ifdef JSON_USE_CPPTL 3054ffe3c632Sopenharmony_ciCppTL::ConstString Value::asConstString() const { 3055ffe3c632Sopenharmony_ci unsigned len; 3056ffe3c632Sopenharmony_ci char const* str; 3057ffe3c632Sopenharmony_ci decodePrefixedString(allocated_, value_.string_, 3058ffe3c632Sopenharmony_ci &len, &str); 3059ffe3c632Sopenharmony_ci return CppTL::ConstString(str, len); 3060ffe3c632Sopenharmony_ci} 3061ffe3c632Sopenharmony_ci#endif 3062ffe3c632Sopenharmony_ci 3063ffe3c632Sopenharmony_ciValue::Int Value::asInt() const { 3064ffe3c632Sopenharmony_ci switch (type_) { 3065ffe3c632Sopenharmony_ci case intValue: 3066ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); 3067ffe3c632Sopenharmony_ci return Int(value_.int_); 3068ffe3c632Sopenharmony_ci case uintValue: 3069ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); 3070ffe3c632Sopenharmony_ci return Int(value_.uint_); 3071ffe3c632Sopenharmony_ci case realValue: 3072ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), 3073ffe3c632Sopenharmony_ci "double out of Int range"); 3074ffe3c632Sopenharmony_ci return Int(value_.real_); 3075ffe3c632Sopenharmony_ci case nullValue: 3076ffe3c632Sopenharmony_ci return 0; 3077ffe3c632Sopenharmony_ci case booleanValue: 3078ffe3c632Sopenharmony_ci return value_.bool_ ? 1 : 0; 3079ffe3c632Sopenharmony_ci default: 3080ffe3c632Sopenharmony_ci break; 3081ffe3c632Sopenharmony_ci } 3082ffe3c632Sopenharmony_ci JSON_FAIL_MESSAGE("Value is not convertible to Int."); 3083ffe3c632Sopenharmony_ci} 3084ffe3c632Sopenharmony_ci 3085ffe3c632Sopenharmony_ciValue::UInt Value::asUInt() const { 3086ffe3c632Sopenharmony_ci switch (type_) { 3087ffe3c632Sopenharmony_ci case intValue: 3088ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); 3089ffe3c632Sopenharmony_ci return UInt(value_.int_); 3090ffe3c632Sopenharmony_ci case uintValue: 3091ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); 3092ffe3c632Sopenharmony_ci return UInt(value_.uint_); 3093ffe3c632Sopenharmony_ci case realValue: 3094ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), 3095ffe3c632Sopenharmony_ci "double out of UInt range"); 3096ffe3c632Sopenharmony_ci return UInt(value_.real_); 3097ffe3c632Sopenharmony_ci case nullValue: 3098ffe3c632Sopenharmony_ci return 0; 3099ffe3c632Sopenharmony_ci case booleanValue: 3100ffe3c632Sopenharmony_ci return value_.bool_ ? 1 : 0; 3101ffe3c632Sopenharmony_ci default: 3102ffe3c632Sopenharmony_ci break; 3103ffe3c632Sopenharmony_ci } 3104ffe3c632Sopenharmony_ci JSON_FAIL_MESSAGE("Value is not convertible to UInt."); 3105ffe3c632Sopenharmony_ci} 3106ffe3c632Sopenharmony_ci 3107ffe3c632Sopenharmony_ci#if defined(JSON_HAS_INT64) 3108ffe3c632Sopenharmony_ci 3109ffe3c632Sopenharmony_ciValue::Int64 Value::asInt64() const { 3110ffe3c632Sopenharmony_ci switch (type_) { 3111ffe3c632Sopenharmony_ci case intValue: 3112ffe3c632Sopenharmony_ci return Int64(value_.int_); 3113ffe3c632Sopenharmony_ci case uintValue: 3114ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); 3115ffe3c632Sopenharmony_ci return Int64(value_.uint_); 3116ffe3c632Sopenharmony_ci case realValue: 3117ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), 3118ffe3c632Sopenharmony_ci "double out of Int64 range"); 3119ffe3c632Sopenharmony_ci return Int64(value_.real_); 3120ffe3c632Sopenharmony_ci case nullValue: 3121ffe3c632Sopenharmony_ci return 0; 3122ffe3c632Sopenharmony_ci case booleanValue: 3123ffe3c632Sopenharmony_ci return value_.bool_ ? 1 : 0; 3124ffe3c632Sopenharmony_ci default: 3125ffe3c632Sopenharmony_ci break; 3126ffe3c632Sopenharmony_ci } 3127ffe3c632Sopenharmony_ci JSON_FAIL_MESSAGE("Value is not convertible to Int64."); 3128ffe3c632Sopenharmony_ci} 3129ffe3c632Sopenharmony_ci 3130ffe3c632Sopenharmony_ciValue::UInt64 Value::asUInt64() const { 3131ffe3c632Sopenharmony_ci switch (type_) { 3132ffe3c632Sopenharmony_ci case intValue: 3133ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); 3134ffe3c632Sopenharmony_ci return UInt64(value_.int_); 3135ffe3c632Sopenharmony_ci case uintValue: 3136ffe3c632Sopenharmony_ci return UInt64(value_.uint_); 3137ffe3c632Sopenharmony_ci case realValue: 3138ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), 3139ffe3c632Sopenharmony_ci "double out of UInt64 range"); 3140ffe3c632Sopenharmony_ci return UInt64(value_.real_); 3141ffe3c632Sopenharmony_ci case nullValue: 3142ffe3c632Sopenharmony_ci return 0; 3143ffe3c632Sopenharmony_ci case booleanValue: 3144ffe3c632Sopenharmony_ci return value_.bool_ ? 1 : 0; 3145ffe3c632Sopenharmony_ci default: 3146ffe3c632Sopenharmony_ci break; 3147ffe3c632Sopenharmony_ci } 3148ffe3c632Sopenharmony_ci JSON_FAIL_MESSAGE("Value is not convertible to UInt64."); 3149ffe3c632Sopenharmony_ci} 3150ffe3c632Sopenharmony_ci#endif // if defined(JSON_HAS_INT64) 3151ffe3c632Sopenharmony_ci 3152ffe3c632Sopenharmony_ciLargestInt Value::asLargestInt() const { 3153ffe3c632Sopenharmony_ci#if defined(JSON_NO_INT64) 3154ffe3c632Sopenharmony_ci return asInt(); 3155ffe3c632Sopenharmony_ci#else 3156ffe3c632Sopenharmony_ci return asInt64(); 3157ffe3c632Sopenharmony_ci#endif 3158ffe3c632Sopenharmony_ci} 3159ffe3c632Sopenharmony_ci 3160ffe3c632Sopenharmony_ciLargestUInt Value::asLargestUInt() const { 3161ffe3c632Sopenharmony_ci#if defined(JSON_NO_INT64) 3162ffe3c632Sopenharmony_ci return asUInt(); 3163ffe3c632Sopenharmony_ci#else 3164ffe3c632Sopenharmony_ci return asUInt64(); 3165ffe3c632Sopenharmony_ci#endif 3166ffe3c632Sopenharmony_ci} 3167ffe3c632Sopenharmony_ci 3168ffe3c632Sopenharmony_cidouble Value::asDouble() const { 3169ffe3c632Sopenharmony_ci switch (type_) { 3170ffe3c632Sopenharmony_ci case intValue: 3171ffe3c632Sopenharmony_ci return static_cast<double>(value_.int_); 3172ffe3c632Sopenharmony_ci case uintValue: 3173ffe3c632Sopenharmony_ci#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 3174ffe3c632Sopenharmony_ci return static_cast<double>(value_.uint_); 3175ffe3c632Sopenharmony_ci#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 3176ffe3c632Sopenharmony_ci return integerToDouble(value_.uint_); 3177ffe3c632Sopenharmony_ci#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 3178ffe3c632Sopenharmony_ci case realValue: 3179ffe3c632Sopenharmony_ci return value_.real_; 3180ffe3c632Sopenharmony_ci case nullValue: 3181ffe3c632Sopenharmony_ci return 0.0; 3182ffe3c632Sopenharmony_ci case booleanValue: 3183ffe3c632Sopenharmony_ci return value_.bool_ ? 1.0 : 0.0; 3184ffe3c632Sopenharmony_ci default: 3185ffe3c632Sopenharmony_ci break; 3186ffe3c632Sopenharmony_ci } 3187ffe3c632Sopenharmony_ci JSON_FAIL_MESSAGE("Value is not convertible to double."); 3188ffe3c632Sopenharmony_ci} 3189ffe3c632Sopenharmony_ci 3190ffe3c632Sopenharmony_cifloat Value::asFloat() const { 3191ffe3c632Sopenharmony_ci switch (type_) { 3192ffe3c632Sopenharmony_ci case intValue: 3193ffe3c632Sopenharmony_ci return static_cast<float>(value_.int_); 3194ffe3c632Sopenharmony_ci case uintValue: 3195ffe3c632Sopenharmony_ci#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 3196ffe3c632Sopenharmony_ci return static_cast<float>(value_.uint_); 3197ffe3c632Sopenharmony_ci#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 3198ffe3c632Sopenharmony_ci return integerToDouble(value_.uint_); 3199ffe3c632Sopenharmony_ci#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 3200ffe3c632Sopenharmony_ci case realValue: 3201ffe3c632Sopenharmony_ci return static_cast<float>(value_.real_); 3202ffe3c632Sopenharmony_ci case nullValue: 3203ffe3c632Sopenharmony_ci return 0.0; 3204ffe3c632Sopenharmony_ci case booleanValue: 3205ffe3c632Sopenharmony_ci return value_.bool_ ? 1.0f : 0.0f; 3206ffe3c632Sopenharmony_ci default: 3207ffe3c632Sopenharmony_ci break; 3208ffe3c632Sopenharmony_ci } 3209ffe3c632Sopenharmony_ci JSON_FAIL_MESSAGE("Value is not convertible to float."); 3210ffe3c632Sopenharmony_ci} 3211ffe3c632Sopenharmony_ci 3212ffe3c632Sopenharmony_cibool Value::asBool() const { 3213ffe3c632Sopenharmony_ci switch (type_) { 3214ffe3c632Sopenharmony_ci case booleanValue: 3215ffe3c632Sopenharmony_ci return value_.bool_; 3216ffe3c632Sopenharmony_ci case nullValue: 3217ffe3c632Sopenharmony_ci return false; 3218ffe3c632Sopenharmony_ci case intValue: 3219ffe3c632Sopenharmony_ci return value_.int_ ? true : false; 3220ffe3c632Sopenharmony_ci case uintValue: 3221ffe3c632Sopenharmony_ci return value_.uint_ ? true : false; 3222ffe3c632Sopenharmony_ci case realValue: 3223ffe3c632Sopenharmony_ci // This is kind of strange. Not recommended. 3224ffe3c632Sopenharmony_ci return (value_.real_ != 0.0) ? true : false; 3225ffe3c632Sopenharmony_ci default: 3226ffe3c632Sopenharmony_ci break; 3227ffe3c632Sopenharmony_ci } 3228ffe3c632Sopenharmony_ci JSON_FAIL_MESSAGE("Value is not convertible to bool."); 3229ffe3c632Sopenharmony_ci} 3230ffe3c632Sopenharmony_ci 3231ffe3c632Sopenharmony_cibool Value::isConvertibleTo(ValueType other) const { 3232ffe3c632Sopenharmony_ci switch (other) { 3233ffe3c632Sopenharmony_ci case nullValue: 3234ffe3c632Sopenharmony_ci return (isNumeric() && asDouble() == 0.0) || 3235ffe3c632Sopenharmony_ci (type_ == booleanValue && value_.bool_ == false) || 3236ffe3c632Sopenharmony_ci (type_ == stringValue && asString() == "") || 3237ffe3c632Sopenharmony_ci (type_ == arrayValue && value_.map_->size() == 0) || 3238ffe3c632Sopenharmony_ci (type_ == objectValue && value_.map_->size() == 0) || 3239ffe3c632Sopenharmony_ci type_ == nullValue; 3240ffe3c632Sopenharmony_ci case intValue: 3241ffe3c632Sopenharmony_ci return isInt() || 3242ffe3c632Sopenharmony_ci (type_ == realValue && InRange(value_.real_, minInt, maxInt)) || 3243ffe3c632Sopenharmony_ci type_ == booleanValue || type_ == nullValue; 3244ffe3c632Sopenharmony_ci case uintValue: 3245ffe3c632Sopenharmony_ci return isUInt() || 3246ffe3c632Sopenharmony_ci (type_ == realValue && InRange(value_.real_, 0, maxUInt)) || 3247ffe3c632Sopenharmony_ci type_ == booleanValue || type_ == nullValue; 3248ffe3c632Sopenharmony_ci case realValue: 3249ffe3c632Sopenharmony_ci return isNumeric() || type_ == booleanValue || type_ == nullValue; 3250ffe3c632Sopenharmony_ci case booleanValue: 3251ffe3c632Sopenharmony_ci return isNumeric() || type_ == booleanValue || type_ == nullValue; 3252ffe3c632Sopenharmony_ci case stringValue: 3253ffe3c632Sopenharmony_ci return isNumeric() || type_ == booleanValue || type_ == stringValue || 3254ffe3c632Sopenharmony_ci type_ == nullValue; 3255ffe3c632Sopenharmony_ci case arrayValue: 3256ffe3c632Sopenharmony_ci return type_ == arrayValue || type_ == nullValue; 3257ffe3c632Sopenharmony_ci case objectValue: 3258ffe3c632Sopenharmony_ci return type_ == objectValue || type_ == nullValue; 3259ffe3c632Sopenharmony_ci } 3260ffe3c632Sopenharmony_ci JSON_ASSERT_UNREACHABLE; 3261ffe3c632Sopenharmony_ci return false; 3262ffe3c632Sopenharmony_ci} 3263ffe3c632Sopenharmony_ci 3264ffe3c632Sopenharmony_ci/// Number of values in array or object 3265ffe3c632Sopenharmony_ciArrayIndex Value::size() const { 3266ffe3c632Sopenharmony_ci switch (type_) { 3267ffe3c632Sopenharmony_ci case nullValue: 3268ffe3c632Sopenharmony_ci case intValue: 3269ffe3c632Sopenharmony_ci case uintValue: 3270ffe3c632Sopenharmony_ci case realValue: 3271ffe3c632Sopenharmony_ci case booleanValue: 3272ffe3c632Sopenharmony_ci case stringValue: 3273ffe3c632Sopenharmony_ci return 0; 3274ffe3c632Sopenharmony_ci case arrayValue: // size of the array is highest index + 1 3275ffe3c632Sopenharmony_ci if (!value_.map_->empty()) { 3276ffe3c632Sopenharmony_ci ObjectValues::const_iterator itLast = value_.map_->end(); 3277ffe3c632Sopenharmony_ci --itLast; 3278ffe3c632Sopenharmony_ci return (*itLast).first.index() + 1; 3279ffe3c632Sopenharmony_ci } 3280ffe3c632Sopenharmony_ci return 0; 3281ffe3c632Sopenharmony_ci case objectValue: 3282ffe3c632Sopenharmony_ci return ArrayIndex(value_.map_->size()); 3283ffe3c632Sopenharmony_ci } 3284ffe3c632Sopenharmony_ci JSON_ASSERT_UNREACHABLE; 3285ffe3c632Sopenharmony_ci return 0; // unreachable; 3286ffe3c632Sopenharmony_ci} 3287ffe3c632Sopenharmony_ci 3288ffe3c632Sopenharmony_cibool Value::empty() const { 3289ffe3c632Sopenharmony_ci if (isNull() || isArray() || isObject()) 3290ffe3c632Sopenharmony_ci return size() == 0u; 3291ffe3c632Sopenharmony_ci else 3292ffe3c632Sopenharmony_ci return false; 3293ffe3c632Sopenharmony_ci} 3294ffe3c632Sopenharmony_ci 3295ffe3c632Sopenharmony_cibool Value::operator!() const { return isNull(); } 3296ffe3c632Sopenharmony_ci 3297ffe3c632Sopenharmony_civoid Value::clear() { 3298ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || 3299ffe3c632Sopenharmony_ci type_ == objectValue, 3300ffe3c632Sopenharmony_ci "in Json::Value::clear(): requires complex value"); 3301ffe3c632Sopenharmony_ci start_ = 0; 3302ffe3c632Sopenharmony_ci limit_ = 0; 3303ffe3c632Sopenharmony_ci switch (type_) { 3304ffe3c632Sopenharmony_ci case arrayValue: 3305ffe3c632Sopenharmony_ci case objectValue: 3306ffe3c632Sopenharmony_ci value_.map_->clear(); 3307ffe3c632Sopenharmony_ci break; 3308ffe3c632Sopenharmony_ci default: 3309ffe3c632Sopenharmony_ci break; 3310ffe3c632Sopenharmony_ci } 3311ffe3c632Sopenharmony_ci} 3312ffe3c632Sopenharmony_ci 3313ffe3c632Sopenharmony_civoid Value::resize(ArrayIndex newSize) { 3314ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue, 3315ffe3c632Sopenharmony_ci "in Json::Value::resize(): requires arrayValue"); 3316ffe3c632Sopenharmony_ci if (type_ == nullValue) 3317ffe3c632Sopenharmony_ci *this = Value(arrayValue); 3318ffe3c632Sopenharmony_ci ArrayIndex oldSize = size(); 3319ffe3c632Sopenharmony_ci if (newSize == 0) 3320ffe3c632Sopenharmony_ci clear(); 3321ffe3c632Sopenharmony_ci else if (newSize > oldSize) 3322ffe3c632Sopenharmony_ci (*this)[newSize - 1]; 3323ffe3c632Sopenharmony_ci else { 3324ffe3c632Sopenharmony_ci for (ArrayIndex index = newSize; index < oldSize; ++index) { 3325ffe3c632Sopenharmony_ci value_.map_->erase(index); 3326ffe3c632Sopenharmony_ci } 3327ffe3c632Sopenharmony_ci assert(size() == newSize); 3328ffe3c632Sopenharmony_ci } 3329ffe3c632Sopenharmony_ci} 3330ffe3c632Sopenharmony_ci 3331ffe3c632Sopenharmony_ciValue& Value::operator[](ArrayIndex index) { 3332ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE( 3333ffe3c632Sopenharmony_ci type_ == nullValue || type_ == arrayValue, 3334ffe3c632Sopenharmony_ci "in Json::Value::operator[](ArrayIndex): requires arrayValue"); 3335ffe3c632Sopenharmony_ci if (type_ == nullValue) 3336ffe3c632Sopenharmony_ci *this = Value(arrayValue); 3337ffe3c632Sopenharmony_ci CZString key(index); 3338ffe3c632Sopenharmony_ci ObjectValues::iterator it = value_.map_->lower_bound(key); 3339ffe3c632Sopenharmony_ci if (it != value_.map_->end() && (*it).first == key) 3340ffe3c632Sopenharmony_ci return (*it).second; 3341ffe3c632Sopenharmony_ci 3342ffe3c632Sopenharmony_ci ObjectValues::value_type defaultValue(key, nullRef); 3343ffe3c632Sopenharmony_ci it = value_.map_->insert(it, defaultValue); 3344ffe3c632Sopenharmony_ci return (*it).second; 3345ffe3c632Sopenharmony_ci} 3346ffe3c632Sopenharmony_ci 3347ffe3c632Sopenharmony_ciValue& Value::operator[](int index) { 3348ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE( 3349ffe3c632Sopenharmony_ci index >= 0, 3350ffe3c632Sopenharmony_ci "in Json::Value::operator[](int index): index cannot be negative"); 3351ffe3c632Sopenharmony_ci return (*this)[ArrayIndex(index)]; 3352ffe3c632Sopenharmony_ci} 3353ffe3c632Sopenharmony_ci 3354ffe3c632Sopenharmony_ciconst Value& Value::operator[](ArrayIndex index) const { 3355ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE( 3356ffe3c632Sopenharmony_ci type_ == nullValue || type_ == arrayValue, 3357ffe3c632Sopenharmony_ci "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); 3358ffe3c632Sopenharmony_ci if (type_ == nullValue) 3359ffe3c632Sopenharmony_ci return nullRef; 3360ffe3c632Sopenharmony_ci CZString key(index); 3361ffe3c632Sopenharmony_ci ObjectValues::const_iterator it = value_.map_->find(key); 3362ffe3c632Sopenharmony_ci if (it == value_.map_->end()) 3363ffe3c632Sopenharmony_ci return nullRef; 3364ffe3c632Sopenharmony_ci return (*it).second; 3365ffe3c632Sopenharmony_ci} 3366ffe3c632Sopenharmony_ci 3367ffe3c632Sopenharmony_ciconst Value& Value::operator[](int index) const { 3368ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE( 3369ffe3c632Sopenharmony_ci index >= 0, 3370ffe3c632Sopenharmony_ci "in Json::Value::operator[](int index) const: index cannot be negative"); 3371ffe3c632Sopenharmony_ci return (*this)[ArrayIndex(index)]; 3372ffe3c632Sopenharmony_ci} 3373ffe3c632Sopenharmony_ci 3374ffe3c632Sopenharmony_civoid Value::initBasic(ValueType vtype, bool allocated) { 3375ffe3c632Sopenharmony_ci type_ = vtype; 3376ffe3c632Sopenharmony_ci allocated_ = allocated; 3377ffe3c632Sopenharmony_ci comments_ = 0; 3378ffe3c632Sopenharmony_ci start_ = 0; 3379ffe3c632Sopenharmony_ci limit_ = 0; 3380ffe3c632Sopenharmony_ci} 3381ffe3c632Sopenharmony_ci 3382ffe3c632Sopenharmony_ci// Access an object value by name, create a null member if it does not exist. 3383ffe3c632Sopenharmony_ci// @pre Type of '*this' is object or null. 3384ffe3c632Sopenharmony_ci// @param key is null-terminated. 3385ffe3c632Sopenharmony_ciValue& Value::resolveReference(const char* key) { 3386ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE( 3387ffe3c632Sopenharmony_ci type_ == nullValue || type_ == objectValue, 3388ffe3c632Sopenharmony_ci "in Json::Value::resolveReference(): requires objectValue"); 3389ffe3c632Sopenharmony_ci if (type_ == nullValue) 3390ffe3c632Sopenharmony_ci *this = Value(objectValue); 3391ffe3c632Sopenharmony_ci CZString actualKey( 3392ffe3c632Sopenharmony_ci key, static_cast<unsigned>(strlen(key)), CZString::noDuplication); // NOTE! 3393ffe3c632Sopenharmony_ci ObjectValues::iterator it = value_.map_->lower_bound(actualKey); 3394ffe3c632Sopenharmony_ci if (it != value_.map_->end() && (*it).first == actualKey) 3395ffe3c632Sopenharmony_ci return (*it).second; 3396ffe3c632Sopenharmony_ci 3397ffe3c632Sopenharmony_ci ObjectValues::value_type defaultValue(actualKey, nullRef); 3398ffe3c632Sopenharmony_ci it = value_.map_->insert(it, defaultValue); 3399ffe3c632Sopenharmony_ci Value& value = (*it).second; 3400ffe3c632Sopenharmony_ci return value; 3401ffe3c632Sopenharmony_ci} 3402ffe3c632Sopenharmony_ci 3403ffe3c632Sopenharmony_ci// @param key is not null-terminated. 3404ffe3c632Sopenharmony_ciValue& Value::resolveReference(char const* key, char const* cend) 3405ffe3c632Sopenharmony_ci{ 3406ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE( 3407ffe3c632Sopenharmony_ci type_ == nullValue || type_ == objectValue, 3408ffe3c632Sopenharmony_ci "in Json::Value::resolveReference(key, end): requires objectValue"); 3409ffe3c632Sopenharmony_ci if (type_ == nullValue) 3410ffe3c632Sopenharmony_ci *this = Value(objectValue); 3411ffe3c632Sopenharmony_ci CZString actualKey( 3412ffe3c632Sopenharmony_ci key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy); 3413ffe3c632Sopenharmony_ci ObjectValues::iterator it = value_.map_->lower_bound(actualKey); 3414ffe3c632Sopenharmony_ci if (it != value_.map_->end() && (*it).first == actualKey) 3415ffe3c632Sopenharmony_ci return (*it).second; 3416ffe3c632Sopenharmony_ci 3417ffe3c632Sopenharmony_ci ObjectValues::value_type defaultValue(actualKey, nullRef); 3418ffe3c632Sopenharmony_ci it = value_.map_->insert(it, defaultValue); 3419ffe3c632Sopenharmony_ci Value& value = (*it).second; 3420ffe3c632Sopenharmony_ci return value; 3421ffe3c632Sopenharmony_ci} 3422ffe3c632Sopenharmony_ci 3423ffe3c632Sopenharmony_ciValue Value::get(ArrayIndex index, const Value& defaultValue) const { 3424ffe3c632Sopenharmony_ci const Value* value = &((*this)[index]); 3425ffe3c632Sopenharmony_ci return value == &nullRef ? defaultValue : *value; 3426ffe3c632Sopenharmony_ci} 3427ffe3c632Sopenharmony_ci 3428ffe3c632Sopenharmony_cibool Value::isValidIndex(ArrayIndex index) const { return index < size(); } 3429ffe3c632Sopenharmony_ci 3430ffe3c632Sopenharmony_ciValue const* Value::find(char const* key, char const* cend) const 3431ffe3c632Sopenharmony_ci{ 3432ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE( 3433ffe3c632Sopenharmony_ci type_ == nullValue || type_ == objectValue, 3434ffe3c632Sopenharmony_ci "in Json::Value::find(key, end, found): requires objectValue or nullValue"); 3435ffe3c632Sopenharmony_ci if (type_ == nullValue) return NULL; 3436ffe3c632Sopenharmony_ci CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication); 3437ffe3c632Sopenharmony_ci ObjectValues::const_iterator it = value_.map_->find(actualKey); 3438ffe3c632Sopenharmony_ci if (it == value_.map_->end()) return NULL; 3439ffe3c632Sopenharmony_ci return &(*it).second; 3440ffe3c632Sopenharmony_ci} 3441ffe3c632Sopenharmony_ciconst Value& Value::operator[](const char* key) const 3442ffe3c632Sopenharmony_ci{ 3443ffe3c632Sopenharmony_ci Value const* found = find(key, key + strlen(key)); 3444ffe3c632Sopenharmony_ci if (!found) return nullRef; 3445ffe3c632Sopenharmony_ci return *found; 3446ffe3c632Sopenharmony_ci} 3447ffe3c632Sopenharmony_ciValue const& Value::operator[](std::string const& key) const 3448ffe3c632Sopenharmony_ci{ 3449ffe3c632Sopenharmony_ci Value const* found = find(key.data(), key.data() + key.length()); 3450ffe3c632Sopenharmony_ci if (!found) return nullRef; 3451ffe3c632Sopenharmony_ci return *found; 3452ffe3c632Sopenharmony_ci} 3453ffe3c632Sopenharmony_ci 3454ffe3c632Sopenharmony_ciValue& Value::operator[](const char* key) { 3455ffe3c632Sopenharmony_ci return resolveReference(key, key + strlen(key)); 3456ffe3c632Sopenharmony_ci} 3457ffe3c632Sopenharmony_ci 3458ffe3c632Sopenharmony_ciValue& Value::operator[](const std::string& key) { 3459ffe3c632Sopenharmony_ci return resolveReference(key.data(), key.data() + key.length()); 3460ffe3c632Sopenharmony_ci} 3461ffe3c632Sopenharmony_ci 3462ffe3c632Sopenharmony_ciValue& Value::operator[](const StaticString& key) { 3463ffe3c632Sopenharmony_ci return resolveReference(key.c_str()); 3464ffe3c632Sopenharmony_ci} 3465ffe3c632Sopenharmony_ci 3466ffe3c632Sopenharmony_ci#ifdef JSON_USE_CPPTL 3467ffe3c632Sopenharmony_ciValue& Value::operator[](const CppTL::ConstString& key) { 3468ffe3c632Sopenharmony_ci return resolveReference(key.c_str(), key.end_c_str()); 3469ffe3c632Sopenharmony_ci} 3470ffe3c632Sopenharmony_ciValue const& Value::operator[](CppTL::ConstString const& key) const 3471ffe3c632Sopenharmony_ci{ 3472ffe3c632Sopenharmony_ci Value const* found = find(key.c_str(), key.end_c_str()); 3473ffe3c632Sopenharmony_ci if (!found) return nullRef; 3474ffe3c632Sopenharmony_ci return *found; 3475ffe3c632Sopenharmony_ci} 3476ffe3c632Sopenharmony_ci#endif 3477ffe3c632Sopenharmony_ci 3478ffe3c632Sopenharmony_ciValue& Value::append(const Value& value) { return (*this)[size()] = value; } 3479ffe3c632Sopenharmony_ci 3480ffe3c632Sopenharmony_ciValue Value::get(char const* key, char const* cend, Value const& defaultValue) const 3481ffe3c632Sopenharmony_ci{ 3482ffe3c632Sopenharmony_ci Value const* found = find(key, cend); 3483ffe3c632Sopenharmony_ci return !found ? defaultValue : *found; 3484ffe3c632Sopenharmony_ci} 3485ffe3c632Sopenharmony_ciValue Value::get(char const* key, Value const& defaultValue) const 3486ffe3c632Sopenharmony_ci{ 3487ffe3c632Sopenharmony_ci return get(key, key + strlen(key), defaultValue); 3488ffe3c632Sopenharmony_ci} 3489ffe3c632Sopenharmony_ciValue Value::get(std::string const& key, Value const& defaultValue) const 3490ffe3c632Sopenharmony_ci{ 3491ffe3c632Sopenharmony_ci return get(key.data(), key.data() + key.length(), defaultValue); 3492ffe3c632Sopenharmony_ci} 3493ffe3c632Sopenharmony_ci 3494ffe3c632Sopenharmony_ci 3495ffe3c632Sopenharmony_cibool Value::removeMember(const char* key, const char* cend, Value* removed) 3496ffe3c632Sopenharmony_ci{ 3497ffe3c632Sopenharmony_ci if (type_ != objectValue) { 3498ffe3c632Sopenharmony_ci return false; 3499ffe3c632Sopenharmony_ci } 3500ffe3c632Sopenharmony_ci CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication); 3501ffe3c632Sopenharmony_ci ObjectValues::iterator it = value_.map_->find(actualKey); 3502ffe3c632Sopenharmony_ci if (it == value_.map_->end()) 3503ffe3c632Sopenharmony_ci return false; 3504ffe3c632Sopenharmony_ci *removed = it->second; 3505ffe3c632Sopenharmony_ci value_.map_->erase(it); 3506ffe3c632Sopenharmony_ci return true; 3507ffe3c632Sopenharmony_ci} 3508ffe3c632Sopenharmony_cibool Value::removeMember(const char* key, Value* removed) 3509ffe3c632Sopenharmony_ci{ 3510ffe3c632Sopenharmony_ci return removeMember(key, key + strlen(key), removed); 3511ffe3c632Sopenharmony_ci} 3512ffe3c632Sopenharmony_cibool Value::removeMember(std::string const& key, Value* removed) 3513ffe3c632Sopenharmony_ci{ 3514ffe3c632Sopenharmony_ci return removeMember(key.data(), key.data() + key.length(), removed); 3515ffe3c632Sopenharmony_ci} 3516ffe3c632Sopenharmony_ciValue Value::removeMember(const char* key) 3517ffe3c632Sopenharmony_ci{ 3518ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, 3519ffe3c632Sopenharmony_ci "in Json::Value::removeMember(): requires objectValue"); 3520ffe3c632Sopenharmony_ci if (type_ == nullValue) 3521ffe3c632Sopenharmony_ci return nullRef; 3522ffe3c632Sopenharmony_ci 3523ffe3c632Sopenharmony_ci Value removed; // null 3524ffe3c632Sopenharmony_ci removeMember(key, key + strlen(key), &removed); 3525ffe3c632Sopenharmony_ci return removed; // still null if removeMember() did nothing 3526ffe3c632Sopenharmony_ci} 3527ffe3c632Sopenharmony_ciValue Value::removeMember(const std::string& key) 3528ffe3c632Sopenharmony_ci{ 3529ffe3c632Sopenharmony_ci return removeMember(key.c_str()); 3530ffe3c632Sopenharmony_ci} 3531ffe3c632Sopenharmony_ci 3532ffe3c632Sopenharmony_cibool Value::removeIndex(ArrayIndex index, Value* removed) { 3533ffe3c632Sopenharmony_ci if (type_ != arrayValue) { 3534ffe3c632Sopenharmony_ci return false; 3535ffe3c632Sopenharmony_ci } 3536ffe3c632Sopenharmony_ci CZString key(index); 3537ffe3c632Sopenharmony_ci ObjectValues::iterator it = value_.map_->find(key); 3538ffe3c632Sopenharmony_ci if (it == value_.map_->end()) { 3539ffe3c632Sopenharmony_ci return false; 3540ffe3c632Sopenharmony_ci } 3541ffe3c632Sopenharmony_ci *removed = it->second; 3542ffe3c632Sopenharmony_ci ArrayIndex oldSize = size(); 3543ffe3c632Sopenharmony_ci // shift left all items left, into the place of the "removed" 3544ffe3c632Sopenharmony_ci for (ArrayIndex i = index; i < (oldSize - 1); ++i){ 3545ffe3c632Sopenharmony_ci CZString keey(i); 3546ffe3c632Sopenharmony_ci (*value_.map_)[keey] = (*this)[i + 1]; 3547ffe3c632Sopenharmony_ci } 3548ffe3c632Sopenharmony_ci // erase the last one ("leftover") 3549ffe3c632Sopenharmony_ci CZString keyLast(oldSize - 1); 3550ffe3c632Sopenharmony_ci ObjectValues::iterator itLast = value_.map_->find(keyLast); 3551ffe3c632Sopenharmony_ci value_.map_->erase(itLast); 3552ffe3c632Sopenharmony_ci return true; 3553ffe3c632Sopenharmony_ci} 3554ffe3c632Sopenharmony_ci 3555ffe3c632Sopenharmony_ci#ifdef JSON_USE_CPPTL 3556ffe3c632Sopenharmony_ciValue Value::get(const CppTL::ConstString& key, 3557ffe3c632Sopenharmony_ci const Value& defaultValue) const { 3558ffe3c632Sopenharmony_ci return get(key.c_str(), key.end_c_str(), defaultValue); 3559ffe3c632Sopenharmony_ci} 3560ffe3c632Sopenharmony_ci#endif 3561ffe3c632Sopenharmony_ci 3562ffe3c632Sopenharmony_cibool Value::isMember(char const* key, char const* cend) const 3563ffe3c632Sopenharmony_ci{ 3564ffe3c632Sopenharmony_ci Value const* value = find(key, cend); 3565ffe3c632Sopenharmony_ci return NULL != value; 3566ffe3c632Sopenharmony_ci} 3567ffe3c632Sopenharmony_cibool Value::isMember(char const* key) const 3568ffe3c632Sopenharmony_ci{ 3569ffe3c632Sopenharmony_ci return isMember(key, key + strlen(key)); 3570ffe3c632Sopenharmony_ci} 3571ffe3c632Sopenharmony_cibool Value::isMember(std::string const& key) const 3572ffe3c632Sopenharmony_ci{ 3573ffe3c632Sopenharmony_ci return isMember(key.data(), key.data() + key.length()); 3574ffe3c632Sopenharmony_ci} 3575ffe3c632Sopenharmony_ci 3576ffe3c632Sopenharmony_ci#ifdef JSON_USE_CPPTL 3577ffe3c632Sopenharmony_cibool Value::isMember(const CppTL::ConstString& key) const { 3578ffe3c632Sopenharmony_ci return isMember(key.c_str(), key.end_c_str()); 3579ffe3c632Sopenharmony_ci} 3580ffe3c632Sopenharmony_ci#endif 3581ffe3c632Sopenharmony_ci 3582ffe3c632Sopenharmony_ciValue::Members Value::getMemberNames() const { 3583ffe3c632Sopenharmony_ci JSON_ASSERT_MESSAGE( 3584ffe3c632Sopenharmony_ci type_ == nullValue || type_ == objectValue, 3585ffe3c632Sopenharmony_ci "in Json::Value::getMemberNames(), value must be objectValue"); 3586ffe3c632Sopenharmony_ci if (type_ == nullValue) 3587ffe3c632Sopenharmony_ci return Value::Members(); 3588ffe3c632Sopenharmony_ci Members members; 3589ffe3c632Sopenharmony_ci members.reserve(value_.map_->size()); 3590ffe3c632Sopenharmony_ci ObjectValues::const_iterator it = value_.map_->begin(); 3591ffe3c632Sopenharmony_ci ObjectValues::const_iterator itEnd = value_.map_->end(); 3592ffe3c632Sopenharmony_ci for (; it != itEnd; ++it) { 3593ffe3c632Sopenharmony_ci members.push_back(std::string((*it).first.data(), 3594ffe3c632Sopenharmony_ci (*it).first.length())); 3595ffe3c632Sopenharmony_ci } 3596ffe3c632Sopenharmony_ci return members; 3597ffe3c632Sopenharmony_ci} 3598ffe3c632Sopenharmony_ci// 3599ffe3c632Sopenharmony_ci//# ifdef JSON_USE_CPPTL 3600ffe3c632Sopenharmony_ci// EnumMemberNames 3601ffe3c632Sopenharmony_ci// Value::enumMemberNames() const 3602ffe3c632Sopenharmony_ci//{ 3603ffe3c632Sopenharmony_ci// if ( type_ == objectValue ) 3604ffe3c632Sopenharmony_ci// { 3605ffe3c632Sopenharmony_ci// return CppTL::Enum::any( CppTL::Enum::transform( 3606ffe3c632Sopenharmony_ci// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ), 3607ffe3c632Sopenharmony_ci// MemberNamesTransform() ) ); 3608ffe3c632Sopenharmony_ci// } 3609ffe3c632Sopenharmony_ci// return EnumMemberNames(); 3610ffe3c632Sopenharmony_ci//} 3611ffe3c632Sopenharmony_ci// 3612ffe3c632Sopenharmony_ci// 3613ffe3c632Sopenharmony_ci// EnumValues 3614ffe3c632Sopenharmony_ci// Value::enumValues() const 3615ffe3c632Sopenharmony_ci//{ 3616ffe3c632Sopenharmony_ci// if ( type_ == objectValue || type_ == arrayValue ) 3617ffe3c632Sopenharmony_ci// return CppTL::Enum::anyValues( *(value_.map_), 3618ffe3c632Sopenharmony_ci// CppTL::Type<const Value &>() ); 3619ffe3c632Sopenharmony_ci// return EnumValues(); 3620ffe3c632Sopenharmony_ci//} 3621ffe3c632Sopenharmony_ci// 3622ffe3c632Sopenharmony_ci//# endif 3623ffe3c632Sopenharmony_ci 3624ffe3c632Sopenharmony_cistatic bool IsIntegral(double d) { 3625ffe3c632Sopenharmony_ci double integral_part; 3626ffe3c632Sopenharmony_ci return modf(d, &integral_part) == 0.0; 3627ffe3c632Sopenharmony_ci} 3628ffe3c632Sopenharmony_ci 3629ffe3c632Sopenharmony_cibool Value::isNull() const { return type_ == nullValue; } 3630ffe3c632Sopenharmony_ci 3631ffe3c632Sopenharmony_cibool Value::isBool() const { return type_ == booleanValue; } 3632ffe3c632Sopenharmony_ci 3633ffe3c632Sopenharmony_cibool Value::isInt() const { 3634ffe3c632Sopenharmony_ci switch (type_) { 3635ffe3c632Sopenharmony_ci case intValue: 3636ffe3c632Sopenharmony_ci return value_.int_ >= minInt && value_.int_ <= maxInt; 3637ffe3c632Sopenharmony_ci case uintValue: 3638ffe3c632Sopenharmony_ci return value_.uint_ <= UInt(maxInt); 3639ffe3c632Sopenharmony_ci case realValue: 3640ffe3c632Sopenharmony_ci return value_.real_ >= minInt && value_.real_ <= maxInt && 3641ffe3c632Sopenharmony_ci IsIntegral(value_.real_); 3642ffe3c632Sopenharmony_ci default: 3643ffe3c632Sopenharmony_ci break; 3644ffe3c632Sopenharmony_ci } 3645ffe3c632Sopenharmony_ci return false; 3646ffe3c632Sopenharmony_ci} 3647ffe3c632Sopenharmony_ci 3648ffe3c632Sopenharmony_cibool Value::isUInt() const { 3649ffe3c632Sopenharmony_ci switch (type_) { 3650ffe3c632Sopenharmony_ci case intValue: 3651ffe3c632Sopenharmony_ci return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); 3652ffe3c632Sopenharmony_ci case uintValue: 3653ffe3c632Sopenharmony_ci return value_.uint_ <= maxUInt; 3654ffe3c632Sopenharmony_ci case realValue: 3655ffe3c632Sopenharmony_ci return value_.real_ >= 0 && value_.real_ <= maxUInt && 3656ffe3c632Sopenharmony_ci IsIntegral(value_.real_); 3657ffe3c632Sopenharmony_ci default: 3658ffe3c632Sopenharmony_ci break; 3659ffe3c632Sopenharmony_ci } 3660ffe3c632Sopenharmony_ci return false; 3661ffe3c632Sopenharmony_ci} 3662ffe3c632Sopenharmony_ci 3663ffe3c632Sopenharmony_cibool Value::isInt64() const { 3664ffe3c632Sopenharmony_ci#if defined(JSON_HAS_INT64) 3665ffe3c632Sopenharmony_ci switch (type_) { 3666ffe3c632Sopenharmony_ci case intValue: 3667ffe3c632Sopenharmony_ci return true; 3668ffe3c632Sopenharmony_ci case uintValue: 3669ffe3c632Sopenharmony_ci return value_.uint_ <= UInt64(maxInt64); 3670ffe3c632Sopenharmony_ci case realValue: 3671ffe3c632Sopenharmony_ci // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a 3672ffe3c632Sopenharmony_ci // double, so double(maxInt64) will be rounded up to 2^63. Therefore we 3673ffe3c632Sopenharmony_ci // require the value to be strictly less than the limit. 3674ffe3c632Sopenharmony_ci return value_.real_ >= double(minInt64) && 3675ffe3c632Sopenharmony_ci value_.real_ < double(maxInt64) && IsIntegral(value_.real_); 3676ffe3c632Sopenharmony_ci default: 3677ffe3c632Sopenharmony_ci break; 3678ffe3c632Sopenharmony_ci } 3679ffe3c632Sopenharmony_ci#endif // JSON_HAS_INT64 3680ffe3c632Sopenharmony_ci return false; 3681ffe3c632Sopenharmony_ci} 3682ffe3c632Sopenharmony_ci 3683ffe3c632Sopenharmony_cibool Value::isUInt64() const { 3684ffe3c632Sopenharmony_ci#if defined(JSON_HAS_INT64) 3685ffe3c632Sopenharmony_ci switch (type_) { 3686ffe3c632Sopenharmony_ci case intValue: 3687ffe3c632Sopenharmony_ci return value_.int_ >= 0; 3688ffe3c632Sopenharmony_ci case uintValue: 3689ffe3c632Sopenharmony_ci return true; 3690ffe3c632Sopenharmony_ci case realValue: 3691ffe3c632Sopenharmony_ci // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a 3692ffe3c632Sopenharmony_ci // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we 3693ffe3c632Sopenharmony_ci // require the value to be strictly less than the limit. 3694ffe3c632Sopenharmony_ci return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && 3695ffe3c632Sopenharmony_ci IsIntegral(value_.real_); 3696ffe3c632Sopenharmony_ci default: 3697ffe3c632Sopenharmony_ci break; 3698ffe3c632Sopenharmony_ci } 3699ffe3c632Sopenharmony_ci#endif // JSON_HAS_INT64 3700ffe3c632Sopenharmony_ci return false; 3701ffe3c632Sopenharmony_ci} 3702ffe3c632Sopenharmony_ci 3703ffe3c632Sopenharmony_cibool Value::isIntegral() const { 3704ffe3c632Sopenharmony_ci#if defined(JSON_HAS_INT64) 3705ffe3c632Sopenharmony_ci return isInt64() || isUInt64(); 3706ffe3c632Sopenharmony_ci#else 3707ffe3c632Sopenharmony_ci return isInt() || isUInt(); 3708ffe3c632Sopenharmony_ci#endif 3709ffe3c632Sopenharmony_ci} 3710ffe3c632Sopenharmony_ci 3711ffe3c632Sopenharmony_cibool Value::isDouble() const { return type_ == realValue || isIntegral(); } 3712ffe3c632Sopenharmony_ci 3713ffe3c632Sopenharmony_cibool Value::isNumeric() const { return isIntegral() || isDouble(); } 3714ffe3c632Sopenharmony_ci 3715ffe3c632Sopenharmony_cibool Value::isString() const { return type_ == stringValue; } 3716ffe3c632Sopenharmony_ci 3717ffe3c632Sopenharmony_cibool Value::isArray() const { return type_ == arrayValue; } 3718ffe3c632Sopenharmony_ci 3719ffe3c632Sopenharmony_cibool Value::isObject() const { return type_ == objectValue; } 3720ffe3c632Sopenharmony_ci 3721ffe3c632Sopenharmony_civoid Value::setComment(const char* comment, size_t len, CommentPlacement placement) { 3722ffe3c632Sopenharmony_ci if (!comments_) 3723ffe3c632Sopenharmony_ci comments_ = new CommentInfo[numberOfCommentPlacement]; 3724ffe3c632Sopenharmony_ci if ((len > 0) && (comment[len-1] == '\n')) { 3725ffe3c632Sopenharmony_ci // Always discard trailing newline, to aid indentation. 3726ffe3c632Sopenharmony_ci len -= 1; 3727ffe3c632Sopenharmony_ci } 3728ffe3c632Sopenharmony_ci comments_[placement].setComment(comment, len); 3729ffe3c632Sopenharmony_ci} 3730ffe3c632Sopenharmony_ci 3731ffe3c632Sopenharmony_civoid Value::setComment(const char* comment, CommentPlacement placement) { 3732ffe3c632Sopenharmony_ci setComment(comment, strlen(comment), placement); 3733ffe3c632Sopenharmony_ci} 3734ffe3c632Sopenharmony_ci 3735ffe3c632Sopenharmony_civoid Value::setComment(const std::string& comment, CommentPlacement placement) { 3736ffe3c632Sopenharmony_ci setComment(comment.c_str(), comment.length(), placement); 3737ffe3c632Sopenharmony_ci} 3738ffe3c632Sopenharmony_ci 3739ffe3c632Sopenharmony_cibool Value::hasComment(CommentPlacement placement) const { 3740ffe3c632Sopenharmony_ci return comments_ != 0 && comments_[placement].comment_ != 0; 3741ffe3c632Sopenharmony_ci} 3742ffe3c632Sopenharmony_ci 3743ffe3c632Sopenharmony_cistd::string Value::getComment(CommentPlacement placement) const { 3744ffe3c632Sopenharmony_ci if (hasComment(placement)) 3745ffe3c632Sopenharmony_ci return comments_[placement].comment_; 3746ffe3c632Sopenharmony_ci return ""; 3747ffe3c632Sopenharmony_ci} 3748ffe3c632Sopenharmony_ci 3749ffe3c632Sopenharmony_civoid Value::setOffsetStart(size_t start) { start_ = start; } 3750ffe3c632Sopenharmony_ci 3751ffe3c632Sopenharmony_civoid Value::setOffsetLimit(size_t limit) { limit_ = limit; } 3752ffe3c632Sopenharmony_ci 3753ffe3c632Sopenharmony_cisize_t Value::getOffsetStart() const { return start_; } 3754ffe3c632Sopenharmony_ci 3755ffe3c632Sopenharmony_cisize_t Value::getOffsetLimit() const { return limit_; } 3756ffe3c632Sopenharmony_ci 3757ffe3c632Sopenharmony_cistd::string Value::toStyledString() const { 3758ffe3c632Sopenharmony_ci StyledWriter writer; 3759ffe3c632Sopenharmony_ci return writer.write(*this); 3760ffe3c632Sopenharmony_ci} 3761ffe3c632Sopenharmony_ci 3762ffe3c632Sopenharmony_ciValue::const_iterator Value::begin() const { 3763ffe3c632Sopenharmony_ci switch (type_) { 3764ffe3c632Sopenharmony_ci case arrayValue: 3765ffe3c632Sopenharmony_ci case objectValue: 3766ffe3c632Sopenharmony_ci if (value_.map_) 3767ffe3c632Sopenharmony_ci return const_iterator(value_.map_->begin()); 3768ffe3c632Sopenharmony_ci break; 3769ffe3c632Sopenharmony_ci default: 3770ffe3c632Sopenharmony_ci break; 3771ffe3c632Sopenharmony_ci } 3772ffe3c632Sopenharmony_ci return const_iterator(); 3773ffe3c632Sopenharmony_ci} 3774ffe3c632Sopenharmony_ci 3775ffe3c632Sopenharmony_ciValue::const_iterator Value::end() const { 3776ffe3c632Sopenharmony_ci switch (type_) { 3777ffe3c632Sopenharmony_ci case arrayValue: 3778ffe3c632Sopenharmony_ci case objectValue: 3779ffe3c632Sopenharmony_ci if (value_.map_) 3780ffe3c632Sopenharmony_ci return const_iterator(value_.map_->end()); 3781ffe3c632Sopenharmony_ci break; 3782ffe3c632Sopenharmony_ci default: 3783ffe3c632Sopenharmony_ci break; 3784ffe3c632Sopenharmony_ci } 3785ffe3c632Sopenharmony_ci return const_iterator(); 3786ffe3c632Sopenharmony_ci} 3787ffe3c632Sopenharmony_ci 3788ffe3c632Sopenharmony_ciValue::iterator Value::begin() { 3789ffe3c632Sopenharmony_ci switch (type_) { 3790ffe3c632Sopenharmony_ci case arrayValue: 3791ffe3c632Sopenharmony_ci case objectValue: 3792ffe3c632Sopenharmony_ci if (value_.map_) 3793ffe3c632Sopenharmony_ci return iterator(value_.map_->begin()); 3794ffe3c632Sopenharmony_ci break; 3795ffe3c632Sopenharmony_ci default: 3796ffe3c632Sopenharmony_ci break; 3797ffe3c632Sopenharmony_ci } 3798ffe3c632Sopenharmony_ci return iterator(); 3799ffe3c632Sopenharmony_ci} 3800ffe3c632Sopenharmony_ci 3801ffe3c632Sopenharmony_ciValue::iterator Value::end() { 3802ffe3c632Sopenharmony_ci switch (type_) { 3803ffe3c632Sopenharmony_ci case arrayValue: 3804ffe3c632Sopenharmony_ci case objectValue: 3805ffe3c632Sopenharmony_ci if (value_.map_) 3806ffe3c632Sopenharmony_ci return iterator(value_.map_->end()); 3807ffe3c632Sopenharmony_ci break; 3808ffe3c632Sopenharmony_ci default: 3809ffe3c632Sopenharmony_ci break; 3810ffe3c632Sopenharmony_ci } 3811ffe3c632Sopenharmony_ci return iterator(); 3812ffe3c632Sopenharmony_ci} 3813ffe3c632Sopenharmony_ci 3814ffe3c632Sopenharmony_ci// class PathArgument 3815ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 3816ffe3c632Sopenharmony_ci 3817ffe3c632Sopenharmony_ciPathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {} 3818ffe3c632Sopenharmony_ci 3819ffe3c632Sopenharmony_ciPathArgument::PathArgument(ArrayIndex index) 3820ffe3c632Sopenharmony_ci : key_(), index_(index), kind_(kindIndex) {} 3821ffe3c632Sopenharmony_ci 3822ffe3c632Sopenharmony_ciPathArgument::PathArgument(const char* key) 3823ffe3c632Sopenharmony_ci : key_(key), index_(), kind_(kindKey) {} 3824ffe3c632Sopenharmony_ci 3825ffe3c632Sopenharmony_ciPathArgument::PathArgument(const std::string& key) 3826ffe3c632Sopenharmony_ci : key_(key.c_str()), index_(), kind_(kindKey) {} 3827ffe3c632Sopenharmony_ci 3828ffe3c632Sopenharmony_ci// class Path 3829ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 3830ffe3c632Sopenharmony_ci 3831ffe3c632Sopenharmony_ciPath::Path(const std::string& path, 3832ffe3c632Sopenharmony_ci const PathArgument& a1, 3833ffe3c632Sopenharmony_ci const PathArgument& a2, 3834ffe3c632Sopenharmony_ci const PathArgument& a3, 3835ffe3c632Sopenharmony_ci const PathArgument& a4, 3836ffe3c632Sopenharmony_ci const PathArgument& a5) { 3837ffe3c632Sopenharmony_ci InArgs in; 3838ffe3c632Sopenharmony_ci in.push_back(&a1); 3839ffe3c632Sopenharmony_ci in.push_back(&a2); 3840ffe3c632Sopenharmony_ci in.push_back(&a3); 3841ffe3c632Sopenharmony_ci in.push_back(&a4); 3842ffe3c632Sopenharmony_ci in.push_back(&a5); 3843ffe3c632Sopenharmony_ci makePath(path, in); 3844ffe3c632Sopenharmony_ci} 3845ffe3c632Sopenharmony_ci 3846ffe3c632Sopenharmony_civoid Path::makePath(const std::string& path, const InArgs& in) { 3847ffe3c632Sopenharmony_ci const char* current = path.c_str(); 3848ffe3c632Sopenharmony_ci const char* end = current + path.length(); 3849ffe3c632Sopenharmony_ci InArgs::const_iterator itInArg = in.begin(); 3850ffe3c632Sopenharmony_ci while (current != end) { 3851ffe3c632Sopenharmony_ci if (*current == '[') { 3852ffe3c632Sopenharmony_ci ++current; 3853ffe3c632Sopenharmony_ci if (*current == '%') 3854ffe3c632Sopenharmony_ci addPathInArg(path, in, itInArg, PathArgument::kindIndex); 3855ffe3c632Sopenharmony_ci else { 3856ffe3c632Sopenharmony_ci ArrayIndex index = 0; 3857ffe3c632Sopenharmony_ci for (; current != end && *current >= '0' && *current <= '9'; ++current) 3858ffe3c632Sopenharmony_ci index = index * 10 + ArrayIndex(*current - '0'); 3859ffe3c632Sopenharmony_ci args_.push_back(index); 3860ffe3c632Sopenharmony_ci } 3861ffe3c632Sopenharmony_ci if (current == end || *current++ != ']') 3862ffe3c632Sopenharmony_ci invalidPath(path, int(current - path.c_str())); 3863ffe3c632Sopenharmony_ci } else if (*current == '%') { 3864ffe3c632Sopenharmony_ci addPathInArg(path, in, itInArg, PathArgument::kindKey); 3865ffe3c632Sopenharmony_ci ++current; 3866ffe3c632Sopenharmony_ci } else if (*current == '.') { 3867ffe3c632Sopenharmony_ci ++current; 3868ffe3c632Sopenharmony_ci } else { 3869ffe3c632Sopenharmony_ci const char* beginName = current; 3870ffe3c632Sopenharmony_ci while (current != end && !strchr("[.", *current)) 3871ffe3c632Sopenharmony_ci ++current; 3872ffe3c632Sopenharmony_ci args_.push_back(std::string(beginName, current)); 3873ffe3c632Sopenharmony_ci } 3874ffe3c632Sopenharmony_ci } 3875ffe3c632Sopenharmony_ci} 3876ffe3c632Sopenharmony_ci 3877ffe3c632Sopenharmony_civoid Path::addPathInArg(const std::string& /*path*/, 3878ffe3c632Sopenharmony_ci const InArgs& in, 3879ffe3c632Sopenharmony_ci InArgs::const_iterator& itInArg, 3880ffe3c632Sopenharmony_ci PathArgument::Kind kind) { 3881ffe3c632Sopenharmony_ci if (itInArg == in.end()) { 3882ffe3c632Sopenharmony_ci // Error: missing argument %d 3883ffe3c632Sopenharmony_ci } else if ((*itInArg)->kind_ != kind) { 3884ffe3c632Sopenharmony_ci // Error: bad argument type 3885ffe3c632Sopenharmony_ci } else { 3886ffe3c632Sopenharmony_ci args_.push_back(**itInArg); 3887ffe3c632Sopenharmony_ci } 3888ffe3c632Sopenharmony_ci} 3889ffe3c632Sopenharmony_ci 3890ffe3c632Sopenharmony_civoid Path::invalidPath(const std::string& /*path*/, int /*location*/) { 3891ffe3c632Sopenharmony_ci // Error: invalid path. 3892ffe3c632Sopenharmony_ci} 3893ffe3c632Sopenharmony_ci 3894ffe3c632Sopenharmony_ciconst Value& Path::resolve(const Value& root) const { 3895ffe3c632Sopenharmony_ci const Value* node = &root; 3896ffe3c632Sopenharmony_ci for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { 3897ffe3c632Sopenharmony_ci const PathArgument& arg = *it; 3898ffe3c632Sopenharmony_ci if (arg.kind_ == PathArgument::kindIndex) { 3899ffe3c632Sopenharmony_ci if (!node->isArray() || !node->isValidIndex(arg.index_)) { 3900ffe3c632Sopenharmony_ci // Error: unable to resolve path (array value expected at position... 3901ffe3c632Sopenharmony_ci } 3902ffe3c632Sopenharmony_ci node = &((*node)[arg.index_]); 3903ffe3c632Sopenharmony_ci } else if (arg.kind_ == PathArgument::kindKey) { 3904ffe3c632Sopenharmony_ci if (!node->isObject()) { 3905ffe3c632Sopenharmony_ci // Error: unable to resolve path (object value expected at position...) 3906ffe3c632Sopenharmony_ci } 3907ffe3c632Sopenharmony_ci node = &((*node)[arg.key_]); 3908ffe3c632Sopenharmony_ci if (node == &Value::nullRef) { 3909ffe3c632Sopenharmony_ci // Error: unable to resolve path (object has no member named '' at 3910ffe3c632Sopenharmony_ci // position...) 3911ffe3c632Sopenharmony_ci } 3912ffe3c632Sopenharmony_ci } 3913ffe3c632Sopenharmony_ci } 3914ffe3c632Sopenharmony_ci return *node; 3915ffe3c632Sopenharmony_ci} 3916ffe3c632Sopenharmony_ci 3917ffe3c632Sopenharmony_ciValue Path::resolve(const Value& root, const Value& defaultValue) const { 3918ffe3c632Sopenharmony_ci const Value* node = &root; 3919ffe3c632Sopenharmony_ci for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { 3920ffe3c632Sopenharmony_ci const PathArgument& arg = *it; 3921ffe3c632Sopenharmony_ci if (arg.kind_ == PathArgument::kindIndex) { 3922ffe3c632Sopenharmony_ci if (!node->isArray() || !node->isValidIndex(arg.index_)) 3923ffe3c632Sopenharmony_ci return defaultValue; 3924ffe3c632Sopenharmony_ci node = &((*node)[arg.index_]); 3925ffe3c632Sopenharmony_ci } else if (arg.kind_ == PathArgument::kindKey) { 3926ffe3c632Sopenharmony_ci if (!node->isObject()) 3927ffe3c632Sopenharmony_ci return defaultValue; 3928ffe3c632Sopenharmony_ci node = &((*node)[arg.key_]); 3929ffe3c632Sopenharmony_ci if (node == &Value::nullRef) 3930ffe3c632Sopenharmony_ci return defaultValue; 3931ffe3c632Sopenharmony_ci } 3932ffe3c632Sopenharmony_ci } 3933ffe3c632Sopenharmony_ci return *node; 3934ffe3c632Sopenharmony_ci} 3935ffe3c632Sopenharmony_ci 3936ffe3c632Sopenharmony_ciValue& Path::make(Value& root) const { 3937ffe3c632Sopenharmony_ci Value* node = &root; 3938ffe3c632Sopenharmony_ci for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { 3939ffe3c632Sopenharmony_ci const PathArgument& arg = *it; 3940ffe3c632Sopenharmony_ci if (arg.kind_ == PathArgument::kindIndex) { 3941ffe3c632Sopenharmony_ci if (!node->isArray()) { 3942ffe3c632Sopenharmony_ci // Error: node is not an array at position ... 3943ffe3c632Sopenharmony_ci } 3944ffe3c632Sopenharmony_ci node = &((*node)[arg.index_]); 3945ffe3c632Sopenharmony_ci } else if (arg.kind_ == PathArgument::kindKey) { 3946ffe3c632Sopenharmony_ci if (!node->isObject()) { 3947ffe3c632Sopenharmony_ci // Error: node is not an object at position... 3948ffe3c632Sopenharmony_ci } 3949ffe3c632Sopenharmony_ci node = &((*node)[arg.key_]); 3950ffe3c632Sopenharmony_ci } 3951ffe3c632Sopenharmony_ci } 3952ffe3c632Sopenharmony_ci return *node; 3953ffe3c632Sopenharmony_ci} 3954ffe3c632Sopenharmony_ci 3955ffe3c632Sopenharmony_ci} // namespace Json 3956ffe3c632Sopenharmony_ci 3957ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 3958ffe3c632Sopenharmony_ci// End of content of file: src/lib_json/json_value.cpp 3959ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 3960ffe3c632Sopenharmony_ci 3961ffe3c632Sopenharmony_ci 3962ffe3c632Sopenharmony_ci 3963ffe3c632Sopenharmony_ci 3964ffe3c632Sopenharmony_ci 3965ffe3c632Sopenharmony_ci 3966ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 3967ffe3c632Sopenharmony_ci// Beginning of content of file: src/lib_json/json_writer.cpp 3968ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 3969ffe3c632Sopenharmony_ci 3970ffe3c632Sopenharmony_ci// Copyright 2011 Baptiste Lepilleur 3971ffe3c632Sopenharmony_ci// Distributed under MIT license, or public domain if desired and 3972ffe3c632Sopenharmony_ci// recognized in your jurisdiction. 3973ffe3c632Sopenharmony_ci// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 3974ffe3c632Sopenharmony_ci 3975ffe3c632Sopenharmony_ci#if !defined(JSON_IS_AMALGAMATION) 3976ffe3c632Sopenharmony_ci#include <json/writer.h> 3977ffe3c632Sopenharmony_ci#include "json_tool.h" 3978ffe3c632Sopenharmony_ci#endif // if !defined(JSON_IS_AMALGAMATION) 3979ffe3c632Sopenharmony_ci#include <iomanip> 3980ffe3c632Sopenharmony_ci#include <memory> 3981ffe3c632Sopenharmony_ci#include <sstream> 3982ffe3c632Sopenharmony_ci#include <utility> 3983ffe3c632Sopenharmony_ci#include <set> 3984ffe3c632Sopenharmony_ci#include <cassert> 3985ffe3c632Sopenharmony_ci#include <cstring> 3986ffe3c632Sopenharmony_ci#include <cstdio> 3987ffe3c632Sopenharmony_ci 3988ffe3c632Sopenharmony_ci#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0 3989ffe3c632Sopenharmony_ci#include <float.h> 3990ffe3c632Sopenharmony_ci#define isfinite _finite 3991ffe3c632Sopenharmony_ci#elif defined(__sun) && defined(__SVR4) //Solaris 3992ffe3c632Sopenharmony_ci#if !defined(isfinite) 3993ffe3c632Sopenharmony_ci#include <ieeefp.h> 3994ffe3c632Sopenharmony_ci#define isfinite finite 3995ffe3c632Sopenharmony_ci#endif 3996ffe3c632Sopenharmony_ci#elif defined(_AIX) 3997ffe3c632Sopenharmony_ci#if !defined(isfinite) 3998ffe3c632Sopenharmony_ci#include <math.h> 3999ffe3c632Sopenharmony_ci#define isfinite finite 4000ffe3c632Sopenharmony_ci#endif 4001ffe3c632Sopenharmony_ci#elif defined(__hpux) 4002ffe3c632Sopenharmony_ci#if !defined(isfinite) 4003ffe3c632Sopenharmony_ci#if defined(__ia64) && !defined(finite) 4004ffe3c632Sopenharmony_ci#define isfinite(x) ((sizeof(x) == sizeof(float) ? \ 4005ffe3c632Sopenharmony_ci _Isfinitef(x) : _IsFinite(x))) 4006ffe3c632Sopenharmony_ci#else 4007ffe3c632Sopenharmony_ci#include <math.h> 4008ffe3c632Sopenharmony_ci#define isfinite finite 4009ffe3c632Sopenharmony_ci#endif 4010ffe3c632Sopenharmony_ci#endif 4011ffe3c632Sopenharmony_ci#else 4012ffe3c632Sopenharmony_ci#include <cmath> 4013ffe3c632Sopenharmony_ci#if !(defined(__QNXNTO__)) // QNX already defines isfinite 4014ffe3c632Sopenharmony_ci#define isfinite std::isfinite 4015ffe3c632Sopenharmony_ci#endif 4016ffe3c632Sopenharmony_ci#endif 4017ffe3c632Sopenharmony_ci 4018ffe3c632Sopenharmony_ci#if defined(_MSC_VER) 4019ffe3c632Sopenharmony_ci#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above 4020ffe3c632Sopenharmony_ci#define snprintf sprintf_s 4021ffe3c632Sopenharmony_ci#elif _MSC_VER >= 1900 // VC++ 14.0 and above 4022ffe3c632Sopenharmony_ci#define snprintf std::snprintf 4023ffe3c632Sopenharmony_ci#else 4024ffe3c632Sopenharmony_ci#define snprintf _snprintf 4025ffe3c632Sopenharmony_ci#endif 4026ffe3c632Sopenharmony_ci#elif defined(__ANDROID__) || defined(__QNXNTO__) 4027ffe3c632Sopenharmony_ci#define snprintf snprintf 4028ffe3c632Sopenharmony_ci#elif __cplusplus >= 201103L 4029ffe3c632Sopenharmony_ci#define snprintf std::snprintf 4030ffe3c632Sopenharmony_ci#endif 4031ffe3c632Sopenharmony_ci 4032ffe3c632Sopenharmony_ci#if defined(__BORLANDC__) 4033ffe3c632Sopenharmony_ci#include <float.h> 4034ffe3c632Sopenharmony_ci#define isfinite _finite 4035ffe3c632Sopenharmony_ci#define snprintf _snprintf 4036ffe3c632Sopenharmony_ci#endif 4037ffe3c632Sopenharmony_ci 4038ffe3c632Sopenharmony_ci#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 4039ffe3c632Sopenharmony_ci// Disable warning about strdup being deprecated. 4040ffe3c632Sopenharmony_ci#pragma warning(disable : 4996) 4041ffe3c632Sopenharmony_ci#endif 4042ffe3c632Sopenharmony_ci 4043ffe3c632Sopenharmony_cinamespace Json { 4044ffe3c632Sopenharmony_ci 4045ffe3c632Sopenharmony_ci#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) 4046ffe3c632Sopenharmony_citypedef std::unique_ptr<StreamWriter> StreamWriterPtr; 4047ffe3c632Sopenharmony_ci#else 4048ffe3c632Sopenharmony_citypedef std::auto_ptr<StreamWriter> StreamWriterPtr; 4049ffe3c632Sopenharmony_ci#endif 4050ffe3c632Sopenharmony_ci 4051ffe3c632Sopenharmony_cistatic bool containsControlCharacter(const char* str) { 4052ffe3c632Sopenharmony_ci while (*str) { 4053ffe3c632Sopenharmony_ci if (isControlCharacter(*(str++))) 4054ffe3c632Sopenharmony_ci return true; 4055ffe3c632Sopenharmony_ci } 4056ffe3c632Sopenharmony_ci return false; 4057ffe3c632Sopenharmony_ci} 4058ffe3c632Sopenharmony_ci 4059ffe3c632Sopenharmony_cistatic bool containsControlCharacter0(const char* str, unsigned len) { 4060ffe3c632Sopenharmony_ci char const* end = str + len; 4061ffe3c632Sopenharmony_ci while (end != str) { 4062ffe3c632Sopenharmony_ci if (isControlCharacter(*str) || 0==*str) 4063ffe3c632Sopenharmony_ci return true; 4064ffe3c632Sopenharmony_ci ++str; 4065ffe3c632Sopenharmony_ci } 4066ffe3c632Sopenharmony_ci return false; 4067ffe3c632Sopenharmony_ci} 4068ffe3c632Sopenharmony_ci 4069ffe3c632Sopenharmony_cistd::string valueToString(LargestInt value) { 4070ffe3c632Sopenharmony_ci UIntToStringBuffer buffer; 4071ffe3c632Sopenharmony_ci char* current = buffer + sizeof(buffer); 4072ffe3c632Sopenharmony_ci if (value == Value::minLargestInt) { 4073ffe3c632Sopenharmony_ci uintToString(LargestUInt(Value::maxLargestInt) + 1, current); 4074ffe3c632Sopenharmony_ci *--current = '-'; 4075ffe3c632Sopenharmony_ci } else if (value < 0) { 4076ffe3c632Sopenharmony_ci uintToString(LargestUInt(-value), current); 4077ffe3c632Sopenharmony_ci *--current = '-'; 4078ffe3c632Sopenharmony_ci } else { 4079ffe3c632Sopenharmony_ci uintToString(LargestUInt(value), current); 4080ffe3c632Sopenharmony_ci } 4081ffe3c632Sopenharmony_ci assert(current >= buffer); 4082ffe3c632Sopenharmony_ci return current; 4083ffe3c632Sopenharmony_ci} 4084ffe3c632Sopenharmony_ci 4085ffe3c632Sopenharmony_cistd::string valueToString(LargestUInt value) { 4086ffe3c632Sopenharmony_ci UIntToStringBuffer buffer; 4087ffe3c632Sopenharmony_ci char* current = buffer + sizeof(buffer); 4088ffe3c632Sopenharmony_ci uintToString(value, current); 4089ffe3c632Sopenharmony_ci assert(current >= buffer); 4090ffe3c632Sopenharmony_ci return current; 4091ffe3c632Sopenharmony_ci} 4092ffe3c632Sopenharmony_ci 4093ffe3c632Sopenharmony_ci#if defined(JSON_HAS_INT64) 4094ffe3c632Sopenharmony_ci 4095ffe3c632Sopenharmony_cistd::string valueToString(Int value) { 4096ffe3c632Sopenharmony_ci return valueToString(LargestInt(value)); 4097ffe3c632Sopenharmony_ci} 4098ffe3c632Sopenharmony_ci 4099ffe3c632Sopenharmony_cistd::string valueToString(UInt value) { 4100ffe3c632Sopenharmony_ci return valueToString(LargestUInt(value)); 4101ffe3c632Sopenharmony_ci} 4102ffe3c632Sopenharmony_ci 4103ffe3c632Sopenharmony_ci#endif // # if defined(JSON_HAS_INT64) 4104ffe3c632Sopenharmony_ci 4105ffe3c632Sopenharmony_cistd::string valueToString(double value, bool useSpecialFloats, unsigned int precision) { 4106ffe3c632Sopenharmony_ci // Allocate a buffer that is more than large enough to store the 16 digits of 4107ffe3c632Sopenharmony_ci // precision requested below. 4108ffe3c632Sopenharmony_ci char buffer[32]; 4109ffe3c632Sopenharmony_ci int len = -1; 4110ffe3c632Sopenharmony_ci 4111ffe3c632Sopenharmony_ci char formatString[6]; 4112ffe3c632Sopenharmony_ci sprintf(formatString, "%%.%dg", precision); 4113ffe3c632Sopenharmony_ci 4114ffe3c632Sopenharmony_ci // Print into the buffer. We need not request the alternative representation 4115ffe3c632Sopenharmony_ci // that always has a decimal point because JSON doesn't distinguish the 4116ffe3c632Sopenharmony_ci // concepts of reals and integers. 4117ffe3c632Sopenharmony_ci if (isfinite(value)) { 4118ffe3c632Sopenharmony_ci len = snprintf(buffer, sizeof(buffer), formatString, value); 4119ffe3c632Sopenharmony_ci } else { 4120ffe3c632Sopenharmony_ci // IEEE standard states that NaN values will not compare to themselves 4121ffe3c632Sopenharmony_ci if (value != value) { 4122ffe3c632Sopenharmony_ci len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null"); 4123ffe3c632Sopenharmony_ci } else if (value < 0) { 4124ffe3c632Sopenharmony_ci len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999"); 4125ffe3c632Sopenharmony_ci } else { 4126ffe3c632Sopenharmony_ci len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999"); 4127ffe3c632Sopenharmony_ci } 4128ffe3c632Sopenharmony_ci // For those, we do not need to call fixNumLoc, but it is fast. 4129ffe3c632Sopenharmony_ci } 4130ffe3c632Sopenharmony_ci assert(len >= 0); 4131ffe3c632Sopenharmony_ci fixNumericLocale(buffer, buffer + len); 4132ffe3c632Sopenharmony_ci return buffer; 4133ffe3c632Sopenharmony_ci} 4134ffe3c632Sopenharmony_ci 4135ffe3c632Sopenharmony_cistd::string valueToString(double value) { return valueToString(value, false, 17); } 4136ffe3c632Sopenharmony_ci 4137ffe3c632Sopenharmony_cistd::string valueToString(bool value) { return value ? "true" : "false"; } 4138ffe3c632Sopenharmony_ci 4139ffe3c632Sopenharmony_cistd::string valueToQuotedString(const char* value) { 4140ffe3c632Sopenharmony_ci if (value == NULL) 4141ffe3c632Sopenharmony_ci return ""; 4142ffe3c632Sopenharmony_ci // Not sure how to handle unicode... 4143ffe3c632Sopenharmony_ci if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && 4144ffe3c632Sopenharmony_ci !containsControlCharacter(value)) 4145ffe3c632Sopenharmony_ci return std::string("\"") + value + "\""; 4146ffe3c632Sopenharmony_ci // We have to walk value and escape any special characters. 4147ffe3c632Sopenharmony_ci // Appending to std::string is not efficient, but this should be rare. 4148ffe3c632Sopenharmony_ci // (Note: forward slashes are *not* rare, but I am not escaping them.) 4149ffe3c632Sopenharmony_ci std::string::size_type maxsize = 4150ffe3c632Sopenharmony_ci strlen(value) * 2 + 3; // allescaped+quotes+NULL 4151ffe3c632Sopenharmony_ci std::string result; 4152ffe3c632Sopenharmony_ci result.reserve(maxsize); // to avoid lots of mallocs 4153ffe3c632Sopenharmony_ci result += "\""; 4154ffe3c632Sopenharmony_ci for (const char* c = value; *c != 0; ++c) { 4155ffe3c632Sopenharmony_ci switch (*c) { 4156ffe3c632Sopenharmony_ci case '\"': 4157ffe3c632Sopenharmony_ci result += "\\\""; 4158ffe3c632Sopenharmony_ci break; 4159ffe3c632Sopenharmony_ci case '\\': 4160ffe3c632Sopenharmony_ci result += "\\\\"; 4161ffe3c632Sopenharmony_ci break; 4162ffe3c632Sopenharmony_ci case '\b': 4163ffe3c632Sopenharmony_ci result += "\\b"; 4164ffe3c632Sopenharmony_ci break; 4165ffe3c632Sopenharmony_ci case '\f': 4166ffe3c632Sopenharmony_ci result += "\\f"; 4167ffe3c632Sopenharmony_ci break; 4168ffe3c632Sopenharmony_ci case '\n': 4169ffe3c632Sopenharmony_ci result += "\\n"; 4170ffe3c632Sopenharmony_ci break; 4171ffe3c632Sopenharmony_ci case '\r': 4172ffe3c632Sopenharmony_ci result += "\\r"; 4173ffe3c632Sopenharmony_ci break; 4174ffe3c632Sopenharmony_ci case '\t': 4175ffe3c632Sopenharmony_ci result += "\\t"; 4176ffe3c632Sopenharmony_ci break; 4177ffe3c632Sopenharmony_ci // case '/': 4178ffe3c632Sopenharmony_ci // Even though \/ is considered a legal escape in JSON, a bare 4179ffe3c632Sopenharmony_ci // slash is also legal, so I see no reason to escape it. 4180ffe3c632Sopenharmony_ci // (I hope I am not misunderstanding something. 4181ffe3c632Sopenharmony_ci // blep notes: actually escaping \/ may be useful in javascript to avoid </ 4182ffe3c632Sopenharmony_ci // sequence. 4183ffe3c632Sopenharmony_ci // Should add a flag to allow this compatibility mode and prevent this 4184ffe3c632Sopenharmony_ci // sequence from occurring. 4185ffe3c632Sopenharmony_ci default: 4186ffe3c632Sopenharmony_ci if (isControlCharacter(*c)) { 4187ffe3c632Sopenharmony_ci std::ostringstream oss; 4188ffe3c632Sopenharmony_ci oss << "\\u" << std::hex << std::uppercase << std::setfill('0') 4189ffe3c632Sopenharmony_ci << std::setw(4) << static_cast<int>(*c); 4190ffe3c632Sopenharmony_ci result += oss.str(); 4191ffe3c632Sopenharmony_ci } else { 4192ffe3c632Sopenharmony_ci result += *c; 4193ffe3c632Sopenharmony_ci } 4194ffe3c632Sopenharmony_ci break; 4195ffe3c632Sopenharmony_ci } 4196ffe3c632Sopenharmony_ci } 4197ffe3c632Sopenharmony_ci result += "\""; 4198ffe3c632Sopenharmony_ci return result; 4199ffe3c632Sopenharmony_ci} 4200ffe3c632Sopenharmony_ci 4201ffe3c632Sopenharmony_ci// https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp 4202ffe3c632Sopenharmony_cistatic char const* strnpbrk(char const* s, char const* accept, size_t n) { 4203ffe3c632Sopenharmony_ci assert((s || !n) && accept); 4204ffe3c632Sopenharmony_ci 4205ffe3c632Sopenharmony_ci char const* const end = s + n; 4206ffe3c632Sopenharmony_ci for (char const* cur = s; cur < end; ++cur) { 4207ffe3c632Sopenharmony_ci int const c = *cur; 4208ffe3c632Sopenharmony_ci for (char const* a = accept; *a; ++a) { 4209ffe3c632Sopenharmony_ci if (*a == c) { 4210ffe3c632Sopenharmony_ci return cur; 4211ffe3c632Sopenharmony_ci } 4212ffe3c632Sopenharmony_ci } 4213ffe3c632Sopenharmony_ci } 4214ffe3c632Sopenharmony_ci return NULL; 4215ffe3c632Sopenharmony_ci} 4216ffe3c632Sopenharmony_cistatic std::string valueToQuotedStringN(const char* value, unsigned length) { 4217ffe3c632Sopenharmony_ci if (value == NULL) 4218ffe3c632Sopenharmony_ci return ""; 4219ffe3c632Sopenharmony_ci // Not sure how to handle unicode... 4220ffe3c632Sopenharmony_ci if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL && 4221ffe3c632Sopenharmony_ci !containsControlCharacter0(value, length)) 4222ffe3c632Sopenharmony_ci return std::string("\"") + value + "\""; 4223ffe3c632Sopenharmony_ci // We have to walk value and escape any special characters. 4224ffe3c632Sopenharmony_ci // Appending to std::string is not efficient, but this should be rare. 4225ffe3c632Sopenharmony_ci // (Note: forward slashes are *not* rare, but I am not escaping them.) 4226ffe3c632Sopenharmony_ci std::string::size_type maxsize = 4227ffe3c632Sopenharmony_ci length * 2 + 3; // allescaped+quotes+NULL 4228ffe3c632Sopenharmony_ci std::string result; 4229ffe3c632Sopenharmony_ci result.reserve(maxsize); // to avoid lots of mallocs 4230ffe3c632Sopenharmony_ci result += "\""; 4231ffe3c632Sopenharmony_ci char const* end = value + length; 4232ffe3c632Sopenharmony_ci for (const char* c = value; c != end; ++c) { 4233ffe3c632Sopenharmony_ci switch (*c) { 4234ffe3c632Sopenharmony_ci case '\"': 4235ffe3c632Sopenharmony_ci result += "\\\""; 4236ffe3c632Sopenharmony_ci break; 4237ffe3c632Sopenharmony_ci case '\\': 4238ffe3c632Sopenharmony_ci result += "\\\\"; 4239ffe3c632Sopenharmony_ci break; 4240ffe3c632Sopenharmony_ci case '\b': 4241ffe3c632Sopenharmony_ci result += "\\b"; 4242ffe3c632Sopenharmony_ci break; 4243ffe3c632Sopenharmony_ci case '\f': 4244ffe3c632Sopenharmony_ci result += "\\f"; 4245ffe3c632Sopenharmony_ci break; 4246ffe3c632Sopenharmony_ci case '\n': 4247ffe3c632Sopenharmony_ci result += "\\n"; 4248ffe3c632Sopenharmony_ci break; 4249ffe3c632Sopenharmony_ci case '\r': 4250ffe3c632Sopenharmony_ci result += "\\r"; 4251ffe3c632Sopenharmony_ci break; 4252ffe3c632Sopenharmony_ci case '\t': 4253ffe3c632Sopenharmony_ci result += "\\t"; 4254ffe3c632Sopenharmony_ci break; 4255ffe3c632Sopenharmony_ci // case '/': 4256ffe3c632Sopenharmony_ci // Even though \/ is considered a legal escape in JSON, a bare 4257ffe3c632Sopenharmony_ci // slash is also legal, so I see no reason to escape it. 4258ffe3c632Sopenharmony_ci // (I hope I am not misunderstanding something.) 4259ffe3c632Sopenharmony_ci // blep notes: actually escaping \/ may be useful in javascript to avoid </ 4260ffe3c632Sopenharmony_ci // sequence. 4261ffe3c632Sopenharmony_ci // Should add a flag to allow this compatibility mode and prevent this 4262ffe3c632Sopenharmony_ci // sequence from occurring. 4263ffe3c632Sopenharmony_ci default: 4264ffe3c632Sopenharmony_ci if ((isControlCharacter(*c)) || (*c == 0)) { 4265ffe3c632Sopenharmony_ci std::ostringstream oss; 4266ffe3c632Sopenharmony_ci oss << "\\u" << std::hex << std::uppercase << std::setfill('0') 4267ffe3c632Sopenharmony_ci << std::setw(4) << static_cast<int>(*c); 4268ffe3c632Sopenharmony_ci result += oss.str(); 4269ffe3c632Sopenharmony_ci } else { 4270ffe3c632Sopenharmony_ci result += *c; 4271ffe3c632Sopenharmony_ci } 4272ffe3c632Sopenharmony_ci break; 4273ffe3c632Sopenharmony_ci } 4274ffe3c632Sopenharmony_ci } 4275ffe3c632Sopenharmony_ci result += "\""; 4276ffe3c632Sopenharmony_ci return result; 4277ffe3c632Sopenharmony_ci} 4278ffe3c632Sopenharmony_ci 4279ffe3c632Sopenharmony_ci// Class Writer 4280ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 4281ffe3c632Sopenharmony_ciWriter::~Writer() {} 4282ffe3c632Sopenharmony_ci 4283ffe3c632Sopenharmony_ci// Class FastWriter 4284ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 4285ffe3c632Sopenharmony_ci 4286ffe3c632Sopenharmony_ciFastWriter::FastWriter() 4287ffe3c632Sopenharmony_ci : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false), 4288ffe3c632Sopenharmony_ci omitEndingLineFeed_(false) {} 4289ffe3c632Sopenharmony_ci 4290ffe3c632Sopenharmony_civoid FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } 4291ffe3c632Sopenharmony_ci 4292ffe3c632Sopenharmony_civoid FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } 4293ffe3c632Sopenharmony_ci 4294ffe3c632Sopenharmony_civoid FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; } 4295ffe3c632Sopenharmony_ci 4296ffe3c632Sopenharmony_cistd::string FastWriter::write(const Value& root) { 4297ffe3c632Sopenharmony_ci document_ = ""; 4298ffe3c632Sopenharmony_ci writeValue(root); 4299ffe3c632Sopenharmony_ci if (!omitEndingLineFeed_) 4300ffe3c632Sopenharmony_ci document_ += "\n"; 4301ffe3c632Sopenharmony_ci return document_; 4302ffe3c632Sopenharmony_ci} 4303ffe3c632Sopenharmony_ci 4304ffe3c632Sopenharmony_civoid FastWriter::writeValue(const Value& value) { 4305ffe3c632Sopenharmony_ci switch (value.type()) { 4306ffe3c632Sopenharmony_ci case nullValue: 4307ffe3c632Sopenharmony_ci if (!dropNullPlaceholders_) 4308ffe3c632Sopenharmony_ci document_ += "null"; 4309ffe3c632Sopenharmony_ci break; 4310ffe3c632Sopenharmony_ci case intValue: 4311ffe3c632Sopenharmony_ci document_ += valueToString(value.asLargestInt()); 4312ffe3c632Sopenharmony_ci break; 4313ffe3c632Sopenharmony_ci case uintValue: 4314ffe3c632Sopenharmony_ci document_ += valueToString(value.asLargestUInt()); 4315ffe3c632Sopenharmony_ci break; 4316ffe3c632Sopenharmony_ci case realValue: 4317ffe3c632Sopenharmony_ci document_ += valueToString(value.asDouble()); 4318ffe3c632Sopenharmony_ci break; 4319ffe3c632Sopenharmony_ci case stringValue: 4320ffe3c632Sopenharmony_ci { 4321ffe3c632Sopenharmony_ci // Is NULL possible for value.string_? 4322ffe3c632Sopenharmony_ci char const* str; 4323ffe3c632Sopenharmony_ci char const* end; 4324ffe3c632Sopenharmony_ci bool ok = value.getString(&str, &end); 4325ffe3c632Sopenharmony_ci if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str)); 4326ffe3c632Sopenharmony_ci break; 4327ffe3c632Sopenharmony_ci } 4328ffe3c632Sopenharmony_ci case booleanValue: 4329ffe3c632Sopenharmony_ci document_ += valueToString(value.asBool()); 4330ffe3c632Sopenharmony_ci break; 4331ffe3c632Sopenharmony_ci case arrayValue: { 4332ffe3c632Sopenharmony_ci document_ += '['; 4333ffe3c632Sopenharmony_ci int size = value.size(); 4334ffe3c632Sopenharmony_ci for (int index = 0; index < size; ++index) { 4335ffe3c632Sopenharmony_ci if (index > 0) 4336ffe3c632Sopenharmony_ci document_ += ','; 4337ffe3c632Sopenharmony_ci writeValue(value[index]); 4338ffe3c632Sopenharmony_ci } 4339ffe3c632Sopenharmony_ci document_ += ']'; 4340ffe3c632Sopenharmony_ci } break; 4341ffe3c632Sopenharmony_ci case objectValue: { 4342ffe3c632Sopenharmony_ci Value::Members members(value.getMemberNames()); 4343ffe3c632Sopenharmony_ci document_ += '{'; 4344ffe3c632Sopenharmony_ci for (Value::Members::iterator it = members.begin(); it != members.end(); 4345ffe3c632Sopenharmony_ci ++it) { 4346ffe3c632Sopenharmony_ci const std::string& name = *it; 4347ffe3c632Sopenharmony_ci if (it != members.begin()) 4348ffe3c632Sopenharmony_ci document_ += ','; 4349ffe3c632Sopenharmony_ci document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())); 4350ffe3c632Sopenharmony_ci document_ += yamlCompatiblityEnabled_ ? ": " : ":"; 4351ffe3c632Sopenharmony_ci writeValue(value[name]); 4352ffe3c632Sopenharmony_ci } 4353ffe3c632Sopenharmony_ci document_ += '}'; 4354ffe3c632Sopenharmony_ci } break; 4355ffe3c632Sopenharmony_ci } 4356ffe3c632Sopenharmony_ci} 4357ffe3c632Sopenharmony_ci 4358ffe3c632Sopenharmony_ci// Class StyledWriter 4359ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 4360ffe3c632Sopenharmony_ci 4361ffe3c632Sopenharmony_ciStyledWriter::StyledWriter() 4362ffe3c632Sopenharmony_ci : rightMargin_(74), indentSize_(3), addChildValues_() {} 4363ffe3c632Sopenharmony_ci 4364ffe3c632Sopenharmony_cistd::string StyledWriter::write(const Value& root) { 4365ffe3c632Sopenharmony_ci document_ = ""; 4366ffe3c632Sopenharmony_ci addChildValues_ = false; 4367ffe3c632Sopenharmony_ci indentString_ = ""; 4368ffe3c632Sopenharmony_ci writeCommentBeforeValue(root); 4369ffe3c632Sopenharmony_ci writeValue(root); 4370ffe3c632Sopenharmony_ci writeCommentAfterValueOnSameLine(root); 4371ffe3c632Sopenharmony_ci document_ += "\n"; 4372ffe3c632Sopenharmony_ci return document_; 4373ffe3c632Sopenharmony_ci} 4374ffe3c632Sopenharmony_ci 4375ffe3c632Sopenharmony_civoid StyledWriter::writeValue(const Value& value) { 4376ffe3c632Sopenharmony_ci switch (value.type()) { 4377ffe3c632Sopenharmony_ci case nullValue: 4378ffe3c632Sopenharmony_ci pushValue("null"); 4379ffe3c632Sopenharmony_ci break; 4380ffe3c632Sopenharmony_ci case intValue: 4381ffe3c632Sopenharmony_ci pushValue(valueToString(value.asLargestInt())); 4382ffe3c632Sopenharmony_ci break; 4383ffe3c632Sopenharmony_ci case uintValue: 4384ffe3c632Sopenharmony_ci pushValue(valueToString(value.asLargestUInt())); 4385ffe3c632Sopenharmony_ci break; 4386ffe3c632Sopenharmony_ci case realValue: 4387ffe3c632Sopenharmony_ci pushValue(valueToString(value.asDouble())); 4388ffe3c632Sopenharmony_ci break; 4389ffe3c632Sopenharmony_ci case stringValue: 4390ffe3c632Sopenharmony_ci { 4391ffe3c632Sopenharmony_ci // Is NULL possible for value.string_? 4392ffe3c632Sopenharmony_ci char const* str; 4393ffe3c632Sopenharmony_ci char const* end; 4394ffe3c632Sopenharmony_ci bool ok = value.getString(&str, &end); 4395ffe3c632Sopenharmony_ci if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str))); 4396ffe3c632Sopenharmony_ci else pushValue(""); 4397ffe3c632Sopenharmony_ci break; 4398ffe3c632Sopenharmony_ci } 4399ffe3c632Sopenharmony_ci case booleanValue: 4400ffe3c632Sopenharmony_ci pushValue(valueToString(value.asBool())); 4401ffe3c632Sopenharmony_ci break; 4402ffe3c632Sopenharmony_ci case arrayValue: 4403ffe3c632Sopenharmony_ci writeArrayValue(value); 4404ffe3c632Sopenharmony_ci break; 4405ffe3c632Sopenharmony_ci case objectValue: { 4406ffe3c632Sopenharmony_ci Value::Members members(value.getMemberNames()); 4407ffe3c632Sopenharmony_ci if (members.empty()) 4408ffe3c632Sopenharmony_ci pushValue("{}"); 4409ffe3c632Sopenharmony_ci else { 4410ffe3c632Sopenharmony_ci writeWithIndent("{"); 4411ffe3c632Sopenharmony_ci indent(); 4412ffe3c632Sopenharmony_ci Value::Members::iterator it = members.begin(); 4413ffe3c632Sopenharmony_ci for (;;) { 4414ffe3c632Sopenharmony_ci const std::string& name = *it; 4415ffe3c632Sopenharmony_ci const Value& childValue = value[name]; 4416ffe3c632Sopenharmony_ci writeCommentBeforeValue(childValue); 4417ffe3c632Sopenharmony_ci writeWithIndent(valueToQuotedString(name.c_str())); 4418ffe3c632Sopenharmony_ci document_ += " : "; 4419ffe3c632Sopenharmony_ci writeValue(childValue); 4420ffe3c632Sopenharmony_ci if (++it == members.end()) { 4421ffe3c632Sopenharmony_ci writeCommentAfterValueOnSameLine(childValue); 4422ffe3c632Sopenharmony_ci break; 4423ffe3c632Sopenharmony_ci } 4424ffe3c632Sopenharmony_ci document_ += ','; 4425ffe3c632Sopenharmony_ci writeCommentAfterValueOnSameLine(childValue); 4426ffe3c632Sopenharmony_ci } 4427ffe3c632Sopenharmony_ci unindent(); 4428ffe3c632Sopenharmony_ci writeWithIndent("}"); 4429ffe3c632Sopenharmony_ci } 4430ffe3c632Sopenharmony_ci } break; 4431ffe3c632Sopenharmony_ci } 4432ffe3c632Sopenharmony_ci} 4433ffe3c632Sopenharmony_ci 4434ffe3c632Sopenharmony_civoid StyledWriter::writeArrayValue(const Value& value) { 4435ffe3c632Sopenharmony_ci unsigned size = value.size(); 4436ffe3c632Sopenharmony_ci if (size == 0) 4437ffe3c632Sopenharmony_ci pushValue("[]"); 4438ffe3c632Sopenharmony_ci else { 4439ffe3c632Sopenharmony_ci bool isArrayMultiLine = isMultineArray(value); 4440ffe3c632Sopenharmony_ci if (isArrayMultiLine) { 4441ffe3c632Sopenharmony_ci writeWithIndent("["); 4442ffe3c632Sopenharmony_ci indent(); 4443ffe3c632Sopenharmony_ci bool hasChildValue = !childValues_.empty(); 4444ffe3c632Sopenharmony_ci unsigned index = 0; 4445ffe3c632Sopenharmony_ci for (;;) { 4446ffe3c632Sopenharmony_ci const Value& childValue = value[index]; 4447ffe3c632Sopenharmony_ci writeCommentBeforeValue(childValue); 4448ffe3c632Sopenharmony_ci if (hasChildValue) 4449ffe3c632Sopenharmony_ci writeWithIndent(childValues_[index]); 4450ffe3c632Sopenharmony_ci else { 4451ffe3c632Sopenharmony_ci writeIndent(); 4452ffe3c632Sopenharmony_ci writeValue(childValue); 4453ffe3c632Sopenharmony_ci } 4454ffe3c632Sopenharmony_ci if (++index == size) { 4455ffe3c632Sopenharmony_ci writeCommentAfterValueOnSameLine(childValue); 4456ffe3c632Sopenharmony_ci break; 4457ffe3c632Sopenharmony_ci } 4458ffe3c632Sopenharmony_ci document_ += ','; 4459ffe3c632Sopenharmony_ci writeCommentAfterValueOnSameLine(childValue); 4460ffe3c632Sopenharmony_ci } 4461ffe3c632Sopenharmony_ci unindent(); 4462ffe3c632Sopenharmony_ci writeWithIndent("]"); 4463ffe3c632Sopenharmony_ci } else // output on a single line 4464ffe3c632Sopenharmony_ci { 4465ffe3c632Sopenharmony_ci assert(childValues_.size() == size); 4466ffe3c632Sopenharmony_ci document_ += "[ "; 4467ffe3c632Sopenharmony_ci for (unsigned index = 0; index < size; ++index) { 4468ffe3c632Sopenharmony_ci if (index > 0) 4469ffe3c632Sopenharmony_ci document_ += ", "; 4470ffe3c632Sopenharmony_ci document_ += childValues_[index]; 4471ffe3c632Sopenharmony_ci } 4472ffe3c632Sopenharmony_ci document_ += " ]"; 4473ffe3c632Sopenharmony_ci } 4474ffe3c632Sopenharmony_ci } 4475ffe3c632Sopenharmony_ci} 4476ffe3c632Sopenharmony_ci 4477ffe3c632Sopenharmony_cibool StyledWriter::isMultineArray(const Value& value) { 4478ffe3c632Sopenharmony_ci int size = value.size(); 4479ffe3c632Sopenharmony_ci bool isMultiLine = size * 3 >= rightMargin_; 4480ffe3c632Sopenharmony_ci childValues_.clear(); 4481ffe3c632Sopenharmony_ci for (int index = 0; index < size && !isMultiLine; ++index) { 4482ffe3c632Sopenharmony_ci const Value& childValue = value[index]; 4483ffe3c632Sopenharmony_ci isMultiLine = ((childValue.isArray() || childValue.isObject()) && 4484ffe3c632Sopenharmony_ci childValue.size() > 0); 4485ffe3c632Sopenharmony_ci } 4486ffe3c632Sopenharmony_ci if (!isMultiLine) // check if line length > max line length 4487ffe3c632Sopenharmony_ci { 4488ffe3c632Sopenharmony_ci childValues_.reserve(size); 4489ffe3c632Sopenharmony_ci addChildValues_ = true; 4490ffe3c632Sopenharmony_ci int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' 4491ffe3c632Sopenharmony_ci for (int index = 0; index < size; ++index) { 4492ffe3c632Sopenharmony_ci if (hasCommentForValue(value[index])) { 4493ffe3c632Sopenharmony_ci isMultiLine = true; 4494ffe3c632Sopenharmony_ci } 4495ffe3c632Sopenharmony_ci writeValue(value[index]); 4496ffe3c632Sopenharmony_ci lineLength += int(childValues_[index].length()); 4497ffe3c632Sopenharmony_ci } 4498ffe3c632Sopenharmony_ci addChildValues_ = false; 4499ffe3c632Sopenharmony_ci isMultiLine = isMultiLine || lineLength >= rightMargin_; 4500ffe3c632Sopenharmony_ci } 4501ffe3c632Sopenharmony_ci return isMultiLine; 4502ffe3c632Sopenharmony_ci} 4503ffe3c632Sopenharmony_ci 4504ffe3c632Sopenharmony_civoid StyledWriter::pushValue(const std::string& value) { 4505ffe3c632Sopenharmony_ci if (addChildValues_) 4506ffe3c632Sopenharmony_ci childValues_.push_back(value); 4507ffe3c632Sopenharmony_ci else 4508ffe3c632Sopenharmony_ci document_ += value; 4509ffe3c632Sopenharmony_ci} 4510ffe3c632Sopenharmony_ci 4511ffe3c632Sopenharmony_civoid StyledWriter::writeIndent() { 4512ffe3c632Sopenharmony_ci if (!document_.empty()) { 4513ffe3c632Sopenharmony_ci char last = document_[document_.length() - 1]; 4514ffe3c632Sopenharmony_ci if (last == ' ') // already indented 4515ffe3c632Sopenharmony_ci return; 4516ffe3c632Sopenharmony_ci if (last != '\n') // Comments may add new-line 4517ffe3c632Sopenharmony_ci document_ += '\n'; 4518ffe3c632Sopenharmony_ci } 4519ffe3c632Sopenharmony_ci document_ += indentString_; 4520ffe3c632Sopenharmony_ci} 4521ffe3c632Sopenharmony_ci 4522ffe3c632Sopenharmony_civoid StyledWriter::writeWithIndent(const std::string& value) { 4523ffe3c632Sopenharmony_ci writeIndent(); 4524ffe3c632Sopenharmony_ci document_ += value; 4525ffe3c632Sopenharmony_ci} 4526ffe3c632Sopenharmony_ci 4527ffe3c632Sopenharmony_civoid StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); } 4528ffe3c632Sopenharmony_ci 4529ffe3c632Sopenharmony_civoid StyledWriter::unindent() { 4530ffe3c632Sopenharmony_ci assert(int(indentString_.size()) >= indentSize_); 4531ffe3c632Sopenharmony_ci indentString_.resize(indentString_.size() - indentSize_); 4532ffe3c632Sopenharmony_ci} 4533ffe3c632Sopenharmony_ci 4534ffe3c632Sopenharmony_civoid StyledWriter::writeCommentBeforeValue(const Value& root) { 4535ffe3c632Sopenharmony_ci if (!root.hasComment(commentBefore)) 4536ffe3c632Sopenharmony_ci return; 4537ffe3c632Sopenharmony_ci 4538ffe3c632Sopenharmony_ci document_ += "\n"; 4539ffe3c632Sopenharmony_ci writeIndent(); 4540ffe3c632Sopenharmony_ci const std::string& comment = root.getComment(commentBefore); 4541ffe3c632Sopenharmony_ci std::string::const_iterator iter = comment.begin(); 4542ffe3c632Sopenharmony_ci while (iter != comment.end()) { 4543ffe3c632Sopenharmony_ci document_ += *iter; 4544ffe3c632Sopenharmony_ci if (*iter == '\n' && 4545ffe3c632Sopenharmony_ci (iter != comment.end() && *(iter + 1) == '/')) 4546ffe3c632Sopenharmony_ci writeIndent(); 4547ffe3c632Sopenharmony_ci ++iter; 4548ffe3c632Sopenharmony_ci } 4549ffe3c632Sopenharmony_ci 4550ffe3c632Sopenharmony_ci // Comments are stripped of trailing newlines, so add one here 4551ffe3c632Sopenharmony_ci document_ += "\n"; 4552ffe3c632Sopenharmony_ci} 4553ffe3c632Sopenharmony_ci 4554ffe3c632Sopenharmony_civoid StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { 4555ffe3c632Sopenharmony_ci if (root.hasComment(commentAfterOnSameLine)) 4556ffe3c632Sopenharmony_ci document_ += " " + root.getComment(commentAfterOnSameLine); 4557ffe3c632Sopenharmony_ci 4558ffe3c632Sopenharmony_ci if (root.hasComment(commentAfter)) { 4559ffe3c632Sopenharmony_ci document_ += "\n"; 4560ffe3c632Sopenharmony_ci document_ += root.getComment(commentAfter); 4561ffe3c632Sopenharmony_ci document_ += "\n"; 4562ffe3c632Sopenharmony_ci } 4563ffe3c632Sopenharmony_ci} 4564ffe3c632Sopenharmony_ci 4565ffe3c632Sopenharmony_cibool StyledWriter::hasCommentForValue(const Value& value) { 4566ffe3c632Sopenharmony_ci return value.hasComment(commentBefore) || 4567ffe3c632Sopenharmony_ci value.hasComment(commentAfterOnSameLine) || 4568ffe3c632Sopenharmony_ci value.hasComment(commentAfter); 4569ffe3c632Sopenharmony_ci} 4570ffe3c632Sopenharmony_ci 4571ffe3c632Sopenharmony_ci// Class StyledStreamWriter 4572ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////// 4573ffe3c632Sopenharmony_ci 4574ffe3c632Sopenharmony_ciStyledStreamWriter::StyledStreamWriter(std::string indentation) 4575ffe3c632Sopenharmony_ci : document_(NULL), rightMargin_(74), indentation_(indentation), 4576ffe3c632Sopenharmony_ci addChildValues_() {} 4577ffe3c632Sopenharmony_ci 4578ffe3c632Sopenharmony_civoid StyledStreamWriter::write(std::ostream& out, const Value& root) { 4579ffe3c632Sopenharmony_ci document_ = &out; 4580ffe3c632Sopenharmony_ci addChildValues_ = false; 4581ffe3c632Sopenharmony_ci indentString_ = ""; 4582ffe3c632Sopenharmony_ci indented_ = true; 4583ffe3c632Sopenharmony_ci writeCommentBeforeValue(root); 4584ffe3c632Sopenharmony_ci if (!indented_) writeIndent(); 4585ffe3c632Sopenharmony_ci indented_ = true; 4586ffe3c632Sopenharmony_ci writeValue(root); 4587ffe3c632Sopenharmony_ci writeCommentAfterValueOnSameLine(root); 4588ffe3c632Sopenharmony_ci *document_ << "\n"; 4589ffe3c632Sopenharmony_ci document_ = NULL; // Forget the stream, for safety. 4590ffe3c632Sopenharmony_ci} 4591ffe3c632Sopenharmony_ci 4592ffe3c632Sopenharmony_civoid StyledStreamWriter::writeValue(const Value& value) { 4593ffe3c632Sopenharmony_ci switch (value.type()) { 4594ffe3c632Sopenharmony_ci case nullValue: 4595ffe3c632Sopenharmony_ci pushValue("null"); 4596ffe3c632Sopenharmony_ci break; 4597ffe3c632Sopenharmony_ci case intValue: 4598ffe3c632Sopenharmony_ci pushValue(valueToString(value.asLargestInt())); 4599ffe3c632Sopenharmony_ci break; 4600ffe3c632Sopenharmony_ci case uintValue: 4601ffe3c632Sopenharmony_ci pushValue(valueToString(value.asLargestUInt())); 4602ffe3c632Sopenharmony_ci break; 4603ffe3c632Sopenharmony_ci case realValue: 4604ffe3c632Sopenharmony_ci pushValue(valueToString(value.asDouble())); 4605ffe3c632Sopenharmony_ci break; 4606ffe3c632Sopenharmony_ci case stringValue: 4607ffe3c632Sopenharmony_ci { 4608ffe3c632Sopenharmony_ci // Is NULL possible for value.string_? 4609ffe3c632Sopenharmony_ci char const* str; 4610ffe3c632Sopenharmony_ci char const* end; 4611ffe3c632Sopenharmony_ci bool ok = value.getString(&str, &end); 4612ffe3c632Sopenharmony_ci if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str))); 4613ffe3c632Sopenharmony_ci else pushValue(""); 4614ffe3c632Sopenharmony_ci break; 4615ffe3c632Sopenharmony_ci } 4616ffe3c632Sopenharmony_ci case booleanValue: 4617ffe3c632Sopenharmony_ci pushValue(valueToString(value.asBool())); 4618ffe3c632Sopenharmony_ci break; 4619ffe3c632Sopenharmony_ci case arrayValue: 4620ffe3c632Sopenharmony_ci writeArrayValue(value); 4621ffe3c632Sopenharmony_ci break; 4622ffe3c632Sopenharmony_ci case objectValue: { 4623ffe3c632Sopenharmony_ci Value::Members members(value.getMemberNames()); 4624ffe3c632Sopenharmony_ci if (members.empty()) 4625ffe3c632Sopenharmony_ci pushValue("{}"); 4626ffe3c632Sopenharmony_ci else { 4627ffe3c632Sopenharmony_ci writeWithIndent("{"); 4628ffe3c632Sopenharmony_ci indent(); 4629ffe3c632Sopenharmony_ci Value::Members::iterator it = members.begin(); 4630ffe3c632Sopenharmony_ci for (;;) { 4631ffe3c632Sopenharmony_ci const std::string& name = *it; 4632ffe3c632Sopenharmony_ci const Value& childValue = value[name]; 4633ffe3c632Sopenharmony_ci writeCommentBeforeValue(childValue); 4634ffe3c632Sopenharmony_ci writeWithIndent(valueToQuotedString(name.c_str())); 4635ffe3c632Sopenharmony_ci *document_ << " : "; 4636ffe3c632Sopenharmony_ci writeValue(childValue); 4637ffe3c632Sopenharmony_ci if (++it == members.end()) { 4638ffe3c632Sopenharmony_ci writeCommentAfterValueOnSameLine(childValue); 4639ffe3c632Sopenharmony_ci break; 4640ffe3c632Sopenharmony_ci } 4641ffe3c632Sopenharmony_ci *document_ << ","; 4642ffe3c632Sopenharmony_ci writeCommentAfterValueOnSameLine(childValue); 4643ffe3c632Sopenharmony_ci } 4644ffe3c632Sopenharmony_ci unindent(); 4645ffe3c632Sopenharmony_ci writeWithIndent("}"); 4646ffe3c632Sopenharmony_ci } 4647ffe3c632Sopenharmony_ci } break; 4648ffe3c632Sopenharmony_ci } 4649ffe3c632Sopenharmony_ci} 4650ffe3c632Sopenharmony_ci 4651ffe3c632Sopenharmony_civoid StyledStreamWriter::writeArrayValue(const Value& value) { 4652ffe3c632Sopenharmony_ci unsigned size = value.size(); 4653ffe3c632Sopenharmony_ci if (size == 0) 4654ffe3c632Sopenharmony_ci pushValue("[]"); 4655ffe3c632Sopenharmony_ci else { 4656ffe3c632Sopenharmony_ci bool isArrayMultiLine = isMultineArray(value); 4657ffe3c632Sopenharmony_ci if (isArrayMultiLine) { 4658ffe3c632Sopenharmony_ci writeWithIndent("["); 4659ffe3c632Sopenharmony_ci indent(); 4660ffe3c632Sopenharmony_ci bool hasChildValue = !childValues_.empty(); 4661ffe3c632Sopenharmony_ci unsigned index = 0; 4662ffe3c632Sopenharmony_ci for (;;) { 4663ffe3c632Sopenharmony_ci const Value& childValue = value[index]; 4664ffe3c632Sopenharmony_ci writeCommentBeforeValue(childValue); 4665ffe3c632Sopenharmony_ci if (hasChildValue) 4666ffe3c632Sopenharmony_ci writeWithIndent(childValues_[index]); 4667ffe3c632Sopenharmony_ci else { 4668ffe3c632Sopenharmony_ci if (!indented_) writeIndent(); 4669ffe3c632Sopenharmony_ci indented_ = true; 4670ffe3c632Sopenharmony_ci writeValue(childValue); 4671ffe3c632Sopenharmony_ci indented_ = false; 4672ffe3c632Sopenharmony_ci } 4673ffe3c632Sopenharmony_ci if (++index == size) { 4674ffe3c632Sopenharmony_ci writeCommentAfterValueOnSameLine(childValue); 4675ffe3c632Sopenharmony_ci break; 4676ffe3c632Sopenharmony_ci } 4677ffe3c632Sopenharmony_ci *document_ << ","; 4678ffe3c632Sopenharmony_ci writeCommentAfterValueOnSameLine(childValue); 4679ffe3c632Sopenharmony_ci } 4680ffe3c632Sopenharmony_ci unindent(); 4681ffe3c632Sopenharmony_ci writeWithIndent("]"); 4682ffe3c632Sopenharmony_ci } else // output on a single line 4683ffe3c632Sopenharmony_ci { 4684ffe3c632Sopenharmony_ci assert(childValues_.size() == size); 4685ffe3c632Sopenharmony_ci *document_ << "[ "; 4686ffe3c632Sopenharmony_ci for (unsigned index = 0; index < size; ++index) { 4687ffe3c632Sopenharmony_ci if (index > 0) 4688ffe3c632Sopenharmony_ci *document_ << ", "; 4689ffe3c632Sopenharmony_ci *document_ << childValues_[index]; 4690ffe3c632Sopenharmony_ci } 4691ffe3c632Sopenharmony_ci *document_ << " ]"; 4692ffe3c632Sopenharmony_ci } 4693ffe3c632Sopenharmony_ci } 4694ffe3c632Sopenharmony_ci} 4695ffe3c632Sopenharmony_ci 4696ffe3c632Sopenharmony_cibool StyledStreamWriter::isMultineArray(const Value& value) { 4697ffe3c632Sopenharmony_ci int size = value.size(); 4698ffe3c632Sopenharmony_ci bool isMultiLine = size * 3 >= rightMargin_; 4699ffe3c632Sopenharmony_ci childValues_.clear(); 4700ffe3c632Sopenharmony_ci for (int index = 0; index < size && !isMultiLine; ++index) { 4701ffe3c632Sopenharmony_ci const Value& childValue = value[index]; 4702ffe3c632Sopenharmony_ci isMultiLine = ((childValue.isArray() || childValue.isObject()) && 4703ffe3c632Sopenharmony_ci childValue.size() > 0); 4704ffe3c632Sopenharmony_ci } 4705ffe3c632Sopenharmony_ci if (!isMultiLine) // check if line length > max line length 4706ffe3c632Sopenharmony_ci { 4707ffe3c632Sopenharmony_ci childValues_.reserve(size); 4708ffe3c632Sopenharmony_ci addChildValues_ = true; 4709ffe3c632Sopenharmony_ci int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' 4710ffe3c632Sopenharmony_ci for (int index = 0; index < size; ++index) { 4711ffe3c632Sopenharmony_ci if (hasCommentForValue(value[index])) { 4712ffe3c632Sopenharmony_ci isMultiLine = true; 4713ffe3c632Sopenharmony_ci } 4714ffe3c632Sopenharmony_ci writeValue(value[index]); 4715ffe3c632Sopenharmony_ci lineLength += int(childValues_[index].length()); 4716ffe3c632Sopenharmony_ci } 4717ffe3c632Sopenharmony_ci addChildValues_ = false; 4718ffe3c632Sopenharmony_ci isMultiLine = isMultiLine || lineLength >= rightMargin_; 4719ffe3c632Sopenharmony_ci } 4720ffe3c632Sopenharmony_ci return isMultiLine; 4721ffe3c632Sopenharmony_ci} 4722ffe3c632Sopenharmony_ci 4723ffe3c632Sopenharmony_civoid StyledStreamWriter::pushValue(const std::string& value) { 4724ffe3c632Sopenharmony_ci if (addChildValues_) 4725ffe3c632Sopenharmony_ci childValues_.push_back(value); 4726ffe3c632Sopenharmony_ci else 4727ffe3c632Sopenharmony_ci *document_ << value; 4728ffe3c632Sopenharmony_ci} 4729ffe3c632Sopenharmony_ci 4730ffe3c632Sopenharmony_civoid StyledStreamWriter::writeIndent() { 4731ffe3c632Sopenharmony_ci // blep intended this to look at the so-far-written string 4732ffe3c632Sopenharmony_ci // to determine whether we are already indented, but 4733ffe3c632Sopenharmony_ci // with a stream we cannot do that. So we rely on some saved state. 4734ffe3c632Sopenharmony_ci // The caller checks indented_. 4735ffe3c632Sopenharmony_ci *document_ << '\n' << indentString_; 4736ffe3c632Sopenharmony_ci} 4737ffe3c632Sopenharmony_ci 4738ffe3c632Sopenharmony_civoid StyledStreamWriter::writeWithIndent(const std::string& value) { 4739ffe3c632Sopenharmony_ci if (!indented_) writeIndent(); 4740ffe3c632Sopenharmony_ci *document_ << value; 4741ffe3c632Sopenharmony_ci indented_ = false; 4742ffe3c632Sopenharmony_ci} 4743ffe3c632Sopenharmony_ci 4744ffe3c632Sopenharmony_civoid StyledStreamWriter::indent() { indentString_ += indentation_; } 4745ffe3c632Sopenharmony_ci 4746ffe3c632Sopenharmony_civoid StyledStreamWriter::unindent() { 4747ffe3c632Sopenharmony_ci assert(indentString_.size() >= indentation_.size()); 4748ffe3c632Sopenharmony_ci indentString_.resize(indentString_.size() - indentation_.size()); 4749ffe3c632Sopenharmony_ci} 4750ffe3c632Sopenharmony_ci 4751ffe3c632Sopenharmony_civoid StyledStreamWriter::writeCommentBeforeValue(const Value& root) { 4752ffe3c632Sopenharmony_ci if (!root.hasComment(commentBefore)) 4753ffe3c632Sopenharmony_ci return; 4754ffe3c632Sopenharmony_ci 4755ffe3c632Sopenharmony_ci if (!indented_) writeIndent(); 4756ffe3c632Sopenharmony_ci const std::string& comment = root.getComment(commentBefore); 4757ffe3c632Sopenharmony_ci std::string::const_iterator iter = comment.begin(); 4758ffe3c632Sopenharmony_ci while (iter != comment.end()) { 4759ffe3c632Sopenharmony_ci *document_ << *iter; 4760ffe3c632Sopenharmony_ci if (*iter == '\n' && 4761ffe3c632Sopenharmony_ci (iter != comment.end() && *(iter + 1) == '/')) 4762ffe3c632Sopenharmony_ci // writeIndent(); // would include newline 4763ffe3c632Sopenharmony_ci *document_ << indentString_; 4764ffe3c632Sopenharmony_ci ++iter; 4765ffe3c632Sopenharmony_ci } 4766ffe3c632Sopenharmony_ci indented_ = false; 4767ffe3c632Sopenharmony_ci} 4768ffe3c632Sopenharmony_ci 4769ffe3c632Sopenharmony_civoid StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) { 4770ffe3c632Sopenharmony_ci if (root.hasComment(commentAfterOnSameLine)) 4771ffe3c632Sopenharmony_ci *document_ << ' ' << root.getComment(commentAfterOnSameLine); 4772ffe3c632Sopenharmony_ci 4773ffe3c632Sopenharmony_ci if (root.hasComment(commentAfter)) { 4774ffe3c632Sopenharmony_ci writeIndent(); 4775ffe3c632Sopenharmony_ci *document_ << root.getComment(commentAfter); 4776ffe3c632Sopenharmony_ci } 4777ffe3c632Sopenharmony_ci indented_ = false; 4778ffe3c632Sopenharmony_ci} 4779ffe3c632Sopenharmony_ci 4780ffe3c632Sopenharmony_cibool StyledStreamWriter::hasCommentForValue(const Value& value) { 4781ffe3c632Sopenharmony_ci return value.hasComment(commentBefore) || 4782ffe3c632Sopenharmony_ci value.hasComment(commentAfterOnSameLine) || 4783ffe3c632Sopenharmony_ci value.hasComment(commentAfter); 4784ffe3c632Sopenharmony_ci} 4785ffe3c632Sopenharmony_ci 4786ffe3c632Sopenharmony_ci////////////////////////// 4787ffe3c632Sopenharmony_ci// BuiltStyledStreamWriter 4788ffe3c632Sopenharmony_ci 4789ffe3c632Sopenharmony_ci/// Scoped enums are not available until C++11. 4790ffe3c632Sopenharmony_cistruct CommentStyle { 4791ffe3c632Sopenharmony_ci /// Decide whether to write comments. 4792ffe3c632Sopenharmony_ci enum Enum { 4793ffe3c632Sopenharmony_ci None, ///< Drop all comments. 4794ffe3c632Sopenharmony_ci Most, ///< Recover odd behavior of previous versions (not implemented yet). 4795ffe3c632Sopenharmony_ci All ///< Keep all comments. 4796ffe3c632Sopenharmony_ci }; 4797ffe3c632Sopenharmony_ci}; 4798ffe3c632Sopenharmony_ci 4799ffe3c632Sopenharmony_cistruct BuiltStyledStreamWriter : public StreamWriter 4800ffe3c632Sopenharmony_ci{ 4801ffe3c632Sopenharmony_ci BuiltStyledStreamWriter( 4802ffe3c632Sopenharmony_ci std::string const& indentation, 4803ffe3c632Sopenharmony_ci CommentStyle::Enum cs, 4804ffe3c632Sopenharmony_ci std::string const& colonSymbol, 4805ffe3c632Sopenharmony_ci std::string const& nullSymbol, 4806ffe3c632Sopenharmony_ci std::string const& endingLineFeedSymbol, 4807ffe3c632Sopenharmony_ci bool useSpecialFloats, 4808ffe3c632Sopenharmony_ci unsigned int precision); 4809ffe3c632Sopenharmony_ci int write(Value const& root, std::ostream* sout) override; 4810ffe3c632Sopenharmony_ciprivate: 4811ffe3c632Sopenharmony_ci void writeValue(Value const& value); 4812ffe3c632Sopenharmony_ci void writeArrayValue(Value const& value); 4813ffe3c632Sopenharmony_ci bool isMultineArray(Value const& value); 4814ffe3c632Sopenharmony_ci void pushValue(std::string const& value); 4815ffe3c632Sopenharmony_ci void writeIndent(); 4816ffe3c632Sopenharmony_ci void writeWithIndent(std::string const& value); 4817ffe3c632Sopenharmony_ci void indent(); 4818ffe3c632Sopenharmony_ci void unindent(); 4819ffe3c632Sopenharmony_ci void writeCommentBeforeValue(Value const& root); 4820ffe3c632Sopenharmony_ci void writeCommentAfterValueOnSameLine(Value const& root); 4821ffe3c632Sopenharmony_ci static bool hasCommentForValue(const Value& value); 4822ffe3c632Sopenharmony_ci 4823ffe3c632Sopenharmony_ci typedef std::vector<std::string> ChildValues; 4824ffe3c632Sopenharmony_ci 4825ffe3c632Sopenharmony_ci ChildValues childValues_; 4826ffe3c632Sopenharmony_ci std::string indentString_; 4827ffe3c632Sopenharmony_ci int rightMargin_; 4828ffe3c632Sopenharmony_ci std::string indentation_; 4829ffe3c632Sopenharmony_ci CommentStyle::Enum cs_; 4830ffe3c632Sopenharmony_ci std::string colonSymbol_; 4831ffe3c632Sopenharmony_ci std::string nullSymbol_; 4832ffe3c632Sopenharmony_ci std::string endingLineFeedSymbol_; 4833ffe3c632Sopenharmony_ci bool addChildValues_ : 1; 4834ffe3c632Sopenharmony_ci bool indented_ : 1; 4835ffe3c632Sopenharmony_ci bool useSpecialFloats_ : 1; 4836ffe3c632Sopenharmony_ci unsigned int precision_; 4837ffe3c632Sopenharmony_ci}; 4838ffe3c632Sopenharmony_ciBuiltStyledStreamWriter::BuiltStyledStreamWriter( 4839ffe3c632Sopenharmony_ci std::string const& indentation, 4840ffe3c632Sopenharmony_ci CommentStyle::Enum cs, 4841ffe3c632Sopenharmony_ci std::string const& colonSymbol, 4842ffe3c632Sopenharmony_ci std::string const& nullSymbol, 4843ffe3c632Sopenharmony_ci std::string const& endingLineFeedSymbol, 4844ffe3c632Sopenharmony_ci bool useSpecialFloats, 4845ffe3c632Sopenharmony_ci unsigned int precision) 4846ffe3c632Sopenharmony_ci : rightMargin_(74) 4847ffe3c632Sopenharmony_ci , indentation_(indentation) 4848ffe3c632Sopenharmony_ci , cs_(cs) 4849ffe3c632Sopenharmony_ci , colonSymbol_(colonSymbol) 4850ffe3c632Sopenharmony_ci , nullSymbol_(nullSymbol) 4851ffe3c632Sopenharmony_ci , endingLineFeedSymbol_(endingLineFeedSymbol) 4852ffe3c632Sopenharmony_ci , addChildValues_(false) 4853ffe3c632Sopenharmony_ci , indented_(false) 4854ffe3c632Sopenharmony_ci , useSpecialFloats_(useSpecialFloats) 4855ffe3c632Sopenharmony_ci , precision_(precision) 4856ffe3c632Sopenharmony_ci{ 4857ffe3c632Sopenharmony_ci} 4858ffe3c632Sopenharmony_ciint BuiltStyledStreamWriter::write(Value const& root, std::ostream* sout) 4859ffe3c632Sopenharmony_ci{ 4860ffe3c632Sopenharmony_ci sout_ = sout; 4861ffe3c632Sopenharmony_ci addChildValues_ = false; 4862ffe3c632Sopenharmony_ci indented_ = true; 4863ffe3c632Sopenharmony_ci indentString_ = ""; 4864ffe3c632Sopenharmony_ci writeCommentBeforeValue(root); 4865ffe3c632Sopenharmony_ci if (!indented_) writeIndent(); 4866ffe3c632Sopenharmony_ci indented_ = true; 4867ffe3c632Sopenharmony_ci writeValue(root); 4868ffe3c632Sopenharmony_ci writeCommentAfterValueOnSameLine(root); 4869ffe3c632Sopenharmony_ci *sout_ << endingLineFeedSymbol_; 4870ffe3c632Sopenharmony_ci sout_ = NULL; 4871ffe3c632Sopenharmony_ci return 0; 4872ffe3c632Sopenharmony_ci} 4873ffe3c632Sopenharmony_civoid BuiltStyledStreamWriter::writeValue(Value const& value) { 4874ffe3c632Sopenharmony_ci switch (value.type()) { 4875ffe3c632Sopenharmony_ci case nullValue: 4876ffe3c632Sopenharmony_ci pushValue(nullSymbol_); 4877ffe3c632Sopenharmony_ci break; 4878ffe3c632Sopenharmony_ci case intValue: 4879ffe3c632Sopenharmony_ci pushValue(valueToString(value.asLargestInt())); 4880ffe3c632Sopenharmony_ci break; 4881ffe3c632Sopenharmony_ci case uintValue: 4882ffe3c632Sopenharmony_ci pushValue(valueToString(value.asLargestUInt())); 4883ffe3c632Sopenharmony_ci break; 4884ffe3c632Sopenharmony_ci case realValue: 4885ffe3c632Sopenharmony_ci pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_)); 4886ffe3c632Sopenharmony_ci break; 4887ffe3c632Sopenharmony_ci case stringValue: 4888ffe3c632Sopenharmony_ci { 4889ffe3c632Sopenharmony_ci // Is NULL is possible for value.string_? 4890ffe3c632Sopenharmony_ci char const* str; 4891ffe3c632Sopenharmony_ci char const* end; 4892ffe3c632Sopenharmony_ci bool ok = value.getString(&str, &end); 4893ffe3c632Sopenharmony_ci if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str))); 4894ffe3c632Sopenharmony_ci else pushValue(""); 4895ffe3c632Sopenharmony_ci break; 4896ffe3c632Sopenharmony_ci } 4897ffe3c632Sopenharmony_ci case booleanValue: 4898ffe3c632Sopenharmony_ci pushValue(valueToString(value.asBool())); 4899ffe3c632Sopenharmony_ci break; 4900ffe3c632Sopenharmony_ci case arrayValue: 4901ffe3c632Sopenharmony_ci writeArrayValue(value); 4902ffe3c632Sopenharmony_ci break; 4903ffe3c632Sopenharmony_ci case objectValue: { 4904ffe3c632Sopenharmony_ci Value::Members members(value.getMemberNames()); 4905ffe3c632Sopenharmony_ci if (members.empty()) 4906ffe3c632Sopenharmony_ci pushValue("{}"); 4907ffe3c632Sopenharmony_ci else { 4908ffe3c632Sopenharmony_ci writeWithIndent("{"); 4909ffe3c632Sopenharmony_ci indent(); 4910ffe3c632Sopenharmony_ci Value::Members::iterator it = members.begin(); 4911ffe3c632Sopenharmony_ci for (;;) { 4912ffe3c632Sopenharmony_ci std::string const& name = *it; 4913ffe3c632Sopenharmony_ci Value const& childValue = value[name]; 4914ffe3c632Sopenharmony_ci writeCommentBeforeValue(childValue); 4915ffe3c632Sopenharmony_ci writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()))); 4916ffe3c632Sopenharmony_ci *sout_ << colonSymbol_; 4917ffe3c632Sopenharmony_ci writeValue(childValue); 4918ffe3c632Sopenharmony_ci if (++it == members.end()) { 4919ffe3c632Sopenharmony_ci writeCommentAfterValueOnSameLine(childValue); 4920ffe3c632Sopenharmony_ci break; 4921ffe3c632Sopenharmony_ci } 4922ffe3c632Sopenharmony_ci *sout_ << ","; 4923ffe3c632Sopenharmony_ci writeCommentAfterValueOnSameLine(childValue); 4924ffe3c632Sopenharmony_ci } 4925ffe3c632Sopenharmony_ci unindent(); 4926ffe3c632Sopenharmony_ci writeWithIndent("}"); 4927ffe3c632Sopenharmony_ci } 4928ffe3c632Sopenharmony_ci } break; 4929ffe3c632Sopenharmony_ci } 4930ffe3c632Sopenharmony_ci} 4931ffe3c632Sopenharmony_ci 4932ffe3c632Sopenharmony_civoid BuiltStyledStreamWriter::writeArrayValue(Value const& value) { 4933ffe3c632Sopenharmony_ci unsigned size = value.size(); 4934ffe3c632Sopenharmony_ci if (size == 0) 4935ffe3c632Sopenharmony_ci pushValue("[]"); 4936ffe3c632Sopenharmony_ci else { 4937ffe3c632Sopenharmony_ci bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value); 4938ffe3c632Sopenharmony_ci if (isMultiLine) { 4939ffe3c632Sopenharmony_ci writeWithIndent("["); 4940ffe3c632Sopenharmony_ci indent(); 4941ffe3c632Sopenharmony_ci bool hasChildValue = !childValues_.empty(); 4942ffe3c632Sopenharmony_ci unsigned index = 0; 4943ffe3c632Sopenharmony_ci for (;;) { 4944ffe3c632Sopenharmony_ci Value const& childValue = value[index]; 4945ffe3c632Sopenharmony_ci writeCommentBeforeValue(childValue); 4946ffe3c632Sopenharmony_ci if (hasChildValue) 4947ffe3c632Sopenharmony_ci writeWithIndent(childValues_[index]); 4948ffe3c632Sopenharmony_ci else { 4949ffe3c632Sopenharmony_ci if (!indented_) writeIndent(); 4950ffe3c632Sopenharmony_ci indented_ = true; 4951ffe3c632Sopenharmony_ci writeValue(childValue); 4952ffe3c632Sopenharmony_ci indented_ = false; 4953ffe3c632Sopenharmony_ci } 4954ffe3c632Sopenharmony_ci if (++index == size) { 4955ffe3c632Sopenharmony_ci writeCommentAfterValueOnSameLine(childValue); 4956ffe3c632Sopenharmony_ci break; 4957ffe3c632Sopenharmony_ci } 4958ffe3c632Sopenharmony_ci *sout_ << ","; 4959ffe3c632Sopenharmony_ci writeCommentAfterValueOnSameLine(childValue); 4960ffe3c632Sopenharmony_ci } 4961ffe3c632Sopenharmony_ci unindent(); 4962ffe3c632Sopenharmony_ci writeWithIndent("]"); 4963ffe3c632Sopenharmony_ci } else // output on a single line 4964ffe3c632Sopenharmony_ci { 4965ffe3c632Sopenharmony_ci assert(childValues_.size() == size); 4966ffe3c632Sopenharmony_ci *sout_ << "["; 4967ffe3c632Sopenharmony_ci if (!indentation_.empty()) *sout_ << " "; 4968ffe3c632Sopenharmony_ci for (unsigned index = 0; index < size; ++index) { 4969ffe3c632Sopenharmony_ci if (index > 0) 4970ffe3c632Sopenharmony_ci *sout_ << ", "; 4971ffe3c632Sopenharmony_ci *sout_ << childValues_[index]; 4972ffe3c632Sopenharmony_ci } 4973ffe3c632Sopenharmony_ci if (!indentation_.empty()) *sout_ << " "; 4974ffe3c632Sopenharmony_ci *sout_ << "]"; 4975ffe3c632Sopenharmony_ci } 4976ffe3c632Sopenharmony_ci } 4977ffe3c632Sopenharmony_ci} 4978ffe3c632Sopenharmony_ci 4979ffe3c632Sopenharmony_cibool BuiltStyledStreamWriter::isMultineArray(Value const& value) { 4980ffe3c632Sopenharmony_ci int size = value.size(); 4981ffe3c632Sopenharmony_ci bool isMultiLine = size * 3 >= rightMargin_; 4982ffe3c632Sopenharmony_ci childValues_.clear(); 4983ffe3c632Sopenharmony_ci for (int index = 0; index < size && !isMultiLine; ++index) { 4984ffe3c632Sopenharmony_ci Value const& childValue = value[index]; 4985ffe3c632Sopenharmony_ci isMultiLine = ((childValue.isArray() || childValue.isObject()) && 4986ffe3c632Sopenharmony_ci childValue.size() > 0); 4987ffe3c632Sopenharmony_ci } 4988ffe3c632Sopenharmony_ci if (!isMultiLine) // check if line length > max line length 4989ffe3c632Sopenharmony_ci { 4990ffe3c632Sopenharmony_ci childValues_.reserve(size); 4991ffe3c632Sopenharmony_ci addChildValues_ = true; 4992ffe3c632Sopenharmony_ci int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' 4993ffe3c632Sopenharmony_ci for (int index = 0; index < size; ++index) { 4994ffe3c632Sopenharmony_ci if (hasCommentForValue(value[index])) { 4995ffe3c632Sopenharmony_ci isMultiLine = true; 4996ffe3c632Sopenharmony_ci } 4997ffe3c632Sopenharmony_ci writeValue(value[index]); 4998ffe3c632Sopenharmony_ci lineLength += int(childValues_[index].length()); 4999ffe3c632Sopenharmony_ci } 5000ffe3c632Sopenharmony_ci addChildValues_ = false; 5001ffe3c632Sopenharmony_ci isMultiLine = isMultiLine || lineLength >= rightMargin_; 5002ffe3c632Sopenharmony_ci } 5003ffe3c632Sopenharmony_ci return isMultiLine; 5004ffe3c632Sopenharmony_ci} 5005ffe3c632Sopenharmony_ci 5006ffe3c632Sopenharmony_civoid BuiltStyledStreamWriter::pushValue(std::string const& value) { 5007ffe3c632Sopenharmony_ci if (addChildValues_) 5008ffe3c632Sopenharmony_ci childValues_.push_back(value); 5009ffe3c632Sopenharmony_ci else 5010ffe3c632Sopenharmony_ci *sout_ << value; 5011ffe3c632Sopenharmony_ci} 5012ffe3c632Sopenharmony_ci 5013ffe3c632Sopenharmony_civoid BuiltStyledStreamWriter::writeIndent() { 5014ffe3c632Sopenharmony_ci // blep intended this to look at the so-far-written string 5015ffe3c632Sopenharmony_ci // to determine whether we are already indented, but 5016ffe3c632Sopenharmony_ci // with a stream we cannot do that. So we rely on some saved state. 5017ffe3c632Sopenharmony_ci // The caller checks indented_. 5018ffe3c632Sopenharmony_ci 5019ffe3c632Sopenharmony_ci if (!indentation_.empty()) { 5020ffe3c632Sopenharmony_ci // In this case, drop newlines too. 5021ffe3c632Sopenharmony_ci *sout_ << '\n' << indentString_; 5022ffe3c632Sopenharmony_ci } 5023ffe3c632Sopenharmony_ci} 5024ffe3c632Sopenharmony_ci 5025ffe3c632Sopenharmony_civoid BuiltStyledStreamWriter::writeWithIndent(std::string const& value) { 5026ffe3c632Sopenharmony_ci if (!indented_) writeIndent(); 5027ffe3c632Sopenharmony_ci *sout_ << value; 5028ffe3c632Sopenharmony_ci indented_ = false; 5029ffe3c632Sopenharmony_ci} 5030ffe3c632Sopenharmony_ci 5031ffe3c632Sopenharmony_civoid BuiltStyledStreamWriter::indent() { indentString_ += indentation_; } 5032ffe3c632Sopenharmony_ci 5033ffe3c632Sopenharmony_civoid BuiltStyledStreamWriter::unindent() { 5034ffe3c632Sopenharmony_ci assert(indentString_.size() >= indentation_.size()); 5035ffe3c632Sopenharmony_ci indentString_.resize(indentString_.size() - indentation_.size()); 5036ffe3c632Sopenharmony_ci} 5037ffe3c632Sopenharmony_ci 5038ffe3c632Sopenharmony_civoid BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) { 5039ffe3c632Sopenharmony_ci if (cs_ == CommentStyle::None) return; 5040ffe3c632Sopenharmony_ci if (!root.hasComment(commentBefore)) 5041ffe3c632Sopenharmony_ci return; 5042ffe3c632Sopenharmony_ci 5043ffe3c632Sopenharmony_ci if (!indented_) writeIndent(); 5044ffe3c632Sopenharmony_ci const std::string& comment = root.getComment(commentBefore); 5045ffe3c632Sopenharmony_ci std::string::const_iterator iter = comment.begin(); 5046ffe3c632Sopenharmony_ci while (iter != comment.end()) { 5047ffe3c632Sopenharmony_ci *sout_ << *iter; 5048ffe3c632Sopenharmony_ci if (*iter == '\n' && 5049ffe3c632Sopenharmony_ci (iter != comment.end() && *(iter + 1) == '/')) 5050ffe3c632Sopenharmony_ci // writeIndent(); // would write extra newline 5051ffe3c632Sopenharmony_ci *sout_ << indentString_; 5052ffe3c632Sopenharmony_ci ++iter; 5053ffe3c632Sopenharmony_ci } 5054ffe3c632Sopenharmony_ci indented_ = false; 5055ffe3c632Sopenharmony_ci} 5056ffe3c632Sopenharmony_ci 5057ffe3c632Sopenharmony_civoid BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) { 5058ffe3c632Sopenharmony_ci if (cs_ == CommentStyle::None) return; 5059ffe3c632Sopenharmony_ci if (root.hasComment(commentAfterOnSameLine)) 5060ffe3c632Sopenharmony_ci *sout_ << " " + root.getComment(commentAfterOnSameLine); 5061ffe3c632Sopenharmony_ci 5062ffe3c632Sopenharmony_ci if (root.hasComment(commentAfter)) { 5063ffe3c632Sopenharmony_ci writeIndent(); 5064ffe3c632Sopenharmony_ci *sout_ << root.getComment(commentAfter); 5065ffe3c632Sopenharmony_ci } 5066ffe3c632Sopenharmony_ci} 5067ffe3c632Sopenharmony_ci 5068ffe3c632Sopenharmony_ci// static 5069ffe3c632Sopenharmony_cibool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) { 5070ffe3c632Sopenharmony_ci return value.hasComment(commentBefore) || 5071ffe3c632Sopenharmony_ci value.hasComment(commentAfterOnSameLine) || 5072ffe3c632Sopenharmony_ci value.hasComment(commentAfter); 5073ffe3c632Sopenharmony_ci} 5074ffe3c632Sopenharmony_ci 5075ffe3c632Sopenharmony_ci/////////////// 5076ffe3c632Sopenharmony_ci// StreamWriter 5077ffe3c632Sopenharmony_ci 5078ffe3c632Sopenharmony_ciStreamWriter::StreamWriter() 5079ffe3c632Sopenharmony_ci : sout_(NULL) 5080ffe3c632Sopenharmony_ci{ 5081ffe3c632Sopenharmony_ci} 5082ffe3c632Sopenharmony_ciStreamWriter::~StreamWriter() 5083ffe3c632Sopenharmony_ci{ 5084ffe3c632Sopenharmony_ci} 5085ffe3c632Sopenharmony_ciStreamWriter::Factory::~Factory() 5086ffe3c632Sopenharmony_ci{} 5087ffe3c632Sopenharmony_ciStreamWriterBuilder::StreamWriterBuilder() 5088ffe3c632Sopenharmony_ci{ 5089ffe3c632Sopenharmony_ci setDefaults(&settings_); 5090ffe3c632Sopenharmony_ci} 5091ffe3c632Sopenharmony_ciStreamWriterBuilder::~StreamWriterBuilder() 5092ffe3c632Sopenharmony_ci{} 5093ffe3c632Sopenharmony_ciStreamWriter* StreamWriterBuilder::newStreamWriter() const 5094ffe3c632Sopenharmony_ci{ 5095ffe3c632Sopenharmony_ci std::string indentation = settings_["indentation"].asString(); 5096ffe3c632Sopenharmony_ci std::string cs_str = settings_["commentStyle"].asString(); 5097ffe3c632Sopenharmony_ci bool eyc = settings_["enableYAMLCompatibility"].asBool(); 5098ffe3c632Sopenharmony_ci bool dnp = settings_["dropNullPlaceholders"].asBool(); 5099ffe3c632Sopenharmony_ci bool usf = settings_["useSpecialFloats"].asBool(); 5100ffe3c632Sopenharmony_ci unsigned int pre = settings_["precision"].asUInt(); 5101ffe3c632Sopenharmony_ci CommentStyle::Enum cs = CommentStyle::All; 5102ffe3c632Sopenharmony_ci if (cs_str == "All") { 5103ffe3c632Sopenharmony_ci cs = CommentStyle::All; 5104ffe3c632Sopenharmony_ci } else if (cs_str == "None") { 5105ffe3c632Sopenharmony_ci cs = CommentStyle::None; 5106ffe3c632Sopenharmony_ci } else { 5107ffe3c632Sopenharmony_ci throwRuntimeError("commentStyle must be 'All' or 'None'"); 5108ffe3c632Sopenharmony_ci } 5109ffe3c632Sopenharmony_ci std::string colonSymbol = " : "; 5110ffe3c632Sopenharmony_ci if (eyc) { 5111ffe3c632Sopenharmony_ci colonSymbol = ": "; 5112ffe3c632Sopenharmony_ci } else if (indentation.empty()) { 5113ffe3c632Sopenharmony_ci colonSymbol = ":"; 5114ffe3c632Sopenharmony_ci } 5115ffe3c632Sopenharmony_ci std::string nullSymbol = "null"; 5116ffe3c632Sopenharmony_ci if (dnp) { 5117ffe3c632Sopenharmony_ci nullSymbol = ""; 5118ffe3c632Sopenharmony_ci } 5119ffe3c632Sopenharmony_ci if (pre > 17) pre = 17; 5120ffe3c632Sopenharmony_ci std::string endingLineFeedSymbol = ""; 5121ffe3c632Sopenharmony_ci return new BuiltStyledStreamWriter( 5122ffe3c632Sopenharmony_ci indentation, cs, 5123ffe3c632Sopenharmony_ci colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre); 5124ffe3c632Sopenharmony_ci} 5125ffe3c632Sopenharmony_cistatic void getValidWriterKeys(std::set<std::string>* valid_keys) 5126ffe3c632Sopenharmony_ci{ 5127ffe3c632Sopenharmony_ci valid_keys->clear(); 5128ffe3c632Sopenharmony_ci valid_keys->insert("indentation"); 5129ffe3c632Sopenharmony_ci valid_keys->insert("commentStyle"); 5130ffe3c632Sopenharmony_ci valid_keys->insert("enableYAMLCompatibility"); 5131ffe3c632Sopenharmony_ci valid_keys->insert("dropNullPlaceholders"); 5132ffe3c632Sopenharmony_ci valid_keys->insert("useSpecialFloats"); 5133ffe3c632Sopenharmony_ci valid_keys->insert("precision"); 5134ffe3c632Sopenharmony_ci} 5135ffe3c632Sopenharmony_cibool StreamWriterBuilder::validate(Json::Value* invalid) const 5136ffe3c632Sopenharmony_ci{ 5137ffe3c632Sopenharmony_ci Json::Value my_invalid; 5138ffe3c632Sopenharmony_ci if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL 5139ffe3c632Sopenharmony_ci Json::Value& inv = *invalid; 5140ffe3c632Sopenharmony_ci std::set<std::string> valid_keys; 5141ffe3c632Sopenharmony_ci getValidWriterKeys(&valid_keys); 5142ffe3c632Sopenharmony_ci Value::Members keys = settings_.getMemberNames(); 5143ffe3c632Sopenharmony_ci size_t n = keys.size(); 5144ffe3c632Sopenharmony_ci for (size_t i = 0; i < n; ++i) { 5145ffe3c632Sopenharmony_ci std::string const& key = keys[i]; 5146ffe3c632Sopenharmony_ci if (valid_keys.find(key) == valid_keys.end()) { 5147ffe3c632Sopenharmony_ci inv[key] = settings_[key]; 5148ffe3c632Sopenharmony_ci } 5149ffe3c632Sopenharmony_ci } 5150ffe3c632Sopenharmony_ci return 0u == inv.size(); 5151ffe3c632Sopenharmony_ci} 5152ffe3c632Sopenharmony_ciValue& StreamWriterBuilder::operator[](std::string key) 5153ffe3c632Sopenharmony_ci{ 5154ffe3c632Sopenharmony_ci return settings_[key]; 5155ffe3c632Sopenharmony_ci} 5156ffe3c632Sopenharmony_ci// static 5157ffe3c632Sopenharmony_civoid StreamWriterBuilder::setDefaults(Json::Value* settings) 5158ffe3c632Sopenharmony_ci{ 5159ffe3c632Sopenharmony_ci //! [StreamWriterBuilderDefaults] 5160ffe3c632Sopenharmony_ci (*settings)["commentStyle"] = "All"; 5161ffe3c632Sopenharmony_ci (*settings)["indentation"] = "\t"; 5162ffe3c632Sopenharmony_ci (*settings)["enableYAMLCompatibility"] = false; 5163ffe3c632Sopenharmony_ci (*settings)["dropNullPlaceholders"] = false; 5164ffe3c632Sopenharmony_ci (*settings)["useSpecialFloats"] = false; 5165ffe3c632Sopenharmony_ci (*settings)["precision"] = 17; 5166ffe3c632Sopenharmony_ci //! [StreamWriterBuilderDefaults] 5167ffe3c632Sopenharmony_ci} 5168ffe3c632Sopenharmony_ci 5169ffe3c632Sopenharmony_cistd::string writeString(StreamWriter::Factory const& builder, Value const& root) { 5170ffe3c632Sopenharmony_ci std::ostringstream sout; 5171ffe3c632Sopenharmony_ci StreamWriterPtr const writer(builder.newStreamWriter()); 5172ffe3c632Sopenharmony_ci writer->write(root, &sout); 5173ffe3c632Sopenharmony_ci return sout.str(); 5174ffe3c632Sopenharmony_ci} 5175ffe3c632Sopenharmony_ci 5176ffe3c632Sopenharmony_cistd::ostream& operator<<(std::ostream& sout, Value const& root) { 5177ffe3c632Sopenharmony_ci StreamWriterBuilder builder; 5178ffe3c632Sopenharmony_ci StreamWriterPtr const writer(builder.newStreamWriter()); 5179ffe3c632Sopenharmony_ci writer->write(root, &sout); 5180ffe3c632Sopenharmony_ci return sout; 5181ffe3c632Sopenharmony_ci} 5182ffe3c632Sopenharmony_ci 5183ffe3c632Sopenharmony_ci} // namespace Json 5184ffe3c632Sopenharmony_ci 5185ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 5186ffe3c632Sopenharmony_ci// End of content of file: src/lib_json/json_writer.cpp 5187ffe3c632Sopenharmony_ci// ////////////////////////////////////////////////////////////////////// 5188ffe3c632Sopenharmony_ci 5189ffe3c632Sopenharmony_ci 5190ffe3c632Sopenharmony_ci 5191ffe3c632Sopenharmony_ci 5192ffe3c632Sopenharmony_ci 5193