| 2599 | |
| 2600 | /* Duplication */ |
| 2601 | CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) |
| 2602 | { |
| 2603 | cJSON *newitem = NULL; |
| 2604 | cJSON *child = NULL; |
| 2605 | cJSON *next = NULL; |
| 2606 | cJSON *newchild = NULL; |
| 2607 | |
| 2608 | /* Bail on bad ptr */ |
| 2609 | if (!item) |
| 2610 | { |
| 2611 | goto fail; |
| 2612 | } |
| 2613 | /* Create new item */ |
| 2614 | newitem = cJSON_New_Item(&global_hooks); |
| 2615 | if (!newitem) |
| 2616 | { |
| 2617 | goto fail; |
| 2618 | } |
| 2619 | /* Copy over all vars */ |
| 2620 | newitem->type = item->type & (~cJSON_IsReference); |
| 2621 | newitem->valueint = item->valueint; |
| 2622 | newitem->valuedouble = item->valuedouble; |
| 2623 | if (item->valuestring) |
| 2624 | { |
| 2625 | newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); |
| 2626 | if (!newitem->valuestring) |
| 2627 | { |
| 2628 | goto fail; |
| 2629 | } |
| 2630 | } |
| 2631 | if (item->string) |
| 2632 | { |
| 2633 | newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); |
| 2634 | if (!newitem->string) |
| 2635 | { |
| 2636 | goto fail; |
| 2637 | } |
| 2638 | } |
| 2639 | /* If non-recursive, then we're done! */ |
| 2640 | if (!recurse) |
| 2641 | { |
| 2642 | return newitem; |
| 2643 | } |
| 2644 | /* Walk the ->next chain for the child. */ |
| 2645 | child = item->child; |
| 2646 | while (child != NULL) |
| 2647 | { |
| 2648 | newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ |
| 2649 | if (!newchild) |
| 2650 | { |
| 2651 | goto fail; |
| 2652 | } |
| 2653 | if (next != NULL) |
| 2654 | { |
| 2655 | /* If newitem->child already set, then crosswire ->prev and ->next and move on */ |
| 2656 | next->next = newchild; |
| 2657 | newchild->prev = next; |
| 2658 | next = newchild; |
nothing calls this directly
no test coverage detected