|  | @@ -241,9 +241,9 @@ static unsigned char* ensure(printbuffer *p, size_t needed)
 | 
	
		
			
				|  |  |      unsigned char *newbuffer = NULL;
 | 
	
		
			
				|  |  |      size_t newsize = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (p == NULL)
 | 
	
		
			
				|  |  | +    if ((p == NULL) || (p->buffer == NULL))
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | -        return (unsigned char*)cJSON_malloc(needed);
 | 
	
		
			
				|  |  | +        return NULL;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (needed > INT_MAX)
 | 
	
	
		
			
				|  | @@ -252,10 +252,6 @@ static unsigned char* ensure(printbuffer *p, size_t needed)
 | 
	
		
			
				|  |  |          return NULL;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (p->buffer == NULL)
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        return NULL;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  |      needed += p->offset;
 | 
	
		
			
				|  |  |      if (needed <= p->length)
 | 
	
		
			
				|  |  |      {
 | 
	
	
		
			
				|  | @@ -328,6 +324,12 @@ static unsigned char *print_number(const cJSON *item, printbuffer *p)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      unsigned char *str = NULL;
 | 
	
		
			
				|  |  |      double d = item->valuedouble;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (p == NULL)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        return NULL;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      /* special case for 0. */
 | 
	
		
			
				|  |  |      if (d == 0)
 | 
	
		
			
				|  |  |      {
 | 
	
	
		
			
				|  | @@ -678,6 +680,11 @@ static unsigned char *print_string_ptr(const unsigned char *str, printbuffer *p)
 | 
	
		
			
				|  |  |      cjbool flag = false;
 | 
	
		
			
				|  |  |      unsigned char token = '\0';
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    if (p == NULL)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        return NULL;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      /* empty string */
 | 
	
		
			
				|  |  |      if (!str)
 | 
	
		
			
				|  |  |      {
 | 
	
	
		
			
				|  | @@ -865,15 +872,66 @@ cJSON *cJSON_Parse(const char *value)
 | 
	
		
			
				|  |  |      return cJSON_ParseWithOpts(value, 0, 0);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#define min(a, b) ((a < b) ? a : b)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static unsigned char *print(const cJSON * const item, cjbool format)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    printbuffer buffer[1];
 | 
	
		
			
				|  |  | +    unsigned char *printed = NULL;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    memset(buffer, 0, sizeof(buffer));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /* create buffer */
 | 
	
		
			
				|  |  | +    buffer->buffer = (unsigned char*) cJSON_malloc(256);
 | 
	
		
			
				|  |  | +    if (buffer->buffer == NULL)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        goto fail;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /* print the value */
 | 
	
		
			
				|  |  | +    if (print_value(item, 0, format, buffer) == NULL)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        goto fail;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    buffer->offset = update(buffer); /* update the length of the string */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /* copy the buffer over to a new one */
 | 
	
		
			
				|  |  | +    printed = (unsigned char*) cJSON_malloc(buffer->offset + 1);
 | 
	
		
			
				|  |  | +    if (printed == NULL)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        goto fail;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    strncpy((char*)printed, (char*)buffer->buffer, min(buffer->length, buffer->offset + 1));
 | 
	
		
			
				|  |  | +    printed[buffer->offset] = '\0'; /* just to be sure */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /* free the buffer */
 | 
	
		
			
				|  |  | +    cJSON_free(buffer->buffer);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return printed;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +fail:
 | 
	
		
			
				|  |  | +    if (buffer->buffer != NULL)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        cJSON_free(buffer->buffer);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (printed != NULL)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        cJSON_free(printed);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return NULL;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /* Render a cJSON item/entity/structure to text. */
 | 
	
		
			
				|  |  |  char *cJSON_Print(const cJSON *item)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -    return (char*)print_value(item, 0, 1, 0);
 | 
	
		
			
				|  |  | +    return (char*)print(item, true);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  char *cJSON_PrintUnformatted(const cJSON *item)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -    return (char*)print_value(item, 0, 0, 0);
 | 
	
		
			
				|  |  | +    return (char*)print(item, false);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  char *cJSON_PrintBuffered(const cJSON *item, int prebuffer, cjbool fmt)
 | 
	
	
		
			
				|  | @@ -977,101 +1035,71 @@ static unsigned char *print_value(const cJSON *item, size_t depth, cjbool fmt, p
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |          return NULL;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    if (p)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (p == NULL)
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | -        switch ((item->type) & 0xFF)
 | 
	
		
			
				|  |  | +        return NULL;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    switch ((item->type) & 0xFF)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        case cJSON_NULL:
 | 
	
		
			
				|  |  | +            out = ensure(p, 5);
 | 
	
		
			
				|  |  | +            if (out != NULL)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                strcpy((char*)out, "null");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            break;
 | 
	
		
			
				|  |  | +        case cJSON_False:
 | 
	
		
			
				|  |  | +            out = ensure(p, 6);
 | 
	
		
			
				|  |  | +            if (out != NULL)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                strcpy((char*)out, "false");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            break;
 | 
	
		
			
				|  |  | +        case cJSON_True:
 | 
	
		
			
				|  |  | +            out = ensure(p, 5);
 | 
	
		
			
				|  |  | +            if (out != NULL)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                strcpy((char*)out, "true");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            break;
 | 
	
		
			
				|  |  | +        case cJSON_Number:
 | 
	
		
			
				|  |  | +            out = print_number(item, p);
 | 
	
		
			
				|  |  | +            break;
 | 
	
		
			
				|  |  | +        case cJSON_Raw:
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            case cJSON_NULL:
 | 
	
		
			
				|  |  | -                out = ensure(p, 5);
 | 
	
		
			
				|  |  | -                if (out != NULL)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    strcpy((char*)out, "null");
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | -            case cJSON_False:
 | 
	
		
			
				|  |  | -                out = ensure(p, 6);
 | 
	
		
			
				|  |  | -                if (out != NULL)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    strcpy((char*)out, "false");
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | -            case cJSON_True:
 | 
	
		
			
				|  |  | -                out = ensure(p, 5);
 | 
	
		
			
				|  |  | -                if (out != NULL)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    strcpy((char*)out, "true");
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | -            case cJSON_Number:
 | 
	
		
			
				|  |  | -                out = print_number(item, p);
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | -            case cJSON_Raw:
 | 
	
		
			
				|  |  | +            size_t raw_length = 0;
 | 
	
		
			
				|  |  | +            if (item->valuestring == NULL)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                size_t raw_length = 0;
 | 
	
		
			
				|  |  | -                if (item->valuestring == NULL)
 | 
	
		
			
				|  |  | +                if (!p->noalloc)
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  | -                    if (!p->noalloc)
 | 
	
		
			
				|  |  | -                    {
 | 
	
		
			
				|  |  | -                        cJSON_free(p->buffer);
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    out = NULL;
 | 
	
		
			
				|  |  | -                    break;
 | 
	
		
			
				|  |  | +                    cJSON_free(p->buffer);
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                raw_length = strlen(item->valuestring) + sizeof('\0');
 | 
	
		
			
				|  |  | -                out = ensure(p, raw_length);
 | 
	
		
			
				|  |  | -                if (out != NULL)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    memcpy(out, item->valuestring, raw_length);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            case cJSON_String:
 | 
	
		
			
				|  |  | -                out = print_string(item, p);
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | -            case cJSON_Array:
 | 
	
		
			
				|  |  | -                out = print_array(item, depth, fmt, p);
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | -            case cJSON_Object:
 | 
	
		
			
				|  |  | -                out = print_object(item, depth, fmt, p);
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | -            default:
 | 
	
		
			
				|  |  | -                out = NULL;
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    else
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        switch ((item->type) & 0xFF)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            case cJSON_NULL:
 | 
	
		
			
				|  |  | -                out = cJSON_strdup((const unsigned char*)"null");
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | -            case cJSON_False:
 | 
	
		
			
				|  |  | -                out = cJSON_strdup((const unsigned char*)"false");
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | -            case cJSON_True:
 | 
	
		
			
				|  |  | -                out = cJSON_strdup((const unsigned char*)"true");
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | -            case cJSON_Number:
 | 
	
		
			
				|  |  | -                out = print_number(item, 0);
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | -            case cJSON_Raw:
 | 
	
		
			
				|  |  | -                out = cJSON_strdup((unsigned char*)item->valuestring);
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | -            case cJSON_String:
 | 
	
		
			
				|  |  | -                out = print_string(item, 0);
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | -            case cJSON_Array:
 | 
	
		
			
				|  |  | -                out = print_array(item, depth, fmt, 0);
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | -            case cJSON_Object:
 | 
	
		
			
				|  |  | -                out = print_object(item, depth, fmt, 0);
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | -            default:
 | 
	
		
			
				|  |  |                  out = NULL;
 | 
	
		
			
				|  |  |                  break;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            raw_length = strlen(item->valuestring) + sizeof('\0');
 | 
	
		
			
				|  |  | +            out = ensure(p, raw_length);
 | 
	
		
			
				|  |  | +            if (out != NULL)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                memcpy(out, item->valuestring, raw_length);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            break;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        case cJSON_String:
 | 
	
		
			
				|  |  | +            out = print_string(item, p);
 | 
	
		
			
				|  |  | +            break;
 | 
	
		
			
				|  |  | +        case cJSON_Array:
 | 
	
		
			
				|  |  | +            out = print_array(item, depth, fmt, p);
 | 
	
		
			
				|  |  | +            break;
 | 
	
		
			
				|  |  | +        case cJSON_Object:
 | 
	
		
			
				|  |  | +            out = print_object(item, depth, fmt, p);
 | 
	
		
			
				|  |  | +            break;
 | 
	
		
			
				|  |  | +        default:
 | 
	
		
			
				|  |  | +            out = NULL;
 | 
	
		
			
				|  |  | +            break;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      return out;
 | 
	
	
		
			
				|  | @@ -1158,16 +1186,18 @@ fail:
 | 
	
		
			
				|  |  |  /* Render an array to text */
 | 
	
		
			
				|  |  |  static unsigned char *print_array(const cJSON *item, size_t depth, cjbool fmt, printbuffer *p)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -    unsigned char **entries;
 | 
	
		
			
				|  |  |      unsigned char *out = NULL;
 | 
	
		
			
				|  |  |      unsigned char *ptr = NULL;
 | 
	
		
			
				|  |  | -    unsigned char *ret = NULL;
 | 
	
		
			
				|  |  |      size_t len = 5;
 | 
	
		
			
				|  |  |      cJSON *child = item->child;
 | 
	
		
			
				|  |  |      size_t numentries = 0;
 | 
	
		
			
				|  |  |      size_t i = 0;
 | 
	
		
			
				|  |  |      cjbool fail = false;
 | 
	
		
			
				|  |  | -    size_t tmplen = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (p == NULL)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        return NULL;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /* How many entries in the array? */
 | 
	
		
			
				|  |  |      while (child)
 | 
	
	
		
			
				|  | @@ -1188,131 +1218,51 @@ static unsigned char *print_array(const cJSON *item, size_t depth, cjbool fmt, p
 | 
	
		
			
				|  |  |          return out;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (p)
 | 
	
		
			
				|  |  | +    /* Compose the output array. */
 | 
	
		
			
				|  |  | +    /* opening square bracket */
 | 
	
		
			
				|  |  | +    i = p->offset;
 | 
	
		
			
				|  |  | +    ptr = ensure(p, 1);
 | 
	
		
			
				|  |  | +    if (ptr == NULL)
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | -        /* Compose the output array. */
 | 
	
		
			
				|  |  | -        /* opening square bracket */
 | 
	
		
			
				|  |  | -        i = p->offset;
 | 
	
		
			
				|  |  | -        ptr = ensure(p, 1);
 | 
	
		
			
				|  |  | -        if (ptr == NULL)
 | 
	
		
			
				|  |  | +        return NULL;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    *ptr = '[';
 | 
	
		
			
				|  |  | +    p->offset++;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    child = item->child;
 | 
	
		
			
				|  |  | +    while (child && !fail)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        if (!print_value(child, depth + 1, fmt, p))
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              return NULL;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        *ptr = '[';
 | 
	
		
			
				|  |  | -        p->offset++;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        child = item->child;
 | 
	
		
			
				|  |  | -        while (child && !fail)
 | 
	
		
			
				|  |  | +        p->offset = update(p);
 | 
	
		
			
				|  |  | +        if (child->next)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            if (!print_value(child, depth + 1, fmt, p))
 | 
	
		
			
				|  |  | +            len = fmt ? 2 : 1;
 | 
	
		
			
				|  |  | +            ptr = ensure(p, len + 1);
 | 
	
		
			
				|  |  | +            if (ptr == NULL)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  return NULL;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            p->offset = update(p);
 | 
	
		
			
				|  |  | -            if (child->next)
 | 
	
		
			
				|  |  | +            *ptr++ = ',';
 | 
	
		
			
				|  |  | +            if(fmt)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                len = fmt ? 2 : 1;
 | 
	
		
			
				|  |  | -                ptr = ensure(p, len + 1);
 | 
	
		
			
				|  |  | -                if (ptr == NULL)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    return NULL;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                *ptr++ = ',';
 | 
	
		
			
				|  |  | -                if(fmt)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    *ptr++ = ' ';
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                *ptr = '\0';
 | 
	
		
			
				|  |  | -                p->offset += len;
 | 
	
		
			
				|  |  | +                *ptr++ = ' ';
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            child = child->next;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        ptr = ensure(p, 2);
 | 
	
		
			
				|  |  | -        if (ptr == NULL)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            return NULL;
 | 
	
		
			
				|  |  | +            *ptr = '\0';
 | 
	
		
			
				|  |  | +            p->offset += len;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        *ptr++ = ']';
 | 
	
		
			
				|  |  | -        *ptr = '\0';
 | 
	
		
			
				|  |  | -        out = (p->buffer) + i;
 | 
	
		
			
				|  |  | +        child = child->next;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    else
 | 
	
		
			
				|  |  | +    ptr = ensure(p, 2);
 | 
	
		
			
				|  |  | +    if (ptr == NULL)
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | -        /* Allocate an array to hold the pointers to all printed values */
 | 
	
		
			
				|  |  | -        entries = (unsigned char**)cJSON_malloc(numentries * sizeof(unsigned char*));
 | 
	
		
			
				|  |  | -        if (!entries)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            return NULL;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        memset(entries, '\0', numentries * sizeof(unsigned char*));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        /* Retrieve all the results: */
 | 
	
		
			
				|  |  | -        child = item->child;
 | 
	
		
			
				|  |  | -        while (child && !fail)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            ret = print_value(child, depth + 1, fmt, 0);
 | 
	
		
			
				|  |  | -            entries[i++] = ret;
 | 
	
		
			
				|  |  | -            if (ret)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                len += strlen((char*)ret) + 2 + (fmt ? 1 : 0);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            else
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                fail = true;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            child = child->next;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        /* If we didn't fail, try to malloc the output string */
 | 
	
		
			
				|  |  | -        if (!fail)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            out = (unsigned char*)cJSON_malloc(len);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        /* If that fails, we fail. */
 | 
	
		
			
				|  |  | -        if (!out)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            fail = true;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        /* Handle failure. */
 | 
	
		
			
				|  |  | -        if (fail)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            /* free all the entries in the array */
 | 
	
		
			
				|  |  | -            for (i = 0; i < numentries; i++)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                if (entries[i])
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    cJSON_free(entries[i]);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            cJSON_free(entries);
 | 
	
		
			
				|  |  | -            return NULL;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        /* Compose the output array. */
 | 
	
		
			
				|  |  | -        *out='[';
 | 
	
		
			
				|  |  | -        ptr = out + 1;
 | 
	
		
			
				|  |  | -        *ptr = '\0';
 | 
	
		
			
				|  |  | -        for (i = 0; i < numentries; i++)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            tmplen = strlen((char*)entries[i]);
 | 
	
		
			
				|  |  | -            memcpy(ptr, entries[i], tmplen);
 | 
	
		
			
				|  |  | -            ptr += tmplen;
 | 
	
		
			
				|  |  | -            if (i != (numentries - 1))
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                *ptr++ = ',';
 | 
	
		
			
				|  |  | -                if(fmt)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    *ptr++ = ' ';
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                *ptr = '\0';
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            cJSON_free(entries[i]);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        cJSON_free(entries);
 | 
	
		
			
				|  |  | -        *ptr++ = ']';
 | 
	
		
			
				|  |  | -        *ptr++ = '\0';
 | 
	
		
			
				|  |  | +        return NULL;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    *ptr++ = ']';
 | 
	
		
			
				|  |  | +    *ptr = '\0';
 | 
	
		
			
				|  |  | +    out = (p->buffer) + i;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      return out;
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -1415,19 +1365,18 @@ fail:
 | 
	
		
			
				|  |  |  /* Render an object to text. */
 | 
	
		
			
				|  |  |  static unsigned char *print_object(const cJSON *item, size_t depth, cjbool fmt, printbuffer *p)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -    unsigned char **entries = NULL;
 | 
	
		
			
				|  |  | -    unsigned char **names = NULL;
 | 
	
		
			
				|  |  |      unsigned char *out = NULL;
 | 
	
		
			
				|  |  |      unsigned char *ptr = NULL;
 | 
	
		
			
				|  |  | -    unsigned char *ret = NULL;
 | 
	
		
			
				|  |  | -    unsigned char *str = NULL;
 | 
	
		
			
				|  |  |      size_t len = 7;
 | 
	
		
			
				|  |  |      size_t i = 0;
 | 
	
		
			
				|  |  |      size_t j = 0;
 | 
	
		
			
				|  |  |      cJSON *child = item->child;
 | 
	
		
			
				|  |  |      size_t numentries = 0;
 | 
	
		
			
				|  |  | -    cjbool fail = false;
 | 
	
		
			
				|  |  | -    size_t tmplen = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (p == NULL)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        return NULL;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /* Count the number of entries. */
 | 
	
		
			
				|  |  |      while (child)
 | 
	
	
		
			
				|  | @@ -1459,229 +1408,105 @@ static unsigned char *print_object(const cJSON *item, size_t depth, cjbool fmt,
 | 
	
		
			
				|  |  |          return out;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (p)
 | 
	
		
			
				|  |  | +    /* Compose the output: */
 | 
	
		
			
				|  |  | +    i = p->offset;
 | 
	
		
			
				|  |  | +    len = fmt ? 2 : 1; /* fmt: {\n */
 | 
	
		
			
				|  |  | +    ptr = ensure(p, len + 1);
 | 
	
		
			
				|  |  | +    if (ptr == NULL)
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | -        /* Compose the output: */
 | 
	
		
			
				|  |  | -        i = p->offset;
 | 
	
		
			
				|  |  | -        len = fmt ? 2 : 1; /* fmt: {\n */
 | 
	
		
			
				|  |  | -        ptr = ensure(p, len + 1);
 | 
	
		
			
				|  |  | -        if (ptr == NULL)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            return NULL;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +        return NULL;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        *ptr++ = '{';
 | 
	
		
			
				|  |  | -        if (fmt)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            *ptr++ = '\n';
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        *ptr = '\0';
 | 
	
		
			
				|  |  | -        p->offset += len;
 | 
	
		
			
				|  |  | +    *ptr++ = '{';
 | 
	
		
			
				|  |  | +    if (fmt)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        *ptr++ = '\n';
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    *ptr = '\0';
 | 
	
		
			
				|  |  | +    p->offset += len;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        child = item->child;
 | 
	
		
			
				|  |  | -        depth++;
 | 
	
		
			
				|  |  | -        while (child)
 | 
	
		
			
				|  |  | +    child = item->child;
 | 
	
		
			
				|  |  | +    depth++;
 | 
	
		
			
				|  |  | +    while (child)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        if (fmt)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            if (fmt)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                ptr = ensure(p, depth);
 | 
	
		
			
				|  |  | -                if (ptr == NULL)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    return NULL;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                for (j = 0; j < depth; j++)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    *ptr++ = '\t';
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                p->offset += depth;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            /* print key */
 | 
	
		
			
				|  |  | -            if (!print_string_ptr((unsigned char*)child->string, p))
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                return NULL;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            p->offset = update(p);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            len = fmt ? 2 : 1;
 | 
	
		
			
				|  |  | -            ptr = ensure(p, len);
 | 
	
		
			
				|  |  | +            ptr = ensure(p, depth);
 | 
	
		
			
				|  |  |              if (ptr == NULL)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  return NULL;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            *ptr++ = ':';
 | 
	
		
			
				|  |  | -            if (fmt)
 | 
	
		
			
				|  |  | +            for (j = 0; j < depth; j++)
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  *ptr++ = '\t';
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            p->offset+=len;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            /* print value */
 | 
	
		
			
				|  |  | -            if (!print_value(child, depth, fmt, p))
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                return NULL;
 | 
	
		
			
				|  |  | -            };
 | 
	
		
			
				|  |  | -            p->offset = update(p);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            /* print comma if not last */
 | 
	
		
			
				|  |  | -            len = (size_t) (fmt ? 1 : 0) + (child->next ? 1 : 0);
 | 
	
		
			
				|  |  | -            ptr = ensure(p, len + 1);
 | 
	
		
			
				|  |  | -            if (ptr == NULL)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                return NULL;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            if (child->next)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                *ptr++ = ',';
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            if (fmt)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                *ptr++ = '\n';
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            *ptr = '\0';
 | 
	
		
			
				|  |  | -            p->offset += len;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            child = child->next;
 | 
	
		
			
				|  |  | +            p->offset += depth;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        ptr = ensure(p, fmt ? (depth + 1) : 2);
 | 
	
		
			
				|  |  | -        if (ptr == NULL)
 | 
	
		
			
				|  |  | +        /* print key */
 | 
	
		
			
				|  |  | +        if (!print_string_ptr((unsigned char*)child->string, p))
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              return NULL;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        if (fmt)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            for (i = 0; i < (depth - 1); i++)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                *ptr++ = '\t';
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        *ptr++ = '}';
 | 
	
		
			
				|  |  | -        *ptr = '\0';
 | 
	
		
			
				|  |  | -        out = (p->buffer) + i;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    else
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        /* Allocate space for the names and the objects */
 | 
	
		
			
				|  |  | -        entries = (unsigned char**)cJSON_malloc(numentries * sizeof(unsigned char*));
 | 
	
		
			
				|  |  | -        if (!entries)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            return NULL;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        names = (unsigned char**)cJSON_malloc(numentries * sizeof(unsigned char*));
 | 
	
		
			
				|  |  | -        if (!names)
 | 
	
		
			
				|  |  | +        p->offset = update(p);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        len = fmt ? 2 : 1;
 | 
	
		
			
				|  |  | +        ptr = ensure(p, len);
 | 
	
		
			
				|  |  | +        if (ptr == NULL)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            cJSON_free(entries);
 | 
	
		
			
				|  |  |              return NULL;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        memset(entries, '\0', sizeof(unsigned char*) * numentries);
 | 
	
		
			
				|  |  | -        memset(names, '\0', sizeof(unsigned char*) * numentries);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        /* Collect all the results into our arrays: */
 | 
	
		
			
				|  |  | -        child = item->child;
 | 
	
		
			
				|  |  | -        depth++;
 | 
	
		
			
				|  |  | +        *ptr++ = ':';
 | 
	
		
			
				|  |  |          if (fmt)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            len += depth;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        while (child && !fail)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            names[i] = str = print_string_ptr((unsigned char*)child->string, 0); /* print key */
 | 
	
		
			
				|  |  | -            entries[i++] = ret = print_value(child, depth, fmt, 0);
 | 
	
		
			
				|  |  | -            if (str && ret)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                len += strlen((char*)ret) + strlen((char*)str) + 2 + (fmt ? 2 + depth : 0);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            else
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                fail = true;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            child = child->next;
 | 
	
		
			
				|  |  | +            *ptr++ = '\t';
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        p->offset+=len;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        /* Try to allocate the output string */
 | 
	
		
			
				|  |  | -        if (!fail)
 | 
	
		
			
				|  |  | +        /* print value */
 | 
	
		
			
				|  |  | +        if (!print_value(child, depth, fmt, p))
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            out = (unsigned char*)cJSON_malloc(len);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        if (!out)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            fail = true;
 | 
	
		
			
				|  |  | +            return NULL;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        p->offset = update(p);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        /* Handle failure */
 | 
	
		
			
				|  |  | -        if (fail)
 | 
	
		
			
				|  |  | +        /* print comma if not last */
 | 
	
		
			
				|  |  | +        len = (size_t) (fmt ? 1 : 0) + (child->next ? 1 : 0);
 | 
	
		
			
				|  |  | +        ptr = ensure(p, len + 1);
 | 
	
		
			
				|  |  | +        if (ptr == NULL)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            /* free all the printed keys and values */
 | 
	
		
			
				|  |  | -            for (i = 0; i < numentries; i++)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                if (names[i])
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    cJSON_free(names[i]);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                if (entries[i])
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    cJSON_free(entries[i]);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            cJSON_free(names);
 | 
	
		
			
				|  |  | -            cJSON_free(entries);
 | 
	
		
			
				|  |  |              return NULL;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        if (child->next)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            *ptr++ = ',';
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        /* Compose the output: */
 | 
	
		
			
				|  |  | -        *out = '{';
 | 
	
		
			
				|  |  | -        ptr = out + 1;
 | 
	
		
			
				|  |  |          if (fmt)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              *ptr++ = '\n';
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          *ptr = '\0';
 | 
	
		
			
				|  |  | -        for (i = 0; i < numentries; i++)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            if (fmt)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                for (j = 0; j < depth; j++)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    *ptr++='\t';
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            tmplen = strlen((char*)names[i]);
 | 
	
		
			
				|  |  | -            memcpy(ptr, names[i], tmplen);
 | 
	
		
			
				|  |  | -            ptr += tmplen;
 | 
	
		
			
				|  |  | -            *ptr++ = ':';
 | 
	
		
			
				|  |  | -            if (fmt)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                *ptr++ = '\t';
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            strcpy((char*)ptr, (char*)entries[i]);
 | 
	
		
			
				|  |  | -            ptr += strlen((char*)entries[i]);
 | 
	
		
			
				|  |  | -            if (i != (numentries - 1))
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                *ptr++ = ',';
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            if (fmt)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                *ptr++ = '\n';
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            *ptr = '\0';
 | 
	
		
			
				|  |  | -            cJSON_free(names[i]);
 | 
	
		
			
				|  |  | -            cJSON_free(entries[i]);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +        p->offset += len;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        cJSON_free(names);
 | 
	
		
			
				|  |  | -        cJSON_free(entries);
 | 
	
		
			
				|  |  | -        if (fmt)
 | 
	
		
			
				|  |  | +        child = child->next;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    ptr = ensure(p, fmt ? (depth + 1) : 2);
 | 
	
		
			
				|  |  | +    if (ptr == NULL)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        return NULL;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if (fmt)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        for (i = 0; i < (depth - 1); i++)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            for (i = 0; i < (depth - 1); i++)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                *ptr++ = '\t';
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +            *ptr++ = '\t';
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        *ptr++ = '}';
 | 
	
		
			
				|  |  | -        *ptr++ = '\0';
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    *ptr++ = '}';
 | 
	
		
			
				|  |  | +    *ptr = '\0';
 | 
	
		
			
				|  |  | +    out = (p->buffer) + i;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      return out;
 | 
	
		
			
				|  |  |  }
 |