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