ovr_sdk

view LibOVR/Src/OVR_JSON.cpp @ 0:1b39a1b46319

initial 0.4.4
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 14 Jan 2015 06:51:16 +0200
parents
children
line 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 2014 Oculus VR, LLC All Rights reserved.
35 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
36 you may not use the Oculus VR Rift SDK except in compliance with the License,
37 which is provided at the time of installation or download, or which
38 otherwise accompanies this software in either electronic or hard copy form.
40 You may obtain a copy of the License at
42 http://www.oculusvr.com/licenses/LICENSE-3.2
44 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
45 distributed under the License is distributed on an "AS IS" BASIS,
46 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
47 See the License for the specific language governing permissions and
48 limitations under the License.
50 ************************************************************************************/
52 #include <string.h>
53 #include <stdio.h>
54 #include <math.h>
55 #include <stdlib.h>
56 #include <float.h>
57 #include <limits.h>
58 #include <ctype.h>
59 #include "OVR_JSON.h"
60 #include "Kernel/OVR_SysFile.h"
61 #include "Kernel/OVR_Log.h"
63 #ifdef OVR_OS_LINUX
64 #include <locale.h>
65 #endif
67 namespace OVR {
70 //-----------------------------------------------------------------------------
71 // Create a new copy of a string
72 static char* JSON_strdup(const char* str)
73 {
74 size_t len = OVR_strlen(str) + 1;
75 char* copy = (char*)OVR_ALLOC(len);
76 if (!copy)
77 return 0;
78 memcpy(copy, str, len);
79 return copy;
80 }
83 //-----------------------------------------------------------------------------
84 // Render the number from the given item into a string.
85 static char* PrintInt(int valueint)
86 {
87 char *str;
88 str = (char*)OVR_ALLOC(21); // 2^64+1 can be represented in 21 chars.
89 if (str)
90 {
91 OVR_sprintf(str, 21, "%d", valueint);
92 }
93 return str;
94 }
97 //-----------------------------------------------------------------------------
98 // Render the number from the given item into a string.
99 static char* PrintNumber(double d)
100 {
101 char *str;
102 int valueint = (int)d;
103 if (fabs(((double)valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
104 {
105 return PrintInt(valueint);
106 }
107 else
108 {
109 str=(char*)OVR_ALLOC(64); // This is a nice tradeoff.
110 if (str)
111 {
112 if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)
113 OVR_sprintf(str, 64, "%.0f", d);
114 else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)
115 OVR_sprintf(str, 64, "%e", d);
116 else
117 OVR_sprintf(str, 64, "%f", d);
118 }
119 }
120 return str;
121 }
124 // Parse the input text into an un-escaped cstring, and populate item.
125 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
127 // Helper to assign error sting and return 0.
128 const char* AssignError(const char** perror, const char *errorMessage)
129 {
130 if (perror)
131 *perror = errorMessage;
132 return 0;
133 }
135 //-----------------------------------------------------------------------------
136 // ***** JSON Node class
138 JSON::JSON(JSONItemType itemType) :
139 Type(itemType), dValue(0.)
140 {
141 }
143 JSON::~JSON()
144 {
145 JSON* child = Children.GetFirst();
146 while (!Children.IsNull(child))
147 {
148 child->RemoveNode();
149 child->Release();
150 child = Children.GetFirst();
151 }
152 }
154 //-----------------------------------------------------------------------------
155 // Parse the input text to generate a number, and populate the result into item
156 // Returns the text position after the parsed number
157 const char* JSON::parseNumber(const char *num)
158 {
159 const char* num_start = num;
160 double n=0, scale=0;
161 int subscale = 0,
162 signsubscale = 1;
163 bool positiveSign = true;
164 char localeSeparator = '.';
166 #ifdef OVR_OS_LINUX
167 // We should switch to a locale aware parsing function, such as atof. We
168 // will probably want to go farther and enforce the 'C' locale on all JSON
169 // output/input.
170 struct lconv* localeConv = localeconv();
171 localeSeparator = localeConv->decimal_point[0];
172 #endif
174 // Could use sscanf for this?
175 if (*num == '-')
176 {
177 positiveSign = false;
178 num++; // Has sign?
179 }
180 if (*num == '0')
181 {
182 num++; // is zero
183 }
185 if (*num>='1' && *num<='9')
186 {
187 do
188 {
189 n = (n*10.0) + (*num++ - '0');
190 }
191 while (*num>='0' && *num<='9'); // Number?
192 }
194 if ((*num=='.' || *num==localeSeparator) && num[1]>='0' && num[1]<='9')
195 {
196 num++;
197 do
198 {
199 n=(n*10.0)+(*num++ -'0');
200 scale--;
201 }
202 while (*num>='0' && *num<='9'); // Fractional part?
203 }
205 if (*num=='e' || *num=='E') // Exponent?
206 {
207 num++;
208 if (*num == '+')
209 {
210 num++;
211 }
212 else if (*num=='-')
213 {
214 signsubscale=-1;
215 num++; // With sign?
216 }
218 while (*num >= '0' && *num <= '9')
219 {
220 subscale = (subscale * 10) + (*num++ - '0'); // Number?
221 }
222 }
224 // Number = +/- number.fraction * 10^+/- exponent
225 n *= pow(10.0, (scale + subscale*signsubscale));
227 if (!positiveSign)
228 {
229 n = -n;
230 }
232 // Assign parsed value.
233 Type = JSON_Number;
234 dValue = n;
235 Value.AssignString(num_start, num - num_start);
237 return num;
238 }
240 // Parses a hex string up to the specified number of digits.
241 // Returns the first character after the string.
242 const char* ParseHex(unsigned* val, unsigned digits, const char* str)
243 {
244 *val = 0;
246 for(unsigned digitCount = 0; digitCount < digits; digitCount++, str++)
247 {
248 unsigned v = *str;
250 if ((v >= '0') && (v <= '9'))
251 v -= '0';
252 else if ((v >= 'a') && (v <= 'f'))
253 v = 10 + v - 'a';
254 else if ((v >= 'A') && (v <= 'F'))
255 v = 10 + v - 'A';
256 else
257 break;
259 *val = *val * 16 + v;
260 }
262 return str;
263 }
265 //-----------------------------------------------------------------------------
266 // Parses the input text into a string item and returns the text position after
267 // the parsed string
268 const char* JSON::parseString(const char* str, const char** perror)
269 {
270 const char* ptr = str+1;
271 const char* p;
272 char* ptr2;
273 char* out;
274 int len=0;
275 unsigned uc, uc2;
277 if (*str!='\"')
278 {
279 return AssignError(perror, "Syntax Error: Missing quote");
280 }
282 while (*ptr!='\"' && *ptr && ++len)
283 {
284 if (*ptr++ == '\\') ptr++; // Skip escaped quotes.
285 }
287 // This is how long we need for the string, roughly.
288 out=(char*)OVR_ALLOC(len+1);
289 if (!out)
290 return 0;
292 ptr = str+1;
293 ptr2= out;
295 while (*ptr!='\"' && *ptr)
296 {
297 if (*ptr!='\\')
298 {
299 *ptr2++ = *ptr++;
300 }
301 else
302 {
303 ptr++;
304 switch (*ptr)
305 {
306 case 'b': *ptr2++ = '\b'; break;
307 case 'f': *ptr2++ = '\f'; break;
308 case 'n': *ptr2++ = '\n'; break;
309 case 'r': *ptr2++ = '\r'; break;
310 case 't': *ptr2++ = '\t'; break;
312 // Transcode utf16 to utf8.
313 case 'u':
315 // Get the unicode char.
316 p = ParseHex(&uc, 4, ptr + 1);
317 if (ptr != p)
318 ptr = p - 1;
320 if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)
321 break; // Check for invalid.
323 // UTF16 surrogate pairs.
324 if (uc>=0xD800 && uc<=0xDBFF)
325 {
326 if (ptr[1]!='\\' || ptr[2]!='u')
327 break; // Missing second-half of surrogate.
329 p= ParseHex(&uc2, 4, ptr + 3);
330 if (ptr != p)
331 ptr = p - 1;
333 if (uc2<0xDC00 || uc2>0xDFFF)
334 break; // Invalid second-half of surrogate.
336 uc = 0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
337 }
339 len=4;
341 if (uc<0x80)
342 len=1;
343 else if (uc<0x800)
344 len=2;
345 else if (uc<0x10000)
346 len=3;
348 ptr2+=len;
350 switch (len)
351 {
352 case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
353 //no break, fall through
354 case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
355 //no break
356 case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
357 //no break
358 case 1: *--ptr2 = (char)(uc | firstByteMark[len]);
359 //no break
360 }
361 ptr2+=len;
362 break;
364 default:
365 *ptr2++ = *ptr;
366 break;
367 }
368 ptr++;
369 }
370 }
372 *ptr2 = 0;
373 if (*ptr=='\"')
374 ptr++;
376 // Make a copy of the string
377 Value=out;
378 OVR_FREE(out);
379 Type=JSON_String;
381 return ptr;
382 }
384 //-----------------------------------------------------------------------------
385 // Render the string provided to an escaped version that can be printed.
386 char* PrintString(const char* str)
387 {
388 const char *ptr;
389 char *ptr2,*out;
390 int len=0;
391 unsigned char token;
393 if (!str)
394 return JSON_strdup("");
395 ptr=str;
397 token=*ptr;
398 while (token && ++len)\
399 {
400 if (strchr("\"\\\b\f\n\r\t",token))
401 len++;
402 else if (token<32)
403 len+=5;
404 ptr++;
405 token=*ptr;
406 }
408 int buff_size = len+3;
409 out=(char*)OVR_ALLOC(buff_size);
410 if (!out)
411 return 0;
413 ptr2 = out;
414 ptr = str;
415 *ptr2++ = '\"';
417 while (*ptr)
418 {
419 if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\')
420 *ptr2++=*ptr++;
421 else
422 {
423 *ptr2++='\\';
424 switch (token=*ptr++)
425 {
426 case '\\': *ptr2++='\\'; break;
427 case '\"': *ptr2++='\"'; break;
428 case '\b': *ptr2++='b'; break;
429 case '\f': *ptr2++='f'; break;
430 case '\n': *ptr2++='n'; break;
431 case '\r': *ptr2++='r'; break;
432 case '\t': *ptr2++='t'; break;
433 default:
434 OVR_sprintf(ptr2, buff_size - (ptr2-out), "u%04x",token);
435 ptr2+=5;
436 break; // Escape and print.
437 }
438 }
439 }
440 *ptr2++='\"';
441 *ptr2++=0;
442 return out;
443 }
445 //-----------------------------------------------------------------------------
446 // Utility to jump whitespace and cr/lf
447 static const char* skip(const char* in)
448 {
449 while (in && *in && (unsigned char)*in<=' ')
450 in++;
451 return in;
452 }
454 //-----------------------------------------------------------------------------
455 // Parses the supplied buffer of JSON text and returns a JSON object tree
456 // The returned object must be Released after use
457 JSON* JSON::Parse(const char* buff, const char** perror)
458 {
459 const char* end = 0;
460 JSON* json = new JSON();
462 if (!json)
463 {
464 AssignError(perror, "Error: Failed to allocate memory");
465 return 0;
466 }
468 end = json->parseValue(skip(buff), perror);
469 if (!end)
470 {
471 json->Release();
472 return NULL;
473 } // parse failure. ep is set.
475 return json;
476 }
478 //-----------------------------------------------------------------------------
479 // This version works for buffers that are not null terminated strings.
480 JSON* JSON::ParseBuffer(const char *buff, int len, const char** perror)
481 {
482 // Our JSON parser does not support length-based parsing,
483 // so ensure it is null-terminated.
484 char *termStr = new char[len + 1];
485 memcpy(termStr, buff, len);
486 termStr[len] = '\0';
488 JSON *objJson = Parse(termStr, perror);
490 delete[]termStr;
492 return objJson;
493 }
495 //-----------------------------------------------------------------------------
496 // Parser core - when encountering text, process appropriately.
497 const char* JSON::parseValue(const char* buff, const char** perror)
498 {
499 if (perror)
500 *perror = 0;
502 if (!buff)
503 return NULL; // Fail on null.
505 if (!strncmp(buff,"null",4))
506 {
507 Type = JSON_Null;
508 return buff+4;
509 }
510 if (!strncmp(buff,"false",5))
511 {
512 Type = JSON_Bool;
513 Value = "false";
514 dValue = 0.;
515 return buff+5;
516 }
517 if (!strncmp(buff,"true",4))
518 {
519 Type = JSON_Bool;
520 Value = "true";
521 dValue = 1.;
522 return buff + 4;
523 }
524 if (*buff=='\"')
525 {
526 return parseString(buff, perror);
527 }
528 if (*buff=='-' || (*buff>='0' && *buff<='9'))
529 {
530 return parseNumber(buff);
531 }
532 if (*buff=='[')
533 {
534 return parseArray(buff, perror);
535 }
536 if (*buff=='{')
537 {
538 return parseObject(buff, perror);
539 }
541 return AssignError(perror, "Syntax Error: Invalid syntax");
542 }
545 //-----------------------------------------------------------------------------
546 // Render a value to text.
547 char* JSON::PrintValue(int depth, bool fmt)
548 {
549 char *out=0;
551 switch (Type)
552 {
553 case JSON_Null: out = JSON_strdup("null"); break;
554 case JSON_Bool:
555 if ((int)dValue == 0)
556 out = JSON_strdup("false");
557 else
558 out = JSON_strdup("true");
559 break;
560 case JSON_Number: out = PrintNumber(dValue); break;
561 case JSON_String: out = PrintString(Value); break;
562 case JSON_Array: out = PrintArray(depth, fmt); break;
563 case JSON_Object: out = PrintObject(depth, fmt); break;
564 case JSON_None: OVR_ASSERT_LOG(false, ("Bad JSON type.")); break;
565 }
566 return out;
567 }
569 //-----------------------------------------------------------------------------
570 // Build an array object from input text and returns the text position after
571 // the parsed array
572 const char* JSON::parseArray(const char* buff, const char** perror)
573 {
574 JSON *child;
575 if (*buff!='[')
576 {
577 return AssignError(perror, "Syntax Error: Missing opening bracket");
578 }
580 Type=JSON_Array;
581 buff=skip(buff+1);
583 if (*buff==']')
584 return buff+1; // empty array.
586 child = new JSON();
587 if (!child)
588 return 0; // memory fail
589 Children.PushBack(child);
591 buff=skip(child->parseValue(skip(buff), perror)); // skip any spacing, get the buff.
592 if (!buff)
593 return 0;
595 while (*buff==',')
596 {
597 JSON *new_item = new JSON();
598 if (!new_item)
599 return AssignError(perror, "Error: Failed to allocate memory");
601 Children.PushBack(new_item);
603 buff=skip(new_item->parseValue(skip(buff+1), perror));
604 if (!buff)
605 return AssignError(perror, "Error: Failed to allocate memory");
606 }
608 if (*buff==']')
609 return buff+1; // end of array
611 return AssignError(perror, "Syntax Error: Missing ending bracket");
612 }
614 //-----------------------------------------------------------------------------
615 // Render an array to text. The returned text must be freed
616 char* JSON::PrintArray(int depth, bool fmt)
617 {
618 char ** entries;
619 char * out = 0, *ptr,*ret;
620 intptr_t len = 5;
622 bool fail = false;
624 // How many entries in the array?
625 int numentries = GetItemCount();
626 if (!numentries)
627 {
628 out=(char*)OVR_ALLOC(3);
629 if (out)
630 OVR_strcpy(out, 3, "[]");
631 return out;
632 }
633 // Allocate an array to hold the values for each
634 entries=(char**)OVR_ALLOC(numentries*sizeof(char*));
635 if (!entries)
636 return 0;
637 memset(entries,0,numentries*sizeof(char*));
639 //// Retrieve all the results:
640 JSON* child = Children.GetFirst();
641 for (int i=0; i<numentries; i++)
642 {
643 //JSON* child = Children[i];
644 ret=child->PrintValue(depth+1, fmt);
645 entries[i]=ret;
646 if (ret)
647 len+=OVR_strlen(ret)+2+(fmt?1:0);
648 else
649 {
650 fail = true;
651 break;
652 }
653 child = Children.GetNext(child);
654 }
656 // If we didn't fail, try to malloc the output string
657 if (!fail)
658 out=(char*)OVR_ALLOC(len);
659 // If that fails, we fail.
660 if (!out)
661 fail = true;
663 // Handle failure.
664 if (fail)
665 {
666 for (int i=0; i<numentries; i++)
667 {
668 if (entries[i])
669 OVR_FREE(entries[i]);
670 }
671 OVR_FREE(entries);
672 return 0;
673 }
675 // Compose the output array.
676 *out='[';
677 ptr=out+1;
678 *ptr=0;
679 for (int i=0; i<numentries; i++)
680 {
681 OVR_strcpy(ptr, len - (ptr-out), entries[i]);
682 ptr+=OVR_strlen(entries[i]);
683 if (i!=numentries-1)
684 {
685 *ptr++=',';
686 if (fmt)
687 *ptr++=' ';
688 *ptr=0;
689 }
690 OVR_FREE(entries[i]);
691 }
692 OVR_FREE(entries);
693 *ptr++=']';
694 *ptr++=0;
695 return out;
696 }
698 //-----------------------------------------------------------------------------
699 // Build an object from the supplied text and returns the text position after
700 // the parsed object
701 const char* JSON::parseObject(const char* buff, const char** perror)
702 {
703 if (*buff!='{')
704 {
705 return AssignError(perror, "Syntax Error: Missing opening brace");
706 }
708 Type=JSON_Object;
709 buff=skip(buff+1);
710 if (*buff=='}')
711 return buff+1; // empty array.
713 JSON* child = new JSON();
714 Children.PushBack(child);
716 buff=skip(child->parseString(skip(buff), perror));
717 if (!buff)
718 return 0;
719 child->Name = child->Value;
720 child->Value.Clear();
722 if (*buff!=':')
723 {
724 return AssignError(perror, "Syntax Error: Missing colon");
725 }
727 buff=skip(child->parseValue(skip(buff+1), perror)); // skip any spacing, get the value.
728 if (!buff)
729 return 0;
731 while (*buff==',')
732 {
733 child = new JSON();
734 if (!child)
735 return 0; // memory fail
737 Children.PushBack(child);
739 buff=skip(child->parseString(skip(buff+1), perror));
740 if (!buff)
741 return 0;
743 child->Name=child->Value;
744 child->Value.Clear();
746 if (*buff!=':')
747 {
748 return AssignError(perror, "Syntax Error: Missing colon");
749 } // fail!
751 // Skip any spacing, get the value.
752 buff=skip(child->parseValue(skip(buff+1), perror));
753 if (!buff)
754 return 0;
755 }
757 if (*buff=='}')
758 return buff+1; // end of array
760 return AssignError(perror, "Syntax Error: Missing closing brace");
761 }
763 //-----------------------------------------------------------------------------
764 // Render an object to text. The returned string must be freed
765 char* JSON::PrintObject(int depth, bool fmt)
766 {
767 char** entries = 0, **names = 0;
768 char* out = 0;
769 char* ptr, *ret, *str;
770 intptr_t len = 7, i = 0, j;
771 bool fail = false;
773 // Count the number of entries.
774 int numentries = GetItemCount();
776 // Explicitly handle empty object case
777 if (numentries == 0)
778 {
779 out=(char*)OVR_ALLOC(fmt?depth+4:4);
780 if (!out)
781 return 0;
782 ptr=out;
783 *ptr++='{';
785 if (fmt)
786 {
787 *ptr++='\n';
788 for (i=0;i<depth-1;i++)
789 *ptr++='\t';
790 }
791 *ptr++='}';
792 *ptr++=0;
793 return out;
794 }
795 // Allocate space for the names and the objects
796 entries=(char**)OVR_ALLOC(numentries*sizeof(char*));
797 if (!entries)
798 return 0;
799 names=(char**)OVR_ALLOC(numentries*sizeof(char*));
801 if (!names)
802 {
803 OVR_FREE(entries);
804 return 0;
805 }
806 memset(entries,0,sizeof(char*)*numentries);
807 memset(names,0,sizeof(char*)*numentries);
809 // Collect all the results into our arrays:
810 depth++;
811 if (fmt)
812 len+=depth;
814 JSON* child = Children.GetFirst();
815 while (!Children.IsNull(child))
816 {
817 names[i] = str = PrintString(child->Name);
818 entries[i++] = ret = child->PrintValue(depth, fmt);
820 if (str && ret)
821 {
822 len += OVR_strlen(ret)+OVR_strlen(str)+2+(fmt?3+depth:0);
823 }
824 else
825 {
826 fail = true;
827 break;
828 }
830 child = Children.GetNext(child);
831 }
833 // Try to allocate the output string
834 if (!fail)
835 out=(char*)OVR_ALLOC(len);
836 if (!out)
837 fail=true;
839 // Handle failure
840 if (fail)
841 {
842 for (i=0;i<numentries;i++)
843 {
844 if (names[i])
845 OVR_FREE(names[i]);
847 if (entries[i])
848 OVR_FREE(entries[i]);}
850 OVR_FREE(names);
851 OVR_FREE(entries);
852 return 0;
853 }
855 // Compose the output:
856 *out = '{';
857 ptr = out+1;
858 if (fmt)
859 {
860 #ifdef OVR_OS_WIN32
861 *ptr++ = '\r';
862 #endif
863 *ptr++ = '\n';
864 }
865 *ptr = 0;
867 for (i=0; i<numentries; i++)
868 {
869 if (fmt)
870 {
871 for (j = 0; j < depth; j++)
872 {
873 *ptr++ = '\t';
874 }
875 }
876 OVR_strcpy(ptr, len - (ptr-out), names[i]);
877 ptr += OVR_strlen(names[i]);
878 *ptr++ =':';
880 if (fmt)
881 {
882 *ptr++ = '\t';
883 }
885 OVR_strcpy(ptr, len - (ptr-out), entries[i]);
886 ptr+=OVR_strlen(entries[i]);
888 if (i != numentries - 1)
889 {
890 *ptr++ = ',';
891 }
893 if (fmt)
894 {
895 #ifdef OVR_OS_WIN32
896 *ptr++ = '\r';
897 #endif
898 *ptr++ = '\n';
899 }
900 *ptr = 0;
902 OVR_FREE(names[i]);
903 OVR_FREE(entries[i]);
904 }
906 OVR_FREE(names);
907 OVR_FREE(entries);
909 if (fmt)
910 {
911 for (i = 0; i < depth - 1; i++)
912 {
913 *ptr++ = '\t';
914 }
915 }
916 *ptr++='}';
917 *ptr++=0;
919 return out;
920 }
924 // Returns the number of child items in the object
925 // Counts the number of items in the object.
926 unsigned JSON::GetItemCount() const
927 {
928 unsigned count = 0;
929 for (const JSON* p = Children.GetFirst(); !Children.IsNull(p); p = p->pNext)
930 {
931 count++;
932 }
933 return count;
934 }
936 JSON* JSON::GetItemByIndex(unsigned index)
937 {
938 unsigned i = 0;
939 JSON* child = 0;
941 if (!Children.IsEmpty())
942 {
943 child = Children.GetFirst();
945 while (i < index)
946 {
947 if (Children.IsNull(child->pNext))
948 {
949 child = 0;
950 break;
951 }
952 child = child->pNext;
953 i++;
954 }
955 }
957 return child;
958 }
960 // Returns the child item with the given name or NULL if not found
961 JSON* JSON::GetItemByName(const char* name)
962 {
963 JSON* child = 0;
965 if (!Children.IsEmpty())
966 {
967 child = Children.GetFirst();
969 while (OVR_strcmp(child->Name, name) != 0)
970 {
971 if (Children.IsNull(child->pNext))
972 {
973 child = 0;
974 break;
975 }
976 child = child->pNext;
977 }
978 }
980 return child;
981 }
983 //-----------------------------------------------------------------------------
984 // Adds a new item to the end of the child list
985 void JSON::AddItem(const char *string, JSON *item)
986 {
987 if (item)
988 {
989 item->Name = string;
990 Children.PushBack(item);
991 }
992 }
994 /*
996 // Removes and frees the items at the given index
997 void JSON::DeleteItem(unsigned int index)
998 {
999 unsigned int num_items = 0;
1000 JSON* child = Children.GetFirst();
1001 while (!Children.IsNull(child) && num_items < index)
1003 num_items++;
1004 child = Children.GetNext(child);
1007 if (!Children.IsNull(child))
1009 child->RemoveNode();
1010 child->Release();
1014 // Replaces and frees the item at the give index with the new item
1015 void JSON::ReplaceItem(unsigned int index, JSON* new_item)
1017 unsigned int num_items = 0;
1018 JSON* child = Children.GetFirst();
1019 while (!Children.IsNull(child) && num_items < index)
1021 num_items++;
1022 child = Children.GetNext(child);
1025 if (!Children.IsNull(child))
1027 child->ReplaceNodeWith(new_item);
1028 child->Release();
1031 */
1033 // Removes and frees the last child item
1034 void JSON::RemoveLast()
1036 JSON* child = Children.GetLast();
1037 if (!Children.IsNull(child))
1039 child->RemoveNode();
1040 child->Release();
1044 JSON* JSON::CreateBool(bool b)
1046 JSON *item = new JSON(JSON_Bool);
1047 if (item)
1049 item->dValue = b ? 1. : 0.;
1050 item->Value = b ? "true" : "false";
1052 return item;
1055 JSON* JSON::CreateNumber(double num)
1057 JSON *item = new JSON(JSON_Number);
1058 if (item)
1060 item->dValue = num;
1062 return item;
1065 JSON* JSON::CreateInt(int num)
1067 JSON *item = new JSON(JSON_Number);
1068 if (item)
1070 item->dValue = num;
1072 return item;
1075 JSON* JSON::CreateString(const char *s)
1077 JSON *item = new JSON(JSON_String);
1078 if (item && s)
1080 item->Value = s;
1082 return item;
1086 //-----------------------------------------------------------------------------
1087 // Get elements by name
1088 double JSON::GetNumberByName(const char *name, double defValue)
1090 JSON* item = GetItemByName(name);
1091 if (!item || item->Type != JSON_Number)
1093 return defValue;
1095 else
1097 return item->dValue;
1101 int JSON::GetIntByName(const char *name, int defValue)
1103 JSON* item = GetItemByName(name);
1104 if (!item || item->Type != JSON_Number)
1106 return defValue;
1108 else
1110 return (int)item->dValue;
1114 bool JSON::GetBoolByName(const char *name, bool defValue)
1116 JSON* item = GetItemByName(name);
1117 if (!item || item->Type != JSON_Bool)
1119 return defValue;
1121 else
1123 return (int)item->dValue != 0;
1127 String JSON::GetStringByName(const char *name, const String &defValue)
1129 JSON* item = GetItemByName(name);
1130 if (!item || item->Type != JSON_String)
1132 return defValue;
1134 else
1136 return item->Value;
1140 //-----------------------------------------------------------------------------
1141 // Adds an element to an array object type
1142 void JSON::AddArrayElement(JSON *item)
1144 if (item)
1146 Children.PushBack(item);
1150 // Inserts an element into a valid array position
1151 void JSON::InsertArrayElement(int index, JSON *item)
1153 if (!item)
1155 return;
1158 if (index == 0)
1160 Children.PushFront(item);
1161 return;
1164 JSON* iter = Children.GetFirst();
1165 int i=0;
1166 while (iter && i<index)
1168 iter = Children.GetNext(iter);
1169 i++;
1172 if (iter)
1173 iter->InsertNodeBefore(item);
1174 else
1175 Children.PushBack(item);
1178 // Returns the size of an array
1179 int JSON::GetArraySize()
1181 if (Type == JSON_Array)
1183 return GetItemCount();
1186 return 0;
1189 // Returns the number value an the give array index
1190 double JSON::GetArrayNumber(int index)
1192 if (Type == JSON_Array)
1194 JSON* number = GetItemByIndex(index);
1195 return number ? number->dValue : 0.0;
1198 return 0;
1201 // Returns the string value at the given array index
1202 const char* JSON::GetArrayString(int index)
1204 if (Type == JSON_Array)
1206 JSON* number = GetItemByIndex(index);
1207 return number ? number->Value : 0;
1210 return 0;
1213 JSON* JSON::Copy()
1215 JSON* copy = new JSON(Type);
1216 copy->Name = Name;
1217 copy->Value = Value;
1218 copy->dValue = dValue;
1220 JSON* child = Children.GetFirst();
1221 while (!Children.IsNull(child))
1223 copy->Children.PushBack(child->Copy());
1224 child = Children.GetNext(child);
1227 return copy;
1230 //-----------------------------------------------------------------------------
1231 // Loads and parses the given JSON file pathname and returns a JSON object tree.
1232 // The returned object must be Released after use.
1233 JSON* JSON::Load(const char* path, const char** perror)
1235 SysFile f;
1236 if (!f.Open(path, File::Open_Read, File::Mode_Read))
1238 AssignError(perror, "Failed to open file");
1239 return NULL;
1242 int len = f.GetLength();
1243 uint8_t* buff = (uint8_t*)OVR_ALLOC(len + 1);
1244 int bytes = f.Read(buff, len);
1245 f.Close();
1247 if (bytes == 0 || bytes != len)
1249 OVR_FREE(buff);
1250 return NULL;
1253 // Ensure the result is null-terminated since Parse() expects null-terminated input.
1254 buff[len] = '\0';
1256 JSON* json = JSON::Parse((char*)buff, perror);
1257 OVR_FREE(buff);
1258 return json;
1261 //-----------------------------------------------------------------------------
1262 // Serializes the JSON object and writes to the give file path
1263 bool JSON::Save(const char* path)
1265 SysFile f;
1266 if (!f.Open(path, File::Open_Write | File::Open_Create | File::Open_Truncate, File::Mode_Write))
1267 return false;
1269 char* text = PrintValue(0, true);
1270 if (text)
1272 intptr_t len = OVR_strlen(text);
1273 OVR_ASSERT(len <= (intptr_t)(int)len);
1275 int bytes = f.Write((uint8_t*)text, (int)len);
1276 f.Close();
1277 OVR_FREE(text);
1278 return (bytes == len);
1280 else
1282 return false;
1287 } // namespace OVR