From 45456d9e82ddc0e514a2b0003cbffa259e9eb9b1 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Tue, 19 Apr 2016 18:25:15 +0900 Subject: [PATCH] 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 --- src/lib/eo/eo_base.eo | 28 ++++++++++ src/lib/eo/eo_base_class.c | 103 +++++++++++++++++++++++++++++++++-- src/tests/eo/suite/eo_test_general.c | 15 +++++ 3 files changed, 142 insertions(+), 4 deletions(-) diff --git a/src/lib/eo/eo_base.eo b/src/lib/eo/eo_base.eo index 0cd1354..51385f1 100644 --- a/src/lib/eo/eo_base.eo +++ b/src/lib/eo/eo_base.eo @@ -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. diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c index 4c5fe71..2420568 100644 --- a/src/lib/eo/eo_base_class.c +++ b/src/lib/eo/eo_base_class.c @@ -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; } diff --git a/src/tests/eo/suite/eo_test_general.c b/src/tests/eo/suite/eo_test_general.c index 9b19210..c1ca0d8 100644 --- a/src/tests/eo/suite/eo_test_general.c +++ b/src/tests/eo/suite/eo_test_general.c @@ -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); -- 2.7.4