• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, 8)
27 
28 namespace Json {
29 
30 /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
31  * Value.
32  *
33  * \deprecated Use CharReader and CharReaderBuilder.
34  */
35 
36 class JSONCPP_DEPRECATED(
37     "Use CharReader and CharReaderBuilder instead.") 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    */
55   JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead")
56   Reader();
57 
58   /** \brief Constructs a Reader allowing the specified feature set for parsing.
59    */
60   JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead")
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    *
328    * You can examine 'settings_` yourself to see the defaults. You can also
329    * write and read them just like any JSON Value.
330    * \sa setDefaults()
331    */
332   Json::Value settings_;
333 
334   CharReaderBuilder();
335   ~CharReaderBuilder() override;
336 
337   CharReader* newCharReader() const override;
338 
339   /** \return true if 'settings' are legal and consistent;
340    *   otherwise, indicate bad settings via 'invalid'.
341    */
342   bool validate(Json::Value* invalid) const;
343 
344   /** A simple way to update a specific setting.
345    */
346   Value& operator[](const String& key);
347 
348   /** Called by ctor, but you can use this to reset settings_.
349    * \pre 'settings' != NULL (but Json::null is fine)
350    * \remark Defaults:
351    * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
352    */
353   static void setDefaults(Json::Value* settings);
354   /** Same as old Features::strictMode().
355    * \pre 'settings' != NULL (but Json::null is fine)
356    * \remark Defaults:
357    * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
358    */
359   static void strictMode(Json::Value* settings);
360 };
361 
362 /** Consume entire stream and use its begin/end.
363  * Someday we might have a real StreamReader, but for now this
364  * is convenient.
365  */
366 bool JSON_API parseFromStream(CharReader::Factory const&, IStream&, Value* root,
367                               String* errs);
368 
369 /** \brief Read from 'sin' into 'root'.
370  *
371  * Always keep comments from the input JSON.
372  *
373  * This can be used to read a file into a particular sub-object.
374  * For example:
375  *   \code
376  *   Json::Value root;
377  *   cin >> root["dir"]["file"];
378  *   cout << root;
379  *   \endcode
380  * Result:
381  * \verbatim
382  * {
383  * "dir": {
384  *    "file": {
385  *    // The input stream JSON would be nested here.
386  *    }
387  * }
388  * }
389  * \endverbatim
390  * \throw std::exception on parse error.
391  * \see Json::operator<<()
392  */
393 JSON_API IStream& operator>>(IStream&, Value&);
394 
395 } // namespace Json
396 
397 #pragma pack(pop)
398 
399 #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
400 #pragma warning(pop)
401 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
402 
403 #endif // JSON_READER_H_INCLUDED
404