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