*
* @param model The model instance to configure.
* @param desc The structure description to use.
- * @param memory If not @c NULL, will be adopted by model.
+ * @param memory If not @c NULL, will be copied by model.
* @return #EINA_TRUE on success, #EINA_FALSE on failure.
*
* This will setup the internal pointers so that the given @a desc is
* used to manage the properties of this struct.
*
- * If a given memory is provided, it will be adopted (not copied!),
- * being free'd when the model is gone.
+ * If a given memory is provided, it will be copied (including
+ * members) and no references are taken after this function returns.
*
* @see #EINA_VALUE_TYPE_STRUCT
*
* @li eina_value_array_pget() and eina_value_array_pset()
*
* eina_value_set() takes an #Eina_Value_Array where just @c subtype
- * and @c step are used. If there is an @c array, it will be adopted
- * and its contents must be properly configurable as @c subtype
- * expects. eina_value_pset() takes a pointer to an #Eina_Value_Array.
- * For your convenience, use eina_value_array_setup().
+ * and @c step are used. If there is an @c array, it will be copied
+ * (including each item) and its contents must be properly
+ * configurable as @c subtype expects. eina_value_pset() takes a
+ * pointer to an #Eina_Value_Array. For your convenience, use
+ * eina_value_array_setup().
*
* eina_value_get() and eina_value_pget() takes a pointer to
* #Eina_Value_Array, it's an exact copy of the current structure in
* @li eina_value_list_pget() and eina_value_list_pset()
*
* eina_value_set() takes an #Eina_Value_List where just @c subtype is
- * used. If there is an @c list, it will be adopted and its contents
- * must be properly configurable as @c subtype
- * expects. eina_value_pset() takes a pointer to an #Eina_Value_List.
- * For your convenience, use eina_value_list_setup().
+ * used. If there is an @c list, it will be copied (including each
+ * item) and its contents must be properly configurable as @c
+ * subtype expects. eina_value_pset() takes a pointer to an
+ * #Eina_Value_List. For your convenience, use
+ * eina_value_list_setup().
*
* eina_value_get() and eina_value_pget() takes a pointer to
* #Eina_Value_List, it's an exact copy of the current structure in
*
* eina_value_set() takes an #Eina_Value_Hash where just @c subtype
* and @c buckets_power_size are used. If there is an @c hash, it will
- * be adopted and its contents must be properly configurable as @c
- * subtype expects. eina_value_pset() takes a pointer to an
- * #Eina_Value_Hash. For your convenience, use
+ * be copied (including each item) and its contents must be
+ * properly configurable as @c subtype expects. eina_value_pset()
+ * takes a pointer to an #Eina_Value_Hash. For your convenience, use
* eina_value_hash_setup().
*
* eina_value_get() and eina_value_pget() takes a pointer to
* @li eina_value_struct_pget() and eina_value_struct_pset()
*
* eina_value_set() takes an #Eina_Value_Struct where just @c desc is
- * used. If there is an @c memory, it will be adopted and its contents
- * must be properly configurable as @c desc expects. eina_value_pset()
- * takes a pointer to an #Eina_Value_Struct. For your convenience, use
+ * used. If there is an @c memory, it will be copied (including each
+ * member) and its contents must be properly configurable as @c desc
+ * expects. eina_value_pset() takes a pointer to an
+ * #Eina_Value_Struct. For your convenience, use
* eina_value_struct_setup().
*
* eina_value_get() and eina_value_pget() takes a pointer to
}
static Eina_Bool
-_eina_value_type_array_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr)
+_eina_value_type_array_pset(const Eina_Value_Type *type, void *mem, const void *ptr)
{
Eina_Value_Array *tmem = mem;
const Eina_Value_Array *desc = ptr;
desc_array = desc->array;
if (desc_array)
{
+ Eina_Value_Array tmp;
+
EINA_SAFETY_ON_FALSE_RETURN_VAL
(desc_array->member_size == desc->subtype->value_size, EINA_FALSE);
tmem->subtype = desc->subtype;
return EINA_TRUE;
}
+
+ if (!_eina_value_type_array_copy(type, desc, &tmp))
+ return EINA_FALSE;
+
+ _eina_value_type_array_flush(type, tmem);
+ memcpy(tmem, &tmp, sizeof(tmp));
+ return EINA_TRUE;
}
if (tmem->array)
{
_eina_value_type_array_flush_elements(tmem);
- if (desc_array)
- eina_inarray_free(tmem->array);
- else
- eina_inarray_setup(tmem->array, desc->subtype->value_size,
- desc->step);
+ eina_inarray_setup(tmem->array, desc->subtype->value_size, desc->step);
}
- else if (!desc_array)
+ else
{
tmem->array = eina_inarray_new(desc->subtype->value_size, desc->step);
if (!tmem->array)
return EINA_FALSE;
}
- if (desc_array)
- tmem->array = desc_array;
-
tmem->subtype = desc->subtype;
-
return EINA_TRUE;
}
}
static Eina_Bool
-_eina_value_type_list_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr)
+_eina_value_type_list_pset(const Eina_Value_Type *type, void *mem, const void *ptr)
{
Eina_Value_List *tmem = mem;
const Eina_Value_List *desc = ptr;
return EINA_TRUE;
}
+ if (desc->list)
+ {
+ Eina_Value_List tmp;
+
+ if (!_eina_value_type_list_copy(type, desc, &tmp))
+ return EINA_FALSE;
+
+ _eina_value_type_list_flush(type, tmem);
+ memcpy(tmem, &tmp, sizeof(tmp));
+ return EINA_TRUE;
+ }
+
_eina_value_type_list_flush_elements(tmem);
- tmem->subtype = desc->subtype;
- tmem->list = desc->list;
+ tmem->subtype = desc->subtype;
return EINA_TRUE;
}
}
static Eina_Bool
-_eina_value_type_hash_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr)
+_eina_value_type_hash_pset(const Eina_Value_Type *type, void *mem, const void *ptr)
{
Eina_Value_Hash *tmem = mem;
const Eina_Value_Hash *desc = ptr;
return EINA_TRUE;
}
- if (tmem->hash) _eina_value_type_hash_flush_elements(tmem);
-
if (desc->hash)
- tmem->hash = desc->hash;
- else if (!_eina_value_type_hash_create(tmem))
- return EINA_FALSE;
+ {
+ Eina_Value_Hash tmp;
+
+ if (!_eina_value_type_hash_copy(type, desc, &tmp))
+ return EINA_FALSE;
+
+ _eina_value_type_hash_flush(type, tmem);
+ memcpy(tmem, &tmp, sizeof(tmp));
+ return EINA_TRUE;
+ }
+
+ if (tmem->hash) _eina_value_type_hash_flush_elements(tmem);
tmem->subtype = desc->subtype;
+ if (!_eina_value_type_hash_create(tmem))
+ return EINA_FALSE;
return EINA_TRUE;
}
return EINA_TRUE;
}
- _eina_value_type_struct_flush(type, mem);
+ if (desc->memory)
+ {
+ Eina_Value_Struct tmp;
- *tmem = *desc;
- if (tmem->memory) return EINA_TRUE;
+ if (!_eina_value_type_struct_copy(type, desc, &tmp))
+ return EINA_FALSE;
+
+ _eina_value_type_struct_flush(type, tmem);
+ memcpy(tmem, &tmp, sizeof(tmp));
+ return EINA_TRUE;
+ }
+
+ if (tmem->memory) _eina_value_type_struct_flush(type, mem);
+
+ tmem->desc = desc->desc;
ops = _eina_value_type_struct_ops_get(desc);
if ((ops) && (ops->alloc))
ops->free(ops, tmem->desc, tmem->memory);
else
free(tmem->memory);
+ tmem->memory = NULL;
+ tmem->desc = NULL;
return EINA_FALSE;
}
}
END_TEST
+static Eina_Bool
+_struct_complex_members_constructor(Eina_Model *m)
+{
+ struct myst {
+ Eina_Value_Array a;
+ Eina_Value_List l;
+ Eina_Value_Hash h;
+ Eina_Value_Struct s;
+ } *st;
+ struct subst {
+ int i, j;
+ };
+ static Eina_Value_Struct_Member myst_members[] = {
+ EINA_VALUE_STRUCT_MEMBER(NULL, struct myst, a),
+ EINA_VALUE_STRUCT_MEMBER(NULL, struct myst, l),
+ EINA_VALUE_STRUCT_MEMBER(NULL, struct myst, h),
+ EINA_VALUE_STRUCT_MEMBER(NULL, struct myst, s)
+ };
+ static Eina_Value_Struct_Desc myst_desc = {
+ EINA_VALUE_STRUCT_DESC_VERSION,
+ NULL, myst_members, EINA_C_ARRAY_LENGTH(myst_members), sizeof(struct myst)
+ };
+ static Eina_Value_Struct_Member subst_members[] = {
+ EINA_VALUE_STRUCT_MEMBER(NULL, struct subst, i),
+ EINA_VALUE_STRUCT_MEMBER(NULL, struct subst, j)
+ };
+ static Eina_Value_Struct_Desc subst_desc = {
+ EINA_VALUE_STRUCT_DESC_VERSION,
+ NULL, subst_members, EINA_C_ARRAY_LENGTH(subst_members),
+ sizeof(struct subst)
+ };
+
+ if (!myst_members[0].type)
+ {
+ myst_members[0].type = EINA_VALUE_TYPE_ARRAY;
+ myst_members[1].type = EINA_VALUE_TYPE_LIST;
+ myst_members[2].type = EINA_VALUE_TYPE_HASH;
+ myst_members[3].type = EINA_VALUE_TYPE_STRUCT;
+ }
+
+ if (!subst_members[0].type)
+ {
+ subst_members[0].type = EINA_VALUE_TYPE_INT;
+ subst_members[1].type = EINA_VALUE_TYPE_INT;
+ }
+
+ if (!eina_model_type_constructor(EINA_MODEL_TYPE_STRUCT, m))
+ return EINA_FALSE;
+
+ st = calloc(1, sizeof(*st));
+ if (!st)
+ {
+ eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
+ return EINA_FALSE;
+ }
+
+ st->a.subtype = EINA_VALUE_TYPE_STRING;
+ st->l.subtype = EINA_VALUE_TYPE_STRING;
+ st->h.subtype = EINA_VALUE_TYPE_STRING;
+ st->s.desc = &subst_desc;
+
+ if (!eina_model_struct_set(m, &myst_desc, st))
+ {
+ free(st);
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
+START_TEST(eina_model_test_struct_complex_members)
+{
+ Eina_Model *m;
+ Eina_Value outv;
+ char *s;
+ Eina_Model_Type type = EINA_MODEL_TYPE_INIT_NOPRIVATE
+ ("struct_complex_members", Eina_Model_Type, NULL, NULL, NULL);
+
+ eina_init();
+
+ type.constructor = _struct_complex_members_constructor;
+ type.parent = EINA_MODEL_TYPE_STRUCT;
+
+ m = eina_model_new(&type);
+ fail_unless(m != NULL);
+
+ fail_unless(eina_model_property_get(m, "a", &outv));
+ fail_unless(eina_value_array_append(&outv, "Hello"));
+ fail_unless(eina_value_array_append(&outv, "World"));
+ fail_unless(eina_model_property_set(m, "a", &outv));
+ eina_value_flush(&outv);
+
+ fail_unless(eina_model_property_get(m, "l", &outv));
+ fail_unless(eina_value_list_append(&outv, "Some"));
+ fail_unless(eina_value_list_append(&outv, "Thing"));
+ fail_unless(eina_model_property_set(m, "l", &outv));
+ eina_value_flush(&outv);
+
+ fail_unless(eina_model_property_get(m, "h", &outv));
+ fail_unless(eina_value_hash_set(&outv, "key", "value"));
+ fail_unless(eina_model_property_set(m, "h", &outv));
+ eina_value_flush(&outv);
+
+ fail_unless(eina_model_property_get(m, "s", &outv));
+ fail_unless(eina_value_struct_set(&outv, "i", 1234));
+ fail_unless(eina_value_struct_set(&outv, "j", 44));
+ fail_unless(eina_model_property_set(m, "s", &outv));
+ eina_value_flush(&outv);
+
+ s = eina_model_to_string(m);
+ fail_unless(s != NULL);
+ ck_assert_str_eq(s, "struct_complex_members({a: [Hello, World], h: {key: value}, l: [Some, Thing], s: {i: 1234, j: 44}}, [])");
+ free(s);
+
+ ck_assert_int_eq(eina_model_refcount(m), 1);
+
+ eina_model_unref(m);
+ eina_shutdown();
+}
+END_TEST
+
void
eina_test_model(TCase *tc)
{
tcase_add_test(tc, eina_model_test_child_sorted_iterator);
tcase_add_test(tc, eina_model_test_child_filtered_iterator);
tcase_add_test(tc, eina_model_test_struct);
+ tcase_add_test(tc, eina_model_test_struct_complex_members);
}
fail_unless(eina_inarray_append(inarray, &c) >= 0);
desc.subtype = EINA_VALUE_TYPE_CHAR;
desc.step = 0;
- desc.array = inarray; /* will be adopted and freed by value */
+ desc.array = inarray;
fail_unless(eina_value_set(value, desc)); /* manually configure */
+ eina_inarray_free(inarray);
+
fail_unless(eina_value_array_get(value, 0, &c));
fail_unless(c == 11);
fail_unless(eina_value_array_get(value, 1, &c));
desc.subtype = EINA_VALUE_TYPE_STRING;
desc.list = NULL;
- desc.list = eina_list_append(desc.list, strdup("hello"));
- desc.list = eina_list_append(desc.list, strdup("world"));
- desc.list = eina_list_append(desc.list, strdup("eina"));
+ desc.list = eina_list_append(desc.list, "hello");
+ desc.list = eina_list_append(desc.list, "world");
+ desc.list = eina_list_append(desc.list, "eina");
fail_unless(eina_list_count(desc.list) == 3);
fail_unless(eina_value_set(value, desc));
+ eina_list_free(desc.list);
+
fail_unless(eina_value_list_get(value, 0, &s));
fail_unless(s != NULL);
fail_unless(strcmp(s, "hello") == 0);
fail_unless(desc.hash != NULL);
/* watch out hash pointer is to a size of subtype->value_size! */
ptr = malloc(sizeof(char *));
- *ptr = strdup("there");
+ *ptr = "there";
fail_unless(eina_hash_add(desc.hash, "hi", ptr));
ptr = malloc(sizeof(char *));
- *ptr = strdup("y");
+ *ptr = "y";
fail_unless(eina_hash_add(desc.hash, "x", ptr));
-
fail_unless(eina_value_set(value, desc));
+ free(eina_hash_find(desc.hash, "hi"));
+ free(eina_hash_find(desc.hash, "x"));
+ eina_hash_free(desc.hash);
+
fail_unless(eina_value_hash_get(value, "hi", &s));
fail_unless(s != NULL);
fail_unless(strcmp(s, "there") == 0);
for (i = 0; i < 10; i++)
{
Eina_Value_Struct desc;
- struct myst *st;
+ struct myst st;
char buf[64];
snprintf(buf, sizeof(buf), "item%02d", i);
- st = malloc(sizeof(struct myst));
- fail_unless(st != NULL);
- st->a = i;
- st->b = i * 10;
- st->c = i * 100;
- st->s = strdup(buf);
- fail_unless(st->s != NULL);
+ st.a = i;
+ st.b = i * 10;
+ st.c = i * 100;
+ st.s = buf;
desc.desc = &myst_desc;
- desc.memory = st;
+ desc.memory = &st;
fail_unless(eina_value_array_append(value, desc));
}