2 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
32 #include "platform/JSONValues.h"
34 #include "platform/Decimal.h"
35 #include "wtf/MathExtras.h"
36 #include "wtf/text/StringBuilder.h"
42 const char* const nullString
= "null";
43 const char* const trueString
= "true";
44 const char* const falseString
= "false";
46 inline bool escapeChar(UChar c
, StringBuilder
* dst
)
49 case '\b': dst
->appendLiteral("\\b"); break;
50 case '\f': dst
->appendLiteral("\\f"); break;
51 case '\n': dst
->appendLiteral("\\n"); break;
52 case '\r': dst
->appendLiteral("\\r"); break;
53 case '\t': dst
->appendLiteral("\\t"); break;
54 case '\\': dst
->appendLiteral("\\\\"); break;
55 case '"': dst
->appendLiteral("\\\""); break;
62 void writeIndent(int depth
, StringBuilder
* output
)
64 for (int i
= 0; i
< depth
; ++i
)
65 output
->appendLiteral(" ");
68 } // anonymous namespace
70 void doubleQuoteStringForJSON(const String
& str
, StringBuilder
* dst
)
73 for (unsigned i
= 0; i
< str
.length(); ++i
) {
75 if (!escapeChar(c
, dst
)) {
76 if (c
< 32 || c
> 126 || c
== '<' || c
== '>') {
77 // 1. Escaping <, > to prevent script execution.
78 // 2. Technically, we could also pass through c > 126 as UTF8, but this
79 // is also optional. It would also be a pain to implement here.
80 unsigned symbol
= static_cast<unsigned>(c
);
81 String symbolCode
= String::format("\\u%04X", symbol
);
82 dst
->append(symbolCode
);
91 String
JSONValue::quoteString(const String
& input
)
93 StringBuilder builder
;
94 doubleQuoteStringForJSON(input
, &builder
);
95 return builder
.toString();
98 bool JSONValue::asBoolean(bool*) const
103 bool JSONValue::asNumber(double*) const
108 bool JSONValue::asNumber(long*) const
113 bool JSONValue::asNumber(int*) const
118 bool JSONValue::asNumber(unsigned long*) const
123 bool JSONValue::asNumber(unsigned*) const
128 bool JSONValue::asString(String
*) const
133 bool JSONValue::asObject(RefPtr
<JSONObject
>*)
138 bool JSONValue::asArray(RefPtr
<JSONArray
>*)
143 PassRefPtr
<JSONObject
> JSONValue::asObject()
148 PassRefPtr
<JSONArray
> JSONValue::asArray()
153 String
JSONValue::toJSONString() const
155 StringBuilder result
;
156 result
.reserveCapacity(512);
158 return result
.toString();
161 String
JSONValue::toPrettyJSONString() const
163 StringBuilder result
;
164 result
.reserveCapacity(512);
165 prettyWriteJSON(&result
);
166 return result
.toString();
169 void JSONValue::writeJSON(StringBuilder
* output
) const
171 ASSERT(m_type
== TypeNull
);
172 output
->append(nullString
, 4);
175 void JSONValue::prettyWriteJSON(StringBuilder
* output
) const
177 prettyWriteJSONInternal(output
, 0);
178 output
->append('\n');
181 void JSONValue::prettyWriteJSONInternal(StringBuilder
* output
, int depth
) const
186 bool JSONBasicValue::asBoolean(bool* output
) const
188 if (type() != TypeBoolean
)
190 *output
= m_boolValue
;
194 bool JSONBasicValue::asNumber(double* output
) const
196 if (type() != TypeNumber
)
198 *output
= m_doubleValue
;
202 bool JSONBasicValue::asNumber(long* output
) const
204 if (type() != TypeNumber
)
206 *output
= static_cast<long>(m_doubleValue
);
210 bool JSONBasicValue::asNumber(int* output
) const
212 if (type() != TypeNumber
)
214 *output
= static_cast<int>(m_doubleValue
);
218 bool JSONBasicValue::asNumber(unsigned long* output
) const
220 if (type() != TypeNumber
)
222 *output
= static_cast<unsigned long>(m_doubleValue
);
226 bool JSONBasicValue::asNumber(unsigned* output
) const
228 if (type() != TypeNumber
)
230 *output
= static_cast<unsigned>(m_doubleValue
);
234 void JSONBasicValue::writeJSON(StringBuilder
* output
) const
236 ASSERT(type() == TypeBoolean
|| type() == TypeNumber
);
237 if (type() == TypeBoolean
) {
239 output
->append(trueString
, 4);
241 output
->append(falseString
, 5);
242 } else if (type() == TypeNumber
) {
243 if (!std::isfinite(m_doubleValue
)) {
244 output
->append(nullString
, 4);
247 output
->append(Decimal::fromDouble(m_doubleValue
).toString());
251 bool JSONString::asString(String
* output
) const
253 *output
= m_stringValue
;
257 void JSONString::writeJSON(StringBuilder
* output
) const
259 ASSERT(type() == TypeString
);
260 doubleQuoteStringForJSON(m_stringValue
, output
);
263 JSONObjectBase::~JSONObjectBase()
267 bool JSONObjectBase::asObject(RefPtr
<JSONObject
>* output
)
269 static_assert(sizeof(JSONObject
) == sizeof(JSONObjectBase
), "cannot cast");
270 *output
= static_cast<JSONObject
*>(this);
274 PassRefPtr
<JSONObject
> JSONObjectBase::asObject()
276 return openAccessors();
279 void JSONObjectBase::setBoolean(const String
& name
, bool value
)
281 setValue(name
, JSONBasicValue::create(value
));
284 void JSONObjectBase::setNumber(const String
& name
, double value
)
286 setValue(name
, JSONBasicValue::create(value
));
289 void JSONObjectBase::setString(const String
& name
, const String
& value
)
291 setValue(name
, JSONString::create(value
));
294 void JSONObjectBase::setValue(const String
& name
, PassRefPtr
<JSONValue
> value
)
297 if (m_data
.set(name
, value
).isNewEntry
)
298 m_order
.append(name
);
301 void JSONObjectBase::setObject(const String
& name
, PassRefPtr
<JSONObject
> value
)
304 if (m_data
.set(name
, value
).isNewEntry
)
305 m_order
.append(name
);
308 void JSONObjectBase::setArray(const String
& name
, PassRefPtr
<JSONArray
> value
)
311 if (m_data
.set(name
, value
).isNewEntry
)
312 m_order
.append(name
);
315 JSONObject
* JSONObjectBase::openAccessors()
317 static_assert(sizeof(JSONObject
) == sizeof(JSONObjectBase
), "cannot cast");
318 return static_cast<JSONObject
*>(this);
321 JSONObjectBase::iterator
JSONObjectBase::find(const String
& name
)
323 return m_data
.find(name
);
326 JSONObjectBase::const_iterator
JSONObjectBase::find(const String
& name
) const
328 return m_data
.find(name
);
331 bool JSONObjectBase::getBoolean(const String
& name
, bool* output
) const
333 RefPtr
<JSONValue
> value
= get(name
);
336 return value
->asBoolean(output
);
339 bool JSONObjectBase::getString(const String
& name
, String
* output
) const
341 RefPtr
<JSONValue
> value
= get(name
);
344 return value
->asString(output
);
347 PassRefPtr
<JSONObject
> JSONObjectBase::getObject(const String
& name
) const
349 RefPtr
<JSONValue
> value
= get(name
);
352 return value
->asObject();
355 PassRefPtr
<JSONArray
> JSONObjectBase::getArray(const String
& name
) const
357 RefPtr
<JSONValue
> value
= get(name
);
360 return value
->asArray();
363 PassRefPtr
<JSONValue
> JSONObjectBase::get(const String
& name
) const
365 Dictionary::const_iterator it
= m_data
.find(name
);
366 if (it
== m_data
.end())
371 void JSONObjectBase::remove(const String
& name
)
374 for (size_t i
= 0; i
< m_order
.size(); ++i
) {
375 if (m_order
[i
] == name
) {
382 void JSONObjectBase::writeJSON(StringBuilder
* output
) const
385 for (size_t i
= 0; i
< m_order
.size(); ++i
) {
386 Dictionary::const_iterator it
= m_data
.find(m_order
[i
]);
387 ASSERT_WITH_SECURITY_IMPLICATION(it
!= m_data
.end());
390 doubleQuoteStringForJSON(it
->key
, output
);
392 it
->value
->writeJSON(output
);
397 void JSONObjectBase::prettyWriteJSONInternal(StringBuilder
* output
, int depth
) const
399 output
->appendLiteral("{\n");
400 for (size_t i
= 0; i
< m_order
.size(); ++i
) {
401 Dictionary::const_iterator it
= m_data
.find(m_order
[i
]);
402 ASSERT_WITH_SECURITY_IMPLICATION(it
!= m_data
.end());
404 output
->appendLiteral(",\n");
405 writeIndent(depth
+ 1, output
);
406 doubleQuoteStringForJSON(it
->key
, output
);
407 output
->appendLiteral(": ");
408 it
->value
->prettyWriteJSONInternal(output
, depth
+ 1);
410 output
->append('\n');
411 writeIndent(depth
, output
);
415 JSONObjectBase::JSONObjectBase()
416 : JSONValue(TypeObject
)
422 JSONArrayBase::~JSONArrayBase()
426 bool JSONArrayBase::asArray(RefPtr
<JSONArray
>* output
)
428 static_assert(sizeof(JSONArrayBase
) == sizeof(JSONArray
), "cannot cast");
429 *output
= static_cast<JSONArray
*>(this);
433 PassRefPtr
<JSONArray
> JSONArrayBase::asArray()
435 static_assert(sizeof(JSONArrayBase
) == sizeof(JSONArray
), "cannot cast");
436 return static_cast<JSONArray
*>(this);
439 void JSONArrayBase::writeJSON(StringBuilder
* output
) const
442 for (Vector
<RefPtr
<JSONValue
>>::const_iterator it
= m_data
.begin(); it
!= m_data
.end(); ++it
) {
443 if (it
!= m_data
.begin())
445 (*it
)->writeJSON(output
);
450 void JSONArrayBase::prettyWriteJSONInternal(StringBuilder
* output
, int depth
) const
453 bool lastInsertedNewLine
= false;
454 for (Vector
<RefPtr
<JSONValue
>>::const_iterator it
= m_data
.begin(); it
!= m_data
.end(); ++it
) {
455 bool insertNewLine
= (*it
)->type() == JSONValue::TypeObject
|| (*it
)->type() == JSONValue::TypeArray
|| (*it
)->type() == JSONValue::TypeString
;
456 if (it
== m_data
.begin()) {
458 output
->append('\n');
459 writeIndent(depth
+ 1, output
);
463 if (lastInsertedNewLine
) {
464 output
->append('\n');
465 writeIndent(depth
+ 1, output
);
470 (*it
)->prettyWriteJSONInternal(output
, depth
+ 1);
471 lastInsertedNewLine
= insertNewLine
;
473 if (lastInsertedNewLine
) {
474 output
->append('\n');
475 writeIndent(depth
, output
);
480 JSONArrayBase::JSONArrayBase()
481 : JSONValue(TypeArray
)
486 void JSONArrayBase::pushBoolean(bool value
)
488 m_data
.append(JSONBasicValue::create(value
));
491 void JSONArrayBase::pushInt(int value
)
493 m_data
.append(JSONBasicValue::create(value
));
496 void JSONArrayBase::pushNumber(double value
)
498 m_data
.append(JSONBasicValue::create(value
));
501 void JSONArrayBase::pushString(const String
& value
)
503 m_data
.append(JSONString::create(value
));
506 void JSONArrayBase::pushValue(PassRefPtr
<JSONValue
> value
)
509 m_data
.append(value
);
512 void JSONArrayBase::pushObject(PassRefPtr
<JSONObject
> value
)
515 m_data
.append(value
);
518 void JSONArrayBase::pushArray(PassRefPtr
<JSONArray
> value
)
521 m_data
.append(value
);
524 PassRefPtr
<JSONValue
> JSONArrayBase::get(size_t index
)
526 ASSERT_WITH_SECURITY_IMPLICATION(index
< m_data
.size());
527 return m_data
[index
];