aboutsummaryrefslogtreecommitdiffhomepage
path: root/modules/skjson/src/SkJSON.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/skjson/src/SkJSON.cpp')
-rw-r--r--modules/skjson/src/SkJSON.cpp48
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 {