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