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