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