blob: 82859fda1af16019330c2ebfbe7d52723fb8061d [file] [log] [blame]
Devin Jeanpierre59e4d352017-07-21 03:44:36 -07001// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
Baptiste Lepilleur7469f1d2010-04-20 21:35:19 +00002// Distributed under MIT license, or public domain if desired and
3// recognized in your jurisdiction.
4// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5
Christopher Dunn6d135cb2007-06-13 15:51:04 +00006#ifndef CPPTL_JSON_READER_H_INCLUDED
Aaron Jacobs9fa4e842014-07-01 08:48:54 +10007#define CPPTL_JSON_READER_H_INCLUDED
Christopher Dunn6d135cb2007-06-13 15:51:04 +00008
Baptiste Lepilleureadc4782011-05-02 21:09:30 +00009#if !defined(JSON_IS_AMALGAMATION)
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100010#include "features.h"
11#include "value.h"
Baptiste Lepilleureadc4782011-05-02 21:09:30 +000012#endif // if !defined(JSON_IS_AMALGAMATION)
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100013#include <deque>
14#include <iosfwd>
15#include <stack>
16#include <string>
Christopher Dunn2c1197c2015-01-29 14:29:40 -060017#include <istream>
Christopher Dunn6d135cb2007-06-13 15:51:04 +000018
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100019// Disable warning C4251: <data member>: <type> needs to have dll-interface to
20// be used by...
Baptiste Lepilleureafd7022013-05-08 20:21:11 +000021#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100022#pragma warning(push)
23#pragma warning(disable : 4251)
Baptiste Lepilleureafd7022013-05-08 20:21:11 +000024#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
25
Sergiy80d6e666f2016-12-03 22:29:14 +020026#pragma pack(push, 8)
27
Christopher Dunn6d135cb2007-06-13 15:51:04 +000028namespace Json {
29
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100030/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
31 *Value.
32 *
Christopher Dunn8df98f62015-02-09 11:15:39 -060033 * \deprecated Use CharReader and CharReaderBuilder.
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100034 */
damiramef16a352017-08-02 22:44:42 -070035class JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") JSON_API Reader {
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100036public:
37 typedef char Char;
Aaron Jacobs11086dd2014-09-15 10:15:29 +100038 typedef const Char* Location;
Christopher Dunn6d135cb2007-06-13 15:51:04 +000039
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100040 /** \brief An error tagged with where in the JSON text it was encountered.
41 *
42 * The offsets give the [start, limit) range of bytes within the text. Note
43 * that this is bytes, not codepoints.
44 *
Christopher Dunn6d135cb2007-06-13 15:51:04 +000045 */
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100046 struct StructuredError {
Christopher Dunnd4513fc2016-02-06 09:25:20 -060047 ptrdiff_t offset_start;
48 ptrdiff_t offset_limit;
Christopher Dawes75570d72016-03-07 08:29:59 +000049 JSONCPP_STRING message;
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100050 };
51
52 /** \brief Constructs a Reader allowing all features
53 * for parsing.
54 */
55 Reader();
56
57 /** \brief Constructs a Reader allowing the specified feature set
58 * for parsing.
59 */
Aaron Jacobs11086dd2014-09-15 10:15:29 +100060 Reader(const Features& features);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100061
62 /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
63 * document.
64 * \param document UTF-8 encoded string containing the document to read.
65 * \param root [out] Contains the root value of the document if it was
66 * successfully parsed.
67 * \param collectComments \c true to collect comment and allow writing them
68 * back during
69 * serialization, \c false to discard comments.
70 * This parameter is ignored if
71 * Features::allowComments_
72 * is \c false.
73 * \return \c true if the document was successfully parsed, \c false if an
74 * error occurred.
75 */
76 bool
Aaron Jacobs11086dd2014-09-15 10:15:29 +100077 parse(const std::string& document, Value& root, bool collectComments = true);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100078
79 /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
80 document.
81 * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
82 document to read.
83 * \param endDoc Pointer on the end of the UTF-8 encoded string of the
84 document to read.
Christopher Dunn2c1197c2015-01-29 14:29:40 -060085 * Must be >= beginDoc.
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100086 * \param root [out] Contains the root value of the document if it was
87 * successfully parsed.
88 * \param collectComments \c true to collect comment and allow writing them
89 back during
90 * serialization, \c false to discard comments.
91 * This parameter is ignored if
92 Features::allowComments_
93 * is \c false.
94 * \return \c true if the document was successfully parsed, \c false if an
95 error occurred.
96 */
Aaron Jacobs11086dd2014-09-15 10:15:29 +100097 bool parse(const char* beginDoc,
98 const char* endDoc,
99 Value& root,
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000100 bool collectComments = true);
101
102 /// \brief Parse from input stream.
103 /// \see Json::operator>>(std::istream&, Json::Value&).
Christopher Dunnb84e0c12016-03-06 11:54:27 -0600104 bool parse(JSONCPP_ISTREAM& is, Value& root, bool collectComments = true);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000105
106 /** \brief Returns a user friendly string that list errors in the parsed
107 * document.
108 * \return Formatted error message with the list of errors with their location
109 * in
110 * the parsed document. An empty string is returned if no error
111 * occurred
112 * during parsing.
113 * \deprecated Use getFormattedErrorMessages() instead (typo fix).
114 */
Christopher Dunned495ed2015-03-08 14:01:28 -0500115 JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
Christopher Dawes75570d72016-03-07 08:29:59 +0000116 JSONCPP_STRING getFormatedErrorMessages() const;
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000117
118 /** \brief Returns a user friendly string that list errors in the parsed
119 * document.
120 * \return Formatted error message with the list of errors with their location
121 * in
122 * the parsed document. An empty string is returned if no error
123 * occurred
124 * during parsing.
125 */
Christopher Dawes75570d72016-03-07 08:29:59 +0000126 JSONCPP_STRING getFormattedErrorMessages() const;
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000127
128 /** \brief Returns a vector of structured erros encounted while parsing.
129 * \return A (possibly empty) vector of StructuredError objects. Currently
130 * only one error can be returned, but the caller should tolerate
131 * multiple
132 * errors. This can occur if the parser recovers from a non-fatal
133 * parse error and then encounters additional errors.
134 */
135 std::vector<StructuredError> getStructuredErrors() const;
136
Mara Kimb84a39c2014-10-23 02:03:43 -0500137 /** \brief Add a semantic error message.
138 * \param value JSON Value location associated with the error
139 * \param message The error message.
140 * \return \c true if the error was successfully added, \c false if the
141 * Value offset exceeds the document size.
142 */
Christopher Dawes75570d72016-03-07 08:29:59 +0000143 bool pushError(const Value& value, const JSONCPP_STRING& message);
Mara Kimb84a39c2014-10-23 02:03:43 -0500144
145 /** \brief Add a semantic error message with extra context.
146 * \param value JSON Value location associated with the error
147 * \param message The error message.
148 * \param extra Additional JSON Value location to contextualize the error
149 * \return \c true if the error was successfully added, \c false if either
150 * Value offset exceeds the document size.
151 */
Christopher Dawes75570d72016-03-07 08:29:59 +0000152 bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
Mara Kimb84a39c2014-10-23 02:03:43 -0500153
154 /** \brief Return whether there are any errors.
155 * \return \c true if there are no errors to report \c false if
156 * errors have occurred.
157 */
158 bool good() const;
159
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000160private:
161 enum TokenType {
162 tokenEndOfStream = 0,
163 tokenObjectBegin,
164 tokenObjectEnd,
165 tokenArrayBegin,
166 tokenArrayEnd,
167 tokenString,
168 tokenNumber,
169 tokenTrue,
170 tokenFalse,
171 tokenNull,
172 tokenArraySeparator,
173 tokenMemberSeparator,
174 tokenComment,
175 tokenError
176 };
177
178 class Token {
179 public:
180 TokenType type_;
181 Location start_;
182 Location end_;
183 };
184
185 class ErrorInfo {
186 public:
187 Token token_;
Christopher Dawes75570d72016-03-07 08:29:59 +0000188 JSONCPP_STRING message_;
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000189 Location extra_;
190 };
191
192 typedef std::deque<ErrorInfo> Errors;
193
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000194 bool readToken(Token& token);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000195 void skipSpaces();
196 bool match(Location pattern, int patternLength);
197 bool readComment();
198 bool readCStyleComment();
199 bool readCppStyleComment();
200 bool readString();
201 void readNumber();
202 bool readValue();
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000203 bool readObject(Token& token);
204 bool readArray(Token& token);
205 bool decodeNumber(Token& token);
206 bool decodeNumber(Token& token, Value& decoded);
207 bool decodeString(Token& token);
Christopher Dawes75570d72016-03-07 08:29:59 +0000208 bool decodeString(Token& token, JSONCPP_STRING& decoded);
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000209 bool decodeDouble(Token& token);
210 bool decodeDouble(Token& token, Value& decoded);
211 bool decodeUnicodeCodePoint(Token& token,
212 Location& current,
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000213 Location end,
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000214 unsigned int& unicode);
215 bool decodeUnicodeEscapeSequence(Token& token,
216 Location& current,
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000217 Location end,
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000218 unsigned int& unicode);
Christopher Dawes75570d72016-03-07 08:29:59 +0000219 bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000220 bool recoverFromError(TokenType skipUntilToken);
Christopher Dawes75570d72016-03-07 08:29:59 +0000221 bool addErrorAndRecover(const JSONCPP_STRING& message,
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000222 Token& token,
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000223 TokenType skipUntilToken);
224 void skipUntilSpace();
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000225 Value& currentValue();
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000226 Char getNextChar();
227 void
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000228 getLocationLineAndColumn(Location location, int& line, int& column) const;
Christopher Dawes75570d72016-03-07 08:29:59 +0000229 JSONCPP_STRING getLocationLineAndColumn(Location location) const;
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000230 void addComment(Location begin, Location end, CommentPlacement placement);
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000231 void skipCommentTokens(Token& token);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000232
damiramef16a352017-08-02 22:44:42 -0700233 static bool containsNewLine(Location begin, Location end);
234 static JSONCPP_STRING normalizeEOL(Location begin, Location end);
235
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000236 typedef std::stack<Value*> Nodes;
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000237 Nodes nodes_;
238 Errors errors_;
Christopher Dawes75570d72016-03-07 08:29:59 +0000239 JSONCPP_STRING document_;
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000240 Location begin_;
241 Location end_;
242 Location current_;
243 Location lastValueEnd_;
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000244 Value* lastValue_;
Christopher Dawes75570d72016-03-07 08:29:59 +0000245 JSONCPP_STRING commentsBefore_;
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000246 Features features_;
247 bool collectComments_;
Christopher Dunn2c1197c2015-01-29 14:29:40 -0600248}; // Reader
249
250/** Interface for reading JSON from a char array.
251 */
252class JSON_API CharReader {
253public:
254 virtual ~CharReader() {}
255 /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
256 document.
257 * The document must be a UTF-8 encoded string containing the document to read.
258 *
259 * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
260 document to read.
261 * \param endDoc Pointer on the end of the UTF-8 encoded string of the
262 document to read.
263 * Must be >= beginDoc.
264 * \param root [out] Contains the root value of the document if it was
265 * successfully parsed.
266 * \param errs [out] Formatted error messages (if not NULL)
267 * a user friendly string that lists errors in the parsed
268 * document.
269 * \return \c true if the document was successfully parsed, \c false if an
270 error occurred.
271 */
272 virtual bool parse(
273 char const* beginDoc, char const* endDoc,
Christopher Dawes75570d72016-03-07 08:29:59 +0000274 Value* root, JSONCPP_STRING* errs) = 0;
Christopher Dunn2c1197c2015-01-29 14:29:40 -0600275
Ben Boeckel80def662015-09-28 15:45:11 -0400276 class JSON_API Factory {
Christopher Dunn2c1197c2015-01-29 14:29:40 -0600277 public:
Tengiz Sharafievbe183de2015-03-14 21:30:00 +0300278 virtual ~Factory() {}
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600279 /** \brief Allocate a CharReader via operator new().
280 * \throw std::exception if something goes wrong (e.g. invalid settings)
281 */
Christopher Dunn2c1197c2015-01-29 14:29:40 -0600282 virtual CharReader* newCharReader() const = 0;
283 }; // Factory
284}; // CharReader
285
Christopher Dunn66a8ba22015-02-09 01:29:43 -0600286/** \brief Build a CharReader implementation.
287
288Usage:
289\code
290 using namespace Json;
291 CharReaderBuilder builder;
Christopher Dunnc312dd52015-03-04 14:56:37 -0600292 builder["collectComments"] = false;
Christopher Dunn66a8ba22015-02-09 01:29:43 -0600293 Value value;
Christopher Dawes75570d72016-03-07 08:29:59 +0000294 JSONCPP_STRING errs;
Christopher Dunn8df98f62015-02-09 11:15:39 -0600295 bool ok = parseFromStream(builder, std::cin, &value, &errs);
Christopher Dunn66a8ba22015-02-09 01:29:43 -0600296\endcode
297*/
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600298class JSON_API CharReaderBuilder : public CharReader::Factory {
Christopher Dunn66a8ba22015-02-09 01:29:43 -0600299public:
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600300 // Note: We use a Json::Value so that we can add data-members to this class
301 // without a major version bump.
302 /** Configuration of this builder.
Christopher Dunn3cf91752015-02-09 18:16:24 -0600303 These are case-sensitive.
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600304 Available settings (case-sensitive):
Christopher Dunnaa13a8b2015-02-13 09:37:39 -0600305 - `"collectComments": false or true`
Christopher Dunn29501c42015-02-10 23:03:27 -0600306 - true to collect comment and allow writing them
307 back during serialization, false to discard comments.
308 This parameter is ignored if allowComments is false.
Christopher Dunnaa13a8b2015-02-13 09:37:39 -0600309 - `"allowComments": false or true`
Christopher Dunn29501c42015-02-10 23:03:27 -0600310 - true if comments are allowed.
Christopher Dunnaa13a8b2015-02-13 09:37:39 -0600311 - `"strictRoot": false or true`
Christopher Dunn29501c42015-02-10 23:03:27 -0600312 - true if root must be either an array or an object value
Christopher Dunnaa13a8b2015-02-13 09:37:39 -0600313 - `"allowDroppedNullPlaceholders": false or true`
Christopher Dunn29501c42015-02-10 23:03:27 -0600314 - true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
Christopher Dunnaa13a8b2015-02-13 09:37:39 -0600315 - `"allowNumericKeys": false or true`
Christopher Dunn29501c42015-02-10 23:03:27 -0600316 - true if numeric object keys are allowed.
Christopher Dunn0c66e692015-02-23 15:55:12 -0600317 - `"allowSingleQuotes": false or true`
318 - true if '' are allowed for strings (both keys and values)
Christopher Dunnaa13a8b2015-02-13 09:37:39 -0600319 - `"stackLimit": integer`
320 - Exceeding stackLimit (recursive depth of `readValue()`) will
321 cause an exception.
Christopher Dunn249ad9f2015-02-10 12:16:03 -0600322 - This is a security issue (seg-faults caused by deeply nested JSON),
323 so the default is low.
Christopher Dunnf4be8152015-02-12 12:34:23 -0600324 - `"failIfExtra": false or true`
325 - If true, `parse()` returns false when extra non-whitespace trails
326 the JSON value in the input string.
Christopher Dunn527332d2015-03-06 12:18:59 -0600327 - `"rejectDupKeys": false or true`
328 - If true, `parse()` returns false when a key is duplicated within an object.
drgler20845632015-09-03 22:19:22 +0200329 - `"allowSpecialFloats": false or true`
330 - If true, special float values (NaNs and infinities) are allowed
331 and their values are lossfree restorable.
Christopher Dunnf757c182015-02-09 18:24:56 -0600332
Christopher Dunn3cf91752015-02-09 18:16:24 -0600333 You can examine 'settings_` yourself
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600334 to see the defaults. You can also write and read them just like any
335 JSON Value.
Christopher Dunnf757c182015-02-09 18:24:56 -0600336 \sa setDefaults()
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600337 */
338 Json::Value settings_;
Christopher Dunn66a8ba22015-02-09 01:29:43 -0600339
Christopher Dunn2c1197c2015-01-29 14:29:40 -0600340 CharReaderBuilder();
Christopher Dunn98e981d2016-03-21 21:00:24 -0500341 ~CharReaderBuilder() JSONCPP_OVERRIDE;
Christopher Dunn2c1197c2015-01-29 14:29:40 -0600342
Christopher Dunn98e981d2016-03-21 21:00:24 -0500343 CharReader* newCharReader() const JSONCPP_OVERRIDE;
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600344
Christopher Dunnf757c182015-02-09 18:24:56 -0600345 /** \return true if 'settings' are legal and consistent;
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600346 * otherwise, indicate bad settings via 'invalid'.
347 */
348 bool validate(Json::Value* invalid) const;
Christopher Dunnc312dd52015-03-04 14:56:37 -0600349
350 /** A simple way to update a specific setting.
351 */
Christopher Dawes75570d72016-03-07 08:29:59 +0000352 Value& operator[](JSONCPP_STRING key);
Christopher Dunnc312dd52015-03-04 14:56:37 -0600353
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600354 /** Called by ctor, but you can use this to reset settings_.
355 * \pre 'settings' != NULL (but Json::null is fine)
Christopher Dunn3cf91752015-02-09 18:16:24 -0600356 * \remark Defaults:
Christopher Dunn56650e82015-04-20 13:10:31 -0700357 * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600358 */
359 static void setDefaults(Json::Value* settings);
Christopher Dunn3cf91752015-02-09 18:16:24 -0600360 /** Same as old Features::strictMode().
361 * \pre 'settings' != NULL (but Json::null is fine)
362 * \remark Defaults:
Christopher Dunn56650e82015-04-20 13:10:31 -0700363 * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
Christopher Dunn3cf91752015-02-09 18:16:24 -0600364 */
365 static void strictMode(Json::Value* settings);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000366};
367
Christopher Dunn2c1197c2015-01-29 14:29:40 -0600368/** Consume entire stream and use its begin/end.
369 * Someday we might have a real StreamReader, but for now this
370 * is convenient.
371 */
Christopher Dunneaa3fd82015-03-05 10:11:43 -0600372bool JSON_API parseFromStream(
Christopher Dunn2c1197c2015-01-29 14:29:40 -0600373 CharReader::Factory const&,
Christopher Dunnb84e0c12016-03-06 11:54:27 -0600374 JSONCPP_ISTREAM&,
Christopher Dunn2c1197c2015-01-29 14:29:40 -0600375 Value* root, std::string* errs);
376
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000377/** \brief Read from 'sin' into 'root'.
378
379 Always keep comments from the input JSON.
380
381 This can be used to read a file into a particular sub-object.
382 For example:
383 \code
384 Json::Value root;
385 cin >> root["dir"]["file"];
386 cout << root;
387 \endcode
388 Result:
389 \verbatim
390 {
391 "dir": {
392 "file": {
393 // The input stream JSON would be nested here.
394 }
395 }
396 }
397 \endverbatim
398 \throw std::exception on parse error.
399 \see Json::operator<<()
400*/
Christopher Dunnb84e0c12016-03-06 11:54:27 -0600401JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&);
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000402
403} // namespace Json
404
Sergiy80d6e666f2016-12-03 22:29:14 +0200405#pragma pack(pop)
406
Baptiste Lepilleureafd7022013-05-08 20:21:11 +0000407#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000408#pragma warning(pop)
Baptiste Lepilleureafd7022013-05-08 20:21:11 +0000409#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
410
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000411#endif // CPPTL_JSON_READER_H_INCLUDED