Commit b16ff281 authored by KaitoHH's avatar KaitoHH

Add feature of locating line and column number of error

parent 2a0bc606
......@@ -2219,14 +2219,17 @@ public:
\return The document itself for fluent API.
*/
template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
GenericDocument& ParseStream(InputStream& is) {
GenericDocument& ParseStream(InputStream& is_) {
GenericReader<SourceEncoding, Encoding, StackAllocator> reader(
stack_.HasAllocator() ? &stack_.GetAllocator() : 0);
ClearStackOnExit scope(*this);
GenericStreamWrapper<InputStream, SourceEncoding> is(is_);
parseResult_ = reader.template Parse<parseFlags>(is, *this);
if (parseResult_) {
RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
ValueType::operator=(*stack_.template Pop<ValueType>(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
......
......@@ -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().
......
......@@ -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 <typename InputStream, typename Encoding>
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
......
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