diff options
Diffstat (limited to 'modules/skjson/src/SkJSON.cpp')
-rw-r--r-- | modules/skjson/src/SkJSON.cpp | 48 |
1 files changed, 17 insertions, 31 deletions
diff --git a/modules/skjson/src/SkJSON.cpp b/modules/skjson/src/SkJSON.cpp index 64f1302a7e..bf176c5c5c 100644 --- a/modules/skjson/src/SkJSON.cpp +++ b/modules/skjson/src/SkJSON.cpp @@ -11,12 +11,12 @@ #include "SkString.h" #include <cmath> -#include <tuple> #include <vector> namespace skjson { -// #define SK_JSON_REPORT_ERRORS +//#define SK_JSON_REPORT_ERRORS + static_assert( sizeof(Value) == 8, ""); static_assert(alignof(Value) == 8, ""); @@ -236,21 +236,7 @@ public: fScopeStack.reserve(kScopeStackReserve); } - const Value parse(const char* p, size_t size) { - if (!size) { - this->error(NullValue(), p, "invalid empty input"); - } - - const char* p_stop = p + size - 1; - - // We're only checking for end-of-stream on object/array close('}',']'), - // so we must trim any whitespace from the buffer tail. - while (p_stop > p && is_ws(*p_stop)) --p_stop; - - if (*p_stop != '}' && *p_stop != ']') { - return this->error(NullValue(), p_stop, "invalid top-level value"); - } - + const Value parse(const char* p) { p = skip_ws(p); switch (*p) { @@ -354,17 +340,17 @@ public: pop_common: SkASSERT(*p == '}' || *p == ']'); + ++p; + if (fScopeStack.empty()) { SkASSERT(fValueStack.size() == 1); - // Success condition: parsed the top level element and reached the stop token. - return p == p_stop + // Stop condition: parsed the top level element and there is no trailing garbage. + return *skip_ws(p) == '\0' ? fValueStack.front() - : this->error(NullValue(), p + 1, "trailing root garbage"); + : this->error(NullValue(), p, "trailing root garbage"); } - ++p; - goto match_post_value; match_array: @@ -391,20 +377,19 @@ public: return NullValue(); } - std::tuple<const char*, const SkString> getError() const { - return std::make_tuple(fErrorToken, fErrorMessage); + const SkString& getError() const { + return fError; } private: - SkArenaAlloc& fAlloc; + SkArenaAlloc& fAlloc; static constexpr size_t kValueStackReserve = 256; static constexpr size_t kScopeStackReserve = 128; std::vector<Value > fValueStack; std::vector<intptr_t> fScopeStack; - const char* fErrorToken = nullptr; - SkString fErrorMessage; + SkString fError; template <typename VectorT> void popScopeAsVec(size_t scope_start) { @@ -505,8 +490,9 @@ private: template <typename T> T error(T&& ret_val, const char* p, const char* msg) { #if defined(SK_JSON_REPORT_ERRORS) - fErrorToken = p; - fErrorMessage.set(msg); + static constexpr size_t kMaxContext = 128; + fError = SkStringPrintf("%s: >", msg); + fError.append(p, std::min(strlen(p), kMaxContext)); #endif return ret_val; } @@ -732,11 +718,11 @@ SkString Value::toString() const { static constexpr size_t kMinChunkSize = 4096; -DOM::DOM(const char* data, size_t size) +DOM::DOM(const char* c_str) : fAlloc(kMinChunkSize) { DOMParser parser(fAlloc); - fRoot = parser.parse(data, size); + fRoot = parser.parse(c_str); } void DOM::write(SkWStream* stream) const { |