Line data Source code
1 : // 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 :
6 : #ifndef CPPTL_JSON_READER_H_INCLUDED
7 : #define CPPTL_JSON_READER_H_INCLUDED
8 :
9 : #if !defined(JSON_IS_AMALGAMATION)
10 : #include "features.h"
11 : #include "value.h"
12 : #endif // if !defined(JSON_IS_AMALGAMATION)
13 : #include <deque>
14 : #include <iosfwd>
15 : #include <stack>
16 : #include <string>
17 : #include <istream>
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 0 : class JSON_API Reader {
36 : public:
37 : typedef char Char;
38 : typedef const Char* Location;
39 :
40 : /** \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 : *
45 : */
46 0 : struct StructuredError {
47 : ptrdiff_t offset_start;
48 : ptrdiff_t offset_limit;
49 : JSONCPP_STRING message;
50 : };
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 : */
60 : Reader(const Features& features);
61 :
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
77 : parse(const std::string& document, Value& root, bool collectComments = true);
78 :
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.
85 : * Must be >= beginDoc.
86 : * \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 : */
97 : bool parse(const char* beginDoc,
98 : const char* endDoc,
99 : Value& root,
100 : bool collectComments = true);
101 :
102 : /// \brief Parse from input stream.
103 : /// \see Json::operator>>(std::istream&, Json::Value&).
104 : bool parse(JSONCPP_ISTREAM& is, Value& root, bool collectComments = true);
105 :
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 : */
115 : JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
116 : JSONCPP_STRING getFormatedErrorMessages() const;
117 :
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 : */
126 : JSONCPP_STRING getFormattedErrorMessages() const;
127 :
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 :
137 : /** \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 : */
143 : bool pushError(const Value& value, const JSONCPP_STRING& message);
144 :
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 : */
152 : bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
153 :
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 :
160 : private:
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 0 : class ErrorInfo {
186 : public:
187 : Token token_;
188 : JSONCPP_STRING message_;
189 : Location extra_;
190 : };
191 :
192 : typedef std::deque<ErrorInfo> Errors;
193 :
194 : bool readToken(Token& token);
195 : 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();
203 : 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);
208 : bool decodeString(Token& token, JSONCPP_STRING& decoded);
209 : bool decodeDouble(Token& token);
210 : bool decodeDouble(Token& token, Value& decoded);
211 : bool decodeUnicodeCodePoint(Token& token,
212 : Location& current,
213 : Location end,
214 : unsigned int& unicode);
215 : bool decodeUnicodeEscapeSequence(Token& token,
216 : Location& current,
217 : Location end,
218 : unsigned int& unicode);
219 : bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
220 : bool recoverFromError(TokenType skipUntilToken);
221 : bool addErrorAndRecover(const JSONCPP_STRING& message,
222 : Token& token,
223 : TokenType skipUntilToken);
224 : void skipUntilSpace();
225 : Value& currentValue();
226 : Char getNextChar();
227 : void
228 : getLocationLineAndColumn(Location location, int& line, int& column) const;
229 : JSONCPP_STRING getLocationLineAndColumn(Location location) const;
230 : void addComment(Location begin, Location end, CommentPlacement placement);
231 : void skipCommentTokens(Token& token);
232 :
233 : typedef std::stack<Value*> Nodes;
234 : Nodes nodes_;
235 : Errors errors_;
236 : JSONCPP_STRING document_;
237 : Location begin_;
238 : Location end_;
239 : Location current_;
240 : Location lastValueEnd_;
241 : Value* lastValue_;
242 : JSONCPP_STRING commentsBefore_;
243 : Features features_;
244 : bool collectComments_;
245 : }; // Reader
246 :
247 : /** Interface for reading JSON from a char array.
248 : */
249 0 : class JSON_API CharReader {
250 : public:
251 0 : virtual ~CharReader() {}
252 : /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
253 : document.
254 : * The document must be a UTF-8 encoded string containing the document to read.
255 : *
256 : * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
257 : document to read.
258 : * \param endDoc Pointer on the end of the UTF-8 encoded string of the
259 : document to read.
260 : * Must be >= beginDoc.
261 : * \param root [out] Contains the root value of the document if it was
262 : * successfully parsed.
263 : * \param errs [out] Formatted error messages (if not NULL)
264 : * a user friendly string that lists errors in the parsed
265 : * document.
266 : * \return \c true if the document was successfully parsed, \c false if an
267 : error occurred.
268 : */
269 : virtual bool parse(
270 : char const* beginDoc, char const* endDoc,
271 : Value* root, JSONCPP_STRING* errs) = 0;
272 :
273 0 : class JSON_API Factory {
274 : public:
275 0 : virtual ~Factory() {}
276 : /** \brief Allocate a CharReader via operator new().
277 : * \throw std::exception if something goes wrong (e.g. invalid settings)
278 : */
279 : virtual CharReader* newCharReader() const = 0;
280 : }; // Factory
281 : }; // CharReader
282 :
283 : /** \brief Build a CharReader implementation.
284 :
285 : Usage:
286 : \code
287 : using namespace Json;
288 : CharReaderBuilder builder;
289 : builder["collectComments"] = false;
290 : Value value;
291 : JSONCPP_STRING errs;
292 : bool ok = parseFromStream(builder, std::cin, &value, &errs);
293 : \endcode
294 : */
295 : class JSON_API CharReaderBuilder : public CharReader::Factory {
296 : public:
297 : // Note: We use a Json::Value so that we can add data-members to this class
298 : // without a major version bump.
299 : /** Configuration of this builder.
300 : These are case-sensitive.
301 : Available settings (case-sensitive):
302 : - `"collectComments": false or true`
303 : - true to collect comment and allow writing them
304 : back during serialization, false to discard comments.
305 : This parameter is ignored if allowComments is false.
306 : - `"allowComments": false or true`
307 : - true if comments are allowed.
308 : - `"strictRoot": false or true`
309 : - true if root must be either an array or an object value
310 : - `"allowDroppedNullPlaceholders": false or true`
311 : - true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
312 : - `"allowNumericKeys": false or true`
313 : - true if numeric object keys are allowed.
314 : - `"allowSingleQuotes": false or true`
315 : - true if '' are allowed for strings (both keys and values)
316 : - `"stackLimit": integer`
317 : - Exceeding stackLimit (recursive depth of `readValue()`) will
318 : cause an exception.
319 : - This is a security issue (seg-faults caused by deeply nested JSON),
320 : so the default is low.
321 : - `"failIfExtra": false or true`
322 : - If true, `parse()` returns false when extra non-whitespace trails
323 : the JSON value in the input string.
324 : - `"rejectDupKeys": false or true`
325 : - If true, `parse()` returns false when a key is duplicated within an object.
326 : - `"allowSpecialFloats": false or true`
327 : - If true, special float values (NaNs and infinities) are allowed
328 : and their values are lossfree restorable.
329 :
330 : You can examine 'settings_` yourself
331 : to see the defaults. You can also write and read them just like any
332 : JSON Value.
333 : \sa setDefaults()
334 : */
335 : Json::Value settings_;
336 :
337 : CharReaderBuilder();
338 : ~CharReaderBuilder() JSONCPP_OVERRIDE;
339 :
340 : CharReader* newCharReader() const JSONCPP_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[](JSONCPP_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(
370 : CharReader::Factory const&,
371 : JSONCPP_ISTREAM&,
372 : Value* root, std::string* errs);
373 :
374 : /** \brief Read from 'sin' into 'root'.
375 :
376 : Always keep comments from the input JSON.
377 :
378 : This can be used to read a file into a particular sub-object.
379 : For example:
380 : \code
381 : Json::Value root;
382 : cin >> root["dir"]["file"];
383 : cout << root;
384 : \endcode
385 : Result:
386 : \verbatim
387 : {
388 : "dir": {
389 : "file": {
390 : // The input stream JSON would be nested here.
391 : }
392 : }
393 : }
394 : \endverbatim
395 : \throw std::exception on parse error.
396 : \see Json::operator<<()
397 : */
398 : JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&);
399 :
400 : } // namespace Json
401 :
402 : #pragma pack(pop)
403 :
404 : #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
405 : #pragma warning(pop)
406 : #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
407 :
408 : #endif // CPPTL_JSON_READER_H_INCLUDED
|