json test

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers reader.h Source File

reader.h

00001 // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
00002 // Distributed under MIT license, or public domain if desired and
00003 // recognized in your jurisdiction.
00004 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
00005 
00006 #ifndef CPPTL_JSON_READER_H_INCLUDED
00007 #define CPPTL_JSON_READER_H_INCLUDED
00008 
00009 #if !defined(JSON_IS_AMALGAMATION)
00010 #include "features.h"
00011 #include "value.h"
00012 #endif // if !defined(JSON_IS_AMALGAMATION)
00013 #include <deque>
00014 #include <iosfwd>
00015 #include <stack>
00016 #include <string>
00017 #include <istream>
00018 
00019 // Disable warning C4251: <data member>: <type> needs to have dll-interface to
00020 // be used by...
00021 #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
00022 #pragma warning(push)
00023 #pragma warning(disable : 4251)
00024 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
00025 
00026 #pragma pack(push, 8)
00027 
00028 namespace Json {
00029 
00030 /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
00031  *Value.
00032  *
00033  * \deprecated Use CharReader and CharReaderBuilder.
00034  */
00035 class JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") JSON_API Reader {
00036 public:
00037   typedef char Char;
00038   typedef const Char* Location;
00039 
00040   /** \brief An error tagged with where in the JSON text it was encountered.
00041    *
00042    * The offsets give the [start, limit) range of bytes within the text. Note
00043    * that this is bytes, not codepoints.
00044    *
00045    */
00046   struct StructuredError {
00047     ptrdiff_t offset_start;
00048     ptrdiff_t offset_limit;
00049     JSONCPP_STRING message;
00050   };
00051 
00052   /** \brief Constructs a Reader allowing all features
00053    * for parsing.
00054    */
00055   Reader();
00056 
00057   /** \brief Constructs a Reader allowing the specified feature set
00058    * for parsing.
00059    */
00060   Reader(const Features& features);
00061 
00062   /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
00063    * document.
00064    * \param document UTF-8 encoded string containing the document to read.
00065    * \param root [out] Contains the root value of the document if it was
00066    *             successfully parsed.
00067    * \param collectComments \c true to collect comment and allow writing them
00068    * back during
00069    *                        serialization, \c false to discard comments.
00070    *                        This parameter is ignored if
00071    * Features::allowComments_
00072    *                        is \c false.
00073    * \return \c true if the document was successfully parsed, \c false if an
00074    * error occurred.
00075    */
00076   bool
00077   parse(const std::string& document, Value& root, bool collectComments = true);
00078 
00079   /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
00080    document.
00081    * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
00082    document to read.
00083    * \param endDoc Pointer on the end of the UTF-8 encoded string of the
00084    document to read.
00085    *               Must be >= beginDoc.
00086    * \param root [out] Contains the root value of the document if it was
00087    *             successfully parsed.
00088    * \param collectComments \c true to collect comment and allow writing them
00089    back during
00090    *                        serialization, \c false to discard comments.
00091    *                        This parameter is ignored if
00092    Features::allowComments_
00093    *                        is \c false.
00094    * \return \c true if the document was successfully parsed, \c false if an
00095    error occurred.
00096    */
00097   bool parse(const char* beginDoc,
00098              const char* endDoc,
00099              Value& root,
00100              bool collectComments = true);
00101 
00102   /// \brief Parse from input stream.
00103   /// \see Json::operator>>(std::istream&, Json::Value&).
00104   bool parse(JSONCPP_ISTREAM& is, Value& root, bool collectComments = true);
00105 
00106   /** \brief Returns a user friendly string that list errors in the parsed
00107    * document.
00108    * \return Formatted error message with the list of errors with their location
00109    * in
00110    *         the parsed document. An empty string is returned if no error
00111    * occurred
00112    *         during parsing.
00113    * \deprecated Use getFormattedErrorMessages() instead (typo fix).
00114    */
00115   JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
00116   JSONCPP_STRING getFormatedErrorMessages() const;
00117 
00118   /** \brief Returns a user friendly string that list errors in the parsed
00119    * document.
00120    * \return Formatted error message with the list of errors with their location
00121    * in
00122    *         the parsed document. An empty string is returned if no error
00123    * occurred
00124    *         during parsing.
00125    */
00126   JSONCPP_STRING getFormattedErrorMessages() const;
00127 
00128   /** \brief Returns a vector of structured erros encounted while parsing.
00129    * \return A (possibly empty) vector of StructuredError objects. Currently
00130    *         only one error can be returned, but the caller should tolerate
00131    * multiple
00132    *         errors.  This can occur if the parser recovers from a non-fatal
00133    *         parse error and then encounters additional errors.
00134    */
00135   std::vector<StructuredError> getStructuredErrors() const;
00136 
00137   /** \brief Add a semantic error message.
00138    * \param value JSON Value location associated with the error
00139    * \param message The error message.
00140    * \return \c true if the error was successfully added, \c false if the
00141    * Value offset exceeds the document size.
00142    */
00143   bool pushError(const Value& value, const JSONCPP_STRING& message);
00144 
00145   /** \brief Add a semantic error message with extra context.
00146    * \param value JSON Value location associated with the error
00147    * \param message The error message.
00148    * \param extra Additional JSON Value location to contextualize the error
00149    * \return \c true if the error was successfully added, \c false if either
00150    * Value offset exceeds the document size.
00151    */
00152   bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
00153 
00154   /** \brief Return whether there are any errors.
00155    * \return \c true if there are no errors to report \c false if
00156    * errors have occurred.
00157    */
00158   bool good() const;
00159 
00160 private:
00161   enum TokenType {
00162     tokenEndOfStream = 0,
00163     tokenObjectBegin,
00164     tokenObjectEnd,
00165     tokenArrayBegin,
00166     tokenArrayEnd,
00167     tokenString,
00168     tokenNumber,
00169     tokenTrue,
00170     tokenFalse,
00171     tokenNull,
00172     tokenArraySeparator,
00173     tokenMemberSeparator,
00174     tokenComment,
00175     tokenError
00176   };
00177 
00178   class Token {
00179   public:
00180     TokenType type_;
00181     Location start_;
00182     Location end_;
00183   };
00184 
00185   class ErrorInfo {
00186   public:
00187     Token token_;
00188     JSONCPP_STRING message_;
00189     Location extra_;
00190   };
00191 
00192   typedef std::deque<ErrorInfo> Errors;
00193 
00194   bool readToken(Token& token);
00195   void skipSpaces();
00196   bool match(Location pattern, int patternLength);
00197   bool readComment();
00198   bool readCStyleComment();
00199   bool readCppStyleComment();
00200   bool readString();
00201   void readNumber();
00202   bool readValue();
00203   bool readObject(Token& token);
00204   bool readArray(Token& token);
00205   bool decodeNumber(Token& token);
00206   bool decodeNumber(Token& token, Value& decoded);
00207   bool decodeString(Token& token);
00208   bool decodeString(Token& token, JSONCPP_STRING& decoded);
00209   bool decodeDouble(Token& token);
00210   bool decodeDouble(Token& token, Value& decoded);
00211   bool decodeUnicodeCodePoint(Token& token,
00212                               Location& current,
00213                               Location end,
00214                               unsigned int& unicode);
00215   bool decodeUnicodeEscapeSequence(Token& token,
00216                                    Location& current,
00217                                    Location end,
00218                                    unsigned int& unicode);
00219   bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
00220   bool recoverFromError(TokenType skipUntilToken);
00221   bool addErrorAndRecover(const JSONCPP_STRING& message,
00222                           Token& token,
00223                           TokenType skipUntilToken);
00224   void skipUntilSpace();
00225   Value& currentValue();
00226   Char getNextChar();
00227   void
00228   getLocationLineAndColumn(Location location, int& line, int& column) const;
00229   JSONCPP_STRING getLocationLineAndColumn(Location location) const;
00230   void addComment(Location begin, Location end, CommentPlacement  placement);
00231   void skipCommentTokens(Token& token);
00232 
00233   static bool containsNewLine(Location begin, Location end);
00234   static JSONCPP_STRING normalizeEOL(Location begin, Location end);
00235 
00236   typedef std::stack<Value*> Nodes;
00237   Nodes nodes_;
00238   Errors errors_;
00239   JSONCPP_STRING document_;
00240   Location begin_;
00241   Location end_;
00242   Location current_;
00243   Location lastValueEnd_;
00244   Value* lastValue_;
00245   JSONCPP_STRING commentsBefore_;
00246   Features features_;
00247   bool collectComments_;
00248 };  // Reader
00249 
00250 /** Interface for reading JSON from a char array.
00251  */
00252 class JSON_API CharReader {
00253 public:
00254   virtual ~CharReader() {}
00255   /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
00256    document.
00257    * The document must be a UTF-8 encoded string containing the document to read.
00258    *
00259    * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
00260    document to read.
00261    * \param endDoc Pointer on the end of the UTF-8 encoded string of the
00262    document to read.
00263    *        Must be >= beginDoc.
00264    * \param root [out] Contains the root value of the document if it was
00265    *             successfully parsed.
00266    * \param errs [out] Formatted error messages (if not NULL)
00267    *        a user friendly string that lists errors in the parsed
00268    * document.
00269    * \return \c true if the document was successfully parsed, \c false if an
00270    error occurred.
00271    */
00272   virtual bool parse(
00273       char const* beginDoc, char const* endDoc,
00274       Value* root, JSONCPP_STRING* errs) = 0;
00275 
00276   class JSON_API Factory {
00277   public:
00278     virtual ~Factory() {}
00279     /** \brief Allocate a CharReader via operator new().
00280      * \throw std::exception if something goes wrong (e.g. invalid settings)
00281      */
00282     virtual CharReader* newCharReader() const = 0;
00283   };  // Factory
00284 };  // CharReader
00285 
00286 /** \brief Build a CharReader implementation.
00287 
00288 Usage:
00289 \code
00290   using namespace Json;
00291   CharReaderBuilder builder;
00292   builder["collectComments"] = false;
00293   Value value;
00294   JSONCPP_STRING errs;
00295   bool ok = parseFromStream(builder, std::cin, &value, &errs);
00296 \endcode
00297 */
00298 class JSON_API CharReaderBuilder : public CharReader::Factory {
00299 public:
00300   // Note: We use a Json::Value so that we can add data-members to this class
00301   // without a major version bump.
00302   /** Configuration of this builder.
00303     These are case-sensitive.
00304     Available settings (case-sensitive):
00305     - `"collectComments": false or true`
00306       - true to collect comment and allow writing them
00307         back during serialization, false to discard comments.
00308         This parameter is ignored if allowComments is false.
00309     - `"allowComments": false or true`
00310       - true if comments are allowed.
00311     - `"strictRoot": false or true`
00312       - true if root must be either an array or an object value
00313     - `"allowDroppedNullPlaceholders": false or true`
00314       - true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
00315     - `"allowNumericKeys": false or true`
00316       - true if numeric object keys are allowed.
00317     - `"allowSingleQuotes": false or true`
00318       - true if '' are allowed for strings (both keys and values)
00319     - `"stackLimit": integer`
00320       - Exceeding stackLimit (recursive depth of `readValue()`) will
00321         cause an exception.
00322       - This is a security issue (seg-faults caused by deeply nested JSON),
00323         so the default is low.
00324     - `"failIfExtra": false or true`
00325       - If true, `parse()` returns false when extra non-whitespace trails
00326         the JSON value in the input string.
00327     - `"rejectDupKeys": false or true`
00328       - If true, `parse()` returns false when a key is duplicated within an object.
00329     - `"allowSpecialFloats": false or true`
00330       - If true, special float values (NaNs and infinities) are allowed 
00331         and their values are lossfree restorable.
00332 
00333     You can examine 'settings_` yourself
00334     to see the defaults. You can also write and read them just like any
00335     JSON Value.
00336     \sa setDefaults()
00337     */
00338   Json::Value settings_;
00339 
00340   CharReaderBuilder();
00341   ~CharReaderBuilder() JSONCPP_OVERRIDE;
00342 
00343   CharReader* newCharReader() const JSONCPP_OVERRIDE;
00344 
00345   /** \return true if 'settings' are legal and consistent;
00346    *   otherwise, indicate bad settings via 'invalid'.
00347    */
00348   bool validate(Json::Value* invalid) const;
00349 
00350   /** A simple way to update a specific setting.
00351    */
00352   Value& operator[](JSONCPP_STRING key);
00353 
00354   /** Called by ctor, but you can use this to reset settings_.
00355    * \pre 'settings' != NULL (but Json::null is fine)
00356    * \remark Defaults:
00357    * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
00358    */
00359   static void setDefaults(Json::Value* settings);
00360   /** Same as old Features::strictMode().
00361    * \pre 'settings' != NULL (but Json::null is fine)
00362    * \remark Defaults:
00363    * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
00364    */
00365   static void strictMode(Json::Value* settings);
00366 };
00367 
00368 /** Consume entire stream and use its begin/end.
00369   * Someday we might have a real StreamReader, but for now this
00370   * is convenient.
00371   */
00372 bool JSON_API parseFromStream(
00373     CharReader::Factory const&,
00374     JSONCPP_ISTREAM&,
00375     Value* root, std::string* errs);
00376 
00377 /** \brief Read from 'sin' into 'root'.
00378 
00379  Always keep comments from the input JSON.
00380 
00381  This can be used to read a file into a particular sub-object.
00382  For example:
00383  \code
00384  Json::Value root;
00385  cin >> root["dir"]["file"];
00386  cout << root;
00387  \endcode
00388  Result:
00389  \verbatim
00390  {
00391  "dir": {
00392      "file": {
00393      // The input stream JSON would be nested here.
00394      }
00395  }
00396  }
00397  \endverbatim
00398  \throw std::exception on parse error.
00399  \see Json::operator<<()
00400 */
00401 JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&);
00402 
00403 } // namespace Json
00404 
00405 #pragma pack(pop)
00406 
00407 #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
00408 #pragma warning(pop)
00409 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
00410 
00411 #endif // CPPTL_JSON_READER_H_INCLUDED