ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

json.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 /*
00024  * Files JSON.cpp and JSONValue.cpp part of the SimpleJSON Library - https://github.com/MJPA/SimpleJSON
00025  *
00026  * Copyright (C) 2010 Mike Anchor
00027  *
00028  * Permission is hereby granted, free of charge, to any person obtaining a copy
00029  * of this software and associated documentation files (the "Software"), to deal
00030  * in the Software without restriction, including without limitation the rights
00031  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00032  * copies of the Software, and to permit persons to whom the Software is
00033  * furnished to do so, subject to the following conditions:
00034  *
00035  * The above copyright notice and this permission notice shall be included in
00036  * all copies or substantial portions of the Software.
00037  *
00038  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00039  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00040  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00041  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00042  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00043  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00044  * THE SOFTWARE.
00045  */
00046 
00047 #include "common/json.h"
00048 
00049 #ifdef __MINGW32__
00050 #define wcsncasecmp wcsnicmp
00051 #endif
00052 
00053 // Macros to free an array/object
00054 #define FREE_ARRAY(x) { JSONArray::iterator iter; for (iter = x.begin(); iter != x.end(); iter++) { delete *iter; } }
00055 #define FREE_OBJECT(x) { JSONObject::iterator iter; for (iter = x.begin(); iter != x.end(); iter++) { delete (*iter)._value; } }
00056 
00057 namespace Common {
00058 
00065 JSON::JSON() {}
00066 
00076 JSONValue *JSON::parse(const char *data) {
00077     // Skip any preceding whitespace, end of data = no JSON = fail
00078     if (!skipWhitespace(&data))
00079         return nullptr;
00080 
00081     // We need the start of a value here now...
00082     JSONValue *value = JSONValue::parse(&data);
00083     if (value == nullptr)
00084         return nullptr;
00085 
00086     // Can be white space now and should be at the end of the string then...
00087     if (skipWhitespace(&data)) {
00088         delete value;
00089         return nullptr;
00090     }
00091 
00092     // We're now at the end of the string
00093     return value;
00094 }
00095 
00105 String JSON::stringify(const JSONValue *value) {
00106     if (value != nullptr)
00107         return value->stringify();
00108     else
00109         return "";
00110 }
00111 
00121 bool JSON::skipWhitespace(const char **data) {
00122     while (**data != 0 && (**data == ' ' || **data == '\t' || **data == '\r' || **data == '\n'))
00123         (*data)++;
00124 
00125     return **data != 0;
00126 }
00127 
00139 bool JSON::extractString(const char **data, String &str) {
00140     str = "";
00141 
00142     while (**data != 0) {
00143         // Save the char so we can change it if need be
00144         char next_char = **data;
00145 
00146         // Escaping something?
00147         if (next_char == '\\') {
00148             // Move over the escape char
00149             (*data)++;
00150 
00151             // Deal with the escaped char
00152             switch (**data) {
00153             case '"': next_char = '"';
00154                 break;
00155             case '\\': next_char = '\\';
00156                 break;
00157             case '/': next_char = '/';
00158                 break;
00159             case 'b': next_char = '\b';
00160                 break;
00161             case 'f': next_char = '\f';
00162                 break;
00163             case 'n': next_char = '\n';
00164                 break;
00165             case 'r': next_char = '\r';
00166                 break;
00167             case 't': next_char = '\t';
00168                 break;
00169             case 'u': {
00170                 // We need 5 chars (4 hex + the 'u') or its not valid
00171                 if (!simplejson_wcsnlen(*data, 5))
00172                     return false;
00173 
00174                 // Deal with the chars
00175                 next_char = 0;
00176                 for (int i = 0; i < 4; i++) {
00177                     // Do it first to move off the 'u' and leave us on the
00178                     // final hex digit as we move on by one later on
00179                     (*data)++;
00180 
00181                     next_char <<= 4;
00182 
00183                     // Parse the hex digit
00184                     if (**data >= '0' && **data <= '9')
00185                         next_char |= (**data - '0');
00186                     else if (**data >= 'A' && **data <= 'F')
00187                         next_char |= (10 + (**data - 'A'));
00188                     else if (**data >= 'a' && **data <= 'f')
00189                         next_char |= (10 + (**data - 'a'));
00190                     else {
00191                         // Invalid hex digit = invalid JSON
00192                         return false;
00193                     }
00194                 }
00195                 break;
00196             }
00197 
00198                 // By the spec, only the above cases are allowed
00199             default:
00200                 return false;
00201             }
00202         }
00203 
00204         // End of the string?
00205         else if (next_char == '"') {
00206             (*data)++;
00207             //str.reserve(); // Remove unused capacity //TODO
00208             return true;
00209         }
00210 
00211         // Disallowed char?
00212         else if (next_char < ' ' && next_char != '\t') {
00213             // SPEC Violation: Allow tabs due to real world cases
00214             return false;
00215         }
00216 
00217         // Add the next char
00218         str += next_char;
00219 
00220         // Move on
00221         (*data)++;
00222     }
00223 
00224     // If we're here, the string ended incorrectly
00225     return false;
00226 }
00227 
00237 double JSON::parseInt(const char **data) {
00238     double integer = 0;
00239     while (**data != 0 && **data >= '0' && **data <= '9')
00240         integer = integer * 10 + (*(*data)++ - '0');
00241 
00242     return integer;
00243 }
00244 
00254 double JSON::parseDecimal(const char **data) {
00255     double decimal = 0.0;
00256     double factor = 0.1;
00257     while (**data != 0 && **data >= '0' && **data <= '9') {
00258         int digit = (*(*data)++ - '0');
00259         decimal = decimal + digit * factor;
00260         factor *= 0.1;
00261     }
00262     return decimal;
00263 }
00264 
00274 JSONValue *JSONValue::parse(const char **data) {
00275     // Is it a string?
00276     if (**data == '"') {
00277         String str;
00278         if (!JSON::extractString(&(++(*data)), str))
00279             return nullptr;
00280         else
00281             return new JSONValue(str);
00282     }
00283 
00284     // Is it a boolean?
00285     else if ((simplejson_wcsnlen(*data, 4) && scumm_strnicmp(*data, "true", 4) == 0) || (simplejson_wcsnlen(*data, 5) && scumm_strnicmp(*data, "false", 5) == 0)) {
00286         bool value = scumm_strnicmp(*data, "true", 4) == 0;
00287         (*data) += value ? 4 : 5;
00288         return new JSONValue(value);
00289     }
00290 
00291     // Is it a null?
00292     else if (simplejson_wcsnlen(*data, 4) && scumm_strnicmp(*data, "null", 4) == 0) {
00293         (*data) += 4;
00294         return new JSONValue();
00295     }
00296 
00297     // Is it a number?
00298     else if (**data == '-' || (**data >= '0' && **data <= '9')) {
00299         // Negative?
00300         bool neg = **data == '-';
00301         if (neg) (*data)++;
00302 
00303         long long int integer = 0;
00304         double number = 0.0;
00305         bool onlyInteger = true;
00306 
00307         // Parse the whole part of the number - only if it wasn't 0
00308         if (**data == '0')
00309             (*data)++;
00310         else if (**data >= '1' && **data <= '9')
00311             number = integer = JSON::parseInt(data);
00312         else
00313             return nullptr;
00314 
00315         // Could be a decimal now...
00316         if (**data == '.') {
00317             (*data)++;
00318 
00319             // Not get any digits?
00320             if (!(**data >= '0' && **data <= '9'))
00321                 return nullptr;
00322 
00323             // Find the decimal and sort the decimal place out
00324             // Use ParseDecimal as ParseInt won't work with decimals less than 0.1
00325             // thanks to Javier Abadia for the report & fix
00326             double decimal = JSON::parseDecimal(data);
00327 
00328             // Save the number
00329             number += decimal;
00330             onlyInteger = false;
00331         }
00332 
00333         // Could be an exponent now...
00334         if (**data == 'E' || **data == 'e') {
00335             (*data)++;
00336 
00337             // Check signage of expo
00338             bool neg_expo = false;
00339             if (**data == '-' || **data == '+') {
00340                 neg_expo = **data == '-';
00341                 (*data)++;
00342             }
00343 
00344             // Not get any digits?
00345             if (!(**data >= '0' && **data <= '9'))
00346                 return nullptr;
00347 
00348             // Sort the expo out
00349             double expo = JSON::parseInt(data);
00350             for (double i = 0.0; i < expo; i++)
00351                 number = neg_expo ? (number / 10.0) : (number * 10.0);
00352             onlyInteger = false;
00353         }
00354 
00355         // Was it neg?
00356         if (neg) number *= -1;
00357 
00358         if (onlyInteger)
00359             return new JSONValue(neg ? -integer : integer);
00360 
00361         return new JSONValue(number);
00362     }
00363 
00364     // An object?
00365     else if (**data == '{') {
00366         JSONObject object;
00367 
00368         (*data)++;
00369 
00370         while (**data != 0) {
00371             // Whitespace at the start?
00372             if (!JSON::skipWhitespace(data)) {
00373                 FREE_OBJECT(object);
00374                 return nullptr;
00375             }
00376 
00377             // Special case - empty object
00378             if (object.size() == 0 && **data == '}') {
00379                 (*data)++;
00380                 return new JSONValue(object);
00381             }
00382 
00383             // We want a string now...
00384             String name;
00385             if (!JSON::extractString(&(++(*data)), name)) {
00386                 FREE_OBJECT(object);
00387                 return nullptr;
00388             }
00389 
00390             // More whitespace?
00391             if (!JSON::skipWhitespace(data)) {
00392                 FREE_OBJECT(object);
00393                 return nullptr;
00394             }
00395 
00396             // Need a : now
00397             if (*((*data)++) != ':') {
00398                 FREE_OBJECT(object);
00399                 return nullptr;
00400             }
00401 
00402             // More whitespace?
00403             if (!JSON::skipWhitespace(data)) {
00404                 FREE_OBJECT(object);
00405                 return nullptr;
00406             }
00407 
00408             // The value is here
00409             JSONValue *value = parse(data);
00410             if (value == nullptr) {
00411                 FREE_OBJECT(object);
00412                 return nullptr;
00413             }
00414 
00415             // Add the name:value
00416             if (object.find(name) != object.end())
00417                 delete object[name];
00418             object[name] = value;
00419 
00420             // More whitespace?
00421             if (!JSON::skipWhitespace(data)) {
00422                 FREE_OBJECT(object);
00423                 return nullptr;
00424             }
00425 
00426             // End of object?
00427             if (**data == '}') {
00428                 (*data)++;
00429                 return new JSONValue(object);
00430             }
00431 
00432             // Want a , now
00433             if (**data != ',') {
00434                 FREE_OBJECT(object);
00435                 return nullptr;
00436             }
00437 
00438             (*data)++;
00439         }
00440 
00441         // Only here if we ran out of data
00442         FREE_OBJECT(object);
00443         return nullptr;
00444     }
00445 
00446     // An array?
00447     else if (**data == '[') {
00448         JSONArray array;
00449 
00450         (*data)++;
00451 
00452         while (**data != 0) {
00453             // Whitespace at the start?
00454             if (!JSON::skipWhitespace(data)) {
00455                 FREE_ARRAY(array);
00456                 return nullptr;
00457             }
00458 
00459             // Special case - empty array
00460             if (array.size() == 0 && **data == ']') {
00461                 (*data)++;
00462                 return new JSONValue(array);
00463             }
00464 
00465             // Get the value
00466             JSONValue *value = parse(data);
00467             if (value == nullptr) {
00468                 FREE_ARRAY(array);
00469                 return nullptr;
00470             }
00471 
00472             // Add the value
00473             array.push_back(value);
00474 
00475             // More whitespace?
00476             if (!JSON::skipWhitespace(data)) {
00477                 FREE_ARRAY(array);
00478                 return nullptr;
00479             }
00480 
00481             // End of array?
00482             if (**data == ']') {
00483                 (*data)++;
00484                 return new JSONValue(array);
00485             }
00486 
00487             // Want a , now
00488             if (**data != ',') {
00489                 FREE_ARRAY(array);
00490                 return nullptr;
00491             }
00492 
00493             (*data)++;
00494         }
00495 
00496         // Only here if we ran out of data
00497         FREE_ARRAY(array);
00498         return nullptr;
00499     }
00500 
00501     // Ran out of possibilites, it's bad!
00502     else {
00503         return nullptr;
00504     }
00505 }
00506 
00512 JSONValue::JSONValue(/*NULL*/) {
00513     _type = JSONType_Null;
00514 }
00515 
00523 JSONValue::JSONValue(const char *charValue) {
00524     _type = JSONType_String;
00525     _stringValue = new String(String(charValue));
00526 }
00527 
00535 JSONValue::JSONValue(const String &stringValue) {
00536     _type = JSONType_String;
00537     _stringValue = new String(stringValue);
00538 }
00539 
00547 JSONValue::JSONValue(bool boolValue) {
00548     _type = JSONType_Bool;
00549     _boolValue = boolValue;
00550 }
00551 
00559 JSONValue::JSONValue(double numberValue) {
00560     _type = JSONType_Number;
00561     _numberValue = numberValue;
00562 }
00563 
00571 JSONValue::JSONValue(long long int numberValue) {
00572     _type = JSONType_IntegerNumber;
00573     _integerValue = numberValue;
00574 }
00575 
00583 JSONValue::JSONValue(const JSONArray &arrayValue) {
00584     _type = JSONType_Array;
00585     _arrayValue = new JSONArray(arrayValue);
00586 }
00587 
00595 JSONValue::JSONValue(const JSONObject &objectValue) {
00596     _type = JSONType_Object;
00597     _objectValue = new JSONObject(objectValue);
00598 }
00599 
00607 JSONValue::JSONValue(const JSONValue &source) {
00608     _type = source._type;
00609 
00610     switch (_type) {
00611     case JSONType_String:
00612         _stringValue = new String(*source._stringValue);
00613         break;
00614 
00615     case JSONType_Bool:
00616         _boolValue = source._boolValue;
00617         break;
00618 
00619     case JSONType_Number:
00620         _numberValue = source._numberValue;
00621         break;
00622 
00623     case JSONType_IntegerNumber:
00624         _integerValue = source._integerValue;
00625         break;
00626 
00627     case JSONType_Array: {
00628         JSONArray source_array = *source._arrayValue;
00629         JSONArray::iterator iter;
00630         _arrayValue = new JSONArray();
00631         for (iter = source_array.begin(); iter != source_array.end(); iter++)
00632             _arrayValue->push_back(new JSONValue(**iter));
00633         break;
00634     }
00635 
00636     case JSONType_Object: {
00637         JSONObject source_object = *source._objectValue;
00638         _objectValue = new JSONObject();
00639         JSONObject::iterator iter;
00640         for (iter = source_object.begin(); iter != source_object.end(); iter++) {
00641             String name = (*iter)._key;
00642             (*_objectValue)[name] = new JSONValue(*((*iter)._value));
00643         }
00644         break;
00645     }
00646 
00647     case JSONType_Null:
00648         // Nothing to do.
00649         break;
00650     }
00651 }
00652 
00659 JSONValue::~JSONValue() {
00660     if (_type == JSONType_Array) {
00661         JSONArray::iterator iter;
00662         for (iter = _arrayValue->begin(); iter != _arrayValue->end(); iter++)
00663             delete *iter;
00664         delete _arrayValue;
00665     } else if (_type == JSONType_Object) {
00666         JSONObject::iterator iter;
00667         for (iter = _objectValue->begin(); iter != _objectValue->end(); iter++) {
00668             delete (*iter)._value;
00669         }
00670         delete _objectValue;
00671     } else if (_type == JSONType_String) {
00672         delete _stringValue;
00673     }
00674 }
00675 
00683 bool JSONValue::isNull() const {
00684     return _type == JSONType_Null;
00685 }
00686 
00694 bool JSONValue::isString() const {
00695     return _type == JSONType_String;
00696 }
00697 
00705 bool JSONValue::isBool() const {
00706     return _type == JSONType_Bool;
00707 }
00708 
00716 bool JSONValue::isNumber() const {
00717     return _type == JSONType_Number;
00718 }
00719 
00727 bool JSONValue::isIntegerNumber() const {
00728     return _type == JSONType_IntegerNumber;
00729 }
00730 
00738 bool JSONValue::isArray() const {
00739     return _type == JSONType_Array;
00740 }
00741 
00749 bool JSONValue::isObject() const {
00750     return _type == JSONType_Object;
00751 }
00752 
00761 const String &JSONValue::asString() const {
00762     return (*_stringValue);
00763 }
00764 
00773 bool JSONValue::asBool() const {
00774     return _boolValue;
00775 }
00776 
00785 double JSONValue::asNumber() const {
00786     return _numberValue;
00787 }
00788 
00797 long long int JSONValue::asIntegerNumber() const {
00798     return _integerValue;
00799 }
00800 
00809 const JSONArray &JSONValue::asArray() const {
00810     return (*_arrayValue);
00811 }
00812 
00821 const JSONObject &JSONValue::asObject() const {
00822     return (*_objectValue);
00823 }
00824 
00834 std::size_t JSONValue::countChildren() const {
00835     switch (_type) {
00836     case JSONType_Array:
00837         return _arrayValue->size();
00838     case JSONType_Object:
00839         return _objectValue->size();
00840     default:
00841         return 0;
00842     }
00843 }
00844 
00853 bool JSONValue::hasChild(std::size_t index) const {
00854     if (_type == JSONType_Array) {
00855         return index < _arrayValue->size();
00856     } else {
00857         return false;
00858     }
00859 }
00860 
00870 JSONValue *JSONValue::child(std::size_t index) {
00871     if (index < _arrayValue->size()) {
00872         return (*_arrayValue)[index];
00873     } else {
00874         return nullptr;
00875     }
00876 }
00877 
00886 bool JSONValue::hasChild(const char *name) const {
00887     if (_type == JSONType_Object) {
00888         return _objectValue->find(name) != _objectValue->end();
00889     } else {
00890         return false;
00891     }
00892 }
00893 
00903 JSONValue *JSONValue::child(const char *name) {
00904     JSONObject::const_iterator it = _objectValue->find(name);
00905     if (it != _objectValue->end()) {
00906         return it->_value;
00907     } else {
00908         return nullptr;
00909     }
00910 }
00911 
00920 Array<String> JSONValue::objectKeys() const {
00921     Array<String> keys;
00922 
00923     if (_type == JSONType_Object) {
00924         JSONObject::const_iterator iter = _objectValue->begin();
00925         while (iter != _objectValue->end()) {
00926             keys.push_back(iter->_key);
00927 
00928             iter++;
00929         }
00930     }
00931 
00932     return keys;
00933 }
00934 
00944 String JSONValue::stringify(bool const prettyprint) const {
00945     size_t const indentDepth = prettyprint ? 1 : 0;
00946     return stringifyImpl(indentDepth);
00947 }
00948 
00949 
00959 String JSONValue::stringifyImpl(size_t const indentDepth) const {
00960     String ret_string;
00961     size_t const indentDepth1 = indentDepth ? indentDepth + 1 : 0;
00962     String const indentStr = indent(indentDepth);
00963     String const indentStr1 = indent(indentDepth1);
00964 
00965     switch (_type) {
00966     case JSONType_Null:
00967         ret_string = "null";
00968         break;
00969 
00970     case JSONType_String:
00971         ret_string = stringifyString(*_stringValue);
00972         break;
00973 
00974     case JSONType_Bool:
00975         ret_string = _boolValue ? "true" : "false";
00976         break;
00977 
00978     case JSONType_Number: {
00979         if (isinf(_numberValue) || isnan(_numberValue))
00980             ret_string = "null";
00981         else {
00982             ret_string = String::format("%g", _numberValue);
00983         }
00984         break;
00985     }
00986 
00987     case JSONType_IntegerNumber: {
00988         ret_string = String::format("%lld", _integerValue);
00989         break;
00990     }
00991 
00992     case JSONType_Array: {
00993         ret_string = indentDepth ? "[\n" + indentStr1 : "[";
00994         JSONArray::const_iterator iter = _arrayValue->begin();
00995         while (iter != _arrayValue->end()) {
00996             ret_string += (*iter)->stringifyImpl(indentDepth1);
00997 
00998             // Not at the end - add a separator
00999             if (++iter != _arrayValue->end())
01000                 ret_string += ",";
01001         }
01002         ret_string += indentDepth ? "\n" + indentStr + "]" : "]";
01003         break;
01004     }
01005 
01006     case JSONType_Object: {
01007         ret_string = indentDepth ? "{\n" + indentStr1 : "{";
01008         JSONObject::const_iterator iter = _objectValue->begin();
01009         while (iter != _objectValue->end()) {
01010             ret_string += stringifyString((*iter)._key);
01011             ret_string += ":";
01012             ret_string += (*iter)._value->stringifyImpl(indentDepth1);
01013 
01014             // Not at the end - add a separator
01015             if (++iter != _objectValue->end())
01016                 ret_string += ",";
01017         }
01018         ret_string += indentDepth ? "\n" + indentStr + "}" : "}";
01019         break;
01020     }
01021     }
01022 
01023     return ret_string;
01024 }
01025 
01037 String JSONValue::stringifyString(const String &str) {
01038     String str_out = "\"";
01039 
01040     String::const_iterator iter = str.begin();
01041     while (iter != str.end()) {
01042         char chr = *iter;
01043 
01044         if (chr == '"' || chr == '\\' || chr == '/') {
01045             str_out += '\\';
01046             str_out += chr;
01047         } else if (chr == '\b') {
01048             str_out += "\\b";
01049         } else if (chr == '\f') {
01050             str_out += "\\f";
01051         } else if (chr == '\n') {
01052             str_out += "\\n";
01053         } else if (chr == '\r') {
01054             str_out += "\\r";
01055         } else if (chr == '\t') {
01056             str_out += "\\t";
01057         } else if (chr < ' ' || chr > 126) {
01058             str_out += "\\u";
01059             for (int i = 0; i < 4; i++) {
01060                 int value = (chr >> 12) & 0xf;
01061                 if (value >= 0 && value <= 9)
01062                     str_out += (char)('0' + value);
01063                 else if (value >= 10 && value <= 15)
01064                     str_out += (char)('A' + (value - 10));
01065                 chr <<= 4;
01066             }
01067         } else {
01068             str_out += chr;
01069         }
01070 
01071         iter++;
01072     }
01073 
01074     str_out += "\"";
01075     return str_out;
01076 }
01077 
01087 String JSONValue::indent(size_t depth) {
01088     const size_t indent_step = 2;
01089     depth ? --depth : 0;
01090     String indentStr;
01091     for (size_t i = 0; i < depth * indent_step; ++i) indentStr += ' ';
01092     return indentStr;
01093 }
01094 
01095 } // End of namespace Common


Generated on Sat May 18 2019 05:01:06 for ResidualVM by doxygen 1.7.1
curved edge   curved edge