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