• 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   typedef char Char;
40   typedef const Char* Location;
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   typedef std::deque<ErrorInfo> Errors;
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,
214                 Location extra = JSONCPP_NULL);
215   bool recoverFromError(TokenType skipUntilToken);
216   bool addErrorAndRecover(const String& message, Token& token,
217                           TokenType skipUntilToken);
218   void skipUntilSpace();
219   Value& currentValue();
220   Char getNextChar();
221   void getLocationLineAndColumn(Location location, int& line,
222                                 int& column) const;
223   String getLocationLineAndColumn(Location location) const;
224   void addComment(Location begin, Location end, CommentPlacement placement);
225   void skipCommentTokens(Token& token);
226 
227   static bool containsNewLine(Location begin, Location end);
228   static String normalizeEOL(Location begin, Location end);
229 
230   typedef std::stack<Value*> Nodes;
231   Nodes nodes_;
232   Errors errors_;
233   String document_;
234   Location begin_;
235   Location end_;
236   Location current_;
237   Location lastValueEnd_;
238   Value* lastValue_;
239   String commentsBefore_;
240   Features features_;
241   bool collectComments_;
242 }; // Reader
243 
244 /** Interface for reading JSON from a char array.
245  */
246 class JSON_API CharReader {
247 public:
~CharReader()248   virtual ~CharReader() {}
249   /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
250    * document. The document must be a UTF-8 encoded string containing the
251    * document to read.
252    *
253    * \param      beginDoc Pointer on the beginning of the UTF-8 encoded string
254    *                      of the document to read.
255    * \param      endDoc   Pointer on the end of the UTF-8 encoded string of the
256    *                      document to read. Must be >= beginDoc.
257    * \param[out] root     Contains the root value of the document if it was
258    *                      successfully parsed.
259    * \param[out] errs     Formatted error messages (if not NULL) a user
260    *                      friendly string that lists errors in the parsed
261    *                      document.
262    * \return \c true if the document was successfully parsed, \c false if an
263    * error occurred.
264    */
265   virtual bool parse(char const* beginDoc, char const* endDoc, Value* root,
266                      String* errs) = 0;
267 
268   class JSON_API Factory {
269   public:
~Factory()270     virtual ~Factory() {}
271     /** \brief Allocate a CharReader via operator new().
272      * \throw std::exception if something goes wrong (e.g. invalid settings)
273      */
274     virtual CharReader* newCharReader() const = 0;
275   }; // Factory
276 };   // CharReader
277 
278 /** \brief Build a CharReader implementation.
279  *
280  * Usage:
281  *   \code
282  *   using namespace Json;
283  *   CharReaderBuilder builder;
284  *   builder["collectComments"] = false;
285  *   Value value;
286  *   String errs;
287  *   bool ok = parseFromStream(builder, std::cin, &value, &errs);
288  *   \endcode
289  */
290 class JSON_API CharReaderBuilder : public CharReader::Factory {
291 public:
292   // Note: We use a Json::Value so that we can add data-members to this class
293   // without a major version bump.
294   /** Configuration of this builder.
295    * These are case-sensitive.
296    * Available settings (case-sensitive):
297    * - `"collectComments": false or true`
298    *   - true to collect comment and allow writing them back during
299    *     serialization, false to discard comments.  This parameter is ignored
300    *     if allowComments is false.
301    * - `"allowComments": false or true`
302    *   - true if comments are allowed.
303    * - `"allowTrailingCommas": false or true`
304    *   - true if trailing commas in objects and arrays are allowed.
305    * - `"strictRoot": false or true`
306    *   - true if root must be either an array or an object value
307    * - `"allowDroppedNullPlaceholders": false or true`
308    *   - true if dropped null placeholders are allowed. (See
309    *     StreamWriterBuilder.)
310    * - `"allowNumericKeys": false or true`
311    *   - true if numeric object keys are allowed.
312    * - `"allowSingleQuotes": false or true`
313    *   - true if '' are allowed for strings (both keys and values)
314    * - `"stackLimit": integer`
315    *   - Exceeding stackLimit (recursive depth of `readValue()`) will cause an
316    *     exception.
317    *   - This is a security issue (seg-faults caused by deeply nested JSON), so
318    *     the default is low.
319    * - `"failIfExtra": false or true`
320    *   - If true, `parse()` returns false when extra non-whitespace trails the
321    *     JSON value in the input string.
322    * - `"rejectDupKeys": false or true`
323    *   - If true, `parse()` returns false when a key is duplicated within an
324    *     object.
325    * - `"allowSpecialFloats": false or true`
326    *   - If true, special float values (NaNs and infinities) are allowed and
327    *     their values are lossfree restorable.
328    *
329    * You can examine 'settings_` yourself to see the defaults. You can also
330    * write and read them just like any JSON Value.
331    * \sa setDefaults()
332    */
333   Json::Value settings_;
334 
335   CharReaderBuilder();
336   ~CharReaderBuilder() JSONCPP_OVERRIDE;
337 
338   CharReader* newCharReader() const JSONCPP_OVERRIDE;
339 
340   /** \return true if 'settings' are legal and consistent;
341    *   otherwise, indicate bad settings via 'invalid'.
342    */
343   bool validate(Json::Value* invalid) const;
344 
345   /** A simple way to update a specific setting.
346    */
347   Value& operator[](const String& key);
348 
349   /** Called by ctor, but you can use this to reset settings_.
350    * \pre 'settings' != NULL (but Json::null is fine)
351    * \remark Defaults:
352    * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
353    */
354   static void setDefaults(Json::Value* settings);
355   /** Same as old Features::strictMode().
356    * \pre 'settings' != NULL (but Json::null is fine)
357    * \remark Defaults:
358    * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
359    */
360   static void strictMode(Json::Value* settings);
361 };
362 
363 /** Consume entire stream and use its begin/end.
364  * Someday we might have a real StreamReader, but for now this
365  * is convenient.
366  */
367 bool JSON_API parseFromStream(CharReader::Factory const&, IStream&, Value* root,
368                               String* errs);
369 
370 /** \brief Read from 'sin' into 'root'.
371  *
372  * Always keep comments from the input JSON.
373  *
374  * This can be used to read a file into a particular sub-object.
375  * For example:
376  *   \code
377  *   Json::Value root;
378  *   cin >> root["dir"]["file"];
379  *   cout << root;
380  *   \endcode
381  * Result:
382  * \verbatim
383  * {
384  * "dir": {
385  *    "file": {
386  *    // The input stream JSON would be nested here.
387  *    }
388  * }
389  * }
390  * \endverbatim
391  * \throw std::exception on parse error.
392  * \see Json::operator<<()
393  */
394 JSON_API IStream& operator>>(IStream&, Value&);
395 
396 } // namespace Json
397 
398 #pragma pack(pop)
399 
400 #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
401 #pragma warning(pop)
402 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
403 
404 #endif // JSON_READER_H_INCLUDED
405