Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmjsoncpp/include/json/reader.h
3156 views
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
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
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
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
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
442
443