blob: c07ce19b541909ad336a57b7ae415772400ef045 [file] [log] [blame]
Baptiste Lepilleur7469f1d2010-04-20 21:35:19 +00001// Copyright 2007-2010 Baptiste Lepilleur
2// 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
Christopher Dunn6d135cb2007-06-13 15:51:04 +000026namespace Json {
27
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100028/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
29 *Value.
30 *
Christopher Dunn8df98f62015-02-09 11:15:39 -060031 * \deprecated Use CharReader and CharReaderBuilder.
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100032 */
33class JSON_API Reader {
34public:
35 typedef char Char;
Aaron Jacobs11086dd2014-09-15 10:15:29 +100036 typedef const Char* Location;
Christopher Dunn6d135cb2007-06-13 15:51:04 +000037
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100038 /** \brief An error tagged with where in the JSON text it was encountered.
39 *
40 * The offsets give the [start, limit) range of bytes within the text. Note
41 * that this is bytes, not codepoints.
42 *
Christopher Dunn6d135cb2007-06-13 15:51:04 +000043 */
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100044 struct StructuredError {
45 size_t offset_start;
46 size_t offset_limit;
47 std::string message;
48 };
49
50 /** \brief Constructs a Reader allowing all features
51 * for parsing.
52 */
53 Reader();
54
55 /** \brief Constructs a Reader allowing the specified feature set
56 * for parsing.
57 */
Aaron Jacobs11086dd2014-09-15 10:15:29 +100058 Reader(const Features& features);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100059
60 /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
61 * document.
62 * \param document UTF-8 encoded string containing the document to read.
63 * \param root [out] Contains the root value of the document if it was
64 * successfully parsed.
65 * \param collectComments \c true to collect comment and allow writing them
66 * back during
67 * serialization, \c false to discard comments.
68 * This parameter is ignored if
69 * Features::allowComments_
70 * is \c false.
71 * \return \c true if the document was successfully parsed, \c false if an
72 * error occurred.
73 */
74 bool
Aaron Jacobs11086dd2014-09-15 10:15:29 +100075 parse(const std::string& document, Value& root, bool collectComments = true);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100076
77 /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
78 document.
79 * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
80 document to read.
81 * \param endDoc Pointer on the end of the UTF-8 encoded string of the
82 document to read.
Christopher Dunn2c1197c2015-01-29 14:29:40 -060083 * Must be >= beginDoc.
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100084 * \param root [out] Contains the root value of the document if it was
85 * successfully parsed.
86 * \param collectComments \c true to collect comment and allow writing them
87 back during
88 * serialization, \c false to discard comments.
89 * This parameter is ignored if
90 Features::allowComments_
91 * is \c false.
92 * \return \c true if the document was successfully parsed, \c false if an
93 error occurred.
94 */
Aaron Jacobs11086dd2014-09-15 10:15:29 +100095 bool parse(const char* beginDoc,
96 const char* endDoc,
97 Value& root,
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100098 bool collectComments = true);
99
100 /// \brief Parse from input stream.
101 /// \see Json::operator>>(std::istream&, Json::Value&).
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000102 bool parse(std::istream& is, Value& root, bool collectComments = true);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000103
104 /** \brief Returns a user friendly string that list errors in the parsed
105 * document.
106 * \return Formatted error message with the list of errors with their location
107 * in
108 * the parsed document. An empty string is returned if no error
109 * occurred
110 * during parsing.
111 * \deprecated Use getFormattedErrorMessages() instead (typo fix).
112 */
Christopher Dunned495ed2015-03-08 14:01:28 -0500113 JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000114 std::string getFormatedErrorMessages() const;
115
116 /** \brief Returns a user friendly string that list errors in the parsed
117 * document.
118 * \return Formatted error message with the list of errors with their location
119 * in
120 * the parsed document. An empty string is returned if no error
121 * occurred
122 * during parsing.
123 */
124 std::string getFormattedErrorMessages() const;
125
126 /** \brief Returns a vector of structured erros encounted while parsing.
127 * \return A (possibly empty) vector of StructuredError objects. Currently
128 * only one error can be returned, but the caller should tolerate
129 * multiple
130 * errors. This can occur if the parser recovers from a non-fatal
131 * parse error and then encounters additional errors.
132 */
133 std::vector<StructuredError> getStructuredErrors() const;
134
Mara Kimb84a39c2014-10-23 02:03:43 -0500135 /** \brief Add a semantic error message.
136 * \param value JSON Value location associated with the error
137 * \param message The error message.
138 * \return \c true if the error was successfully added, \c false if the
139 * Value offset exceeds the document size.
140 */
141 bool pushError(const Value& value, const std::string& message);
142
143 /** \brief Add a semantic error message with extra context.
144 * \param value JSON Value location associated with the error
145 * \param message The error message.
146 * \param extra Additional JSON Value location to contextualize the error
147 * \return \c true if the error was successfully added, \c false if either
148 * Value offset exceeds the document size.
149 */
150 bool pushError(const Value& value, const std::string& message, const Value& extra);
151
152 /** \brief Return whether there are any errors.
153 * \return \c true if there are no errors to report \c false if
154 * errors have occurred.
155 */
156 bool good() const;
157
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000158private:
159 enum TokenType {
160 tokenEndOfStream = 0,
161 tokenObjectBegin,
162 tokenObjectEnd,
163 tokenArrayBegin,
164 tokenArrayEnd,
165 tokenString,
166 tokenNumber,
167 tokenTrue,
168 tokenFalse,
169 tokenNull,
170 tokenArraySeparator,
171 tokenMemberSeparator,
172 tokenComment,
173 tokenError
174 };
175
176 class Token {
177 public:
178 TokenType type_;
179 Location start_;
180 Location end_;
181 };
182
183 class ErrorInfo {
184 public:
185 Token token_;
186 std::string message_;
187 Location extra_;
188 };
189
190 typedef std::deque<ErrorInfo> Errors;
191
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000192 bool readToken(Token& token);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000193 void skipSpaces();
194 bool match(Location pattern, int patternLength);
195 bool readComment();
196 bool readCStyleComment();
197 bool readCppStyleComment();
198 bool readString();
199 void readNumber();
200 bool readValue();
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000201 bool readObject(Token& token);
202 bool readArray(Token& token);
203 bool decodeNumber(Token& token);
204 bool decodeNumber(Token& token, Value& decoded);
205 bool decodeString(Token& token);
206 bool decodeString(Token& token, std::string& decoded);
207 bool decodeDouble(Token& token);
208 bool decodeDouble(Token& token, Value& decoded);
209 bool decodeUnicodeCodePoint(Token& token,
210 Location& current,
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000211 Location end,
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000212 unsigned int& unicode);
213 bool decodeUnicodeEscapeSequence(Token& token,
214 Location& current,
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000215 Location end,
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000216 unsigned int& unicode);
217 bool addError(const std::string& message, Token& token, Location extra = 0);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000218 bool recoverFromError(TokenType skipUntilToken);
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000219 bool addErrorAndRecover(const std::string& message,
220 Token& token,
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000221 TokenType skipUntilToken);
222 void skipUntilSpace();
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000223 Value& currentValue();
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000224 Char getNextChar();
225 void
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000226 getLocationLineAndColumn(Location location, int& line, int& column) const;
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000227 std::string getLocationLineAndColumn(Location location) const;
228 void addComment(Location begin, Location end, CommentPlacement placement);
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000229 void skipCommentTokens(Token& token);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000230
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000231 typedef std::stack<Value*> Nodes;
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000232 Nodes nodes_;
233 Errors errors_;
234 std::string document_;
235 Location begin_;
236 Location end_;
237 Location current_;
238 Location lastValueEnd_;
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000239 Value* lastValue_;
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000240 std::string commentsBefore_;
241 Features features_;
242 bool collectComments_;
Christopher Dunn2c1197c2015-01-29 14:29:40 -0600243}; // Reader
244
245/** Interface for reading JSON from a char array.
246 */
247class JSON_API CharReader {
248public:
249 virtual ~CharReader() {}
250 /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
251 document.
252 * The document must be a UTF-8 encoded string containing the document to read.
253 *
254 * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
255 document to read.
256 * \param endDoc Pointer on the end of the UTF-8 encoded string of the
257 document to read.
258 * Must be >= beginDoc.
259 * \param root [out] Contains the root value of the document if it was
260 * successfully parsed.
261 * \param errs [out] Formatted error messages (if not NULL)
262 * a user friendly string that lists errors in the parsed
263 * document.
264 * \return \c true if the document was successfully parsed, \c false if an
265 error occurred.
266 */
267 virtual bool parse(
268 char const* beginDoc, char const* endDoc,
269 Value* root, std::string* errs) = 0;
270
271 class Factory {
272 public:
Tengiz Sharafievbe183de2015-03-14 21:30:00 +0300273 virtual ~Factory() {}
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600274 /** \brief Allocate a CharReader via operator new().
275 * \throw std::exception if something goes wrong (e.g. invalid settings)
276 */
Christopher Dunn2c1197c2015-01-29 14:29:40 -0600277 virtual CharReader* newCharReader() const = 0;
278 }; // Factory
279}; // CharReader
280
Christopher Dunn66a8ba22015-02-09 01:29:43 -0600281/** \brief Build a CharReader implementation.
282
283Usage:
284\code
285 using namespace Json;
286 CharReaderBuilder builder;
Christopher Dunnc312dd52015-03-04 14:56:37 -0600287 builder["collectComments"] = false;
Christopher Dunn66a8ba22015-02-09 01:29:43 -0600288 Value value;
289 std::string errs;
Christopher Dunn8df98f62015-02-09 11:15:39 -0600290 bool ok = parseFromStream(builder, std::cin, &value, &errs);
Christopher Dunn66a8ba22015-02-09 01:29:43 -0600291\endcode
292*/
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600293class JSON_API CharReaderBuilder : public CharReader::Factory {
Christopher Dunn66a8ba22015-02-09 01:29:43 -0600294public:
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600295 // Note: We use a Json::Value so that we can add data-members to this class
296 // without a major version bump.
297 /** Configuration of this builder.
Christopher Dunn3cf91752015-02-09 18:16:24 -0600298 These are case-sensitive.
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600299 Available settings (case-sensitive):
Christopher Dunnaa13a8b2015-02-13 09:37:39 -0600300 - `"collectComments": false or true`
Christopher Dunn29501c42015-02-10 23:03:27 -0600301 - true to collect comment and allow writing them
302 back during serialization, false to discard comments.
303 This parameter is ignored if allowComments is false.
Christopher Dunnaa13a8b2015-02-13 09:37:39 -0600304 - `"allowComments": false or true`
Christopher Dunn29501c42015-02-10 23:03:27 -0600305 - true if comments are allowed.
Christopher Dunnaa13a8b2015-02-13 09:37:39 -0600306 - `"strictRoot": false or true`
Christopher Dunn29501c42015-02-10 23:03:27 -0600307 - true if root must be either an array or an object value
Christopher Dunnaa13a8b2015-02-13 09:37:39 -0600308 - `"allowDroppedNullPlaceholders": false or true`
Christopher Dunn29501c42015-02-10 23:03:27 -0600309 - true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
Christopher Dunnaa13a8b2015-02-13 09:37:39 -0600310 - `"allowNumericKeys": false or true`
Christopher Dunn29501c42015-02-10 23:03:27 -0600311 - true if numeric object keys are allowed.
Christopher Dunn0c66e692015-02-23 15:55:12 -0600312 - `"allowSingleQuotes": false or true`
313 - true if '' are allowed for strings (both keys and values)
Christopher Dunnaa13a8b2015-02-13 09:37:39 -0600314 - `"stackLimit": integer`
315 - Exceeding stackLimit (recursive depth of `readValue()`) will
316 cause an exception.
Christopher Dunn249ad9f2015-02-10 12:16:03 -0600317 - This is a security issue (seg-faults caused by deeply nested JSON),
318 so the default is low.
Christopher Dunnf4be8152015-02-12 12:34:23 -0600319 - `"failIfExtra": false or true`
320 - If true, `parse()` returns false when extra non-whitespace trails
321 the JSON value in the input string.
Christopher Dunn527332d2015-03-06 12:18:59 -0600322 - `"rejectDupKeys": false or true`
323 - If true, `parse()` returns false when a key is duplicated within an object.
drgler20845632015-09-03 22:19:22 +0200324 - `"allowSpecialFloats": false or true`
325 - If true, special float values (NaNs and infinities) are allowed
326 and their values are lossfree restorable.
Christopher Dunnf757c182015-02-09 18:24:56 -0600327
Christopher Dunn3cf91752015-02-09 18:16:24 -0600328 You can examine 'settings_` yourself
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600329 to see the defaults. You can also write and read them just like any
330 JSON Value.
Christopher Dunnf757c182015-02-09 18:24:56 -0600331 \sa setDefaults()
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600332 */
333 Json::Value settings_;
Christopher Dunn66a8ba22015-02-09 01:29:43 -0600334
Christopher Dunn2c1197c2015-01-29 14:29:40 -0600335 CharReaderBuilder();
Christopher Dunn66a8ba22015-02-09 01:29:43 -0600336 virtual ~CharReaderBuilder();
Christopher Dunn2c1197c2015-01-29 14:29:40 -0600337
338 virtual CharReader* newCharReader() const;
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600339
Christopher Dunnf757c182015-02-09 18:24:56 -0600340 /** \return true if 'settings' are legal and consistent;
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600341 * otherwise, indicate bad settings via 'invalid'.
342 */
343 bool validate(Json::Value* invalid) const;
Christopher Dunnc312dd52015-03-04 14:56:37 -0600344
345 /** A simple way to update a specific setting.
346 */
347 Value& operator[](std::string key);
348
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600349 /** Called by ctor, but you can use this to reset settings_.
350 * \pre 'settings' != NULL (but Json::null is fine)
Christopher Dunn3cf91752015-02-09 18:16:24 -0600351 * \remark Defaults:
Christopher Dunn56650e82015-04-20 13:10:31 -0700352 * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
Christopher Dunna9e1ab32015-02-09 17:22:28 -0600353 */
354 static void setDefaults(Json::Value* settings);
Christopher Dunn3cf91752015-02-09 18:16:24 -0600355 /** Same as old Features::strictMode().
356 * \pre 'settings' != NULL (but Json::null is fine)
357 * \remark Defaults:
Christopher Dunn56650e82015-04-20 13:10:31 -0700358 * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
Christopher Dunn3cf91752015-02-09 18:16:24 -0600359 */
360 static void strictMode(Json::Value* settings);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000361};
362
Christopher Dunn2c1197c2015-01-29 14:29:40 -0600363/** Consume entire stream and use its begin/end.
364 * Someday we might have a real StreamReader, but for now this
365 * is convenient.
366 */
Christopher Dunneaa3fd82015-03-05 10:11:43 -0600367bool JSON_API parseFromStream(
Christopher Dunn2c1197c2015-01-29 14:29:40 -0600368 CharReader::Factory const&,
369 std::istream&,
370 Value* root, std::string* errs);
371
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000372/** \brief Read from 'sin' into 'root'.
373
374 Always keep comments from the input JSON.
375
376 This can be used to read a file into a particular sub-object.
377 For example:
378 \code
379 Json::Value root;
380 cin >> root["dir"]["file"];
381 cout << root;
382 \endcode
383 Result:
384 \verbatim
385 {
386 "dir": {
387 "file": {
388 // The input stream JSON would be nested here.
389 }
390 }
391 }
392 \endverbatim
393 \throw std::exception on parse error.
394 \see Json::operator<<()
395*/
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000396JSON_API std::istream& operator>>(std::istream&, Value&);
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000397
398} // namespace Json
399
Baptiste Lepilleureafd7022013-05-08 20:21:11 +0000400#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000401#pragma warning(pop)
Baptiste Lepilleureafd7022013-05-08 20:21:11 +0000402#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
403
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000404#endif // CPPTL_JSON_READER_H_INCLUDED