blob: 98814d50e294f00a79a5a04324e82fbe01ac4f0b [file] [log] [blame]
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001// 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
6#ifndef CPPTL_JSON_READER_H_INCLUDED
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05007#define CPPTL_JSON_READER_H_INCLUDED
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04008
9#if !defined(JSON_IS_AMALGAMATION)
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050010#include "features.h"
11#include "value.h"
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040012#endif // if !defined(JSON_IS_AMALGAMATION)
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050013#include <deque>
14#include <iosfwd>
15#include <stack>
16#include <string>
17
18// Disable warning C4251: <data member>: <type> needs to have dll-interface to
19// be used by...
20#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
21#pragma warning(push)
22#pragma warning(disable : 4251)
23#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040024
25namespace Json {
26
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050027/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
28 *Value.
29 *
30 */
31class JSON_API Reader {
32public:
33 typedef char Char;
34 typedef const Char* Location;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040035
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050036 /** \brief An error tagged with where in the JSON text it was encountered.
37 *
38 * The offsets give the [start, limit) range of bytes within the text. Note
39 * that this is bytes, not codepoints.
40 *
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040041 */
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050042 struct StructuredError {
43 size_t offset_start;
44 size_t offset_limit;
45 std::string message;
46 };
47
48 /** \brief Constructs a Reader allowing all features
49 * for parsing.
50 */
51 Reader();
52
53 /** \brief Constructs a Reader allowing the specified feature set
54 * for parsing.
55 */
56 Reader(const Features& features);
57
58 /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
59 * document.
60 * \param document UTF-8 encoded string containing the document to read.
61 * \param root [out] Contains the root value of the document if it was
62 * successfully parsed.
63 * \param collectComments \c true to collect comment and allow writing them
64 * back during
65 * serialization, \c false to discard comments.
66 * This parameter is ignored if
67 * Features::allowComments_
68 * is \c false.
69 * \return \c true if the document was successfully parsed, \c false if an
70 * error occurred.
71 */
72 bool
73 parse(const std::string& document, Value& root, bool collectComments = true);
74
75 /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
76 document.
77 * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
78 document to read.
79 * \param endDoc Pointer on the end of the UTF-8 encoded string of the
80 document to read.
81 \ Must be >= beginDoc.
82 * \param root [out] Contains the root value of the document if it was
83 * successfully parsed.
84 * \param collectComments \c true to collect comment and allow writing them
85 back during
86 * serialization, \c false to discard comments.
87 * This parameter is ignored if
88 Features::allowComments_
89 * is \c false.
90 * \return \c true if the document was successfully parsed, \c false if an
91 error occurred.
92 */
93 bool parse(const char* beginDoc,
94 const char* endDoc,
95 Value& root,
96 bool collectComments = true);
97
98 /// \brief Parse from input stream.
99 /// \see Json::operator>>(std::istream&, Json::Value&).
100 bool parse(std::istream& is, Value& root, bool collectComments = true);
101
102 /** \brief Returns a user friendly string that list errors in the parsed
103 * document.
104 * \return Formatted error message with the list of errors with their location
105 * in
106 * the parsed document. An empty string is returned if no error
107 * occurred
108 * during parsing.
109 * \deprecated Use getFormattedErrorMessages() instead (typo fix).
110 */
111 JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead")
112 std::string getFormatedErrorMessages() const;
113
114 /** \brief Returns a user friendly string that list errors in the parsed
115 * document.
116 * \return Formatted error message with the list of errors with their location
117 * in
118 * the parsed document. An empty string is returned if no error
119 * occurred
120 * during parsing.
121 */
122 std::string getFormattedErrorMessages() const;
123
124 /** \brief Returns a vector of structured erros encounted while parsing.
125 * \return A (possibly empty) vector of StructuredError objects. Currently
126 * only one error can be returned, but the caller should tolerate
127 * multiple
128 * errors. This can occur if the parser recovers from a non-fatal
129 * parse error and then encounters additional errors.
130 */
131 std::vector<StructuredError> getStructuredErrors() const;
132
133 /** \brief Add a semantic error message.
134 * \param value JSON Value location associated with the error
135 * \param message The error message.
136 * \return \c true if the error was successfully added, \c false if the
137 * Value offset exceeds the document size.
138 */
139 bool pushError(const Value& value, const std::string& message);
140
141 /** \brief Add a semantic error message with extra context.
142 * \param value JSON Value location associated with the error
143 * \param message The error message.
144 * \param extra Additional JSON Value location to contextualize the error
145 * \return \c true if the error was successfully added, \c false if either
146 * Value offset exceeds the document size.
147 */
148 bool pushError(const Value& value, const std::string& message, const Value& extra);
149
150 /** \brief Return whether there are any errors.
151 * \return \c true if there are no errors to report \c false if
152 * errors have occurred.
153 */
154 bool good() const;
155
156private:
157 enum TokenType {
158 tokenEndOfStream = 0,
159 tokenObjectBegin,
160 tokenObjectEnd,
161 tokenArrayBegin,
162 tokenArrayEnd,
163 tokenString,
164 tokenNumber,
165 tokenTrue,
166 tokenFalse,
167 tokenNull,
168 tokenArraySeparator,
169 tokenMemberSeparator,
170 tokenComment,
171 tokenError
172 };
173
174 class Token {
175 public:
176 TokenType type_;
177 Location start_;
178 Location end_;
179 };
180
181 class ErrorInfo {
182 public:
183 Token token_;
184 std::string message_;
185 Location extra_;
186 };
187
188 typedef std::deque<ErrorInfo> Errors;
189
190 bool expectToken(TokenType type, Token& token, const char* message);
191 bool readToken(Token& token);
192 void skipSpaces();
193 bool match(Location pattern, int patternLength);
194 bool readComment();
195 bool readCStyleComment();
196 bool readCppStyleComment();
197 bool readString();
198 void readNumber();
199 bool readValue();
200 bool readObject(Token& token);
201 bool readArray(Token& token);
202 bool decodeNumber(Token& token);
203 bool decodeNumber(Token& token, Value& decoded);
204 bool decodeString(Token& token);
205 bool decodeString(Token& token, std::string& decoded);
206 bool decodeDouble(Token& token);
207 bool decodeDouble(Token& token, Value& decoded);
208 bool decodeUnicodeCodePoint(Token& token,
209 Location& current,
210 Location end,
211 unsigned int& unicode);
212 bool decodeUnicodeEscapeSequence(Token& token,
213 Location& current,
214 Location end,
215 unsigned int& unicode);
216 bool addError(const std::string& message, Token& token, Location extra = 0);
217 bool recoverFromError(TokenType skipUntilToken);
218 bool addErrorAndRecover(const std::string& message,
219 Token& token,
220 TokenType skipUntilToken);
221 void skipUntilSpace();
222 Value& currentValue();
223 Char getNextChar();
224 void
225 getLocationLineAndColumn(Location location, int& line, int& column) const;
226 std::string getLocationLineAndColumn(Location location) const;
227 void addComment(Location begin, Location end, CommentPlacement placement);
228 void skipCommentTokens(Token& token);
229
230 typedef std::stack<Value*> Nodes;
231 Nodes nodes_;
232 Errors errors_;
233 std::string document_;
234 Location begin_;
235 Location end_;
236 Location current_;
237 Location lastValueEnd_;
238 Value* lastValue_;
239 std::string commentsBefore_;
240 Features features_;
241 bool collectComments_;
242};
243
244/** \brief Read from 'sin' into 'root'.
245
246 Always keep comments from the input JSON.
247
248 This can be used to read a file into a particular sub-object.
249 For example:
250 \code
251 Json::Value root;
252 cin >> root["dir"]["file"];
253 cout << root;
254 \endcode
255 Result:
256 \verbatim
257 {
258 "dir": {
259 "file": {
260 // The input stream JSON would be nested here.
261 }
262 }
263 }
264 \endverbatim
265 \throw std::exception on parse error.
266 \see Json::operator<<()
267*/
268JSON_API std::istream& operator>>(std::istream&, Value&);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400269
270} // namespace Json
271
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500272#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
273#pragma warning(pop)
274#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
275
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400276#endif // CPPTL_JSON_READER_H_INCLUDED