LCOV - code coverage report
Current view: top level - src - cJSON.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 815 0.0 %
Date: 2018-11-14 16:53:58 Functions: 0 56 0.0 %

          Line data    Source code
       1             : /* cJSON.c - JSON parser in C.
       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             :  * SPDX-License-Identifier: MIT
      23             :  *
      24             :  * Note that this code has been modified from the original code taken
      25             :  * from cjson-code-58.zip before 2014 (my first local commit was in
      26             :  * 2014 but I may used the code even earlier).  Since 2016 the project
      27             :  * was revived and moved to https://github.com/DaveGamble/cJSON.git.
      28             :  * It is now a lot more complex and has substantial changes so that it
      29             :  * is not possible to merge them directly.  In any case we only need a
      30             :  * simple parser and not a complete library.  I have looked through
      31             :  * the commits and fixed a few things which should apply; I also added
      32             :  * a few references to the upstream code.  Regression test are missing!
      33             :  */
      34             : 
      35             : #ifdef HAVE_CONFIG_H
      36             : # include <config.h>
      37             : #endif
      38             : 
      39             : #include <string.h>
      40             : #include <stdio.h>
      41             : #include <math.h>
      42             : #include <stdlib.h>
      43             : #include <float.h>
      44             : #include <limits.h>
      45             : #include <ctype.h>
      46             : #include <errno.h>
      47             : 
      48             : #include <gpg-error.h>
      49             : 
      50             : #include "cJSON.h"
      51             : 
      52             : /* Only use calloc. */
      53             : #define CALLOC_ONLY 1
      54             : 
      55             : /* To avoid that a compiler optimizes certain memset calls away, these
      56             :    macros may be used instead. */
      57             : #define wipememory2(_ptr,_set,_len) do { \
      58             :         volatile char *_vptr=(volatile char *)(_ptr); \
      59             :         size_t _vlen=(_len); \
      60             :         while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \
      61             :     } while(0)
      62             : #define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
      63             : 
      64             : /* We use malloc function wrappers from gpgrt (aka libgpg-error).  */
      65             : #if GPGRT_VERSION_NUMBER >= 0x011c00 /* 1.28 */
      66             : # include <gpgrt.h>
      67             : # define xtrycalloc(a,b) gpgrt_calloc ((a), (b))
      68             : # define xtrystrdup(a)   gpgrt_strdup ((a))
      69             : # define xfree(a)        gpgrt_free ((a))
      70             : # if CALLOC_ONLY
      71             : #  define xtrymalloc(a)  gpgrt_calloc (1, (a))
      72             : # else
      73             : #  define xtrymalloc(a)  gpgrt_malloc ((a))
      74             : # endif
      75             : #else /* Without gpgrt (aka libgpg-error).  */
      76             : # define xtrycalloc(a,b) calloc ((a), (b))
      77             : # define xtrystrdup(a)   strdup ((a))
      78             : # define xfree(a)        free ((a))
      79             : # if CALLOC_ONLY
      80             : #  define xtrymalloc(a)  calloc (1, (a))
      81             : # else
      82             : #  define xtrymalloc(a)  malloc ((a))
      83             : # endif
      84             : #endif
      85             : 
      86             : 
      87             : static int
      88           0 : cJSON_strcasecmp (const char *s1, const char *s2)
      89             : {
      90           0 :   if (!s1)
      91           0 :     return (s1 == s2) ? 0 : 1;
      92           0 :   if (!s2)
      93           0 :     return 1;
      94           0 :   for (; tolower (*(const unsigned char *)s1)
      95           0 :          == tolower (*(const unsigned char *) s2); ++s1, ++s2)
      96           0 :     if (*s1 == 0)
      97           0 :       return 0;
      98           0 :   return tolower (*(const unsigned char *) s1) -
      99           0 :     tolower (*(const unsigned char *) s2);
     100             : }
     101             : 
     102             : /* Internal constructor. */
     103             : static cJSON *
     104           0 : cJSON_New_Item (void)
     105             : {
     106           0 :   return xtrycalloc (1, sizeof (cJSON));
     107             : }
     108             : 
     109             : /* Delete a cJSON structure.  (Does not clobber ERRNO). */
     110             : void
     111           0 : cJSON_Delete (cJSON * c)
     112             : {
     113             :   cJSON *next;
     114             :   int save_errno;
     115             : 
     116           0 :   if (!c)
     117           0 :     return;
     118             : 
     119           0 :   save_errno = errno;
     120           0 :   while (c)
     121             :     {
     122           0 :       next = c->next;
     123           0 :       if (!(c->type & cJSON_IsReference) && c->child)
     124           0 :         cJSON_Delete (c->child);
     125           0 :       if (!(c->type & cJSON_IsReference) && c->valuestring)
     126             :         {
     127           0 :           wipememory (c->valuestring, strlen (c->valuestring));
     128           0 :           xfree (c->valuestring);
     129             :         }
     130           0 :       if (c->string)
     131             :         {
     132           0 :           wipememory (c->string, strlen (c->string));
     133           0 :           xfree (c->string);
     134             :         }
     135           0 :       xfree (c);
     136           0 :       c = next;
     137             :     }
     138           0 :   errno = save_errno;
     139             : }
     140             : 
     141             : /* Parse the input text to generate a number, and populate the result
     142             :  * into item. */
     143             : static const char *
     144           0 : parse_number (cJSON * item, const char *num)
     145             : {
     146           0 :   double n = 0, sign = 1, scale = 0;
     147           0 :   int subscale = 0, signsubscale = 1;
     148             : 
     149           0 :   if (*num == '-')
     150           0 :     sign = -1, num++;           /* Has sign? */
     151           0 :   if (*num == '0')
     152           0 :     num++;                      /* is zero */
     153           0 :   if (*num >= '1' && *num <= '9')
     154             :     do
     155           0 :       n = (n * 10.0) + (*num++ - '0');
     156           0 :     while (*num >= '0' && *num <= '9');   /* Number? */
     157           0 :   if (*num == '.' && num[1] >= '0' && num[1] <= '9')
     158             :     {
     159           0 :       num++;
     160             :       do
     161           0 :         n = (n * 10.0) + (*num++ - '0'), scale--;
     162           0 :       while (*num >= '0' && *num <= '9');
     163             :     }                           /* Fractional part? */
     164           0 :   if (*num == 'e' || *num == 'E')       /* Exponent? */
     165             :     {
     166           0 :       num++;
     167           0 :       if (*num == '+')
     168           0 :         num++;
     169           0 :       else if (*num == '-')
     170           0 :         signsubscale = -1, num++;       /* With sign? */
     171           0 :       while (*num >= '0' && *num <= '9')
     172           0 :         subscale = (subscale * 10) + (*num++ - '0');    /* Number? */
     173             :     }
     174             : 
     175             :   /* number = +/- number.fraction * 10^+/- exponent */
     176           0 :   n = sign * n * pow (10.0, (scale + subscale * signsubscale));
     177             : 
     178           0 :   item->valuedouble = n;
     179           0 :   item->valueint = (int) n;
     180           0 :   item->type = cJSON_Number;
     181           0 :   return num;
     182             : }
     183             : 
     184             : /* Render the number nicely from the given item into a string. */
     185             : static char *
     186           0 : print_number (cJSON * item)
     187             : {
     188             :   char *str;
     189           0 :   double d = item->valuedouble;
     190           0 :   if (fabs (((double) item->valueint) - d) <= DBL_EPSILON && d <= INT_MAX
     191           0 :       && d >= INT_MIN)
     192             :     {
     193             :       /* 2^64+1 can be represented in 21 chars. */
     194           0 :       str = xtrymalloc (21);
     195           0 :       if (str)
     196           0 :         sprintf (str, "%d", item->valueint);
     197             :     }
     198             :   else
     199             :     {
     200           0 :       str = xtrymalloc (64);    /* This is a nice tradeoff. */
     201           0 :       if (str)
     202             :         {
     203           0 :           if (fabs (floor (d) - d) <= DBL_EPSILON && fabs (d) < 1.0e60)
     204           0 :             sprintf (str, "%.0f", d);
     205           0 :           else if (fabs (d) < 1.0e-6 || fabs (d) > 1.0e9)
     206           0 :             sprintf (str, "%e", d);
     207             :           else
     208           0 :             sprintf (str, "%f", d);
     209             :         }
     210             :     }
     211           0 :   return str;
     212             : }
     213             : 
     214             : static unsigned
     215           0 : parse_hex4 (const char *str)
     216             : {
     217           0 :   unsigned h = 0;
     218           0 :   if (*str >= '0' && *str <= '9')
     219           0 :     h += (*str) - '0';
     220           0 :   else if (*str >= 'A' && *str <= 'F')
     221           0 :     h += 10 + (*str) - 'A';
     222           0 :   else if (*str >= 'a' && *str <= 'f')
     223           0 :     h += 10 + (*str) - 'a';
     224             :   else
     225           0 :     return 0;
     226           0 :   h = h << 4;
     227           0 :   str++;
     228           0 :   if (*str >= '0' && *str <= '9')
     229           0 :     h += (*str) - '0';
     230           0 :   else if (*str >= 'A' && *str <= 'F')
     231           0 :     h += 10 + (*str) - 'A';
     232           0 :   else if (*str >= 'a' && *str <= 'f')
     233           0 :     h += 10 + (*str) - 'a';
     234             :   else
     235           0 :     return 0;
     236           0 :   h = h << 4;
     237           0 :   str++;
     238           0 :   if (*str >= '0' && *str <= '9')
     239           0 :     h += (*str) - '0';
     240           0 :   else if (*str >= 'A' && *str <= 'F')
     241           0 :     h += 10 + (*str) - 'A';
     242           0 :   else if (*str >= 'a' && *str <= 'f')
     243           0 :     h += 10 + (*str) - 'a';
     244             :   else
     245           0 :     return 0;
     246           0 :   h = h << 4;
     247           0 :   str++;
     248           0 :   if (*str >= '0' && *str <= '9')
     249           0 :     h += (*str) - '0';
     250           0 :   else if (*str >= 'A' && *str <= 'F')
     251           0 :     h += 10 + (*str) - 'A';
     252           0 :   else if (*str >= 'a' && *str <= 'f')
     253           0 :     h += 10 + (*str) - 'a';
     254             :   else
     255           0 :     return 0;
     256           0 :   return h;
     257             : }
     258             : 
     259             : /* Parse the input text into an unescaped cstring, and populate item. */
     260             : static const unsigned char firstByteMark[7] =
     261             :   { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
     262             : static const char *
     263           0 : parse_string (cJSON * item, const char *str, const char **ep)
     264             : {
     265           0 :   const char *ptr = str + 1;
     266             :   char *ptr2;
     267             :   char *out;
     268           0 :   int len = 0;
     269             :   unsigned uc, uc2;
     270             : 
     271             :   /* FIXME: We should consider eary failure like it is done with
     272             :    * commit 8656386c4f4a12f1cf3d6b26158407fd05e65029 in upstream.  */
     273           0 :   if (*str != '\"')
     274             :     {
     275           0 :       *ep = str;
     276           0 :       return 0;
     277             :     }                           /* not a string! */
     278             : 
     279           0 :   while (*ptr != '\"' && *ptr && ++len)
     280           0 :     if (*ptr++ == '\\' && *ptr)
     281           0 :       ptr++;                    /* Skip escaped quotes. */
     282             : 
     283           0 :   out = xtrymalloc (len + 2);   /* This is how long we need for the
     284             :                                  * string, roughly.  We add one extra
     285             :                                  * byte in case the last input
     286             :                                  * character is a backslash.  */
     287           0 :   if (!out)
     288           0 :     return 0;
     289             : 
     290           0 :   ptr = str + 1;
     291           0 :   ptr2 = out;
     292           0 :   while (*ptr != '\"' && *ptr)
     293             :     {
     294           0 :       if (*ptr != '\\')
     295           0 :         *ptr2++ = *ptr++;
     296             :       else
     297             :         {
     298           0 :           ptr++;
     299           0 :           if (!*ptr)
     300           0 :             break;
     301           0 :           switch (*ptr)
     302             :             {
     303             :             case 'b':
     304           0 :               *ptr2++ = '\b';
     305           0 :               break;
     306             :             case 'f':
     307           0 :               *ptr2++ = '\f';
     308           0 :               break;
     309             :             case 'n':
     310           0 :               *ptr2++ = '\n';
     311           0 :               break;
     312             :             case 'r':
     313           0 :               *ptr2++ = '\r';
     314           0 :               break;
     315             :             case 't':
     316           0 :               *ptr2++ = '\t';
     317           0 :               break;
     318             :             case 'u':           /* transcode utf16 to utf8. */
     319           0 :               uc = parse_hex4 (ptr + 1);
     320           0 :               if (!uc)
     321           0 :                 break;          /* Bad hex; continue right after the 'u'. */
     322           0 :               ptr += 4;         /* get the unicode char. */
     323             : 
     324           0 :               if ((uc >= 0xDC00 && uc <= 0xDFFF))
     325           0 :                 break;          /* check for invalid.   */
     326             : 
     327           0 :               if (uc >= 0xD800 && uc <= 0xDBFF)   /* UTF16 surrogate pairs. */
     328             :                 {
     329           0 :                   if (ptr[1] != '\\' || ptr[2] != 'u')
     330             :                     break;      /* missing second-half of surrogate.    */
     331           0 :                   ptr += 2;
     332           0 :                   uc2 = parse_hex4 (ptr + 1);
     333           0 :                   if (!uc2)
     334           0 :                     break;      /* Bad hex; continue right after the 'u'. */
     335           0 :                   ptr += 4;
     336           0 :                   if (uc2 < 0xDC00 || uc2 > 0xDFFF)
     337             :                     break;      /* invalid second-half of surrogate.    */
     338           0 :                   uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF));
     339             :                 }
     340             : 
     341           0 :               len = 4;
     342           0 :               if (uc < 0x80)
     343           0 :                 len = 1;
     344           0 :               else if (uc < 0x800)
     345           0 :                 len = 2;
     346           0 :               else if (uc < 0x10000)
     347           0 :                 len = 3;
     348           0 :               ptr2 += len;
     349             : 
     350           0 :               switch (len)
     351             :                 {
     352             :                 case 4:
     353           0 :                   *--ptr2 = ((uc | 0x80) & 0xBF);
     354           0 :                   uc >>= 6;
     355             :                 case 3:
     356           0 :                   *--ptr2 = ((uc | 0x80) & 0xBF);
     357           0 :                   uc >>= 6;
     358             :                 case 2:
     359           0 :                   *--ptr2 = ((uc | 0x80) & 0xBF);
     360           0 :                   uc >>= 6;
     361             :                 case 1:
     362           0 :                   *--ptr2 = (uc | firstByteMark[len]);
     363             :                 }
     364           0 :               ptr2 += len;
     365           0 :               break;
     366             :             default:
     367             :               /* Fixme: Should we fail here: See
     368             :                * https://github.com/DaveGamble/cJSON/issues/10  */
     369           0 :               *ptr2++ = *ptr;
     370           0 :               break;
     371             :             }
     372           0 :           ptr++;
     373             :         }
     374             :     }
     375           0 :   *ptr2 = 0;
     376           0 :   if (*ptr == '\"')
     377           0 :     ptr++;
     378           0 :   item->valuestring = out;
     379           0 :   item->type = cJSON_String;
     380           0 :   return ptr;
     381             : }
     382             : 
     383             : /* Render the cstring provided to an escaped version that can be printed. */
     384             : static char *
     385           0 : print_string_ptr (const char *str)
     386             : {
     387             :   const char *ptr;
     388             :   char *ptr2, *out;
     389           0 :   int len = 0;
     390             :   unsigned char token;
     391             : 
     392           0 :   if (!str)
     393           0 :     return xtrystrdup ("");
     394           0 :   ptr = str;
     395           0 :   while ((token = *ptr) && ++len)
     396             :     {
     397           0 :       if (strchr ("\"\\\b\f\n\r\t", token))
     398           0 :         len++;
     399           0 :       else if (token < 32)
     400           0 :         len += 5;
     401           0 :       ptr++;
     402             :     }
     403             : 
     404           0 :   out = xtrymalloc (len + 3);
     405           0 :   if (!out)
     406           0 :     return 0;
     407             : 
     408           0 :   ptr2 = out;
     409           0 :   ptr = str;
     410           0 :   *ptr2++ = '\"';
     411           0 :   while (*ptr)
     412             :     {
     413           0 :       if ((unsigned char) *ptr > 31 && *ptr != '\"' && *ptr != '\\')
     414           0 :         *ptr2++ = *ptr++;
     415             :       else
     416             :         {
     417           0 :           *ptr2++ = '\\';
     418           0 :           switch (token = *ptr++)
     419             :             {
     420             :             case '\\':
     421           0 :               *ptr2++ = '\\';
     422           0 :               break;
     423             :             case '\"':
     424           0 :               *ptr2++ = '\"';
     425           0 :               break;
     426             :             case '\b':
     427           0 :               *ptr2++ = 'b';
     428           0 :               break;
     429             :             case '\f':
     430           0 :               *ptr2++ = 'f';
     431           0 :               break;
     432             :             case '\n':
     433           0 :               *ptr2++ = 'n';
     434           0 :               break;
     435             :             case '\r':
     436           0 :               *ptr2++ = 'r';
     437           0 :               break;
     438             :             case '\t':
     439           0 :               *ptr2++ = 't';
     440           0 :               break;
     441             :             default:
     442           0 :               sprintf (ptr2, "u%04x", token);
     443           0 :               ptr2 += 5;
     444           0 :               break;            /* escape and print */
     445             :             }
     446             :         }
     447             :     }
     448           0 :   *ptr2++ = '\"';
     449           0 :   *ptr2++ = 0;
     450           0 :   return out;
     451             : }
     452             : 
     453             : /* Invote print_string_ptr (which is useful) on an item. */
     454             : static char *
     455           0 : print_string (cJSON * item)
     456             : {
     457           0 :   return print_string_ptr (item->valuestring);
     458             : }
     459             : 
     460             : /* Predeclare these prototypes. */
     461             : static const char *parse_value (cJSON * item, const char *value,
     462             :                                 const char **ep);
     463             : static char *print_value (cJSON * item, int depth, int fmt);
     464             : static const char *parse_array (cJSON * item, const char *value,
     465             :                                 const char **ep);
     466             : static char *print_array (cJSON * item, int depth, int fmt);
     467             : static const char *parse_object (cJSON * item, const char *value,
     468             :                                  const char **ep);
     469             : static char *print_object (cJSON * item, int depth, int fmt);
     470             : 
     471             : /* Utility to jump whitespace and cr/lf */
     472             : static const char *
     473           0 : skip (const char *in)
     474             : {
     475           0 :   while (in && *in && (unsigned char) *in <= 32)
     476           0 :     in++;
     477           0 :   return in;
     478             : }
     479             : 
     480             : /* Parse an object - create a new root, and populate. */
     481             : cJSON *
     482           0 : cJSON_ParseWithOpts (const char *value, const char **return_parse_end,
     483             :                      int require_null_terminated, size_t *r_erroff)
     484             : {
     485           0 :   const char *end = 0;
     486           0 :   const char *ep = 0;
     487             :   cJSON *c;
     488             : 
     489           0 :   if (r_erroff)
     490           0 :     *r_erroff = 0;
     491             : 
     492           0 :   c = cJSON_New_Item ();
     493           0 :   if (!c)
     494           0 :     return NULL; /* memory fail */
     495             : 
     496           0 :   end = parse_value (c, skip (value), &ep);
     497           0 :   if (!end)
     498             :     {
     499           0 :       cJSON_Delete (c);
     500           0 :       errno = EINVAL;
     501           0 :       if (r_erroff)
     502           0 :         *r_erroff = ep - value;
     503           0 :       return 0;
     504             :     }                           /* parse failure. ep is set. */
     505             : 
     506             :   /* if we require null-terminated JSON without appended garbage, skip
     507             :      and then check for a null terminator */
     508           0 :   if (require_null_terminated)
     509             :     {
     510           0 :       end = skip (end);
     511           0 :       if (*end)
     512             :         {
     513           0 :           cJSON_Delete (c);
     514           0 :           ep = end;
     515           0 :           errno = EINVAL;
     516           0 :           if (r_erroff)
     517           0 :             *r_erroff = ep - value;
     518           0 :           return 0;
     519             :         }
     520             :     }
     521           0 :   if (return_parse_end)
     522           0 :     *return_parse_end = end;
     523           0 :   return c;
     524             : }
     525             : 
     526             : /* Default options for cJSON_Parse */
     527             : cJSON *
     528           0 : cJSON_Parse (const char *value, size_t *r_erroff)
     529             : {
     530           0 :   return cJSON_ParseWithOpts (value, 0, 0, r_erroff);
     531             : }
     532             : 
     533             : /* Render a cJSON item/entity/structure to text. */
     534             : char *
     535           0 : cJSON_Print (cJSON * item)
     536             : {
     537           0 :   return print_value (item, 0, 1);
     538             : }
     539             : 
     540             : char *
     541           0 : cJSON_PrintUnformatted (cJSON * item)
     542             : {
     543           0 :   return print_value (item, 0, 0);
     544             : }
     545             : 
     546             : /* Parser core - when encountering text, process appropriately. */
     547             : static const char *
     548           0 : parse_value (cJSON * item, const char *value, const char **ep)
     549             : {
     550           0 :   if (!value)
     551           0 :     return 0;                   /* Fail on null. */
     552           0 :   if (!strncmp (value, "null", 4))
     553             :     {
     554           0 :       item->type = cJSON_NULL;
     555           0 :       return value + 4;
     556             :     }
     557           0 :   if (!strncmp (value, "false", 5))
     558             :     {
     559           0 :       item->type = cJSON_False;
     560           0 :       return value + 5;
     561             :     }
     562           0 :   if (!strncmp (value, "true", 4))
     563             :     {
     564           0 :       item->type = cJSON_True;
     565           0 :       item->valueint = 1;
     566           0 :       return value + 4;
     567             :     }
     568           0 :   if (*value == '\"')
     569             :     {
     570           0 :       return parse_string (item, value, ep);
     571             :     }
     572           0 :   if (*value == '-' || (*value >= '0' && *value <= '9'))
     573             :     {
     574           0 :       return parse_number (item, value);
     575             :     }
     576           0 :   if (*value == '[')
     577             :     {
     578           0 :       return parse_array (item, value, ep);
     579             :     }
     580           0 :   if (*value == '{')
     581             :     {
     582           0 :       return parse_object (item, value, ep);
     583             :     }
     584             : 
     585           0 :   *ep = value;
     586           0 :   return 0;                     /* failure. */
     587             : }
     588             : 
     589             : /* Render a value to text. */
     590             : static char *
     591           0 : print_value (cJSON * item, int depth, int fmt)
     592             : {
     593           0 :   char *out = 0;
     594           0 :   if (!item)
     595           0 :     return 0;
     596           0 :   switch ((item->type) & 255)
     597             :     {
     598             :     case cJSON_NULL:
     599           0 :       out = xtrystrdup ("null");
     600           0 :       break;
     601             :     case cJSON_False:
     602           0 :       out = xtrystrdup ("false");
     603           0 :       break;
     604             :     case cJSON_True:
     605           0 :       out = xtrystrdup ("true");
     606           0 :       break;
     607             :     case cJSON_Number:
     608           0 :       out = print_number (item);
     609           0 :       break;
     610             :     case cJSON_String:
     611           0 :       out = print_string (item);
     612           0 :       break;
     613             :     case cJSON_Array:
     614           0 :       out = print_array (item, depth, fmt);
     615           0 :       break;
     616             :     case cJSON_Object:
     617           0 :       out = print_object (item, depth, fmt);
     618           0 :       break;
     619             :     }
     620           0 :   return out;
     621             : }
     622             : 
     623             : /* Build an array from input text. */
     624             : static const char *
     625           0 : parse_array (cJSON * item, const char *value, const char **ep)
     626             : {
     627             :   cJSON *child;
     628           0 :   if (*value != '[')
     629             :     {
     630           0 :       *ep = value;
     631           0 :       return 0;
     632             :     }                           /* not an array! */
     633             : 
     634           0 :   item->type = cJSON_Array;
     635           0 :   value = skip (value + 1);
     636           0 :   if (*value == ']')
     637           0 :     return value + 1;           /* empty array. */
     638             : 
     639           0 :   item->child = child = cJSON_New_Item ();
     640           0 :   if (!item->child)
     641           0 :     return 0;                   /* memory fail */
     642             :   /* skip any spacing, get the value. */
     643           0 :   value = skip (parse_value (child, skip (value), ep));
     644           0 :   if (!value)
     645           0 :     return 0;
     646             : 
     647           0 :   while (*value == ',')
     648             :     {
     649             :       cJSON *new_item;
     650           0 :       if (!(new_item = cJSON_New_Item ()))
     651           0 :         return 0;               /* memory fail */
     652           0 :       child->next = new_item;
     653           0 :       new_item->prev = child;
     654           0 :       child = new_item;
     655           0 :       value = skip (parse_value (child, skip (value + 1), ep));
     656           0 :       if (!value)
     657           0 :         return 0;               /* memory fail */
     658             :     }
     659             : 
     660           0 :   if (*value == ']')
     661           0 :     return value + 1;           /* end of array */
     662           0 :   *ep = value;
     663           0 :   return 0;                     /* malformed. */
     664             : }
     665             : 
     666             : /* Render an array to text */
     667             : static char *
     668           0 : print_array (cJSON * item, int depth, int fmt)
     669             : {
     670             :   char **entries;
     671           0 :   char *out = 0, *ptr, *ret;
     672           0 :   int len = 5;
     673           0 :   cJSON *child = item->child;
     674           0 :   int numentries = 0, i = 0, fail = 0;
     675             : 
     676             :   /* How many entries in the array? */
     677           0 :   while (child)
     678           0 :     numentries++, child = child->next;
     679             :   /* Explicitly handle numentries==0 */
     680           0 :   if (!numentries)
     681             :     {
     682           0 :       out = xtrymalloc (3);
     683           0 :       if (out)
     684           0 :         strcpy (out, "[]");
     685           0 :       return out;
     686             :     }
     687             :   /* Allocate an array to hold the values for each */
     688           0 :   entries = xtrymalloc (numentries * sizeof (char *));
     689           0 :   if (!entries)
     690           0 :     return 0;
     691           0 :   memset (entries, 0, numentries * sizeof (char *));
     692             :   /* Retrieve all the results: */
     693           0 :   child = item->child;
     694           0 :   while (child && !fail)
     695             :     {
     696           0 :       ret = print_value (child, depth + 1, fmt);
     697           0 :       entries[i++] = ret;
     698           0 :       if (ret)
     699           0 :         len += strlen (ret) + 2 + (fmt ? 1 : 0);
     700             :       else
     701           0 :         fail = 1;
     702           0 :       child = child->next;
     703             :     }
     704             : 
     705             :   /* If we didn't fail, try to xtrymalloc the output string */
     706           0 :   if (!fail)
     707           0 :     out = xtrymalloc (len);
     708             :   /* If that fails, we fail. */
     709           0 :   if (!out)
     710           0 :     fail = 1;
     711             : 
     712             :   /* Handle failure. */
     713           0 :   if (fail)
     714             :     {
     715           0 :       for (i = 0; i < numentries; i++)
     716           0 :         if (entries[i])
     717           0 :           xfree (entries[i]);
     718           0 :       xfree (entries);
     719           0 :       return 0;
     720             :     }
     721             : 
     722             :   /* Compose the output array. */
     723           0 :   *out = '[';
     724           0 :   ptr = out + 1;
     725           0 :   *ptr = 0;
     726           0 :   for (i = 0; i < numentries; i++)
     727             :     {
     728           0 :       strcpy (ptr, entries[i]);
     729           0 :       ptr += strlen (entries[i]);
     730           0 :       if (i != numentries - 1)
     731             :         {
     732           0 :           *ptr++ = ',';
     733           0 :           if (fmt)
     734           0 :             *ptr++ = ' ';
     735           0 :           *ptr = 0;
     736             :         }
     737           0 :       xfree (entries[i]);
     738             :     }
     739           0 :   xfree (entries);
     740           0 :   *ptr++ = ']';
     741           0 :   *ptr++ = 0;
     742           0 :   return out;
     743             : }
     744             : 
     745             : /* Build an object from the text. */
     746             : static const char *
     747           0 : parse_object (cJSON * item, const char *value, const char **ep)
     748             : {
     749             :   cJSON *child;
     750           0 :   if (*value != '{')
     751             :     {
     752           0 :       *ep = value;
     753           0 :       return 0;
     754             :     }                           /* not an object! */
     755             : 
     756           0 :   item->type = cJSON_Object;
     757           0 :   value = skip (value + 1);
     758           0 :   if (*value == '}')
     759           0 :     return value + 1;           /* empty array. */
     760             : 
     761           0 :   item->child = child = cJSON_New_Item ();
     762           0 :   if (!item->child)
     763           0 :     return 0;
     764           0 :   value = skip (parse_string (child, skip (value), ep));
     765           0 :   if (!value)
     766           0 :     return 0;
     767           0 :   child->string = child->valuestring;
     768           0 :   child->valuestring = 0;
     769           0 :   if (*value != ':')
     770             :     {
     771           0 :       *ep = value;
     772           0 :       return 0;
     773             :     }                           /* fail! */
     774             :   /* skip any spacing, get the value. */
     775           0 :   value = skip (parse_value (child, skip (value + 1), ep));
     776           0 :   if (!value)
     777           0 :     return 0;
     778             : 
     779           0 :   while (*value == ',')
     780             :     {
     781             :       cJSON *new_item;
     782           0 :       if (!(new_item = cJSON_New_Item ()))
     783           0 :         return 0;               /* memory fail */
     784           0 :       child->next = new_item;
     785           0 :       new_item->prev = child;
     786           0 :       child = new_item;
     787           0 :       value = skip (parse_string (child, skip (value + 1), ep));
     788           0 :       if (!value)
     789           0 :         return 0;
     790           0 :       child->string = child->valuestring;
     791           0 :       child->valuestring = 0;
     792           0 :       if (*value != ':')
     793             :         {
     794           0 :           *ep = value;
     795           0 :           return 0;
     796             :         }                       /* fail! */
     797             :       /* skip any spacing, get the value. */
     798           0 :       value = skip (parse_value (child, skip (value + 1), ep));
     799           0 :       if (!value)
     800           0 :         return 0;
     801             :     }
     802             : 
     803           0 :   if (*value == '}')
     804           0 :     return value + 1;           /* end of array */
     805           0 :   *ep = value;
     806           0 :   return 0;                     /* malformed. */
     807             : }
     808             : 
     809             : /* Render an object to text. */
     810             : static char *
     811           0 : print_object (cJSON * item, int depth, int fmt)
     812             : {
     813           0 :   char **entries = 0, **names = 0;
     814           0 :   char *out = 0, *ptr, *ret, *str;
     815           0 :   int len = 7, i = 0, j;
     816           0 :   cJSON *child = item->child;
     817           0 :   int numentries = 0, fail = 0;
     818             :   /* Count the number of entries. */
     819           0 :   while (child)
     820           0 :     numentries++, child = child->next;
     821             :   /* Explicitly handle empty object case */
     822           0 :   if (!numentries)
     823             :     {
     824           0 :       out = xtrymalloc (fmt ? depth + 4 : 3);
     825           0 :       if (!out)
     826           0 :         return 0;
     827           0 :       ptr = out;
     828           0 :       *ptr++ = '{';
     829           0 :       if (fmt)
     830             :         {
     831           0 :           *ptr++ = '\n';
     832           0 :           for (i = 0; i < depth - 1; i++)
     833           0 :             *ptr++ = '\t';
     834             :         }
     835           0 :       *ptr++ = '}';
     836           0 :       *ptr++ = 0;
     837           0 :       return out;
     838             :     }
     839             :   /* Allocate space for the names and the objects */
     840           0 :   entries = xtrymalloc (numentries * sizeof (char *));
     841           0 :   if (!entries)
     842           0 :     return 0;
     843           0 :   names = xtrymalloc (numentries * sizeof (char *));
     844           0 :   if (!names)
     845             :     {
     846           0 :       xfree (entries);
     847           0 :       return 0;
     848             :     }
     849           0 :   memset (entries, 0, sizeof (char *) * numentries);
     850           0 :   memset (names, 0, sizeof (char *) * numentries);
     851             : 
     852             :   /* Collect all the results into our arrays: */
     853           0 :   child = item->child;
     854           0 :   depth++;
     855           0 :   if (fmt)
     856           0 :     len += depth;
     857           0 :   while (child)
     858             :     {
     859           0 :       names[i] = str = print_string_ptr (child->string);
     860           0 :       entries[i++] = ret = print_value (child, depth, fmt);
     861           0 :       if (str && ret)
     862           0 :         len += strlen (ret) + strlen (str) + 2 + (fmt ? 2 + depth : 0);
     863             :       else
     864           0 :         fail = 1;
     865           0 :       child = child->next;
     866             :     }
     867             : 
     868             :   /* Try to allocate the output string */
     869           0 :   if (!fail)
     870           0 :     out = xtrymalloc (len);
     871           0 :   if (!out)
     872           0 :     fail = 1;
     873             : 
     874             :   /* Handle failure */
     875           0 :   if (fail)
     876             :     {
     877           0 :       for (i = 0; i < numentries; i++)
     878             :         {
     879           0 :           if (names[i])
     880           0 :             xfree (names[i]);
     881           0 :           if (entries[i])
     882           0 :             xfree (entries[i]);
     883             :         }
     884           0 :       xfree (names);
     885           0 :       xfree (entries);
     886           0 :       return 0;
     887             :     }
     888             : 
     889             :   /* Compose the output: */
     890           0 :   *out = '{';
     891           0 :   ptr = out + 1;
     892           0 :   if (fmt)
     893           0 :     *ptr++ = '\n';
     894           0 :   *ptr = 0;
     895           0 :   for (i = 0; i < numentries; i++)
     896             :     {
     897           0 :       if (fmt)
     898           0 :         for (j = 0; j < depth; j++)
     899           0 :           *ptr++ = '\t';
     900           0 :       strcpy (ptr, names[i]);
     901           0 :       ptr += strlen (names[i]);
     902           0 :       *ptr++ = ':';
     903           0 :       if (fmt)
     904           0 :         *ptr++ = '\t';
     905           0 :       strcpy (ptr, entries[i]);
     906           0 :       ptr += strlen (entries[i]);
     907           0 :       if (i != numentries - 1)
     908           0 :         *ptr++ = ',';
     909           0 :       if (fmt)
     910           0 :         *ptr++ = '\n';
     911           0 :       *ptr = 0;
     912           0 :       xfree (names[i]);
     913           0 :       xfree (entries[i]);
     914             :     }
     915             : 
     916           0 :   xfree (names);
     917           0 :   xfree (entries);
     918           0 :   if (fmt)
     919           0 :     for (i = 0; i < depth - 1; i++)
     920           0 :       *ptr++ = '\t';
     921           0 :   *ptr++ = '}';
     922           0 :   *ptr++ = 0;
     923           0 :   return out;
     924             : }
     925             : 
     926             : /* Get Array size/item / object item. */
     927             : int
     928           0 : cJSON_GetArraySize (cJSON * array)
     929             : {
     930           0 :   cJSON *c = array->child;
     931           0 :   int i = 0;
     932           0 :   while (c)
     933           0 :     i++, c = c->next;
     934           0 :   return i;
     935             : }
     936             : 
     937             : cJSON *
     938           0 : cJSON_GetArrayItem (cJSON * array, int item)
     939             : {
     940           0 :   cJSON *c = array->child;
     941           0 :   while (c && item > 0)
     942           0 :     item--, c = c->next;
     943           0 :   return c;
     944             : }
     945             : 
     946             : cJSON *
     947           0 : cJSON_GetObjectItem (cJSON * object, const char *string)
     948             : {
     949           0 :   cJSON *c = object->child;
     950           0 :   while (c && cJSON_strcasecmp (c->string, string))
     951           0 :     c = c->next;
     952           0 :   return c;
     953             : }
     954             : 
     955             : /* Utility for array list handling. */
     956             : static void
     957           0 : suffix_object (cJSON * prev, cJSON * item)
     958             : {
     959           0 :   prev->next = item;
     960           0 :   item->prev = prev;
     961           0 : }
     962             : 
     963             : /* Utility for handling references. */
     964             : static cJSON *
     965           0 : create_reference (cJSON * item)
     966             : {
     967           0 :   cJSON *ref = cJSON_New_Item ();
     968           0 :   if (!ref)
     969           0 :     return 0;
     970           0 :   memcpy (ref, item, sizeof (cJSON));
     971           0 :   ref->string = 0;
     972           0 :   ref->type |= cJSON_IsReference;
     973           0 :   ref->next = ref->prev = 0;
     974           0 :   return ref;
     975             : }
     976             : 
     977             : /* Add item to array/object. */
     978             : void
     979           0 : cJSON_AddItemToArray (cJSON * array, cJSON * item)
     980             : {
     981             :   cJSON *c;
     982             : 
     983           0 :   if (!item || !array)
     984           0 :     return;
     985           0 :   c = array->child;
     986           0 :   if (!c)
     987             :     {
     988           0 :       array->child = item;
     989             :     }
     990             :   else
     991             :     {
     992           0 :       while (c && c->next)
     993           0 :         c = c->next;
     994           0 :       suffix_object (c, item);
     995             :     }
     996             : }
     997             : 
     998             : cJSON *
     999           0 : cJSON_AddItemToObject (cJSON * object, const char *string, cJSON * item)
    1000             : {
    1001             :   char *tmp;
    1002             : 
    1003           0 :   if (!item)
    1004           0 :     return 0;
    1005           0 :   tmp = xtrystrdup (string);
    1006           0 :   if (!tmp)
    1007           0 :     return NULL;
    1008             : 
    1009           0 :   if (item->string)
    1010           0 :     xfree (item->string);
    1011           0 :   item->string = tmp;
    1012           0 :   cJSON_AddItemToArray (object, item);
    1013           0 :   return object;
    1014             : }
    1015             : 
    1016             : cJSON *
    1017           0 : cJSON_AddNullToObject (cJSON *object, const char *name)
    1018             : {
    1019             :   cJSON *obj, *tmp;
    1020             : 
    1021           0 :   tmp = cJSON_CreateNull ();
    1022           0 :   if (!tmp)
    1023           0 :     return NULL;
    1024           0 :   obj = cJSON_AddItemToObject(object, name, tmp);
    1025           0 :   if (!obj)
    1026           0 :     cJSON_Delete (tmp);
    1027           0 :   return obj;
    1028             : }
    1029             : 
    1030             : cJSON *
    1031           0 : cJSON_AddTrueToObject (cJSON *object, const char *name)
    1032             : {
    1033             :   cJSON *obj, *tmp;
    1034             : 
    1035           0 :   tmp = cJSON_CreateTrue ();
    1036           0 :   if (!tmp)
    1037           0 :     return NULL;
    1038           0 :   obj = cJSON_AddItemToObject(object, name, tmp);
    1039           0 :   if (!obj)
    1040           0 :     cJSON_Delete (tmp);
    1041           0 :   return obj;
    1042             : }
    1043             : 
    1044             : cJSON *
    1045           0 : cJSON_AddFalseToObject (cJSON *object, const char *name)
    1046             : {
    1047             :   cJSON *obj, *tmp;
    1048             : 
    1049           0 :   tmp = cJSON_CreateFalse ();
    1050           0 :   if (!tmp)
    1051           0 :     return NULL;
    1052           0 :   obj = cJSON_AddItemToObject(object, name, tmp);
    1053           0 :   if (!obj)
    1054           0 :     cJSON_Delete (tmp);
    1055           0 :   return obj;
    1056             : }
    1057             : 
    1058             : cJSON *
    1059           0 : cJSON_AddBoolToObject (cJSON *object, const char *name, int b)
    1060             : {
    1061             :   cJSON *obj, *tmp;
    1062             : 
    1063           0 :   tmp = cJSON_CreateBool (b);
    1064           0 :   if (!tmp)
    1065           0 :     return NULL;
    1066           0 :   obj = cJSON_AddItemToObject(object, name, tmp);
    1067           0 :   if (!obj)
    1068           0 :     cJSON_Delete (tmp);
    1069           0 :   return obj;
    1070             : }
    1071             : 
    1072             : cJSON *
    1073           0 : cJSON_AddNumberToObject (cJSON *object, const char *name, double num)
    1074             : {
    1075             :   cJSON *obj, *tmp;
    1076             : 
    1077           0 :   tmp = cJSON_CreateNumber (num);
    1078           0 :   if (!tmp)
    1079           0 :     return NULL;
    1080           0 :   obj = cJSON_AddItemToObject(object, name, tmp);
    1081           0 :   if (!obj)
    1082           0 :     cJSON_Delete (tmp);
    1083           0 :   return obj;
    1084             : }
    1085             : 
    1086             : cJSON *
    1087           0 : cJSON_AddStringToObject (cJSON *object, const char *name, const char *string)
    1088             : {
    1089             :   cJSON *obj, *tmp;
    1090             : 
    1091           0 :   tmp = cJSON_CreateString (string);
    1092           0 :   if (!tmp)
    1093           0 :     return NULL;
    1094           0 :   obj = cJSON_AddItemToObject(object, name, tmp);
    1095           0 :   if (!obj)
    1096           0 :     cJSON_Delete (tmp);
    1097           0 :   return obj;
    1098             : }
    1099             : 
    1100             : void
    1101           0 : cJSON_AddItemReferenceToArray (cJSON * array, cJSON * item)
    1102             : {
    1103           0 :   cJSON_AddItemToArray (array, create_reference (item));
    1104           0 : }
    1105             : 
    1106             : void
    1107           0 : cJSON_AddItemReferenceToObject (cJSON * object, const char *string,
    1108             :                                 cJSON * item)
    1109             : {
    1110           0 :   cJSON_AddItemToObject (object, string, create_reference (item));
    1111           0 : }
    1112             : 
    1113             : cJSON *
    1114           0 : cJSON_DetachItemFromArray (cJSON * array, int which)
    1115             : {
    1116           0 :   cJSON *c = array->child;
    1117           0 :   while (c && which > 0)
    1118           0 :     c = c->next, which--;
    1119           0 :   if (!c)
    1120           0 :     return 0;
    1121           0 :   if (c->prev)
    1122           0 :     c->prev->next = c->next;
    1123           0 :   if (c->next)
    1124           0 :     c->next->prev = c->prev;
    1125           0 :   if (c == array->child)
    1126           0 :     array->child = c->next;
    1127           0 :   c->prev = c->next = 0;
    1128           0 :   return c;
    1129             : }
    1130             : 
    1131             : void
    1132           0 : cJSON_DeleteItemFromArray (cJSON * array, int which)
    1133             : {
    1134           0 :   cJSON_Delete (cJSON_DetachItemFromArray (array, which));
    1135           0 : }
    1136             : 
    1137             : cJSON *
    1138           0 : cJSON_DetachItemFromObject (cJSON * object, const char *string)
    1139             : {
    1140           0 :   int i = 0;
    1141           0 :   cJSON *c = object->child;
    1142           0 :   while (c && cJSON_strcasecmp (c->string, string))
    1143           0 :     i++, c = c->next;
    1144           0 :   if (c)
    1145           0 :     return cJSON_DetachItemFromArray (object, i);
    1146           0 :   return 0;
    1147             : }
    1148             : 
    1149             : void
    1150           0 : cJSON_DeleteItemFromObject (cJSON * object, const char *string)
    1151             : {
    1152           0 :   cJSON_Delete (cJSON_DetachItemFromObject (object, string));
    1153           0 : }
    1154             : 
    1155             : /* Replace array/object items with new ones. */
    1156             : void
    1157           0 : cJSON_ReplaceItemInArray (cJSON * array, int which, cJSON * newitem)
    1158             : {
    1159           0 :   cJSON *c = array->child;
    1160           0 :   while (c && which > 0)
    1161           0 :     c = c->next, which--;
    1162           0 :   if (!c)
    1163           0 :     return;
    1164           0 :   newitem->next = c->next;
    1165           0 :   newitem->prev = c->prev;
    1166           0 :   if (newitem->next)
    1167           0 :     newitem->next->prev = newitem;
    1168           0 :   if (c == array->child)
    1169           0 :     array->child = newitem;
    1170             :   else
    1171           0 :     newitem->prev->next = newitem;
    1172           0 :   c->next = c->prev = 0;
    1173           0 :   cJSON_Delete (c);
    1174             : }
    1175             : 
    1176             : void
    1177           0 : cJSON_ReplaceItemInObject (cJSON * object, const char *string,
    1178             :                            cJSON * newitem)
    1179             : {
    1180           0 :   int i = 0;
    1181           0 :   cJSON *c = object->child;
    1182           0 :   while (c && cJSON_strcasecmp (c->string, string))
    1183           0 :     i++, c = c->next;
    1184           0 :   if (c)
    1185             :     {
    1186             :       /* FIXME: I guess we should free newitem->string here.  See
    1187             :        * upstream commit 0d10e279c8b604f71829b5d49d092719f4ae96b6.  */
    1188           0 :       newitem->string = xtrystrdup (string);
    1189           0 :       cJSON_ReplaceItemInArray (object, i, newitem);
    1190             :     }
    1191           0 : }
    1192             : 
    1193             : /* Create basic types: */
    1194             : cJSON *
    1195           0 : cJSON_CreateNull (void)
    1196             : {
    1197           0 :   cJSON *item = cJSON_New_Item ();
    1198           0 :   if (item)
    1199           0 :     item->type = cJSON_NULL;
    1200           0 :   return item;
    1201             : }
    1202             : 
    1203             : cJSON *
    1204           0 : cJSON_CreateTrue (void)
    1205             : {
    1206           0 :   cJSON *item = cJSON_New_Item ();
    1207           0 :   if (item)
    1208           0 :     item->type = cJSON_True;
    1209           0 :   return item;
    1210             : }
    1211             : 
    1212             : cJSON *
    1213           0 : cJSON_CreateFalse (void)
    1214             : {
    1215           0 :   cJSON *item = cJSON_New_Item ();
    1216           0 :   if (item)
    1217           0 :     item->type = cJSON_False;
    1218           0 :   return item;
    1219             : }
    1220             : 
    1221             : cJSON *
    1222           0 : cJSON_CreateBool (int b)
    1223             : {
    1224           0 :   cJSON *item = cJSON_New_Item ();
    1225           0 :   if (item)
    1226           0 :     item->type = b ? cJSON_True : cJSON_False;
    1227           0 :   return item;
    1228             : }
    1229             : 
    1230             : cJSON *
    1231           0 : cJSON_CreateNumber (double num)
    1232             : {
    1233           0 :   cJSON *item = cJSON_New_Item ();
    1234           0 :   if (item)
    1235             :     {
    1236           0 :       item->type = cJSON_Number;
    1237           0 :       item->valuedouble = num;
    1238           0 :       item->valueint = (int) num;
    1239             :     }
    1240           0 :   return item;
    1241             : }
    1242             : 
    1243             : cJSON *
    1244           0 : cJSON_CreateString (const char *string)
    1245             : {
    1246           0 :   cJSON *item = cJSON_New_Item ();
    1247           0 :   if (item)
    1248             :     {
    1249           0 :       item->type = cJSON_String;
    1250           0 :       item->valuestring = xtrystrdup (string);
    1251             :     }
    1252           0 :   return item;
    1253             : }
    1254             : 
    1255             : cJSON *
    1256           0 : cJSON_CreateStringConvey (char *string)
    1257             : {
    1258           0 :   cJSON *item = cJSON_New_Item ();
    1259           0 :   if (item)
    1260             :     {
    1261           0 :       item->type = cJSON_String;
    1262           0 :       item->valuestring = string;
    1263             :     }
    1264           0 :   return item;
    1265             : }
    1266             : 
    1267             : cJSON *
    1268           0 : cJSON_CreateArray (void)
    1269             : {
    1270           0 :   cJSON *item = cJSON_New_Item ();
    1271           0 :   if (item)
    1272           0 :     item->type = cJSON_Array;
    1273           0 :   return item;
    1274             : }
    1275             : 
    1276             : cJSON *
    1277           0 : cJSON_CreateObject (void)
    1278             : {
    1279           0 :   cJSON *item = cJSON_New_Item ();
    1280           0 :   if (item)
    1281           0 :     item->type = cJSON_Object;
    1282           0 :   return item;
    1283             : }
    1284             : 
    1285             : /* Create Arrays: */
    1286             : cJSON *
    1287           0 : cJSON_CreateIntArray (const int *numbers, int count)
    1288             : {
    1289             :   int i;
    1290           0 :   cJSON *n = 0, *p = 0, *a = cJSON_CreateArray ();
    1291           0 :   for (i = 0; a && i < count; i++)
    1292             :     {
    1293           0 :       n = cJSON_CreateNumber (numbers[i]);
    1294           0 :       if (!i)
    1295           0 :         a->child = n;
    1296             :       else
    1297           0 :         suffix_object (p, n);
    1298           0 :       p = n;
    1299             :     }
    1300           0 :   return a;
    1301             : }
    1302             : 
    1303             : cJSON *
    1304           0 : cJSON_CreateFloatArray (const float *numbers, int count)
    1305             : {
    1306             :   int i;
    1307           0 :   cJSON *n = 0, *p = 0, *a = cJSON_CreateArray ();
    1308           0 :   for (i = 0; a && i < count; i++)
    1309             :     {
    1310           0 :       n = cJSON_CreateNumber (numbers[i]);
    1311           0 :       if (!i)
    1312           0 :         a->child = n;
    1313             :       else
    1314           0 :         suffix_object (p, n);
    1315           0 :       p = n;
    1316             :     }
    1317           0 :   return a;
    1318             : }
    1319             : 
    1320             : cJSON *
    1321           0 : cJSON_CreateDoubleArray (const double *numbers, int count)
    1322             : {
    1323             :   int i;
    1324           0 :   cJSON *n = 0, *p = 0, *a = cJSON_CreateArray ();
    1325           0 :   for (i = 0; a && i < count; i++)
    1326             :     {
    1327           0 :       n = cJSON_CreateNumber (numbers[i]);
    1328           0 :       if (!i)
    1329           0 :         a->child = n;
    1330             :       else
    1331           0 :         suffix_object (p, n);
    1332           0 :       p = n;
    1333             :     }
    1334           0 :   return a;
    1335             : }
    1336             : 
    1337             : cJSON *
    1338           0 : cJSON_CreateStringArray (const char **strings, int count)
    1339             : {
    1340             :   int i;
    1341           0 :   cJSON *n = 0, *p = 0, *a = cJSON_CreateArray ();
    1342           0 :   for (i = 0; a && i < count; i++)
    1343             :     {
    1344           0 :       n = cJSON_CreateString (strings[i]);
    1345           0 :       if (!i)
    1346           0 :         a->child = n;
    1347             :       else
    1348           0 :         suffix_object (p, n);
    1349           0 :       p = n;
    1350             :     }
    1351           0 :   return a;
    1352             : }
    1353             : 
    1354             : /* Duplication */
    1355             : cJSON *
    1356           0 : cJSON_Duplicate (cJSON * item, int recurse)
    1357             : {
    1358           0 :   cJSON *newitem, *cptr, *nptr = 0, *newchild;
    1359             :   /* Bail on bad ptr */
    1360           0 :   if (!item)
    1361           0 :     return 0;
    1362             :   /* Create new item */
    1363           0 :   newitem = cJSON_New_Item ();
    1364           0 :   if (!newitem)
    1365           0 :     return 0;
    1366             :   /* Copy over all vars */
    1367           0 :   newitem->type = item->type & (~cJSON_IsReference), newitem->valueint =
    1368           0 :     item->valueint, newitem->valuedouble = item->valuedouble;
    1369           0 :   if (item->valuestring)
    1370             :     {
    1371           0 :       newitem->valuestring = xtrystrdup (item->valuestring);
    1372           0 :       if (!newitem->valuestring)
    1373             :         {
    1374           0 :           cJSON_Delete (newitem);
    1375           0 :           return 0;
    1376             :         }
    1377             :     }
    1378           0 :   if (item->string)
    1379             :     {
    1380           0 :       newitem->string = xtrystrdup (item->string);
    1381           0 :       if (!newitem->string)
    1382             :         {
    1383           0 :           cJSON_Delete (newitem);
    1384           0 :           return 0;
    1385             :         }
    1386             :     }
    1387             :   /* If non-recursive, then we're done! */
    1388           0 :   if (!recurse)
    1389           0 :     return newitem;
    1390             :   /* Walk the ->next chain for the child. */
    1391           0 :   cptr = item->child;
    1392           0 :   while (cptr)
    1393             :     {
    1394             :       /* Duplicate (with recurse) each item in the ->next chain */
    1395           0 :       newchild = cJSON_Duplicate (cptr, 1);
    1396           0 :       if (!newchild)
    1397             :         {
    1398           0 :           cJSON_Delete (newitem);
    1399           0 :           return 0;
    1400             :         }
    1401           0 :       if (nptr)
    1402             :         {
    1403             :           /* If newitem->child already set,
    1404             :            * then crosswire ->prev and ->next and move on.  */
    1405           0 :           nptr->next = newchild, newchild->prev = nptr;
    1406           0 :           nptr = newchild;
    1407             :         }
    1408             :       else
    1409             :         {
    1410             :           /* Set newitem->child and move to it.  */
    1411           0 :           newitem->child = newchild;
    1412           0 :           nptr = newchild;
    1413             :         }
    1414           0 :       cptr = cptr->next;
    1415             :     }
    1416           0 :   return newitem;
    1417             : }
    1418             : 
    1419             : void
    1420           0 : cJSON_Minify (char *json)
    1421             : {
    1422           0 :   char *into = json;
    1423           0 :   while (*json)
    1424             :     {
    1425           0 :       if (*json == ' ')
    1426           0 :         json++;
    1427           0 :       else if (*json == '\t')
    1428           0 :         json++;                 /* Whitespace characters.  */
    1429           0 :       else if (*json == '\r')
    1430           0 :         json++;
    1431           0 :       else if (*json == '\n')
    1432           0 :         json++;
    1433           0 :       else if (*json == '/' && json[1] == '/')
    1434           0 :         while (*json && *json != '\n')
    1435           0 :           json++;               /* Double-slash comments, to end of line.  */
    1436           0 :       else if (*json == '/' && json[1] == '*')
    1437             :         {
    1438           0 :           while (*json && !(*json == '*' && json[1] == '/'))
    1439           0 :             json++;
    1440           0 :           json += 2;
    1441             :         }                       /* Multiline comments.  */
    1442           0 :       else if (*json == '\"')
    1443             :         {
    1444           0 :           *into++ = *json++;
    1445           0 :           while (*json && *json != '\"')
    1446             :             {
    1447           0 :               if (*json == '\\')
    1448           0 :                 *into++ = *json++;
    1449           0 :               if (*json)
    1450           0 :                 *into++ = *json++;
    1451             :             }
    1452           0 :           if (*json)
    1453           0 :             *into++ = *json++;
    1454             :         }                       /* String literals, which are \" sensitive.  */
    1455             :       else
    1456           0 :         *into++ = *json++;      /* All other characters.  */
    1457             :     }
    1458           0 :   *into = 0;                    /* and null-terminate.  */
    1459           0 : }

Generated by: LCOV version 1.13