diff options
Diffstat (limited to 'LibOVR/Src/OVR_JSON.cpp')
-rw-r--r-- | LibOVR/Src/OVR_JSON.cpp | 1287 |
1 files changed, 0 insertions, 1287 deletions
diff --git a/LibOVR/Src/OVR_JSON.cpp b/LibOVR/Src/OVR_JSON.cpp deleted file mode 100644 index 7b40fb1..0000000 --- a/LibOVR/Src/OVR_JSON.cpp +++ /dev/null @@ -1,1287 +0,0 @@ -/************************************************************************************ - -PublicHeader: None -Filename : OVR_JSON.h -Content : JSON format reader and writer -Created : April 9, 2013 -Author : Brant Lewis -Notes : - The code is a derivative of the cJSON library written by Dave Gamble and subject - to the following permissive copyright. - - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - - -Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. - -Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); -you may not use the Oculus VR Rift SDK except in compliance with the License, -which is provided at the time of installation or download, or which -otherwise accompanies this software in either electronic or hard copy form. - -You may obtain a copy of the License at - -http://www.oculusvr.com/licenses/LICENSE-3.2 - -Unless required by applicable law or agreed to in writing, the Oculus VR SDK -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -************************************************************************************/ - -#include <string.h> -#include <stdio.h> -#include <math.h> -#include <stdlib.h> -#include <float.h> -#include <limits.h> -#include <ctype.h> -#include "OVR_JSON.h" -#include "Kernel/OVR_SysFile.h" -#include "Kernel/OVR_Log.h" - -#ifdef OVR_OS_LINUX -#include <locale.h> -#endif - -namespace OVR { - - -//----------------------------------------------------------------------------- -// Create a new copy of a string -static char* JSON_strdup(const char* str) -{ - size_t len = OVR_strlen(str) + 1; - char* copy = (char*)OVR_ALLOC(len); - if (!copy) - return 0; - memcpy(copy, str, len); - return copy; -} - - -//----------------------------------------------------------------------------- -// Render the number from the given item into a string. -static char* PrintInt(int valueint) -{ - char *str; - str = (char*)OVR_ALLOC(21); // 2^64+1 can be represented in 21 chars. - if (str) - { - OVR_sprintf(str, 21, "%d", valueint); - } - return str; -} - - -//----------------------------------------------------------------------------- -// Render the number from the given item into a string. -static char* PrintNumber(double d) -{ - char *str; - int valueint = (int)d; - if (fabs(((double)valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) - { - return PrintInt(valueint); - } - else - { - str=(char*)OVR_ALLOC(64); // This is a nice tradeoff. - if (str) - { - if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60) - OVR_sprintf(str, 64, "%.0f", d); - else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) - OVR_sprintf(str, 64, "%e", d); - else - OVR_sprintf(str, 64, "%f", d); - } - } - return str; -} - - -// Parse the input text into an un-escaped cstring, and populate item. -static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - -// Helper to assign error sting and return 0. -const char* AssignError(const char** perror, const char *errorMessage) -{ - if (perror) - *perror = errorMessage; - return 0; -} - -//----------------------------------------------------------------------------- -// ***** JSON Node class - -JSON::JSON(JSONItemType itemType) : - Type(itemType), dValue(0.) -{ -} - -JSON::~JSON() -{ - JSON* child = Children.GetFirst(); - while (!Children.IsNull(child)) - { - child->RemoveNode(); - child->Release(); - child = Children.GetFirst(); - } -} - -//----------------------------------------------------------------------------- -// Parse the input text to generate a number, and populate the result into item -// Returns the text position after the parsed number -const char* JSON::parseNumber(const char *num) -{ - const char* num_start = num; - double n=0, scale=0; - int subscale = 0, - signsubscale = 1; - bool positiveSign = true; - char localeSeparator = '.'; - -#ifdef OVR_OS_LINUX - // We should switch to a locale aware parsing function, such as atof. We - // will probably want to go farther and enforce the 'C' locale on all JSON - // output/input. - struct lconv* localeConv = localeconv(); - localeSeparator = localeConv->decimal_point[0]; -#endif - - // Could use sscanf for this? - if (*num == '-') - { - positiveSign = false; - num++; // Has sign? - } - if (*num == '0') - { - num++; // is zero - } - - if (*num>='1' && *num<='9') - { - do - { - n = (n*10.0) + (*num++ - '0'); - } - while (*num>='0' && *num<='9'); // Number? - } - - if ((*num=='.' || *num==localeSeparator) && num[1]>='0' && num[1]<='9') - { - num++; - do - { - n=(n*10.0)+(*num++ -'0'); - scale--; - } - while (*num>='0' && *num<='9'); // Fractional part? - } - - if (*num=='e' || *num=='E') // Exponent? - { - num++; - if (*num == '+') - { - num++; - } - else if (*num=='-') - { - signsubscale=-1; - num++; // With sign? - } - - while (*num >= '0' && *num <= '9') - { - subscale = (subscale * 10) + (*num++ - '0'); // Number? - } - } - - // Number = +/- number.fraction * 10^+/- exponent - n *= pow(10.0, (scale + subscale*signsubscale)); - - if (!positiveSign) - { - n = -n; - } - - // Assign parsed value. - Type = JSON_Number; - dValue = n; - Value.AssignString(num_start, num - num_start); - - return num; -} - -// Parses a hex string up to the specified number of digits. -// Returns the first character after the string. -const char* ParseHex(unsigned* val, unsigned digits, const char* str) -{ - *val = 0; - - for(unsigned digitCount = 0; digitCount < digits; digitCount++, str++) - { - unsigned v = *str; - - if ((v >= '0') && (v <= '9')) - v -= '0'; - else if ((v >= 'a') && (v <= 'f')) - v = 10 + v - 'a'; - else if ((v >= 'A') && (v <= 'F')) - v = 10 + v - 'A'; - else - break; - - *val = *val * 16 + v; - } - - return str; -} - -//----------------------------------------------------------------------------- -// Parses the input text into a string item and returns the text position after -// the parsed string -const char* JSON::parseString(const char* str, const char** perror) -{ - const char* ptr = str+1; - const char* p; - char* ptr2; - char* out; - int len=0; - unsigned uc, uc2; - - if (*str!='\"') - { - return AssignError(perror, "Syntax Error: Missing quote"); - } - - while (*ptr!='\"' && *ptr && ++len) - { - if (*ptr++ == '\\') ptr++; // Skip escaped quotes. - } - - // This is how long we need for the string, roughly. - out=(char*)OVR_ALLOC(len+1); - if (!out) - return 0; - - ptr = str+1; - ptr2= out; - - while (*ptr!='\"' && *ptr) - { - if (*ptr!='\\') - { - *ptr2++ = *ptr++; - } - else - { - ptr++; - switch (*ptr) - { - case 'b': *ptr2++ = '\b'; break; - case 'f': *ptr2++ = '\f'; break; - case 'n': *ptr2++ = '\n'; break; - case 'r': *ptr2++ = '\r'; break; - case 't': *ptr2++ = '\t'; break; - - // Transcode utf16 to utf8. - case 'u': - - // Get the unicode char. - p = ParseHex(&uc, 4, ptr + 1); - if (ptr != p) - ptr = p - 1; - - if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) - break; // Check for invalid. - - // UTF16 surrogate pairs. - if (uc>=0xD800 && uc<=0xDBFF) - { - if (ptr[1]!='\\' || ptr[2]!='u') - break; // Missing second-half of surrogate. - - p= ParseHex(&uc2, 4, ptr + 3); - if (ptr != p) - ptr = p - 1; - - if (uc2<0xDC00 || uc2>0xDFFF) - break; // Invalid second-half of surrogate. - - uc = 0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); - } - - len=4; - - if (uc<0x80) - len=1; - else if (uc<0x800) - len=2; - else if (uc<0x10000) - len=3; - - ptr2+=len; - - switch (len) - { - case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; - //no break, fall through - case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; - //no break - case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; - //no break - case 1: *--ptr2 = (char)(uc | firstByteMark[len]); - //no break - } - ptr2+=len; - break; - - default: - *ptr2++ = *ptr; - break; - } - ptr++; - } - } - - *ptr2 = 0; - if (*ptr=='\"') - ptr++; - - // Make a copy of the string - Value=out; - OVR_FREE(out); - Type=JSON_String; - - return ptr; -} - -//----------------------------------------------------------------------------- -// Render the string provided to an escaped version that can be printed. -char* PrintString(const char* str) -{ - const char *ptr; - char *ptr2,*out; - int len=0; - unsigned char token; - - if (!str) - return JSON_strdup(""); - ptr=str; - - token=*ptr; - while (token && ++len)\ - { - if (strchr("\"\\\b\f\n\r\t",token)) - len++; - else if (token<32) - len+=5; - ptr++; - token=*ptr; - } - - int buff_size = len+3; - out=(char*)OVR_ALLOC(buff_size); - if (!out) - return 0; - - ptr2 = out; - ptr = str; - *ptr2++ = '\"'; - - while (*ptr) - { - if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') - *ptr2++=*ptr++; - else - { - *ptr2++='\\'; - switch (token=*ptr++) - { - case '\\': *ptr2++='\\'; break; - case '\"': *ptr2++='\"'; break; - case '\b': *ptr2++='b'; break; - case '\f': *ptr2++='f'; break; - case '\n': *ptr2++='n'; break; - case '\r': *ptr2++='r'; break; - case '\t': *ptr2++='t'; break; - default: - OVR_sprintf(ptr2, buff_size - (ptr2-out), "u%04x",token); - ptr2+=5; - break; // Escape and print. - } - } - } - *ptr2++='\"'; - *ptr2++=0; - return out; -} - -//----------------------------------------------------------------------------- -// Utility to jump whitespace and cr/lf -static const char* skip(const char* in) -{ - while (in && *in && (unsigned char)*in<=' ') - in++; - return in; -} - -//----------------------------------------------------------------------------- -// Parses the supplied buffer of JSON text and returns a JSON object tree -// The returned object must be Released after use -JSON* JSON::Parse(const char* buff, const char** perror) -{ - const char* end = 0; - JSON* json = new JSON(); - - if (!json) - { - AssignError(perror, "Error: Failed to allocate memory"); - return 0; - } - - end = json->parseValue(skip(buff), perror); - if (!end) - { - json->Release(); - return NULL; - } // parse failure. ep is set. - - return json; -} - -//----------------------------------------------------------------------------- -// This version works for buffers that are not null terminated strings. -JSON* JSON::ParseBuffer(const char *buff, int len, const char** perror) -{ - // Our JSON parser does not support length-based parsing, - // so ensure it is null-terminated. - char *termStr = new char[len + 1]; - memcpy(termStr, buff, len); - termStr[len] = '\0'; - - JSON *objJson = Parse(termStr, perror); - - delete[]termStr; - - return objJson; -} - -//----------------------------------------------------------------------------- -// Parser core - when encountering text, process appropriately. -const char* JSON::parseValue(const char* buff, const char** perror) -{ - if (perror) - *perror = 0; - - if (!buff) - return NULL; // Fail on null. - - if (!strncmp(buff,"null",4)) - { - Type = JSON_Null; - return buff+4; - } - if (!strncmp(buff,"false",5)) - { - Type = JSON_Bool; - Value = "false"; - dValue = 0.; - return buff+5; - } - if (!strncmp(buff,"true",4)) - { - Type = JSON_Bool; - Value = "true"; - dValue = 1.; - return buff + 4; - } - if (*buff=='\"') - { - return parseString(buff, perror); - } - if (*buff=='-' || (*buff>='0' && *buff<='9')) - { - return parseNumber(buff); - } - if (*buff=='[') - { - return parseArray(buff, perror); - } - if (*buff=='{') - { - return parseObject(buff, perror); - } - - return AssignError(perror, "Syntax Error: Invalid syntax"); -} - - -//----------------------------------------------------------------------------- -// Render a value to text. -char* JSON::PrintValue(int depth, bool fmt) -{ - char *out=0; - - switch (Type) - { - case JSON_Null: out = JSON_strdup("null"); break; - case JSON_Bool: - if ((int)dValue == 0) - out = JSON_strdup("false"); - else - out = JSON_strdup("true"); - break; - case JSON_Number: out = PrintNumber(dValue); break; - case JSON_String: out = PrintString(Value); break; - case JSON_Array: out = PrintArray(depth, fmt); break; - case JSON_Object: out = PrintObject(depth, fmt); break; - case JSON_None: OVR_ASSERT_LOG(false, ("Bad JSON type.")); break; - } - return out; -} - -//----------------------------------------------------------------------------- -// Build an array object from input text and returns the text position after -// the parsed array -const char* JSON::parseArray(const char* buff, const char** perror) -{ - JSON *child; - if (*buff!='[') - { - return AssignError(perror, "Syntax Error: Missing opening bracket"); - } - - Type=JSON_Array; - buff=skip(buff+1); - - if (*buff==']') - return buff+1; // empty array. - - child = new JSON(); - if (!child) - return 0; // memory fail - Children.PushBack(child); - - buff=skip(child->parseValue(skip(buff), perror)); // skip any spacing, get the buff. - if (!buff) - return 0; - - while (*buff==',') - { - JSON *new_item = new JSON(); - if (!new_item) - return AssignError(perror, "Error: Failed to allocate memory"); - - Children.PushBack(new_item); - - buff=skip(new_item->parseValue(skip(buff+1), perror)); - if (!buff) - return AssignError(perror, "Error: Failed to allocate memory"); - } - - if (*buff==']') - return buff+1; // end of array - - return AssignError(perror, "Syntax Error: Missing ending bracket"); -} - -//----------------------------------------------------------------------------- -// Render an array to text. The returned text must be freed -char* JSON::PrintArray(int depth, bool fmt) -{ - char ** entries; - char * out = 0, *ptr,*ret; - intptr_t len = 5; - - bool fail = false; - - // How many entries in the array? - int numentries = GetItemCount(); - if (!numentries) - { - out=(char*)OVR_ALLOC(3); - if (out) - OVR_strcpy(out, 3, "[]"); - return out; - } - // Allocate an array to hold the values for each - entries=(char**)OVR_ALLOC(numentries*sizeof(char*)); - if (!entries) - return 0; - memset(entries,0,numentries*sizeof(char*)); - - //// Retrieve all the results: - JSON* child = Children.GetFirst(); - for (int i=0; i<numentries; i++) - { - //JSON* child = Children[i]; - ret=child->PrintValue(depth+1, fmt); - entries[i]=ret; - if (ret) - len+=OVR_strlen(ret)+2+(fmt?1:0); - else - { - fail = true; - break; - } - child = Children.GetNext(child); - } - - // If we didn't fail, try to malloc the output string - if (!fail) - out=(char*)OVR_ALLOC(len); - // If that fails, we fail. - if (!out) - fail = true; - - // Handle failure. - if (fail) - { - for (int i=0; i<numentries; i++) - { - if (entries[i]) - OVR_FREE(entries[i]); - } - OVR_FREE(entries); - return 0; - } - - // Compose the output array. - *out='['; - ptr=out+1; - *ptr=0; - for (int i=0; i<numentries; i++) - { - OVR_strcpy(ptr, len - (ptr-out), entries[i]); - ptr+=OVR_strlen(entries[i]); - if (i!=numentries-1) - { - *ptr++=','; - if (fmt) - *ptr++=' '; - *ptr=0; - } - OVR_FREE(entries[i]); - } - OVR_FREE(entries); - *ptr++=']'; - *ptr++=0; - return out; -} - -//----------------------------------------------------------------------------- -// Build an object from the supplied text and returns the text position after -// the parsed object -const char* JSON::parseObject(const char* buff, const char** perror) -{ - if (*buff!='{') - { - return AssignError(perror, "Syntax Error: Missing opening brace"); - } - - Type=JSON_Object; - buff=skip(buff+1); - if (*buff=='}') - return buff+1; // empty array. - - JSON* child = new JSON(); - Children.PushBack(child); - - buff=skip(child->parseString(skip(buff), perror)); - if (!buff) - return 0; - child->Name = child->Value; - child->Value.Clear(); - - if (*buff!=':') - { - return AssignError(perror, "Syntax Error: Missing colon"); - } - - buff=skip(child->parseValue(skip(buff+1), perror)); // skip any spacing, get the value. - if (!buff) - return 0; - - while (*buff==',') - { - child = new JSON(); - if (!child) - return 0; // memory fail - - Children.PushBack(child); - - buff=skip(child->parseString(skip(buff+1), perror)); - if (!buff) - return 0; - - child->Name=child->Value; - child->Value.Clear(); - - if (*buff!=':') - { - return AssignError(perror, "Syntax Error: Missing colon"); - } // fail! - - // Skip any spacing, get the value. - buff=skip(child->parseValue(skip(buff+1), perror)); - if (!buff) - return 0; - } - - if (*buff=='}') - return buff+1; // end of array - - return AssignError(perror, "Syntax Error: Missing closing brace"); -} - -//----------------------------------------------------------------------------- -// Render an object to text. The returned string must be freed -char* JSON::PrintObject(int depth, bool fmt) -{ - char** entries = 0, **names = 0; - char* out = 0; - char* ptr, *ret, *str; - intptr_t len = 7, i = 0, j; - bool fail = false; - - // Count the number of entries. - int numentries = GetItemCount(); - - // Explicitly handle empty object case - if (numentries == 0) - { - out=(char*)OVR_ALLOC(fmt?depth+4:4); - if (!out) - return 0; - ptr=out; - *ptr++='{'; - - if (fmt) - { - *ptr++='\n'; - for (i=0;i<depth-1;i++) - *ptr++='\t'; - } - *ptr++='}'; - *ptr++=0; - return out; - } - // Allocate space for the names and the objects - entries=(char**)OVR_ALLOC(numentries*sizeof(char*)); - if (!entries) - return 0; - names=(char**)OVR_ALLOC(numentries*sizeof(char*)); - - if (!names) - { - OVR_FREE(entries); - return 0; - } - memset(entries,0,sizeof(char*)*numentries); - memset(names,0,sizeof(char*)*numentries); - - // Collect all the results into our arrays: - depth++; - if (fmt) - len+=depth; - - JSON* child = Children.GetFirst(); - while (!Children.IsNull(child)) - { - names[i] = str = PrintString(child->Name); - entries[i++] = ret = child->PrintValue(depth, fmt); - - if (str && ret) - { - len += OVR_strlen(ret)+OVR_strlen(str)+2+(fmt?3+depth:0); - } - else - { - fail = true; - break; - } - - child = Children.GetNext(child); - } - - // Try to allocate the output string - if (!fail) - out=(char*)OVR_ALLOC(len); - if (!out) - fail=true; - - // Handle failure - if (fail) - { - for (i=0;i<numentries;i++) - { - if (names[i]) - OVR_FREE(names[i]); - - if (entries[i]) - OVR_FREE(entries[i]);} - - OVR_FREE(names); - OVR_FREE(entries); - return 0; - } - - // Compose the output: - *out = '{'; - ptr = out+1; - if (fmt) - { -#ifdef OVR_OS_WIN32 - *ptr++ = '\r'; -#endif - *ptr++ = '\n'; - } - *ptr = 0; - - for (i=0; i<numentries; i++) - { - if (fmt) - { - for (j = 0; j < depth; j++) - { - *ptr++ = '\t'; - } - } - OVR_strcpy(ptr, len - (ptr-out), names[i]); - ptr += OVR_strlen(names[i]); - *ptr++ =':'; - - if (fmt) - { - *ptr++ = '\t'; - } - - OVR_strcpy(ptr, len - (ptr-out), entries[i]); - ptr+=OVR_strlen(entries[i]); - - if (i != numentries - 1) - { - *ptr++ = ','; - } - - if (fmt) - { -#ifdef OVR_OS_WIN32 - *ptr++ = '\r'; -#endif - *ptr++ = '\n'; - } - *ptr = 0; - - OVR_FREE(names[i]); - OVR_FREE(entries[i]); - } - - OVR_FREE(names); - OVR_FREE(entries); - - if (fmt) - { - for (i = 0; i < depth - 1; i++) - { - *ptr++ = '\t'; - } - } - *ptr++='}'; - *ptr++=0; - - return out; -} - - - -// Returns the number of child items in the object -// Counts the number of items in the object. -unsigned JSON::GetItemCount() const -{ - unsigned count = 0; - for (const JSON* p = Children.GetFirst(); !Children.IsNull(p); p = p->pNext) - { - count++; - } - return count; -} - -JSON* JSON::GetItemByIndex(unsigned index) -{ - unsigned i = 0; - JSON* child = 0; - - if (!Children.IsEmpty()) - { - child = Children.GetFirst(); - - while (i < index) - { - if (Children.IsNull(child->pNext)) - { - child = 0; - break; - } - child = child->pNext; - i++; - } - } - - return child; -} - -// Returns the child item with the given name or NULL if not found -JSON* JSON::GetItemByName(const char* name) -{ - JSON* child = 0; - - if (!Children.IsEmpty()) - { - child = Children.GetFirst(); - - while (OVR_strcmp(child->Name, name) != 0) - { - if (Children.IsNull(child->pNext)) - { - child = 0; - break; - } - child = child->pNext; - } - } - - return child; -} - -//----------------------------------------------------------------------------- -// Adds a new item to the end of the child list -void JSON::AddItem(const char *string, JSON *item) -{ - if (item) - { - item->Name = string; - Children.PushBack(item); - } -} - -/* - -// Removes and frees the items at the given index -void JSON::DeleteItem(unsigned int index) -{ - unsigned int num_items = 0; - JSON* child = Children.GetFirst(); - while (!Children.IsNull(child) && num_items < index) - { - num_items++; - child = Children.GetNext(child); - } - - if (!Children.IsNull(child)) - - child->RemoveNode(); - child->Release(); - } -} - -// Replaces and frees the item at the give index with the new item -void JSON::ReplaceItem(unsigned int index, JSON* new_item) -{ - unsigned int num_items = 0; - JSON* child = Children.GetFirst(); - while (!Children.IsNull(child) && num_items < index) - { - num_items++; - child = Children.GetNext(child); - } - - if (!Children.IsNull(child)) - { - child->ReplaceNodeWith(new_item); - child->Release(); - } -} -*/ - -// Removes and frees the last child item -void JSON::RemoveLast() -{ - JSON* child = Children.GetLast(); - if (!Children.IsNull(child)) - { - child->RemoveNode(); - child->Release(); - } -} - -JSON* JSON::CreateBool(bool b) -{ - JSON *item = new JSON(JSON_Bool); - if (item) - { - item->dValue = b ? 1. : 0.; - item->Value = b ? "true" : "false"; - } - return item; -} - -JSON* JSON::CreateNumber(double num) -{ - JSON *item = new JSON(JSON_Number); - if (item) - { - item->dValue = num; - } - return item; -} - -JSON* JSON::CreateInt(int num) -{ - JSON *item = new JSON(JSON_Number); - if (item) - { - item->dValue = num; - } - return item; -} - -JSON* JSON::CreateString(const char *s) -{ - JSON *item = new JSON(JSON_String); - if (item && s) - { - item->Value = s; - } - return item; -} - - -//----------------------------------------------------------------------------- -// Get elements by name -double JSON::GetNumberByName(const char *name, double defValue) -{ - JSON* item = GetItemByName(name); - if (!item || item->Type != JSON_Number) - { - return defValue; - } - else - { - return item->dValue; - } -} - -int JSON::GetIntByName(const char *name, int defValue) -{ - JSON* item = GetItemByName(name); - if (!item || item->Type != JSON_Number) - { - return defValue; - } - else - { - return (int)item->dValue; - } -} - -bool JSON::GetBoolByName(const char *name, bool defValue) -{ - JSON* item = GetItemByName(name); - if (!item || item->Type != JSON_Bool) - { - return defValue; - } - else - { - return (int)item->dValue != 0; - } -} - -String JSON::GetStringByName(const char *name, const String &defValue) -{ - JSON* item = GetItemByName(name); - if (!item || item->Type != JSON_String) - { - return defValue; - } - else - { - return item->Value; - } -} - -//----------------------------------------------------------------------------- -// Adds an element to an array object type -void JSON::AddArrayElement(JSON *item) -{ - if (item) - { - Children.PushBack(item); - } -} - -// Inserts an element into a valid array position -void JSON::InsertArrayElement(int index, JSON *item) -{ - if (!item) - { - return; - } - - if (index == 0) - { - Children.PushFront(item); - return; - } - - JSON* iter = Children.GetFirst(); - int i=0; - while (iter && i<index) - { - iter = Children.GetNext(iter); - i++; - } - - if (iter) - iter->InsertNodeBefore(item); - else - Children.PushBack(item); -} - -// Returns the size of an array -int JSON::GetArraySize() -{ - if (Type == JSON_Array) - { - return GetItemCount(); - } - - return 0; -} - -// Returns the number value an the give array index -double JSON::GetArrayNumber(int index) -{ - if (Type == JSON_Array) - { - JSON* number = GetItemByIndex(index); - return number ? number->dValue : 0.0; - } - - return 0; -} - -// Returns the string value at the given array index -const char* JSON::GetArrayString(int index) -{ - if (Type == JSON_Array) - { - JSON* number = GetItemByIndex(index); - return number ? number->Value : 0; - } - - return 0; -} - -JSON* JSON::Copy() -{ - JSON* copy = new JSON(Type); - copy->Name = Name; - copy->Value = Value; - copy->dValue = dValue; - - JSON* child = Children.GetFirst(); - while (!Children.IsNull(child)) - { - copy->Children.PushBack(child->Copy()); - child = Children.GetNext(child); - } - - return copy; -} - -//----------------------------------------------------------------------------- -// Loads and parses the given JSON file pathname and returns a JSON object tree. -// The returned object must be Released after use. -JSON* JSON::Load(const char* path, const char** perror) -{ - SysFile f; - if (!f.Open(path, File::Open_Read, File::Mode_Read)) - { - AssignError(perror, "Failed to open file"); - return NULL; - } - - int len = f.GetLength(); - uint8_t* buff = (uint8_t*)OVR_ALLOC(len + 1); - int bytes = f.Read(buff, len); - f.Close(); - - if (bytes == 0 || bytes != len) - { - OVR_FREE(buff); - return NULL; - } - - // Ensure the result is null-terminated since Parse() expects null-terminated input. - buff[len] = '\0'; - - JSON* json = JSON::Parse((char*)buff, perror); - OVR_FREE(buff); - return json; -} - -//----------------------------------------------------------------------------- -// Serializes the JSON object and writes to the give file path -bool JSON::Save(const char* path) -{ - SysFile f; - if (!f.Open(path, File::Open_Write | File::Open_Create | File::Open_Truncate, File::Mode_Write)) - return false; - - char* text = PrintValue(0, true); - if (text) - { - intptr_t len = OVR_strlen(text); - OVR_ASSERT(len <= (intptr_t)(int)len); - - int bytes = f.Write((uint8_t*)text, (int)len); - f.Close(); - OVR_FREE(text); - return (bytes == len); - } - else - { - return false; - } -} - - -} // namespace OVR |