//------------------------------------------------------------------------------ /* Copyright (c) 2011-2013, OpenCoin, Inc. */ //============================================================================== #ifndef CPPTL_JSON_READER_H_INCLUDED # define CPPTL_JSON_READER_H_INCLUDED namespace Json { /** \brief Unserialize a JSON document into a Value. * */ class JSON_API Reader { public: typedef char Char; typedef const Char* Location; /** \brief Constructs a Reader allowing all features * for parsing. */ Reader (); /** \brief Constructs a Reader allowing the specified feature set * for parsing. */ Reader ( const Features& features ); /** \brief Read a Value from a JSON document. * \param document UTF-8 encoded string containing the document to read. * \param root [out] Contains the root value of the document if it was * successfully parsed. * \param collectComments \c true to collect comment and allow writing them back during * serialization, \c false to discard comments. * This parameter is ignored if Features::allowComments_ * is \c false. * \return \c true if the document was successfully parsed, \c false if an error occurred. */ bool parse ( const std::string& document, Value& root, bool collectComments = true ); /** \brief Read a Value from a JSON document. * \param document UTF-8 encoded string containing the document to read. * \param root [out] Contains the root value of the document if it was * successfully parsed. * \param collectComments \c true to collect comment and allow writing them back during * serialization, \c false to discard comments. * This parameter is ignored if Features::allowComments_ * is \c false. * \return \c true if the document was successfully parsed, \c false if an error occurred. */ bool parse ( const char* beginDoc, const char* endDoc, Value& root, bool collectComments = true ); /// \brief Parse from input stream. /// \see Json::operator>>(std::istream&, Json::Value&). bool parse ( std::istream& is, Value& root, bool collectComments = true ); /** \brief Returns a user friendly string that list errors in the parsed document. * \return Formatted error message with the list of errors with their location in * the parsed document. An empty string is returned if no error occurred * during parsing. */ std::string getFormatedErrorMessages () const; private: enum TokenType { tokenEndOfStream = 0, tokenObjectBegin, tokenObjectEnd, tokenArrayBegin, tokenArrayEnd, tokenString, tokenNumber, tokenTrue, tokenFalse, tokenNull, tokenArraySeparator, tokenMemberSeparator, tokenComment, tokenError }; class Token { public: TokenType type_; Location start_; Location end_; }; class ErrorInfo { public: Token token_; std::string message_; Location extra_; }; typedef std::deque Errors; bool expectToken ( TokenType type, Token& token, const char* message ); bool readToken ( Token& token ); void skipSpaces (); bool match ( Location pattern, int patternLength ); bool readComment (); bool readCStyleComment (); bool readCppStyleComment (); bool readString (); void readNumber (); bool readValue (); bool readObject ( Token& token ); bool readArray ( Token& token ); bool decodeNumber ( Token& token ); bool decodeString ( Token& token ); bool decodeString ( Token& token, std::string& decoded ); bool decodeDouble ( Token& token ); bool decodeUnicodeCodePoint ( Token& token, Location& current, Location end, unsigned int& unicode ); bool decodeUnicodeEscapeSequence ( Token& token, Location& current, Location end, unsigned int& unicode ); bool addError ( const std::string& message, Token& token, Location extra = 0 ); bool recoverFromError ( TokenType skipUntilToken ); bool addErrorAndRecover ( const std::string& message, Token& token, TokenType skipUntilToken ); void skipUntilSpace (); Value& currentValue (); Char getNextChar (); void getLocationLineAndColumn ( Location location, int& line, int& column ) const; std::string getLocationLineAndColumn ( Location location ) const; void addComment ( Location begin, Location end, CommentPlacement placement ); void skipCommentTokens ( Token& token ); typedef std::stack Nodes; Nodes nodes_; Errors errors_; std::string document_; Location begin_; Location end_; Location current_; Location lastValueEnd_; Value* lastValue_; std::string commentsBefore_; Features features_; bool collectComments_; }; /** \brief Read from 'sin' into 'root'. Always keep comments from the input JSON. This can be used to read a file into a particular sub-object. For example: \code Json::Value root; cin >> root["dir"]["file"]; cout << root; \endcode Result: \verbatim { "dir": { "file": { // The input stream JSON would be nested here. } } } \endverbatim \throw std::exception on parse error. \see Json::operator<<() */ std::istream& operator>> ( std::istream&, Value& ); } // namespace Json #endif // CPPTL_JSON_READER_H_INCLUDED