OVR_JSON.cpp
Go to the documentation of this file.
00001 /************************************************************************************
00002 
00003 PublicHeader:   None
00004 Filename    :   OVR_JSON.h
00005 Content     :   JSON format reader and writer
00006 Created     :   April 9, 2013
00007 Author      :   Brant Lewis
00008 Notes       :
00009   The code is a derivative of the cJSON library written by Dave Gamble and subject 
00010   to the following permissive copyright.
00011 
00012   Copyright (c) 2009 Dave Gamble
00013  
00014   Permission is hereby granted, free of charge, to any person obtaining a copy
00015   of this software and associated documentation files (the "Software"), to deal
00016   in the Software without restriction, including without limitation the rights
00017   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00018   copies of the Software, and to permit persons to whom the Software is
00019   furnished to do so, subject to the following conditions:
00020  
00021   The above copyright notice and this permission notice shall be included in
00022   all copies or substantial portions of the Software.
00023  
00024   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00025   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00026   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00027   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00028   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00029   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00030   THE SOFTWARE.
00031 
00032 
00033 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
00034 
00035 Use of this software is subject to the terms of the Oculus license
00036 agreement provided at the time of installation or download, or which
00037 otherwise accompanies this software in either electronic or hard copy form.
00038 
00039 ************************************************************************************/
00040 
00041 #include <string.h>
00042 #include <stdio.h>
00043 #include <math.h>
00044 #include <stdlib.h>
00045 #include <float.h>
00046 #include <limits.h>
00047 #include <ctype.h>
00048 #include "OVR_JSON.h"
00049 #include "Kernel/OVR_SysFile.h"
00050 #include "Kernel/OVR_Log.h"
00051 
00052 namespace OVR {
00053 
00054 
00055 //-----------------------------------------------------------------------------
00056 // Create a new copy of a string
00057 static char* JSON_strdup(const char* str)
00058 {
00059     UPInt len  = OVR_strlen(str) + 1;
00060     char* copy = (char*)OVR_ALLOC(len);
00061     if (!copy)
00062         return 0;
00063     memcpy(copy, str, len);
00064     return copy;
00065 }
00066 
00067 
00068 //-----------------------------------------------------------------------------
00069 // Render the number from the given item into a string.
00070 static char* PrintNumber(double d)
00071 {
00072         char *str;
00073         //double d=item->valuedouble;
00074     int valueint = (int)d;
00075         if (fabs(((double)valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
00076         {
00077                 str=(char*)OVR_ALLOC(21);       // 2^64+1 can be represented in 21 chars.
00078                 if (str)
00079             OVR_sprintf(str, 21, "%d", valueint);
00080         }
00081         else
00082         {
00083                 str=(char*)OVR_ALLOC(64);       // This is a nice tradeoff.
00084                 if (str)
00085                 {
00086                         if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)
00087                 OVR_sprintf(str, 64, "%.0f", d);
00088                         else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)
00089                 OVR_sprintf(str, 64, "%e", d);
00090                         else
00091                 OVR_sprintf(str, 64, "%f", d);
00092                 }
00093         }
00094         return str;
00095 }
00096 
00097 // Parse the input text into an un-escaped cstring, and populate item.
00098 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
00099 
00100 // Helper to assign error sting and return 0.
00101 const char* AssignError(const char** perror, const char *errorMessage)
00102 {
00103     if (perror)
00104         *perror = errorMessage;
00105     return 0;
00106 }
00107 
00108 //-----------------------------------------------------------------------------
00109 // ***** JSON Node class
00110 
00111 JSON::JSON(JSONItemType itemType)
00112     : Type(itemType), dValue(0.0)
00113 {
00114 }
00115 
00116 JSON::~JSON()
00117 {
00118     JSON* child = Children.GetFirst();
00119     while (!Children.IsNull(child))
00120     {
00121         child->RemoveNode();
00122         child->Release();
00123         child = Children.GetFirst();
00124     }
00125 }
00126 
00127 //-----------------------------------------------------------------------------
00128 // Parse the input text to generate a number, and populate the result into item
00129 // Returns the text position after the parsed number
00130 const char* JSON::parseNumber(const char *num)
00131 {
00132     const char* num_start = num;
00133     double      n=0, sign=1, scale=0;
00134     int         subscale     = 0,
00135                 signsubscale = 1;
00136 
00137         // Could use sscanf for this?
00138         if (*num=='-') 
00139         sign=-1,num++;  // Has sign?
00140         if (*num=='0')
00141         num++;                  // is zero
00142         
00143     if (*num>='1' && *num<='9') 
00144     {
00145         do
00146         {   
00147             n=(n*10.0)+(*num++ -'0');
00148         }
00149         while (*num>='0' && *num<='9'); // Number?
00150     }
00151 
00152         if (*num=='.' && num[1]>='0' && num[1]<='9')
00153     {
00154         num++;
00155         do
00156         {
00157             n=(n*10.0)+(*num++ -'0');
00158             scale--;
00159         }
00160         while (*num>='0' && *num<='9');  // Fractional part?
00161     }
00162 
00163         if (*num=='e' || *num=='E')             // Exponent?
00164         {
00165         num++;
00166         if (*num=='+')
00167             num++;
00168         else if (*num=='-')
00169         {
00170             signsubscale=-1;
00171             num++;              // With sign?
00172         }
00173 
00174                 while (*num>='0' && *num<='9')
00175             subscale=(subscale*10)+(*num++ - '0');      // Number?
00176         }
00177 
00178     // Number = +/- number.fraction * 10^+/- exponent
00179         n = sign*n*pow(10.0,(scale+subscale*signsubscale));
00180 
00181     // Assign parsed value.
00182         Type   = JSON_Number;
00183     dValue = n;
00184     Value.AssignString(num_start, num - num_start);
00185     
00186         return num;
00187 }
00188 
00189 // Parses a hex string up to the specified number of digits.
00190 // Returns the first character after the string.
00191 const char* ParseHex(unsigned* val, unsigned digits, const char* str)
00192 {
00193     *val = 0;
00194 
00195     for(unsigned digitCount = 0; digitCount < digits; digitCount++, str++)
00196     {
00197         unsigned v = *str;
00198 
00199         if ((v >= '0') && (v <= '9'))
00200             v -= '0';
00201         else if ((v >= 'a') && (v <= 'f'))
00202             v = 10 + v - 'a';
00203         else if ((v >= 'A') && (v <= 'F'))
00204             v = 10 + v - 'A';
00205         else
00206             break;
00207 
00208         *val = *val * 16 + v;
00209     }
00210 
00211     return str;
00212 }
00213 
00214 //-----------------------------------------------------------------------------
00215 // Parses the input text into a string item and returns the text position after
00216 // the parsed string
00217 const char* JSON::parseString(const char* str, const char** perror)
00218 {
00219         const char* ptr = str+1;
00220     const char* p;
00221     char*       ptr2;
00222     char*       out;
00223     int         len=0;
00224     unsigned    uc, uc2;
00225         
00226     if (*str!='\"')
00227     {
00228         return AssignError(perror, "Syntax Error: Missing quote");
00229     }
00230         
00231         while (*ptr!='\"' && *ptr && ++len)
00232     {   
00233         if (*ptr++ == '\\') ptr++;      // Skip escaped quotes.
00234     }
00235         
00236     // This is how long we need for the string, roughly.
00237         out=(char*)OVR_ALLOC(len+1);
00238         if (!out)
00239         return 0;
00240         
00241         ptr = str+1;
00242     ptr2= out;
00243 
00244         while (*ptr!='\"' && *ptr)
00245         {
00246                 if (*ptr!='\\')
00247         {
00248             *ptr2++ = *ptr++;
00249         }
00250                 else
00251                 {
00252                         ptr++;
00253                         switch (*ptr)
00254                         {
00255                                 case 'b': *ptr2++ = '\b';       break;
00256                                 case 'f': *ptr2++ = '\f';       break;
00257                                 case 'n': *ptr2++ = '\n';       break;
00258                                 case 'r': *ptr2++ = '\r';       break;
00259                                 case 't': *ptr2++ = '\t';       break;
00260 
00261                 // Transcode utf16 to utf8.
00262                 case 'u':
00263 
00264                     // Get the unicode char.
00265                     p = ParseHex(&uc, 4, ptr + 1);
00266                     if (ptr != p)
00267                         ptr = p - 1;
00268 
00269                                         if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)
00270                         break;  // Check for invalid.
00271 
00272                     // UTF16 surrogate pairs.
00273                                         if (uc>=0xD800 && uc<=0xDBFF)
00274                                         {
00275                                                 if (ptr[1]!='\\' || ptr[2]!='u')
00276                             break;      // Missing second-half of surrogate.
00277 
00278                         p= ParseHex(&uc2, 4, ptr + 3);
00279                         if (ptr != p)
00280                             ptr = p - 1;
00281                         
00282                                                 if (uc2<0xDC00 || uc2>0xDFFF)
00283                             break;      // Invalid second-half of surrogate.
00284 
00285                                                 uc = 0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
00286                                         }
00287 
00288                                         len=4;
00289                     
00290                     if (uc<0x80)
00291                         len=1;
00292                     else if (uc<0x800)
00293                         len=2;
00294                     else if (uc<0x10000)
00295                         len=3;
00296                     
00297                     ptr2+=len;
00298                                         
00299                                         switch (len)
00300                     {
00301                                                 case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
00302                                                 case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
00303                                                 case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
00304                                                 case 1: *--ptr2 = (char)(uc | firstByteMark[len]);
00305                                         }
00306                                         ptr2+=len;
00307                                         break;
00308 
00309                 default:
00310                     *ptr2++ = *ptr;
00311                     break;
00312                         }
00313                         ptr++;
00314                 }
00315         }
00316 
00317         *ptr2 = 0;
00318         if (*ptr=='\"')
00319         ptr++;
00320         
00321     // Make a copy of the string 
00322     Value=out;
00323     OVR_FREE(out);
00324         Type=JSON_String;
00325 
00326         return ptr;
00327 }
00328 
00329 //-----------------------------------------------------------------------------
00330 // Render the string provided to an escaped version that can be printed.
00331 char* PrintString(const char* str)
00332 {
00333         const char *ptr;
00334     char *ptr2,*out;
00335     int len=0;
00336     unsigned char token;
00337         
00338         if (!str)
00339         return JSON_strdup("");
00340         ptr=str;
00341     
00342     token=*ptr;
00343     while (token && ++len)\
00344     {
00345         if (strchr("\"\\\b\f\n\r\t",token))
00346             len++;
00347         else if (token<32) 
00348             len+=5;
00349         ptr++;
00350         token=*ptr;
00351     }
00352         
00353         int buff_size = len+3;
00354     out=(char*)OVR_ALLOC(buff_size);
00355         if (!out)
00356         return 0;
00357 
00358         ptr2 = out;
00359     ptr  = str;
00360         *ptr2++ = '\"';
00361 
00362         while (*ptr)
00363         {
00364                 if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') 
00365             *ptr2++=*ptr++;
00366                 else
00367                 {
00368                         *ptr2++='\\';
00369                         switch (token=*ptr++)
00370                         {
00371                                 case '\\':      *ptr2++='\\';   break;
00372                                 case '\"':      *ptr2++='\"';   break;
00373                                 case '\b':      *ptr2++='b';    break;
00374                                 case '\f':      *ptr2++='f';    break;
00375                                 case '\n':      *ptr2++='n';    break;
00376                                 case '\r':      *ptr2++='r';    break;
00377                                 case '\t':      *ptr2++='t';    break;
00378                                 default: 
00379                     OVR_sprintf(ptr2, buff_size - (ptr2-out), "u%04x",token);
00380                     ptr2+=5;
00381                     break;      // Escape and print.
00382                         }
00383                 }
00384         }
00385         *ptr2++='\"';
00386     *ptr2++=0;
00387         return out;
00388 }
00389 
00390 //-----------------------------------------------------------------------------
00391 // Utility to jump whitespace and cr/lf
00392 static const char* skip(const char* in)
00393 {
00394     while (in && *in && (unsigned char)*in<=' ') 
00395         in++; 
00396     return in;
00397 }
00398 
00399 //-----------------------------------------------------------------------------
00400 // Parses the supplied buffer of JSON text and returns a JSON object tree
00401 // The returned object must be Released after use
00402 JSON* JSON::Parse(const char* buff, const char** perror)
00403 {
00404     const char* end = 0;
00405         JSON*       json = new JSON();
00406         
00407         if (!json)
00408     {
00409         AssignError(perror, "Error: Failed to allocate memory");
00410         return 0;
00411     }
00412  
00413         end = json->parseValue(skip(buff), perror);
00414         if (!end)
00415     {
00416         json->Release();
00417         return NULL;
00418     }   // parse failure. ep is set.
00419 
00420     return json;
00421 }
00422 
00423 //-----------------------------------------------------------------------------
00424 // Parser core - when encountering text, process appropriately.
00425 const char* JSON::parseValue(const char* buff, const char** perror)
00426 {
00427     if (perror)
00428         *perror = 0;
00429 
00430         if (!buff)
00431         return NULL;    // Fail on null.
00432 
00433         if (!strncmp(buff,"null",4))
00434     {
00435         Type = JSON_Null;
00436         return buff+4;
00437     }
00438         if (!strncmp(buff,"false",5))
00439     { 
00440         Type   = JSON_Bool;
00441         Value  = "false";
00442         dValue = 0;
00443         return buff+5;
00444     }
00445         if (!strncmp(buff,"true",4))
00446     {
00447         Type   = JSON_Bool;
00448         Value  = "true";
00449         dValue = 1;
00450         return buff+4;
00451     }
00452         if (*buff=='\"')
00453     {
00454         return parseString(buff, perror);
00455     }
00456         if (*buff=='-' || (*buff>='0' && *buff<='9'))
00457     { 
00458         return parseNumber(buff);
00459     }
00460         if (*buff=='[')
00461     { 
00462         return parseArray(buff, perror);
00463     }
00464         if (*buff=='{')
00465     {
00466         return parseObject(buff, perror);
00467     }
00468 
00469     return AssignError(perror, "Syntax Error: Invalid syntax");
00470 }
00471 
00472 
00473 //-----------------------------------------------------------------------------
00474 // Render a value to text. 
00475 char* JSON::PrintValue(int depth, bool fmt)
00476 {
00477         char *out=0;
00478 
00479     switch (Type)
00480         {
00481         case JSON_Null:     out = JSON_strdup("null");  break;
00482         case JSON_Bool:
00483             if (dValue == 0)
00484                 out = JSON_strdup("false");
00485             else
00486                 out = JSON_strdup("true");
00487             break;
00488         case JSON_Number:       out = PrintNumber(dValue); break;
00489         case JSON_String:       out = PrintString(Value); break;
00490         case JSON_Array:        out = PrintArray(depth, fmt); break;
00491         case JSON_Object:       out = PrintObject(depth, fmt); break;
00492         case JSON_None: OVR_ASSERT_LOG(false, ("Bad JSON type.")); break;
00493         }
00494         return out;
00495 }
00496 
00497 //-----------------------------------------------------------------------------
00498 // Build an array object from input text and returns the text position after
00499 // the parsed array
00500 const char* JSON::parseArray(const char* buff, const char** perror)
00501 {
00502         JSON *child;
00503         if (*buff!='[')
00504     {
00505         return AssignError(perror, "Syntax Error: Missing opening bracket");
00506     }
00507 
00508         Type=JSON_Array;
00509         buff=skip(buff+1);
00510         
00511     if (*buff==']')
00512         return buff+1;  // empty array.
00513 
00514     child = new JSON();
00515         if (!child)
00516         return 0;                // memory fail
00517     Children.PushBack(child);
00518         
00519     buff=skip(child->parseValue(skip(buff), perror));   // skip any spacing, get the buff. 
00520         if (!buff)
00521         return 0;
00522 
00523         while (*buff==',')
00524         {
00525                 JSON *new_item = new JSON();
00526                 if (!new_item)
00527             return AssignError(perror, "Error: Failed to allocate memory");
00528                 
00529         Children.PushBack(new_item);
00530 
00531                 buff=skip(new_item->parseValue(skip(buff+1), perror));
00532                 if (!buff)
00533             return AssignError(perror, "Error: Failed to allocate memory");
00534         }
00535 
00536         if (*buff==']')
00537         return buff+1;  // end of array
00538 
00539     return AssignError(perror, "Syntax Error: Missing ending bracket");
00540 }
00541 
00542 //-----------------------------------------------------------------------------
00543 // Render an array to text.  The returned text must be freed
00544 char* JSON::PrintArray(int depth, bool fmt)
00545 {
00546         char **entries;
00547         char * out = 0,*ptr,*ret;
00548     SPInt  len = 5;
00549         
00550     bool fail = false;
00551         
00552         // How many entries in the array? 
00553     int numentries = GetItemCount();
00554         if (!numentries)
00555         {
00556                 out=(char*)OVR_ALLOC(3);
00557                 if (out)
00558             OVR_strcpy(out, 3, "[]");
00559                 return out;
00560         }
00561         // Allocate an array to hold the values for each
00562         entries=(char**)OVR_ALLOC(numentries*sizeof(char*));
00563         if (!entries)
00564         return 0;
00565         memset(entries,0,numentries*sizeof(char*));
00566 
00568     JSON* child = Children.GetFirst();
00569     for (int i=0; i<numentries; i++)
00570         {
00571                 //JSON* child = Children[i];
00572         ret=child->PrintValue(depth+1, fmt);
00573                 entries[i]=ret;
00574                 if (ret)
00575             len+=OVR_strlen(ret)+2+(fmt?1:0);
00576         else
00577         {
00578             fail = true;
00579             break;
00580         }
00581         child = Children.GetNext(child);
00582         }
00583         
00584         // If we didn't fail, try to malloc the output string 
00585         if (!fail)
00586         out=(char*)OVR_ALLOC(len);
00587         // If that fails, we fail. 
00588         if (!out)
00589         fail = true;
00590 
00591         // Handle failure.
00592         if (fail)
00593         {
00594                 for (int i=0; i<numentries; i++) 
00595         {
00596             if (entries[i])
00597                 OVR_FREE(entries[i]);
00598         }
00599                 OVR_FREE(entries);
00600                 return 0;
00601         }
00602         
00603         // Compose the output array.
00604         *out='[';
00605         ptr=out+1;
00606     *ptr=0;
00607         for (int i=0; i<numentries; i++)
00608         {
00609                 OVR_strcpy(ptr, len - (ptr-out), entries[i]);
00610         ptr+=OVR_strlen(entries[i]);
00611                 if (i!=numentries-1)
00612         {
00613             *ptr++=',';
00614             if (fmt)
00615                 *ptr++=' ';
00616             *ptr=0;
00617         }
00618                 OVR_FREE(entries[i]);
00619         }
00620         OVR_FREE(entries);
00621         *ptr++=']';
00622     *ptr++=0;
00623         return out;     
00624 }
00625 
00626 //-----------------------------------------------------------------------------
00627 // Build an object from the supplied text and returns the text position after
00628 // the parsed object
00629 const char* JSON::parseObject(const char* buff, const char** perror)
00630 {
00631         if (*buff!='{')
00632     {
00633         return AssignError(perror, "Syntax Error: Missing opening brace");
00634     }
00635         
00636         Type=JSON_Object;
00637         buff=skip(buff+1);
00638         if (*buff=='}')
00639         return buff+1;  // empty array.
00640         
00641     JSON* child = new JSON();
00642     Children.PushBack(child);
00643 
00644         buff=skip(child->parseString(skip(buff), perror));
00645         if (!buff) 
00646         return 0;
00647         child->Name = child->Value;
00648     child->Value.Clear();
00649         
00650     if (*buff!=':')
00651     {
00652         return AssignError(perror, "Syntax Error: Missing colon");
00653     }
00654 
00655         buff=skip(child->parseValue(skip(buff+1), perror));     // skip any spacing, get the value.
00656         if (!buff)
00657         return 0;
00658         
00659         while (*buff==',')
00660         {
00661         child = new JSON();
00662                 if (!child)
00663             return 0; // memory fail
00664                 
00665         Children.PushBack(child);
00666 
00667                 buff=skip(child->parseString(skip(buff+1), perror));
00668                 if (!buff)
00669             return 0;
00670                 
00671         child->Name=child->Value;
00672         child->Value.Clear();
00673                 
00674         if (*buff!=':')
00675         {
00676             return AssignError(perror, "Syntax Error: Missing colon");
00677         }       // fail!
00678                 
00679         // Skip any spacing, get the value.
00680         buff=skip(child->parseValue(skip(buff+1), perror));
00681                 if (!buff)
00682             return 0;
00683         }
00684         
00685         if (*buff=='}')
00686         return buff+1;  // end of array 
00687         
00688     return AssignError(perror, "Syntax Error: Missing closing brace");
00689 }
00690 
00691 //-----------------------------------------------------------------------------
00692 // Render an object to text.  The returned string must be freed
00693 char* JSON::PrintObject(int depth, bool fmt)
00694 {
00695         char** entries = 0, **names = 0;
00696         char*  out = 0;
00697     char*  ptr, *ret, *str;
00698     SPInt  len = 7, i = 0, j;
00699     bool   fail = false;
00700         
00701     // Count the number of entries.
00702     int numentries = GetItemCount();
00703     
00704         // Explicitly handle empty object case
00705         if (numentries == 0)
00706         {
00707                 out=(char*)OVR_ALLOC(fmt?depth+3:3);
00708                 if (!out)
00709             return 0;
00710                 ptr=out;
00711         *ptr++='{';
00712                 
00713         if (fmt)
00714         {
00715             *ptr++='\n';
00716             for (i=0;i<depth-1;i++)
00717                 *ptr++='\t';
00718         }
00719                 *ptr++='}';
00720         *ptr++=0;
00721                 return out;
00722         }
00723         // Allocate space for the names and the objects
00724         entries=(char**)OVR_ALLOC(numentries*sizeof(char*));
00725         if (!entries)
00726         return 0;
00727         names=(char**)OVR_ALLOC(numentries*sizeof(char*));
00728         
00729     if (!names)
00730     {
00731         OVR_FREE(entries);
00732         return 0;
00733     }
00734         memset(entries,0,sizeof(char*)*numentries);
00735         memset(names,0,sizeof(char*)*numentries);
00736 
00737         // Collect all the results into our arrays:
00738     depth++;
00739     if (fmt)
00740         len+=depth;
00741 
00742     JSON* child = Children.GetFirst();
00743     while (!Children.IsNull(child))
00744         {
00745                 names[i]     = str = PrintString(child->Name);
00746                 entries[i++] = ret = child->PrintValue(depth, fmt);
00747 
00748                 if (str && ret)
00749         {
00750             len += OVR_strlen(ret)+OVR_strlen(str)+2+(fmt?2+depth:0);
00751         }
00752         else
00753         {
00754             fail = true;
00755             break;
00756         }
00757                 
00758         child = Children.GetNext(child);
00759         }
00760         
00761         // Try to allocate the output string
00762         if (!fail)
00763         out=(char*)OVR_ALLOC(len);
00764         if (!out)
00765         fail=true;
00766 
00767         // Handle failure
00768         if (fail)
00769         {
00770                 for (i=0;i<numentries;i++)
00771         {
00772             if (names[i])
00773                 OVR_FREE(names[i]);
00774             
00775             if (entries[i])
00776                 OVR_FREE(entries[i]);}
00777                 
00778         OVR_FREE(names);
00779         OVR_FREE(entries);
00780                 return 0;
00781         }
00782         
00783         // Compose the output:
00784         *out = '{';
00785     ptr  = out+1;
00786     if (fmt)
00787         *ptr++='\n';
00788     *ptr = 0;
00789         
00790     for (i=0; i<numentries; i++)
00791         {
00792                 if (fmt)
00793         {
00794             for (j=0; j<depth; j++)
00795                 *ptr++ = '\t';
00796         }
00797                 OVR_strcpy(ptr, len - (ptr-out), names[i]);
00798         ptr   += OVR_strlen(names[i]);
00799                 *ptr++ =':';
00800         
00801         if (fmt)
00802             *ptr++='\t';
00803                 
00804         OVR_strcpy(ptr, len - (ptr-out), entries[i]);
00805         ptr+=OVR_strlen(entries[i]);
00806                 
00807         if (i!=numentries-1)
00808             *ptr++ = ',';
00809                 
00810         if (fmt)
00811             *ptr++ = '\n';
00812         *ptr = 0;
00813                 
00814         OVR_FREE(names[i]);
00815         OVR_FREE(entries[i]);
00816         }
00817         
00818         OVR_FREE(names);
00819     OVR_FREE(entries);
00820         
00821     if (fmt)
00822     {
00823         for (i=0;i<depth-1;i++)
00824             *ptr++='\t';
00825     }
00826         *ptr++='}';
00827     *ptr++=0;
00828         
00829     return out; 
00830 }
00831 
00832 
00833 
00834 // Returns the number of child items in the object
00835 // Counts the number of items in the object.
00836 unsigned JSON::GetItemCount() const
00837 {
00838     unsigned count = 0;
00839     for(const JSON* p = Children.GetFirst(); !Children.IsNull(p); p = p->pNext)
00840         count++;
00841     return count;
00842 }
00843 
00844 JSON* JSON::GetItemByIndex(unsigned index)
00845 {
00846     unsigned i     = 0;
00847     JSON*    child = 0;
00848 
00849     if (!Children.IsEmpty())
00850     {
00851         child = Children.GetFirst();
00852 
00853         while (i < index)
00854         {   
00855             if (Children.IsNull(child->pNext))
00856             {
00857                 child = 0;
00858                 break;
00859             }
00860             child = child->pNext;
00861             i++;
00862         }
00863     }
00864   
00865     return child;
00866 }
00867 
00868 // Returns the child item with the given name or NULL if not found
00869 JSON* JSON::GetItemByName(const char* name)
00870 {
00871     JSON* child = 0;
00872 
00873     if (!Children.IsEmpty())
00874     {
00875         child = Children.GetFirst();
00876 
00877         while (OVR_strcmp(child->Name, name) != 0)
00878         {   
00879             if (Children.IsNull(child->pNext))
00880             {
00881                 child = 0;
00882                 break;
00883             }
00884             child = child->pNext;
00885         }
00886     }
00887 
00888     return child;
00889 }
00890 
00891 //-----------------------------------------------------------------------------
00892 // Adds a new item to the end of the child list
00893 void JSON::AddItem(const char *string, JSON *item)
00894 {
00895     if (!item)
00896         return;
00897  
00898     item->Name = string;
00899     Children.PushBack(item);
00900 }
00901 
00902 /*
00903 
00904 // Removes and frees the items at the given index
00905 void JSON::DeleteItem(unsigned int index)
00906 {
00907     unsigned int num_items = 0;
00908     JSON* child = Children.GetFirst();
00909     while (!Children.IsNull(child) && num_items < index)
00910     {   
00911         num_items++;
00912         child = Children.GetNext(child);
00913     }
00914 
00915     if (!Children.IsNull(child))
00916     
00917         child->RemoveNode();
00918         child->Release();
00919     }
00920 }
00921 
00922 // Replaces and frees the item at the give index with the new item
00923 void JSON::ReplaceItem(unsigned int index, JSON* new_item)
00924 {
00925     unsigned int num_items = 0;
00926     JSON* child = Children.GetFirst();
00927     while (!Children.IsNull(child) && num_items < index)
00928     {   
00929         num_items++;
00930         child = Children.GetNext(child);
00931     }
00932 
00933     if (!Children.IsNull(child))
00934     {
00935         child->ReplaceNodeWith(new_item);
00936         child->Release();        
00937     }
00938 }
00939 */
00940 
00941 // Helper function to simplify creation of a typed object
00942 JSON* JSON::createHelper(JSONItemType itemType, double dval, const char* strVal)
00943 {
00944     JSON *item = new JSON(itemType);
00945     if (item)
00946     {
00947         item->dValue = dval;
00948         if (strVal)
00949             item->Value = strVal;
00950     }
00951     return item;
00952 }
00953 
00954 
00955 //-----------------------------------------------------------------------------
00956 // Adds an element to an array object type
00957 void JSON::AddArrayElement(JSON *item)
00958 {
00959     if (!item)
00960         return;
00961 
00962     Children.PushBack(item);
00963 }
00964 
00965 
00966 // Returns the size of an array
00967 int JSON::GetArraySize()
00968 {
00969     if (Type == JSON_Array)
00970         return GetItemCount();
00971     else
00972         return 0;
00973 }
00974 
00975 // Returns the number value an the give array index
00976 double JSON::GetArrayNumber(int index)
00977 {
00978     if (Type == JSON_Array)
00979     {
00980         JSON* number = GetItemByIndex(index);
00981         return number ? number->dValue : 0.0;
00982     }
00983     else
00984     {
00985         return 0;
00986     }
00987 }
00988 
00989 // Returns the string value at the given array index
00990 const char* JSON::GetArrayString(int index)
00991 {
00992     if (Type == JSON_Array)
00993     {
00994         JSON* number = GetItemByIndex(index);
00995         return number ? number->Value : 0;
00996     }
00997     else
00998     {
00999         return 0;
01000     }
01001 }
01002 
01003 //-----------------------------------------------------------------------------
01004 // Loads and parses the given JSON file pathname and returns a JSON object tree.
01005 // The returned object must be Released after use.
01006 JSON* JSON::Load(const char* path, const char** perror)
01007 {
01008     SysFile f;
01009     if (!f.Open(path, File::Open_Read, File::Mode_Read))
01010     {
01011         AssignError(perror, "Failed to open file");
01012         return NULL;
01013     }
01014 
01015     int    len   = f.GetLength();
01016     UByte* buff  = (UByte*)OVR_ALLOC(len);
01017     int    bytes = f.Read(buff, len);
01018     f.Close();
01019 
01020     if (bytes == 0 || bytes != len)
01021     {
01022         OVR_FREE(buff);
01023         return NULL;
01024     }
01025 
01026     JSON* json = JSON::Parse((char*)buff, perror);
01027     OVR_FREE(buff);
01028     return json;
01029 }
01030 
01031 //-----------------------------------------------------------------------------
01032 // Serializes the JSON object and writes to the give file path
01033 bool JSON::Save(const char* path)
01034 {
01035     SysFile f;
01036     if (!f.Open(path, File::Open_Write | File::Open_Create | File::Open_Truncate, File::Mode_Write))
01037         return false;
01038 
01039     char* text = PrintValue(0, true);
01040     if (text)
01041     {
01042         SPInt len   = OVR_strlen(text);
01043         OVR_ASSERT(len < (SPInt)(int)len);
01044 
01045         int   bytes = f.Write((UByte*)text, (int)len);
01046         f.Close();
01047         OVR_FREE(text);
01048         return (bytes == len);
01049     }
01050     else
01051     {
01052         return false;
01053     }
01054 }
01055 
01056 }


oculus_sdk
Author(s):
autogenerated on Mon Oct 6 2014 03:01:18