| 2787 | } |
| 2788 | |
| 2789 | cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse) |
| 2790 | { |
| 2791 | cJSON *newitem = NULL; |
| 2792 | cJSON *child = NULL; |
| 2793 | cJSON *next = NULL; |
| 2794 | cJSON *newchild = NULL; |
| 2795 | |
| 2796 | /* Bail on bad ptr */ |
| 2797 | if (!item) |
| 2798 | { |
| 2799 | goto fail; |
| 2800 | } |
| 2801 | /* Create new item */ |
| 2802 | newitem = cJSON_New_Item(&global_hooks); |
| 2803 | if (!newitem) |
| 2804 | { |
| 2805 | goto fail; |
| 2806 | } |
| 2807 | /* Copy over all vars */ |
| 2808 | newitem->type = item->type & (~cJSON_IsReference); |
| 2809 | newitem->valueint = item->valueint; |
| 2810 | newitem->valuedouble = item->valuedouble; |
| 2811 | if (item->valuestring) |
| 2812 | { |
| 2813 | newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); |
| 2814 | if (!newitem->valuestring) |
| 2815 | { |
| 2816 | goto fail; |
| 2817 | } |
| 2818 | } |
| 2819 | if (item->string) |
| 2820 | { |
| 2821 | newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); |
| 2822 | if (!newitem->string) |
| 2823 | { |
| 2824 | goto fail; |
| 2825 | } |
| 2826 | } |
| 2827 | /* If non-recursive, then we're done! */ |
| 2828 | if (!recurse) |
| 2829 | { |
| 2830 | return newitem; |
| 2831 | } |
| 2832 | /* Walk the ->next chain for the child. */ |
| 2833 | child = item->child; |
| 2834 | while (child != NULL) |
| 2835 | { |
| 2836 | if(depth >= CJSON_CIRCULAR_LIMIT) { |
| 2837 | goto fail; |
| 2838 | } |
| 2839 | newchild = cJSON_Duplicate_rec(child, depth + 1, true); /* Duplicate (with recurse) each item in the ->next chain */ |
| 2840 | if (!newchild) |
| 2841 | { |
| 2842 | goto fail; |
| 2843 | } |
| 2844 | if (next != NULL) |
| 2845 | { |
| 2846 | /* If newitem->child already set, then crosswire ->prev and ->next and move on */ |
no test coverage detected