Duplication */
| 2714 | |
| 2715 | /* Duplication */ |
| 2716 | CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) |
| 2717 | { |
| 2718 | cJSON *newitem = NULL; |
| 2719 | cJSON *child = NULL; |
| 2720 | cJSON *next = NULL; |
| 2721 | cJSON *newchild = NULL; |
| 2722 | |
| 2723 | /* Bail on bad ptr */ |
| 2724 | if (!item) |
| 2725 | { |
| 2726 | goto fail; |
| 2727 | } |
| 2728 | /* Create new item */ |
| 2729 | newitem = cJSON_New_Item(&global_hooks); |
| 2730 | if (!newitem) |
| 2731 | { |
| 2732 | goto fail; |
| 2733 | } |
| 2734 | /* Copy over all vars */ |
| 2735 | newitem->type = item->type & (~cJSON_IsReference); |
| 2736 | newitem->valueint = item->valueint; |
| 2737 | newitem->valuedouble = item->valuedouble; |
| 2738 | if (item->valuestring) |
| 2739 | { |
| 2740 | newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); |
| 2741 | if (!newitem->valuestring) |
| 2742 | { |
| 2743 | goto fail; |
| 2744 | } |
| 2745 | } |
| 2746 | if (item->string) |
| 2747 | { |
| 2748 | newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); |
| 2749 | if (!newitem->string) |
| 2750 | { |
| 2751 | goto fail; |
| 2752 | } |
| 2753 | } |
| 2754 | /* If non-recursive, then we're done! */ |
| 2755 | if (!recurse) |
| 2756 | { |
| 2757 | return newitem; |
| 2758 | } |
| 2759 | /* Walk the ->next chain for the child. */ |
| 2760 | child = item->child; |
| 2761 | while (child != NULL) |
| 2762 | { |
| 2763 | newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ |
| 2764 | if (!newchild) |
| 2765 | { |
| 2766 | goto fail; |
| 2767 | } |
| 2768 | if (next != NULL) |
| 2769 | { |
| 2770 | /* If newitem->child already set, then crosswire ->prev and ->next and move on */ |
| 2771 | next->next = newchild; |
| 2772 | newchild->prev = next; |
| 2773 | next = newchild; |
nothing calls this directly
no test coverage detected