/src/mozilla-central/toolkit/components/jsoncpp/include/json/reader.h
Line | Count | Source (jump to first uncovered line) |
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 | | 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 | | 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 | | 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 | | 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 | | 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 |