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