diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp
index 703a5c2..cd1b9cc 100644
--- a/src/lib_json/json_reader.cpp
+++ b/src/lib_json/json_reader.cpp
@@ -892,11 +892,225 @@ bool Reader::good() const {
return !errors_.size();
}
-class OldReader : public CharReader {
+// exact copy of Reader, renamed to OldReader
+class OldReader {
+public:
+ typedef char Char;
+ typedef const Char* Location;
+
+ /** \brief An error tagged with where in the JSON text it was encountered.
+ *
+ * The offsets give the [start, limit) range of bytes within the text. Note
+ * that this is bytes, not codepoints.
+ *
+ */
+ struct StructuredError {
+ size_t offset_start;
+ size_t offset_limit;
+ std::string message;
+ };
+
+ /** \brief Constructs a Reader allowing all features
+ * for parsing.
+ */
+ Reader();
+
+ /** \brief Constructs a Reader allowing the specified feature set
+ * for parsing.
+ */
+ Reader(const Features& features);
+
+ /** \brief Read a Value from a JSON
+ * document.
+ * \param document UTF-8 encoded string containing the document to read.
+ * \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
+ * back during
+ * serialization, \c false to discard comments.
+ * This parameter is ignored if
+ * Features::allowComments_
+ * is \c false.
+ * \return \c true if the document was successfully parsed, \c false if an
+ * error occurred.
+ */
+ bool
+ parse(const std::string& document, Value& root, bool collectComments = true);
+
+ /** \brief Read a Value from a JSON
+ document.
+ * \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 collectComments \c true to collect comment and allow writing them
+ back during
+ * serialization, \c false to discard comments.
+ * This parameter is ignored if
+ Features::allowComments_
+ * is \c false.
+ * \return \c true if the document was successfully parsed, \c false if an
+ error occurred.
+ */
+ bool parse(const char* beginDoc,
+ const char* endDoc,
+ Value& root,
+ bool collectComments = true);
+
+ /// \brief Parse from input stream.
+ /// \see Json::operator>>(std::istream&, Json::Value&).
+ bool parse(std::istream& is, Value& root, bool collectComments = true);
+
+ /** \brief Returns a user friendly string that list errors in the parsed
+ * document.
+ * \return Formatted error message with the list of errors with their location
+ * in
+ * the parsed document. An empty string is returned if no error
+ * occurred
+ * during parsing.
+ * \deprecated Use getFormattedErrorMessages() instead (typo fix).
+ */
+ JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead")
+ std::string getFormatedErrorMessages() const;
+
+ /** \brief Returns a user friendly string that list errors in the parsed
+ * document.
+ * \return Formatted error message with the list of errors with their location
+ * in
+ * the parsed document. An empty string is returned if no error
+ * occurred
+ * during parsing.
+ */
+ std::string getFormattedErrorMessages() const;
+
+ /** \brief Returns a vector of structured erros encounted while parsing.
+ * \return A (possibly empty) vector of StructuredError objects. Currently
+ * only one error can be returned, but the caller should tolerate
+ * multiple
+ * errors. This can occur if the parser recovers from a non-fatal
+ * parse error and then encounters additional errors.
+ */
+ std::vector getStructuredErrors() const;
+
+ /** \brief Add a semantic error message.
+ * \param value JSON Value location associated with the error
+ * \param message The error message.
+ * \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);
+
+ /** \brief Add a semantic error message with extra context.
+ * \param value JSON Value location associated with the error
+ * \param message The error message.
+ * \param extra Additional JSON Value location to contextualize the error
+ * \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);
+
+ /** \brief Return whether there are any errors.
+ * \return \c true if there are no errors to report \c false if
+ * errors have occurred.
+ */
+ bool good() const;
+
+private:
+ enum TokenType {
+ tokenEndOfStream = 0,
+ tokenObjectBegin,
+ tokenObjectEnd,
+ tokenArrayBegin,
+ tokenArrayEnd,
+ tokenString,
+ tokenNumber,
+ tokenTrue,
+ tokenFalse,
+ tokenNull,
+ tokenArraySeparator,
+ tokenMemberSeparator,
+ tokenComment,
+ tokenError
+ };
+
+ class Token {
+ public:
+ TokenType type_;
+ Location start_;
+ Location end_;
+ };
+
+ class ErrorInfo {
+ public:
+ Token token_;
+ std::string message_;
+ Location extra_;
+ };
+
+ typedef std::deque Errors;
+
+ bool readToken(Token& token);
+ void skipSpaces();
+ bool match(Location pattern, int patternLength);
+ bool readComment();
+ bool readCStyleComment();
+ bool readCppStyleComment();
+ bool readString();
+ void readNumber();
+ bool readValue();
+ bool readObject(Token& token);
+ bool readArray(Token& token);
+ bool decodeNumber(Token& token);
+ bool decodeNumber(Token& token, Value& decoded);
+ bool decodeString(Token& token);
+ bool decodeString(Token& token, std::string& decoded);
+ bool decodeDouble(Token& token);
+ bool decodeDouble(Token& token, Value& decoded);
+ bool decodeUnicodeCodePoint(Token& token,
+ Location& current,
+ Location end,
+ unsigned int& unicode);
+ bool decodeUnicodeEscapeSequence(Token& token,
+ Location& current,
+ Location end,
+ unsigned int& unicode);
+ bool addError(const std::string& message, Token& token, Location extra = 0);
+ bool recoverFromError(TokenType skipUntilToken);
+ bool addErrorAndRecover(const std::string& message,
+ Token& token,
+ TokenType skipUntilToken);
+ void skipUntilSpace();
+ Value& currentValue();
+ Char getNextChar();
+ void
+ getLocationLineAndColumn(Location location, int& line, int& column) const;
+ std::string getLocationLineAndColumn(Location location) const;
+ void addComment(Location begin, Location end, CommentPlacement placement);
+ void skipCommentTokens(Token& token);
+
+ typedef std::stack Nodes;
+ Nodes nodes_;
+ Errors errors_;
+ std::string document_;
+ Location begin_;
+ Location end_;
+ Location current_;
+ Location lastValueEnd_;
+ Value* lastValue_;
+ std::string commentsBefore_;
+ Features features_;
+ bool collectComments_;
+}; // Reader
+
+
+class OldCharReader : public CharReader {
bool const collectComments_;
Reader reader_;
public:
- OldReader(
+ OldCharReader(
bool collectComments,
Features const& features)
: collectComments_(collectComments)
@@ -930,7 +1144,7 @@ CharReader* CharReaderBuilder::newCharReader() const
features.strictRoot_ = settings_["strictRoot"].asBool();
features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
- return new OldReader(collectComments, features);
+ return new OldCharReader(collectComments, features);
}
static void getValidReaderKeys(std::set* valid_keys)
{