ovr_sdk
diff LibOVR/Src/OVR_JSON.cpp @ 0:1b39a1b46319
initial 0.4.4
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 14 Jan 2015 06:51:16 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/LibOVR/Src/OVR_JSON.cpp Wed Jan 14 06:51:16 2015 +0200 1.3 @@ -0,0 +1,1287 @@ 1.4 +/************************************************************************************ 1.5 + 1.6 +PublicHeader: None 1.7 +Filename : OVR_JSON.h 1.8 +Content : JSON format reader and writer 1.9 +Created : April 9, 2013 1.10 +Author : Brant Lewis 1.11 +Notes : 1.12 + The code is a derivative of the cJSON library written by Dave Gamble and subject 1.13 + to the following permissive copyright. 1.14 + 1.15 + Copyright (c) 2009 Dave Gamble 1.16 + 1.17 + Permission is hereby granted, free of charge, to any person obtaining a copy 1.18 + of this software and associated documentation files (the "Software"), to deal 1.19 + in the Software without restriction, including without limitation the rights 1.20 + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1.21 + copies of the Software, and to permit persons to whom the Software is 1.22 + furnished to do so, subject to the following conditions: 1.23 + 1.24 + The above copyright notice and this permission notice shall be included in 1.25 + all copies or substantial portions of the Software. 1.26 + 1.27 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1.28 + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1.29 + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1.30 + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1.31 + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1.32 + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 1.33 + THE SOFTWARE. 1.34 + 1.35 + 1.36 +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. 1.37 + 1.38 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 1.39 +you may not use the Oculus VR Rift SDK except in compliance with the License, 1.40 +which is provided at the time of installation or download, or which 1.41 +otherwise accompanies this software in either electronic or hard copy form. 1.42 + 1.43 +You may obtain a copy of the License at 1.44 + 1.45 +http://www.oculusvr.com/licenses/LICENSE-3.2 1.46 + 1.47 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 1.48 +distributed under the License is distributed on an "AS IS" BASIS, 1.49 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.50 +See the License for the specific language governing permissions and 1.51 +limitations under the License. 1.52 + 1.53 +************************************************************************************/ 1.54 + 1.55 +#include <string.h> 1.56 +#include <stdio.h> 1.57 +#include <math.h> 1.58 +#include <stdlib.h> 1.59 +#include <float.h> 1.60 +#include <limits.h> 1.61 +#include <ctype.h> 1.62 +#include "OVR_JSON.h" 1.63 +#include "Kernel/OVR_SysFile.h" 1.64 +#include "Kernel/OVR_Log.h" 1.65 + 1.66 +#ifdef OVR_OS_LINUX 1.67 +#include <locale.h> 1.68 +#endif 1.69 + 1.70 +namespace OVR { 1.71 + 1.72 + 1.73 +//----------------------------------------------------------------------------- 1.74 +// Create a new copy of a string 1.75 +static char* JSON_strdup(const char* str) 1.76 +{ 1.77 + size_t len = OVR_strlen(str) + 1; 1.78 + char* copy = (char*)OVR_ALLOC(len); 1.79 + if (!copy) 1.80 + return 0; 1.81 + memcpy(copy, str, len); 1.82 + return copy; 1.83 +} 1.84 + 1.85 + 1.86 +//----------------------------------------------------------------------------- 1.87 +// Render the number from the given item into a string. 1.88 +static char* PrintInt(int valueint) 1.89 +{ 1.90 + char *str; 1.91 + str = (char*)OVR_ALLOC(21); // 2^64+1 can be represented in 21 chars. 1.92 + if (str) 1.93 + { 1.94 + OVR_sprintf(str, 21, "%d", valueint); 1.95 + } 1.96 + return str; 1.97 +} 1.98 + 1.99 + 1.100 +//----------------------------------------------------------------------------- 1.101 +// Render the number from the given item into a string. 1.102 +static char* PrintNumber(double d) 1.103 +{ 1.104 + char *str; 1.105 + int valueint = (int)d; 1.106 + if (fabs(((double)valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) 1.107 + { 1.108 + return PrintInt(valueint); 1.109 + } 1.110 + else 1.111 + { 1.112 + str=(char*)OVR_ALLOC(64); // This is a nice tradeoff. 1.113 + if (str) 1.114 + { 1.115 + if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60) 1.116 + OVR_sprintf(str, 64, "%.0f", d); 1.117 + else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) 1.118 + OVR_sprintf(str, 64, "%e", d); 1.119 + else 1.120 + OVR_sprintf(str, 64, "%f", d); 1.121 + } 1.122 + } 1.123 + return str; 1.124 +} 1.125 + 1.126 + 1.127 +// Parse the input text into an un-escaped cstring, and populate item. 1.128 +static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; 1.129 + 1.130 +// Helper to assign error sting and return 0. 1.131 +const char* AssignError(const char** perror, const char *errorMessage) 1.132 +{ 1.133 + if (perror) 1.134 + *perror = errorMessage; 1.135 + return 0; 1.136 +} 1.137 + 1.138 +//----------------------------------------------------------------------------- 1.139 +// ***** JSON Node class 1.140 + 1.141 +JSON::JSON(JSONItemType itemType) : 1.142 + Type(itemType), dValue(0.) 1.143 +{ 1.144 +} 1.145 + 1.146 +JSON::~JSON() 1.147 +{ 1.148 + JSON* child = Children.GetFirst(); 1.149 + while (!Children.IsNull(child)) 1.150 + { 1.151 + child->RemoveNode(); 1.152 + child->Release(); 1.153 + child = Children.GetFirst(); 1.154 + } 1.155 +} 1.156 + 1.157 +//----------------------------------------------------------------------------- 1.158 +// Parse the input text to generate a number, and populate the result into item 1.159 +// Returns the text position after the parsed number 1.160 +const char* JSON::parseNumber(const char *num) 1.161 +{ 1.162 + const char* num_start = num; 1.163 + double n=0, scale=0; 1.164 + int subscale = 0, 1.165 + signsubscale = 1; 1.166 + bool positiveSign = true; 1.167 + char localeSeparator = '.'; 1.168 + 1.169 +#ifdef OVR_OS_LINUX 1.170 + // We should switch to a locale aware parsing function, such as atof. We 1.171 + // will probably want to go farther and enforce the 'C' locale on all JSON 1.172 + // output/input. 1.173 + struct lconv* localeConv = localeconv(); 1.174 + localeSeparator = localeConv->decimal_point[0]; 1.175 +#endif 1.176 + 1.177 + // Could use sscanf for this? 1.178 + if (*num == '-') 1.179 + { 1.180 + positiveSign = false; 1.181 + num++; // Has sign? 1.182 + } 1.183 + if (*num == '0') 1.184 + { 1.185 + num++; // is zero 1.186 + } 1.187 + 1.188 + if (*num>='1' && *num<='9') 1.189 + { 1.190 + do 1.191 + { 1.192 + n = (n*10.0) + (*num++ - '0'); 1.193 + } 1.194 + while (*num>='0' && *num<='9'); // Number? 1.195 + } 1.196 + 1.197 + if ((*num=='.' || *num==localeSeparator) && num[1]>='0' && num[1]<='9') 1.198 + { 1.199 + num++; 1.200 + do 1.201 + { 1.202 + n=(n*10.0)+(*num++ -'0'); 1.203 + scale--; 1.204 + } 1.205 + while (*num>='0' && *num<='9'); // Fractional part? 1.206 + } 1.207 + 1.208 + if (*num=='e' || *num=='E') // Exponent? 1.209 + { 1.210 + num++; 1.211 + if (*num == '+') 1.212 + { 1.213 + num++; 1.214 + } 1.215 + else if (*num=='-') 1.216 + { 1.217 + signsubscale=-1; 1.218 + num++; // With sign? 1.219 + } 1.220 + 1.221 + while (*num >= '0' && *num <= '9') 1.222 + { 1.223 + subscale = (subscale * 10) + (*num++ - '0'); // Number? 1.224 + } 1.225 + } 1.226 + 1.227 + // Number = +/- number.fraction * 10^+/- exponent 1.228 + n *= pow(10.0, (scale + subscale*signsubscale)); 1.229 + 1.230 + if (!positiveSign) 1.231 + { 1.232 + n = -n; 1.233 + } 1.234 + 1.235 + // Assign parsed value. 1.236 + Type = JSON_Number; 1.237 + dValue = n; 1.238 + Value.AssignString(num_start, num - num_start); 1.239 + 1.240 + return num; 1.241 +} 1.242 + 1.243 +// Parses a hex string up to the specified number of digits. 1.244 +// Returns the first character after the string. 1.245 +const char* ParseHex(unsigned* val, unsigned digits, const char* str) 1.246 +{ 1.247 + *val = 0; 1.248 + 1.249 + for(unsigned digitCount = 0; digitCount < digits; digitCount++, str++) 1.250 + { 1.251 + unsigned v = *str; 1.252 + 1.253 + if ((v >= '0') && (v <= '9')) 1.254 + v -= '0'; 1.255 + else if ((v >= 'a') && (v <= 'f')) 1.256 + v = 10 + v - 'a'; 1.257 + else if ((v >= 'A') && (v <= 'F')) 1.258 + v = 10 + v - 'A'; 1.259 + else 1.260 + break; 1.261 + 1.262 + *val = *val * 16 + v; 1.263 + } 1.264 + 1.265 + return str; 1.266 +} 1.267 + 1.268 +//----------------------------------------------------------------------------- 1.269 +// Parses the input text into a string item and returns the text position after 1.270 +// the parsed string 1.271 +const char* JSON::parseString(const char* str, const char** perror) 1.272 +{ 1.273 + const char* ptr = str+1; 1.274 + const char* p; 1.275 + char* ptr2; 1.276 + char* out; 1.277 + int len=0; 1.278 + unsigned uc, uc2; 1.279 + 1.280 + if (*str!='\"') 1.281 + { 1.282 + return AssignError(perror, "Syntax Error: Missing quote"); 1.283 + } 1.284 + 1.285 + while (*ptr!='\"' && *ptr && ++len) 1.286 + { 1.287 + if (*ptr++ == '\\') ptr++; // Skip escaped quotes. 1.288 + } 1.289 + 1.290 + // This is how long we need for the string, roughly. 1.291 + out=(char*)OVR_ALLOC(len+1); 1.292 + if (!out) 1.293 + return 0; 1.294 + 1.295 + ptr = str+1; 1.296 + ptr2= out; 1.297 + 1.298 + while (*ptr!='\"' && *ptr) 1.299 + { 1.300 + if (*ptr!='\\') 1.301 + { 1.302 + *ptr2++ = *ptr++; 1.303 + } 1.304 + else 1.305 + { 1.306 + ptr++; 1.307 + switch (*ptr) 1.308 + { 1.309 + case 'b': *ptr2++ = '\b'; break; 1.310 + case 'f': *ptr2++ = '\f'; break; 1.311 + case 'n': *ptr2++ = '\n'; break; 1.312 + case 'r': *ptr2++ = '\r'; break; 1.313 + case 't': *ptr2++ = '\t'; break; 1.314 + 1.315 + // Transcode utf16 to utf8. 1.316 + case 'u': 1.317 + 1.318 + // Get the unicode char. 1.319 + p = ParseHex(&uc, 4, ptr + 1); 1.320 + if (ptr != p) 1.321 + ptr = p - 1; 1.322 + 1.323 + if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) 1.324 + break; // Check for invalid. 1.325 + 1.326 + // UTF16 surrogate pairs. 1.327 + if (uc>=0xD800 && uc<=0xDBFF) 1.328 + { 1.329 + if (ptr[1]!='\\' || ptr[2]!='u') 1.330 + break; // Missing second-half of surrogate. 1.331 + 1.332 + p= ParseHex(&uc2, 4, ptr + 3); 1.333 + if (ptr != p) 1.334 + ptr = p - 1; 1.335 + 1.336 + if (uc2<0xDC00 || uc2>0xDFFF) 1.337 + break; // Invalid second-half of surrogate. 1.338 + 1.339 + uc = 0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); 1.340 + } 1.341 + 1.342 + len=4; 1.343 + 1.344 + if (uc<0x80) 1.345 + len=1; 1.346 + else if (uc<0x800) 1.347 + len=2; 1.348 + else if (uc<0x10000) 1.349 + len=3; 1.350 + 1.351 + ptr2+=len; 1.352 + 1.353 + switch (len) 1.354 + { 1.355 + case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 1.356 + //no break, fall through 1.357 + case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 1.358 + //no break 1.359 + case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 1.360 + //no break 1.361 + case 1: *--ptr2 = (char)(uc | firstByteMark[len]); 1.362 + //no break 1.363 + } 1.364 + ptr2+=len; 1.365 + break; 1.366 + 1.367 + default: 1.368 + *ptr2++ = *ptr; 1.369 + break; 1.370 + } 1.371 + ptr++; 1.372 + } 1.373 + } 1.374 + 1.375 + *ptr2 = 0; 1.376 + if (*ptr=='\"') 1.377 + ptr++; 1.378 + 1.379 + // Make a copy of the string 1.380 + Value=out; 1.381 + OVR_FREE(out); 1.382 + Type=JSON_String; 1.383 + 1.384 + return ptr; 1.385 +} 1.386 + 1.387 +//----------------------------------------------------------------------------- 1.388 +// Render the string provided to an escaped version that can be printed. 1.389 +char* PrintString(const char* str) 1.390 +{ 1.391 + const char *ptr; 1.392 + char *ptr2,*out; 1.393 + int len=0; 1.394 + unsigned char token; 1.395 + 1.396 + if (!str) 1.397 + return JSON_strdup(""); 1.398 + ptr=str; 1.399 + 1.400 + token=*ptr; 1.401 + while (token && ++len)\ 1.402 + { 1.403 + if (strchr("\"\\\b\f\n\r\t",token)) 1.404 + len++; 1.405 + else if (token<32) 1.406 + len+=5; 1.407 + ptr++; 1.408 + token=*ptr; 1.409 + } 1.410 + 1.411 + int buff_size = len+3; 1.412 + out=(char*)OVR_ALLOC(buff_size); 1.413 + if (!out) 1.414 + return 0; 1.415 + 1.416 + ptr2 = out; 1.417 + ptr = str; 1.418 + *ptr2++ = '\"'; 1.419 + 1.420 + while (*ptr) 1.421 + { 1.422 + if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') 1.423 + *ptr2++=*ptr++; 1.424 + else 1.425 + { 1.426 + *ptr2++='\\'; 1.427 + switch (token=*ptr++) 1.428 + { 1.429 + case '\\': *ptr2++='\\'; break; 1.430 + case '\"': *ptr2++='\"'; break; 1.431 + case '\b': *ptr2++='b'; break; 1.432 + case '\f': *ptr2++='f'; break; 1.433 + case '\n': *ptr2++='n'; break; 1.434 + case '\r': *ptr2++='r'; break; 1.435 + case '\t': *ptr2++='t'; break; 1.436 + default: 1.437 + OVR_sprintf(ptr2, buff_size - (ptr2-out), "u%04x",token); 1.438 + ptr2+=5; 1.439 + break; // Escape and print. 1.440 + } 1.441 + } 1.442 + } 1.443 + *ptr2++='\"'; 1.444 + *ptr2++=0; 1.445 + return out; 1.446 +} 1.447 + 1.448 +//----------------------------------------------------------------------------- 1.449 +// Utility to jump whitespace and cr/lf 1.450 +static const char* skip(const char* in) 1.451 +{ 1.452 + while (in && *in && (unsigned char)*in<=' ') 1.453 + in++; 1.454 + return in; 1.455 +} 1.456 + 1.457 +//----------------------------------------------------------------------------- 1.458 +// Parses the supplied buffer of JSON text and returns a JSON object tree 1.459 +// The returned object must be Released after use 1.460 +JSON* JSON::Parse(const char* buff, const char** perror) 1.461 +{ 1.462 + const char* end = 0; 1.463 + JSON* json = new JSON(); 1.464 + 1.465 + if (!json) 1.466 + { 1.467 + AssignError(perror, "Error: Failed to allocate memory"); 1.468 + return 0; 1.469 + } 1.470 + 1.471 + end = json->parseValue(skip(buff), perror); 1.472 + if (!end) 1.473 + { 1.474 + json->Release(); 1.475 + return NULL; 1.476 + } // parse failure. ep is set. 1.477 + 1.478 + return json; 1.479 +} 1.480 + 1.481 +//----------------------------------------------------------------------------- 1.482 +// This version works for buffers that are not null terminated strings. 1.483 +JSON* JSON::ParseBuffer(const char *buff, int len, const char** perror) 1.484 +{ 1.485 + // Our JSON parser does not support length-based parsing, 1.486 + // so ensure it is null-terminated. 1.487 + char *termStr = new char[len + 1]; 1.488 + memcpy(termStr, buff, len); 1.489 + termStr[len] = '\0'; 1.490 + 1.491 + JSON *objJson = Parse(termStr, perror); 1.492 + 1.493 + delete[]termStr; 1.494 + 1.495 + return objJson; 1.496 +} 1.497 + 1.498 +//----------------------------------------------------------------------------- 1.499 +// Parser core - when encountering text, process appropriately. 1.500 +const char* JSON::parseValue(const char* buff, const char** perror) 1.501 +{ 1.502 + if (perror) 1.503 + *perror = 0; 1.504 + 1.505 + if (!buff) 1.506 + return NULL; // Fail on null. 1.507 + 1.508 + if (!strncmp(buff,"null",4)) 1.509 + { 1.510 + Type = JSON_Null; 1.511 + return buff+4; 1.512 + } 1.513 + if (!strncmp(buff,"false",5)) 1.514 + { 1.515 + Type = JSON_Bool; 1.516 + Value = "false"; 1.517 + dValue = 0.; 1.518 + return buff+5; 1.519 + } 1.520 + if (!strncmp(buff,"true",4)) 1.521 + { 1.522 + Type = JSON_Bool; 1.523 + Value = "true"; 1.524 + dValue = 1.; 1.525 + return buff + 4; 1.526 + } 1.527 + if (*buff=='\"') 1.528 + { 1.529 + return parseString(buff, perror); 1.530 + } 1.531 + if (*buff=='-' || (*buff>='0' && *buff<='9')) 1.532 + { 1.533 + return parseNumber(buff); 1.534 + } 1.535 + if (*buff=='[') 1.536 + { 1.537 + return parseArray(buff, perror); 1.538 + } 1.539 + if (*buff=='{') 1.540 + { 1.541 + return parseObject(buff, perror); 1.542 + } 1.543 + 1.544 + return AssignError(perror, "Syntax Error: Invalid syntax"); 1.545 +} 1.546 + 1.547 + 1.548 +//----------------------------------------------------------------------------- 1.549 +// Render a value to text. 1.550 +char* JSON::PrintValue(int depth, bool fmt) 1.551 +{ 1.552 + char *out=0; 1.553 + 1.554 + switch (Type) 1.555 + { 1.556 + case JSON_Null: out = JSON_strdup("null"); break; 1.557 + case JSON_Bool: 1.558 + if ((int)dValue == 0) 1.559 + out = JSON_strdup("false"); 1.560 + else 1.561 + out = JSON_strdup("true"); 1.562 + break; 1.563 + case JSON_Number: out = PrintNumber(dValue); break; 1.564 + case JSON_String: out = PrintString(Value); break; 1.565 + case JSON_Array: out = PrintArray(depth, fmt); break; 1.566 + case JSON_Object: out = PrintObject(depth, fmt); break; 1.567 + case JSON_None: OVR_ASSERT_LOG(false, ("Bad JSON type.")); break; 1.568 + } 1.569 + return out; 1.570 +} 1.571 + 1.572 +//----------------------------------------------------------------------------- 1.573 +// Build an array object from input text and returns the text position after 1.574 +// the parsed array 1.575 +const char* JSON::parseArray(const char* buff, const char** perror) 1.576 +{ 1.577 + JSON *child; 1.578 + if (*buff!='[') 1.579 + { 1.580 + return AssignError(perror, "Syntax Error: Missing opening bracket"); 1.581 + } 1.582 + 1.583 + Type=JSON_Array; 1.584 + buff=skip(buff+1); 1.585 + 1.586 + if (*buff==']') 1.587 + return buff+1; // empty array. 1.588 + 1.589 + child = new JSON(); 1.590 + if (!child) 1.591 + return 0; // memory fail 1.592 + Children.PushBack(child); 1.593 + 1.594 + buff=skip(child->parseValue(skip(buff), perror)); // skip any spacing, get the buff. 1.595 + if (!buff) 1.596 + return 0; 1.597 + 1.598 + while (*buff==',') 1.599 + { 1.600 + JSON *new_item = new JSON(); 1.601 + if (!new_item) 1.602 + return AssignError(perror, "Error: Failed to allocate memory"); 1.603 + 1.604 + Children.PushBack(new_item); 1.605 + 1.606 + buff=skip(new_item->parseValue(skip(buff+1), perror)); 1.607 + if (!buff) 1.608 + return AssignError(perror, "Error: Failed to allocate memory"); 1.609 + } 1.610 + 1.611 + if (*buff==']') 1.612 + return buff+1; // end of array 1.613 + 1.614 + return AssignError(perror, "Syntax Error: Missing ending bracket"); 1.615 +} 1.616 + 1.617 +//----------------------------------------------------------------------------- 1.618 +// Render an array to text. The returned text must be freed 1.619 +char* JSON::PrintArray(int depth, bool fmt) 1.620 +{ 1.621 + char ** entries; 1.622 + char * out = 0, *ptr,*ret; 1.623 + intptr_t len = 5; 1.624 + 1.625 + bool fail = false; 1.626 + 1.627 + // How many entries in the array? 1.628 + int numentries = GetItemCount(); 1.629 + if (!numentries) 1.630 + { 1.631 + out=(char*)OVR_ALLOC(3); 1.632 + if (out) 1.633 + OVR_strcpy(out, 3, "[]"); 1.634 + return out; 1.635 + } 1.636 + // Allocate an array to hold the values for each 1.637 + entries=(char**)OVR_ALLOC(numentries*sizeof(char*)); 1.638 + if (!entries) 1.639 + return 0; 1.640 + memset(entries,0,numentries*sizeof(char*)); 1.641 + 1.642 + //// Retrieve all the results: 1.643 + JSON* child = Children.GetFirst(); 1.644 + for (int i=0; i<numentries; i++) 1.645 + { 1.646 + //JSON* child = Children[i]; 1.647 + ret=child->PrintValue(depth+1, fmt); 1.648 + entries[i]=ret; 1.649 + if (ret) 1.650 + len+=OVR_strlen(ret)+2+(fmt?1:0); 1.651 + else 1.652 + { 1.653 + fail = true; 1.654 + break; 1.655 + } 1.656 + child = Children.GetNext(child); 1.657 + } 1.658 + 1.659 + // If we didn't fail, try to malloc the output string 1.660 + if (!fail) 1.661 + out=(char*)OVR_ALLOC(len); 1.662 + // If that fails, we fail. 1.663 + if (!out) 1.664 + fail = true; 1.665 + 1.666 + // Handle failure. 1.667 + if (fail) 1.668 + { 1.669 + for (int i=0; i<numentries; i++) 1.670 + { 1.671 + if (entries[i]) 1.672 + OVR_FREE(entries[i]); 1.673 + } 1.674 + OVR_FREE(entries); 1.675 + return 0; 1.676 + } 1.677 + 1.678 + // Compose the output array. 1.679 + *out='['; 1.680 + ptr=out+1; 1.681 + *ptr=0; 1.682 + for (int i=0; i<numentries; i++) 1.683 + { 1.684 + OVR_strcpy(ptr, len - (ptr-out), entries[i]); 1.685 + ptr+=OVR_strlen(entries[i]); 1.686 + if (i!=numentries-1) 1.687 + { 1.688 + *ptr++=','; 1.689 + if (fmt) 1.690 + *ptr++=' '; 1.691 + *ptr=0; 1.692 + } 1.693 + OVR_FREE(entries[i]); 1.694 + } 1.695 + OVR_FREE(entries); 1.696 + *ptr++=']'; 1.697 + *ptr++=0; 1.698 + return out; 1.699 +} 1.700 + 1.701 +//----------------------------------------------------------------------------- 1.702 +// Build an object from the supplied text and returns the text position after 1.703 +// the parsed object 1.704 +const char* JSON::parseObject(const char* buff, const char** perror) 1.705 +{ 1.706 + if (*buff!='{') 1.707 + { 1.708 + return AssignError(perror, "Syntax Error: Missing opening brace"); 1.709 + } 1.710 + 1.711 + Type=JSON_Object; 1.712 + buff=skip(buff+1); 1.713 + if (*buff=='}') 1.714 + return buff+1; // empty array. 1.715 + 1.716 + JSON* child = new JSON(); 1.717 + Children.PushBack(child); 1.718 + 1.719 + buff=skip(child->parseString(skip(buff), perror)); 1.720 + if (!buff) 1.721 + return 0; 1.722 + child->Name = child->Value; 1.723 + child->Value.Clear(); 1.724 + 1.725 + if (*buff!=':') 1.726 + { 1.727 + return AssignError(perror, "Syntax Error: Missing colon"); 1.728 + } 1.729 + 1.730 + buff=skip(child->parseValue(skip(buff+1), perror)); // skip any spacing, get the value. 1.731 + if (!buff) 1.732 + return 0; 1.733 + 1.734 + while (*buff==',') 1.735 + { 1.736 + child = new JSON(); 1.737 + if (!child) 1.738 + return 0; // memory fail 1.739 + 1.740 + Children.PushBack(child); 1.741 + 1.742 + buff=skip(child->parseString(skip(buff+1), perror)); 1.743 + if (!buff) 1.744 + return 0; 1.745 + 1.746 + child->Name=child->Value; 1.747 + child->Value.Clear(); 1.748 + 1.749 + if (*buff!=':') 1.750 + { 1.751 + return AssignError(perror, "Syntax Error: Missing colon"); 1.752 + } // fail! 1.753 + 1.754 + // Skip any spacing, get the value. 1.755 + buff=skip(child->parseValue(skip(buff+1), perror)); 1.756 + if (!buff) 1.757 + return 0; 1.758 + } 1.759 + 1.760 + if (*buff=='}') 1.761 + return buff+1; // end of array 1.762 + 1.763 + return AssignError(perror, "Syntax Error: Missing closing brace"); 1.764 +} 1.765 + 1.766 +//----------------------------------------------------------------------------- 1.767 +// Render an object to text. The returned string must be freed 1.768 +char* JSON::PrintObject(int depth, bool fmt) 1.769 +{ 1.770 + char** entries = 0, **names = 0; 1.771 + char* out = 0; 1.772 + char* ptr, *ret, *str; 1.773 + intptr_t len = 7, i = 0, j; 1.774 + bool fail = false; 1.775 + 1.776 + // Count the number of entries. 1.777 + int numentries = GetItemCount(); 1.778 + 1.779 + // Explicitly handle empty object case 1.780 + if (numentries == 0) 1.781 + { 1.782 + out=(char*)OVR_ALLOC(fmt?depth+4:4); 1.783 + if (!out) 1.784 + return 0; 1.785 + ptr=out; 1.786 + *ptr++='{'; 1.787 + 1.788 + if (fmt) 1.789 + { 1.790 + *ptr++='\n'; 1.791 + for (i=0;i<depth-1;i++) 1.792 + *ptr++='\t'; 1.793 + } 1.794 + *ptr++='}'; 1.795 + *ptr++=0; 1.796 + return out; 1.797 + } 1.798 + // Allocate space for the names and the objects 1.799 + entries=(char**)OVR_ALLOC(numentries*sizeof(char*)); 1.800 + if (!entries) 1.801 + return 0; 1.802 + names=(char**)OVR_ALLOC(numentries*sizeof(char*)); 1.803 + 1.804 + if (!names) 1.805 + { 1.806 + OVR_FREE(entries); 1.807 + return 0; 1.808 + } 1.809 + memset(entries,0,sizeof(char*)*numentries); 1.810 + memset(names,0,sizeof(char*)*numentries); 1.811 + 1.812 + // Collect all the results into our arrays: 1.813 + depth++; 1.814 + if (fmt) 1.815 + len+=depth; 1.816 + 1.817 + JSON* child = Children.GetFirst(); 1.818 + while (!Children.IsNull(child)) 1.819 + { 1.820 + names[i] = str = PrintString(child->Name); 1.821 + entries[i++] = ret = child->PrintValue(depth, fmt); 1.822 + 1.823 + if (str && ret) 1.824 + { 1.825 + len += OVR_strlen(ret)+OVR_strlen(str)+2+(fmt?3+depth:0); 1.826 + } 1.827 + else 1.828 + { 1.829 + fail = true; 1.830 + break; 1.831 + } 1.832 + 1.833 + child = Children.GetNext(child); 1.834 + } 1.835 + 1.836 + // Try to allocate the output string 1.837 + if (!fail) 1.838 + out=(char*)OVR_ALLOC(len); 1.839 + if (!out) 1.840 + fail=true; 1.841 + 1.842 + // Handle failure 1.843 + if (fail) 1.844 + { 1.845 + for (i=0;i<numentries;i++) 1.846 + { 1.847 + if (names[i]) 1.848 + OVR_FREE(names[i]); 1.849 + 1.850 + if (entries[i]) 1.851 + OVR_FREE(entries[i]);} 1.852 + 1.853 + OVR_FREE(names); 1.854 + OVR_FREE(entries); 1.855 + return 0; 1.856 + } 1.857 + 1.858 + // Compose the output: 1.859 + *out = '{'; 1.860 + ptr = out+1; 1.861 + if (fmt) 1.862 + { 1.863 +#ifdef OVR_OS_WIN32 1.864 + *ptr++ = '\r'; 1.865 +#endif 1.866 + *ptr++ = '\n'; 1.867 + } 1.868 + *ptr = 0; 1.869 + 1.870 + for (i=0; i<numentries; i++) 1.871 + { 1.872 + if (fmt) 1.873 + { 1.874 + for (j = 0; j < depth; j++) 1.875 + { 1.876 + *ptr++ = '\t'; 1.877 + } 1.878 + } 1.879 + OVR_strcpy(ptr, len - (ptr-out), names[i]); 1.880 + ptr += OVR_strlen(names[i]); 1.881 + *ptr++ =':'; 1.882 + 1.883 + if (fmt) 1.884 + { 1.885 + *ptr++ = '\t'; 1.886 + } 1.887 + 1.888 + OVR_strcpy(ptr, len - (ptr-out), entries[i]); 1.889 + ptr+=OVR_strlen(entries[i]); 1.890 + 1.891 + if (i != numentries - 1) 1.892 + { 1.893 + *ptr++ = ','; 1.894 + } 1.895 + 1.896 + if (fmt) 1.897 + { 1.898 +#ifdef OVR_OS_WIN32 1.899 + *ptr++ = '\r'; 1.900 +#endif 1.901 + *ptr++ = '\n'; 1.902 + } 1.903 + *ptr = 0; 1.904 + 1.905 + OVR_FREE(names[i]); 1.906 + OVR_FREE(entries[i]); 1.907 + } 1.908 + 1.909 + OVR_FREE(names); 1.910 + OVR_FREE(entries); 1.911 + 1.912 + if (fmt) 1.913 + { 1.914 + for (i = 0; i < depth - 1; i++) 1.915 + { 1.916 + *ptr++ = '\t'; 1.917 + } 1.918 + } 1.919 + *ptr++='}'; 1.920 + *ptr++=0; 1.921 + 1.922 + return out; 1.923 +} 1.924 + 1.925 + 1.926 + 1.927 +// Returns the number of child items in the object 1.928 +// Counts the number of items in the object. 1.929 +unsigned JSON::GetItemCount() const 1.930 +{ 1.931 + unsigned count = 0; 1.932 + for (const JSON* p = Children.GetFirst(); !Children.IsNull(p); p = p->pNext) 1.933 + { 1.934 + count++; 1.935 + } 1.936 + return count; 1.937 +} 1.938 + 1.939 +JSON* JSON::GetItemByIndex(unsigned index) 1.940 +{ 1.941 + unsigned i = 0; 1.942 + JSON* child = 0; 1.943 + 1.944 + if (!Children.IsEmpty()) 1.945 + { 1.946 + child = Children.GetFirst(); 1.947 + 1.948 + while (i < index) 1.949 + { 1.950 + if (Children.IsNull(child->pNext)) 1.951 + { 1.952 + child = 0; 1.953 + break; 1.954 + } 1.955 + child = child->pNext; 1.956 + i++; 1.957 + } 1.958 + } 1.959 + 1.960 + return child; 1.961 +} 1.962 + 1.963 +// Returns the child item with the given name or NULL if not found 1.964 +JSON* JSON::GetItemByName(const char* name) 1.965 +{ 1.966 + JSON* child = 0; 1.967 + 1.968 + if (!Children.IsEmpty()) 1.969 + { 1.970 + child = Children.GetFirst(); 1.971 + 1.972 + while (OVR_strcmp(child->Name, name) != 0) 1.973 + { 1.974 + if (Children.IsNull(child->pNext)) 1.975 + { 1.976 + child = 0; 1.977 + break; 1.978 + } 1.979 + child = child->pNext; 1.980 + } 1.981 + } 1.982 + 1.983 + return child; 1.984 +} 1.985 + 1.986 +//----------------------------------------------------------------------------- 1.987 +// Adds a new item to the end of the child list 1.988 +void JSON::AddItem(const char *string, JSON *item) 1.989 +{ 1.990 + if (item) 1.991 + { 1.992 + item->Name = string; 1.993 + Children.PushBack(item); 1.994 + } 1.995 +} 1.996 + 1.997 +/* 1.998 + 1.999 +// Removes and frees the items at the given index 1.1000 +void JSON::DeleteItem(unsigned int index) 1.1001 +{ 1.1002 + unsigned int num_items = 0; 1.1003 + JSON* child = Children.GetFirst(); 1.1004 + while (!Children.IsNull(child) && num_items < index) 1.1005 + { 1.1006 + num_items++; 1.1007 + child = Children.GetNext(child); 1.1008 + } 1.1009 + 1.1010 + if (!Children.IsNull(child)) 1.1011 + 1.1012 + child->RemoveNode(); 1.1013 + child->Release(); 1.1014 + } 1.1015 +} 1.1016 + 1.1017 +// Replaces and frees the item at the give index with the new item 1.1018 +void JSON::ReplaceItem(unsigned int index, JSON* new_item) 1.1019 +{ 1.1020 + unsigned int num_items = 0; 1.1021 + JSON* child = Children.GetFirst(); 1.1022 + while (!Children.IsNull(child) && num_items < index) 1.1023 + { 1.1024 + num_items++; 1.1025 + child = Children.GetNext(child); 1.1026 + } 1.1027 + 1.1028 + if (!Children.IsNull(child)) 1.1029 + { 1.1030 + child->ReplaceNodeWith(new_item); 1.1031 + child->Release(); 1.1032 + } 1.1033 +} 1.1034 +*/ 1.1035 + 1.1036 +// Removes and frees the last child item 1.1037 +void JSON::RemoveLast() 1.1038 +{ 1.1039 + JSON* child = Children.GetLast(); 1.1040 + if (!Children.IsNull(child)) 1.1041 + { 1.1042 + child->RemoveNode(); 1.1043 + child->Release(); 1.1044 + } 1.1045 +} 1.1046 + 1.1047 +JSON* JSON::CreateBool(bool b) 1.1048 +{ 1.1049 + JSON *item = new JSON(JSON_Bool); 1.1050 + if (item) 1.1051 + { 1.1052 + item->dValue = b ? 1. : 0.; 1.1053 + item->Value = b ? "true" : "false"; 1.1054 + } 1.1055 + return item; 1.1056 +} 1.1057 + 1.1058 +JSON* JSON::CreateNumber(double num) 1.1059 +{ 1.1060 + JSON *item = new JSON(JSON_Number); 1.1061 + if (item) 1.1062 + { 1.1063 + item->dValue = num; 1.1064 + } 1.1065 + return item; 1.1066 +} 1.1067 + 1.1068 +JSON* JSON::CreateInt(int num) 1.1069 +{ 1.1070 + JSON *item = new JSON(JSON_Number); 1.1071 + if (item) 1.1072 + { 1.1073 + item->dValue = num; 1.1074 + } 1.1075 + return item; 1.1076 +} 1.1077 + 1.1078 +JSON* JSON::CreateString(const char *s) 1.1079 +{ 1.1080 + JSON *item = new JSON(JSON_String); 1.1081 + if (item && s) 1.1082 + { 1.1083 + item->Value = s; 1.1084 + } 1.1085 + return item; 1.1086 +} 1.1087 + 1.1088 + 1.1089 +//----------------------------------------------------------------------------- 1.1090 +// Get elements by name 1.1091 +double JSON::GetNumberByName(const char *name, double defValue) 1.1092 +{ 1.1093 + JSON* item = GetItemByName(name); 1.1094 + if (!item || item->Type != JSON_Number) 1.1095 + { 1.1096 + return defValue; 1.1097 + } 1.1098 + else 1.1099 + { 1.1100 + return item->dValue; 1.1101 + } 1.1102 +} 1.1103 + 1.1104 +int JSON::GetIntByName(const char *name, int defValue) 1.1105 +{ 1.1106 + JSON* item = GetItemByName(name); 1.1107 + if (!item || item->Type != JSON_Number) 1.1108 + { 1.1109 + return defValue; 1.1110 + } 1.1111 + else 1.1112 + { 1.1113 + return (int)item->dValue; 1.1114 + } 1.1115 +} 1.1116 + 1.1117 +bool JSON::GetBoolByName(const char *name, bool defValue) 1.1118 +{ 1.1119 + JSON* item = GetItemByName(name); 1.1120 + if (!item || item->Type != JSON_Bool) 1.1121 + { 1.1122 + return defValue; 1.1123 + } 1.1124 + else 1.1125 + { 1.1126 + return (int)item->dValue != 0; 1.1127 + } 1.1128 +} 1.1129 + 1.1130 +String JSON::GetStringByName(const char *name, const String &defValue) 1.1131 +{ 1.1132 + JSON* item = GetItemByName(name); 1.1133 + if (!item || item->Type != JSON_String) 1.1134 + { 1.1135 + return defValue; 1.1136 + } 1.1137 + else 1.1138 + { 1.1139 + return item->Value; 1.1140 + } 1.1141 +} 1.1142 + 1.1143 +//----------------------------------------------------------------------------- 1.1144 +// Adds an element to an array object type 1.1145 +void JSON::AddArrayElement(JSON *item) 1.1146 +{ 1.1147 + if (item) 1.1148 + { 1.1149 + Children.PushBack(item); 1.1150 + } 1.1151 +} 1.1152 + 1.1153 +// Inserts an element into a valid array position 1.1154 +void JSON::InsertArrayElement(int index, JSON *item) 1.1155 +{ 1.1156 + if (!item) 1.1157 + { 1.1158 + return; 1.1159 + } 1.1160 + 1.1161 + if (index == 0) 1.1162 + { 1.1163 + Children.PushFront(item); 1.1164 + return; 1.1165 + } 1.1166 + 1.1167 + JSON* iter = Children.GetFirst(); 1.1168 + int i=0; 1.1169 + while (iter && i<index) 1.1170 + { 1.1171 + iter = Children.GetNext(iter); 1.1172 + i++; 1.1173 + } 1.1174 + 1.1175 + if (iter) 1.1176 + iter->InsertNodeBefore(item); 1.1177 + else 1.1178 + Children.PushBack(item); 1.1179 +} 1.1180 + 1.1181 +// Returns the size of an array 1.1182 +int JSON::GetArraySize() 1.1183 +{ 1.1184 + if (Type == JSON_Array) 1.1185 + { 1.1186 + return GetItemCount(); 1.1187 + } 1.1188 + 1.1189 + return 0; 1.1190 +} 1.1191 + 1.1192 +// Returns the number value an the give array index 1.1193 +double JSON::GetArrayNumber(int index) 1.1194 +{ 1.1195 + if (Type == JSON_Array) 1.1196 + { 1.1197 + JSON* number = GetItemByIndex(index); 1.1198 + return number ? number->dValue : 0.0; 1.1199 + } 1.1200 + 1.1201 + return 0; 1.1202 +} 1.1203 + 1.1204 +// Returns the string value at the given array index 1.1205 +const char* JSON::GetArrayString(int index) 1.1206 +{ 1.1207 + if (Type == JSON_Array) 1.1208 + { 1.1209 + JSON* number = GetItemByIndex(index); 1.1210 + return number ? number->Value : 0; 1.1211 + } 1.1212 + 1.1213 + return 0; 1.1214 +} 1.1215 + 1.1216 +JSON* JSON::Copy() 1.1217 +{ 1.1218 + JSON* copy = new JSON(Type); 1.1219 + copy->Name = Name; 1.1220 + copy->Value = Value; 1.1221 + copy->dValue = dValue; 1.1222 + 1.1223 + JSON* child = Children.GetFirst(); 1.1224 + while (!Children.IsNull(child)) 1.1225 + { 1.1226 + copy->Children.PushBack(child->Copy()); 1.1227 + child = Children.GetNext(child); 1.1228 + } 1.1229 + 1.1230 + return copy; 1.1231 +} 1.1232 + 1.1233 +//----------------------------------------------------------------------------- 1.1234 +// Loads and parses the given JSON file pathname and returns a JSON object tree. 1.1235 +// The returned object must be Released after use. 1.1236 +JSON* JSON::Load(const char* path, const char** perror) 1.1237 +{ 1.1238 + SysFile f; 1.1239 + if (!f.Open(path, File::Open_Read, File::Mode_Read)) 1.1240 + { 1.1241 + AssignError(perror, "Failed to open file"); 1.1242 + return NULL; 1.1243 + } 1.1244 + 1.1245 + int len = f.GetLength(); 1.1246 + uint8_t* buff = (uint8_t*)OVR_ALLOC(len + 1); 1.1247 + int bytes = f.Read(buff, len); 1.1248 + f.Close(); 1.1249 + 1.1250 + if (bytes == 0 || bytes != len) 1.1251 + { 1.1252 + OVR_FREE(buff); 1.1253 + return NULL; 1.1254 + } 1.1255 + 1.1256 + // Ensure the result is null-terminated since Parse() expects null-terminated input. 1.1257 + buff[len] = '\0'; 1.1258 + 1.1259 + JSON* json = JSON::Parse((char*)buff, perror); 1.1260 + OVR_FREE(buff); 1.1261 + return json; 1.1262 +} 1.1263 + 1.1264 +//----------------------------------------------------------------------------- 1.1265 +// Serializes the JSON object and writes to the give file path 1.1266 +bool JSON::Save(const char* path) 1.1267 +{ 1.1268 + SysFile f; 1.1269 + if (!f.Open(path, File::Open_Write | File::Open_Create | File::Open_Truncate, File::Mode_Write)) 1.1270 + return false; 1.1271 + 1.1272 + char* text = PrintValue(0, true); 1.1273 + if (text) 1.1274 + { 1.1275 + intptr_t len = OVR_strlen(text); 1.1276 + OVR_ASSERT(len <= (intptr_t)(int)len); 1.1277 + 1.1278 + int bytes = f.Write((uint8_t*)text, (int)len); 1.1279 + f.Close(); 1.1280 + OVR_FREE(text); 1.1281 + return (bytes == len); 1.1282 + } 1.1283 + else 1.1284 + { 1.1285 + return false; 1.1286 + } 1.1287 +} 1.1288 + 1.1289 + 1.1290 +} // namespace OVR