JsonCpp源码阅读(一)——Reader类
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 <a HREF="http://www.json.org">JSON</a> 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 <a HREF="http://www.json.org">JSON</a> 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<ErrorInfo> 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 ¤t, Location end, unsigned int &unicode ); bool decodeUnicodeEscapeSequence( Token &token, Location ¤t, 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 ¤tValue(); 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<Value *> 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_; };
简而言之:
Reader类的对外接口只有两个构造函数:
Reader(); Reader( const Features &features );
第二个构造函数,我们在后面再进行分析。
三个解析重载的解析函数:
bool parse( const std::string &document, Value &root, bool collectComments = true ); bool parse( const char *beginDoc, const char *endDoc, Value &root, bool collectComments = true ); bool parse( std::istream &is, Value &root, bool collectComments = true );
一个获取错误信息函数:
std::string getFormatedErrorMessages() const;
这些是Reader类的对外接口。接着我们看是如何实现的,从它的简单的私有函数开始:
void Reader::skipSpaces() { while ( current_ != end_ ) { Char c = *current_; if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ) ++current_; else break; } }
void skipSpaces(); 该函数是跳过开通所有空格,'\t','\r'和'\n'字符。使用的是私有成员变量:
Location begin_;
Location end_;
Location current_;
Location lastValueEnd_;
其中的Location类型是const char *类型的指针,从typedef char Char;和typedef const Char *Location;这知道。
Reader::Char Reader::getNextChar() { if ( current_ == end_ ) return 0; return *current_++; }
这里的getNextChar(),是获取到当前字符,然后 current_指针往后移动一次。这里感觉这个函数名和函数的行为不符合啊,大家有什么见解可以提出了,有可能是我的疏漏。
未完待续...
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步