Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / src / utils / SkJSON.h
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
8 #ifndef SkJSON_DEFINED
9 #define SkJSON_DEFINED
10
11 #include "include/core/SkTypes.h"
12 #include "include/private/SkNoncopyable.h"
13 #include "src/core/SkArenaAlloc.h"
14
15 #include <cstring>
16 #include <string_view>
17
18 class SkString;
19 class SkWStream;
20
21 namespace skjson {
22
23 /**
24  *  A fast and likely non-conforming JSON parser.
25  *
26  *  Some known limitations/compromises:
27  *
28  *    -- single-precision FP numbers
29  *
30  *    -- missing string unescaping (no current users, could be easily added)
31  *
32  *
33  *  Values are opaque, fixed-size (64 bits), immutable records.
34  *
35  *  They can be converted to facade types for type-specific functionality.
36  *
37  *  E.g.:
38  *
39  *     if (v.is<ArrayValue>()) {
40  *         for (const auto& item : v.as<ArrayValue>()) {
41  *             if (const NumberValue* n = item) {
42  *                 printf("Found number: %f", **n);
43  *             }
44  *         }
45  *     }
46  *
47  *     if (v.is<ObjectValue>()) {
48  *         const StringValue* id = v.as<ObjectValue>()["id"];
49  *         if (id) {
50  *             printf("Found object ID: %s", id->begin());
51  *         } else {
52  *             printf("Missing object ID");
53  *         }
54  *     }
55  */
56 class alignas(8) Value {
57 public:
58     enum class Type {
59         kNull,
60         kBool,
61         kNumber,
62         kString,
63         kArray,
64         kObject,
65     };
66
67     /**
68      * @return    The type of this value.
69      */
70     Type getType() const;
71
72     /**
73      * @return    True if the record matches the facade type T.
74      */
75     template <typename T>
76     bool is() const { return this->getType() == T::kType; }
77
78     /**
79      * Unguarded conversion to facade types.
80      *
81      * @return    The record cast as facade type T&.
82      */
83     template <typename T>
84     const T& as() const {
85         SkASSERT(this->is<T>());
86         return *reinterpret_cast<const T*>(this);
87     }
88
89     /**
90      * Guarded conversion to facade types.
91      *
92      * @return    The record cast as facade type T*.
93      */
94     template <typename T>
95     operator const T*() const {
96         return this->is<T>() ? &this->as<T>() : nullptr;
97     }
98
99     /**
100      * @return    The string representation of this value.
101      */
102     SkString toString() const;
103
104 protected:
105     /*
106       Value implementation notes:
107
108         -- fixed 64-bit size
109
110         -- 8-byte aligned
111
112         -- union of:
113
114              bool
115              int32
116              float
117              char[8] (short string storage)
118              external payload (tagged) pointer
119
120          -- lowest 3 bits reserved for tag storage
121
122      */
123     enum class Tag : uint8_t {
124         // n.b.: we picked kShortString == 0 on purpose,
125         // to enable certain short-string optimizations.
126         kShortString                  = 0b00000000,  // inline payload
127         kNull                         = 0b00000001,  // no payload
128         kBool                         = 0b00000010,  // inline payload
129         kInt                          = 0b00000011,  // inline payload
130         kFloat                        = 0b00000100,  // inline payload
131         kString                       = 0b00000101,  // ptr to external storage
132         kArray                        = 0b00000110,  // ptr to external storage
133         kObject                       = 0b00000111,  // ptr to external storage
134     };
135     inline static constexpr uint8_t kTagMask = 0b00000111;
136
137     void init_tagged(Tag);
138     void init_tagged_pointer(Tag, void*);
139
140     Tag getTag() const {
141         return static_cast<Tag>(fData8[0] & kTagMask);
142     }
143
144     // Access the record payload as T.
145     //
146     // Since the tag is stored in the lower bits, we skip the first word whenever feasible.
147     //
148     // E.g. (U == unused)
149     //
150     //   uint8_t
151     //    -----------------------------------------------------------------------
152     //   |TAG| U  |  val8  |   U    |   U    |   U    |   U    |   U    |   U    |
153     //    -----------------------------------------------------------------------
154     //
155     //   uint16_t
156     //    -----------------------------------------------------------------------
157     //   |TAG|      U      |      val16      |        U        |        U        |
158     //    -----------------------------------------------------------------------
159     //
160     //   uint32_t
161     //    -----------------------------------------------------------------------
162     //   |TAG|             U                 |                val32              |
163     //    -----------------------------------------------------------------------
164     //
165     //   T* (32b)
166     //    -----------------------------------------------------------------------
167     //   |TAG|             U                 |             T* (32bits)           |
168     //    -----------------------------------------------------------------------
169     //
170     //   T* (64b)
171     //    -----------------------------------------------------------------------
172     //   |TAG|                        T* (61bits)                                |
173     //    -----------------------------------------------------------------------
174     //
175     template <typename T>
176     const T* cast() const {
177         static_assert(sizeof (T) <=  sizeof(Value), "");
178         static_assert(alignof(T) <= alignof(Value), "");
179
180         return (sizeof(T) > sizeof(*this) / 2)
181                 ? reinterpret_cast<const T*>(this) + 0  // need all the bits
182                 : reinterpret_cast<const T*>(this) + 1; // skip the first word (where the tag lives)
183     }
184
185     template <typename T>
186     T* cast() { return const_cast<T*>(const_cast<const Value*>(this)->cast<T>()); }
187
188     // Access the pointer payload.
189     template <typename T>
190     const T* ptr() const {
191         static_assert(sizeof(uintptr_t)     == sizeof(Value) ||
192                       sizeof(uintptr_t) * 2 == sizeof(Value), "");
193
194         return (sizeof(uintptr_t) < sizeof(Value))
195             // For 32-bit, pointers are stored unmodified.
196             ? *this->cast<const T*>()
197             // For 64-bit, we use the lower bits of the pointer as tag storage.
198             : reinterpret_cast<T*>(*this->cast<uintptr_t>() & ~static_cast<uintptr_t>(kTagMask));
199     }
200
201 private:
202     inline static constexpr size_t kValueSize = 8;
203
204     uint8_t fData8[kValueSize];
205
206 #if !defined(SK_CPU_LENDIAN)
207     // The current value layout assumes LE and will take some tweaking for BE.
208     static_assert(false, "Big-endian builds are not supported at this time.");
209 #endif
210 };
211
212 class NullValue final : public Value {
213 public:
214     inline static constexpr Type kType = Type::kNull;
215
216     NullValue();
217 };
218
219 class BoolValue final : public Value {
220 public:
221     inline static constexpr Type kType = Type::kBool;
222
223     explicit BoolValue(bool);
224
225     bool operator *() const {
226         SkASSERT(this->getTag() == Tag::kBool);
227         return *this->cast<bool>();
228     }
229 };
230
231 class NumberValue final : public Value {
232 public:
233     inline static constexpr Type kType = Type::kNumber;
234
235     explicit NumberValue(int32_t);
236     explicit NumberValue(float);
237
238     double operator *() const {
239         SkASSERT(this->getTag() == Tag::kInt ||
240                  this->getTag() == Tag::kFloat);
241
242         return this->getTag() == Tag::kInt
243             ? static_cast<double>(*this->cast<int32_t>())
244             : static_cast<double>(*this->cast<float>());
245     }
246 };
247
248 template <typename T, Value::Type vtype>
249 class VectorValue : public Value {
250 public:
251     using ValueT = T;
252     inline static constexpr Type kType = vtype;
253
254     size_t size() const {
255         SkASSERT(this->getType() == kType);
256         return *this->ptr<size_t>();
257     }
258
259     const T* begin() const {
260         SkASSERT(this->getType() == kType);
261         const auto* size_ptr = this->ptr<size_t>();
262         return reinterpret_cast<const T*>(size_ptr + 1);
263     }
264
265     const T* end() const {
266         SkASSERT(this->getType() == kType);
267         const auto* size_ptr = this->ptr<size_t>();
268         return reinterpret_cast<const T*>(size_ptr + 1) + *size_ptr;
269     }
270
271     const T& operator[](size_t i) const {
272         SkASSERT(this->getType() == kType);
273         SkASSERT(i < this->size());
274
275         return *(this->begin() + i);
276     }
277 };
278
279 class ArrayValue final : public VectorValue<Value, Value::Type::kArray> {
280 public:
281     ArrayValue(const Value* src, size_t size, SkArenaAlloc& alloc);
282 };
283
284 class StringValue final : public Value {
285 public:
286     inline static constexpr Type kType = Type::kString;
287
288     StringValue();
289     StringValue(const char* src, size_t size, SkArenaAlloc& alloc);
290
291     size_t size() const {
292         switch (this->getTag()) {
293         case Tag::kShortString:
294             // We don't bother storing a length for short strings on the assumption
295             // that strlen is fast in this case.  If this becomes problematic, we
296             // can either go back to storing (7-len) in the tag byte or write a fast
297             // short_strlen.
298             return strlen(this->cast<char>());
299         case Tag::kString:
300             return this->cast<VectorValue<char, Value::Type::kString>>()->size();
301         default:
302             return 0;
303         }
304     }
305
306     const char* begin() const {
307         return this->getTag() == Tag::kShortString
308             ? this->cast<char>()
309             : this->cast<VectorValue<char, Value::Type::kString>>()->begin();
310     }
311
312     const char* end() const {
313         return this->getTag() == Tag::kShortString
314             ? strchr(this->cast<char>(), '\0')
315             : this->cast<VectorValue<char, Value::Type::kString>>()->end();
316     }
317
318     std::string_view str() const {
319         return std::string_view(this->begin(), this->size());
320     }
321 };
322
323 struct Member {
324     StringValue fKey;
325           Value fValue;
326 };
327
328 class ObjectValue final : public VectorValue<Member, Value::Type::kObject> {
329 public:
330     ObjectValue(const Member* src, size_t size, SkArenaAlloc& alloc);
331
332     const  Value& operator[](const char*) const;
333
334     const Member& operator[](size_t i) const {
335         return this->VectorValue::operator[](i);
336     }
337 };
338
339 class DOM final : public SkNoncopyable {
340 public:
341     DOM(const char*, size_t);
342
343     const Value& root() const { return fRoot; }
344
345     void write(SkWStream*) const;
346
347 private:
348     SkArenaAlloc fAlloc;
349     Value        fRoot;
350 };
351
352 inline Value::Type Value::getType() const {
353     switch (this->getTag()) {
354     case Tag::kNull:        return Type::kNull;
355     case Tag::kBool:        return Type::kBool;
356     case Tag::kInt:         return Type::kNumber;
357     case Tag::kFloat:       return Type::kNumber;
358     case Tag::kShortString: return Type::kString;
359     case Tag::kString:      return Type::kString;
360     case Tag::kArray:       return Type::kArray;
361     case Tag::kObject:      return Type::kObject;
362     }
363
364     SkASSERT(false); // unreachable
365     return Type::kNull;
366 }
367
368 } // namespace skjson
369
370 #endif // SkJSON_DEFINED
371