OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2010 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 #include "platform/JSONValues.h" | |
32 | |
33 #include "platform/Decimal.h" | |
34 #include "wtf/MathExtras.h" | |
35 #include "wtf/text/StringBuilder.h" | |
36 #include <algorithm> | |
37 #include <cmath> | |
38 | |
39 namespace blink { | |
40 | |
41 namespace { | |
42 | |
43 const char* const nullString = "null"; | |
44 const char* const trueString = "true"; | |
45 const char* const falseString = "false"; | |
46 | |
47 inline bool escapeChar(UChar c, StringBuilder* dst) | |
48 { | |
49 switch (c) { | |
50 case '\b': dst->append("\\b"); break; | |
51 case '\f': dst->append("\\f"); break; | |
52 case '\n': dst->append("\\n"); break; | |
53 case '\r': dst->append("\\r"); break; | |
54 case '\t': dst->append("\\t"); break; | |
55 case '\\': dst->append("\\\\"); break; | |
56 case '"': dst->append("\\\""); break; | |
57 default: | |
58 return false; | |
59 } | |
60 return true; | |
61 } | |
62 | |
63 const LChar hexDigits[17] = "0123456789ABCDEF"; | |
64 | |
65 void appendUnsignedAsHex(UChar number, StringBuilder* dst) | |
66 { | |
67 dst->append("\\u"); | |
68 for (size_t i = 0; i < 4; ++i) { | |
69 dst->append(hexDigits[(number & 0xF000) >> 12]); | |
70 number <<= 4; | |
71 } | |
72 } | |
73 | |
74 void writeIndent(int depth, StringBuilder* output) | |
75 { | |
76 for (int i = 0; i < depth; ++i) | |
77 output->append(" "); | |
78 } | |
79 | |
80 } // anonymous namespace | |
81 | |
82 void escapeStringForJSON(const String& str, StringBuilder* dst) | |
83 { | |
84 for (unsigned i = 0; i < str.length(); ++i) { | |
85 UChar c = str[i]; | |
86 if (!escapeChar(c, dst)) { | |
87 if (c < 32 || c > 126 || c == '<' || c == '>') { | |
88 // 1. Escaping <, > to prevent script execution. | |
89 // 2. Technically, we could also pass through c > 126 as UTF8, b
ut this | |
90 // is also optional. It would also be a pain to implement her
e. | |
91 appendUnsignedAsHex(c, dst); | |
92 } else { | |
93 dst->append(c); | |
94 } | |
95 } | |
96 } | |
97 } | |
98 | |
99 void doubleQuoteStringForJSON(const String& str, StringBuilder* dst) | |
100 { | |
101 dst->append('"'); | |
102 escapeStringForJSON(str, dst); | |
103 dst->append('"'); | |
104 } | |
105 | |
106 String JSONValue::quoteString(const String& input) | |
107 { | |
108 StringBuilder builder; | |
109 doubleQuoteStringForJSON(input, &builder); | |
110 return builder.toString(); | |
111 } | |
112 | |
113 bool JSONValue::asBoolean(bool*) const | |
114 { | |
115 return false; | |
116 } | |
117 | |
118 bool JSONValue::asDouble(double*) const | |
119 { | |
120 return false; | |
121 } | |
122 | |
123 bool JSONValue::asInteger(int*) const | |
124 { | |
125 return false; | |
126 } | |
127 | |
128 bool JSONValue::asString(String*) const | |
129 { | |
130 return false; | |
131 } | |
132 | |
133 String JSONValue::toJSONString() const | |
134 { | |
135 StringBuilder result; | |
136 result.reserveCapacity(512); | |
137 writeJSON(&result); | |
138 return result.toString(); | |
139 } | |
140 | |
141 String JSONValue::toPrettyJSONString() const | |
142 { | |
143 StringBuilder result; | |
144 result.reserveCapacity(512); | |
145 prettyWriteJSON(&result); | |
146 return result.toString(); | |
147 } | |
148 | |
149 void JSONValue::writeJSON(StringBuilder* output) const | |
150 { | |
151 DCHECK(m_type == TypeNull); | |
152 output->append(nullString, 4); | |
153 } | |
154 | |
155 void JSONValue::prettyWriteJSON(StringBuilder* output) const | |
156 { | |
157 prettyWriteJSONInternal(output, 0); | |
158 output->append('\n'); | |
159 } | |
160 | |
161 void JSONValue::prettyWriteJSONInternal(StringBuilder* output, int depth) const | |
162 { | |
163 writeJSON(output); | |
164 } | |
165 | |
166 std::unique_ptr<JSONValue> JSONValue::clone() const | |
167 { | |
168 return JSONValue::null(); | |
169 } | |
170 | |
171 bool JSONBasicValue::asBoolean(bool* output) const | |
172 { | |
173 if (getType() != TypeBoolean) | |
174 return false; | |
175 *output = m_boolValue; | |
176 return true; | |
177 } | |
178 | |
179 bool JSONBasicValue::asDouble(double* output) const | |
180 { | |
181 if (getType() == TypeDouble) { | |
182 *output = m_doubleValue; | |
183 return true; | |
184 } | |
185 if (getType() == TypeInteger) { | |
186 *output = m_integerValue; | |
187 return true; | |
188 } | |
189 return false; | |
190 } | |
191 | |
192 bool JSONBasicValue::asInteger(int* output) const | |
193 { | |
194 if (getType() != TypeInteger) | |
195 return false; | |
196 *output = m_integerValue; | |
197 return true; | |
198 } | |
199 | |
200 void JSONBasicValue::writeJSON(StringBuilder* output) const | |
201 { | |
202 DCHECK(getType() == TypeBoolean || getType() == TypeInteger || getType() ==
TypeDouble); | |
203 if (getType() == TypeBoolean) { | |
204 if (m_boolValue) | |
205 output->append(trueString, 4); | |
206 else | |
207 output->append(falseString, 5); | |
208 } else if (getType() == TypeDouble) { | |
209 if (!std::isfinite(m_doubleValue)) { | |
210 output->append(nullString, 4); | |
211 return; | |
212 } | |
213 output->append(Decimal::fromDouble(m_doubleValue).toString()); | |
214 } else if (getType() == TypeInteger) { | |
215 output->append(String::number(m_integerValue)); | |
216 } | |
217 } | |
218 | |
219 std::unique_ptr<JSONValue> JSONBasicValue::clone() const | |
220 { | |
221 switch (getType()) { | |
222 case TypeDouble: return JSONBasicValue::create(m_doubleValue); | |
223 case TypeInteger: return JSONBasicValue::create(m_integerValue); | |
224 case TypeBoolean: return JSONBasicValue::create(m_boolValue); | |
225 default: | |
226 NOTREACHED(); | |
227 } | |
228 return nullptr; | |
229 } | |
230 | |
231 bool JSONString::asString(String* output) const | |
232 { | |
233 *output = m_stringValue; | |
234 return true; | |
235 } | |
236 | |
237 void JSONString::writeJSON(StringBuilder* output) const | |
238 { | |
239 DCHECK(getType() == TypeString); | |
240 doubleQuoteStringForJSON(m_stringValue, output); | |
241 } | |
242 | |
243 std::unique_ptr<JSONValue> JSONString::clone() const | |
244 { | |
245 return JSONString::create(m_stringValue); | |
246 } | |
247 | |
248 JSONObject::~JSONObject() | |
249 { | |
250 } | |
251 | |
252 void JSONObject::setBoolean(const String& name, bool value) | |
253 { | |
254 setValue(name, JSONBasicValue::create(value)); | |
255 } | |
256 | |
257 void JSONObject::setInteger(const String& name, int value) | |
258 { | |
259 setValue(name, JSONBasicValue::create(value)); | |
260 } | |
261 | |
262 void JSONObject::setDouble(const String& name, double value) | |
263 { | |
264 setValue(name, JSONBasicValue::create(value)); | |
265 } | |
266 | |
267 void JSONObject::setString(const String& name, const String& value) | |
268 { | |
269 setValue(name, JSONString::create(value)); | |
270 } | |
271 | |
272 void JSONObject::setValue(const String& name, std::unique_ptr<JSONValue> value) | |
273 { | |
274 set(name, value); | |
275 } | |
276 | |
277 void JSONObject::setObject(const String& name, std::unique_ptr<JSONObject> value
) | |
278 { | |
279 set(name, value); | |
280 } | |
281 | |
282 void JSONObject::setArray(const String& name, std::unique_ptr<JSONArray> value) | |
283 { | |
284 set(name, value); | |
285 } | |
286 | |
287 bool JSONObject::getBoolean(const String& name, bool* output) const | |
288 { | |
289 JSONValue* value = get(name); | |
290 if (!value) | |
291 return false; | |
292 return value->asBoolean(output); | |
293 } | |
294 | |
295 bool JSONObject::getInteger(const String& name, int* output) const | |
296 { | |
297 JSONValue* value = get(name); | |
298 if (!value) | |
299 return false; | |
300 return value->asInteger(output); | |
301 } | |
302 | |
303 bool JSONObject::getDouble(const String& name, double* output) const | |
304 { | |
305 JSONValue* value = get(name); | |
306 if (!value) | |
307 return false; | |
308 return value->asDouble(output); | |
309 } | |
310 | |
311 bool JSONObject::getString(const String& name, String* output) const | |
312 { | |
313 JSONValue* value = get(name); | |
314 if (!value) | |
315 return false; | |
316 return value->asString(output); | |
317 } | |
318 | |
319 JSONObject* JSONObject::getObject(const String& name) const | |
320 { | |
321 return JSONObject::cast(get(name)); | |
322 } | |
323 | |
324 JSONArray* JSONObject::getArray(const String& name) const | |
325 { | |
326 return JSONArray::cast(get(name)); | |
327 } | |
328 | |
329 JSONValue* JSONObject::get(const String& name) const | |
330 { | |
331 Dictionary::const_iterator it = m_data.find(name); | |
332 if (it == m_data.end()) | |
333 return nullptr; | |
334 return it->value.get(); | |
335 } | |
336 | |
337 JSONObject::Entry JSONObject::at(size_t index) const | |
338 { | |
339 const String key = m_order[index]; | |
340 return std::make_pair(key, m_data.find(key)->value.get()); | |
341 } | |
342 | |
343 bool JSONObject::booleanProperty(const String& name, bool defaultValue) const | |
344 { | |
345 bool result = defaultValue; | |
346 getBoolean(name, &result); | |
347 return result; | |
348 } | |
349 | |
350 int JSONObject::integerProperty(const String& name, int defaultValue) const | |
351 { | |
352 int result = defaultValue; | |
353 getInteger(name, &result); | |
354 return result; | |
355 } | |
356 | |
357 double JSONObject::doubleProperty(const String& name, double defaultValue) const | |
358 { | |
359 double result = defaultValue; | |
360 getDouble(name, &result); | |
361 return result; | |
362 } | |
363 | |
364 void JSONObject::remove(const String& name) | |
365 { | |
366 m_data.remove(name); | |
367 for (size_t i = 0; i < m_order.size(); ++i) { | |
368 if (m_order[i] == name) { | |
369 m_order.remove(i); | |
370 break; | |
371 } | |
372 } | |
373 } | |
374 | |
375 void JSONObject::writeJSON(StringBuilder* output) const | |
376 { | |
377 output->append('{'); | |
378 for (size_t i = 0; i < m_order.size(); ++i) { | |
379 Dictionary::const_iterator it = m_data.find(m_order[i]); | |
380 CHECK(it != m_data.end()); | |
381 if (i) | |
382 output->append(','); | |
383 doubleQuoteStringForJSON(it->key, output); | |
384 output->append(':'); | |
385 it->value->writeJSON(output); | |
386 } | |
387 output->append('}'); | |
388 } | |
389 | |
390 void JSONObject::prettyWriteJSONInternal(StringBuilder* output, int depth) const | |
391 { | |
392 output->append("{\n"); | |
393 for (size_t i = 0; i < m_order.size(); ++i) { | |
394 Dictionary::const_iterator it = m_data.find(m_order[i]); | |
395 CHECK(it != m_data.end()); | |
396 if (i) | |
397 output->append(",\n"); | |
398 writeIndent(depth + 1, output); | |
399 doubleQuoteStringForJSON(it->key, output); | |
400 output->append(": "); | |
401 it->value->prettyWriteJSONInternal(output, depth + 1); | |
402 } | |
403 output->append('\n'); | |
404 writeIndent(depth, output); | |
405 output->append('}'); | |
406 } | |
407 | |
408 std::unique_ptr<JSONValue> JSONObject::clone() const | |
409 { | |
410 std::unique_ptr<JSONObject> result = JSONObject::create(); | |
411 for (size_t i = 0; i < m_order.size(); ++i) { | |
412 String key = m_order[i]; | |
413 Dictionary::const_iterator value = m_data.find(key); | |
414 DCHECK(value != m_data.end() && value->value); | |
415 result->setValue(key, value->value->clone()); | |
416 } | |
417 return std::move(result); | |
418 } | |
419 | |
420 JSONObject::JSONObject() | |
421 : JSONValue(TypeObject) | |
422 , m_data() | |
423 , m_order() | |
424 { | |
425 } | |
426 | |
427 JSONArray::~JSONArray() | |
428 { | |
429 } | |
430 | |
431 void JSONArray::writeJSON(StringBuilder* output) const | |
432 { | |
433 output->append('['); | |
434 bool first = true; | |
435 for (const std::unique_ptr<JSONValue>& value : m_data) { | |
436 if (!first) | |
437 output->append(','); | |
438 value->writeJSON(output); | |
439 first = false; | |
440 } | |
441 output->append(']'); | |
442 } | |
443 | |
444 void JSONArray::prettyWriteJSONInternal(StringBuilder* output, int depth) const | |
445 { | |
446 output->append('['); | |
447 bool first = true; | |
448 bool lastInsertedNewLine = false; | |
449 for (const std::unique_ptr<JSONValue>& value : m_data) { | |
450 bool insertNewLine = value->getType() == JSONValue::TypeObject || value-
>getType() == JSONValue::TypeArray || value->getType() == JSONValue::TypeString; | |
451 if (first) { | |
452 if (insertNewLine) { | |
453 output->append('\n'); | |
454 writeIndent(depth + 1, output); | |
455 } | |
456 first = false; | |
457 } else { | |
458 output->append(','); | |
459 if (lastInsertedNewLine) { | |
460 output->append('\n'); | |
461 writeIndent(depth + 1, output); | |
462 } else { | |
463 output->append(' '); | |
464 } | |
465 } | |
466 value->prettyWriteJSONInternal(output, depth + 1); | |
467 lastInsertedNewLine = insertNewLine; | |
468 } | |
469 if (lastInsertedNewLine) { | |
470 output->append('\n'); | |
471 writeIndent(depth, output); | |
472 } | |
473 output->append(']'); | |
474 } | |
475 | |
476 std::unique_ptr<JSONValue> JSONArray::clone() const | |
477 { | |
478 std::unique_ptr<JSONArray> result = JSONArray::create(); | |
479 for (const std::unique_ptr<JSONValue>& value : m_data) | |
480 result->pushValue(value->clone()); | |
481 return std::move(result); | |
482 } | |
483 | |
484 JSONArray::JSONArray() | |
485 : JSONValue(TypeArray) | |
486 { | |
487 } | |
488 | |
489 void JSONArray::pushBoolean(bool value) | |
490 { | |
491 m_data.append(JSONBasicValue::create(value)); | |
492 } | |
493 | |
494 void JSONArray::pushInteger(int value) | |
495 { | |
496 m_data.append(JSONBasicValue::create(value)); | |
497 } | |
498 | |
499 void JSONArray::pushDouble(double value) | |
500 { | |
501 m_data.append(JSONBasicValue::create(value)); | |
502 } | |
503 | |
504 void JSONArray::pushString(const String& value) | |
505 { | |
506 m_data.append(JSONString::create(value)); | |
507 } | |
508 | |
509 void JSONArray::pushValue(std::unique_ptr<JSONValue> value) | |
510 { | |
511 DCHECK(value); | |
512 m_data.append(std::move(value)); | |
513 } | |
514 | |
515 void JSONArray::pushObject(std::unique_ptr<JSONObject> value) | |
516 { | |
517 DCHECK(value); | |
518 m_data.append(std::move(value)); | |
519 } | |
520 | |
521 void JSONArray::pushArray(std::unique_ptr<JSONArray> value) | |
522 { | |
523 DCHECK(value); | |
524 m_data.append(std::move(value)); | |
525 } | |
526 | |
527 JSONValue* JSONArray::at(size_t index) | |
528 { | |
529 DCHECK_LT(index, m_data.size()); | |
530 return m_data[index].get(); | |
531 } | |
532 | |
533 } // namespace blink | |
OLD | NEW |