From b1bb7706888163a309a6dcbec9cf2aaa577ee052 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Tue, 14 Feb 2012 09:48:00 +0000 Subject: [PATCH] Eina model: Fix issues with interface inheritance. The ptr comparison had issues. Order of interface overrides was wrong. SVN revision: 67915 --- legacy/eina/src/lib/eina_model.c | 25 ++--- legacy/eina/src/tests/eina_test_model.c | 134 ++++++++++++++++++++++++ 2 files changed, 140 insertions(+), 19 deletions(-) diff --git a/legacy/eina/src/lib/eina_model.c b/legacy/eina/src/lib/eina_model.c index ee45a7bc79..b6d358981d 100644 --- a/legacy/eina/src/lib/eina_model.c +++ b/legacy/eina/src/lib/eina_model.c @@ -3487,23 +3487,17 @@ EAPI const Eina_Model_Interface * eina_model_interface_get(const Eina_Model *model, const char *name) { const Eina_Model_Description *desc; - const Eina_Model_Interface **itr, **itr_end; + const Eina_Model_Interface **itr, **itr_first; EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL); desc = model->desc; - itr = desc->cache.ifaces; - itr_end = itr + desc->total.ifaces; - - /* try pointer comparison for the speed aware users */ - for (; itr < itr_end; itr++) - if ((*itr)->name == name) - return *itr; + itr_first = desc->cache.ifaces; + itr = itr_first + desc->total.ifaces - 1; /* fallback to strcmp if user is lazy about speed */ - itr = desc->cache.ifaces; - for (; itr < itr_end; itr++) + for (; itr >= itr_first; itr--) if (strcmp((*itr)->name, name) == 0) return *itr; @@ -4798,7 +4792,7 @@ eina_model_type_subclass_check(const Eina_Model_Type *type, const Eina_Model_Typ } static inline const Eina_Model_Interface * -_eina_model_type_interface_get(const Eina_Model_Type *type, const char *name, Eina_Bool ptr_cmp) +_eina_model_type_interface_get(const Eina_Model_Type *type, const char *name, Eina_Bool ptr_cmp __UNUSED__) { const Eina_Model_Interface **itr; @@ -4808,15 +4802,8 @@ _eina_model_type_interface_get(const Eina_Model_Type *type, const char *name, Ei if (!type->interfaces) return _eina_model_type_interface_get(type->parent, name, ptr_cmp); - if (ptr_cmp) { - for (itr = type->interfaces; itr != NULL; itr++) - if ((*itr)->name == name) - return *itr; - } - else - { - for (itr = type->interfaces; itr != NULL; itr++) + for (itr = type->interfaces ; itr != NULL ; itr++) if (strcmp((*itr)->name, name) == 0) return *itr; } diff --git a/legacy/eina/src/tests/eina_test_model.c b/legacy/eina/src/tests/eina_test_model.c index a38c2b0ec4..e8c9ad0f12 100644 --- a/legacy/eina/src/tests/eina_test_model.c +++ b/legacy/eina/src/tests/eina_test_model.c @@ -967,6 +967,139 @@ START_TEST(eina_model_test_struct_complex_members) } END_TEST +typedef struct _Animal_Type +{ + Eina_Model_Type parent_class; + void (*eat)(Eina_Model *mdl); +} Animal_Type; + +typedef struct _Human_Type +{ + Animal_Type parent_class; + void (*talk)(Eina_Model *mdl); +} Human_Type; + +typedef struct _Pooper_Interface +{ + Eina_Model_Interface base_interface; + void (*poop)(Eina_Model *mdl); +} Pooper_Interface; + +#define ANIMAL_TYPE(x) ((Animal_Type *) x) +#define HUMAN_TYPE(x) ((Human_Type *) x) +#define POOPER_IFACE(x) ((Pooper_Interface *) x) +#define POOPER_IFACE_NAME "Pooper_Interace" + +#define INHER_CB_COUNT(prefix) \ +static int prefix ## _count = 0; \ +static void \ +prefix (Eina_Model *mdl) \ +{ \ + (void) mdl; \ + (prefix ## _count)++; \ +} + +static void +animal_eat(Eina_Model *mdl) +{ + void (*pf)(Eina_Model *mdl); + pf = eina_model_method_resolve(mdl, Animal_Type, eat); + EINA_SAFETY_ON_NULL_RETURN(pf); + pf(mdl); +} + +static void +pooper_poop(Eina_Model *mdl) +{ + const Eina_Model_Interface *iface = NULL; + iface = eina_model_interface_get(mdl, POOPER_IFACE_NAME); + + EINA_SAFETY_ON_NULL_RETURN(iface); + + void (*pf)(Eina_Model *); + + pf = eina_model_interface_method_resolve(iface, mdl, Pooper_Interface, poop); + EINA_SAFETY_ON_NULL_RETURN(pf); + pf(mdl); +} + +INHER_CB_COUNT(_animal_poop); +INHER_CB_COUNT(_human_poop); +INHER_CB_COUNT(_animal_eat); +INHER_CB_COUNT(_human_eat); + +START_TEST(eina_model_test_inheritance) +{ + eina_init(); + + Pooper_Interface _ANIMAL_POOPER_IFACE; + Eina_Model_Interface *ANIMAL_POOPER_IFACE = (Eina_Model_Interface *) &_ANIMAL_POOPER_IFACE; + memset(&_ANIMAL_POOPER_IFACE, 0, sizeof(_ANIMAL_POOPER_IFACE)); + ANIMAL_POOPER_IFACE->version = EINA_MODEL_INTERFACE_VERSION; + ANIMAL_POOPER_IFACE->interface_size = sizeof(Pooper_Interface); + ANIMAL_POOPER_IFACE->name = POOPER_IFACE_NAME; + POOPER_IFACE(ANIMAL_POOPER_IFACE)->poop = _animal_poop; + + Pooper_Interface _HUMAN_POOPER_IFACE; + Eina_Model_Interface *HUMAN_POOPER_IFACE = (Eina_Model_Interface *) &_HUMAN_POOPER_IFACE; + memset(&_HUMAN_POOPER_IFACE, 0, sizeof(_HUMAN_POOPER_IFACE)); + HUMAN_POOPER_IFACE->version = EINA_MODEL_INTERFACE_VERSION; + HUMAN_POOPER_IFACE->interface_size = sizeof(Pooper_Interface); + HUMAN_POOPER_IFACE->name = POOPER_IFACE_NAME; + POOPER_IFACE(HUMAN_POOPER_IFACE)->poop = _human_poop; + + const Eina_Model_Interface *ANIMAL_IFACES[] = {ANIMAL_POOPER_IFACE, NULL}; + const Eina_Model_Interface *HUMAN_IFACES[] = {HUMAN_POOPER_IFACE, NULL}; + + /* Init Animal Type */ + Animal_Type _ANIMAL_TYPE; + Eina_Model_Type *ANIMAL_TYPE = (Eina_Model_Type *) &_ANIMAL_TYPE; + + memset(&_ANIMAL_TYPE, 0, sizeof(_ANIMAL_TYPE)); + Eina_Model_Type *type = (Eina_Model_Type *) &_ANIMAL_TYPE; + type->version = EINA_MODEL_TYPE_VERSION; + type->parent = EINA_MODEL_TYPE_BASE; + type->type_size = sizeof(Animal_Type); + type->name = "Animal_Type"; + type->parent = EINA_MODEL_TYPE_GENERIC; + type->interfaces = ANIMAL_IFACES; + + ANIMAL_TYPE(type)->eat = _animal_eat; + + /* Init Human Type */ + Animal_Type _HUMAN_TYPE; + Eina_Model_Type *HUMAN_TYPE = (Eina_Model_Type *) &_HUMAN_TYPE; + memset(&_HUMAN_TYPE, 0, sizeof(_HUMAN_TYPE)); + type = (Eina_Model_Type *) &_HUMAN_TYPE; + type->version = EINA_MODEL_TYPE_VERSION; + type->parent = ANIMAL_TYPE; + type->type_size = sizeof(Human_Type); + type->name = "Human_Type"; + type->interfaces = HUMAN_IFACES; + + ANIMAL_TYPE(type)->eat = _human_eat; + + Eina_Model *hm, *am; + am = eina_model_new(ANIMAL_TYPE); + hm = eina_model_new(HUMAN_TYPE); + + animal_eat(am); + fail_if(_animal_eat_count != 1); + animal_eat(hm); + fail_if(_human_eat_count != 1); + + pooper_poop(am); + fail_if(_animal_poop_count != 1); + pooper_poop(hm); + fail_if(_human_poop_count != 1); + + fail_if(_animal_eat_count != 1); + fail_if(_human_eat_count != 1); + fail_if(_animal_poop_count != 1); + fail_if(_human_poop_count != 1); +} +END_TEST + void eina_test_model(TCase *tc) { @@ -980,4 +1113,5 @@ eina_test_model(TCase *tc) 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); + tcase_add_test(tc, eina_model_test_inheritance); }