oculus1

view libovr/Src/OVR_JSON.cpp @ 17:cfe4979ab3eb

ops, minor error in the last commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 21 Sep 2013 07:09:48 +0300
parents
children
line source
1 /************************************************************************************
3 PublicHeader: None
4 Filename : OVR_JSON.h
5 Content : JSON format reader and writer
6 Created : April 9, 2013
7 Author : Brant Lewis
8 Notes :
9 The code is a derivative of the cJSON library written by Dave Gamble and subject
10 to the following permissive copyright.
12 Copyright (c) 2009 Dave Gamble
14 Permission is hereby granted, free of charge, to any person obtaining a copy
15 of this software and associated documentation files (the "Software"), to deal
16 in the Software without restriction, including without limitation the rights
17 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18 copies of the Software, and to permit persons to whom the Software is
19 furnished to do so, subject to the following conditions:
21 The above copyright notice and this permission notice shall be included in
22 all copies or substantial portions of the Software.
24 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30 THE SOFTWARE.
33 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
35 Use of this software is subject to the terms of the Oculus license
36 agreement provided at the time of installation or download, or which
37 otherwise accompanies this software in either electronic or hard copy form.
39 ************************************************************************************/
41 #include <string.h>
42 #include <stdio.h>
43 #include <math.h>
44 #include <stdlib.h>
45 #include <float.h>
46 #include <limits.h>
47 #include <ctype.h>
48 #include "OVR_JSON.h"
49 #include "Kernel/OVR_SysFile.h"
50 #include "Kernel/OVR_Log.h"
52 namespace OVR {
55 //-----------------------------------------------------------------------------
56 // Create a new copy of a string
57 static char* JSON_strdup(const char* str)
58 {
59 UPInt len = OVR_strlen(str) + 1;
60 char* copy = (char*)OVR_ALLOC(len);
61 if (!copy)
62 return 0;
63 memcpy(copy, str, len);
64 return copy;
65 }
68 //-----------------------------------------------------------------------------
69 // Render the number from the given item into a string.
70 static char* PrintNumber(double d)
71 {
72 char *str;
73 //double d=item->valuedouble;
74 int valueint = (int)d;
75 if (fabs(((double)valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
76 {
77 str=(char*)OVR_ALLOC(21); // 2^64+1 can be represented in 21 chars.
78 if (str)
79 OVR_sprintf(str, 21, "%d", valueint);
80 }
81 else
82 {
83 str=(char*)OVR_ALLOC(64); // This is a nice tradeoff.
84 if (str)
85 {
86 if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)
87 OVR_sprintf(str, 64, "%.0f", d);
88 else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)
89 OVR_sprintf(str, 64, "%e", d);
90 else
91 OVR_sprintf(str, 64, "%f", d);
92 }
93 }
94 return str;
95 }
97 // Parse the input text into an un-escaped cstring, and populate item.
98 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
100 // Helper to assign error sting and return 0.
101 const char* AssignError(const char** perror, const char *errorMessage)
102 {
103 if (perror)
104 *perror = errorMessage;
105 return 0;
106 }
108 //-----------------------------------------------------------------------------
109 // ***** JSON Node class
111 JSON::JSON(JSONItemType itemType)
112 : Type(itemType), dValue(0.0)
113 {
114 }
116 JSON::~JSON()
117 {
118 JSON* child = Children.GetFirst();
119 while (!Children.IsNull(child))
120 {
121 child->RemoveNode();
122 child->Release();
123 child = Children.GetFirst();
124 }
125 }
127 //-----------------------------------------------------------------------------
128 // Parse the input text to generate a number, and populate the result into item
129 // Returns the text position after the parsed number
130 const char* JSON::parseNumber(const char *num)
131 {
132 const char* num_start = num;
133 double n=0, sign=1, scale=0;
134 int subscale = 0,
135 signsubscale = 1;
137 // Could use sscanf for this?
138 if (*num=='-')
139 sign=-1,num++; // Has sign?
140 if (*num=='0')
141 num++; // is zero
143 if (*num>='1' && *num<='9')
144 {
145 do
146 {
147 n=(n*10.0)+(*num++ -'0');
148 }
149 while (*num>='0' && *num<='9'); // Number?
150 }
152 if (*num=='.' && num[1]>='0' && num[1]<='9')
153 {
154 num++;
155 do
156 {
157 n=(n*10.0)+(*num++ -'0');
158 scale--;
159 }
160 while (*num>='0' && *num<='9'); // Fractional part?
161 }
163 if (*num=='e' || *num=='E') // Exponent?
164 {
165 num++;
166 if (*num=='+')
167 num++;
168 else if (*num=='-')
169 {
170 signsubscale=-1;
171 num++; // With sign?
172 }
174 while (*num>='0' && *num<='9')
175 subscale=(subscale*10)+(*num++ - '0'); // Number?
176 }
178 // Number = +/- number.fraction * 10^+/- exponent
179 n = sign*n*pow(10.0,(scale+subscale*signsubscale));
181 // Assign parsed value.
182 Type = JSON_Number;
183 dValue = n;
184 Value.AssignString(num_start, num - num_start);
186 return num;
187 }
189 // Parses a hex string up to the specified number of digits.
190 // Returns the first character after the string.
191 const char* ParseHex(unsigned* val, unsigned digits, const char* str)
192 {
193 *val = 0;
195 for(unsigned digitCount = 0; digitCount < digits; digitCount++, str++)
196 {
197 unsigned v = *str;
199 if ((v >= '0') && (v <= '9'))
200 v -= '0';
201 else if ((v >= 'a') && (v <= 'f'))
202 v = 10 + v - 'a';
203 else if ((v >= 'A') && (v <= 'F'))
204 v = 10 + v - 'A';
205 else
206 break;
208 *val = *val * 16 + v;
209 }
211 return str;
212 }
214 //-----------------------------------------------------------------------------
215 // Parses the input text into a string item and returns the text position after
216 // the parsed string
217 const char* JSON::parseString(const char* str, const char** perror)
218 {
219 const char* ptr = str+1;
220 const char* p;
221 char* ptr2;
222 char* out;
223 int len=0;
224 unsigned uc, uc2;
226 if (*str!='\"')
227 {
228 return AssignError(perror, "Syntax Error: Missing quote");
229 }
231 while (*ptr!='\"' && *ptr && ++len)
232 {
233 if (*ptr++ == '\\') ptr++; // Skip escaped quotes.
234 }
236 // This is how long we need for the string, roughly.
237 out=(char*)OVR_ALLOC(len+1);
238 if (!out)
239 return 0;
241 ptr = str+1;
242 ptr2= out;
244 while (*ptr!='\"' && *ptr)
245 {
246 if (*ptr!='\\')
247 {
248 *ptr2++ = *ptr++;
249 }
250 else
251 {
252 ptr++;
253 switch (*ptr)
254 {
255 case 'b': *ptr2++ = '\b'; break;
256 case 'f': *ptr2++ = '\f'; break;
257 case 'n': *ptr2++ = '\n'; break;
258 case 'r': *ptr2++ = '\r'; break;
259 case 't': *ptr2++ = '\t'; break;
261 // Transcode utf16 to utf8.
262 case 'u':
264 // Get the unicode char.
265 p = ParseHex(&uc, 4, ptr + 1);
266 if (ptr != p)
267 ptr = p - 1;
269 if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)
270 break; // Check for invalid.
272 // UTF16 surrogate pairs.
273 if (uc>=0xD800 && uc<=0xDBFF)
274 {
275 if (ptr[1]!='\\' || ptr[2]!='u')
276 break; // Missing second-half of surrogate.
278 p= ParseHex(&uc2, 4, ptr + 3);
279 if (ptr != p)
280 ptr = p - 1;
282 if (uc2<0xDC00 || uc2>0xDFFF)
283 break; // Invalid second-half of surrogate.
285 uc = 0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
286 }
288 len=4;
290 if (uc<0x80)
291 len=1;
292 else if (uc<0x800)
293 len=2;
294 else if (uc<0x10000)
295 len=3;
297 ptr2+=len;
299 switch (len)
300 {
301 case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
302 case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
303 case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
304 case 1: *--ptr2 = (char)(uc | firstByteMark[len]);
305 }
306 ptr2+=len;
307 break;
309 default:
310 *ptr2++ = *ptr;
311 break;
312 }
313 ptr++;
314 }
315 }
317 *ptr2 = 0;
318 if (*ptr=='\"')
319 ptr++;
321 // Make a copy of the string
322 Value=out;
323 OVR_FREE(out);
324 Type=JSON_String;
326 return ptr;
327 }
329 //-----------------------------------------------------------------------------
330 // Render the string provided to an escaped version that can be printed.
331 char* PrintString(const char* str)
332 {
333 const char *ptr;
334 char *ptr2,*out;
335 int len=0;
336 unsigned char token;
338 if (!str)
339 return JSON_strdup("");
340 ptr=str;
342 token=*ptr;
343 while (token && ++len)\
344 {
345 if (strchr("\"\\\b\f\n\r\t",token))
346 len++;
347 else if (token<32)
348 len+=5;
349 ptr++;
350 token=*ptr;
351 }
353 int buff_size = len+3;
354 out=(char*)OVR_ALLOC(buff_size);
355 if (!out)
356 return 0;
358 ptr2 = out;
359 ptr = str;
360 *ptr2++ = '\"';
362 while (*ptr)
363 {
364 if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\')
365 *ptr2++=*ptr++;
366 else
367 {
368 *ptr2++='\\';
369 switch (token=*ptr++)
370 {
371 case '\\': *ptr2++='\\'; break;
372 case '\"': *ptr2++='\"'; break;
373 case '\b': *ptr2++='b'; break;
374 case '\f': *ptr2++='f'; break;
375 case '\n': *ptr2++='n'; break;
376 case '\r': *ptr2++='r'; break;
377 case '\t': *ptr2++='t'; break;
378 default:
379 OVR_sprintf(ptr2, buff_size - (ptr2-out), "u%04x",token);
380 ptr2+=5;
381 break; // Escape and print.
382 }
383 }
384 }
385 *ptr2++='\"';
386 *ptr2++=0;
387 return out;
388 }
390 //-----------------------------------------------------------------------------
391 // Utility to jump whitespace and cr/lf
392 static const char* skip(const char* in)
393 {
394 while (in && *in && (unsigned char)*in<=' ')
395 in++;
396 return in;
397 }
399 //-----------------------------------------------------------------------------
400 // Parses the supplied buffer of JSON text and returns a JSON object tree
401 // The returned object must be Released after use
402 JSON* JSON::Parse(const char* buff, const char** perror)
403 {
404 const char* end = 0;
405 JSON* json = new JSON();
407 if (!json)
408 {
409 AssignError(perror, "Error: Failed to allocate memory");
410 return 0;
411 }
413 end = json->parseValue(skip(buff), perror);
414 if (!end)
415 {
416 json->Release();
417 return NULL;
418 } // parse failure. ep is set.
420 return json;
421 }
423 //-----------------------------------------------------------------------------
424 // Parser core - when encountering text, process appropriately.
425 const char* JSON::parseValue(const char* buff, const char** perror)
426 {
427 if (perror)
428 *perror = 0;
430 if (!buff)
431 return NULL; // Fail on null.
433 if (!strncmp(buff,"null",4))
434 {
435 Type = JSON_Null;
436 return buff+4;
437 }
438 if (!strncmp(buff,"false",5))
439 {
440 Type = JSON_Bool;
441 Value = "false";
442 dValue = 0;
443 return buff+5;
444 }
445 if (!strncmp(buff,"true",4))
446 {
447 Type = JSON_Bool;
448 Value = "true";
449 dValue = 1;
450 return buff+4;
451 }
452 if (*buff=='\"')
453 {
454 return parseString(buff, perror);
455 }
456 if (*buff=='-' || (*buff>='0' && *buff<='9'))
457 {
458 return parseNumber(buff);
459 }
460 if (*buff=='[')
461 {
462 return parseArray(buff, perror);
463 }
464 if (*buff=='{')
465 {
466 return parseObject(buff, perror);
467 }
469 return AssignError(perror, "Syntax Error: Invalid syntax");
470 }
473 //-----------------------------------------------------------------------------
474 // Render a value to text.
475 char* JSON::PrintValue(int depth, bool fmt)
476 {
477 char *out=0;
479 switch (Type)
480 {
481 case JSON_Null: out = JSON_strdup("null"); break;
482 case JSON_Bool:
483 if (dValue == 0)
484 out = JSON_strdup("false");
485 else
486 out = JSON_strdup("true");
487 break;
488 case JSON_Number: out = PrintNumber(dValue); break;
489 case JSON_String: out = PrintString(Value); break;
490 case JSON_Array: out = PrintArray(depth, fmt); break;
491 case JSON_Object: out = PrintObject(depth, fmt); break;
492 case JSON_None: OVR_ASSERT_LOG(false, ("Bad JSON type.")); break;
493 }
494 return out;
495 }
497 //-----------------------------------------------------------------------------
498 // Build an array object from input text and returns the text position after
499 // the parsed array
500 const char* JSON::parseArray(const char* buff, const char** perror)
501 {
502 JSON *child;
503 if (*buff!='[')
504 {
505 return AssignError(perror, "Syntax Error: Missing opening bracket");
506 }
508 Type=JSON_Array;
509 buff=skip(buff+1);
511 if (*buff==']')
512 return buff+1; // empty array.
514 child = new JSON();
515 if (!child)
516 return 0; // memory fail
517 Children.PushBack(child);
519 buff=skip(child->parseValue(skip(buff), perror)); // skip any spacing, get the buff.
520 if (!buff)
521 return 0;
523 while (*buff==',')
524 {
525 JSON *new_item = new JSON();
526 if (!new_item)
527 return AssignError(perror, "Error: Failed to allocate memory");
529 Children.PushBack(new_item);
531 buff=skip(new_item->parseValue(skip(buff+1), perror));
532 if (!buff)
533 return AssignError(perror, "Error: Failed to allocate memory");
534 }
536 if (*buff==']')
537 return buff+1; // end of array
539 return AssignError(perror, "Syntax Error: Missing ending bracket");
540 }
542 //-----------------------------------------------------------------------------
543 // Render an array to text. The returned text must be freed
544 char* JSON::PrintArray(int depth, bool fmt)
545 {
546 char **entries;
547 char * out = 0,*ptr,*ret;
548 SPInt len = 5;
550 bool fail = false;
552 // How many entries in the array?
553 int numentries = GetItemCount();
554 if (!numentries)
555 {
556 out=(char*)OVR_ALLOC(3);
557 if (out)
558 OVR_strcpy(out, 3, "[]");
559 return out;
560 }
561 // Allocate an array to hold the values for each
562 entries=(char**)OVR_ALLOC(numentries*sizeof(char*));
563 if (!entries)
564 return 0;
565 memset(entries,0,numentries*sizeof(char*));
567 //// Retrieve all the results:
568 JSON* child = Children.GetFirst();
569 for (int i=0; i<numentries; i++)
570 {
571 //JSON* child = Children[i];
572 ret=child->PrintValue(depth+1, fmt);
573 entries[i]=ret;
574 if (ret)
575 len+=OVR_strlen(ret)+2+(fmt?1:0);
576 else
577 {
578 fail = true;
579 break;
580 }
581 child = Children.GetNext(child);
582 }
584 // If we didn't fail, try to malloc the output string
585 if (!fail)
586 out=(char*)OVR_ALLOC(len);
587 // If that fails, we fail.
588 if (!out)
589 fail = true;
591 // Handle failure.
592 if (fail)
593 {
594 for (int i=0; i<numentries; i++)
595 {
596 if (entries[i])
597 OVR_FREE(entries[i]);
598 }
599 OVR_FREE(entries);
600 return 0;
601 }
603 // Compose the output array.
604 *out='[';
605 ptr=out+1;
606 *ptr=0;
607 for (int i=0; i<numentries; i++)
608 {
609 OVR_strcpy(ptr, len - (ptr-out), entries[i]);
610 ptr+=OVR_strlen(entries[i]);
611 if (i!=numentries-1)
612 {
613 *ptr++=',';
614 if (fmt)
615 *ptr++=' ';
616 *ptr=0;
617 }
618 OVR_FREE(entries[i]);
619 }
620 OVR_FREE(entries);
621 *ptr++=']';
622 *ptr++=0;
623 return out;
624 }
626 //-----------------------------------------------------------------------------
627 // Build an object from the supplied text and returns the text position after
628 // the parsed object
629 const char* JSON::parseObject(const char* buff, const char** perror)
630 {
631 if (*buff!='{')
632 {
633 return AssignError(perror, "Syntax Error: Missing opening brace");
634 }
636 Type=JSON_Object;
637 buff=skip(buff+1);
638 if (*buff=='}')
639 return buff+1; // empty array.
641 JSON* child = new JSON();
642 Children.PushBack(child);
644 buff=skip(child->parseString(skip(buff), perror));
645 if (!buff)
646 return 0;
647 child->Name = child->Value;
648 child->Value.Clear();
650 if (*buff!=':')
651 {
652 return AssignError(perror, "Syntax Error: Missing colon");
653 }
655 buff=skip(child->parseValue(skip(buff+1), perror)); // skip any spacing, get the value.
656 if (!buff)
657 return 0;
659 while (*buff==',')
660 {
661 child = new JSON();
662 if (!child)
663 return 0; // memory fail
665 Children.PushBack(child);
667 buff=skip(child->parseString(skip(buff+1), perror));
668 if (!buff)
669 return 0;
671 child->Name=child->Value;
672 child->Value.Clear();
674 if (*buff!=':')
675 {
676 return AssignError(perror, "Syntax Error: Missing colon");
677 } // fail!
679 // Skip any spacing, get the value.
680 buff=skip(child->parseValue(skip(buff+1), perror));
681 if (!buff)
682 return 0;
683 }
685 if (*buff=='}')
686 return buff+1; // end of array
688 return AssignError(perror, "Syntax Error: Missing closing brace");
689 }
691 //-----------------------------------------------------------------------------
692 // Render an object to text. The returned string must be freed
693 char* JSON::PrintObject(int depth, bool fmt)
694 {
695 char** entries = 0, **names = 0;
696 char* out = 0;
697 char* ptr, *ret, *str;
698 SPInt len = 7, i = 0, j;
699 bool fail = false;
701 // Count the number of entries.
702 int numentries = GetItemCount();
704 // Explicitly handle empty object case
705 if (numentries == 0)
706 {
707 out=(char*)OVR_ALLOC(fmt?depth+3:3);
708 if (!out)
709 return 0;
710 ptr=out;
711 *ptr++='{';
713 if (fmt)
714 {
715 *ptr++='\n';
716 for (i=0;i<depth-1;i++)
717 *ptr++='\t';
718 }
719 *ptr++='}';
720 *ptr++=0;
721 return out;
722 }
723 // Allocate space for the names and the objects
724 entries=(char**)OVR_ALLOC(numentries*sizeof(char*));
725 if (!entries)
726 return 0;
727 names=(char**)OVR_ALLOC(numentries*sizeof(char*));
729 if (!names)
730 {
731 OVR_FREE(entries);
732 return 0;
733 }
734 memset(entries,0,sizeof(char*)*numentries);
735 memset(names,0,sizeof(char*)*numentries);
737 // Collect all the results into our arrays:
738 depth++;
739 if (fmt)
740 len+=depth;
742 JSON* child = Children.GetFirst();
743 while (!Children.IsNull(child))
744 {
745 names[i] = str = PrintString(child->Name);
746 entries[i++] = ret = child->PrintValue(depth, fmt);
748 if (str && ret)
749 {
750 len += OVR_strlen(ret)+OVR_strlen(str)+2+(fmt?2+depth:0);
751 }
752 else
753 {
754 fail = true;
755 break;
756 }
758 child = Children.GetNext(child);
759 }
761 // Try to allocate the output string
762 if (!fail)
763 out=(char*)OVR_ALLOC(len);
764 if (!out)
765 fail=true;
767 // Handle failure
768 if (fail)
769 {
770 for (i=0;i<numentries;i++)
771 {
772 if (names[i])
773 OVR_FREE(names[i]);
775 if (entries[i])
776 OVR_FREE(entries[i]);}
778 OVR_FREE(names);
779 OVR_FREE(entries);
780 return 0;
781 }
783 // Compose the output:
784 *out = '{';
785 ptr = out+1;
786 if (fmt)
787 *ptr++='\n';
788 *ptr = 0;
790 for (i=0; i<numentries; i++)
791 {
792 if (fmt)
793 {
794 for (j=0; j<depth; j++)
795 *ptr++ = '\t';
796 }
797 OVR_strcpy(ptr, len - (ptr-out), names[i]);
798 ptr += OVR_strlen(names[i]);
799 *ptr++ =':';
801 if (fmt)
802 *ptr++='\t';
804 OVR_strcpy(ptr, len - (ptr-out), entries[i]);
805 ptr+=OVR_strlen(entries[i]);
807 if (i!=numentries-1)
808 *ptr++ = ',';
810 if (fmt)
811 *ptr++ = '\n';
812 *ptr = 0;
814 OVR_FREE(names[i]);
815 OVR_FREE(entries[i]);
816 }
818 OVR_FREE(names);
819 OVR_FREE(entries);
821 if (fmt)
822 {
823 for (i=0;i<depth-1;i++)
824 *ptr++='\t';
825 }
826 *ptr++='}';
827 *ptr++=0;
829 return out;
830 }
834 // Returns the number of child items in the object
835 // Counts the number of items in the object.
836 unsigned JSON::GetItemCount() const
837 {
838 unsigned count = 0;
839 for(const JSON* p = Children.GetFirst(); !Children.IsNull(p); p = p->pNext)
840 count++;
841 return count;
842 }
844 JSON* JSON::GetItemByIndex(unsigned index)
845 {
846 unsigned i = 0;
847 JSON* child = 0;
849 if (!Children.IsEmpty())
850 {
851 child = Children.GetFirst();
853 while (i < index)
854 {
855 if (Children.IsNull(child->pNext))
856 {
857 child = 0;
858 break;
859 }
860 child = child->pNext;
861 i++;
862 }
863 }
865 return child;
866 }
868 // Returns the child item with the given name or NULL if not found
869 JSON* JSON::GetItemByName(const char* name)
870 {
871 JSON* child = 0;
873 if (!Children.IsEmpty())
874 {
875 child = Children.GetFirst();
877 while (OVR_strcmp(child->Name, name) != 0)
878 {
879 if (Children.IsNull(child->pNext))
880 {
881 child = 0;
882 break;
883 }
884 child = child->pNext;
885 }
886 }
888 return child;
889 }
891 //-----------------------------------------------------------------------------
892 // Adds a new item to the end of the child list
893 void JSON::AddItem(const char *string, JSON *item)
894 {
895 if (!item)
896 return;
898 item->Name = string;
899 Children.PushBack(item);
900 }
902 /*
904 // Removes and frees the items at the given index
905 void JSON::DeleteItem(unsigned int index)
906 {
907 unsigned int num_items = 0;
908 JSON* child = Children.GetFirst();
909 while (!Children.IsNull(child) && num_items < index)
910 {
911 num_items++;
912 child = Children.GetNext(child);
913 }
915 if (!Children.IsNull(child))
917 child->RemoveNode();
918 child->Release();
919 }
920 }
922 // Replaces and frees the item at the give index with the new item
923 void JSON::ReplaceItem(unsigned int index, JSON* new_item)
924 {
925 unsigned int num_items = 0;
926 JSON* child = Children.GetFirst();
927 while (!Children.IsNull(child) && num_items < index)
928 {
929 num_items++;
930 child = Children.GetNext(child);
931 }
933 if (!Children.IsNull(child))
934 {
935 child->ReplaceNodeWith(new_item);
936 child->Release();
937 }
938 }
939 */
941 // Helper function to simplify creation of a typed object
942 JSON* JSON::createHelper(JSONItemType itemType, double dval, const char* strVal)
943 {
944 JSON *item = new JSON(itemType);
945 if (item)
946 {
947 item->dValue = dval;
948 if (strVal)
949 item->Value = strVal;
950 }
951 return item;
952 }
955 //-----------------------------------------------------------------------------
956 // Adds an element to an array object type
957 void JSON::AddArrayElement(JSON *item)
958 {
959 if (!item)
960 return;
962 Children.PushBack(item);
963 }
966 // Returns the size of an array
967 int JSON::GetArraySize()
968 {
969 if (Type == JSON_Array)
970 return GetItemCount();
971 else
972 return 0;
973 }
975 // Returns the number value an the give array index
976 double JSON::GetArrayNumber(int index)
977 {
978 if (Type == JSON_Array)
979 {
980 JSON* number = GetItemByIndex(index);
981 return number ? number->dValue : 0.0;
982 }
983 else
984 {
985 return 0;
986 }
987 }
989 // Returns the string value at the given array index
990 const char* JSON::GetArrayString(int index)
991 {
992 if (Type == JSON_Array)
993 {
994 JSON* number = GetItemByIndex(index);
995 return number ? number->Value : 0;
996 }
997 else
998 {
999 return 0;
1003 //-----------------------------------------------------------------------------
1004 // Loads and parses the given JSON file pathname and returns a JSON object tree.
1005 // The returned object must be Released after use.
1006 JSON* JSON::Load(const char* path, const char** perror)
1008 SysFile f;
1009 if (!f.Open(path, File::Open_Read, File::Mode_Read))
1011 AssignError(perror, "Failed to open file");
1012 return NULL;
1015 int len = f.GetLength();
1016 UByte* buff = (UByte*)OVR_ALLOC(len);
1017 int bytes = f.Read(buff, len);
1018 f.Close();
1020 if (bytes == 0 || bytes != len)
1022 OVR_FREE(buff);
1023 return NULL;
1026 JSON* json = JSON::Parse((char*)buff, perror);
1027 OVR_FREE(buff);
1028 return json;
1031 //-----------------------------------------------------------------------------
1032 // Serializes the JSON object and writes to the give file path
1033 bool JSON::Save(const char* path)
1035 SysFile f;
1036 if (!f.Open(path, File::Open_Write | File::Open_Create | File::Open_Truncate, File::Mode_Write))
1037 return false;
1039 char* text = PrintValue(0, true);
1040 if (text)
1042 SPInt len = OVR_strlen(text);
1043 OVR_ASSERT(len < (SPInt)(int)len);
1045 int bytes = f.Write((UByte*)text, (int)len);
1046 f.Close();
1047 OVR_FREE(text);
1048 return (bytes == len);
1050 else
1052 return false;