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