SkJSON.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. /*
  2. * Copyright 2018 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #ifndef SkJSON_DEFINED
  8. #define SkJSON_DEFINED
  9. #include "include/core/SkTypes.h"
  10. #include "include/private/SkNoncopyable.h"
  11. #include "include/private/SkTo.h"
  12. #include "src/core/SkArenaAlloc.h"
  13. #include <cstring>
  14. class SkString;
  15. class SkWStream;
  16. namespace skjson {
  17. /**
  18. * A fast and likely non-conforming JSON parser.
  19. *
  20. * Some known limitations/compromises:
  21. *
  22. * -- single-precision FP numbers
  23. *
  24. * -- missing string unescaping (no current users, could be easily added)
  25. *
  26. *
  27. * Values are opaque, fixed-size (64 bits), immutable records.
  28. *
  29. * They can be converted to facade types for type-specific functionality.
  30. *
  31. * E.g.:
  32. *
  33. * if (v.is<ArrayValue>()) {
  34. * for (const auto& item : v.as<ArrayValue>()) {
  35. * if (const NumberValue* n = item) {
  36. * printf("Found number: %f", **n);
  37. * }
  38. * }
  39. * }
  40. *
  41. * if (v.is<ObjectValue>()) {
  42. * const StringValue* id = v.as<ObjectValue>()["id"];
  43. * if (id) {
  44. * printf("Found object ID: %s", id->begin());
  45. * } else {
  46. * printf("Missing object ID");
  47. * }
  48. * }
  49. */
  50. class alignas(8) Value {
  51. public:
  52. enum class Type {
  53. kNull,
  54. kBool,
  55. kNumber,
  56. kString,
  57. kArray,
  58. kObject,
  59. };
  60. /**
  61. * @return The type of this value.
  62. */
  63. Type getType() const;
  64. /**
  65. * @return True if the record matches the facade type T.
  66. */
  67. template <typename T>
  68. bool is() const { return this->getType() == T::kType; }
  69. /**
  70. * Unguarded conversion to facade types.
  71. *
  72. * @return The record cast as facade type T&.
  73. */
  74. template <typename T>
  75. const T& as() const {
  76. SkASSERT(this->is<T>());
  77. return *reinterpret_cast<const T*>(this);
  78. }
  79. /**
  80. * Guarded conversion to facade types.
  81. *
  82. * @return The record cast as facade type T*.
  83. */
  84. template <typename T>
  85. operator const T*() const {
  86. return this->is<T>() ? &this->as<T>() : nullptr;
  87. }
  88. /**
  89. * @return The string representation of this value.
  90. */
  91. SkString toString() const;
  92. protected:
  93. /*
  94. Value implementation notes:
  95. -- fixed 64-bit size
  96. -- 8-byte aligned
  97. -- union of:
  98. bool
  99. int32
  100. float
  101. char[8] (short string storage)
  102. external payload (tagged) pointer
  103. -- highest 3 bits reserved for type storage
  104. */
  105. enum class Tag : uint8_t {
  106. // We picked kShortString == 0 so that tag 0x00 and stored max_size-size (7-7=0)
  107. // conveniently overlap the '\0' terminator, allowing us to store a 7 character
  108. // C string inline.
  109. kShortString = 0b00000000, // inline payload
  110. kNull = 0b00100000, // no payload
  111. kBool = 0b01000000, // inline payload
  112. kInt = 0b01100000, // inline payload
  113. kFloat = 0b10000000, // inline payload
  114. kString = 0b10100000, // ptr to external storage
  115. kArray = 0b11000000, // ptr to external storage
  116. kObject = 0b11100000, // ptr to external storage
  117. };
  118. static constexpr uint8_t kTagMask = 0b11100000;
  119. void init_tagged(Tag);
  120. void init_tagged_pointer(Tag, void*);
  121. Tag getTag() const {
  122. return static_cast<Tag>(fData8[kTagOffset] & kTagMask);
  123. }
  124. // Access the record data as T.
  125. //
  126. // This is also used to access the payload for inline records. Since the record type lives in
  127. // the high bits, sizeof(T) must be less than sizeof(Value) when accessing inline payloads.
  128. //
  129. // E.g.
  130. //
  131. // uint8_t
  132. // -----------------------------------------------------------------------
  133. // | val8 | val8 | val8 | val8 | val8 | val8 | val8 | TYPE|
  134. // -----------------------------------------------------------------------
  135. //
  136. // uint32_t
  137. // -----------------------------------------------------------------------
  138. // | val32 | unused | TYPE|
  139. // -----------------------------------------------------------------------
  140. //
  141. // T* (64b)
  142. // -----------------------------------------------------------------------
  143. // | T* (kTypeShift bits) |TYPE|
  144. // -----------------------------------------------------------------------
  145. //
  146. template <typename T>
  147. const T* cast() const {
  148. static_assert(sizeof (T) <= sizeof(Value), "");
  149. static_assert(alignof(T) <= alignof(Value), "");
  150. return reinterpret_cast<const T*>(this);
  151. }
  152. template <typename T>
  153. T* cast() { return const_cast<T*>(const_cast<const Value*>(this)->cast<T>()); }
  154. // Access the pointer payload.
  155. template <typename T>
  156. const T* ptr() const {
  157. static_assert(sizeof(uintptr_t) == sizeof(Value) ||
  158. sizeof(uintptr_t) * 2 == sizeof(Value), "");
  159. return (sizeof(uintptr_t) < sizeof(Value))
  160. // For 32-bit, pointers are stored unmodified.
  161. ? *this->cast<const T*>()
  162. // For 64-bit, we use the high bits of the pointer as tag storage.
  163. : reinterpret_cast<T*>(*this->cast<uintptr_t>() & kTagPointerMask);
  164. }
  165. private:
  166. static constexpr size_t kValueSize = 8;
  167. uint8_t fData8[kValueSize];
  168. #if defined(SK_CPU_LENDIAN)
  169. static constexpr size_t kTagOffset = kValueSize - 1;
  170. static constexpr uintptr_t kTagPointerMask =
  171. ~(static_cast<uintptr_t>(kTagMask) << ((sizeof(uintptr_t) - 1) * 8));
  172. #else
  173. // The current value layout assumes LE and will take some tweaking for BE.
  174. static_assert(false, "Big-endian builds are not supported at this time.");
  175. #endif
  176. };
  177. class NullValue final : public Value {
  178. public:
  179. static constexpr Type kType = Type::kNull;
  180. NullValue();
  181. };
  182. class BoolValue final : public Value {
  183. public:
  184. static constexpr Type kType = Type::kBool;
  185. explicit BoolValue(bool);
  186. bool operator *() const {
  187. SkASSERT(this->getTag() == Tag::kBool);
  188. return *this->cast<bool>();
  189. }
  190. };
  191. class NumberValue final : public Value {
  192. public:
  193. static constexpr Type kType = Type::kNumber;
  194. explicit NumberValue(int32_t);
  195. explicit NumberValue(float);
  196. double operator *() const {
  197. SkASSERT(this->getTag() == Tag::kInt ||
  198. this->getTag() == Tag::kFloat);
  199. return this->getTag() == Tag::kInt
  200. ? static_cast<double>(*this->cast<int32_t>())
  201. : static_cast<double>(*this->cast<float>());
  202. }
  203. };
  204. template <typename T, Value::Type vtype>
  205. class VectorValue : public Value {
  206. public:
  207. using ValueT = T;
  208. static constexpr Type kType = vtype;
  209. size_t size() const {
  210. SkASSERT(this->getType() == kType);
  211. return *this->ptr<size_t>();
  212. }
  213. const T* begin() const {
  214. SkASSERT(this->getType() == kType);
  215. const auto* size_ptr = this->ptr<size_t>();
  216. return reinterpret_cast<const T*>(size_ptr + 1);
  217. }
  218. const T* end() const {
  219. SkASSERT(this->getType() == kType);
  220. const auto* size_ptr = this->ptr<size_t>();
  221. return reinterpret_cast<const T*>(size_ptr + 1) + *size_ptr;
  222. }
  223. const T& operator[](size_t i) const {
  224. SkASSERT(this->getType() == kType);
  225. SkASSERT(i < this->size());
  226. return *(this->begin() + i);
  227. }
  228. };
  229. class ArrayValue final : public VectorValue<Value, Value::Type::kArray> {
  230. public:
  231. ArrayValue(const Value* src, size_t size, SkArenaAlloc& alloc);
  232. };
  233. class StringValue final : public Value {
  234. public:
  235. static constexpr Type kType = Type::kString;
  236. StringValue();
  237. StringValue(const char* src, size_t size, SkArenaAlloc& alloc);
  238. size_t size() const {
  239. switch (this->getTag()) {
  240. case Tag::kShortString:
  241. // We don't bother storing a length for short strings on the assumption
  242. // that strlen is fast in this case. If this becomes problematic, we
  243. // can either go back to storing (7-len) in the tag byte or write a fast
  244. // short_strlen.
  245. return strlen(this->cast<char>());
  246. case Tag::kString:
  247. return this->cast<VectorValue<char, Value::Type::kString>>()->size();
  248. default:
  249. return 0;
  250. }
  251. }
  252. const char* begin() const {
  253. return this->getTag() == Tag::kShortString
  254. ? this->cast<char>()
  255. : this->cast<VectorValue<char, Value::Type::kString>>()->begin();
  256. }
  257. const char* end() const {
  258. return this->getTag() == Tag::kShortString
  259. ? strchr(this->cast<char>(), '\0')
  260. : this->cast<VectorValue<char, Value::Type::kString>>()->end();
  261. }
  262. };
  263. struct Member {
  264. StringValue fKey;
  265. Value fValue;
  266. };
  267. class ObjectValue final : public VectorValue<Member, Value::Type::kObject> {
  268. public:
  269. ObjectValue(const Member* src, size_t size, SkArenaAlloc& alloc);
  270. const Value& operator[](const char*) const;
  271. private:
  272. // Not particularly interesting - hiding for disambiguation.
  273. const Member& operator[](size_t i) const = delete;
  274. };
  275. class DOM final : public SkNoncopyable {
  276. public:
  277. DOM(const char*, size_t);
  278. const Value& root() const { return fRoot; }
  279. void write(SkWStream*) const;
  280. private:
  281. SkArenaAlloc fAlloc;
  282. Value fRoot;
  283. };
  284. inline Value::Type Value::getType() const {
  285. switch (this->getTag()) {
  286. case Tag::kNull: return Type::kNull;
  287. case Tag::kBool: return Type::kBool;
  288. case Tag::kInt: return Type::kNumber;
  289. case Tag::kFloat: return Type::kNumber;
  290. case Tag::kShortString: return Type::kString;
  291. case Tag::kString: return Type::kString;
  292. case Tag::kArray: return Type::kArray;
  293. case Tag::kObject: return Type::kObject;
  294. }
  295. SkASSERT(false); // unreachable
  296. return Type::kNull;
  297. }
  298. } // namespace skjson
  299. #endif // SkJSON_DEFINED