blob: e99dbc0c70cdf0831808ee2aeee93f85d1290cc4 [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
Aaron Jacobs9fa4e842014-07-01 08:48:54 +10007#define CPPTL_JSON_READER_H_INCLUDED
Christopher Dunn6d135cb2007-06-13 15:51:04 +00008
Baptiste Lepilleureadc4782011-05-02 21:09:30 +00009#if !defined(JSON_IS_AMALGAMATION)
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100010#include "features.h"
11#include "value.h"
Baptiste Lepilleureadc4782011-05-02 21:09:30 +000012#endif // if !defined(JSON_IS_AMALGAMATION)
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100013#include <deque>
14#include <iosfwd>
15#include <stack>
16#include <string>
Christopher Dunn6d135cb2007-06-13 15:51:04 +000017
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100018// Disable warning C4251: <data member>: <type> needs to have dll-interface to
19// be used by...
Baptiste Lepilleureafd7022013-05-08 20:21:11 +000020#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100021#pragma warning(push)
22#pragma warning(disable : 4251)
Baptiste Lepilleureafd7022013-05-08 20:21:11 +000023#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
24
Christopher Dunn6d135cb2007-06-13 15:51:04 +000025namespace Json {
26
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100027/** \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;
Aaron Jacobs11086dd2014-09-15 10:15:29 +100034 typedef const Char* Location;
Christopher Dunn6d135cb2007-06-13 15:51:04 +000035
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100036 /** \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 *
Christopher Dunn6d135cb2007-06-13 15:51:04 +000041 */
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100042 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 */
Aaron Jacobs11086dd2014-09-15 10:15:29 +100056 Reader(const Features& features);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100057
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
Aaron Jacobs11086dd2014-09-15 10:15:29 +100073 parse(const std::string& document, Value& root, bool collectComments = true);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100074
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 */
Aaron Jacobs11086dd2014-09-15 10:15:29 +100093 bool parse(const char* beginDoc,
94 const char* endDoc,
95 Value& root,
Aaron Jacobs9fa4e842014-07-01 08:48:54 +100096 bool collectComments = true);
97
98 /// \brief Parse from input stream.
99 /// \see Json::operator>>(std::istream&, Json::Value&).
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000100 bool parse(std::istream& is, Value& root, bool collectComments = true);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000101
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
133private:
134 enum TokenType {
135 tokenEndOfStream = 0,
136 tokenObjectBegin,
137 tokenObjectEnd,
138 tokenArrayBegin,
139 tokenArrayEnd,
140 tokenString,
141 tokenNumber,
142 tokenTrue,
143 tokenFalse,
144 tokenNull,
145 tokenArraySeparator,
146 tokenMemberSeparator,
147 tokenComment,
148 tokenError
149 };
150
151 class Token {
152 public:
153 TokenType type_;
154 Location start_;
155 Location end_;
156 };
157
158 class ErrorInfo {
159 public:
160 Token token_;
161 std::string message_;
162 Location extra_;
163 };
164
165 typedef std::deque<ErrorInfo> Errors;
166
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000167 bool expectToken(TokenType type, Token& token, const char* message);
168 bool readToken(Token& token);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000169 void skipSpaces();
170 bool match(Location pattern, int patternLength);
171 bool readComment();
172 bool readCStyleComment();
173 bool readCppStyleComment();
174 bool readString();
175 void readNumber();
176 bool readValue();
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000177 bool readObject(Token& token);
178 bool readArray(Token& token);
179 bool decodeNumber(Token& token);
180 bool decodeNumber(Token& token, Value& decoded);
181 bool decodeString(Token& token);
182 bool decodeString(Token& token, std::string& decoded);
183 bool decodeDouble(Token& token);
184 bool decodeDouble(Token& token, Value& decoded);
185 bool decodeUnicodeCodePoint(Token& token,
186 Location& current,
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000187 Location end,
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000188 unsigned int& unicode);
189 bool decodeUnicodeEscapeSequence(Token& token,
190 Location& current,
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000191 Location end,
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000192 unsigned int& unicode);
193 bool addError(const std::string& message, Token& token, Location extra = 0);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000194 bool recoverFromError(TokenType skipUntilToken);
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000195 bool addErrorAndRecover(const std::string& message,
196 Token& token,
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000197 TokenType skipUntilToken);
198 void skipUntilSpace();
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000199 Value& currentValue();
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000200 Char getNextChar();
201 void
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000202 getLocationLineAndColumn(Location location, int& line, int& column) const;
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000203 std::string getLocationLineAndColumn(Location location) const;
204 void addComment(Location begin, Location end, CommentPlacement placement);
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000205 void skipCommentTokens(Token& token);
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000206
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000207 typedef std::stack<Value*> Nodes;
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000208 Nodes nodes_;
209 Errors errors_;
210 std::string document_;
211 Location begin_;
212 Location end_;
213 Location current_;
214 Location lastValueEnd_;
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000215 Value* lastValue_;
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000216 std::string commentsBefore_;
217 Features features_;
218 bool collectComments_;
219};
220
221/** \brief Read from 'sin' into 'root'.
222
223 Always keep comments from the input JSON.
224
225 This can be used to read a file into a particular sub-object.
226 For example:
227 \code
228 Json::Value root;
229 cin >> root["dir"]["file"];
230 cout << root;
231 \endcode
232 Result:
233 \verbatim
234 {
235 "dir": {
236 "file": {
237 // The input stream JSON would be nested here.
238 }
239 }
240 }
241 \endverbatim
242 \throw std::exception on parse error.
243 \see Json::operator<<()
244*/
Aaron Jacobs11086dd2014-09-15 10:15:29 +1000245JSON_API std::istream& operator>>(std::istream&, Value&);
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000246
247} // namespace Json
248
Baptiste Lepilleureafd7022013-05-08 20:21:11 +0000249#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
Aaron Jacobs9fa4e842014-07-01 08:48:54 +1000250#pragma warning(pop)
Baptiste Lepilleureafd7022013-05-08 20:21:11 +0000251#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
252
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000253#endif // CPPTL_JSON_READER_H_INCLUDED