diff --git a/src/parser.cpp b/src/parser.cpp index e8a47d5..ad58c8e 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -23,11 +23,7 @@ struct StringStream { static constexpr bool isStream = std::is_same_v; auto error(std::string_view msg) const noexcept { - if constexpr (isStream) { - return Err(ParseError(std::string(msg), stream.tellg(), line, column)); - } else { - return Err(ParseError(std::string(msg), offset, line, column)); - } + return Err(ParseError(std::string(msg), offset, line, column)); } Result take() noexcept { @@ -38,8 +34,8 @@ struct StringStream { if (stream.empty()) return this->error("eof"); ch = stream[0]; stream = stream.substr(1); - ++offset; } + ++offset; if (ch == '\n') { ++line; column = 1; @@ -57,6 +53,7 @@ struct StringStream { buffer.resize(n); if (!stream.read(buffer.data(), n)) return this->error("eof"); column += n; + offset += n; return Ok(std::move(buffer)); } else { if (stream.size() < n) return this->error("eof"); @@ -84,6 +81,7 @@ struct StringStream { if constexpr (isStream) { while (stream.good() && isWhitespace(stream.peek())) { char ch = stream.get(); + ++offset; if (ch == '\n') { ++line; column = 1; diff --git a/test/test.cpp b/test/test.cpp index 4855442..a5477c8 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -382,11 +382,27 @@ TEST_CASE("ParseError line numbers") { auto err = matjson::parse("{").unwrapErr(); REQUIRE(err.line == 1); REQUIRE(err.column == 2); + REQUIRE(err.offset == 1); err = matjson::parse("{\n\"hello").unwrapErr(); REQUIRE(err.line == 2); REQUIRE(err.column == 7); + REQUIRE(err.offset == 8); +} + +TEST_CASE("ParseError line numbers from stream") { + std::istringstream stream("{"); + auto err = matjson::parse(stream).unwrapErr(); + REQUIRE(err.line == 1); + REQUIRE(err.column == 2); + REQUIRE(err.offset == 1); + + stream = std::istringstream("{\n\"hello"); + err = matjson::parse(stream).unwrapErr(); + REQUIRE(err.line == 2); + REQUIRE(err.column == 7); + REQUIRE(err.offset == 8); } TEST_CASE("parseAs") { @@ -401,6 +417,8 @@ TEST_CASE("Parse from stream") { std::istringstream stream(R"({"name": "Hello!","value": 123})"); auto res = matjson::parse(stream).unwrap(); + // parsing should consume the whole stream + REQUIRE(stream.eof()); REQUIRE(res == CoolStruct{.name = "Hello!", .value = 123}); @@ -412,6 +430,10 @@ TEST_CASE("Parse from stream") { stream = std::istringstream("[1, 2, 3"); REQUIRE(matjson::parse(stream).isErr()); + stream = std::istringstream("[1, 2!, 3"); + REQUIRE(matjson::parse(stream).isErr()); + REQUIRE(!stream.eof()); + stream = std::istringstream(""); REQUIRE(matjson::parse(stream).isErr());