Unreviewed, rolling out r234489.
[WebKit-https.git] / Source / WTF / wtf / JSONValues.h
1 /*
2  * Copyright (C) 2009 Google Inc. All rights reserved.
3  * Copyright (C) 2014 University of Washington. All rights reserved.
4  * Copyright (C) 2017 Apple Inc. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following disclaimer
14  * in the documentation and/or other materials provided with the
15  * distribution.
16  *     * Neither the name of Google Inc. nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #pragma once
34
35 #include <wtf/HashMap.h>
36 #include <wtf/text/StringHash.h>
37 #include <wtf/text/WTFString.h>
38
39 namespace WTF {
40
41 // Make sure compiled symbols contain the WTF namespace prefix, but
42 // use a different inner namespace name so that JSON::Value is not ambigious.
43 // Otherwise, the compiler would have both WTF::JSON::Value and JSON::Value
44 // in scope and client code would have to use WTF::JSON::Value, which is tedious.
45 namespace JSONImpl {
46
47 class Array;
48 class ArrayBase;
49 class Object;
50 class ObjectBase;
51
52 // FIXME: unify this JSON parser with JSONParse in JavaScriptCore.
53 class WTF_EXPORT_PRIVATE Value : public RefCounted<Value> {
54 public:
55     static const int maxDepth = 1000;
56
57     virtual ~Value()
58     {
59         switch (m_type) {
60         case Type::Null:
61         case Type::Boolean:
62         case Type::Double:
63         case Type::Integer:
64             break;
65         case Type::String:
66             if (m_value.string)
67                 m_value.string->deref();
68             break;
69         case Type::Object:
70         case Type::Array:
71             break;
72         }
73     }
74
75     static Ref<Value> null();
76     static Ref<Value> create(bool);
77     static Ref<Value> create(int);
78     static Ref<Value> create(double);
79     static Ref<Value> create(const String&);
80     static Ref<Value> create(const char*);
81
82     enum class Type {
83         Null = 0,
84         Boolean,
85         Double,
86         Integer,
87         String,
88         Object,
89         Array,
90     };
91
92     Type type() const { return m_type; }
93     bool isNull() const { return m_type == Type::Null; }
94
95     bool asBoolean(bool&) const;
96     bool asInteger(int&) const;
97     bool asInteger(unsigned&) const;
98     bool asInteger(long&) const;
99     bool asInteger(long long&) const;
100     bool asInteger(unsigned long&) const;
101     bool asInteger(unsigned long long&) const;
102     bool asDouble(double&) const;
103     bool asDouble(float&) const;
104     bool asString(String&) const;
105     bool asValue(RefPtr<Value>&);
106
107     virtual bool asObject(RefPtr<Object>&);
108     virtual bool asArray(RefPtr<Array>&);
109
110     static bool parseJSON(const String& jsonInput, RefPtr<Value>& output);
111
112     String toJSONString() const;
113     virtual void writeJSON(StringBuilder& output) const;
114
115     virtual size_t memoryCost() const;
116
117 protected:
118     Value()
119         : m_type { Type::Null }
120     {
121     }
122
123     explicit Value(Type type)
124         : m_type(type)
125     {
126     }
127
128     explicit Value(bool value)
129         : m_type { Type::Boolean }
130     {
131         m_value.boolean = value;
132     }
133
134     explicit Value(int value)
135         : m_type { Type::Integer }
136     {
137         m_value.number = static_cast<double>(value);
138     }
139
140     explicit Value(double value)
141         : m_type(Type::Double)
142     {
143         m_value.number = value;
144     }
145
146     explicit Value(const String& value)
147         : m_type { Type::String }
148     {
149         m_value.string = value.impl();
150         if (m_value.string)
151             m_value.string->ref();
152     }
153
154     explicit Value(const char* value)
155         : m_type { Type::String }
156     {
157         String wrapper(value);
158         m_value.string = wrapper.impl();
159         if (m_value.string)
160             m_value.string->ref();
161     }
162
163 private:
164     Type m_type { Type::Null };
165     union {
166         bool boolean;
167         double number;
168         StringImpl* string;
169     } m_value;
170 };
171
172 class WTF_EXPORT_PRIVATE ObjectBase : public Value {
173 private:
174     typedef HashMap<String, RefPtr<Value>> Dictionary;
175
176 public:
177     typedef Dictionary::iterator iterator;
178     typedef Dictionary::const_iterator const_iterator;
179
180     Object* openAccessors();
181
182     size_t memoryCost() const final;
183
184 protected:
185     virtual ~ObjectBase();
186
187     bool asObject(RefPtr<Object>& output) override;
188
189     // FIXME: use templates to reduce the amount of duplicated set*() methods.
190     void setBoolean(const String& name, bool);
191     void setInteger(const String& name, int);
192     void setDouble(const String& name, double);
193     void setString(const String& name, const String&);
194     void setValue(const String& name, RefPtr<Value>&&);
195     void setObject(const String& name, RefPtr<ObjectBase>&&);
196     void setArray(const String& name, RefPtr<ArrayBase>&&);
197
198     iterator find(const String& name);
199     const_iterator find(const String& name) const;
200
201     // FIXME: use templates to reduce the amount of duplicated get*() methods.
202     bool getBoolean(const String& name, bool& output) const;
203     template<class T> bool getDouble(const String& name, T& output) const
204     {
205         RefPtr<Value> value;
206         if (!getValue(name, value))
207             return false;
208
209         return value->asDouble(output);
210     }
211     template<class T> bool getInteger(const String& name, T& output) const
212     {
213         RefPtr<Value> value;
214         if (!getValue(name, value))
215             return false;
216
217         return value->asInteger(output);
218     }
219
220     template<class T> std::optional<T> getNumber(const String& name) const
221     {
222         RefPtr<Value> value;
223         if (!getValue(name, value))
224             return std::nullopt;
225
226         T result;
227         if (!value->asDouble(result))
228             return std::nullopt;
229
230         return result;
231     }
232
233     bool getString(const String& name, String& output) const;
234     bool getObject(const String& name, RefPtr<Object>&) const;
235     bool getArray(const String& name, RefPtr<Array>&) const;
236     bool getValue(const String& name, RefPtr<Value>&) const;
237
238     void remove(const String& name);
239
240     void writeJSON(StringBuilder& output) const override;
241
242     iterator begin() { return m_map.begin(); }
243     iterator end() { return m_map.end(); }
244     const_iterator begin() const { return m_map.begin(); }
245     const_iterator end() const { return m_map.end(); }
246
247     int size() const { return m_map.size(); }
248
249 protected:
250     ObjectBase();
251
252 private:
253     Dictionary m_map;
254     Vector<String> m_order;
255 };
256
257 class Object : public ObjectBase {
258 public:
259     static WTF_EXPORT_PRIVATE Ref<Object> create();
260
261     using ObjectBase::asObject;
262
263     // This class expected non-cyclic values, as we cannot serialize cycles in JSON.
264     using ObjectBase::setBoolean;
265     using ObjectBase::setInteger;
266     using ObjectBase::setDouble;
267     using ObjectBase::setString;
268     using ObjectBase::setValue;
269     using ObjectBase::setObject;
270     using ObjectBase::setArray;
271
272     using ObjectBase::find;
273     using ObjectBase::getBoolean;
274     using ObjectBase::getInteger;
275     using ObjectBase::getDouble;
276     using ObjectBase::getNumber;
277     using ObjectBase::getString;
278     using ObjectBase::getObject;
279     using ObjectBase::getArray;
280     using ObjectBase::getValue;
281
282     using ObjectBase::remove;
283
284     using ObjectBase::begin;
285     using ObjectBase::end;
286
287     using ObjectBase::size;
288 };
289
290
291 class WTF_EXPORT_PRIVATE ArrayBase : public Value {
292 public:
293     typedef Vector<RefPtr<Value>>::iterator iterator;
294     typedef Vector<RefPtr<Value>>::const_iterator const_iterator;
295
296     unsigned length() const { return static_cast<unsigned>(m_map.size()); }
297
298     RefPtr<Value> get(size_t index) const;
299
300     size_t memoryCost() const final;
301
302 protected:
303     virtual ~ArrayBase();
304
305     bool asArray(RefPtr<Array>&) override;
306
307     void pushBoolean(bool);
308     void pushInteger(int);
309     void pushDouble(double);
310     void pushString(const String&);
311     void pushValue(RefPtr<Value>&&);
312     void pushObject(RefPtr<ObjectBase>&&);
313     void pushArray(RefPtr<ArrayBase>&&);
314
315     void writeJSON(StringBuilder& output) const override;
316
317     iterator begin() { return m_map.begin(); }
318     iterator end() { return m_map.end(); }
319     const_iterator begin() const { return m_map.begin(); }
320     const_iterator end() const { return m_map.end(); }
321
322 protected:
323     ArrayBase();
324
325 private:
326     Vector<RefPtr<Value>> m_map;
327 };
328
329 class Array : public ArrayBase {
330 public:
331     static WTF_EXPORT_PRIVATE Ref<Array> create();
332
333     using ArrayBase::asArray;
334
335     // This class expected non-cyclic values, as we cannot serialize cycles in JSON.
336     using ArrayBase::pushBoolean;
337     using ArrayBase::pushInteger;
338     using ArrayBase::pushDouble;
339     using ArrayBase::pushString;
340     using ArrayBase::pushValue;
341     using ArrayBase::pushObject;
342     using ArrayBase::pushArray;
343
344     using ArrayBase::get;
345
346     using ArrayBase::begin;
347     using ArrayBase::end;
348 };
349
350
351 inline ObjectBase::iterator ObjectBase::find(const String& name)
352 {
353     return m_map.find(name);
354 }
355
356 inline ObjectBase::const_iterator ObjectBase::find(const String& name) const
357 {
358     return m_map.find(name);
359 }
360
361 inline void ObjectBase::setBoolean(const String& name, bool value)
362 {
363     setValue(name, Value::create(value));
364 }
365
366 inline void ObjectBase::setInteger(const String& name, int value)
367 {
368     setValue(name, Value::create(value));
369 }
370
371 inline void ObjectBase::setDouble(const String& name, double value)
372 {
373     setValue(name, Value::create(value));
374 }
375
376 inline void ObjectBase::setString(const String& name, const String& value)
377 {
378     setValue(name, Value::create(value));
379 }
380
381 inline void ObjectBase::setValue(const String& name, RefPtr<Value>&& value)
382 {
383     ASSERT(value);
384     if (m_map.set(name, WTFMove(value)).isNewEntry)
385         m_order.append(name);
386 }
387
388 inline void ObjectBase::setObject(const String& name, RefPtr<ObjectBase>&& value)
389 {
390     ASSERT(value);
391     if (m_map.set(name, WTFMove(value)).isNewEntry)
392         m_order.append(name);
393 }
394
395 inline void ObjectBase::setArray(const String& name, RefPtr<ArrayBase>&& value)
396 {
397     ASSERT(value);
398     if (m_map.set(name, WTFMove(value)).isNewEntry)
399         m_order.append(name);
400 }
401
402 inline void ArrayBase::pushBoolean(bool value)
403 {
404     m_map.append(Value::create(value));
405 }
406
407 inline void ArrayBase::pushInteger(int value)
408 {
409     m_map.append(Value::create(value));
410 }
411
412 inline void ArrayBase::pushDouble(double value)
413 {
414     m_map.append(Value::create(value));
415 }
416
417 inline void ArrayBase::pushString(const String& value)
418 {
419     m_map.append(Value::create(value));
420 }
421
422 inline void ArrayBase::pushValue(RefPtr<Value>&& value)
423 {
424     ASSERT(value);
425     m_map.append(WTFMove(value));
426 }
427
428 inline void ArrayBase::pushObject(RefPtr<ObjectBase>&& value)
429 {
430     ASSERT(value);
431     m_map.append(WTFMove(value));
432 }
433
434 inline void ArrayBase::pushArray(RefPtr<ArrayBase>&& value)
435 {
436     ASSERT(value);
437     m_map.append(WTFMove(value));
438 }
439
440 template<typename T>
441 class ArrayOf : public ArrayBase {
442 private:
443     ArrayOf() { }
444
445     Array& castedArray()
446     {
447         COMPILE_ASSERT(sizeof(Array) == sizeof(ArrayOf<T>), cannot_cast);
448         return *static_cast<Array*>(static_cast<ArrayBase*>(this));
449     }
450
451 public:
452     void addItem(RefPtr<T>&& value)
453     {
454         castedArray().pushValue(WTFMove(value));
455     }
456     
457     void addItem(const String& value)
458     {
459         castedArray().pushString(value);
460     }
461
462     void addItem(int value)
463     {
464         castedArray().pushInteger(value);
465     }
466
467     void addItem(double value)
468     {
469         castedArray().pushDouble(value);
470     }
471
472     static Ref<ArrayOf<T>> create()
473     {
474         return adoptRef(*new ArrayOf<T>());
475     }
476
477     using ArrayBase::get;
478     using ArrayBase::begin;
479     using ArrayBase::end;
480 };
481
482 } // namespace JSONImpl
483
484 } // namespace WTF
485
486 namespace JSON {
487 using namespace WTF::JSONImpl;
488 }
489