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