|  | @@ -122,6 +122,7 @@ typedef struct internal_context
 | 
											
												
													
														|  |      cJSON_bool format;
 |  |      cJSON_bool format;
 | 
											
												
													
														|  |      cJSON_bool allow_data_after_json;
 |  |      cJSON_bool allow_data_after_json;
 | 
											
												
													
														|  |      cJSON_bool case_sensitive;
 |  |      cJSON_bool case_sensitive;
 | 
											
												
													
														|  | 
 |  | +    cJSON_bool duplicate_recursive;
 | 
											
												
													
														|  |      cJSON_Allocators allocators;
 |  |      cJSON_Allocators allocators;
 | 
											
												
													
														|  |      void *userdata;
 |  |      void *userdata;
 | 
											
												
													
														|  |      size_t end_position;
 |  |      size_t end_position;
 | 
											
										
											
												
													
														|  | @@ -196,6 +197,7 @@ static void deallocate(const internal_context * const context, void *pointer)
 | 
											
												
													
														|  |      true, /* enable formatting by default */\
 |  |      true, /* enable formatting by default */\
 | 
											
												
													
														|  |      true, /* allow data after the JSON by default */\
 |  |      true, /* allow data after the JSON by default */\
 | 
											
												
													
														|  |      true, /* case sensitive by default */\
 |  |      true, /* case sensitive by default */\
 | 
											
												
													
														|  | 
 |  | +    true, /* Do cJSON_Duplicate recursively by default */\
 | 
											
												
													
														|  |      {\
 |  |      {\
 | 
											
												
													
														|  |          malloc_wrapper,\
 |  |          malloc_wrapper,\
 | 
											
												
													
														|  |          free_wrapper,\
 |  |          free_wrapper,\
 | 
											
										
											
												
													
														|  | @@ -2637,56 +2639,60 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
 | 
											
												
													
														|  |      return a;
 |  |      return a;
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -/* Duplication */
 |  | 
 | 
											
												
													
														|  | -CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
 |  | 
 | 
											
												
													
														|  | 
 |  | +static cJSON *duplicate_json(const cJSON *item, const internal_context * const context)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  |      cJSON *newitem = NULL;
 |  |      cJSON *newitem = NULL;
 | 
											
												
													
														|  |      cJSON *child = NULL;
 |  |      cJSON *child = NULL;
 | 
											
												
													
														|  |      cJSON *next = NULL;
 |  |      cJSON *next = NULL;
 | 
											
												
													
														|  |      cJSON *newchild = NULL;
 |  |      cJSON *newchild = NULL;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    /* Bail on bad ptr */
 |  | 
 | 
											
												
													
														|  | -    if (!item)
 |  | 
 | 
											
												
													
														|  | 
 |  | +    if (item == NULL)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  |          goto fail;
 |  |          goto fail;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  | -    /* Create new item */
 |  | 
 | 
											
												
													
														|  | -    newitem = create_item(&global_context);
 |  | 
 | 
											
												
													
														|  | -    if (!newitem)
 |  | 
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    newitem = create_item(context);
 | 
											
												
													
														|  | 
 |  | +    if (newitem == NULL)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  |          goto fail;
 |  |          goto fail;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |      /* Copy over all vars */
 |  |      /* Copy over all vars */
 | 
											
												
													
														|  |      newitem->type = item->type & (~cJSON_IsReference);
 |  |      newitem->type = item->type & (~cJSON_IsReference);
 | 
											
												
													
														|  |      newitem->valueint = item->valueint;
 |  |      newitem->valueint = item->valueint;
 | 
											
												
													
														|  |      newitem->valuedouble = item->valuedouble;
 |  |      newitem->valuedouble = item->valuedouble;
 | 
											
												
													
														|  | -    if (item->valuestring)
 |  | 
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    if (item->valuestring != NULL)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | -        newitem->valuestring = (char*)custom_strdup((unsigned char*)item->valuestring, &global_context);
 |  | 
 | 
											
												
													
														|  | -        if (!newitem->valuestring)
 |  | 
 | 
											
												
													
														|  | 
 |  | +        newitem->valuestring = (char*)custom_strdup((unsigned char*)item->valuestring, context);
 | 
											
												
													
														|  | 
 |  | +        if (newitem->valuestring == NULL)
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  |              goto fail;
 |  |              goto fail;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  | -    if (item->string)
 |  | 
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    if (item->string != NULL)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | -        newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)custom_strdup((unsigned char*)item->string, &global_context);
 |  | 
 | 
											
												
													
														|  | 
 |  | +        newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)custom_strdup((unsigned char*)item->string, context);
 | 
											
												
													
														|  |          if (!newitem->string)
 |  |          if (!newitem->string)
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  |              goto fail;
 |  |              goto fail;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |      /* If non-recursive, then we're done! */
 |  |      /* If non-recursive, then we're done! */
 | 
											
												
													
														|  | -    if (!recurse)
 |  | 
 | 
											
												
													
														|  | 
 |  | +    if (!context->duplicate_recursive)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  |          return newitem;
 |  |          return newitem;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |      /* Walk the ->next chain for the child. */
 |  |      /* Walk the ->next chain for the child. */
 | 
											
												
													
														|  |      child = item->child;
 |  |      child = item->child;
 | 
											
												
													
														|  |      while (child != NULL)
 |  |      while (child != NULL)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | -        newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
 |  | 
 | 
											
												
													
														|  | -        if (!newchild)
 |  | 
 | 
											
												
													
														|  | 
 |  | +        /* Each item in the ->next chain */
 | 
											
												
													
														|  | 
 |  | +        newchild = duplicate_json(child, context);
 | 
											
												
													
														|  | 
 |  | +        if (newchild == NULL)
 | 
											
												
													
														|  |          {
 |  |          {
 | 
											
												
													
														|  |              goto fail;
 |  |              goto fail;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
										
											
												
													
														|  | @@ -2711,12 +2717,19 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
 | 
											
												
													
														|  |  fail:
 |  |  fail:
 | 
											
												
													
														|  |      if (newitem != NULL)
 |  |      if (newitem != NULL)
 | 
											
												
													
														|  |      {
 |  |      {
 | 
											
												
													
														|  | -        delete_item(newitem, &global_context);
 |  | 
 | 
											
												
													
														|  | 
 |  | +        delete_item(newitem, context);
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      return NULL;
 |  |      return NULL;
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
 | 
											
												
													
														|  | 
 |  | +{
 | 
											
												
													
														|  | 
 |  | +    internal_context context = global_context;
 | 
											
												
													
														|  | 
 |  | +    context.duplicate_recursive = recurse;
 | 
											
												
													
														|  | 
 |  | +    return duplicate_json(item, &context);
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  CJSON_PUBLIC(void) cJSON_Minify(char *json)
 |  |  CJSON_PUBLIC(void) cJSON_Minify(char *json)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  |      unsigned char *into = (unsigned char*)json;
 |  |      unsigned char *into = (unsigned char*)json;
 |