Annotation of embedaddon/iperf/src/cjson.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:   Copyright (c) 2009 Dave Gamble
                      3: 
                      4:   Permission is hereby granted, free of charge, to any person obtaining a copy
                      5:   of this software and associated documentation files (the "Software"), to deal
                      6:   in the Software without restriction, including without limitation the rights
                      7:   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                      8:   copies of the Software, and to permit persons to whom the Software is
                      9:   furnished to do so, subject to the following conditions:
                     10: 
                     11:   The above copyright notice and this permission notice shall be included in
                     12:   all copies or substantial portions of the Software.
                     13: 
                     14:   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     15:   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     16:   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
                     17:   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     18:   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     19:   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     20:   THE SOFTWARE.
                     21: */
                     22: 
                     23: /* cJSON */
                     24: /* JSON parser in C. */
                     25: 
                     26: #include <string.h>
                     27: #include <stdio.h>
                     28: #include <math.h>
                     29: #include <stdlib.h>
                     30: #include <float.h>
                     31: #include <limits.h>
                     32: #include <ctype.h>
                     33: #ifdef HAVE_STDINT_H
                     34: #include <stdint.h> 
                     35: #endif
                     36: #include <sys/types.h>
                     37: #include "cjson.h"
                     38: 
                     39: #ifndef LLONG_MAX
                     40: #define LLONG_MAX 9223372036854775807LL
                     41: #endif
                     42: #ifndef LLONG_MIN
                     43: #define LLONG_MIN (-LLONG_MAX - 1LL)
                     44: #endif
                     45: static const char *global_ep;
                     46: 
                     47: const char *cJSON_GetErrorPtr(void) {return global_ep;}
                     48: 
                     49: static int cJSON_strcasecmp(const char *s1,const char *s2)
                     50: {
                     51:        if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
                     52:        for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0)    return 0;
                     53:        return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
                     54: }
                     55: 
                     56: static void *(*cJSON_malloc)(size_t sz) = malloc;
                     57: static void (*cJSON_free)(void *ptr) = free;
                     58: 
                     59: static char* cJSON_strdup(const char* str)
                     60: {
                     61:       size_t len;
                     62:       char* copy;
                     63: 
                     64:       len = strlen(str) + 1;
                     65:       if (!(copy = (char*)cJSON_malloc(len))) return 0;
                     66:       memcpy(copy,str,len);
                     67:       return copy;
                     68: }
                     69: 
                     70: void cJSON_InitHooks(cJSON_Hooks* hooks)
                     71: {
                     72:     if (!hooks) { /* Reset hooks */
                     73:         cJSON_malloc = malloc;
                     74:         cJSON_free = free;
                     75:         return;
                     76:     }
                     77: 
                     78:        cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
                     79:        cJSON_free       = (hooks->free_fn)?hooks->free_fn:free;
                     80: }
                     81: 
                     82: /* Internal constructor. */
                     83: static cJSON *cJSON_New_Item(void)
                     84: {
                     85:        cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
                     86:        if (node) memset(node,0,sizeof(cJSON));
                     87:        return node;
                     88: }
                     89: 
                     90: /* Delete a cJSON structure. */
                     91: void cJSON_Delete(cJSON *c)
                     92: {
                     93:        cJSON *next;
                     94:        while (c)
                     95:        {
                     96:                next=c->next;
                     97:                if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
                     98:                if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
                     99:                if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string);
                    100:                cJSON_free(c);
                    101:                c=next;
                    102:        }
                    103: }
                    104: 
                    105: /* Parse the input text to generate a number, and populate the result into item. */
                    106: static const char *parse_number(cJSON *item,const char *num)
                    107: {
                    108:        double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
                    109: 
                    110:        if (*num=='-') sign=-1,num++;   /* Has sign? */
                    111:        if (*num=='0') num++;                   /* is zero */
                    112:        if (*num>='1' && *num<='9')     do      n=(n*10.0)+(*num++ -'0');       while (*num>='0' && *num<='9'); /* Number? */
                    113:        if (*num=='.' && num[1]>='0' && num[1]<='9') {num++;            do      n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');}      /* Fractional part? */
                    114:        if (*num=='e' || *num=='E')             /* Exponent? */
                    115:        {       num++;if (*num=='+') num++;     else if (*num=='-') signsubscale=-1,num++;              /* With sign? */
                    116:                while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0');   /* Number? */
                    117:        }
                    118: 
                    119:        n=sign*n*pow(10.0,(scale+subscale*signsubscale));       /* number = +/- number.fraction * 10^+/- exponent */
                    120:        
                    121:        item->valuedouble=n;
                    122:        item->valueint=(int64_t)n;
                    123:        item->type=cJSON_Number;
                    124:        return num;
                    125: }
                    126: 
                    127: static int pow2gt (int x)      {       --x;    x|=x>>1;        x|=x>>2;        x|=x>>4;        x|=x>>8;        x|=x>>16;       return x+1;     }
                    128: 
                    129: typedef struct {char *buffer; int length; int offset; } printbuffer;
                    130: 
                    131: static char* ensure(printbuffer *p,int needed)
                    132: {
                    133:        char *newbuffer;int newsize;
                    134:        if (!p || !p->buffer) return 0;
                    135:        needed+=p->offset;
                    136:        if (needed<=p->length) return p->buffer+p->offset;
                    137: 
                    138:        newsize=pow2gt(needed);
                    139:        newbuffer=(char*)cJSON_malloc(newsize);
                    140:        if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;}
                    141:        if (newbuffer) memcpy(newbuffer,p->buffer,p->length);
                    142:        cJSON_free(p->buffer);
                    143:        p->length=newsize;
                    144:        p->buffer=newbuffer;
                    145:        return newbuffer+p->offset;
                    146: }
                    147: 
                    148: static int update(printbuffer *p)
                    149: {
                    150:        char *str;
                    151:        if (!p || !p->buffer) return 0;
                    152:        str=p->buffer+p->offset;
                    153:        return p->offset+strlen(str);
                    154: }
                    155: 
                    156: /* Render the number nicely from the given item into a string. */
                    157: static char *print_number(cJSON *item,printbuffer *p)
                    158: {
                    159:        char *str=0;
                    160:        double d=item->valuedouble;
                    161:        if (d==0)
                    162:        {
                    163:                if (p)  str=ensure(p,2);
                    164:                else    str=(char*)cJSON_malloc(2);     /* special case for 0. */
                    165:                if (str) strcpy(str,"0");
                    166:        }
                    167:        else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=LLONG_MAX && d>=LLONG_MIN)
                    168:        {
                    169:                if (p)  str=ensure(p,64);
                    170:                else    str=(char*)cJSON_malloc(64);
                    171:                if (str)        sprintf(str,"%lld",(long long) item->valueint);
                    172:        }
                    173:        else
                    174:        {
                    175:                if (p)  str=ensure(p,64);
                    176:                else    str=(char*)cJSON_malloc(64);    /* This is a nice tradeoff. */
                    177:                if (str)
                    178:                {
                    179:                        if (fpclassify(d) != FP_ZERO && !isnormal(d))                           sprintf(str,"null");
                    180:                        else if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)       sprintf(str,"%.0f",d);
                    181:                        else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)                                       sprintf(str,"%e",d);
                    182:                        else                                                                                                            sprintf(str,"%f",d);
                    183:                }
                    184:        }
                    185:        return str;
                    186: }
                    187: 
                    188: static unsigned parse_hex4(const char *str)
                    189: {
                    190:        unsigned h=0;
                    191:        if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
                    192:        h=h<<4;str++;
                    193:        if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
                    194:        h=h<<4;str++;
                    195:        if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
                    196:        h=h<<4;str++;
                    197:        if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
                    198:        return h;
                    199: }
                    200: 
                    201: /* Parse the input text into an unescaped cstring, and populate item. */
                    202: static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
                    203: static const char *parse_string(cJSON *item,const char *str,const char **ep)
                    204: {
                    205:        const char *ptr=str+1,*end_ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
                    206:        if (*str!='\"') {*ep=str;return 0;}     /* not a string! */
                    207:        
                    208:        while (*end_ptr!='\"' && *end_ptr && ++len) if (*end_ptr++ == '\\') end_ptr++;  /* Skip escaped quotes. */
                    209:        
                    210:        out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
                    211:        if (!out) return 0;
                    212:        item->valuestring=out; /* assign here so out will be deleted during cJSON_Delete() later */
                    213:        item->type=cJSON_String;
                    214:        
                    215:        ptr=str+1;ptr2=out;
                    216:        while (ptr < end_ptr)
                    217:        {
                    218:                if (*ptr!='\\') *ptr2++=*ptr++;
                    219:                else
                    220:                {
                    221:                        ptr++;
                    222:                        switch (*ptr)
                    223:                        {
                    224:                                case 'b': *ptr2++='\b'; break;
                    225:                                case 'f': *ptr2++='\f'; break;
                    226:                                case 'n': *ptr2++='\n'; break;
                    227:                                case 'r': *ptr2++='\r'; break;
                    228:                                case 't': *ptr2++='\t'; break;
                    229:                                case 'u':        /* transcode utf16 to utf8. */
                    230:                                        uc=parse_hex4(ptr+1);ptr+=4;    /* get the unicode char. */
                    231:                                        if (ptr >= end_ptr) {*ep=str;return 0;} /* invalid */
                    232:                                        
                    233:                                        if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)    {*ep=str;return 0;} /* check for invalid.   */
                    234:                                        
                    235:                                        if (uc>=0xD800 && uc<=0xDBFF)   /* UTF16 surrogate pairs.       */
                    236:                                        {
                    237:                                                if (ptr+6 > end_ptr)    {*ep=str;return 0;}     /* invalid */
                    238:                                                if (ptr[1]!='\\' || ptr[2]!='u')    {*ep=str;return 0;} /* missing second-half of surrogate.    */
                    239:                                                uc2=parse_hex4(ptr+3);ptr+=6;
                    240:                                                if (uc2<0xDC00 || uc2>0xDFFF)       {*ep=str;return 0;} /* invalid second-half of surrogate.    */
                    241:                                                uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
                    242:                                        }
                    243: 
                    244:                                        len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
                    245:                                        
                    246:                                        switch (len) {
                    247:                                                case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
                    248:                                                case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
                    249:                                                case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
                    250:                                                case 1: *--ptr2 =(uc | firstByteMark[len]);
                    251:                                        }
                    252:                                        ptr2+=len;
                    253:                                        break;
                    254:                                default:  *ptr2++=*ptr; break;
                    255:                        }
                    256:                        ptr++;
                    257:                }
                    258:        }
                    259:        *ptr2=0;
                    260:        if (*ptr=='\"') ptr++;
                    261:        return ptr;
                    262: }
                    263: 
                    264: /* Render the cstring provided to an escaped version that can be printed. */
                    265: static char *print_string_ptr(const char *str,printbuffer *p)
                    266: {
                    267:        const char *ptr;char *ptr2,*out;int len=0,flag=0;unsigned char token;
                    268: 
                    269:        if (!str)
                    270:        {
                    271:                if (p)  out=ensure(p,3);
                    272:                else    out=(char*)cJSON_malloc(3);
                    273:                if (!out) return 0;
                    274:                strcpy(out,"\"\"");
                    275:                return out;
                    276:        }
                    277:        
                    278:        for (ptr=str;*ptr;ptr++) flag|=((*ptr>0 && *ptr<32)||(*ptr=='\"')||(*ptr=='\\'))?1:0;
                    279:        if (!flag)
                    280:        {
                    281:                len=ptr-str;
                    282:                if (p) out=ensure(p,len+3);
                    283:                else            out=(char*)cJSON_malloc(len+3);
                    284:                if (!out) return 0;
                    285:                ptr2=out;*ptr2++='\"';
                    286:                strcpy(ptr2,str);
                    287:                ptr2[len]='\"';
                    288:                ptr2[len+1]=0;
                    289:                return out;
                    290:        }
                    291:        
                    292:        ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
                    293:        
                    294:        if (p)  out=ensure(p,len+3);
                    295:        else    out=(char*)cJSON_malloc(len+3);
                    296:        if (!out) return 0;
                    297: 
                    298:        ptr2=out;ptr=str;
                    299:        *ptr2++='\"';
                    300:        while (*ptr)
                    301:        {
                    302:                if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
                    303:                else
                    304:                {
                    305:                        *ptr2++='\\';
                    306:                        switch (token=*ptr++)
                    307:                        {
                    308:                                case '\\':      *ptr2++='\\';   break;
                    309:                                case '\"':      *ptr2++='\"';   break;
                    310:                                case '\b':      *ptr2++='b';    break;
                    311:                                case '\f':      *ptr2++='f';    break;
                    312:                                case '\n':      *ptr2++='n';    break;
                    313:                                case '\r':      *ptr2++='r';    break;
                    314:                                case '\t':      *ptr2++='t';    break;
                    315:                                default: sprintf(ptr2,"u%04x",token);ptr2+=5;   break;  /* escape and print */
                    316:                        }
                    317:                }
                    318:        }
                    319:        *ptr2++='\"';*ptr2++=0;
                    320:        return out;
                    321: }
                    322: /* Invote print_string_ptr (which is useful) on an item. */
                    323: static char *print_string(cJSON *item,printbuffer *p)  {return print_string_ptr(item->valuestring,p);}
                    324: 
                    325: /* Predeclare these prototypes. */
                    326: static const char *parse_value(cJSON *item,const char *value,const char **ep);
                    327: static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p);
                    328: static const char *parse_array(cJSON *item,const char *value,const char **ep);
                    329: static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p);
                    330: static const char *parse_object(cJSON *item,const char *value,const char **ep);
                    331: static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p);
                    332: 
                    333: /* Utility to jump whitespace and cr/lf */
                    334: static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
                    335: 
                    336: /* Parse an object - create a new root, and populate. */
                    337: cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
                    338: {
                    339:        const char *end=0,**ep=return_parse_end?return_parse_end:&global_ep;
                    340:        cJSON *c=cJSON_New_Item();
                    341:        *ep=0;
                    342:        if (!c) return 0;       /* memory fail */
                    343: 
                    344:        end=parse_value(c,skip(value),ep);
                    345:        if (!end)       {cJSON_Delete(c);return 0;}     /* parse failure. ep is set. */
                    346: 
                    347:        /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
                    348:        if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);*ep=end;return 0;}}
                    349:        if (return_parse_end) *return_parse_end=end;
                    350:        return c;
                    351: }
                    352: /* Default options for cJSON_Parse */
                    353: cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}
                    354: 
                    355: /* Render a cJSON item/entity/structure to text. */
                    356: char *cJSON_Print(cJSON *item)                         {return print_value(item,0,1,0);}
                    357: char *cJSON_PrintUnformatted(cJSON *item)      {return print_value(item,0,0,0);}
                    358: 
                    359: char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt)
                    360: {
                    361:        printbuffer p;
                    362:        p.buffer=(char*)cJSON_malloc(prebuffer);
                    363:        p.length=prebuffer;
                    364:        p.offset=0;
                    365:        return print_value(item,0,fmt,&p);
                    366: }
                    367: 
                    368: 
                    369: /* Parser core - when encountering text, process appropriately. */
                    370: static const char *parse_value(cJSON *item,const char *value,const char **ep)
                    371: {
                    372:        if (!value)                                             return 0;       /* Fail on null. */
                    373:        if (!strncmp(value,"null",4))   { item->type=cJSON_NULL;  return value+4; }
                    374:        if (!strncmp(value,"false",5))  { item->type=cJSON_False; return value+5; }
                    375:        if (!strncmp(value,"true",4))   { item->type=cJSON_True; item->valueint=1;      return value+4; }
                    376:        if (*value=='\"')                               { return parse_string(item,value,ep); }
                    377:        if (*value=='-' || (*value>='0' && *value<='9'))        { return parse_number(item,value); }
                    378:        if (*value=='[')                                { return parse_array(item,value,ep); }
                    379:        if (*value=='{')                                { return parse_object(item,value,ep); }
                    380: 
                    381:        *ep=value;return 0;     /* failure. */
                    382: }
                    383: 
                    384: /* Render a value to text. */
                    385: static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p)
                    386: {
                    387:        char *out=0;
                    388:        if (!item) return 0;
                    389:        if (p)
                    390:        {
                    391:                switch ((item->type)&255)
                    392:                {
                    393:                        case cJSON_NULL:        {out=ensure(p,5);       if (out) strcpy(out,"null");    break;}
                    394:                        case cJSON_False:       {out=ensure(p,6);       if (out) strcpy(out,"false");   break;}
                    395:                        case cJSON_True:        {out=ensure(p,5);       if (out) strcpy(out,"true");    break;}
                    396:                        case cJSON_Number:      out=print_number(item,p);break;
                    397:                        case cJSON_String:      out=print_string(item,p);break;
                    398:                        case cJSON_Array:       out=print_array(item,depth,fmt,p);break;
                    399:                        case cJSON_Object:      out=print_object(item,depth,fmt,p);break;
                    400:                }
                    401:        }
                    402:        else
                    403:        {
                    404:                switch ((item->type)&255)
                    405:                {
                    406:                        case cJSON_NULL:        out=cJSON_strdup("null");       break;
                    407:                        case cJSON_False:       out=cJSON_strdup("false");break;
                    408:                        case cJSON_True:        out=cJSON_strdup("true"); break;
                    409:                        case cJSON_Number:      out=print_number(item,0);break;
                    410:                        case cJSON_String:      out=print_string(item,0);break;
                    411:                        case cJSON_Array:       out=print_array(item,depth,fmt,0);break;
                    412:                        case cJSON_Object:      out=print_object(item,depth,fmt,0);break;
                    413:                }
                    414:        }
                    415:        return out;
                    416: }
                    417: 
                    418: /* Build an array from input text. */
                    419: static const char *parse_array(cJSON *item,const char *value,const char **ep)
                    420: {
                    421:        cJSON *child;
                    422:        if (*value!='[')        {*ep=value;return 0;}   /* not an array! */
                    423: 
                    424:        item->type=cJSON_Array;
                    425:        value=skip(value+1);
                    426:        if (*value==']') return value+1;        /* empty array. */
                    427: 
                    428:        item->child=child=cJSON_New_Item();
                    429:        if (!item->child) return 0;              /* memory fail */
                    430:        value=skip(parse_value(child,skip(value),ep));  /* skip any spacing, get the value. */
                    431:        if (!value) return 0;
                    432: 
                    433:        while (*value==',')
                    434:        {
                    435:                cJSON *new_item;
                    436:                if (!(new_item=cJSON_New_Item())) return 0;     /* memory fail */
                    437:                child->next=new_item;new_item->prev=child;child=new_item;
                    438:                value=skip(parse_value(child,skip(value+1),ep));
                    439:                if (!value) return 0;   /* memory fail */
                    440:        }
                    441: 
                    442:        if (*value==']') return value+1;        /* end of array */
                    443:        *ep=value;return 0;     /* malformed. */
                    444: }
                    445: 
                    446: /* Render an array to text */
                    447: static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p)
                    448: {
                    449:        char **entries;
                    450:        char *out=0,*ptr,*ret;int len=5;
                    451:        cJSON *child=item->child;
                    452:        int numentries=0,i=0,fail=0;
                    453:        size_t tmplen=0;
                    454:        
                    455:        /* How many entries in the array? */
                    456:        while (child) numentries++,child=child->next;
                    457:        /* Explicitly handle numentries==0 */
                    458:        if (!numentries)
                    459:        {
                    460:                if (p)  out=ensure(p,3);
                    461:                else    out=(char*)cJSON_malloc(3);
                    462:                if (out) strcpy(out,"[]");
                    463:                return out;
                    464:        }
                    465: 
                    466:        if (p)
                    467:        {
                    468:                /* Compose the output array. */
                    469:                i=p->offset;
                    470:                ptr=ensure(p,1);if (!ptr) return 0;     *ptr='[';       p->offset++;
                    471:                child=item->child;
                    472:                while (child && !fail)
                    473:                {
                    474:                        print_value(child,depth+1,fmt,p);
                    475:                        p->offset=update(p);
                    476:                        if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;p->offset+=len;}
                    477:                        child=child->next;
                    478:                }
                    479:                ptr=ensure(p,2);if (!ptr) return 0;     *ptr++=']';*ptr=0;
                    480:                out=(p->buffer)+i;
                    481:        }
                    482:        else
                    483:        {
                    484:                /* Allocate an array to hold the values for each */
                    485:                entries=(char**)cJSON_malloc(numentries*sizeof(char*));
                    486:                if (!entries) return 0;
                    487:                memset(entries,0,numentries*sizeof(char*));
                    488:                /* Retrieve all the results: */
                    489:                child=item->child;
                    490:                while (child && !fail)
                    491:                {
                    492:                        ret=print_value(child,depth+1,fmt,0);
                    493:                        entries[i++]=ret;
                    494:                        if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
                    495:                        child=child->next;
                    496:                }
                    497:                
                    498:                /* If we didn't fail, try to malloc the output string */
                    499:                if (!fail)      out=(char*)cJSON_malloc(len);
                    500:                /* If that fails, we fail. */
                    501:                if (!out) fail=1;
                    502: 
                    503:                /* Handle failure. */
                    504:                if (fail)
                    505:                {
                    506:                        for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
                    507:                        cJSON_free(entries);
                    508:                        return 0;
                    509:                }
                    510:                
                    511:                /* Compose the output array. */
                    512:                *out='[';
                    513:                ptr=out+1;*ptr=0;
                    514:                for (i=0;i<numentries;i++)
                    515:                {
                    516:                        tmplen=strlen(entries[i]);memcpy(ptr,entries[i],tmplen);ptr+=tmplen;
                    517:                        if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
                    518:                        cJSON_free(entries[i]);
                    519:                }
                    520:                cJSON_free(entries);
                    521:                *ptr++=']';*ptr++=0;
                    522:        }
                    523:        return out;     
                    524: }
                    525: 
                    526: /* Build an object from the text. */
                    527: static const char *parse_object(cJSON *item,const char *value,const char **ep)
                    528: {
                    529:        cJSON *child;
                    530:        if (*value!='{')        {*ep=value;return 0;}   /* not an object! */
                    531:        
                    532:        item->type=cJSON_Object;
                    533:        value=skip(value+1);
                    534:        if (*value=='}') return value+1;        /* empty array. */
                    535:        
                    536:        item->child=child=cJSON_New_Item();
                    537:        if (!item->child) return 0;
                    538:        value=skip(parse_string(child,skip(value),ep));
                    539:        if (!value) return 0;
                    540:        child->string=child->valuestring;child->valuestring=0;
                    541:        if (*value!=':') {*ep=value;return 0;}  /* fail! */
                    542:        value=skip(parse_value(child,skip(value+1),ep));        /* skip any spacing, get the value. */
                    543:        if (!value) return 0;
                    544:        
                    545:        while (*value==',')
                    546:        {
                    547:                cJSON *new_item;
                    548:                if (!(new_item=cJSON_New_Item()))       return 0; /* memory fail */
                    549:                child->next=new_item;new_item->prev=child;child=new_item;
                    550:                value=skip(parse_string(child,skip(value+1),ep));
                    551:                if (!value) return 0;
                    552:                child->string=child->valuestring;child->valuestring=0;
                    553:                if (*value!=':') {*ep=value;return 0;}  /* fail! */
                    554:                value=skip(parse_value(child,skip(value+1),ep));        /* skip any spacing, get the value. */
                    555:                if (!value) return 0;
                    556:        }
                    557:        
                    558:        if (*value=='}') return value+1;        /* end of array */
                    559:        *ep=value;return 0;     /* malformed. */
                    560: }
                    561: 
                    562: /* Render an object to text. */
                    563: static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p)
                    564: {
                    565:        char **entries=0,**names=0;
                    566:        char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
                    567:        cJSON *child=item->child;
                    568:        int numentries=0,fail=0;
                    569:        size_t tmplen=0;
                    570:        /* Count the number of entries. */
                    571:        while (child) numentries++,child=child->next;
                    572:        /* Explicitly handle empty object case */
                    573:        if (!numentries)
                    574:        {
                    575:                if (p) out=ensure(p,fmt?depth+4:3);
                    576:                else    out=(char*)cJSON_malloc(fmt?depth+4:3);
                    577:                if (!out)       return 0;
                    578:                ptr=out;*ptr++='{';
                    579:                if (fmt) {*ptr++='\n';for (i=0;i<depth;i++) *ptr++='\t';}
                    580:                *ptr++='}';*ptr++=0;
                    581:                return out;
                    582:        }
                    583:        if (p)
                    584:        {
                    585:                /* Compose the output: */
                    586:                i=p->offset;
                    587:                len=fmt?2:1;    ptr=ensure(p,len+1);    if (!ptr) return 0;
                    588:                *ptr++='{';     if (fmt) *ptr++='\n';   *ptr=0; p->offset+=len;
                    589:                child=item->child;depth++;
                    590:                while (child)
                    591:                {
                    592:                        if (fmt)
                    593:                        {
                    594:                                ptr=ensure(p,depth);    if (!ptr) return 0;
                    595:                                for (j=0;j<depth;j++) *ptr++='\t';
                    596:                                p->offset+=depth;
                    597:                        }
                    598:                        print_string_ptr(child->string,p);
                    599:                        p->offset=update(p);
                    600:                        
                    601:                        len=fmt?2:1;
                    602:                        ptr=ensure(p,len);      if (!ptr) return 0;
                    603:                        *ptr++=':';if (fmt) *ptr++='\t';
                    604:                        p->offset+=len;
                    605:                        
                    606:                        print_value(child,depth,fmt,p);
                    607:                        p->offset=update(p);
                    608: 
                    609:                        len=(fmt?1:0)+(child->next?1:0);
                    610:                        ptr=ensure(p,len+1); if (!ptr) return 0;
                    611:                        if (child->next) *ptr++=',';
                    612:                        if (fmt) *ptr++='\n';*ptr=0;
                    613:                        p->offset+=len;
                    614:                        child=child->next;
                    615:                }
                    616:                ptr=ensure(p,fmt?(depth+1):2);   if (!ptr) return 0;
                    617:                if (fmt)        for (i=0;i<depth-1;i++) *ptr++='\t';
                    618:                *ptr++='}';*ptr=0;
                    619:                out=(p->buffer)+i;
                    620:        }
                    621:        else
                    622:        {
                    623:                /* Allocate space for the names and the objects */
                    624:                entries=(char**)cJSON_malloc(numentries*sizeof(char*));
                    625:                if (!entries) return 0;
                    626:                names=(char**)cJSON_malloc(numentries*sizeof(char*));
                    627:                if (!names) {cJSON_free(entries);return 0;}
                    628:                memset(entries,0,sizeof(char*)*numentries);
                    629:                memset(names,0,sizeof(char*)*numentries);
                    630: 
                    631:                /* Collect all the results into our arrays: */
                    632:                child=item->child;depth++;if (fmt) len+=depth;
                    633:                while (child && !fail)
                    634:                {
                    635:                        names[i]=str=print_string_ptr(child->string,0);
                    636:                        entries[i++]=ret=print_value(child,depth,fmt,0);
                    637:                        if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
                    638:                        child=child->next;
                    639:                }
                    640:                
                    641:                /* Try to allocate the output string */
                    642:                if (!fail)      out=(char*)cJSON_malloc(len);
                    643:                if (!out) fail=1;
                    644: 
                    645:                /* Handle failure */
                    646:                if (fail)
                    647:                {
                    648:                        for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
                    649:                        cJSON_free(names);cJSON_free(entries);
                    650:                        return 0;
                    651:                }
                    652:                
                    653:                /* Compose the output: */
                    654:                *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
                    655:                for (i=0;i<numentries;i++)
                    656:                {
                    657:                        if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
                    658:                        tmplen=strlen(names[i]);memcpy(ptr,names[i],tmplen);ptr+=tmplen;
                    659:                        *ptr++=':';if (fmt) *ptr++='\t';
                    660:                        strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
                    661:                        if (i!=numentries-1) *ptr++=',';
                    662:                        if (fmt) *ptr++='\n';*ptr=0;
                    663:                        cJSON_free(names[i]);cJSON_free(entries[i]);
                    664:                }
                    665:                
                    666:                cJSON_free(names);cJSON_free(entries);
                    667:                if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
                    668:                *ptr++='}';*ptr++=0;
                    669:        }
                    670:        return out;     
                    671: }
                    672: 
                    673: /* Get Array size/item / object item. */
                    674: int    cJSON_GetArraySize(cJSON *array)                                                        {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
                    675: cJSON *cJSON_GetArrayItem(cJSON *array,int item)                               {cJSON *c=array?array->child:0;while (c && item>0) item--,c=c->next; return c;}
                    676: cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)   {cJSON *c=object?object->child:0;while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
                    677: int cJSON_HasObjectItem(cJSON *object,const char *string)              {return cJSON_GetObjectItem(object,string)?1:0;}
                    678: 
                    679: /* Utility for array list handling. */
                    680: static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
                    681: /* Utility for handling references. */
                    682: static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
                    683: 
                    684: /* Add item to array/object. */
                    685: void   cJSON_AddItemToArray(cJSON *array, cJSON *item)                                         {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
                    686: void   cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item)     {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
                    687: void   cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item)   {if (!item) return; if (!(item->type&cJSON_StringIsConst) && item->string) cJSON_free(item->string);item->string=(char*)string;item->type|=cJSON_StringIsConst;cJSON_AddItemToArray(object,item);}
                    688: void   cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)                                                {cJSON_AddItemToArray(array,create_reference(item));}
                    689: void   cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item)    {cJSON_AddItemToObject(object,string,create_reference(item));}
                    690: 
                    691: cJSON *cJSON_DetachItemFromArray(cJSON *array,int which)                       {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
                    692:        if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
                    693: void   cJSON_DeleteItemFromArray(cJSON *array,int which)                       {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
                    694: cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
                    695: void   cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
                    696: 
                    697: /* Replace array/object items with new ones. */
                    698: void   cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem)          {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) {cJSON_AddItemToArray(array,newitem);return;}
                    699:        newitem->next=c;newitem->prev=c->prev;c->prev=newitem;if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;}
                    700: void   cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem)         {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
                    701:        newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
                    702:        if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
                    703: void   cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
                    704: 
                    705: /* Create basic types: */
                    706: cJSON *cJSON_CreateNull(void)                                  {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
                    707: cJSON *cJSON_CreateTrue(void)                                  {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
                    708: cJSON *cJSON_CreateFalse(void)                                 {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
                    709: cJSON *cJSON_CreateBool(int b)                                 {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
                    710: cJSON *cJSON_CreateNumber(double num)                  {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int64_t)num;}return item;}
                    711: cJSON *cJSON_CreateString(const char *string)  {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);if(!item->valuestring){cJSON_Delete(item);return 0;}}return item;}
                    712: cJSON *cJSON_CreateArray(void)                                 {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
                    713: cJSON *cJSON_CreateObject(void)                                        {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
                    714: 
                    715: /* Create Arrays: */
                    716: cJSON *cJSON_CreateIntArray(const int *numbers,int count)              {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!n){cJSON_Delete(a);return 0;}if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
                    717: cJSON *cJSON_CreateFloatArray(const float *numbers,int count)  {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!n){cJSON_Delete(a);return 0;}if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
                    718: cJSON *cJSON_CreateDoubleArray(const double *numbers,int count)        {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!n){cJSON_Delete(a);return 0;}if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
                    719: cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!n){cJSON_Delete(a);return 0;}if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
                    720: 
                    721: /* Duplication */
                    722: cJSON *cJSON_Duplicate(cJSON *item,int recurse)
                    723: {
                    724:        cJSON *newitem,*cptr,*nptr=0,*newchild;
                    725:        /* Bail on bad ptr */
                    726:        if (!item) return 0;
                    727:        /* Create new item */
                    728:        newitem=cJSON_New_Item();
                    729:        if (!newitem) return 0;
                    730:        /* Copy over all vars */
                    731:        newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
                    732:        if (item->valuestring)  {newitem->valuestring=cJSON_strdup(item->valuestring);  if (!newitem->valuestring)      {cJSON_Delete(newitem);return 0;}}
                    733:        if (item->string)               {newitem->string=cJSON_strdup(item->string);                    if (!newitem->string)           {cJSON_Delete(newitem);return 0;}}
                    734:        /* If non-recursive, then we're done! */
                    735:        if (!recurse) return newitem;
                    736:        /* Walk the ->next chain for the child. */
                    737:        cptr=item->child;
                    738:        while (cptr)
                    739:        {
                    740:                newchild=cJSON_Duplicate(cptr,1);               /* Duplicate (with recurse) each item in the ->next chain */
                    741:                if (!newchild) {cJSON_Delete(newitem);return 0;}
                    742:                if (nptr)       {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;}        /* If newitem->child already set, then crosswire ->prev and ->next and move on */
                    743:                else            {newitem->child=newchild;nptr=newchild;}                                        /* Set newitem->child and move to it */
                    744:                cptr=cptr->next;
                    745:        }
                    746:        return newitem;
                    747: }
                    748: 
                    749: void cJSON_Minify(char *json)
                    750: {
                    751:        char *into=json;
                    752:        while (*json)
                    753:        {
                    754:                if (*json==' ') json++;
                    755:                else if (*json=='\t') json++;   /* Whitespace characters. */
                    756:                else if (*json=='\r') json++;
                    757:                else if (*json=='\n') json++;
                    758:                else if (*json=='/' && json[1]=='/')  while (*json && *json!='\n') json++;      /* double-slash comments, to end of line. */
                    759:                else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;}   /* multiline comments. */
                    760:                else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals, which are \" sensitive. */
                    761:                else *into++=*json++;                   /* All other characters. */
                    762:        }
                    763:        *into=0;        /* and null-terminate. */
                    764: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>