Free Electron
reader.h
1 // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
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 
6 #ifndef JSON_READER_H_INCLUDED
7 #define JSON_READER_H_INCLUDED
8 
9 #if !defined(JSON_IS_AMALGAMATION)
10 #include "json_features.h"
11 #include "value.h"
12 #endif // if !defined(JSON_IS_AMALGAMATION)
13 #include <deque>
14 #include <iosfwd>
15 #include <istream>
16 #include <stack>
17 #include <string>
18 
19 // Disable warning C4251: <data member>: <type> needs to have dll-interface to
20 // be used by...
21 #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
22 #pragma warning(push)
23 #pragma warning(disable : 4251)
24 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
25 
26 #pragma pack(push)
27 #pragma pack()
28 
29 namespace Json {
30 
31 /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
32  * Value.
33  *
34  * \deprecated Use CharReader and CharReaderBuilder.
35  */
36 
37 class JSON_API Reader {
38 public:
39  using Char = char;
40  using Location = const Char*;
41 
42  /** \brief An error tagged with where in the JSON text it was encountered.
43  *
44  * The offsets give the [start, limit) range of bytes within the text. Note
45  * that this is bytes, not codepoints.
46  */
47  struct StructuredError {
48  ptrdiff_t offset_start;
49  ptrdiff_t offset_limit;
50  String message;
51  };
52 
53  /** \brief Constructs a Reader allowing all features for parsing.
54  * \deprecated Use CharReader and CharReaderBuilder.
55  */
56  Reader();
57 
58  /** \brief Constructs a Reader allowing the specified feature set for parsing.
59  * \deprecated Use CharReader and CharReaderBuilder.
60  */
61  Reader(const Features& features);
62 
63  /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
64  * document.
65  *
66  * \param document UTF-8 encoded string containing the document
67  * to read.
68  * \param[out] root Contains the root value of the document if it
69  * was successfully parsed.
70  * \param collectComments \c true to collect comment and allow writing
71  * them back during serialization, \c false to
72  * discard comments. This parameter is ignored
73  * if Features::allowComments_ is \c false.
74  * \return \c true if the document was successfully parsed, \c false if an
75  * error occurred.
76  */
77  bool parse(const std::string& document, Value& root,
78  bool collectComments = true);
79 
80  /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
81  * document.
82  *
83  * \param beginDoc Pointer on the beginning of the UTF-8 encoded
84  * string of the document to read.
85  * \param endDoc Pointer on the end of the UTF-8 encoded string
86  * of the document to read. Must be >= beginDoc.
87  * \param[out] root Contains the root value of the document if it
88  * was successfully parsed.
89  * \param collectComments \c true to collect comment and allow writing
90  * them back during serialization, \c false to
91  * discard comments. This parameter is ignored
92  * if Features::allowComments_ is \c false.
93  * \return \c true if the document was successfully parsed, \c false if an
94  * error occurred.
95  */
96  bool parse(const char* beginDoc, const char* endDoc, Value& root,
97  bool collectComments = true);
98 
99  /// \brief Parse from input stream.
100  /// \see Json::operator>>(std::istream&, Json::Value&).
101  bool parse(IStream& is, Value& root, bool collectComments = true);
102 
103  /** \brief Returns a user friendly string that list errors in the parsed
104  * document.
105  *
106  * \return Formatted error message with the list of errors with their
107  * location in the parsed document. An empty string is returned if no error
108  * occurred during parsing.
109  * \deprecated Use getFormattedErrorMessages() instead (typo fix).
110  */
111  JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
112  String getFormatedErrorMessages() const;
113 
114  /** \brief Returns a user friendly string that list errors in the parsed
115  * document.
116  *
117  * \return Formatted error message with the list of errors with their
118  * location in the parsed document. An empty string is returned if no error
119  * occurred during parsing.
120  */
121  String getFormattedErrorMessages() const;
122 
123  /** \brief Returns a vector of structured errors encountered while parsing.
124  *
125  * \return A (possibly empty) vector of StructuredError objects. Currently
126  * only one error can be returned, but the caller should tolerate multiple
127  * errors. This can occur if the parser recovers from a non-fatal parse
128  * error and then encounters additional errors.
129  */
130  std::vector<StructuredError> getStructuredErrors() const;
131 
132  /** \brief Add a semantic error message.
133  *
134  * \param value JSON Value location associated with the error
135  * \param message The error message.
136  * \return \c true if the error was successfully added, \c false if the Value
137  * offset exceeds the document size.
138  */
139  bool pushError(const Value& value, const String& message);
140 
141  /** \brief Add a semantic error message with extra context.
142  *
143  * \param value JSON Value location associated with the error
144  * \param message The error message.
145  * \param extra Additional JSON Value location to contextualize the error
146  * \return \c true if the error was successfully added, \c false if either
147  * Value offset exceeds the document size.
148  */
149  bool pushError(const Value& value, const String& message, const Value& extra);
150 
151  /** \brief Return whether there are any errors.
152  *
153  * \return \c true if there are no errors to report \c false if errors have
154  * occurred.
155  */
156  bool good() const;
157 
158 private:
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  String message_;
187  Location extra_;
188  };
189 
190  using Errors = std::deque<ErrorInfo>;
191 
192  bool readToken(Token& token);
193  void skipSpaces();
194  bool match(const Char* pattern, int patternLength);
195  bool readComment();
196  bool readCStyleComment();
197  bool readCppStyleComment();
198  bool readString();
199  void readNumber();
200  bool readValue();
201  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, String& decoded);
207  bool decodeDouble(Token& token);
208  bool decodeDouble(Token& token, Value& decoded);
209  bool decodeUnicodeCodePoint(Token& token, Location& current, Location end,
210  unsigned int& unicode);
211  bool decodeUnicodeEscapeSequence(Token& token, Location& current,
212  Location end, unsigned int& unicode);
213  bool addError(const String& message, Token& token, Location extra = nullptr);
214  bool recoverFromError(TokenType skipUntilToken);
215  bool addErrorAndRecover(const String& message, Token& token,
216  TokenType skipUntilToken);
217  void skipUntilSpace();
218  Value& currentValue();
219  Char getNextChar();
220  void getLocationLineAndColumn(Location location, int& line,
221  int& column) const;
222  String getLocationLineAndColumn(Location location) const;
223  void addComment(Location begin, Location end, CommentPlacement placement);
224  void skipCommentTokens(Token& token);
225 
226  static bool containsNewLine(Location begin, Location end);
227  static String normalizeEOL(Location begin, Location end);
228 
229  using Nodes = std::stack<Value*>;
230  Nodes nodes_;
231  Errors errors_;
232  String document_;
233  Location begin_{};
234  Location end_{};
235  Location current_{};
236  Location lastValueEnd_{};
237  Value* lastValue_{};
238  String commentsBefore_;
239  Features features_;
240  bool collectComments_{};
241 }; // Reader
242 
243 /** Interface for reading JSON from a char array.
244  */
245 class JSON_API CharReader {
246 public:
247  virtual ~CharReader() = default;
248  /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
249  * document. The document must be a UTF-8 encoded string containing the
250  * document to read.
251  *
252  * \param beginDoc Pointer on the beginning of the UTF-8 encoded string
253  * of the document to read.
254  * \param endDoc Pointer on the end of the UTF-8 encoded string of the
255  * document to read. Must be >= beginDoc.
256  * \param[out] root Contains the root value of the document if it was
257  * successfully parsed.
258  * \param[out] errs Formatted error messages (if not NULL) a user
259  * friendly string that lists errors in the parsed
260  * document.
261  * \return \c true if the document was successfully parsed, \c false if an
262  * error occurred.
263  */
264  virtual bool parse(char const* beginDoc, char const* endDoc, Value* root,
265  String* errs) = 0;
266 
267  class JSON_API Factory {
268  public:
269  virtual ~Factory() = default;
270  /** \brief Allocate a CharReader via operator new().
271  * \throw std::exception if something goes wrong (e.g. invalid settings)
272  */
273  virtual CharReader* newCharReader() const = 0;
274  }; // Factory
275 }; // CharReader
276 
277 /** \brief Build a CharReader implementation.
278  *
279  * Usage:
280  * \code
281  * using namespace Json;
282  * CharReaderBuilder builder;
283  * builder["collectComments"] = false;
284  * Value value;
285  * String errs;
286  * bool ok = parseFromStream(builder, std::cin, &value, &errs);
287  * \endcode
288  */
289 class JSON_API CharReaderBuilder : public CharReader::Factory {
290 public:
291  // Note: We use a Json::Value so that we can add data-members to this class
292  // without a major version bump.
293  /** Configuration of this builder.
294  * These are case-sensitive.
295  * Available settings (case-sensitive):
296  * - `"collectComments": false or true`
297  * - true to collect comment and allow writing them back during
298  * serialization, false to discard comments. This parameter is ignored
299  * if allowComments is false.
300  * - `"allowComments": false or true`
301  * - true if comments are allowed.
302  * - `"allowTrailingCommas": false or true`
303  * - true if trailing commas in objects and arrays are allowed.
304  * - `"strictRoot": false or true`
305  * - true if root must be either an array or an object value
306  * - `"allowDroppedNullPlaceholders": false or true`
307  * - true if dropped null placeholders are allowed. (See
308  * StreamWriterBuilder.)
309  * - `"allowNumericKeys": false or true`
310  * - true if numeric object keys are allowed.
311  * - `"allowSingleQuotes": false or true`
312  * - true if '' are allowed for strings (both keys and values)
313  * - `"stackLimit": integer`
314  * - Exceeding stackLimit (recursive depth of `readValue()`) will cause an
315  * exception.
316  * - This is a security issue (seg-faults caused by deeply nested JSON), so
317  * the default is low.
318  * - `"failIfExtra": false or true`
319  * - If true, `parse()` returns false when extra non-whitespace trails the
320  * JSON value in the input string.
321  * - `"rejectDupKeys": false or true`
322  * - If true, `parse()` returns false when a key is duplicated within an
323  * object.
324  * - `"allowSpecialFloats": false or true`
325  * - If true, special float values (NaNs and infinities) are allowed and
326  * their values are lossfree restorable.
327  * - `"skipBom": false or true`
328  * - If true, if the input starts with the Unicode byte order mark (BOM),
329  * it is skipped.
330  *
331  * You can examine 'settings_` yourself to see the defaults. You can also
332  * write and read them just like any JSON Value.
333  * \sa setDefaults()
334  */
336 
338  ~CharReaderBuilder() override;
339 
340  CharReader* newCharReader() const override;
341 
342  /** \return true if 'settings' are legal and consistent;
343  * otherwise, indicate bad settings via 'invalid'.
344  */
345  bool validate(Json::Value* invalid) const;
346 
347  /** A simple way to update a specific setting.
348  */
349  Value& operator[](const String& key);
350 
351  /** Called by ctor, but you can use this to reset settings_.
352  * \pre 'settings' != NULL (but Json::null is fine)
353  * \remark Defaults:
354  * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
355  */
356  static void setDefaults(Json::Value* settings);
357  /** Same as old Features::strictMode().
358  * \pre 'settings' != NULL (but Json::null is fine)
359  * \remark Defaults:
360  * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
361  */
362  static void strictMode(Json::Value* settings);
363 };
364 
365 /** Consume entire stream and use its begin/end.
366  * Someday we might have a real StreamReader, but for now this
367  * is convenient.
368  */
369 bool JSON_API parseFromStream(CharReader::Factory const&, IStream&, Value* root,
370  String* errs);
371 
372 /** \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  */
396 JSON_API IStream& operator>>(IStream&, Value&);
397 
398 } // namespace Json
399 
400 #pragma pack(pop)
401 
402 #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
403 #pragma warning(pop)
404 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
405 
406 #endif // JSON_READER_H_INCLUDED
Json::Value settings_
Configuration of this builder.
Definition: reader.h:335
Represents a JSON value.
Definition: value.h:194
Configuration passed to reader and writer.
Definition: json_features.h:22
JSON_API IStream & operator>>(IStream &, Value &)
Read from &#39;sin&#39; into &#39;root&#39;.
An error tagged with where in the JSON text it was encountered.
Definition: reader.h:47
Build a CharReader implementation.
Definition: reader.h:289
JSON (JavaScript Object Notation).
Definition: allocator.h:15
CommentPlacement
Definition: value.h:119
bool JSON_API parseFromStream(CharReader::Factory const &, IStream &, Value *root, String *errs)
Consume entire stream and use its begin/end.
Unserialize a JSON document into a Value.
Definition: reader.h:37
Interface for reading JSON from a char array.
Definition: reader.h:245