eo base - add value keys in addition to object and void ptr data keys

eina value would allow any value to be attached to an eo object and
also be freed nicely too. this would allow any generic data to go
there without overloading a void * that us c coders love to abuse.

@feature
This commit is contained in:
Carsten Haitzler 2016-04-19 18:25:15 +09:00
parent 1b266ff1e4
commit 45456d9e82
3 changed files with 142 additions and 4 deletions

View File

@ -223,6 +223,34 @@ abstract Eo.Base ()
@in key: const(char)*; [[the key associated with the object ref]]
}
}
key_value_set {
[[Set value on the object.
This stores the value with the given string key on the object
and it will be freed when replaced or deleted or the referring
object is deleted.
This is the same key store used by key_data_set and key_obj_set
etc. so keys are shared and can store only one thing
]]
params {
@in key: const(char)*; [[the key associated with the value]]
@in value: Eina_Value *; [[the value to set]]
}
}
key_value_get @const {
[[Get generic value from object.]]
params {
@in key: const(char)*; [[the key associated with the value]]
}
return: Eina_Value *; [[the value for the key]]
}
key_value_del {
[[Del generic value from object.]]
params {
@in key: const(char)*; [[the key associated with the value]]
}
}
event_thaw {
[[thaw events of object.

View File

@ -42,6 +42,7 @@ typedef struct
Eina_Stringshare *key;
void *data;
Eina_Bool data_is_obj : 1;
Eina_Bool data_is_value : 1;
} Eo_Generic_Data_Node;
@ -110,6 +111,7 @@ _eo_generic_data_del_all(Eo *obj, Eo_Base_Data *pd)
_eo_base_cb_key_obj_del, obj);
eo_unref(node->data);
}
else if (node->data_is_value) eina_value_free(node->data);
_eo_generic_data_node_free(node);
}
}
@ -124,7 +126,8 @@ _eo_base_key_data_set(Eo *obj, Eo_Base_Data *pd, const char *key, const void *da
{
if (!strcmp(node->key, key))
{
if ((!node->data_is_obj) && (node->data == data)) return;
if ((!node->data_is_obj) && (!node->data_is_value) &&
(node->data == data)) return;
pd->generic_data = eina_inlist_remove(pd->generic_data,
EINA_INLIST_GET(node));
if (node->data_is_obj)
@ -133,6 +136,7 @@ _eo_base_key_data_set(Eo *obj, Eo_Base_Data *pd, const char *key, const void *da
_eo_base_cb_key_obj_del, obj);
eo_unref(node->data);
}
else if (node->data_is_value) eina_value_free(node->data);
_eo_generic_data_node_free(node);
break;
}
@ -157,7 +161,7 @@ _eo_base_key_data_get(const Eo *obj, Eo_Base_Data *pd, const char *key)
{
if (!strcmp(node->key, key))
{
if (!node->data_is_obj)
if ((!node->data_is_obj) && (!node->data_is_value))
{
pd->generic_data = eina_inlist_promote(pd->generic_data,
EINA_INLIST_GET(node));
@ -165,7 +169,7 @@ _eo_base_key_data_get(const Eo *obj, Eo_Base_Data *pd, const char *key)
}
else
{
ERR("Object %p key '%s' is an object, not raw data",
ERR("Object %p key '%s' wants raw data but is not raw data",
obj, key);
return NULL;
}
@ -192,6 +196,7 @@ _eo_base_key_data_del(Eo *obj, Eo_Base_Data *pd, const char *key)
_eo_base_cb_key_obj_del, obj);
eo_unref(node->data);
}
else if (node->data_is_value) eina_value_free(node->data);
_eo_generic_data_node_free(node);
return;
}
@ -217,6 +222,7 @@ _eo_base_key_obj_set(Eo *obj, Eo_Base_Data *pd, const char *key, Eo *objdata)
_eo_base_cb_key_obj_del, obj);
eo_unref(node->data);
}
else if (node->data_is_value) eina_value_free(node->data);
_eo_generic_data_node_free(node);
break;
}
@ -252,7 +258,7 @@ _eo_base_key_obj_get(const Eo *obj, Eo_Base_Data *pd, const char *key)
}
else
{
ERR("Object %p key '%s' is an object, not an object",
ERR("Object %p key '%s' asked for object but is not an object",
obj, key);
return NULL;
}
@ -279,6 +285,95 @@ _eo_base_key_obj_del(Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *key)
_eo_base_cb_key_obj_del, obj);
eo_unref(node->data);
}
else if (node->data_is_value) eina_value_free(node->data);
_eo_generic_data_node_free(node);
return;
}
}
}
EOLIAN static void
_eo_base_key_value_set(Eo *obj, Eo_Base_Data *pd, const char *key, Eina_Value *value)
{
Eo_Generic_Data_Node *node;
if (!key) return;
EINA_INLIST_FOREACH(pd->generic_data, node)
{
if (!strcmp(node->key, key))
{
if ((node->data_is_value) && (node->data == value)) return;
pd->generic_data = eina_inlist_remove(pd->generic_data,
EINA_INLIST_GET(node));
if (node->data_is_obj)
{
eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
_eo_base_cb_key_obj_del, obj);
eo_unref(node->data);
}
else if (node->data_is_value) eina_value_free(node->data);
_eo_generic_data_node_free(node);
break;
}
}
node = calloc(1, sizeof(Eo_Generic_Data_Node));
if (!node) return;
node->key = eina_stringshare_add(key);
node->data = (void *)value;
node->data_is_value = EINA_TRUE;
eo_event_callback_add(node->data, EO_BASE_EVENT_DEL,
_eo_base_cb_key_obj_del, obj);
pd->generic_data = eina_inlist_prepend(pd->generic_data,
EINA_INLIST_GET(node));
}
EOLIAN static Eina_Value *
_eo_base_key_value_get(const Eo *obj, Eo_Base_Data *pd, const char *key)
{
Eo_Generic_Data_Node *node;
if (!key) return NULL;
EINA_INLIST_FOREACH(pd->generic_data, node)
{
if (!strcmp(node->key, key))
{
if (node->data_is_value)
{
pd->generic_data = eina_inlist_promote(pd->generic_data,
EINA_INLIST_GET(node));
return node->data;
}
else
{
ERR("Object %p key '%s' asked for value but is not a value",
obj, key);
return NULL;
}
}
}
return NULL;
}
EOLIAN static void
_eo_base_key_value_del(Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *key)
{
Eo_Generic_Data_Node *node;
if (!key) return;
EINA_INLIST_FOREACH(pd->generic_data, node)
{
if (!strcmp(node->key, key))
{
pd->generic_data = eina_inlist_remove(pd->generic_data,
EINA_INLIST_GET(node));
if (node->data_is_obj)
{
eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
_eo_base_cb_key_obj_del, obj);
eo_unref(node->data);
}
else if (node->data_is_value) eina_value_free(node->data);
_eo_generic_data_node_free(node);
return;
}

View File

@ -602,6 +602,8 @@ START_TEST(eo_generic_data)
Eo *obj3 = eo_add(SIMPLE_CLASS, NULL);
Eo *objtmp;
void *data = NULL;
Eina_Value *value;
Eina_Value *value2;
eo_key_data_set(obj, "test1", (void *) 1);
data = eo_key_data_get(obj, "test1");
@ -657,6 +659,19 @@ START_TEST(eo_generic_data)
objtmp = eo_key_obj_get(obj, "test1");
fail_if(objtmp);
value = eina_value_new(EINA_VALUE_TYPE_INT);
eina_value_set(value, 1234);
value2 = eo_key_value_get(obj, "value1");
fail_if(value2 != NULL);
eo_key_value_set(obj, "value1", value);
value2 = eo_key_value_get(obj, "value1");
fail_if(value != value2);
eo_key_value_del(obj, "value1");
value2 = eo_key_value_get(obj, "value1");
fail_if(value2 != NULL);
eo_unref(obj);
eo_unref(obj2);
eo_unref(obj3);