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 WebCore {
     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->append("\\b", 2); break;
     50     case '\f': dst->append("\\f", 2); break;
     51     case '\n': dst->append("\\n", 2); break;
     52     case '\r': dst->append("\\r", 2); break;
     53     case '\t': dst->append("\\t", 2); break;
     54     case '\\': dst->append("\\\\", 2); break;
     55     case '"': dst->append("\\\"", 2); 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 } // anonymous namespace
     84 
     85 bool JSONValue::asBoolean(bool*) const
     86 {
     87     return false;
     88 }
     89 
     90 bool JSONValue::asNumber(double*) const
     91 {
     92     return false;
     93 }
     94 
     95 bool JSONValue::asNumber(long*) const
     96 {
     97     return false;
     98 }
     99 
    100 bool JSONValue::asNumber(int*) const
    101 {
    102     return false;
    103 }
    104 
    105 bool JSONValue::asNumber(unsigned long*) const
    106 {
    107     return false;
    108 }
    109 
    110 bool JSONValue::asNumber(unsigned*) const
    111 {
    112     return false;
    113 }
    114 
    115 bool JSONValue::asString(String*) const
    116 {
    117     return false;
    118 }
    119 
    120 bool JSONValue::asValue(RefPtr<JSONValue>* output)
    121 {
    122     *output = this;
    123     return true;
    124 }
    125 
    126 bool JSONValue::asObject(RefPtr<JSONObject>*)
    127 {
    128     return false;
    129 }
    130 
    131 bool JSONValue::asArray(RefPtr<JSONArray>*)
    132 {
    133     return false;
    134 }
    135 
    136 PassRefPtr<JSONObject> JSONValue::asObject()
    137 {
    138     return nullptr;
    139 }
    140 
    141 PassRefPtr<JSONArray> JSONValue::asArray()
    142 {
    143     return nullptr;
    144 }
    145 
    146 String JSONValue::toJSONString() const
    147 {
    148     StringBuilder result;
    149     result.reserveCapacity(512);
    150     writeJSON(&result);
    151     return result.toString();
    152 }
    153 
    154 void JSONValue::writeJSON(StringBuilder* output) const
    155 {
    156     ASSERT(m_type == TypeNull);
    157     output->append(nullString, 4);
    158 }
    159 
    160 bool JSONBasicValue::asBoolean(bool* output) const
    161 {
    162     if (type() != TypeBoolean)
    163         return false;
    164     *output = m_boolValue;
    165     return true;
    166 }
    167 
    168 bool JSONBasicValue::asNumber(double* output) const
    169 {
    170     if (type() != TypeNumber)
    171         return false;
    172     *output = m_doubleValue;
    173     return true;
    174 }
    175 
    176 bool JSONBasicValue::asNumber(long* output) const
    177 {
    178     if (type() != TypeNumber)
    179         return false;
    180     *output = static_cast<long>(m_doubleValue);
    181     return true;
    182 }
    183 
    184 bool JSONBasicValue::asNumber(int* output) const
    185 {
    186     if (type() != TypeNumber)
    187         return false;
    188     *output = static_cast<int>(m_doubleValue);
    189     return true;
    190 }
    191 
    192 bool JSONBasicValue::asNumber(unsigned long* output) const
    193 {
    194     if (type() != TypeNumber)
    195         return false;
    196     *output = static_cast<unsigned long>(m_doubleValue);
    197     return true;
    198 }
    199 
    200 bool JSONBasicValue::asNumber(unsigned* output) const
    201 {
    202     if (type() != TypeNumber)
    203         return false;
    204     *output = static_cast<unsigned>(m_doubleValue);
    205     return true;
    206 }
    207 
    208 void JSONBasicValue::writeJSON(StringBuilder* output) const
    209 {
    210     ASSERT(type() == TypeBoolean || type() == TypeNumber);
    211     if (type() == TypeBoolean) {
    212         if (m_boolValue)
    213             output->append(trueString, 4);
    214         else
    215             output->append(falseString, 5);
    216     } else if (type() == TypeNumber) {
    217         if (!std::isfinite(m_doubleValue)) {
    218             output->append(nullString, 4);
    219             return;
    220         }
    221         output->append(Decimal::fromDouble(m_doubleValue).toString());
    222     }
    223 }
    224 
    225 bool JSONString::asString(String* output) const
    226 {
    227     *output = m_stringValue;
    228     return true;
    229 }
    230 
    231 void JSONString::writeJSON(StringBuilder* output) const
    232 {
    233     ASSERT(type() == TypeString);
    234     doubleQuoteString(m_stringValue, output);
    235 }
    236 
    237 JSONObjectBase::~JSONObjectBase()
    238 {
    239 }
    240 
    241 bool JSONObjectBase::asObject(RefPtr<JSONObject>* output)
    242 {
    243     COMPILE_ASSERT(sizeof(JSONObject) == sizeof(JSONObjectBase), cannot_cast);
    244     *output = static_cast<JSONObject*>(this);
    245     return true;
    246 }
    247 
    248 PassRefPtr<JSONObject> JSONObjectBase::asObject()
    249 {
    250     return openAccessors();
    251 }
    252 
    253 void JSONObjectBase::setBoolean(const String& name, bool value)
    254 {
    255     setValue(name, JSONBasicValue::create(value));
    256 }
    257 
    258 void JSONObjectBase::setNumber(const String& name, double value)
    259 {
    260     setValue(name, JSONBasicValue::create(value));
    261 }
    262 
    263 void JSONObjectBase::setString(const String& name, const String& value)
    264 {
    265     setValue(name, JSONString::create(value));
    266 }
    267 
    268 void JSONObjectBase::setValue(const String& name, PassRefPtr<JSONValue> value)
    269 {
    270     ASSERT(value);
    271     if (m_data.set(name, value).isNewEntry)
    272         m_order.append(name);
    273 }
    274 
    275 void JSONObjectBase::setObject(const String& name, PassRefPtr<JSONObject> value)
    276 {
    277     ASSERT(value);
    278     if (m_data.set(name, value).isNewEntry)
    279         m_order.append(name);
    280 }
    281 
    282 void JSONObjectBase::setArray(const String& name, PassRefPtr<JSONArray> value)
    283 {
    284     ASSERT(value);
    285     if (m_data.set(name, value).isNewEntry)
    286         m_order.append(name);
    287 }
    288 
    289 JSONObject* JSONObjectBase::openAccessors()
    290 {
    291     COMPILE_ASSERT(sizeof(JSONObject) == sizeof(JSONObjectBase), cannot_cast);
    292     return static_cast<JSONObject*>(this);
    293 }
    294 
    295 JSONObjectBase::iterator JSONObjectBase::find(const String& name)
    296 {
    297     return m_data.find(name);
    298 }
    299 
    300 JSONObjectBase::const_iterator JSONObjectBase::find(const String& name) const
    301 {
    302     return m_data.find(name);
    303 }
    304 
    305 bool JSONObjectBase::getBoolean(const String& name, bool* output) const
    306 {
    307     RefPtr<JSONValue> value = get(name);
    308     if (!value)
    309         return false;
    310     return value->asBoolean(output);
    311 }
    312 
    313 bool JSONObjectBase::getString(const String& name, String* output) const
    314 {
    315     RefPtr<JSONValue> value = get(name);
    316     if (!value)
    317         return false;
    318     return value->asString(output);
    319 }
    320 
    321 PassRefPtr<JSONObject> JSONObjectBase::getObject(const String& name) const
    322 {
    323     RefPtr<JSONValue> value = get(name);
    324     if (!value)
    325         return nullptr;
    326     return value->asObject();
    327 }
    328 
    329 PassRefPtr<JSONArray> JSONObjectBase::getArray(const String& name) const
    330 {
    331     RefPtr<JSONValue> value = get(name);
    332     if (!value)
    333         return nullptr;
    334     return value->asArray();
    335 }
    336 
    337 PassRefPtr<JSONValue> JSONObjectBase::get(const String& name) const
    338 {
    339     Dictionary::const_iterator it = m_data.find(name);
    340     if (it == m_data.end())
    341         return nullptr;
    342     return it->value;
    343 }
    344 
    345 void JSONObjectBase::remove(const String& name)
    346 {
    347     m_data.remove(name);
    348     for (size_t i = 0; i < m_order.size(); ++i) {
    349         if (m_order[i] == name) {
    350             m_order.remove(i);
    351             break;
    352         }
    353     }
    354 }
    355 
    356 void JSONObjectBase::writeJSON(StringBuilder* output) const
    357 {
    358     output->append('{');
    359     for (size_t i = 0; i < m_order.size(); ++i) {
    360         Dictionary::const_iterator it = m_data.find(m_order[i]);
    361         ASSERT_WITH_SECURITY_IMPLICATION(it != m_data.end());
    362         if (i)
    363             output->append(',');
    364         doubleQuoteString(it->key, output);
    365         output->append(':');
    366         it->value->writeJSON(output);
    367     }
    368     output->append('}');
    369 }
    370 
    371 JSONObjectBase::JSONObjectBase()
    372     : JSONValue(TypeObject)
    373     , m_data()
    374     , m_order()
    375 {
    376 }
    377 
    378 JSONArrayBase::~JSONArrayBase()
    379 {
    380 }
    381 
    382 bool JSONArrayBase::asArray(RefPtr<JSONArray>* output)
    383 {
    384     COMPILE_ASSERT(sizeof(JSONArrayBase) == sizeof(JSONArray), cannot_cast);
    385     *output = static_cast<JSONArray*>(this);
    386     return true;
    387 }
    388 
    389 PassRefPtr<JSONArray> JSONArrayBase::asArray()
    390 {
    391     COMPILE_ASSERT(sizeof(JSONArrayBase) == sizeof(JSONArray), cannot_cast);
    392     return static_cast<JSONArray*>(this);
    393 }
    394 
    395 void JSONArrayBase::writeJSON(StringBuilder* output) const
    396 {
    397     output->append('[');
    398     for (Vector<RefPtr<JSONValue> >::const_iterator it = m_data.begin(); it != m_data.end(); ++it) {
    399         if (it != m_data.begin())
    400             output->append(',');
    401         (*it)->writeJSON(output);
    402     }
    403     output->append(']');
    404 }
    405 
    406 JSONArrayBase::JSONArrayBase()
    407     : JSONValue(TypeArray)
    408     , m_data()
    409 {
    410 }
    411 
    412 void JSONArrayBase::pushBoolean(bool value)
    413 {
    414     m_data.append(JSONBasicValue::create(value));
    415 }
    416 
    417 void JSONArrayBase::pushInt(int value)
    418 {
    419     m_data.append(JSONBasicValue::create(value));
    420 }
    421 
    422 void JSONArrayBase::pushNumber(double value)
    423 {
    424     m_data.append(JSONBasicValue::create(value));
    425 }
    426 
    427 void JSONArrayBase::pushString(const String& value)
    428 {
    429     m_data.append(JSONString::create(value));
    430 }
    431 
    432 void JSONArrayBase::pushValue(PassRefPtr<JSONValue> value)
    433 {
    434     ASSERT(value);
    435     m_data.append(value);
    436 }
    437 
    438 void JSONArrayBase::pushObject(PassRefPtr<JSONObject> value)
    439 {
    440     ASSERT(value);
    441     m_data.append(value);
    442 }
    443 
    444 void JSONArrayBase::pushArray(PassRefPtr<JSONArray> value)
    445 {
    446     ASSERT(value);
    447     m_data.append(value);
    448 }
    449 
    450 PassRefPtr<JSONValue> JSONArrayBase::get(size_t index)
    451 {
    452     ASSERT_WITH_SECURITY_IMPLICATION(index < m_data.size());
    453     return m_data[index];
    454 }
    455 
    456 } // namespace WebCore
    457