diff options
Diffstat (limited to 'include/json/reader.h')
-rw-r--r-- | include/json/reader.h | 177 |
1 files changed, 156 insertions, 21 deletions
diff --git a/include/json/reader.h b/include/json/reader.h index 98814d5..82859fd 100644 --- a/include/json/reader.h +++ b/include/json/reader.h @@ -1,4 +1,4 @@ -// Copyright 2007-2010 Baptiste Lepilleur +// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors // Distributed under MIT license, or public domain if desired and // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE @@ -14,6 +14,7 @@ #include <iosfwd> #include <stack> #include <string> +#include <istream> // Disable warning C4251: <data member>: <type> needs to have dll-interface to // be used by... @@ -22,13 +23,16 @@ #pragma warning(disable : 4251) #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma pack(push, 8) + namespace Json { /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a *Value. * + * \deprecated Use CharReader and CharReaderBuilder. */ -class JSON_API Reader { +class JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") JSON_API Reader { public: typedef char Char; typedef const Char* Location; @@ -40,9 +44,9 @@ public: * */ struct StructuredError { - size_t offset_start; - size_t offset_limit; - std::string message; + ptrdiff_t offset_start; + ptrdiff_t offset_limit; + JSONCPP_STRING message; }; /** \brief Constructs a Reader allowing all features @@ -78,7 +82,7 @@ public: document to read. * \param endDoc Pointer on the end of the UTF-8 encoded string of the document to read. - \ Must be >= beginDoc. + * Must be >= beginDoc. * \param root [out] Contains the root value of the document if it was * successfully parsed. * \param collectComments \c true to collect comment and allow writing them @@ -97,7 +101,7 @@ public: /// \brief Parse from input stream. /// \see Json::operator>>(std::istream&, Json::Value&). - bool parse(std::istream& is, Value& root, bool collectComments = true); + bool parse(JSONCPP_ISTREAM& is, Value& root, bool collectComments = true); /** \brief Returns a user friendly string that list errors in the parsed * document. @@ -108,8 +112,8 @@ public: * during parsing. * \deprecated Use getFormattedErrorMessages() instead (typo fix). */ - JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead") - std::string getFormatedErrorMessages() const; + JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.") + JSONCPP_STRING getFormatedErrorMessages() const; /** \brief Returns a user friendly string that list errors in the parsed * document. @@ -119,7 +123,7 @@ public: * occurred * during parsing. */ - std::string getFormattedErrorMessages() const; + JSONCPP_STRING getFormattedErrorMessages() const; /** \brief Returns a vector of structured erros encounted while parsing. * \return A (possibly empty) vector of StructuredError objects. Currently @@ -136,7 +140,7 @@ public: * \return \c true if the error was successfully added, \c false if the * Value offset exceeds the document size. */ - bool pushError(const Value& value, const std::string& message); + bool pushError(const Value& value, const JSONCPP_STRING& message); /** \brief Add a semantic error message with extra context. * \param value JSON Value location associated with the error @@ -145,7 +149,7 @@ public: * \return \c true if the error was successfully added, \c false if either * Value offset exceeds the document size. */ - bool pushError(const Value& value, const std::string& message, const Value& extra); + bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra); /** \brief Return whether there are any errors. * \return \c true if there are no errors to report \c false if @@ -181,13 +185,12 @@ private: class ErrorInfo { public: Token token_; - std::string message_; + JSONCPP_STRING message_; Location extra_; }; typedef std::deque<ErrorInfo> Errors; - bool expectToken(TokenType type, Token& token, const char* message); bool readToken(Token& token); void skipSpaces(); bool match(Location pattern, int patternLength); @@ -202,7 +205,7 @@ private: bool decodeNumber(Token& token); bool decodeNumber(Token& token, Value& decoded); bool decodeString(Token& token); - bool decodeString(Token& token, std::string& decoded); + bool decodeString(Token& token, JSONCPP_STRING& decoded); bool decodeDouble(Token& token); bool decodeDouble(Token& token, Value& decoded); bool decodeUnicodeCodePoint(Token& token, @@ -213,9 +216,9 @@ private: Location& current, Location end, unsigned int& unicode); - bool addError(const std::string& message, Token& token, Location extra = 0); + bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0); bool recoverFromError(TokenType skipUntilToken); - bool addErrorAndRecover(const std::string& message, + bool addErrorAndRecover(const JSONCPP_STRING& message, Token& token, TokenType skipUntilToken); void skipUntilSpace(); @@ -223,24 +226,154 @@ private: Char getNextChar(); void getLocationLineAndColumn(Location location, int& line, int& column) const; - std::string getLocationLineAndColumn(Location location) const; + JSONCPP_STRING getLocationLineAndColumn(Location location) const; void addComment(Location begin, Location end, CommentPlacement placement); void skipCommentTokens(Token& token); + static bool containsNewLine(Location begin, Location end); + static JSONCPP_STRING normalizeEOL(Location begin, Location end); + typedef std::stack<Value*> Nodes; Nodes nodes_; Errors errors_; - std::string document_; + JSONCPP_STRING document_; Location begin_; Location end_; Location current_; Location lastValueEnd_; Value* lastValue_; - std::string commentsBefore_; + JSONCPP_STRING commentsBefore_; Features features_; bool collectComments_; +}; // Reader + +/** Interface for reading JSON from a char array. + */ +class JSON_API CharReader { +public: + virtual ~CharReader() {} + /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> + document. + * The document must be a UTF-8 encoded string containing the document to read. + * + * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the + document to read. + * \param endDoc Pointer on the end of the UTF-8 encoded string of the + document to read. + * Must be >= beginDoc. + * \param root [out] Contains the root value of the document if it was + * successfully parsed. + * \param errs [out] Formatted error messages (if not NULL) + * a user friendly string that lists errors in the parsed + * document. + * \return \c true if the document was successfully parsed, \c false if an + error occurred. + */ + virtual bool parse( + char const* beginDoc, char const* endDoc, + Value* root, JSONCPP_STRING* errs) = 0; + + class JSON_API Factory { + public: + virtual ~Factory() {} + /** \brief Allocate a CharReader via operator new(). + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + virtual CharReader* newCharReader() const = 0; + }; // Factory +}; // CharReader + +/** \brief Build a CharReader implementation. + +Usage: +\code + using namespace Json; + CharReaderBuilder builder; + builder["collectComments"] = false; + Value value; + JSONCPP_STRING errs; + bool ok = parseFromStream(builder, std::cin, &value, &errs); +\endcode +*/ +class JSON_API CharReaderBuilder : public CharReader::Factory { +public: + // Note: We use a Json::Value so that we can add data-members to this class + // without a major version bump. + /** Configuration of this builder. + These are case-sensitive. + Available settings (case-sensitive): + - `"collectComments": false or true` + - true to collect comment and allow writing them + back during serialization, false to discard comments. + This parameter is ignored if allowComments is false. + - `"allowComments": false or true` + - true if comments are allowed. + - `"strictRoot": false or true` + - true if root must be either an array or an object value + - `"allowDroppedNullPlaceholders": false or true` + - true if dropped null placeholders are allowed. (See StreamWriterBuilder.) + - `"allowNumericKeys": false or true` + - true if numeric object keys are allowed. + - `"allowSingleQuotes": false or true` + - true if '' are allowed for strings (both keys and values) + - `"stackLimit": integer` + - Exceeding stackLimit (recursive depth of `readValue()`) will + cause an exception. + - This is a security issue (seg-faults caused by deeply nested JSON), + so the default is low. + - `"failIfExtra": false or true` + - If true, `parse()` returns false when extra non-whitespace trails + the JSON value in the input string. + - `"rejectDupKeys": false or true` + - If true, `parse()` returns false when a key is duplicated within an object. + - `"allowSpecialFloats": false or true` + - If true, special float values (NaNs and infinities) are allowed + and their values are lossfree restorable. + + You can examine 'settings_` yourself + to see the defaults. You can also write and read them just like any + JSON Value. + \sa setDefaults() + */ + Json::Value settings_; + + CharReaderBuilder(); + ~CharReaderBuilder() JSONCPP_OVERRIDE; + + CharReader* newCharReader() const JSONCPP_OVERRIDE; + + /** \return true if 'settings' are legal and consistent; + * otherwise, indicate bad settings via 'invalid'. + */ + bool validate(Json::Value* invalid) const; + + /** A simple way to update a specific setting. + */ + Value& operator[](JSONCPP_STRING key); + + /** Called by ctor, but you can use this to reset settings_. + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults + */ + static void setDefaults(Json::Value* settings); + /** Same as old Features::strictMode(). + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode + */ + static void strictMode(Json::Value* settings); }; +/** Consume entire stream and use its begin/end. + * Someday we might have a real StreamReader, but for now this + * is convenient. + */ +bool JSON_API parseFromStream( + CharReader::Factory const&, + JSONCPP_ISTREAM&, + Value* root, std::string* errs); + /** \brief Read from 'sin' into 'root'. Always keep comments from the input JSON. @@ -265,10 +398,12 @@ private: \throw std::exception on parse error. \see Json::operator<<() */ -JSON_API std::istream& operator>>(std::istream&, Value&); +JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&); } // namespace Json +#pragma pack(pop) + #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) #pragma warning(pop) #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) |