oculus1
diff libovr/Src/OVR_JSON.cpp @ 1:e2f9e4603129
added LibOVR and started a simple vr wrapper.
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 14 Sep 2013 16:14:59 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libovr/Src/OVR_JSON.cpp Sat Sep 14 16:14:59 2013 +0300 1.3 @@ -0,0 +1,1056 @@ 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 2012 Oculus VR, Inc. All Rights reserved. 1.37 + 1.38 +Use of this software is subject to the terms of the Oculus license 1.39 +agreement provided at the time of installation or download, or which 1.40 +otherwise accompanies this software in either electronic or hard copy form. 1.41 + 1.42 +************************************************************************************/ 1.43 + 1.44 +#include <string.h> 1.45 +#include <stdio.h> 1.46 +#include <math.h> 1.47 +#include <stdlib.h> 1.48 +#include <float.h> 1.49 +#include <limits.h> 1.50 +#include <ctype.h> 1.51 +#include "OVR_JSON.h" 1.52 +#include "Kernel/OVR_SysFile.h" 1.53 +#include "Kernel/OVR_Log.h" 1.54 + 1.55 +namespace OVR { 1.56 + 1.57 + 1.58 +//----------------------------------------------------------------------------- 1.59 +// Create a new copy of a string 1.60 +static char* JSON_strdup(const char* str) 1.61 +{ 1.62 + UPInt len = OVR_strlen(str) + 1; 1.63 + char* copy = (char*)OVR_ALLOC(len); 1.64 + if (!copy) 1.65 + return 0; 1.66 + memcpy(copy, str, len); 1.67 + return copy; 1.68 +} 1.69 + 1.70 + 1.71 +//----------------------------------------------------------------------------- 1.72 +// Render the number from the given item into a string. 1.73 +static char* PrintNumber(double d) 1.74 +{ 1.75 + char *str; 1.76 + //double d=item->valuedouble; 1.77 + int valueint = (int)d; 1.78 + if (fabs(((double)valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) 1.79 + { 1.80 + str=(char*)OVR_ALLOC(21); // 2^64+1 can be represented in 21 chars. 1.81 + if (str) 1.82 + OVR_sprintf(str, 21, "%d", valueint); 1.83 + } 1.84 + else 1.85 + { 1.86 + str=(char*)OVR_ALLOC(64); // This is a nice tradeoff. 1.87 + if (str) 1.88 + { 1.89 + if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60) 1.90 + OVR_sprintf(str, 64, "%.0f", d); 1.91 + else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) 1.92 + OVR_sprintf(str, 64, "%e", d); 1.93 + else 1.94 + OVR_sprintf(str, 64, "%f", d); 1.95 + } 1.96 + } 1.97 + return str; 1.98 +} 1.99 + 1.100 +// Parse the input text into an un-escaped cstring, and populate item. 1.101 +static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; 1.102 + 1.103 +// Helper to assign error sting and return 0. 1.104 +const char* AssignError(const char** perror, const char *errorMessage) 1.105 +{ 1.106 + if (perror) 1.107 + *perror = errorMessage; 1.108 + return 0; 1.109 +} 1.110 + 1.111 +//----------------------------------------------------------------------------- 1.112 +// ***** JSON Node class 1.113 + 1.114 +JSON::JSON(JSONItemType itemType) 1.115 + : Type(itemType), dValue(0.0) 1.116 +{ 1.117 +} 1.118 + 1.119 +JSON::~JSON() 1.120 +{ 1.121 + JSON* child = Children.GetFirst(); 1.122 + while (!Children.IsNull(child)) 1.123 + { 1.124 + child->RemoveNode(); 1.125 + child->Release(); 1.126 + child = Children.GetFirst(); 1.127 + } 1.128 +} 1.129 + 1.130 +//----------------------------------------------------------------------------- 1.131 +// Parse the input text to generate a number, and populate the result into item 1.132 +// Returns the text position after the parsed number 1.133 +const char* JSON::parseNumber(const char *num) 1.134 +{ 1.135 + const char* num_start = num; 1.136 + double n=0, sign=1, scale=0; 1.137 + int subscale = 0, 1.138 + signsubscale = 1; 1.139 + 1.140 + // Could use sscanf for this? 1.141 + if (*num=='-') 1.142 + sign=-1,num++; // Has sign? 1.143 + if (*num=='0') 1.144 + num++; // is zero 1.145 + 1.146 + if (*num>='1' && *num<='9') 1.147 + { 1.148 + do 1.149 + { 1.150 + n=(n*10.0)+(*num++ -'0'); 1.151 + } 1.152 + while (*num>='0' && *num<='9'); // Number? 1.153 + } 1.154 + 1.155 + if (*num=='.' && num[1]>='0' && num[1]<='9') 1.156 + { 1.157 + num++; 1.158 + do 1.159 + { 1.160 + n=(n*10.0)+(*num++ -'0'); 1.161 + scale--; 1.162 + } 1.163 + while (*num>='0' && *num<='9'); // Fractional part? 1.164 + } 1.165 + 1.166 + if (*num=='e' || *num=='E') // Exponent? 1.167 + { 1.168 + num++; 1.169 + if (*num=='+') 1.170 + num++; 1.171 + else if (*num=='-') 1.172 + { 1.173 + signsubscale=-1; 1.174 + num++; // With sign? 1.175 + } 1.176 + 1.177 + while (*num>='0' && *num<='9') 1.178 + subscale=(subscale*10)+(*num++ - '0'); // Number? 1.179 + } 1.180 + 1.181 + // Number = +/- number.fraction * 10^+/- exponent 1.182 + n = sign*n*pow(10.0,(scale+subscale*signsubscale)); 1.183 + 1.184 + // Assign parsed value. 1.185 + Type = JSON_Number; 1.186 + dValue = n; 1.187 + Value.AssignString(num_start, num - num_start); 1.188 + 1.189 + return num; 1.190 +} 1.191 + 1.192 +// Parses a hex string up to the specified number of digits. 1.193 +// Returns the first character after the string. 1.194 +const char* ParseHex(unsigned* val, unsigned digits, const char* str) 1.195 +{ 1.196 + *val = 0; 1.197 + 1.198 + for(unsigned digitCount = 0; digitCount < digits; digitCount++, str++) 1.199 + { 1.200 + unsigned v = *str; 1.201 + 1.202 + if ((v >= '0') && (v <= '9')) 1.203 + v -= '0'; 1.204 + else if ((v >= 'a') && (v <= 'f')) 1.205 + v = 10 + v - 'a'; 1.206 + else if ((v >= 'A') && (v <= 'F')) 1.207 + v = 10 + v - 'A'; 1.208 + else 1.209 + break; 1.210 + 1.211 + *val = *val * 16 + v; 1.212 + } 1.213 + 1.214 + return str; 1.215 +} 1.216 + 1.217 +//----------------------------------------------------------------------------- 1.218 +// Parses the input text into a string item and returns the text position after 1.219 +// the parsed string 1.220 +const char* JSON::parseString(const char* str, const char** perror) 1.221 +{ 1.222 + const char* ptr = str+1; 1.223 + const char* p; 1.224 + char* ptr2; 1.225 + char* out; 1.226 + int len=0; 1.227 + unsigned uc, uc2; 1.228 + 1.229 + if (*str!='\"') 1.230 + { 1.231 + return AssignError(perror, "Syntax Error: Missing quote"); 1.232 + } 1.233 + 1.234 + while (*ptr!='\"' && *ptr && ++len) 1.235 + { 1.236 + if (*ptr++ == '\\') ptr++; // Skip escaped quotes. 1.237 + } 1.238 + 1.239 + // This is how long we need for the string, roughly. 1.240 + out=(char*)OVR_ALLOC(len+1); 1.241 + if (!out) 1.242 + return 0; 1.243 + 1.244 + ptr = str+1; 1.245 + ptr2= out; 1.246 + 1.247 + while (*ptr!='\"' && *ptr) 1.248 + { 1.249 + if (*ptr!='\\') 1.250 + { 1.251 + *ptr2++ = *ptr++; 1.252 + } 1.253 + else 1.254 + { 1.255 + ptr++; 1.256 + switch (*ptr) 1.257 + { 1.258 + case 'b': *ptr2++ = '\b'; break; 1.259 + case 'f': *ptr2++ = '\f'; break; 1.260 + case 'n': *ptr2++ = '\n'; break; 1.261 + case 'r': *ptr2++ = '\r'; break; 1.262 + case 't': *ptr2++ = '\t'; break; 1.263 + 1.264 + // Transcode utf16 to utf8. 1.265 + case 'u': 1.266 + 1.267 + // Get the unicode char. 1.268 + p = ParseHex(&uc, 4, ptr + 1); 1.269 + if (ptr != p) 1.270 + ptr = p - 1; 1.271 + 1.272 + if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) 1.273 + break; // Check for invalid. 1.274 + 1.275 + // UTF16 surrogate pairs. 1.276 + if (uc>=0xD800 && uc<=0xDBFF) 1.277 + { 1.278 + if (ptr[1]!='\\' || ptr[2]!='u') 1.279 + break; // Missing second-half of surrogate. 1.280 + 1.281 + p= ParseHex(&uc2, 4, ptr + 3); 1.282 + if (ptr != p) 1.283 + ptr = p - 1; 1.284 + 1.285 + if (uc2<0xDC00 || uc2>0xDFFF) 1.286 + break; // Invalid second-half of surrogate. 1.287 + 1.288 + uc = 0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); 1.289 + } 1.290 + 1.291 + len=4; 1.292 + 1.293 + if (uc<0x80) 1.294 + len=1; 1.295 + else if (uc<0x800) 1.296 + len=2; 1.297 + else if (uc<0x10000) 1.298 + len=3; 1.299 + 1.300 + ptr2+=len; 1.301 + 1.302 + switch (len) 1.303 + { 1.304 + case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 1.305 + case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 1.306 + case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 1.307 + case 1: *--ptr2 = (char)(uc | firstByteMark[len]); 1.308 + } 1.309 + ptr2+=len; 1.310 + break; 1.311 + 1.312 + default: 1.313 + *ptr2++ = *ptr; 1.314 + break; 1.315 + } 1.316 + ptr++; 1.317 + } 1.318 + } 1.319 + 1.320 + *ptr2 = 0; 1.321 + if (*ptr=='\"') 1.322 + ptr++; 1.323 + 1.324 + // Make a copy of the string 1.325 + Value=out; 1.326 + OVR_FREE(out); 1.327 + Type=JSON_String; 1.328 + 1.329 + return ptr; 1.330 +} 1.331 + 1.332 +//----------------------------------------------------------------------------- 1.333 +// Render the string provided to an escaped version that can be printed. 1.334 +char* PrintString(const char* str) 1.335 +{ 1.336 + const char *ptr; 1.337 + char *ptr2,*out; 1.338 + int len=0; 1.339 + unsigned char token; 1.340 + 1.341 + if (!str) 1.342 + return JSON_strdup(""); 1.343 + ptr=str; 1.344 + 1.345 + token=*ptr; 1.346 + while (token && ++len)\ 1.347 + { 1.348 + if (strchr("\"\\\b\f\n\r\t",token)) 1.349 + len++; 1.350 + else if (token<32) 1.351 + len+=5; 1.352 + ptr++; 1.353 + token=*ptr; 1.354 + } 1.355 + 1.356 + int buff_size = len+3; 1.357 + out=(char*)OVR_ALLOC(buff_size); 1.358 + if (!out) 1.359 + return 0; 1.360 + 1.361 + ptr2 = out; 1.362 + ptr = str; 1.363 + *ptr2++ = '\"'; 1.364 + 1.365 + while (*ptr) 1.366 + { 1.367 + if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') 1.368 + *ptr2++=*ptr++; 1.369 + else 1.370 + { 1.371 + *ptr2++='\\'; 1.372 + switch (token=*ptr++) 1.373 + { 1.374 + case '\\': *ptr2++='\\'; break; 1.375 + case '\"': *ptr2++='\"'; break; 1.376 + case '\b': *ptr2++='b'; break; 1.377 + case '\f': *ptr2++='f'; break; 1.378 + case '\n': *ptr2++='n'; break; 1.379 + case '\r': *ptr2++='r'; break; 1.380 + case '\t': *ptr2++='t'; break; 1.381 + default: 1.382 + OVR_sprintf(ptr2, buff_size - (ptr2-out), "u%04x",token); 1.383 + ptr2+=5; 1.384 + break; // Escape and print. 1.385 + } 1.386 + } 1.387 + } 1.388 + *ptr2++='\"'; 1.389 + *ptr2++=0; 1.390 + return out; 1.391 +} 1.392 + 1.393 +//----------------------------------------------------------------------------- 1.394 +// Utility to jump whitespace and cr/lf 1.395 +static const char* skip(const char* in) 1.396 +{ 1.397 + while (in && *in && (unsigned char)*in<=' ') 1.398 + in++; 1.399 + return in; 1.400 +} 1.401 + 1.402 +//----------------------------------------------------------------------------- 1.403 +// Parses the supplied buffer of JSON text and returns a JSON object tree 1.404 +// The returned object must be Released after use 1.405 +JSON* JSON::Parse(const char* buff, const char** perror) 1.406 +{ 1.407 + const char* end = 0; 1.408 + JSON* json = new JSON(); 1.409 + 1.410 + if (!json) 1.411 + { 1.412 + AssignError(perror, "Error: Failed to allocate memory"); 1.413 + return 0; 1.414 + } 1.415 + 1.416 + end = json->parseValue(skip(buff), perror); 1.417 + if (!end) 1.418 + { 1.419 + json->Release(); 1.420 + return NULL; 1.421 + } // parse failure. ep is set. 1.422 + 1.423 + return json; 1.424 +} 1.425 + 1.426 +//----------------------------------------------------------------------------- 1.427 +// Parser core - when encountering text, process appropriately. 1.428 +const char* JSON::parseValue(const char* buff, const char** perror) 1.429 +{ 1.430 + if (perror) 1.431 + *perror = 0; 1.432 + 1.433 + if (!buff) 1.434 + return NULL; // Fail on null. 1.435 + 1.436 + if (!strncmp(buff,"null",4)) 1.437 + { 1.438 + Type = JSON_Null; 1.439 + return buff+4; 1.440 + } 1.441 + if (!strncmp(buff,"false",5)) 1.442 + { 1.443 + Type = JSON_Bool; 1.444 + Value = "false"; 1.445 + dValue = 0; 1.446 + return buff+5; 1.447 + } 1.448 + if (!strncmp(buff,"true",4)) 1.449 + { 1.450 + Type = JSON_Bool; 1.451 + Value = "true"; 1.452 + dValue = 1; 1.453 + return buff+4; 1.454 + } 1.455 + if (*buff=='\"') 1.456 + { 1.457 + return parseString(buff, perror); 1.458 + } 1.459 + if (*buff=='-' || (*buff>='0' && *buff<='9')) 1.460 + { 1.461 + return parseNumber(buff); 1.462 + } 1.463 + if (*buff=='[') 1.464 + { 1.465 + return parseArray(buff, perror); 1.466 + } 1.467 + if (*buff=='{') 1.468 + { 1.469 + return parseObject(buff, perror); 1.470 + } 1.471 + 1.472 + return AssignError(perror, "Syntax Error: Invalid syntax"); 1.473 +} 1.474 + 1.475 + 1.476 +//----------------------------------------------------------------------------- 1.477 +// Render a value to text. 1.478 +char* JSON::PrintValue(int depth, bool fmt) 1.479 +{ 1.480 + char *out=0; 1.481 + 1.482 + switch (Type) 1.483 + { 1.484 + case JSON_Null: out = JSON_strdup("null"); break; 1.485 + case JSON_Bool: 1.486 + if (dValue == 0) 1.487 + out = JSON_strdup("false"); 1.488 + else 1.489 + out = JSON_strdup("true"); 1.490 + break; 1.491 + case JSON_Number: out = PrintNumber(dValue); break; 1.492 + case JSON_String: out = PrintString(Value); break; 1.493 + case JSON_Array: out = PrintArray(depth, fmt); break; 1.494 + case JSON_Object: out = PrintObject(depth, fmt); break; 1.495 + case JSON_None: OVR_ASSERT_LOG(false, ("Bad JSON type.")); break; 1.496 + } 1.497 + return out; 1.498 +} 1.499 + 1.500 +//----------------------------------------------------------------------------- 1.501 +// Build an array object from input text and returns the text position after 1.502 +// the parsed array 1.503 +const char* JSON::parseArray(const char* buff, const char** perror) 1.504 +{ 1.505 + JSON *child; 1.506 + if (*buff!='[') 1.507 + { 1.508 + return AssignError(perror, "Syntax Error: Missing opening bracket"); 1.509 + } 1.510 + 1.511 + Type=JSON_Array; 1.512 + buff=skip(buff+1); 1.513 + 1.514 + if (*buff==']') 1.515 + return buff+1; // empty array. 1.516 + 1.517 + child = new JSON(); 1.518 + if (!child) 1.519 + return 0; // memory fail 1.520 + Children.PushBack(child); 1.521 + 1.522 + buff=skip(child->parseValue(skip(buff), perror)); // skip any spacing, get the buff. 1.523 + if (!buff) 1.524 + return 0; 1.525 + 1.526 + while (*buff==',') 1.527 + { 1.528 + JSON *new_item = new JSON(); 1.529 + if (!new_item) 1.530 + return AssignError(perror, "Error: Failed to allocate memory"); 1.531 + 1.532 + Children.PushBack(new_item); 1.533 + 1.534 + buff=skip(new_item->parseValue(skip(buff+1), perror)); 1.535 + if (!buff) 1.536 + return AssignError(perror, "Error: Failed to allocate memory"); 1.537 + } 1.538 + 1.539 + if (*buff==']') 1.540 + return buff+1; // end of array 1.541 + 1.542 + return AssignError(perror, "Syntax Error: Missing ending bracket"); 1.543 +} 1.544 + 1.545 +//----------------------------------------------------------------------------- 1.546 +// Render an array to text. The returned text must be freed 1.547 +char* JSON::PrintArray(int depth, bool fmt) 1.548 +{ 1.549 + char **entries; 1.550 + char * out = 0,*ptr,*ret; 1.551 + SPInt len = 5; 1.552 + 1.553 + bool fail = false; 1.554 + 1.555 + // How many entries in the array? 1.556 + int numentries = GetItemCount(); 1.557 + if (!numentries) 1.558 + { 1.559 + out=(char*)OVR_ALLOC(3); 1.560 + if (out) 1.561 + OVR_strcpy(out, 3, "[]"); 1.562 + return out; 1.563 + } 1.564 + // Allocate an array to hold the values for each 1.565 + entries=(char**)OVR_ALLOC(numentries*sizeof(char*)); 1.566 + if (!entries) 1.567 + return 0; 1.568 + memset(entries,0,numentries*sizeof(char*)); 1.569 + 1.570 + //// Retrieve all the results: 1.571 + JSON* child = Children.GetFirst(); 1.572 + for (int i=0; i<numentries; i++) 1.573 + { 1.574 + //JSON* child = Children[i]; 1.575 + ret=child->PrintValue(depth+1, fmt); 1.576 + entries[i]=ret; 1.577 + if (ret) 1.578 + len+=OVR_strlen(ret)+2+(fmt?1:0); 1.579 + else 1.580 + { 1.581 + fail = true; 1.582 + break; 1.583 + } 1.584 + child = Children.GetNext(child); 1.585 + } 1.586 + 1.587 + // If we didn't fail, try to malloc the output string 1.588 + if (!fail) 1.589 + out=(char*)OVR_ALLOC(len); 1.590 + // If that fails, we fail. 1.591 + if (!out) 1.592 + fail = true; 1.593 + 1.594 + // Handle failure. 1.595 + if (fail) 1.596 + { 1.597 + for (int i=0; i<numentries; i++) 1.598 + { 1.599 + if (entries[i]) 1.600 + OVR_FREE(entries[i]); 1.601 + } 1.602 + OVR_FREE(entries); 1.603 + return 0; 1.604 + } 1.605 + 1.606 + // Compose the output array. 1.607 + *out='['; 1.608 + ptr=out+1; 1.609 + *ptr=0; 1.610 + for (int i=0; i<numentries; i++) 1.611 + { 1.612 + OVR_strcpy(ptr, len - (ptr-out), entries[i]); 1.613 + ptr+=OVR_strlen(entries[i]); 1.614 + if (i!=numentries-1) 1.615 + { 1.616 + *ptr++=','; 1.617 + if (fmt) 1.618 + *ptr++=' '; 1.619 + *ptr=0; 1.620 + } 1.621 + OVR_FREE(entries[i]); 1.622 + } 1.623 + OVR_FREE(entries); 1.624 + *ptr++=']'; 1.625 + *ptr++=0; 1.626 + return out; 1.627 +} 1.628 + 1.629 +//----------------------------------------------------------------------------- 1.630 +// Build an object from the supplied text and returns the text position after 1.631 +// the parsed object 1.632 +const char* JSON::parseObject(const char* buff, const char** perror) 1.633 +{ 1.634 + if (*buff!='{') 1.635 + { 1.636 + return AssignError(perror, "Syntax Error: Missing opening brace"); 1.637 + } 1.638 + 1.639 + Type=JSON_Object; 1.640 + buff=skip(buff+1); 1.641 + if (*buff=='}') 1.642 + return buff+1; // empty array. 1.643 + 1.644 + JSON* child = new JSON(); 1.645 + Children.PushBack(child); 1.646 + 1.647 + buff=skip(child->parseString(skip(buff), perror)); 1.648 + if (!buff) 1.649 + return 0; 1.650 + child->Name = child->Value; 1.651 + child->Value.Clear(); 1.652 + 1.653 + if (*buff!=':') 1.654 + { 1.655 + return AssignError(perror, "Syntax Error: Missing colon"); 1.656 + } 1.657 + 1.658 + buff=skip(child->parseValue(skip(buff+1), perror)); // skip any spacing, get the value. 1.659 + if (!buff) 1.660 + return 0; 1.661 + 1.662 + while (*buff==',') 1.663 + { 1.664 + child = new JSON(); 1.665 + if (!child) 1.666 + return 0; // memory fail 1.667 + 1.668 + Children.PushBack(child); 1.669 + 1.670 + buff=skip(child->parseString(skip(buff+1), perror)); 1.671 + if (!buff) 1.672 + return 0; 1.673 + 1.674 + child->Name=child->Value; 1.675 + child->Value.Clear(); 1.676 + 1.677 + if (*buff!=':') 1.678 + { 1.679 + return AssignError(perror, "Syntax Error: Missing colon"); 1.680 + } // fail! 1.681 + 1.682 + // Skip any spacing, get the value. 1.683 + buff=skip(child->parseValue(skip(buff+1), perror)); 1.684 + if (!buff) 1.685 + return 0; 1.686 + } 1.687 + 1.688 + if (*buff=='}') 1.689 + return buff+1; // end of array 1.690 + 1.691 + return AssignError(perror, "Syntax Error: Missing closing brace"); 1.692 +} 1.693 + 1.694 +//----------------------------------------------------------------------------- 1.695 +// Render an object to text. The returned string must be freed 1.696 +char* JSON::PrintObject(int depth, bool fmt) 1.697 +{ 1.698 + char** entries = 0, **names = 0; 1.699 + char* out = 0; 1.700 + char* ptr, *ret, *str; 1.701 + SPInt len = 7, i = 0, j; 1.702 + bool fail = false; 1.703 + 1.704 + // Count the number of entries. 1.705 + int numentries = GetItemCount(); 1.706 + 1.707 + // Explicitly handle empty object case 1.708 + if (numentries == 0) 1.709 + { 1.710 + out=(char*)OVR_ALLOC(fmt?depth+3:3); 1.711 + if (!out) 1.712 + return 0; 1.713 + ptr=out; 1.714 + *ptr++='{'; 1.715 + 1.716 + if (fmt) 1.717 + { 1.718 + *ptr++='\n'; 1.719 + for (i=0;i<depth-1;i++) 1.720 + *ptr++='\t'; 1.721 + } 1.722 + *ptr++='}'; 1.723 + *ptr++=0; 1.724 + return out; 1.725 + } 1.726 + // Allocate space for the names and the objects 1.727 + entries=(char**)OVR_ALLOC(numentries*sizeof(char*)); 1.728 + if (!entries) 1.729 + return 0; 1.730 + names=(char**)OVR_ALLOC(numentries*sizeof(char*)); 1.731 + 1.732 + if (!names) 1.733 + { 1.734 + OVR_FREE(entries); 1.735 + return 0; 1.736 + } 1.737 + memset(entries,0,sizeof(char*)*numentries); 1.738 + memset(names,0,sizeof(char*)*numentries); 1.739 + 1.740 + // Collect all the results into our arrays: 1.741 + depth++; 1.742 + if (fmt) 1.743 + len+=depth; 1.744 + 1.745 + JSON* child = Children.GetFirst(); 1.746 + while (!Children.IsNull(child)) 1.747 + { 1.748 + names[i] = str = PrintString(child->Name); 1.749 + entries[i++] = ret = child->PrintValue(depth, fmt); 1.750 + 1.751 + if (str && ret) 1.752 + { 1.753 + len += OVR_strlen(ret)+OVR_strlen(str)+2+(fmt?2+depth:0); 1.754 + } 1.755 + else 1.756 + { 1.757 + fail = true; 1.758 + break; 1.759 + } 1.760 + 1.761 + child = Children.GetNext(child); 1.762 + } 1.763 + 1.764 + // Try to allocate the output string 1.765 + if (!fail) 1.766 + out=(char*)OVR_ALLOC(len); 1.767 + if (!out) 1.768 + fail=true; 1.769 + 1.770 + // Handle failure 1.771 + if (fail) 1.772 + { 1.773 + for (i=0;i<numentries;i++) 1.774 + { 1.775 + if (names[i]) 1.776 + OVR_FREE(names[i]); 1.777 + 1.778 + if (entries[i]) 1.779 + OVR_FREE(entries[i]);} 1.780 + 1.781 + OVR_FREE(names); 1.782 + OVR_FREE(entries); 1.783 + return 0; 1.784 + } 1.785 + 1.786 + // Compose the output: 1.787 + *out = '{'; 1.788 + ptr = out+1; 1.789 + if (fmt) 1.790 + *ptr++='\n'; 1.791 + *ptr = 0; 1.792 + 1.793 + for (i=0; i<numentries; i++) 1.794 + { 1.795 + if (fmt) 1.796 + { 1.797 + for (j=0; j<depth; j++) 1.798 + *ptr++ = '\t'; 1.799 + } 1.800 + OVR_strcpy(ptr, len - (ptr-out), names[i]); 1.801 + ptr += OVR_strlen(names[i]); 1.802 + *ptr++ =':'; 1.803 + 1.804 + if (fmt) 1.805 + *ptr++='\t'; 1.806 + 1.807 + OVR_strcpy(ptr, len - (ptr-out), entries[i]); 1.808 + ptr+=OVR_strlen(entries[i]); 1.809 + 1.810 + if (i!=numentries-1) 1.811 + *ptr++ = ','; 1.812 + 1.813 + if (fmt) 1.814 + *ptr++ = '\n'; 1.815 + *ptr = 0; 1.816 + 1.817 + OVR_FREE(names[i]); 1.818 + OVR_FREE(entries[i]); 1.819 + } 1.820 + 1.821 + OVR_FREE(names); 1.822 + OVR_FREE(entries); 1.823 + 1.824 + if (fmt) 1.825 + { 1.826 + for (i=0;i<depth-1;i++) 1.827 + *ptr++='\t'; 1.828 + } 1.829 + *ptr++='}'; 1.830 + *ptr++=0; 1.831 + 1.832 + return out; 1.833 +} 1.834 + 1.835 + 1.836 + 1.837 +// Returns the number of child items in the object 1.838 +// Counts the number of items in the object. 1.839 +unsigned JSON::GetItemCount() const 1.840 +{ 1.841 + unsigned count = 0; 1.842 + for(const JSON* p = Children.GetFirst(); !Children.IsNull(p); p = p->pNext) 1.843 + count++; 1.844 + return count; 1.845 +} 1.846 + 1.847 +JSON* JSON::GetItemByIndex(unsigned index) 1.848 +{ 1.849 + unsigned i = 0; 1.850 + JSON* child = 0; 1.851 + 1.852 + if (!Children.IsEmpty()) 1.853 + { 1.854 + child = Children.GetFirst(); 1.855 + 1.856 + while (i < index) 1.857 + { 1.858 + if (Children.IsNull(child->pNext)) 1.859 + { 1.860 + child = 0; 1.861 + break; 1.862 + } 1.863 + child = child->pNext; 1.864 + i++; 1.865 + } 1.866 + } 1.867 + 1.868 + return child; 1.869 +} 1.870 + 1.871 +// Returns the child item with the given name or NULL if not found 1.872 +JSON* JSON::GetItemByName(const char* name) 1.873 +{ 1.874 + JSON* child = 0; 1.875 + 1.876 + if (!Children.IsEmpty()) 1.877 + { 1.878 + child = Children.GetFirst(); 1.879 + 1.880 + while (OVR_strcmp(child->Name, name) != 0) 1.881 + { 1.882 + if (Children.IsNull(child->pNext)) 1.883 + { 1.884 + child = 0; 1.885 + break; 1.886 + } 1.887 + child = child->pNext; 1.888 + } 1.889 + } 1.890 + 1.891 + return child; 1.892 +} 1.893 + 1.894 +//----------------------------------------------------------------------------- 1.895 +// Adds a new item to the end of the child list 1.896 +void JSON::AddItem(const char *string, JSON *item) 1.897 +{ 1.898 + if (!item) 1.899 + return; 1.900 + 1.901 + item->Name = string; 1.902 + Children.PushBack(item); 1.903 +} 1.904 + 1.905 +/* 1.906 + 1.907 +// Removes and frees the items at the given index 1.908 +void JSON::DeleteItem(unsigned int index) 1.909 +{ 1.910 + unsigned int num_items = 0; 1.911 + JSON* child = Children.GetFirst(); 1.912 + while (!Children.IsNull(child) && num_items < index) 1.913 + { 1.914 + num_items++; 1.915 + child = Children.GetNext(child); 1.916 + } 1.917 + 1.918 + if (!Children.IsNull(child)) 1.919 + 1.920 + child->RemoveNode(); 1.921 + child->Release(); 1.922 + } 1.923 +} 1.924 + 1.925 +// Replaces and frees the item at the give index with the new item 1.926 +void JSON::ReplaceItem(unsigned int index, JSON* new_item) 1.927 +{ 1.928 + unsigned int num_items = 0; 1.929 + JSON* child = Children.GetFirst(); 1.930 + while (!Children.IsNull(child) && num_items < index) 1.931 + { 1.932 + num_items++; 1.933 + child = Children.GetNext(child); 1.934 + } 1.935 + 1.936 + if (!Children.IsNull(child)) 1.937 + { 1.938 + child->ReplaceNodeWith(new_item); 1.939 + child->Release(); 1.940 + } 1.941 +} 1.942 +*/ 1.943 + 1.944 +// Helper function to simplify creation of a typed object 1.945 +JSON* JSON::createHelper(JSONItemType itemType, double dval, const char* strVal) 1.946 +{ 1.947 + JSON *item = new JSON(itemType); 1.948 + if (item) 1.949 + { 1.950 + item->dValue = dval; 1.951 + if (strVal) 1.952 + item->Value = strVal; 1.953 + } 1.954 + return item; 1.955 +} 1.956 + 1.957 + 1.958 +//----------------------------------------------------------------------------- 1.959 +// Adds an element to an array object type 1.960 +void JSON::AddArrayElement(JSON *item) 1.961 +{ 1.962 + if (!item) 1.963 + return; 1.964 + 1.965 + Children.PushBack(item); 1.966 +} 1.967 + 1.968 + 1.969 +// Returns the size of an array 1.970 +int JSON::GetArraySize() 1.971 +{ 1.972 + if (Type == JSON_Array) 1.973 + return GetItemCount(); 1.974 + else 1.975 + return 0; 1.976 +} 1.977 + 1.978 +// Returns the number value an the give array index 1.979 +double JSON::GetArrayNumber(int index) 1.980 +{ 1.981 + if (Type == JSON_Array) 1.982 + { 1.983 + JSON* number = GetItemByIndex(index); 1.984 + return number ? number->dValue : 0.0; 1.985 + } 1.986 + else 1.987 + { 1.988 + return 0; 1.989 + } 1.990 +} 1.991 + 1.992 +// Returns the string value at the given array index 1.993 +const char* JSON::GetArrayString(int index) 1.994 +{ 1.995 + if (Type == JSON_Array) 1.996 + { 1.997 + JSON* number = GetItemByIndex(index); 1.998 + return number ? number->Value : 0; 1.999 + } 1.1000 + else 1.1001 + { 1.1002 + return 0; 1.1003 + } 1.1004 +} 1.1005 + 1.1006 +//----------------------------------------------------------------------------- 1.1007 +// Loads and parses the given JSON file pathname and returns a JSON object tree. 1.1008 +// The returned object must be Released after use. 1.1009 +JSON* JSON::Load(const char* path, const char** perror) 1.1010 +{ 1.1011 + SysFile f; 1.1012 + if (!f.Open(path, File::Open_Read, File::Mode_Read)) 1.1013 + { 1.1014 + AssignError(perror, "Failed to open file"); 1.1015 + return NULL; 1.1016 + } 1.1017 + 1.1018 + int len = f.GetLength(); 1.1019 + UByte* buff = (UByte*)OVR_ALLOC(len); 1.1020 + int bytes = f.Read(buff, len); 1.1021 + f.Close(); 1.1022 + 1.1023 + if (bytes == 0 || bytes != len) 1.1024 + { 1.1025 + OVR_FREE(buff); 1.1026 + return NULL; 1.1027 + } 1.1028 + 1.1029 + JSON* json = JSON::Parse((char*)buff, perror); 1.1030 + OVR_FREE(buff); 1.1031 + return json; 1.1032 +} 1.1033 + 1.1034 +//----------------------------------------------------------------------------- 1.1035 +// Serializes the JSON object and writes to the give file path 1.1036 +bool JSON::Save(const char* path) 1.1037 +{ 1.1038 + SysFile f; 1.1039 + if (!f.Open(path, File::Open_Write | File::Open_Create | File::Open_Truncate, File::Mode_Write)) 1.1040 + return false; 1.1041 + 1.1042 + char* text = PrintValue(0, true); 1.1043 + if (text) 1.1044 + { 1.1045 + SPInt len = OVR_strlen(text); 1.1046 + OVR_ASSERT(len < (SPInt)(int)len); 1.1047 + 1.1048 + int bytes = f.Write((UByte*)text, (int)len); 1.1049 + f.Close(); 1.1050 + OVR_FREE(text); 1.1051 + return (bytes == len); 1.1052 + } 1.1053 + else 1.1054 + { 1.1055 + return false; 1.1056 + } 1.1057 +} 1.1058 + 1.1059 +}