Commit 2fcb9997 authored by Philipp A. Hartmann's avatar Philipp A. Hartmann

add ParseResult

parent 44755211
...@@ -1210,7 +1210,7 @@ public: ...@@ -1210,7 +1210,7 @@ public:
/*! \param allocator Optional allocator for allocating stack memory. /*! \param allocator Optional allocator for allocating stack memory.
\param stackCapacity Initial capacity of stack in bytes. \param stackCapacity Initial capacity of stack in bytes.
*/ */
GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseErrorCode_(kParseErrorNone), errorOffset_(0) {} GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseResult_() {}
//!@name Parse from stream //!@name Parse from stream
//!@{ //!@{
...@@ -1227,12 +1227,11 @@ public: ...@@ -1227,12 +1227,11 @@ public:
ValueType::SetNull(); // Remove existing root if exist ValueType::SetNull(); // Remove existing root if exist
GenericReader<SourceEncoding, Encoding, Allocator> reader(&GetAllocator()); GenericReader<SourceEncoding, Encoding, Allocator> reader(&GetAllocator());
ClearStackOnExit scope(*this); ClearStackOnExit scope(*this);
if (reader.template Parse<parseFlags>(is, *this)) { parseResult_ = reader.template Parse<parseFlags>(is, *this);
if (parseResult_) {
RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
this->RawAssign(*stack_.template Pop<ValueType>(1)); // Add this-> to prevent issue 13. this->RawAssign(*stack_.template Pop<ValueType>(1)); // Add this-> to prevent issue 13.
} }
parseErrorCode_ = reader.GetParseErrorCode();
errorOffset_ = reader.GetErrorOffset();
return *this; return *this;
} }
...@@ -1328,13 +1327,13 @@ public: ...@@ -1328,13 +1327,13 @@ public:
//!@{ //!@{
//! Whether a parse error was occured in the last parsing. //! Whether a parse error was occured in the last parsing.
bool HasParseError() const { return parseErrorCode_ != kParseErrorNone; } bool HasParseError() const { return parseResult_.IsError(); }
//! Get the message of parsing error. //! Get the message of parsing error.
ParseErrorCode GetParseError() const { return parseErrorCode_; } ParseErrorCode GetParseError() const { return parseResult_.Code(); }
//! Get the offset in character of the parsing error. //! Get the offset in character of the parsing error.
size_t GetErrorOffset() const { return errorOffset_; } size_t GetErrorOffset() const { return parseResult_.Offset(); }
//!@} //!@}
...@@ -1401,8 +1400,7 @@ private: ...@@ -1401,8 +1400,7 @@ private:
static const size_t kDefaultStackCapacity = 1024; static const size_t kDefaultStackCapacity = 1024;
internal::Stack<Allocator> stack_; internal::Stack<Allocator> stack_;
ParseErrorCode parseErrorCode_; ParseResult parseResult_;
size_t errorOffset_;
}; };
//! GenericDocument with UTF8 encoding //! GenericDocument with UTF8 encoding
......
...@@ -59,6 +59,28 @@ enum ParseErrorCode { ...@@ -59,6 +59,28 @@ enum ParseErrorCode {
kParseErrorNumberMissExponent //!< Miss exponent in number. kParseErrorNumberMissExponent //!< Miss exponent in number.
}; };
struct ParseResult {
ParseResult() : code_(kParseErrorNone), offset_(0) {}
ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}
ParseErrorCode Code() const { return code_; }
size_t Offset() const { return offset_; }
operator bool() const { return !IsError(); }
bool IsError() const { return code_ != kParseErrorNone; }
bool operator==(const ParseResult& that) const { return code_ == that.code_; }
bool operator==(ParseErrorCode code) const { return code_ == code; }
friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
void Clear() { Set(kParseErrorNone); }
void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }
private:
ParseErrorCode code_;
size_t offset_;
};
//! Function pointer type of GetParseError(). //! Function pointer type of GetParseError().
/*! This is the prototype for GetParseError_X(), where X is a locale. /*! This is the prototype for GetParseError_X(), where X is a locale.
......
...@@ -38,8 +38,7 @@ RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant ...@@ -38,8 +38,7 @@ RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \ #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \
RAPIDJSON_MULTILINEMACRO_BEGIN \ RAPIDJSON_MULTILINEMACRO_BEGIN \
RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \ RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
parseErrorCode_ = parseErrorCode; \ parseResult_.Set(parseErrorCode,offset); \
errorOffset_ = offset; \
RAPIDJSON_MULTILINEMACRO_END RAPIDJSON_MULTILINEMACRO_END
#endif #endif
...@@ -51,7 +50,7 @@ RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant ...@@ -51,7 +50,7 @@ RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
RAPIDJSON_MULTILINEMACRO_END RAPIDJSON_MULTILINEMACRO_END
#endif #endif
#include "error/error.h" // ParseErrorCode #include "error/error.h" // ParseErrorCode, ParseResult
namespace rapidjson { namespace rapidjson {
...@@ -273,7 +272,7 @@ public: ...@@ -273,7 +272,7 @@ public:
/*! \param allocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) /*! \param allocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing)
\param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing)
*/ */
GenericReader(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseErrorCode_(kParseErrorNone), errorOffset_(0) {} GenericReader(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseResult_() {}
//! Parse JSON text. //! Parse JSON text.
/*! \tparam parseFlags Combination of \ref ParseFlag. /*! \tparam parseFlags Combination of \ref ParseFlag.
...@@ -284,16 +283,15 @@ public: ...@@ -284,16 +283,15 @@ public:
\return Whether the parsing is successful. \return Whether the parsing is successful.
*/ */
template <unsigned parseFlags, typename InputStream, typename Handler> template <unsigned parseFlags, typename InputStream, typename Handler>
bool Parse(InputStream& is, Handler& handler) { ParseResult Parse(InputStream& is, Handler& handler) {
parseErrorCode_ = kParseErrorNone; parseResult_.Clear();
errorOffset_ = 0;
ClearStackOnExit scope(*this); ClearStackOnExit scope(*this);
SkipWhitespace(is); SkipWhitespace(is);
if (is.Peek() == '\0') { if (is.Peek() == '\0') {
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell()); RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell());
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(false); RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
} }
else { else {
switch (is.Peek()) { switch (is.Peek()) {
...@@ -301,17 +299,17 @@ public: ...@@ -301,17 +299,17 @@ public:
case '[': ParseArray<parseFlags>(is, handler); break; case '[': ParseArray<parseFlags>(is, handler); break;
default: RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotObjectOrArray, is.Tell()); default: RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotObjectOrArray, is.Tell());
} }
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(false); RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
SkipWhitespace(is); SkipWhitespace(is);
if (is.Peek() != '\0') { if (is.Peek() != '\0') {
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell()); RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell());
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(false); RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
} }
} }
return true; return parseResult_;
} }
//! Parse JSON text (with \ref kParseDefaultFlags) //! Parse JSON text (with \ref kParseDefaultFlags)
...@@ -322,15 +320,15 @@ public: ...@@ -322,15 +320,15 @@ public:
\return Whether the parsing is successful. \return Whether the parsing is successful.
*/ */
template <typename InputStream, typename Handler> template <typename InputStream, typename Handler>
bool Parse(InputStream& is, Handler& handler) { ParseResult Parse(InputStream& is, Handler& handler) {
return Parse<kParseDefaultFlags>(is, handler); return Parse<kParseDefaultFlags>(is, handler);
} }
bool HasParseError() const { return parseErrorCode_ != kParseErrorNone; } bool HasParseError() const { return parseResult_.IsError(); }
ParseErrorCode GetParseErrorCode() const { return parseErrorCode_; } ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); }
size_t GetErrorOffset() const { return errorOffset_; } size_t GetErrorOffset() const { return parseResult_.Offset(); }
private: private:
// Prohibit copy constructor & assignment operator. // Prohibit copy constructor & assignment operator.
...@@ -755,8 +753,7 @@ private: ...@@ -755,8 +753,7 @@ private:
static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string.
internal::Stack<Allocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. internal::Stack<Allocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing.
ParseErrorCode parseErrorCode_; ParseResult parseResult_;
size_t errorOffset_;
}; // class GenericReader }; // class GenericReader
//! Reader with UTF8 encoding and default allocator. //! Reader with UTF8 encoding and default allocator.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment