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_ = &currentValue();
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_ = &currentValue();
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