ovr_sdk

annotate 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
rev   line source
nuclear@0 1 /************************************************************************************
nuclear@0 2
nuclear@0 3 PublicHeader: None
nuclear@0 4 Filename : OVR_JSON.h
nuclear@0 5 Content : JSON format reader and writer
nuclear@0 6 Created : April 9, 2013
nuclear@0 7 Author : Brant Lewis
nuclear@0 8 Notes :
nuclear@0 9 The code is a derivative of the cJSON library written by Dave Gamble and subject
nuclear@0 10 to the following permissive copyright.
nuclear@0 11
nuclear@0 12 Copyright (c) 2009 Dave Gamble
nuclear@0 13
nuclear@0 14 Permission is hereby granted, free of charge, to any person obtaining a copy
nuclear@0 15 of this software and associated documentation files (the "Software"), to deal
nuclear@0 16 in the Software without restriction, including without limitation the rights
nuclear@0 17 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
nuclear@0 18 copies of the Software, and to permit persons to whom the Software is
nuclear@0 19 furnished to do so, subject to the following conditions:
nuclear@0 20
nuclear@0 21 The above copyright notice and this permission notice shall be included in
nuclear@0 22 all copies or substantial portions of the Software.
nuclear@0 23
nuclear@0 24 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
nuclear@0 25 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
nuclear@0 26 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
nuclear@0 27 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
nuclear@0 28 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
nuclear@0 29 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
nuclear@0 30 THE SOFTWARE.
nuclear@0 31
nuclear@0 32
nuclear@0 33 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
nuclear@0 34
nuclear@0 35 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
nuclear@0 36 you may not use the Oculus VR Rift SDK except in compliance with the License,
nuclear@0 37 which is provided at the time of installation or download, or which
nuclear@0 38 otherwise accompanies this software in either electronic or hard copy form.
nuclear@0 39
nuclear@0 40 You may obtain a copy of the License at
nuclear@0 41
nuclear@0 42 http://www.oculusvr.com/licenses/LICENSE-3.2
nuclear@0 43
nuclear@0 44 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
nuclear@0 45 distributed under the License is distributed on an "AS IS" BASIS,
nuclear@0 46 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
nuclear@0 47 See the License for the specific language governing permissions and
nuclear@0 48 limitations under the License.
nuclear@0 49
nuclear@0 50 ************************************************************************************/
nuclear@0 51
nuclear@0 52 #include <string.h>
nuclear@0 53 #include <stdio.h>
nuclear@0 54 #include <math.h>
nuclear@0 55 #include <stdlib.h>
nuclear@0 56 #include <float.h>
nuclear@0 57 #include <limits.h>
nuclear@0 58 #include <ctype.h>
nuclear@0 59 #include "OVR_JSON.h"
nuclear@0 60 #include "Kernel/OVR_SysFile.h"
nuclear@0 61 #include "Kernel/OVR_Log.h"
nuclear@0 62
nuclear@0 63 #ifdef OVR_OS_LINUX
nuclear@0 64 #include <locale.h>
nuclear@0 65 #endif
nuclear@0 66
nuclear@0 67 namespace OVR {
nuclear@0 68
nuclear@0 69
nuclear@0 70 //-----------------------------------------------------------------------------
nuclear@0 71 // Create a new copy of a string
nuclear@0 72 static char* JSON_strdup(const char* str)
nuclear@0 73 {
nuclear@0 74 size_t len = OVR_strlen(str) + 1;
nuclear@0 75 char* copy = (char*)OVR_ALLOC(len);
nuclear@0 76 if (!copy)
nuclear@0 77 return 0;
nuclear@0 78 memcpy(copy, str, len);
nuclear@0 79 return copy;
nuclear@0 80 }
nuclear@0 81
nuclear@0 82
nuclear@0 83 //-----------------------------------------------------------------------------
nuclear@0 84 // Render the number from the given item into a string.
nuclear@0 85 static char* PrintInt(int valueint)
nuclear@0 86 {
nuclear@0 87 char *str;
nuclear@0 88 str = (char*)OVR_ALLOC(21); // 2^64+1 can be represented in 21 chars.
nuclear@0 89 if (str)
nuclear@0 90 {
nuclear@0 91 OVR_sprintf(str, 21, "%d", valueint);
nuclear@0 92 }
nuclear@0 93 return str;
nuclear@0 94 }
nuclear@0 95
nuclear@0 96
nuclear@0 97 //-----------------------------------------------------------------------------
nuclear@0 98 // Render the number from the given item into a string.
nuclear@0 99 static char* PrintNumber(double d)
nuclear@0 100 {
nuclear@0 101 char *str;
nuclear@0 102 int valueint = (int)d;
nuclear@0 103 if (fabs(((double)valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
nuclear@0 104 {
nuclear@0 105 return PrintInt(valueint);
nuclear@0 106 }
nuclear@0 107 else
nuclear@0 108 {
nuclear@0 109 str=(char*)OVR_ALLOC(64); // This is a nice tradeoff.
nuclear@0 110 if (str)
nuclear@0 111 {
nuclear@0 112 if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)
nuclear@0 113 OVR_sprintf(str, 64, "%.0f", d);
nuclear@0 114 else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)
nuclear@0 115 OVR_sprintf(str, 64, "%e", d);
nuclear@0 116 else
nuclear@0 117 OVR_sprintf(str, 64, "%f", d);
nuclear@0 118 }
nuclear@0 119 }
nuclear@0 120 return str;
nuclear@0 121 }
nuclear@0 122
nuclear@0 123
nuclear@0 124 // Parse the input text into an un-escaped cstring, and populate item.
nuclear@0 125 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
nuclear@0 126
nuclear@0 127 // Helper to assign error sting and return 0.
nuclear@0 128 const char* AssignError(const char** perror, const char *errorMessage)
nuclear@0 129 {
nuclear@0 130 if (perror)
nuclear@0 131 *perror = errorMessage;
nuclear@0 132 return 0;
nuclear@0 133 }
nuclear@0 134
nuclear@0 135 //-----------------------------------------------------------------------------
nuclear@0 136 // ***** JSON Node class
nuclear@0 137
nuclear@0 138 JSON::JSON(JSONItemType itemType) :
nuclear@0 139 Type(itemType), dValue(0.)
nuclear@0 140 {
nuclear@0 141 }
nuclear@0 142
nuclear@0 143 JSON::~JSON()
nuclear@0 144 {
nuclear@0 145 JSON* child = Children.GetFirst();
nuclear@0 146 while (!Children.IsNull(child))
nuclear@0 147 {
nuclear@0 148 child->RemoveNode();
nuclear@0 149 child->Release();
nuclear@0 150 child = Children.GetFirst();
nuclear@0 151 }
nuclear@0 152 }
nuclear@0 153
nuclear@0 154 //-----------------------------------------------------------------------------
nuclear@0 155 // Parse the input text to generate a number, and populate the result into item
nuclear@0 156 // Returns the text position after the parsed number
nuclear@0 157 const char* JSON::parseNumber(const char *num)
nuclear@0 158 {
nuclear@0 159 const char* num_start = num;
nuclear@0 160 double n=0, scale=0;
nuclear@0 161 int subscale = 0,
nuclear@0 162 signsubscale = 1;
nuclear@0 163 bool positiveSign = true;
nuclear@0 164 char localeSeparator = '.';
nuclear@0 165
nuclear@0 166 #ifdef OVR_OS_LINUX
nuclear@0 167 // We should switch to a locale aware parsing function, such as atof. We
nuclear@0 168 // will probably want to go farther and enforce the 'C' locale on all JSON
nuclear@0 169 // output/input.
nuclear@0 170 struct lconv* localeConv = localeconv();
nuclear@0 171 localeSeparator = localeConv->decimal_point[0];
nuclear@0 172 #endif
nuclear@0 173
nuclear@0 174 // Could use sscanf for this?
nuclear@0 175 if (*num == '-')
nuclear@0 176 {
nuclear@0 177 positiveSign = false;
nuclear@0 178 num++; // Has sign?
nuclear@0 179 }
nuclear@0 180 if (*num == '0')
nuclear@0 181 {
nuclear@0 182 num++; // is zero
nuclear@0 183 }
nuclear@0 184
nuclear@0 185 if (*num>='1' && *num<='9')
nuclear@0 186 {
nuclear@0 187 do
nuclear@0 188 {
nuclear@0 189 n = (n*10.0) + (*num++ - '0');
nuclear@0 190 }
nuclear@0 191 while (*num>='0' && *num<='9'); // Number?
nuclear@0 192 }
nuclear@0 193
nuclear@0 194 if ((*num=='.' || *num==localeSeparator) && num[1]>='0' && num[1]<='9')
nuclear@0 195 {
nuclear@0 196 num++;
nuclear@0 197 do
nuclear@0 198 {
nuclear@0 199 n=(n*10.0)+(*num++ -'0');
nuclear@0 200 scale--;
nuclear@0 201 }
nuclear@0 202 while (*num>='0' && *num<='9'); // Fractional part?
nuclear@0 203 }
nuclear@0 204
nuclear@0 205 if (*num=='e' || *num=='E') // Exponent?
nuclear@0 206 {
nuclear@0 207 num++;
nuclear@0 208 if (*num == '+')
nuclear@0 209 {
nuclear@0 210 num++;
nuclear@0 211 }
nuclear@0 212 else if (*num=='-')
nuclear@0 213 {
nuclear@0 214 signsubscale=-1;
nuclear@0 215 num++; // With sign?
nuclear@0 216 }
nuclear@0 217
nuclear@0 218 while (*num >= '0' && *num <= '9')
nuclear@0 219 {
nuclear@0 220 subscale = (subscale * 10) + (*num++ - '0'); // Number?
nuclear@0 221 }
nuclear@0 222 }
nuclear@0 223
nuclear@0 224 // Number = +/- number.fraction * 10^+/- exponent
nuclear@0 225 n *= pow(10.0, (scale + subscale*signsubscale));
nuclear@0 226
nuclear@0 227 if (!positiveSign)
nuclear@0 228 {
nuclear@0 229 n = -n;
nuclear@0 230 }
nuclear@0 231
nuclear@0 232 // Assign parsed value.
nuclear@0 233 Type = JSON_Number;
nuclear@0 234 dValue = n;
nuclear@0 235 Value.AssignString(num_start, num - num_start);
nuclear@0 236
nuclear@0 237 return num;
nuclear@0 238 }
nuclear@0 239
nuclear@0 240 // Parses a hex string up to the specified number of digits.
nuclear@0 241 // Returns the first character after the string.
nuclear@0 242 const char* ParseHex(unsigned* val, unsigned digits, const char* str)
nuclear@0 243 {
nuclear@0 244 *val = 0;
nuclear@0 245
nuclear@0 246 for(unsigned digitCount = 0; digitCount < digits; digitCount++, str++)
nuclear@0 247 {
nuclear@0 248 unsigned v = *str;
nuclear@0 249
nuclear@0 250 if ((v >= '0') && (v <= '9'))
nuclear@0 251 v -= '0';
nuclear@0 252 else if ((v >= 'a') && (v <= 'f'))
nuclear@0 253 v = 10 + v - 'a';
nuclear@0 254 else if ((v >= 'A') && (v <= 'F'))
nuclear@0 255 v = 10 + v - 'A';
nuclear@0 256 else
nuclear@0 257 break;
nuclear@0 258
nuclear@0 259 *val = *val * 16 + v;
nuclear@0 260 }
nuclear@0 261
nuclear@0 262 return str;
nuclear@0 263 }
nuclear@0 264
nuclear@0 265 //-----------------------------------------------------------------------------
nuclear@0 266 // Parses the input text into a string item and returns the text position after
nuclear@0 267 // the parsed string
nuclear@0 268 const char* JSON::parseString(const char* str, const char** perror)
nuclear@0 269 {
nuclear@0 270 const char* ptr = str+1;
nuclear@0 271 const char* p;
nuclear@0 272 char* ptr2;
nuclear@0 273 char* out;
nuclear@0 274 int len=0;
nuclear@0 275 unsigned uc, uc2;
nuclear@0 276
nuclear@0 277 if (*str!='\"')
nuclear@0 278 {
nuclear@0 279 return AssignError(perror, "Syntax Error: Missing quote");
nuclear@0 280 }
nuclear@0 281
nuclear@0 282 while (*ptr!='\"' && *ptr && ++len)
nuclear@0 283 {
nuclear@0 284 if (*ptr++ == '\\') ptr++; // Skip escaped quotes.
nuclear@0 285 }
nuclear@0 286
nuclear@0 287 // This is how long we need for the string, roughly.
nuclear@0 288 out=(char*)OVR_ALLOC(len+1);
nuclear@0 289 if (!out)
nuclear@0 290 return 0;
nuclear@0 291
nuclear@0 292 ptr = str+1;
nuclear@0 293 ptr2= out;
nuclear@0 294
nuclear@0 295 while (*ptr!='\"' && *ptr)
nuclear@0 296 {
nuclear@0 297 if (*ptr!='\\')
nuclear@0 298 {
nuclear@0 299 *ptr2++ = *ptr++;
nuclear@0 300 }
nuclear@0 301 else
nuclear@0 302 {
nuclear@0 303 ptr++;
nuclear@0 304 switch (*ptr)
nuclear@0 305 {
nuclear@0 306 case 'b': *ptr2++ = '\b'; break;
nuclear@0 307 case 'f': *ptr2++ = '\f'; break;
nuclear@0 308 case 'n': *ptr2++ = '\n'; break;
nuclear@0 309 case 'r': *ptr2++ = '\r'; break;
nuclear@0 310 case 't': *ptr2++ = '\t'; break;
nuclear@0 311
nuclear@0 312 // Transcode utf16 to utf8.
nuclear@0 313 case 'u':
nuclear@0 314
nuclear@0 315 // Get the unicode char.
nuclear@0 316 p = ParseHex(&uc, 4, ptr + 1);
nuclear@0 317 if (ptr != p)
nuclear@0 318 ptr = p - 1;
nuclear@0 319
nuclear@0 320 if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)
nuclear@0 321 break; // Check for invalid.
nuclear@0 322
nuclear@0 323 // UTF16 surrogate pairs.
nuclear@0 324 if (uc>=0xD800 && uc<=0xDBFF)
nuclear@0 325 {
nuclear@0 326 if (ptr[1]!='\\' || ptr[2]!='u')
nuclear@0 327 break; // Missing second-half of surrogate.
nuclear@0 328
nuclear@0 329 p= ParseHex(&uc2, 4, ptr + 3);
nuclear@0 330 if (ptr != p)
nuclear@0 331 ptr = p - 1;
nuclear@0 332
nuclear@0 333 if (uc2<0xDC00 || uc2>0xDFFF)
nuclear@0 334 break; // Invalid second-half of surrogate.
nuclear@0 335
nuclear@0 336 uc = 0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
nuclear@0 337 }
nuclear@0 338
nuclear@0 339 len=4;
nuclear@0 340
nuclear@0 341 if (uc<0x80)
nuclear@0 342 len=1;
nuclear@0 343 else if (uc<0x800)
nuclear@0 344 len=2;
nuclear@0 345 else if (uc<0x10000)
nuclear@0 346 len=3;
nuclear@0 347
nuclear@0 348 ptr2+=len;
nuclear@0 349
nuclear@0 350 switch (len)
nuclear@0 351 {
nuclear@0 352 case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
nuclear@0 353 //no break, fall through
nuclear@0 354 case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
nuclear@0 355 //no break
nuclear@0 356 case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
nuclear@0 357 //no break
nuclear@0 358 case 1: *--ptr2 = (char)(uc | firstByteMark[len]);
nuclear@0 359 //no break
nuclear@0 360 }
nuclear@0 361 ptr2+=len;
nuclear@0 362 break;
nuclear@0 363
nuclear@0 364 default:
nuclear@0 365 *ptr2++ = *ptr;
nuclear@0 366 break;
nuclear@0 367 }
nuclear@0 368 ptr++;
nuclear@0 369 }
nuclear@0 370 }
nuclear@0 371
nuclear@0 372 *ptr2 = 0;
nuclear@0 373 if (*ptr=='\"')
nuclear@0 374 ptr++;
nuclear@0 375
nuclear@0 376 // Make a copy of the string
nuclear@0 377 Value=out;
nuclear@0 378 OVR_FREE(out);
nuclear@0 379 Type=JSON_String;
nuclear@0 380
nuclear@0 381 return ptr;
nuclear@0 382 }
nuclear@0 383
nuclear@0 384 //-----------------------------------------------------------------------------
nuclear@0 385 // Render the string provided to an escaped version that can be printed.
nuclear@0 386 char* PrintString(const char* str)
nuclear@0 387 {
nuclear@0 388 const char *ptr;
nuclear@0 389 char *ptr2,*out;
nuclear@0 390 int len=0;
nuclear@0 391 unsigned char token;
nuclear@0 392
nuclear@0 393 if (!str)
nuclear@0 394 return JSON_strdup("");
nuclear@0 395 ptr=str;
nuclear@0 396
nuclear@0 397 token=*ptr;
nuclear@0 398 while (token && ++len)\
nuclear@0 399 {
nuclear@0 400 if (strchr("\"\\\b\f\n\r\t",token))
nuclear@0 401 len++;
nuclear@0 402 else if (token<32)
nuclear@0 403 len+=5;
nuclear@0 404 ptr++;
nuclear@0 405 token=*ptr;
nuclear@0 406 }
nuclear@0 407
nuclear@0 408 int buff_size = len+3;
nuclear@0 409 out=(char*)OVR_ALLOC(buff_size);
nuclear@0 410 if (!out)
nuclear@0 411 return 0;
nuclear@0 412
nuclear@0 413 ptr2 = out;
nuclear@0 414 ptr = str;
nuclear@0 415 *ptr2++ = '\"';
nuclear@0 416
nuclear@0 417 while (*ptr)
nuclear@0 418 {
nuclear@0 419 if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\')
nuclear@0 420 *ptr2++=*ptr++;
nuclear@0 421 else
nuclear@0 422 {
nuclear@0 423 *ptr2++='\\';
nuclear@0 424 switch (token=*ptr++)
nuclear@0 425 {
nuclear@0 426 case '\\': *ptr2++='\\'; break;
nuclear@0 427 case '\"': *ptr2++='\"'; break;
nuclear@0 428 case '\b': *ptr2++='b'; break;
nuclear@0 429 case '\f': *ptr2++='f'; break;
nuclear@0 430 case '\n': *ptr2++='n'; break;
nuclear@0 431 case '\r': *ptr2++='r'; break;
nuclear@0 432 case '\t': *ptr2++='t'; break;
nuclear@0 433 default:
nuclear@0 434 OVR_sprintf(ptr2, buff_size - (ptr2-out), "u%04x",token);
nuclear@0 435 ptr2+=5;
nuclear@0 436 break; // Escape and print.
nuclear@0 437 }
nuclear@0 438 }
nuclear@0 439 }
nuclear@0 440 *ptr2++='\"';
nuclear@0 441 *ptr2++=0;
nuclear@0 442 return out;
nuclear@0 443 }
nuclear@0 444
nuclear@0 445 //-----------------------------------------------------------------------------
nuclear@0 446 // Utility to jump whitespace and cr/lf
nuclear@0 447 static const char* skip(const char* in)
nuclear@0 448 {
nuclear@0 449 while (in && *in && (unsigned char)*in<=' ')
nuclear@0 450 in++;
nuclear@0 451 return in;
nuclear@0 452 }
nuclear@0 453
nuclear@0 454 //-----------------------------------------------------------------------------
nuclear@0 455 // Parses the supplied buffer of JSON text and returns a JSON object tree
nuclear@0 456 // The returned object must be Released after use
nuclear@0 457 JSON* JSON::Parse(const char* buff, const char** perror)
nuclear@0 458 {
nuclear@0 459 const char* end = 0;
nuclear@0 460 JSON* json = new JSON();
nuclear@0 461
nuclear@0 462 if (!json)
nuclear@0 463 {
nuclear@0 464 AssignError(perror, "Error: Failed to allocate memory");
nuclear@0 465 return 0;
nuclear@0 466 }
nuclear@0 467
nuclear@0 468 end = json->parseValue(skip(buff), perror);
nuclear@0 469 if (!end)
nuclear@0 470 {
nuclear@0 471 json->Release();
nuclear@0 472 return NULL;
nuclear@0 473 } // parse failure. ep is set.
nuclear@0 474
nuclear@0 475 return json;
nuclear@0 476 }
nuclear@0 477
nuclear@0 478 //-----------------------------------------------------------------------------
nuclear@0 479 // This version works for buffers that are not null terminated strings.
nuclear@0 480 JSON* JSON::ParseBuffer(const char *buff, int len, const char** perror)
nuclear@0 481 {
nuclear@0 482 // Our JSON parser does not support length-based parsing,
nuclear@0 483 // so ensure it is null-terminated.
nuclear@0 484 char *termStr = new char[len + 1];
nuclear@0 485 memcpy(termStr, buff, len);
nuclear@0 486 termStr[len] = '\0';
nuclear@0 487
nuclear@0 488 JSON *objJson = Parse(termStr, perror);
nuclear@0 489
nuclear@0 490 delete[]termStr;
nuclear@0 491
nuclear@0 492 return objJson;
nuclear@0 493 }
nuclear@0 494
nuclear@0 495 //-----------------------------------------------------------------------------
nuclear@0 496 // Parser core - when encountering text, process appropriately.
nuclear@0 497 const char* JSON::parseValue(const char* buff, const char** perror)
nuclear@0 498 {
nuclear@0 499 if (perror)
nuclear@0 500 *perror = 0;
nuclear@0 501
nuclear@0 502 if (!buff)
nuclear@0 503 return NULL; // Fail on null.
nuclear@0 504
nuclear@0 505 if (!strncmp(buff,"null",4))
nuclear@0 506 {
nuclear@0 507 Type = JSON_Null;
nuclear@0 508 return buff+4;
nuclear@0 509 }
nuclear@0 510 if (!strncmp(buff,"false",5))
nuclear@0 511 {
nuclear@0 512 Type = JSON_Bool;
nuclear@0 513 Value = "false";
nuclear@0 514 dValue = 0.;
nuclear@0 515 return buff+5;
nuclear@0 516 }
nuclear@0 517 if (!strncmp(buff,"true",4))
nuclear@0 518 {
nuclear@0 519 Type = JSON_Bool;
nuclear@0 520 Value = "true";
nuclear@0 521 dValue = 1.;
nuclear@0 522 return buff + 4;
nuclear@0 523 }
nuclear@0 524 if (*buff=='\"')
nuclear@0 525 {
nuclear@0 526 return parseString(buff, perror);
nuclear@0 527 }
nuclear@0 528 if (*buff=='-' || (*buff>='0' && *buff<='9'))
nuclear@0 529 {
nuclear@0 530 return parseNumber(buff);
nuclear@0 531 }
nuclear@0 532 if (*buff=='[')
nuclear@0 533 {
nuclear@0 534 return parseArray(buff, perror);
nuclear@0 535 }
nuclear@0 536 if (*buff=='{')
nuclear@0 537 {
nuclear@0 538 return parseObject(buff, perror);
nuclear@0 539 }
nuclear@0 540
nuclear@0 541 return AssignError(perror, "Syntax Error: Invalid syntax");
nuclear@0 542 }
nuclear@0 543
nuclear@0 544
nuclear@0 545 //-----------------------------------------------------------------------------
nuclear@0 546 // Render a value to text.
nuclear@0 547 char* JSON::PrintValue(int depth, bool fmt)
nuclear@0 548 {
nuclear@0 549 char *out=0;
nuclear@0 550
nuclear@0 551 switch (Type)
nuclear@0 552 {
nuclear@0 553 case JSON_Null: out = JSON_strdup("null"); break;
nuclear@0 554 case JSON_Bool:
nuclear@0 555 if ((int)dValue == 0)
nuclear@0 556 out = JSON_strdup("false");
nuclear@0 557 else
nuclear@0 558 out = JSON_strdup("true");
nuclear@0 559 break;
nuclear@0 560 case JSON_Number: out = PrintNumber(dValue); break;
nuclear@0 561 case JSON_String: out = PrintString(Value); break;
nuclear@0 562 case JSON_Array: out = PrintArray(depth, fmt); break;
nuclear@0 563 case JSON_Object: out = PrintObject(depth, fmt); break;
nuclear@0 564 case JSON_None: OVR_ASSERT_LOG(false, ("Bad JSON type.")); break;
nuclear@0 565 }
nuclear@0 566 return out;
nuclear@0 567 }
nuclear@0 568
nuclear@0 569 //-----------------------------------------------------------------------------
nuclear@0 570 // Build an array object from input text and returns the text position after
nuclear@0 571 // the parsed array
nuclear@0 572 const char* JSON::parseArray(const char* buff, const char** perror)
nuclear@0 573 {
nuclear@0 574 JSON *child;
nuclear@0 575 if (*buff!='[')
nuclear@0 576 {
nuclear@0 577 return AssignError(perror, "Syntax Error: Missing opening bracket");
nuclear@0 578 }
nuclear@0 579
nuclear@0 580 Type=JSON_Array;
nuclear@0 581 buff=skip(buff+1);
nuclear@0 582
nuclear@0 583 if (*buff==']')
nuclear@0 584 return buff+1; // empty array.
nuclear@0 585
nuclear@0 586 child = new JSON();
nuclear@0 587 if (!child)
nuclear@0 588 return 0; // memory fail
nuclear@0 589 Children.PushBack(child);
nuclear@0 590
nuclear@0 591 buff=skip(child->parseValue(skip(buff), perror)); // skip any spacing, get the buff.
nuclear@0 592 if (!buff)
nuclear@0 593 return 0;
nuclear@0 594
nuclear@0 595 while (*buff==',')
nuclear@0 596 {
nuclear@0 597 JSON *new_item = new JSON();
nuclear@0 598 if (!new_item)
nuclear@0 599 return AssignError(perror, "Error: Failed to allocate memory");
nuclear@0 600
nuclear@0 601 Children.PushBack(new_item);
nuclear@0 602
nuclear@0 603 buff=skip(new_item->parseValue(skip(buff+1), perror));
nuclear@0 604 if (!buff)
nuclear@0 605 return AssignError(perror, "Error: Failed to allocate memory");
nuclear@0 606 }
nuclear@0 607
nuclear@0 608 if (*buff==']')
nuclear@0 609 return buff+1; // end of array
nuclear@0 610
nuclear@0 611 return AssignError(perror, "Syntax Error: Missing ending bracket");
nuclear@0 612 }
nuclear@0 613
nuclear@0 614 //-----------------------------------------------------------------------------
nuclear@0 615 // Render an array to text. The returned text must be freed
nuclear@0 616 char* JSON::PrintArray(int depth, bool fmt)
nuclear@0 617 {
nuclear@0 618 char ** entries;
nuclear@0 619 char * out = 0, *ptr,*ret;
nuclear@0 620 intptr_t len = 5;
nuclear@0 621
nuclear@0 622 bool fail = false;
nuclear@0 623
nuclear@0 624 // How many entries in the array?
nuclear@0 625 int numentries = GetItemCount();
nuclear@0 626 if (!numentries)
nuclear@0 627 {
nuclear@0 628 out=(char*)OVR_ALLOC(3);
nuclear@0 629 if (out)
nuclear@0 630 OVR_strcpy(out, 3, "[]");
nuclear@0 631 return out;
nuclear@0 632 }
nuclear@0 633 // Allocate an array to hold the values for each
nuclear@0 634 entries=(char**)OVR_ALLOC(numentries*sizeof(char*));
nuclear@0 635 if (!entries)
nuclear@0 636 return 0;
nuclear@0 637 memset(entries,0,numentries*sizeof(char*));
nuclear@0 638
nuclear@0 639 //// Retrieve all the results:
nuclear@0 640 JSON* child = Children.GetFirst();
nuclear@0 641 for (int i=0; i<numentries; i++)
nuclear@0 642 {
nuclear@0 643 //JSON* child = Children[i];
nuclear@0 644 ret=child->PrintValue(depth+1, fmt);
nuclear@0 645 entries[i]=ret;
nuclear@0 646 if (ret)
nuclear@0 647 len+=OVR_strlen(ret)+2+(fmt?1:0);
nuclear@0 648 else
nuclear@0 649 {
nuclear@0 650 fail = true;
nuclear@0 651 break;
nuclear@0 652 }
nuclear@0 653 child = Children.GetNext(child);
nuclear@0 654 }
nuclear@0 655
nuclear@0 656 // If we didn't fail, try to malloc the output string
nuclear@0 657 if (!fail)
nuclear@0 658 out=(char*)OVR_ALLOC(len);
nuclear@0 659 // If that fails, we fail.
nuclear@0 660 if (!out)
nuclear@0 661 fail = true;
nuclear@0 662
nuclear@0 663 // Handle failure.
nuclear@0 664 if (fail)
nuclear@0 665 {
nuclear@0 666 for (int i=0; i<numentries; i++)
nuclear@0 667 {
nuclear@0 668 if (entries[i])
nuclear@0 669 OVR_FREE(entries[i]);
nuclear@0 670 }
nuclear@0 671 OVR_FREE(entries);
nuclear@0 672 return 0;
nuclear@0 673 }
nuclear@0 674
nuclear@0 675 // Compose the output array.
nuclear@0 676 *out='[';
nuclear@0 677 ptr=out+1;
nuclear@0 678 *ptr=0;
nuclear@0 679 for (int i=0; i<numentries; i++)
nuclear@0 680 {
nuclear@0 681 OVR_strcpy(ptr, len - (ptr-out), entries[i]);
nuclear@0 682 ptr+=OVR_strlen(entries[i]);
nuclear@0 683 if (i!=numentries-1)
nuclear@0 684 {
nuclear@0 685 *ptr++=',';
nuclear@0 686 if (fmt)
nuclear@0 687 *ptr++=' ';
nuclear@0 688 *ptr=0;
nuclear@0 689 }
nuclear@0 690 OVR_FREE(entries[i]);
nuclear@0 691 }
nuclear@0 692 OVR_FREE(entries);
nuclear@0 693 *ptr++=']';
nuclear@0 694 *ptr++=0;
nuclear@0 695 return out;
nuclear@0 696 }
nuclear@0 697
nuclear@0 698 //-----------------------------------------------------------------------------
nuclear@0 699 // Build an object from the supplied text and returns the text position after
nuclear@0 700 // the parsed object
nuclear@0 701 const char* JSON::parseObject(const char* buff, const char** perror)
nuclear@0 702 {
nuclear@0 703 if (*buff!='{')
nuclear@0 704 {
nuclear@0 705 return AssignError(perror, "Syntax Error: Missing opening brace");
nuclear@0 706 }
nuclear@0 707
nuclear@0 708 Type=JSON_Object;
nuclear@0 709 buff=skip(buff+1);
nuclear@0 710 if (*buff=='}')
nuclear@0 711 return buff+1; // empty array.
nuclear@0 712
nuclear@0 713 JSON* child = new JSON();
nuclear@0 714 Children.PushBack(child);
nuclear@0 715
nuclear@0 716 buff=skip(child->parseString(skip(buff), perror));
nuclear@0 717 if (!buff)
nuclear@0 718 return 0;
nuclear@0 719 child->Name = child->Value;
nuclear@0 720 child->Value.Clear();
nuclear@0 721
nuclear@0 722 if (*buff!=':')
nuclear@0 723 {
nuclear@0 724 return AssignError(perror, "Syntax Error: Missing colon");
nuclear@0 725 }
nuclear@0 726
nuclear@0 727 buff=skip(child->parseValue(skip(buff+1), perror)); // skip any spacing, get the value.
nuclear@0 728 if (!buff)
nuclear@0 729 return 0;
nuclear@0 730
nuclear@0 731 while (*buff==',')
nuclear@0 732 {
nuclear@0 733 child = new JSON();
nuclear@0 734 if (!child)
nuclear@0 735 return 0; // memory fail
nuclear@0 736
nuclear@0 737 Children.PushBack(child);
nuclear@0 738
nuclear@0 739 buff=skip(child->parseString(skip(buff+1), perror));
nuclear@0 740 if (!buff)
nuclear@0 741 return 0;
nuclear@0 742
nuclear@0 743 child->Name=child->Value;
nuclear@0 744 child->Value.Clear();
nuclear@0 745
nuclear@0 746 if (*buff!=':')
nuclear@0 747 {
nuclear@0 748 return AssignError(perror, "Syntax Error: Missing colon");
nuclear@0 749 } // fail!
nuclear@0 750
nuclear@0 751 // Skip any spacing, get the value.
nuclear@0 752 buff=skip(child->parseValue(skip(buff+1), perror));
nuclear@0 753 if (!buff)
nuclear@0 754 return 0;
nuclear@0 755 }
nuclear@0 756
nuclear@0 757 if (*buff=='}')
nuclear@0 758 return buff+1; // end of array
nuclear@0 759
nuclear@0 760 return AssignError(perror, "Syntax Error: Missing closing brace");
nuclear@0 761 }
nuclear@0 762
nuclear@0 763 //-----------------------------------------------------------------------------
nuclear@0 764 // Render an object to text. The returned string must be freed
nuclear@0 765 char* JSON::PrintObject(int depth, bool fmt)
nuclear@0 766 {
nuclear@0 767 char** entries = 0, **names = 0;
nuclear@0 768 char* out = 0;
nuclear@0 769 char* ptr, *ret, *str;
nuclear@0 770 intptr_t len = 7, i = 0, j;
nuclear@0 771 bool fail = false;
nuclear@0 772
nuclear@0 773 // Count the number of entries.
nuclear@0 774 int numentries = GetItemCount();
nuclear@0 775
nuclear@0 776 // Explicitly handle empty object case
nuclear@0 777 if (numentries == 0)
nuclear@0 778 {
nuclear@0 779 out=(char*)OVR_ALLOC(fmt?depth+4:4);
nuclear@0 780 if (!out)
nuclear@0 781 return 0;
nuclear@0 782 ptr=out;
nuclear@0 783 *ptr++='{';
nuclear@0 784
nuclear@0 785 if (fmt)
nuclear@0 786 {
nuclear@0 787 *ptr++='\n';
nuclear@0 788 for (i=0;i<depth-1;i++)
nuclear@0 789 *ptr++='\t';
nuclear@0 790 }
nuclear@0 791 *ptr++='}';
nuclear@0 792 *ptr++=0;
nuclear@0 793 return out;
nuclear@0 794 }
nuclear@0 795 // Allocate space for the names and the objects
nuclear@0 796 entries=(char**)OVR_ALLOC(numentries*sizeof(char*));
nuclear@0 797 if (!entries)
nuclear@0 798 return 0;
nuclear@0 799 names=(char**)OVR_ALLOC(numentries*sizeof(char*));
nuclear@0 800
nuclear@0 801 if (!names)
nuclear@0 802 {
nuclear@0 803 OVR_FREE(entries);
nuclear@0 804 return 0;
nuclear@0 805 }
nuclear@0 806 memset(entries,0,sizeof(char*)*numentries);
nuclear@0 807 memset(names,0,sizeof(char*)*numentries);
nuclear@0 808
nuclear@0 809 // Collect all the results into our arrays:
nuclear@0 810 depth++;
nuclear@0 811 if (fmt)
nuclear@0 812 len+=depth;
nuclear@0 813
nuclear@0 814 JSON* child = Children.GetFirst();
nuclear@0 815 while (!Children.IsNull(child))
nuclear@0 816 {
nuclear@0 817 names[i] = str = PrintString(child->Name);
nuclear@0 818 entries[i++] = ret = child->PrintValue(depth, fmt);
nuclear@0 819
nuclear@0 820 if (str && ret)
nuclear@0 821 {
nuclear@0 822 len += OVR_strlen(ret)+OVR_strlen(str)+2+(fmt?3+depth:0);
nuclear@0 823 }
nuclear@0 824 else
nuclear@0 825 {
nuclear@0 826 fail = true;
nuclear@0 827 break;
nuclear@0 828 }
nuclear@0 829
nuclear@0 830 child = Children.GetNext(child);
nuclear@0 831 }
nuclear@0 832
nuclear@0 833 // Try to allocate the output string
nuclear@0 834 if (!fail)
nuclear@0 835 out=(char*)OVR_ALLOC(len);
nuclear@0 836 if (!out)
nuclear@0 837 fail=true;
nuclear@0 838
nuclear@0 839 // Handle failure
nuclear@0 840 if (fail)
nuclear@0 841 {
nuclear@0 842 for (i=0;i<numentries;i++)
nuclear@0 843 {
nuclear@0 844 if (names[i])
nuclear@0 845 OVR_FREE(names[i]);
nuclear@0 846
nuclear@0 847 if (entries[i])
nuclear@0 848 OVR_FREE(entries[i]);}
nuclear@0 849
nuclear@0 850 OVR_FREE(names);
nuclear@0 851 OVR_FREE(entries);
nuclear@0 852 return 0;
nuclear@0 853 }
nuclear@0 854
nuclear@0 855 // Compose the output:
nuclear@0 856 *out = '{';
nuclear@0 857 ptr = out+1;
nuclear@0 858 if (fmt)
nuclear@0 859 {
nuclear@0 860 #ifdef OVR_OS_WIN32
nuclear@0 861 *ptr++ = '\r';
nuclear@0 862 #endif
nuclear@0 863 *ptr++ = '\n';
nuclear@0 864 }
nuclear@0 865 *ptr = 0;
nuclear@0 866
nuclear@0 867 for (i=0; i<numentries; i++)
nuclear@0 868 {
nuclear@0 869 if (fmt)
nuclear@0 870 {
nuclear@0 871 for (j = 0; j < depth; j++)
nuclear@0 872 {
nuclear@0 873 *ptr++ = '\t';
nuclear@0 874 }
nuclear@0 875 }
nuclear@0 876 OVR_strcpy(ptr, len - (ptr-out), names[i]);
nuclear@0 877 ptr += OVR_strlen(names[i]);
nuclear@0 878 *ptr++ =':';
nuclear@0 879
nuclear@0 880 if (fmt)
nuclear@0 881 {
nuclear@0 882 *ptr++ = '\t';
nuclear@0 883 }
nuclear@0 884
nuclear@0 885 OVR_strcpy(ptr, len - (ptr-out), entries[i]);
nuclear@0 886 ptr+=OVR_strlen(entries[i]);
nuclear@0 887
nuclear@0 888 if (i != numentries - 1)
nuclear@0 889 {
nuclear@0 890 *ptr++ = ',';
nuclear@0 891 }
nuclear@0 892
nuclear@0 893 if (fmt)
nuclear@0 894 {
nuclear@0 895 #ifdef OVR_OS_WIN32
nuclear@0 896 *ptr++ = '\r';
nuclear@0 897 #endif
nuclear@0 898 *ptr++ = '\n';
nuclear@0 899 }
nuclear@0 900 *ptr = 0;
nuclear@0 901
nuclear@0 902 OVR_FREE(names[i]);
nuclear@0 903 OVR_FREE(entries[i]);
nuclear@0 904 }
nuclear@0 905
nuclear@0 906 OVR_FREE(names);
nuclear@0 907 OVR_FREE(entries);
nuclear@0 908
nuclear@0 909 if (fmt)
nuclear@0 910 {
nuclear@0 911 for (i = 0; i < depth - 1; i++)
nuclear@0 912 {
nuclear@0 913 *ptr++ = '\t';
nuclear@0 914 }
nuclear@0 915 }
nuclear@0 916 *ptr++='}';
nuclear@0 917 *ptr++=0;
nuclear@0 918
nuclear@0 919 return out;
nuclear@0 920 }
nuclear@0 921
nuclear@0 922
nuclear@0 923
nuclear@0 924 // Returns the number of child items in the object
nuclear@0 925 // Counts the number of items in the object.
nuclear@0 926 unsigned JSON::GetItemCount() const
nuclear@0 927 {
nuclear@0 928 unsigned count = 0;
nuclear@0 929 for (const JSON* p = Children.GetFirst(); !Children.IsNull(p); p = p->pNext)
nuclear@0 930 {
nuclear@0 931 count++;
nuclear@0 932 }
nuclear@0 933 return count;
nuclear@0 934 }
nuclear@0 935
nuclear@0 936 JSON* JSON::GetItemByIndex(unsigned index)
nuclear@0 937 {
nuclear@0 938 unsigned i = 0;
nuclear@0 939 JSON* child = 0;
nuclear@0 940
nuclear@0 941 if (!Children.IsEmpty())
nuclear@0 942 {
nuclear@0 943 child = Children.GetFirst();
nuclear@0 944
nuclear@0 945 while (i < index)
nuclear@0 946 {
nuclear@0 947 if (Children.IsNull(child->pNext))
nuclear@0 948 {
nuclear@0 949 child = 0;
nuclear@0 950 break;
nuclear@0 951 }
nuclear@0 952 child = child->pNext;
nuclear@0 953 i++;
nuclear@0 954 }
nuclear@0 955 }
nuclear@0 956
nuclear@0 957 return child;
nuclear@0 958 }
nuclear@0 959
nuclear@0 960 // Returns the child item with the given name or NULL if not found
nuclear@0 961 JSON* JSON::GetItemByName(const char* name)
nuclear@0 962 {
nuclear@0 963 JSON* child = 0;
nuclear@0 964
nuclear@0 965 if (!Children.IsEmpty())
nuclear@0 966 {
nuclear@0 967 child = Children.GetFirst();
nuclear@0 968
nuclear@0 969 while (OVR_strcmp(child->Name, name) != 0)
nuclear@0 970 {
nuclear@0 971 if (Children.IsNull(child->pNext))
nuclear@0 972 {
nuclear@0 973 child = 0;
nuclear@0 974 break;
nuclear@0 975 }
nuclear@0 976 child = child->pNext;
nuclear@0 977 }
nuclear@0 978 }
nuclear@0 979
nuclear@0 980 return child;
nuclear@0 981 }
nuclear@0 982
nuclear@0 983 //-----------------------------------------------------------------------------
nuclear@0 984 // Adds a new item to the end of the child list
nuclear@0 985 void JSON::AddItem(const char *string, JSON *item)
nuclear@0 986 {
nuclear@0 987 if (item)
nuclear@0 988 {
nuclear@0 989 item->Name = string;
nuclear@0 990 Children.PushBack(item);
nuclear@0 991 }
nuclear@0 992 }
nuclear@0 993
nuclear@0 994 /*
nuclear@0 995
nuclear@0 996 // Removes and frees the items at the given index
nuclear@0 997 void JSON::DeleteItem(unsigned int index)
nuclear@0 998 {
nuclear@0 999 unsigned int num_items = 0;
nuclear@0 1000 JSON* child = Children.GetFirst();
nuclear@0 1001 while (!Children.IsNull(child) && num_items < index)
nuclear@0 1002 {
nuclear@0 1003 num_items++;
nuclear@0 1004 child = Children.GetNext(child);
nuclear@0 1005 }
nuclear@0 1006
nuclear@0 1007 if (!Children.IsNull(child))
nuclear@0 1008
nuclear@0 1009 child->RemoveNode();
nuclear@0 1010 child->Release();
nuclear@0 1011 }
nuclear@0 1012 }
nuclear@0 1013
nuclear@0 1014 // Replaces and frees the item at the give index with the new item
nuclear@0 1015 void JSON::ReplaceItem(unsigned int index, JSON* new_item)
nuclear@0 1016 {
nuclear@0 1017 unsigned int num_items = 0;
nuclear@0 1018 JSON* child = Children.GetFirst();
nuclear@0 1019 while (!Children.IsNull(child) && num_items < index)
nuclear@0 1020 {
nuclear@0 1021 num_items++;
nuclear@0 1022 child = Children.GetNext(child);
nuclear@0 1023 }
nuclear@0 1024
nuclear@0 1025 if (!Children.IsNull(child))
nuclear@0 1026 {
nuclear@0 1027 child->ReplaceNodeWith(new_item);
nuclear@0 1028 child->Release();
nuclear@0 1029 }
nuclear@0 1030 }
nuclear@0 1031 */
nuclear@0 1032
nuclear@0 1033 // Removes and frees the last child item
nuclear@0 1034 void JSON::RemoveLast()
nuclear@0 1035 {
nuclear@0 1036 JSON* child = Children.GetLast();
nuclear@0 1037 if (!Children.IsNull(child))
nuclear@0 1038 {
nuclear@0 1039 child->RemoveNode();
nuclear@0 1040 child->Release();
nuclear@0 1041 }
nuclear@0 1042 }
nuclear@0 1043
nuclear@0 1044 JSON* JSON::CreateBool(bool b)
nuclear@0 1045 {
nuclear@0 1046 JSON *item = new JSON(JSON_Bool);
nuclear@0 1047 if (item)
nuclear@0 1048 {
nuclear@0 1049 item->dValue = b ? 1. : 0.;
nuclear@0 1050 item->Value = b ? "true" : "false";
nuclear@0 1051 }
nuclear@0 1052 return item;
nuclear@0 1053 }
nuclear@0 1054
nuclear@0 1055 JSON* JSON::CreateNumber(double num)
nuclear@0 1056 {
nuclear@0 1057 JSON *item = new JSON(JSON_Number);
nuclear@0 1058 if (item)
nuclear@0 1059 {
nuclear@0 1060 item->dValue = num;
nuclear@0 1061 }
nuclear@0 1062 return item;
nuclear@0 1063 }
nuclear@0 1064
nuclear@0 1065 JSON* JSON::CreateInt(int num)
nuclear@0 1066 {
nuclear@0 1067 JSON *item = new JSON(JSON_Number);
nuclear@0 1068 if (item)
nuclear@0 1069 {
nuclear@0 1070 item->dValue = num;
nuclear@0 1071 }
nuclear@0 1072 return item;
nuclear@0 1073 }
nuclear@0 1074
nuclear@0 1075 JSON* JSON::CreateString(const char *s)
nuclear@0 1076 {
nuclear@0 1077 JSON *item = new JSON(JSON_String);
nuclear@0 1078 if (item && s)
nuclear@0 1079 {
nuclear@0 1080 item->Value = s;
nuclear@0 1081 }
nuclear@0 1082 return item;
nuclear@0 1083 }
nuclear@0 1084
nuclear@0 1085
nuclear@0 1086 //-----------------------------------------------------------------------------
nuclear@0 1087 // Get elements by name
nuclear@0 1088 double JSON::GetNumberByName(const char *name, double defValue)
nuclear@0 1089 {
nuclear@0 1090 JSON* item = GetItemByName(name);
nuclear@0 1091 if (!item || item->Type != JSON_Number)
nuclear@0 1092 {
nuclear@0 1093 return defValue;
nuclear@0 1094 }
nuclear@0 1095 else
nuclear@0 1096 {
nuclear@0 1097 return item->dValue;
nuclear@0 1098 }
nuclear@0 1099 }
nuclear@0 1100
nuclear@0 1101 int JSON::GetIntByName(const char *name, int defValue)
nuclear@0 1102 {
nuclear@0 1103 JSON* item = GetItemByName(name);
nuclear@0 1104 if (!item || item->Type != JSON_Number)
nuclear@0 1105 {
nuclear@0 1106 return defValue;
nuclear@0 1107 }
nuclear@0 1108 else
nuclear@0 1109 {
nuclear@0 1110 return (int)item->dValue;
nuclear@0 1111 }
nuclear@0 1112 }
nuclear@0 1113
nuclear@0 1114 bool JSON::GetBoolByName(const char *name, bool defValue)
nuclear@0 1115 {
nuclear@0 1116 JSON* item = GetItemByName(name);
nuclear@0 1117 if (!item || item->Type != JSON_Bool)
nuclear@0 1118 {
nuclear@0 1119 return defValue;
nuclear@0 1120 }
nuclear@0 1121 else
nuclear@0 1122 {
nuclear@0 1123 return (int)item->dValue != 0;
nuclear@0 1124 }
nuclear@0 1125 }
nuclear@0 1126
nuclear@0 1127 String JSON::GetStringByName(const char *name, const String &defValue)
nuclear@0 1128 {
nuclear@0 1129 JSON* item = GetItemByName(name);
nuclear@0 1130 if (!item || item->Type != JSON_String)
nuclear@0 1131 {
nuclear@0 1132 return defValue;
nuclear@0 1133 }
nuclear@0 1134 else
nuclear@0 1135 {
nuclear@0 1136 return item->Value;
nuclear@0 1137 }
nuclear@0 1138 }
nuclear@0 1139
nuclear@0 1140 //-----------------------------------------------------------------------------
nuclear@0 1141 // Adds an element to an array object type
nuclear@0 1142 void JSON::AddArrayElement(JSON *item)
nuclear@0 1143 {
nuclear@0 1144 if (item)
nuclear@0 1145 {
nuclear@0 1146 Children.PushBack(item);
nuclear@0 1147 }
nuclear@0 1148 }
nuclear@0 1149
nuclear@0 1150 // Inserts an element into a valid array position
nuclear@0 1151 void JSON::InsertArrayElement(int index, JSON *item)
nuclear@0 1152 {
nuclear@0 1153 if (!item)
nuclear@0 1154 {
nuclear@0 1155 return;
nuclear@0 1156 }
nuclear@0 1157
nuclear@0 1158 if (index == 0)
nuclear@0 1159 {
nuclear@0 1160 Children.PushFront(item);
nuclear@0 1161 return;
nuclear@0 1162 }
nuclear@0 1163
nuclear@0 1164 JSON* iter = Children.GetFirst();
nuclear@0 1165 int i=0;
nuclear@0 1166 while (iter && i<index)
nuclear@0 1167 {
nuclear@0 1168 iter = Children.GetNext(iter);
nuclear@0 1169 i++;
nuclear@0 1170 }
nuclear@0 1171
nuclear@0 1172 if (iter)
nuclear@0 1173 iter->InsertNodeBefore(item);
nuclear@0 1174 else
nuclear@0 1175 Children.PushBack(item);
nuclear@0 1176 }
nuclear@0 1177
nuclear@0 1178 // Returns the size of an array
nuclear@0 1179 int JSON::GetArraySize()
nuclear@0 1180 {
nuclear@0 1181 if (Type == JSON_Array)
nuclear@0 1182 {
nuclear@0 1183 return GetItemCount();
nuclear@0 1184 }
nuclear@0 1185
nuclear@0 1186 return 0;
nuclear@0 1187 }
nuclear@0 1188
nuclear@0 1189 // Returns the number value an the give array index
nuclear@0 1190 double JSON::GetArrayNumber(int index)
nuclear@0 1191 {
nuclear@0 1192 if (Type == JSON_Array)
nuclear@0 1193 {
nuclear@0 1194 JSON* number = GetItemByIndex(index);
nuclear@0 1195 return number ? number->dValue : 0.0;
nuclear@0 1196 }
nuclear@0 1197
nuclear@0 1198 return 0;
nuclear@0 1199 }
nuclear@0 1200
nuclear@0 1201 // Returns the string value at the given array index
nuclear@0 1202 const char* JSON::GetArrayString(int index)
nuclear@0 1203 {
nuclear@0 1204 if (Type == JSON_Array)
nuclear@0 1205 {
nuclear@0 1206 JSON* number = GetItemByIndex(index);
nuclear@0 1207 return number ? number->Value : 0;
nuclear@0 1208 }
nuclear@0 1209
nuclear@0 1210 return 0;
nuclear@0 1211 }
nuclear@0 1212
nuclear@0 1213 JSON* JSON::Copy()
nuclear@0 1214 {
nuclear@0 1215 JSON* copy = new JSON(Type);
nuclear@0 1216 copy->Name = Name;
nuclear@0 1217 copy->Value = Value;
nuclear@0 1218 copy->dValue = dValue;
nuclear@0 1219
nuclear@0 1220 JSON* child = Children.GetFirst();
nuclear@0 1221 while (!Children.IsNull(child))
nuclear@0 1222 {
nuclear@0 1223 copy->Children.PushBack(child->Copy());
nuclear@0 1224 child = Children.GetNext(child);
nuclear@0 1225 }
nuclear@0 1226
nuclear@0 1227 return copy;
nuclear@0 1228 }
nuclear@0 1229
nuclear@0 1230 //-----------------------------------------------------------------------------
nuclear@0 1231 // Loads and parses the given JSON file pathname and returns a JSON object tree.
nuclear@0 1232 // The returned object must be Released after use.
nuclear@0 1233 JSON* JSON::Load(const char* path, const char** perror)
nuclear@0 1234 {
nuclear@0 1235 SysFile f;
nuclear@0 1236 if (!f.Open(path, File::Open_Read, File::Mode_Read))
nuclear@0 1237 {
nuclear@0 1238 AssignError(perror, "Failed to open file");
nuclear@0 1239 return NULL;
nuclear@0 1240 }
nuclear@0 1241
nuclear@0 1242 int len = f.GetLength();
nuclear@0 1243 uint8_t* buff = (uint8_t*)OVR_ALLOC(len + 1);
nuclear@0 1244 int bytes = f.Read(buff, len);
nuclear@0 1245 f.Close();
nuclear@0 1246
nuclear@0 1247 if (bytes == 0 || bytes != len)
nuclear@0 1248 {
nuclear@0 1249 OVR_FREE(buff);
nuclear@0 1250 return NULL;
nuclear@0 1251 }
nuclear@0 1252
nuclear@0 1253 // Ensure the result is null-terminated since Parse() expects null-terminated input.
nuclear@0 1254 buff[len] = '\0';
nuclear@0 1255
nuclear@0 1256 JSON* json = JSON::Parse((char*)buff, perror);
nuclear@0 1257 OVR_FREE(buff);
nuclear@0 1258 return json;
nuclear@0 1259 }
nuclear@0 1260
nuclear@0 1261 //-----------------------------------------------------------------------------
nuclear@0 1262 // Serializes the JSON object and writes to the give file path
nuclear@0 1263 bool JSON::Save(const char* path)
nuclear@0 1264 {
nuclear@0 1265 SysFile f;
nuclear@0 1266 if (!f.Open(path, File::Open_Write | File::Open_Create | File::Open_Truncate, File::Mode_Write))
nuclear@0 1267 return false;
nuclear@0 1268
nuclear@0 1269 char* text = PrintValue(0, true);
nuclear@0 1270 if (text)
nuclear@0 1271 {
nuclear@0 1272 intptr_t len = OVR_strlen(text);
nuclear@0 1273 OVR_ASSERT(len <= (intptr_t)(int)len);
nuclear@0 1274
nuclear@0 1275 int bytes = f.Write((uint8_t*)text, (int)len);
nuclear@0 1276 f.Close();
nuclear@0 1277 OVR_FREE(text);
nuclear@0 1278 return (bytes == len);
nuclear@0 1279 }
nuclear@0 1280 else
nuclear@0 1281 {
nuclear@0 1282 return false;
nuclear@0 1283 }
nuclear@0 1284 }
nuclear@0 1285
nuclear@0 1286
nuclear@0 1287 } // namespace OVR