blob: ee1d6a2444a8e92d20c98a08643b538923c0d06e [file] [log] [blame]
Christopher Dunn6d135cb2007-06-13 15:51:04 +00001#ifndef CPPTL_JSON_READER_H_INCLUDED
2# define CPPTL_JSON_READER_H_INCLUDED
3
Baptiste Lepilleur88681472009-11-18 21:38:54 +00004# include "features.h"
Christopher Dunn6d135cb2007-06-13 15:51:04 +00005# include "value.h"
6# include <deque>
7# include <stack>
8# include <string>
9# include <iostream>
10
11namespace Json {
12
Christopher Dunn6d135cb2007-06-13 15:51:04 +000013 /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value.
14 *
Christopher Dunn6d135cb2007-06-13 15:51:04 +000015 */
16 class JSON_API Reader
17 {
18 public:
19 typedef char Char;
20 typedef const Char *Location;
21
Baptiste Lepilleur88681472009-11-18 21:38:54 +000022 /** \brief Constructs a Reader allowing all features
23 * for parsing.
24 */
Christopher Dunn6d135cb2007-06-13 15:51:04 +000025 Reader();
26
Baptiste Lepilleur88681472009-11-18 21:38:54 +000027 /** \brief Constructs a Reader allowing the specified feature set
28 * for parsing.
29 */
30 Reader( const Features &features );
31
Christopher Dunn6d135cb2007-06-13 15:51:04 +000032 /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
33 * \param document UTF-8 encoded string containing the document to read.
34 * \param root [out] Contains the root value of the document if it was
35 * successfully parsed.
36 * \param collectComments \c true to collect comment and allow writing them back during
37 * serialization, \c false to discard comments.
Baptiste Lepilleur88681472009-11-18 21:38:54 +000038 * This parameter is ignored if Features::allowComments_
39 * is \c false.
Christopher Dunn6d135cb2007-06-13 15:51:04 +000040 * \return \c true if the document was successfully parsed, \c false if an error occurred.
41 */
42 bool parse( const std::string &document,
43 Value &root,
44 bool collectComments = true );
45
46 /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
47 * \param document UTF-8 encoded string containing the document to read.
48 * \param root [out] Contains the root value of the document if it was
49 * successfully parsed.
50 * \param collectComments \c true to collect comment and allow writing them back during
51 * serialization, \c false to discard comments.
Baptiste Lepilleur88681472009-11-18 21:38:54 +000052 * This parameter is ignored if Features::allowComments_
53 * is \c false.
Christopher Dunn6d135cb2007-06-13 15:51:04 +000054 * \return \c true if the document was successfully parsed, \c false if an error occurred.
55 */
56 bool parse( const char *beginDoc, const char *endDoc,
57 Value &root,
58 bool collectComments = true );
59
60 /// \brief Parse from input stream.
61 /// \see Json::operator>>(std::istream&, Json::Value&).
Baptiste Lepilleur88681472009-11-18 21:38:54 +000062 bool parse( std::istream &is,
Christopher Dunn6d135cb2007-06-13 15:51:04 +000063 Value &root,
64 bool collectComments = true );
65
66 /** \brief Returns a user friendly string that list errors in the parsed document.
67 * \return Formatted error message with the list of errors with their location in
68 * the parsed document. An empty string is returned if no error occurred
69 * during parsing.
70 */
71 std::string getFormatedErrorMessages() const;
72
73 private:
74 enum TokenType
75 {
76 tokenEndOfStream = 0,
77 tokenObjectBegin,
78 tokenObjectEnd,
79 tokenArrayBegin,
80 tokenArrayEnd,
81 tokenString,
82 tokenNumber,
83 tokenTrue,
84 tokenFalse,
85 tokenNull,
86 tokenArraySeparator,
87 tokenMemberSeparator,
88 tokenComment,
89 tokenError
90 };
91
92 class Token
93 {
94 public:
95 TokenType type_;
96 Location start_;
97 Location end_;
98 };
99
100 class ErrorInfo
101 {
102 public:
103 Token token_;
104 std::string message_;
105 Location extra_;
106 };
107
108 typedef std::deque<ErrorInfo> Errors;
109
110 bool expectToken( TokenType type, Token &token, const char *message );
111 bool readToken( Token &token );
112 void skipSpaces();
113 bool match( Location pattern,
114 int patternLength );
115 bool readComment();
116 bool readCStyleComment();
117 bool readCppStyleComment();
118 bool readString();
119 void readNumber();
120 bool readValue();
121 bool readObject( Token &token );
122 bool readArray( Token &token );
123 bool decodeNumber( Token &token );
124 bool decodeString( Token &token );
125 bool decodeString( Token &token, std::string &decoded );
126 bool decodeDouble( Token &token );
Malay Shahee4b4da2009-11-13 04:21:14 +0000127 bool decodeUnicodeCodePoint( Token &token,
128 Location &current,
129 Location end,
130 unsigned int &unicode );
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000131 bool decodeUnicodeEscapeSequence( Token &token,
132 Location &current,
133 Location end,
134 unsigned int &unicode );
135 bool addError( const std::string &message,
136 Token &token,
137 Location extra = 0 );
138 bool recoverFromError( TokenType skipUntilToken );
139 bool addErrorAndRecover( const std::string &message,
140 Token &token,
141 TokenType skipUntilToken );
142 void skipUntilSpace();
143 Value &currentValue();
144 Char getNextChar();
145 void getLocationLineAndColumn( Location location,
146 int &line,
147 int &column ) const;
148 std::string getLocationLineAndColumn( Location location ) const;
149 void addComment( Location begin,
150 Location end,
151 CommentPlacement placement );
152 void skipCommentTokens( Token &token );
153
154 typedef std::stack<Value *> Nodes;
155 Nodes nodes_;
156 Errors errors_;
157 std::string document_;
158 Location begin_;
159 Location end_;
160 Location current_;
161 Location lastValueEnd_;
162 Value *lastValue_;
163 std::string commentsBefore_;
Baptiste Lepilleur88681472009-11-18 21:38:54 +0000164 Features features_;
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000165 bool collectComments_;
166 };
167
168 /** \brief Read from 'sin' into 'root'.
169
170 Always keep comments from the input JSON.
171
172 This can be used to read a file into a particular sub-object.
173 For example:
174 \code
175 Json::Value root;
176 cin >> root["dir"]["file"];
177 cout << root;
178 \endcode
179 Result:
180 \verbatim
181 {
182 "dir": {
183 "file": {
184 // The input stream JSON would be nested here.
185 }
186 }
187 }
188 \endverbatim
189 \throw std::exception on parse error.
190 \see Json::operator<<()
191 */
192 std::istream& operator>>( std::istream&, Value& );
193
194} // namespace Json
195
196#endif // CPPTL_JSON_READER_H_INCLUDED