1/*
2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#ifndef JSONValues_h
32#define JSONValues_h
33
34#include "platform/PlatformExport.h"
35#include "wtf/Forward.h"
36#include "wtf/HashMap.h"
37#include "wtf/RefCounted.h"
38#include "wtf/Vector.h"
39#include "wtf/text/StringHash.h"
40#include "wtf/text/WTFString.h"
41
42namespace WebCore {
43
44class JSONArray;
45class JSONObject;
46
47class PLATFORM_EXPORT JSONValue : public RefCounted<JSONValue> {
48public:
49    static const int maxDepth = 1000;
50
51    JSONValue() : m_type(TypeNull) { }
52    virtual ~JSONValue() { }
53
54    static PassRefPtr<JSONValue> null()
55    {
56        return adoptRef(new JSONValue());
57    }
58
59    typedef enum {
60        TypeNull = 0,
61        TypeBoolean,
62        TypeNumber,
63        TypeString,
64        TypeObject,
65        TypeArray
66    } Type;
67
68    Type type() const { return m_type; }
69
70    bool isNull() const { return m_type == TypeNull; }
71
72    virtual bool asBoolean(bool* output) const;
73    virtual bool asNumber(double* output) const;
74    virtual bool asNumber(long* output) const;
75    virtual bool asNumber(int* output) const;
76    virtual bool asNumber(unsigned long* output) const;
77    virtual bool asNumber(unsigned* output) const;
78    virtual bool asString(String* output) const;
79    virtual bool asValue(RefPtr<JSONValue>* output);
80    virtual bool asObject(RefPtr<JSONObject>* output);
81    virtual bool asArray(RefPtr<JSONArray>* output);
82    virtual PassRefPtr<JSONObject> asObject();
83    virtual PassRefPtr<JSONArray> asArray();
84
85    String toJSONString() const;
86    virtual void writeJSON(StringBuilder* output) const;
87
88protected:
89    explicit JSONValue(Type type) : m_type(type) { }
90
91private:
92    Type m_type;
93};
94
95class PLATFORM_EXPORT JSONBasicValue : public JSONValue {
96public:
97
98    static PassRefPtr<JSONBasicValue> create(bool value)
99    {
100        return adoptRef(new JSONBasicValue(value));
101    }
102
103    static PassRefPtr<JSONBasicValue> create(int value)
104    {
105        return adoptRef(new JSONBasicValue(value));
106    }
107
108    static PassRefPtr<JSONBasicValue> create(double value)
109    {
110        return adoptRef(new JSONBasicValue(value));
111    }
112
113    virtual bool asBoolean(bool* output) const;
114    virtual bool asNumber(double* output) const;
115    virtual bool asNumber(long* output) const;
116    virtual bool asNumber(int* output) const;
117    virtual bool asNumber(unsigned long* output) const;
118    virtual bool asNumber(unsigned* output) const;
119
120    virtual void writeJSON(StringBuilder* output) const;
121
122private:
123    explicit JSONBasicValue(bool value) : JSONValue(TypeBoolean), m_boolValue(value) { }
124    explicit JSONBasicValue(int value) : JSONValue(TypeNumber), m_doubleValue((double)value) { }
125    explicit JSONBasicValue(double value) : JSONValue(TypeNumber), m_doubleValue(value) { }
126
127    union {
128        bool m_boolValue;
129        double m_doubleValue;
130    };
131};
132
133class PLATFORM_EXPORT JSONString : public JSONValue {
134public:
135    static PassRefPtr<JSONString> create(const String& value)
136    {
137        return adoptRef(new JSONString(value));
138    }
139
140    static PassRefPtr<JSONString> create(const char* value)
141    {
142        return adoptRef(new JSONString(value));
143    }
144
145    virtual bool asString(String* output) const;
146
147    virtual void writeJSON(StringBuilder* output) const;
148
149private:
150    explicit JSONString(const String& value) : JSONValue(TypeString), m_stringValue(value) { }
151    explicit JSONString(const char* value) : JSONValue(TypeString), m_stringValue(value) { }
152
153    String m_stringValue;
154};
155
156class PLATFORM_EXPORT JSONObjectBase : public JSONValue {
157private:
158    typedef HashMap<String, RefPtr<JSONValue> > Dictionary;
159
160public:
161    typedef Dictionary::iterator iterator;
162    typedef Dictionary::const_iterator const_iterator;
163
164    virtual PassRefPtr<JSONObject> asObject();
165    JSONObject* openAccessors();
166
167protected:
168    ~JSONObjectBase();
169
170    virtual bool asObject(RefPtr<JSONObject>* output);
171
172    void setBoolean(const String& name, bool);
173    void setNumber(const String& name, double);
174    void setString(const String& name, const String&);
175    void setValue(const String& name, PassRefPtr<JSONValue>);
176    void setObject(const String& name, PassRefPtr<JSONObject>);
177    void setArray(const String& name, PassRefPtr<JSONArray>);
178
179    iterator find(const String& name);
180    const_iterator find(const String& name) const;
181    bool getBoolean(const String& name, bool* output) const;
182    template<class T> bool getNumber(const String& name, T* output) const
183    {
184        RefPtr<JSONValue> value = get(name);
185        if (!value)
186            return false;
187        return value->asNumber(output);
188    }
189    bool getString(const String& name, String* output) const;
190    PassRefPtr<JSONObject> getObject(const String& name) const;
191    PassRefPtr<JSONArray> getArray(const String& name) const;
192    PassRefPtr<JSONValue> get(const String& name) const;
193
194    void remove(const String& name);
195
196    virtual void writeJSON(StringBuilder* output) const;
197
198    iterator begin() { return m_data.begin(); }
199    iterator end() { return m_data.end(); }
200    const_iterator begin() const { return m_data.begin(); }
201    const_iterator end() const { return m_data.end(); }
202
203    int size() const { return m_data.size(); }
204
205protected:
206    JSONObjectBase();
207
208private:
209    Dictionary m_data;
210    Vector<String> m_order;
211};
212
213class PLATFORM_EXPORT JSONObject : public JSONObjectBase {
214public:
215    static PassRefPtr<JSONObject> create()
216    {
217        return adoptRef(new JSONObject());
218    }
219
220    using JSONObjectBase::asObject;
221
222    using JSONObjectBase::setBoolean;
223    using JSONObjectBase::setNumber;
224    using JSONObjectBase::setString;
225    using JSONObjectBase::setValue;
226    using JSONObjectBase::setObject;
227    using JSONObjectBase::setArray;
228
229    using JSONObjectBase::find;
230    using JSONObjectBase::getBoolean;
231    using JSONObjectBase::getNumber;
232    using JSONObjectBase::getString;
233    using JSONObjectBase::getObject;
234    using JSONObjectBase::getArray;
235    using JSONObjectBase::get;
236
237    using JSONObjectBase::remove;
238
239    using JSONObjectBase::begin;
240    using JSONObjectBase::end;
241
242    using JSONObjectBase::size;
243};
244
245
246class PLATFORM_EXPORT JSONArrayBase : public JSONValue {
247public:
248    typedef Vector<RefPtr<JSONValue> >::iterator iterator;
249    typedef Vector<RefPtr<JSONValue> >::const_iterator const_iterator;
250
251    virtual PassRefPtr<JSONArray> asArray();
252
253    unsigned length() const { return m_data.size(); }
254
255protected:
256    ~JSONArrayBase();
257
258    virtual bool asArray(RefPtr<JSONArray>* output);
259
260    void pushBoolean(bool);
261    void pushInt(int);
262    void pushNumber(double);
263    void pushString(const String&);
264    void pushValue(PassRefPtr<JSONValue>);
265    void pushObject(PassRefPtr<JSONObject>);
266    void pushArray(PassRefPtr<JSONArray>);
267
268    PassRefPtr<JSONValue> get(size_t index);
269
270    virtual void writeJSON(StringBuilder* output) const;
271
272    iterator begin() { return m_data.begin(); }
273    iterator end() { return m_data.end(); }
274    const_iterator begin() const { return m_data.begin(); }
275    const_iterator end() const { return m_data.end(); }
276
277protected:
278    JSONArrayBase();
279
280private:
281    Vector<RefPtr<JSONValue> > m_data;
282};
283
284class PLATFORM_EXPORT JSONArray : public JSONArrayBase {
285public:
286    static PassRefPtr<JSONArray> create()
287    {
288        return adoptRef(new JSONArray());
289    }
290
291    using JSONArrayBase::asArray;
292
293    using JSONArrayBase::pushBoolean;
294    using JSONArrayBase::pushInt;
295    using JSONArrayBase::pushNumber;
296    using JSONArrayBase::pushString;
297    using JSONArrayBase::pushValue;
298    using JSONArrayBase::pushObject;
299    using JSONArrayBase::pushArray;
300
301    using JSONArrayBase::get;
302
303    using JSONArrayBase::begin;
304    using JSONArrayBase::end;
305};
306
307
308inline JSONObjectBase::iterator JSONObjectBase::find(const String& name)
309{
310    return m_data.find(name);
311}
312
313inline JSONObjectBase::const_iterator JSONObjectBase::find(const String& name) const
314{
315    return m_data.find(name);
316}
317
318inline void JSONObjectBase::setBoolean(const String& name, bool value)
319{
320    setValue(name, JSONBasicValue::create(value));
321}
322
323inline void JSONObjectBase::setNumber(const String& name, double value)
324{
325    setValue(name, JSONBasicValue::create(value));
326}
327
328inline void JSONObjectBase::setString(const String& name, const String& value)
329{
330    setValue(name, JSONString::create(value));
331}
332
333inline void JSONObjectBase::setValue(const String& name, PassRefPtr<JSONValue> value)
334{
335    ASSERT(value);
336    if (m_data.set(name, value).isNewEntry)
337        m_order.append(name);
338}
339
340inline void JSONObjectBase::setObject(const String& name, PassRefPtr<JSONObject> value)
341{
342    ASSERT(value);
343    if (m_data.set(name, value).isNewEntry)
344        m_order.append(name);
345}
346
347inline void JSONObjectBase::setArray(const String& name, PassRefPtr<JSONArray> value)
348{
349    ASSERT(value);
350    if (m_data.set(name, value).isNewEntry)
351        m_order.append(name);
352}
353
354inline void JSONArrayBase::pushBoolean(bool value)
355{
356    m_data.append(JSONBasicValue::create(value));
357}
358
359inline void JSONArrayBase::pushInt(int value)
360{
361    m_data.append(JSONBasicValue::create(value));
362}
363
364inline void JSONArrayBase::pushNumber(double value)
365{
366    m_data.append(JSONBasicValue::create(value));
367}
368
369inline void JSONArrayBase::pushString(const String& value)
370{
371    m_data.append(JSONString::create(value));
372}
373
374inline void JSONArrayBase::pushValue(PassRefPtr<JSONValue> value)
375{
376    ASSERT(value);
377    m_data.append(value);
378}
379
380inline void JSONArrayBase::pushObject(PassRefPtr<JSONObject> value)
381{
382    ASSERT(value);
383    m_data.append(value);
384}
385
386inline void JSONArrayBase::pushArray(PassRefPtr<JSONArray> value)
387{
388    ASSERT(value);
389    m_data.append(value);
390}
391
392} // namespace WebCore
393
394#endif // !defined(JSONValues_h)
395