Coverage Report

Created: 2018-09-25 14:53

/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