aboutsummaryrefslogtreecommitdiffhomepage
path: root/modules/skjson/include/SkJSON.h
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2018-06-08 12:25:38 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-06-08 17:45:33 +0000
commit7796f00dcfd09ca52140c4133ddc9bc197b832db (patch)
treeea438f8ab65f69a8d5e1b93c1d759d347a928959 /modules/skjson/include/SkJSON.h
parent61e66867ae10451fd365a676747a2c853bdd723d (diff)
SkJson
For now this is only wired to a bench and a couple of tests. Local numbers, for a ~500KB BM "compressed" json: micros bench 2456.54 json_rapidjson nonrendering 1192.38 json_skjson nonrendering Change-Id: I7b3514f84c7c525d1787722c43ad6095e3692563 Reviewed-on: https://skia-review.googlesource.com/127622 Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Florin Malita <fmalita@chromium.org>
Diffstat (limited to 'modules/skjson/include/SkJSON.h')
-rw-r--r--modules/skjson/include/SkJSON.h139
1 files changed, 139 insertions, 0 deletions
diff --git a/modules/skjson/include/SkJSON.h b/modules/skjson/include/SkJSON.h
new file mode 100644
index 0000000000..4cb312c64f
--- /dev/null
+++ b/modules/skjson/include/SkJSON.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkJSON_DEFINED
+#define SkJSON_DEFINED
+
+#include "SkArenaAlloc.h"
+#include "SkTypes.h"
+
+class SkWStream;
+
+namespace skjson {
+
+/**
+ * A fast and likely non-conforming JSON parser.
+ *
+ * Some known limitations/compromises:
+ *
+ * -- single-precision FP numbers
+ *
+ * -- missing string unescaping (no current users, could be easily added)
+ *
+ *
+ * Values are opaque, fixed-size (64 bits), immutable records.
+ *
+ * They can be freely converted to any of the facade types for type-specific functionality.
+ *
+ * Note: type checking is lazy/deferred, to facilitate chained property access - e.g.
+ *
+ * if (!v.as<ObjectValue>()["foo"].as<ObjectValue>()["bar"].is<NullValue>())
+ * LOG("found v.foo.bar!");
+ */
+class alignas(8) Value {
+public:
+ enum class Type {
+ kNull,
+ kBool,
+ kNumber,
+ kString,
+ kArray,
+ kObject,
+ };
+
+ /**
+ * @return The public type of this record.
+ */
+ Type getType() const;
+
+ /**
+ * @return True if the record matches the facade type T.
+ */
+ template <typename T>
+ bool is() const { return T::IsType(this->getType()); }
+
+ /**
+ * @return The record cast as facade type T.
+ *
+ * Note: this is always safe, as proper typing is enforced in the facade methods.
+ */
+ template <typename T>
+ const T& as() const {
+ return *reinterpret_cast<const T*>(this->is<T>() ? this : &Value::Null());
+ }
+
+ /**
+ * @return Null value singleton.
+ */
+ static const Value& Null();
+
+protected:
+ uint8_t fData8[8];
+};
+
+class NullValue final : public Value {
+public:
+ static bool IsType(Value::Type t) { return t == Type::kNull; }
+};
+
+template <typename T, Value::Type vtype>
+class PrimitiveValue final : public Value {
+public:
+ static bool IsType(Value::Type t) { return t == vtype; }
+
+ T operator *() const;
+};
+
+template <typename T, Value::Type vtype>
+class VectorValue : public Value {
+public:
+ static bool IsType(Value::Type t) { return t == vtype; }
+
+ size_t size() const;
+
+ const T* begin() const;
+ const T* end() const;
+
+ const T& operator[](size_t i) const {
+ return (i < this->size()) ? *(this->begin() + i) : T::Null();
+ }
+};
+
+using BoolValue = PrimitiveValue<bool , Value::Type::kBool >;
+using NumberValue = PrimitiveValue<double, Value::Type::kNumber>;
+using StringValue = VectorValue<char , Value::Type::kString>;
+using ArrayValue = VectorValue<Value , Value::Type::kArray >;
+
+struct Member {
+ StringValue fKey;
+ Value fValue;
+
+ static const Member& Null();
+};
+
+class ObjectValue final : public VectorValue<Member, Value::Type::kObject> {
+public:
+ const Value& operator[](const char*) const;
+};
+
+class DOM final : public SkNoncopyable {
+public:
+ explicit DOM(const char*);
+
+ const Value& root() const { return *fRoot; }
+
+ void write(SkWStream*) const;
+
+private:
+ SkArenaAlloc fAlloc;
+ const Value* fRoot;
+};
+
+} // namespace skjson
+
+#endif // SkJSON_DEFINED
+