Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Sync from libucl
Baptiste Daroussin committed 11 years ago
commit 52c3ef80c874ea8554020e59748bad81ca6e41b0
parent e0ede9b
2 files changed +80 -0
modified external/libucl/include/ucl.h
@@ -239,6 +239,14 @@ UCL_EXTERN ucl_object_t* ucl_object_new (void) UCL_WARN_UNUSED_RESULT;
UCL_EXTERN ucl_object_t* ucl_object_typed_new (ucl_type_t type) UCL_WARN_UNUSED_RESULT;

/**
+
 * Perform deep copy of an object copying everything
+
 * @param other object to copy
+
 * @return new object with refcount equal to 1
+
 */
+
UCL_EXTERN ucl_object_t * ucl_object_copy (const ucl_object_t *other)
+
	UCL_WARN_UNUSED_RESULT;
+

+
/**
 * Return the type of an object
 * @return the object type
 */
modified external/libucl/src/ucl_util.c
@@ -1179,6 +1179,12 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
	elt->key = key;
	elt->keylen = keylen;

+
	if (elt->trash_stack[UCL_TRASH_KEY] != NULL) {
+
		/* Remove copied key */
+
		free (elt->trash_stack[UCL_TRASH_KEY]);
+
		elt->trash_stack[UCL_TRASH_KEY] = NULL;
+
		elt->flags &= ~UCL_OBJECT_ALLOCATED_KEY;
+
	}
	if (copy_key) {
		ucl_copy_key_trash (elt);
	}
@@ -1859,6 +1865,72 @@ ucl_object_ref (const ucl_object_t *obj)
	return res;
}

+
static ucl_object_t *
+
ucl_object_copy_internal (const ucl_object_t *other, bool allow_array)
+
{
+

+
	ucl_object_t *new;
+
	ucl_object_iter_t it = NULL;
+
	const ucl_object_t *cur;
+

+
	new = malloc (sizeof (*new));
+

+
	if (new != NULL) {
+
		memcpy (new, other, sizeof (*new));
+
		new->ref = 1;
+
		/* Unlink from others */
+
		new->prev = new->next = NULL;
+

+
		/* deep copy of values stored */
+
		if (other->trash_stack[UCL_TRASH_KEY] != NULL) {
+
			new->trash_stack[UCL_TRASH_KEY] =
+
					strdup (other->trash_stack[UCL_TRASH_KEY]);
+
			if (other->key == (const char *)other->trash_stack[UCL_TRASH_KEY]) {
+
				new->key = new->trash_stack[UCL_TRASH_KEY];
+
			}
+
		}
+
		if (other->trash_stack[UCL_TRASH_VALUE] != NULL) {
+
			new->trash_stack[UCL_TRASH_VALUE] =
+
					strdup (other->trash_stack[UCL_TRASH_VALUE]);
+
			if (new->type == UCL_STRING) {
+
				new->value.sv = new->trash_stack[UCL_TRASH_VALUE];
+
			}
+
		}
+

+
		if (other->type == UCL_ARRAY || other->type == UCL_OBJECT) {
+
			/* reset old value */
+
			memset (&new->value, 0, sizeof (new->value));
+

+
			while ((cur = ucl_iterate_object (other, &it, true)) != NULL) {
+
				if (other->type == UCL_ARRAY) {
+
					ucl_array_append (new, ucl_object_copy_internal (cur, false));
+
				}
+
				else {
+
					ucl_object_t *cp = ucl_object_copy_internal (cur, true);
+
					if (cp != NULL) {
+
						ucl_object_insert_key (new, cp, cp->key, cp->keylen,
+
								false);
+
					}
+
				}
+
			}
+
		}
+
		else if (allow_array && other->next != NULL) {
+
			LL_FOREACH (other->next, cur) {
+
				ucl_object_t *cp = ucl_object_copy_internal (cur, true);
+
				DL_APPEND (new, cp);
+
			}
+
		}
+
	}
+

+
	return new;
+
}
+

+
ucl_object_t *
+
ucl_object_copy (const ucl_object_t *other)
+
{
+
	return ucl_object_copy_internal (other, true);
+
}
+

void
ucl_object_unref (ucl_object_t *obj)
{