diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 93b091f6..de657409 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -2219,14 +2219,17 @@ public: \return The document itself for fluent API. */ template - GenericDocument& ParseStream(InputStream& is) { + GenericDocument& ParseStream(InputStream& is_) { GenericReader reader( stack_.HasAllocator() ? &stack_.GetAllocator() : 0); ClearStackOnExit scope(*this); + GenericStreamWrapper is(is_); parseResult_ = reader.template Parse(is, *this); if (parseResult_) { RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object ValueType::operator=(*stack_.template Pop(1));// Move value from stack to document + } else { + parseResult_.SetPos(is.line_, is.col_); } return *this; } @@ -2355,6 +2358,12 @@ public: //! Get the position of last parsing error in input, 0 otherwise. size_t GetErrorOffset() const { return parseResult_.Offset(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorLine() const { return parseResult_.Line(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorColumn() const { return parseResult_.Col(); } //! Implicit conversion to get the last parse result #ifndef __clang // -Wdocumentation diff --git a/include/rapidjson/error/error.h b/include/rapidjson/error/error.h index 9311d2f0..be805791 100644 --- a/include/rapidjson/error/error.h +++ b/include/rapidjson/error/error.h @@ -116,6 +116,10 @@ public: ParseErrorCode Code() const { return code_; } //! Get the error offset, if \ref IsError(), 0 otherwise. size_t Offset() const { return offset_; } + //! Get the position of line number if error exists. + size_t Line() const { return line_; } + //! Get the position of column number if error exists. + size_t Col() const { return col_; } //! Explicit conversion to \c bool, returns \c true, iff !\ref IsError(). operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; } @@ -134,10 +138,14 @@ public: void Clear() { Set(kParseErrorNone); } //! Update error code and offset. void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; } + //! Update line number and column number of the error position + void SetPos(size_t line, size_t col) { line_ = line; col_ = col; } private: ParseErrorCode code_; size_t offset_; + size_t line_; + size_t col_; }; //! Function pointer type of GetParseError(). diff --git a/include/rapidjson/stream.h b/include/rapidjson/stream.h index fef82c25..4e4ba80a 100644 --- a/include/rapidjson/stream.h +++ b/include/rapidjson/stream.h @@ -100,6 +100,48 @@ inline void PutN(Stream& stream, Ch c, size_t n) { PutUnsafe(stream, c); } +/////////////////////////////////////////////////////////////////////////////// +// GenericStreamWrapper + +//! A Stream Wrapper +/*! \tThis string stream is designed for counting line and column number + \tof the error (if exists) position, while just forwarding any received + \tmessage to the origin stream. + \note implements Stream concept +*/ +template +class GenericStreamWrapper { +public: + typedef typename Encoding::Ch Ch; + size_t line_; + size_t col_; + GenericStreamWrapper(InputStream& is): is_(is), line_(1), col_(0) {} + + Ch Peek() const { return is_.Peek(); } + + // counting line and column number + Ch Take() { + Ch ch = is_.Take(); + if(ch == '\n') { + line_ ++; + col_ = 0; + } else { + col_ ++; + } + return ch; + } + size_t Tell() { return is_.Tell(); } + + Ch* PutBegin() { return is_.PutBegin(); } + void Put(Ch ch) { return is_.Put(ch); } + void Flush() { return is_.Flush(); } + size_t PutEnd(Ch* ch) { is_.PutEnd(ch); } + + const Ch* Peek4() const { is_.Peek4(); } +private: + InputStream& is_; +}; + /////////////////////////////////////////////////////////////////////////////// // StringStream