From 588e205dd9fe779096438718b413f1ba2d91e44a Mon Sep 17 00:00:00 2001 From: barbieri Date: Tue, 31 Jan 2012 15:26:48 +0000 Subject: [PATCH] eina_model: change the way extensions are done. Thanks to Tasn review it was noticed that subclasses using "const void *value" with sub-structure would have to resolve their methods manually, quite bad. Then the extension will happen with structures inside structures, as previously used in Evas_Smart_Class. To allow the system to resolve the methods and keep it, it is now specificed the type_size. A new function is added to help extensions: eina_model_type_method_resolve(), together with few helper macros. To allow Eina_Model_Type to be augmented with more methods without breaking the ABI, 4 slots are left there. We expect we got it right from beginning and these will never be used, but we can never be sure ;-) Last but not least, similar changes were done to Eina_Model_Interface for consistency matters. git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/eina@67635 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/include/eina_model.h | 250 +++++++++++++++++++++++++++++- src/lib/eina_model.c | 386 ++++++++++++++++++++++++++--------------------- 2 files changed, 458 insertions(+), 178 deletions(-) diff --git a/src/include/eina_model.h b/src/include/eina_model.h index 7723a70..7fac3c3 100644 --- a/src/include/eina_model.h +++ b/src/include/eina_model.h @@ -495,6 +495,7 @@ struct _Eina_Model_Type #define EINA_MODEL_TYPE_VERSION (1) unsigned int version; /**< must be #EINA_MODEL_TYPE_VERSION */ unsigned int private_size; /**< used to allocate type private data */ + unsigned int type_size; /**< used to know sizeof(Eina_Model_Type) or subtypes (which may be bigger, by including Eina_Model_Type as a header */ const char *name; /**< name for debug and introspection */ const Eina_Model_Type *parent; /**< parent type, must be EINA_MODEL_TYPE_BASE or a child of */ const Eina_Model_Interface **interfaces; /**< null terminated array of interfaces */ @@ -525,9 +526,132 @@ struct _Eina_Model_Type Eina_Iterator *(*child_sorted_iterator_get)(Eina_Model *model, unsigned int start, unsigned int count, Eina_Compare_Cb compare); Eina_Iterator *(*child_filtered_iterator_get)(Eina_Model *model, unsigned int start, unsigned int count, Eina_Each_Cb match, const void *data); char *(*to_string)(const Eina_Model *model); /**< used to represent model as string, usually for debug purposes or user convenience */ - const void *value; /**< may hold extension methods */ + void *__extension_ptr0; /**< not to be used */ + void *__extension_ptr1; /**< not to be used */ + void *__extension_ptr2; /**< not to be used */ + void *__extension_ptr3; /**< not to be used */ }; +#define EINA_MODEL_TYPE_INIT(name, type, private_type, parent, interfaces, events) \ + {EINA_MODEL_TYPE_VERSION, \ + sizeof(private_type), \ + sizeof(type), \ + name, \ + parent, \ + interfaces, \ + events, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL \ + } + +#define EINA_MODEL_TYPE_INIT_NOPRIVATE(name, type, parent, interfaces, events) \ + {EINA_MODEL_TYPE_VERSION, \ + 0, \ + sizeof(type), \ + name, \ + parent, \ + interfaces, \ + events, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL \ + } + +#define EINA_MODEL_TYPE_INIT_NULL \ + {0, \ + 0, \ + 0, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL \ + } + EAPI Eina_Bool eina_model_type_constructor(const Eina_Model_Type *type, Eina_Model *model) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT; EAPI Eina_Bool eina_model_type_destructor(const Eina_Model_Type *type, @@ -609,6 +733,61 @@ EAPI Eina_Iterator *eina_model_type_child_filtered_iterator_get(const Eina_Model EAPI char *eina_model_type_to_string(const Eina_Model_Type *type, const Eina_Model *model) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT EINA_MALLOC; + +/** + * @brief Get resolved method from types that extend Eina_Model_Type given offset. + * + * @param model the model to query the method + * @param offset the byte offset in the structure given as type, it + * must be bigger than Eina_Model_Type itself. + * @return address to resolved method, or @c NULL if method is not + * implemented. + * + * When implementing new types that augments the basic methods from + * Eina_Model_Type, the recommended structure layout is as follow: + * @code + * typedef struct _My_Type My_Type; + * struct _My_Type { + * Eina_Model_Type base; + * int (*my_method)(Eina_Model *model); + * }; + * + * int my_type_my_method(Eina_Model *model); + * @endcode + * + * Then the implementation of @c my_type_my_method() needs to get the + * most specific @c my_method that is not @c NULL from type hierarchy, + * also called "resolve the method". + * + * To do this in an efficient way, Eina_Model infrastructure + * pre-resolves all methods and provides this function for efficient + * query. The recommended implementation of my_type_my_method() would + * be: + * @code + * int my_type_my_method(Eina_Model *model) + * { + * int (*meth)(Eina_Model *); + * + * EINA_SAFETY_ON_FALSE_RETURN(eina_model_instance_check(model, MY_TYPE), -1); + * + * meth = eina_model_method_resolve(model, offsetof(My_Type, my_method)); + * EINA_SAFETY_ON_NULL_RETURN(meth, -1); + * return meth(model); + * } + * @endcode + * + * @note offset must be bigger than Eina_Model_Type, otherwise use + * specific functions such as eina_model_property_get(). + * + * @since 1.2 + */ +EAPI const void *eina_model_method_resolve(const Eina_Model *model, + unsigned int offset) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT EINA_PURE; + +EAPI const void *eina_model_type_method_resolve(const Eina_Model_Type *type, + const Eina_Model *model, + unsigned int offset) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT EINA_PURE; + /** * @struct _Eina_Model_Interface * @@ -628,6 +807,7 @@ struct _Eina_Model_Interface #define EINA_MODEL_INTERFACE_VERSION (1) unsigned int version; /**< must be #EINA_MODEL_INTERFACE_VERSION */ unsigned int private_size; /**< used to allocate interface private data */ + unsigned int interface_size; /**< used to know sizeof(Eina_Model_Interface) or subtypes (which may be bigger, by including Eina_Model_Interface as header */ const char *name; /**< name for debug and introspection */ const Eina_Model_Interface **interfaces; /**< null terminated array of parent interfaces */ const Eina_Model_Event_Description *events; /**< null terminated array of events */ @@ -637,9 +817,69 @@ struct _Eina_Model_Interface Eina_Bool (*destructor)(Eina_Model *model); /**< destruct interface instance, flush will be called after it. Should call parent's destructor if needed. Release reference to other models here. */ Eina_Bool (*copy)(const Eina_Model *src, Eina_Model *dst); /**< copy interface private data, do @b not call parent interface copy! */ Eina_Bool (*deep_copy)(const Eina_Model *src, Eina_Model *dst); /**< deep copy interface private data, do @b not call parent interface deep copy! */ - const void *value; /**< holds the actual interface methods */ + void *__extension_ptr0; /**< not to be used */ + void *__extension_ptr1; /**< not to be used */ + void *__extension_ptr2; /**< not to be used */ + void *__extension_ptr3; /**< not to be used */ }; +#define EINA_MODEL_INTERFACE_INIT(name, iface, private_type, parent, events) \ + {EINA_MODEL_INTERFACE_VERSION, \ + sizeof(private_type), \ + sizeof(iface), \ + name, \ + parent, \ + events, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL \ + } + +#define EINA_MODEL_INTERFACE_INIT_NOPRIVATE(name, iface, parent, events) \ + {EINA_MODEL_INTERFACE_VERSION, \ + 0, \ + sizeof(iface), \ + name, \ + parent, \ + events, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL \ + } + +#define EINA_MODEL_INTERFACE_INIT_NULL \ + {0, \ + 0, \ + 0, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL \ + } + EAPI Eina_Bool eina_model_interface_constructor(const Eina_Model_Interface *iface, Eina_Model *model) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT; EAPI Eina_Bool eina_model_interface_destructor(const Eina_Model_Interface *iface, @@ -651,6 +891,10 @@ EAPI Eina_Bool eina_model_interface_deep_copy(const Eina_Model_Interface *iface, const Eina_Model *src, Eina_Model *dst) EINA_ARG_NONNULL(1, 2, 3); +EAPI const void *eina_model_interface_method_resolve(const Eina_Model_Interface *iface, + const Eina_Model *model, + unsigned int offset) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT EINA_PURE; + struct _Eina_Model_Event_Description { @@ -752,6 +996,7 @@ EAPI extern const char *EINA_MODEL_INTERFACE_NAME_PROPERTIES; typedef struct _Eina_Model_Interface_Properties Eina_Model_Interface_Properties; struct _Eina_Model_Interface_Properties { + Eina_Model_Interface base; #define EINA_MODEL_INTERFACE_PROPERTIES_VERSION (1) unsigned int version; Eina_Bool (*compare)(const Eina_Model *a, const Eina_Model *b, int *cmp); @@ -890,6 +1135,7 @@ typedef struct _Eina_Model_Interface_Children Eina_Model_Interface_Children; */ struct _Eina_Model_Interface_Children { + Eina_Model_Interface base; #define EINA_MODEL_INTERFACE_CHILDREN_VERSION (1) unsigned int version; Eina_Bool (*compare)(const Eina_Model *a, const Eina_Model *b, int *cmp); diff --git a/src/lib/eina_model.c b/src/lib/eina_model.c index 03d5488..2a8750c 100644 --- a/src/lib/eina_model.c +++ b/src/lib/eina_model.c @@ -339,6 +339,7 @@ struct _Eina_Model_Description Eina_Iterator *(*child_sorted_iterator_get)(Eina_Model *model, unsigned int start, unsigned int count, Eina_Compare_Cb compare); Eina_Iterator *(*child_filtered_iterator_get)(Eina_Model *model, unsigned int start, unsigned int count, Eina_Each_Cb match, const void *data); char *(*to_string)(const Eina_Model *model); /**< used to represent model as string, usually for debug purposes or user convenience */ + const void **extension; } type; } ops; struct { @@ -354,8 +355,8 @@ struct _Eina_Model_Description static Eina_Bool _eina_model_description_type_fill(Eina_Model_Description *desc, const Eina_Model_Type *type) { - const Eina_Model_Type *itr; - unsigned int count; + const Eina_Model_Type *itr, *last_itr = NULL; + unsigned int count, child_size = 0; for (count = 0, itr = type; itr != NULL; itr = itr->parent, count++) { @@ -370,6 +371,20 @@ _eina_model_description_type_fill(Eina_Model_Description *desc, const Eina_Model CRITICAL("Type %p provides no name!", itr); return EINA_FALSE; } + if (itr->type_size < sizeof(Eina_Model_Type)) + { + CRITICAL("Type %p %s size must be >= sizeof(Eina_Model_Type)!", + itr, itr->name); + return EINA_FALSE; + } + if (child_size == 0) child_size = itr->type_size; + else if (child_size < itr->type_size) + { + CRITICAL("Type %p %s size is bigger than its child type %p %s!", + itr, itr->name, last_itr, last_itr->name); + return EINA_FALSE; + } + last_itr = itr; #define DEF_METH(meth) \ if (!desc->ops.type.meth) desc->ops.type.meth = itr->meth @@ -424,14 +439,51 @@ _eina_model_description_type_fill(Eina_Model_Description *desc, const Eina_Model CK_METH(property_get); #undef CK_METH + if (child_size <= sizeof(Eina_Model_Type)) + desc->ops.type.extension = NULL; + else + { + unsigned ext_size = child_size - sizeof(Eina_Model_Type); + unsigned ext_count = ext_size / sizeof(void *); + + if (ext_size % sizeof(void *) != 0) + { + CRITICAL("Extension size %u is not multiple of sizeof(void*)", + ext_size); + return EINA_FALSE; + } + + desc->ops.type.extension = calloc(ext_count, sizeof(void *)); + EINA_SAFETY_ON_NULL_RETURN_VAL(desc->ops.type.extension, EINA_FALSE); + + for (itr = type; itr != NULL; itr = itr->parent) + { + unsigned cur_size = itr->type_size - sizeof(Eina_Model_Type); + unsigned i, cur_count = cur_size / sizeof(void *); + const void * const *ptr = (const void **)((const char *)itr + sizeof(Eina_Model_Type)); + + if (cur_size == 0) break; + + for (i = 0; i < cur_count; i++) + { + if (desc->ops.type.extension[i]) continue; + desc->ops.type.extension[i] = ptr[i]; + } + } + } + desc->cache.types = malloc(count * sizeof(Eina_Model_Type *)); - EINA_SAFETY_ON_NULL_RETURN_VAL(desc->cache.types, EINA_FALSE); + EINA_SAFETY_ON_NULL_GOTO(desc->cache.types, cache_types_failed); desc->total.types = count; for (count = 0, itr = type; itr != NULL; itr = itr->parent, count++) desc->cache.types[count] = itr; return EINA_TRUE; + + cache_types_failed: + free(desc->ops.type.extension); + return EINA_FALSE; } static inline Eina_Bool @@ -859,6 +911,7 @@ _eina_model_description_get_internal(const Eina_Model_Type *type) free(desc->cache.ifaces); failed_ifaces: free(desc->cache.types); + free(desc->ops.type.extension); failed_type: free(desc); return NULL; @@ -880,6 +933,7 @@ _eina_model_description_dispose_internal(Eina_Model_Description *desc) INF("Disposed model description for type %p (%s)", type, type->name); + free(desc->ops.type.extension); free(desc->cache.types); free(desc->cache.ifaces); free(desc->cache.privates); @@ -1040,6 +1094,8 @@ _eina_model_interface_find_offset(const Eina_Model_Interface *iface, unsigned in const unsigned char *ptr = (const unsigned char *)iface; const void **addr = (const void **)(ptr + offset); + if (offset + sizeof(void *) > iface->interface_size) return NULL; + if (*addr) return *addr; if (!iface->interfaces) return NULL; @@ -1053,30 +1109,6 @@ _eina_model_interface_find_offset(const Eina_Model_Interface *iface, unsigned in return NULL; } -/* similar to _eina_model_interface_find_offset(), but looks for - * offset in Eina_Model_Interface::value instead of the interface - * itself. - */ -static const void * -_eina_model_interface_value_find_offset(const Eina_Model_Interface *iface, unsigned int offset) -{ - const Eina_Model_Interface **itr; - const unsigned char *ptr = iface->value; - const void **addr = (const void **)(ptr + offset); - - if ((ptr) && (*addr)) return *addr; - if (!iface->interfaces) return NULL; - - for (itr = iface->interfaces; *itr != NULL; itr++) - { - const void *r = _eina_model_interface_value_find_offset(*itr, offset); - if (r) - return r; - } - - return NULL; -} - static void _eina_model_event_callback_free_deleted(Eina_Model *model) { @@ -1945,6 +1977,7 @@ static const Eina_Model_Event_Description _eina_model_type_base_events[] = { static const Eina_Model_Type _EINA_MODEL_TYPE_BASE = { EINA_MODEL_TYPE_VERSION, 0, /* there is no private data */ + sizeof(Eina_Model_Type), "Eina_Model_Type_Base", NULL, /* should be the only type with NULL here! */ NULL, /* no interfaces implemented */ @@ -1975,7 +2008,10 @@ static const Eina_Model_Type _EINA_MODEL_TYPE_BASE = { _eina_model_type_base_child_sorted_iterator_get, _eina_model_type_base_child_filtered_iterator_get, _eina_model_type_base_to_string, - NULL /* no extensions */ + NULL, /* extension pointer */ + NULL, /* extension pointer */ + NULL, /* extension pointer */ + NULL /* extension pointer */ }; /* @@ -2087,7 +2123,7 @@ _eina_model_type_mixin_compare(const Eina_Model *a, const Eina_Model *b, int *cm if (priv->if_properties) { Eina_Bool (*compare)(const Eina_Model*, const Eina_Model*, int *) = - _eina_model_interface_value_find_offset + _eina_model_interface_find_offset (priv->if_properties, offsetof(Eina_Model_Interface_Properties, compare)); @@ -2103,7 +2139,7 @@ _eina_model_type_mixin_compare(const Eina_Model *a, const Eina_Model *b, int *cm if (priv->if_children) { Eina_Bool (*compare)(const Eina_Model*, const Eina_Model*, int *) = - _eina_model_interface_value_find_offset + _eina_model_interface_find_offset (priv->if_children, offsetof(Eina_Model_Interface_Children, compare)); @@ -2280,6 +2316,7 @@ _eina_model_type_mixin_child_sort(Eina_Model *model, Eina_Compare_Cb compare) static const Eina_Model_Type _EINA_MODEL_TYPE_MIXIN = { EINA_MODEL_TYPE_VERSION, sizeof(Eina_Model_Type_Mixin_Data), + sizeof(Eina_Model_Type), "Eina_Model_Type_Mixin", &_EINA_MODEL_TYPE_BASE, NULL, /* no interfaces implemented */ @@ -2310,7 +2347,10 @@ static const Eina_Model_Type _EINA_MODEL_TYPE_MIXIN = { NULL, /* use default sorted iterator get */ NULL, /* use default filtered iterator get */ NULL, /* use default to string */ - NULL /* no extensions */ + NULL, /* extension pointer */ + NULL, /* extension pointer */ + NULL, /* extension pointer */ + NULL /* extension pointer */ }; #undef EINA_MODEL_TYPE_MIXIN_GET @@ -2468,7 +2508,25 @@ _eina_model_interface_properties_hash_names_list(const Eina_Model *model) } #undef EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET -static const Eina_Model_Interface_Properties _EINA_MODEL_INTERFACE_PROPERTIES_HASH_VALUE = { +static const Eina_Model_Interface_Properties _EINA_MODEL_INTERFACE_PROPERTIES_HASH = { + { + EINA_MODEL_INTERFACE_VERSION, + sizeof(Eina_Hash *), + sizeof(Eina_Model_Interface_Properties), + _EINA_MODEL_INTERFACE_NAME_PROPERTIES, + NULL, /* no parent interfaces */ + NULL, /* no extra events */ + _eina_model_interface_properties_hash_setup, + _eina_model_interface_properties_hash_flush, + _eina_model_interface_properties_hash_constructor, + _eina_model_interface_properties_hash_destructor, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL + }, EINA_MODEL_INTERFACE_PROPERTIES_VERSION, NULL, /* no compare */ NULL, /* no load */ @@ -2479,21 +2537,6 @@ static const Eina_Model_Interface_Properties _EINA_MODEL_INTERFACE_PROPERTIES_HA _eina_model_interface_properties_hash_names_list }; -static const Eina_Model_Interface _EINA_MODEL_INTERFACE_PROPERTIES_HASH = { - EINA_MODEL_INTERFACE_VERSION, - sizeof(Eina_Hash *), - _EINA_MODEL_INTERFACE_NAME_PROPERTIES, - NULL, /* no parent interfaces */ - NULL, /* no extra events */ - _eina_model_interface_properties_hash_setup, - _eina_model_interface_properties_hash_flush, - _eina_model_interface_properties_hash_constructor, - _eina_model_interface_properties_hash_destructor, - NULL, - NULL, - &_EINA_MODEL_INTERFACE_PROPERTIES_HASH_VALUE -}; - /* EINA_MODEL_INTERFACE_PROPERTIES_STRUCT ******************************/ static Eina_Value_Struct * @@ -2615,7 +2658,25 @@ _eina_model_interface_properties_struct_names_list(const Eina_Model *model) } #undef EINA_MODEL_INTERFACE_PROPERTIES_STRUCT_GET -static const Eina_Model_Interface_Properties _EINA_MODEL_INTERFACE_PROPERTIES_STRUCT_VALUE = { +static const Eina_Model_Interface_Properties _EINA_MODEL_INTERFACE_PROPERTIES_STRUCT = { + { + EINA_MODEL_INTERFACE_VERSION, + sizeof(Eina_Value), + sizeof(Eina_Model_Interface_Properties), + _EINA_MODEL_INTERFACE_NAME_PROPERTIES, + NULL, /* no parent interfaces */ + NULL, /* no extra events */ + _eina_model_interface_properties_struct_setup, + _eina_model_interface_properties_struct_flush, + _eina_model_interface_properties_struct_constructor, + _eina_model_interface_properties_struct_destructor, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL + }, EINA_MODEL_INTERFACE_PROPERTIES_VERSION, NULL, /* no compare */ NULL, /* no load */ @@ -2626,21 +2687,6 @@ static const Eina_Model_Interface_Properties _EINA_MODEL_INTERFACE_PROPERTIES_ST _eina_model_interface_properties_struct_names_list }; -static const Eina_Model_Interface _EINA_MODEL_INTERFACE_PROPERTIES_STRUCT = { - EINA_MODEL_INTERFACE_VERSION, - sizeof(Eina_Value), - _EINA_MODEL_INTERFACE_NAME_PROPERTIES, - NULL, /* no parent interfaces */ - NULL, /* no extra events */ - _eina_model_interface_properties_struct_setup, - _eina_model_interface_properties_struct_flush, - _eina_model_interface_properties_struct_constructor, - _eina_model_interface_properties_struct_destructor, - NULL, - NULL, - &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT_VALUE -}; - /* EINA_MODEL_INTERFACE_CHILDREN_INARRAY ******************************/ #define EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model) \ @@ -2788,7 +2834,25 @@ _eina_model_interface_children_inarray_sort(Eina_Model *model, Eina_Compare_Cb c } #undef EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET -static const Eina_Model_Interface_Children _EINA_MODEL_INTERFACE_CHILDREN_INARRAY_VALUE = { +static const Eina_Model_Interface_Children _EINA_MODEL_INTERFACE_CHILDREN_INARRAY = { + { + EINA_MODEL_INTERFACE_VERSION, + sizeof(Eina_Inarray), + sizeof(Eina_Model_Interface_Children), + _EINA_MODEL_INTERFACE_NAME_CHILDREN, + NULL, /* no parent interfaces */ + NULL, /* no extra events */ + _eina_model_interface_children_inarray_setup, + _eina_model_interface_children_inarray_flush, + _eina_model_interface_children_inarray_constructor, + _eina_model_interface_children_inarray_destructor, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL + }, EINA_MODEL_INTERFACE_CHILDREN_VERSION, NULL, /* no compare */ NULL, /* no load */ @@ -2801,108 +2865,35 @@ static const Eina_Model_Interface_Children _EINA_MODEL_INTERFACE_CHILDREN_INARRA _eina_model_interface_children_inarray_sort }; -static const Eina_Model_Interface _EINA_MODEL_INTERFACE_CHILDREN_INARRAY = { - EINA_MODEL_INTERFACE_VERSION, - sizeof(Eina_Inarray), - _EINA_MODEL_INTERFACE_NAME_CHILDREN, - NULL, /* no parent interfaces */ - NULL, /* no extra events */ - _eina_model_interface_children_inarray_setup, - _eina_model_interface_children_inarray_flush, - _eina_model_interface_children_inarray_constructor, - _eina_model_interface_children_inarray_destructor, - NULL, - NULL, - &_EINA_MODEL_INTERFACE_CHILDREN_INARRAY_VALUE -}; - /* EINA_MODEL_TYPE_GENERIC ********************************************/ static const Eina_Model_Interface *_EINA_MODEL_TYPE_GENERIC_IFACES[] = { - &_EINA_MODEL_INTERFACE_PROPERTIES_HASH, - &_EINA_MODEL_INTERFACE_CHILDREN_INARRAY, + &_EINA_MODEL_INTERFACE_PROPERTIES_HASH.base, + &_EINA_MODEL_INTERFACE_CHILDREN_INARRAY.base, NULL }; -static const Eina_Model_Type _EINA_MODEL_TYPE_GENERIC = { - EINA_MODEL_TYPE_VERSION, - 0, - "Eina_Model_Type_Generic", - &_EINA_MODEL_TYPE_MIXIN, - _EINA_MODEL_TYPE_GENERIC_IFACES, - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL /* inherit from mix-in */ -}; +static const Eina_Model_Type _EINA_MODEL_TYPE_GENERIC = + EINA_MODEL_TYPE_INIT_NOPRIVATE("Eina_Model_Type_Generic", + Eina_Model_Type, + &_EINA_MODEL_TYPE_MIXIN, + _EINA_MODEL_TYPE_GENERIC_IFACES, + NULL); /* EINA_MODEL_TYPE_STRUCT ********************************************/ static const Eina_Model_Interface *_EINA_MODEL_TYPE_STRUCT_IFACES[] = { - &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT, - &_EINA_MODEL_INTERFACE_CHILDREN_INARRAY, + &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base, + &_EINA_MODEL_INTERFACE_CHILDREN_INARRAY.base, NULL }; -static const Eina_Model_Type _EINA_MODEL_TYPE_STRUCT = { - EINA_MODEL_TYPE_VERSION, - 0, - "Eina_Model_Type_Struct", - &_EINA_MODEL_TYPE_MIXIN, - _EINA_MODEL_TYPE_STRUCT_IFACES, - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL, /* inherit from mix-in */ - NULL /* inherit from mix-in */ -}; +static const Eina_Model_Type _EINA_MODEL_TYPE_STRUCT = + EINA_MODEL_TYPE_INIT_NOPRIVATE("Eina_Model_Type_Struct", + Eina_Model_Type, + &_EINA_MODEL_TYPE_MIXIN, + _EINA_MODEL_TYPE_STRUCT_IFACES, + NULL); /** */ @@ -2985,10 +2976,10 @@ eina_model_init(void) EINA_MODEL_TYPE_GENERIC = &_EINA_MODEL_TYPE_GENERIC; EINA_MODEL_TYPE_STRUCT = &_EINA_MODEL_TYPE_STRUCT; - EINA_MODEL_INTERFACE_PROPERTIES_HASH = &_EINA_MODEL_INTERFACE_PROPERTIES_HASH; - EINA_MODEL_INTERFACE_PROPERTIES_STRUCT = &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT; + EINA_MODEL_INTERFACE_PROPERTIES_HASH = &_EINA_MODEL_INTERFACE_PROPERTIES_HASH.base; + EINA_MODEL_INTERFACE_PROPERTIES_STRUCT = &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base; - EINA_MODEL_INTERFACE_CHILDREN_INARRAY = &_EINA_MODEL_INTERFACE_CHILDREN_INARRAY; + EINA_MODEL_INTERFACE_CHILDREN_INARRAY = &_EINA_MODEL_INTERFACE_CHILDREN_INARRAY.base; EINA_MODEL_INTERFACE_NAME_PROPERTIES = _EINA_MODEL_INTERFACE_NAME_PROPERTIES; EINA_MODEL_INTERFACE_NAME_CHILDREN = _EINA_MODEL_INTERFACE_NAME_CHILDREN; @@ -4681,6 +4672,40 @@ eina_model_type_private_data_get(const Eina_Model *model, const Eina_Model_Type return NULL; } +EAPI const void * +eina_model_method_resolve(const Eina_Model *model, unsigned int offset) +{ + const Eina_Model_Description *desc; + + EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL(offset > sizeof(Eina_Model_Type), NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL(offset % sizeof(void *) == 0, NULL); + + desc = model->desc; + EINA_SAFETY_ON_FALSE_RETURN_VAL + (offset + sizeof(void *) < desc->cache.types[0]->type_size, NULL); + + offset -= sizeof(Eina_Model_Type); + offset /= sizeof(void *); + return desc->ops.type.extension[offset]; +} + +EAPI const void * +eina_model_type_method_resolve(const Eina_Model_Type *type, const Eina_Model *model, unsigned int offset) +{ + const Eina_Model_Description *desc; + + EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL(offset > sizeof(Eina_Model_Type), NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL(offset % sizeof(void *) == 0, NULL); + + desc = model->desc; + EINA_SAFETY_ON_FALSE_RETURN_VAL + (offset + sizeof(void *) < desc->cache.types[0]->type_size, NULL); + + return _eina_model_type_find_offset(type, offset); +} + /* interface functions ************************************************/ EAPI Eina_Bool @@ -4804,6 +4829,15 @@ eina_model_interface_deep_copy(const Eina_Model_Interface *iface, const Eina_Mod return deep_copy(src, dst); } +EAPI const void * +eina_model_interface_method_resolve(const Eina_Model_Interface *iface, const Eina_Model *model, unsigned int offset) +{ + EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL(offset > sizeof(Eina_Model_Interface), NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL(offset % sizeof(void *) == 0, NULL); + return _eina_model_interface_find_offset(iface, offset); +} + /* Eina_Model_Interface_Properties ************************************/ @@ -4818,7 +4852,7 @@ eina_model_interface_properties_compare(const Eina_Model_Interface *iface, const EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, a, EINA_FALSE); EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, b, EINA_FALSE); - compare = _eina_model_interface_value_find_offset + compare = _eina_model_interface_find_offset (iface, offsetof(Eina_Model_Interface_Properties, compare)); EINA_SAFETY_ON_NULL_RETURN_VAL(compare, EINA_FALSE); return compare(a, b, cmp); @@ -4831,7 +4865,7 @@ eina_model_interface_properties_load(const Eina_Model_Interface *iface, Eina_Mod EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - load = _eina_model_interface_value_find_offset + load = _eina_model_interface_find_offset (iface, offsetof(Eina_Model_Interface_Properties, load)); EINA_SAFETY_ON_NULL_RETURN_VAL(load, EINA_FALSE); return load(model); @@ -4844,7 +4878,7 @@ eina_model_interface_properties_unload(const Eina_Model_Interface *iface, Eina_M EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - unload = _eina_model_interface_value_find_offset + unload = _eina_model_interface_find_offset (iface, offsetof(Eina_Model_Interface_Properties, unload)); EINA_SAFETY_ON_NULL_RETURN_VAL(unload, EINA_FALSE); return unload(model); @@ -4859,7 +4893,7 @@ eina_model_interface_properties_get(const Eina_Model_Interface *iface, const Ein EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE); EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - get = _eina_model_interface_value_find_offset + get = _eina_model_interface_find_offset (iface, offsetof(Eina_Model_Interface_Properties, get)); EINA_SAFETY_ON_NULL_RETURN_VAL(get, EINA_FALSE); return get(model, name, value); @@ -4875,7 +4909,7 @@ eina_model_interface_properties_set(const Eina_Model_Interface *iface, Eina_Mode EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), EINA_FALSE); EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - set = _eina_model_interface_value_find_offset + set = _eina_model_interface_find_offset (iface, offsetof(Eina_Model_Interface_Properties, set)); EINA_SAFETY_ON_NULL_RETURN_VAL(set, EINA_FALSE); return set(model, name, value); @@ -4889,7 +4923,7 @@ eina_model_interface_properties_del(const Eina_Model_Interface *iface, Eina_Mode EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE); EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - del = _eina_model_interface_value_find_offset + del = _eina_model_interface_find_offset (iface, offsetof(Eina_Model_Interface_Properties, del)); EINA_SAFETY_ON_NULL_RETURN_VAL(del, EINA_FALSE); return del(model, name); @@ -4902,7 +4936,7 @@ eina_model_interface_properties_names_list_get(const Eina_Model_Interface *iface EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, NULL); - names_list_get = _eina_model_interface_value_find_offset + names_list_get = _eina_model_interface_find_offset (iface, offsetof(Eina_Model_Interface_Properties, names_list_get)); EINA_SAFETY_ON_NULL_RETURN_VAL(names_list_get, NULL); return names_list_get(model); @@ -4922,7 +4956,7 @@ eina_model_interface_children_compare(const Eina_Model_Interface *iface, const E EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, a, EINA_FALSE); EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, b, EINA_FALSE); - compare = _eina_model_interface_value_find_offset + compare = _eina_model_interface_find_offset (iface, offsetof(Eina_Model_Interface_Children, compare)); EINA_SAFETY_ON_NULL_RETURN_VAL(compare, EINA_FALSE); return compare(a, b, cmp); @@ -4935,7 +4969,7 @@ eina_model_interface_children_load(const Eina_Model_Interface *iface, Eina_Model EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - load = _eina_model_interface_value_find_offset + load = _eina_model_interface_find_offset (iface, offsetof(Eina_Model_Interface_Children, load)); EINA_SAFETY_ON_NULL_RETURN_VAL(load, EINA_FALSE); return load(model); @@ -4948,7 +4982,7 @@ eina_model_interface_children_unload(const Eina_Model_Interface *iface, Eina_Mod EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - unload = _eina_model_interface_value_find_offset + unload = _eina_model_interface_find_offset (iface, offsetof(Eina_Model_Interface_Children, unload)); EINA_SAFETY_ON_NULL_RETURN_VAL(unload, EINA_FALSE); return unload(model); @@ -4961,7 +4995,7 @@ eina_model_interface_children_count(const Eina_Model_Interface *iface, const Ein EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, -1); - count = _eina_model_interface_value_find_offset + count = _eina_model_interface_find_offset (iface, offsetof(Eina_Model_Interface_Children, count)); EINA_SAFETY_ON_NULL_RETURN_VAL(count, -1); return count(model); @@ -4974,7 +5008,7 @@ eina_model_interface_children_get(const Eina_Model_Interface *iface, const Eina_ EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, NULL); - get = _eina_model_interface_value_find_offset + get = _eina_model_interface_find_offset (iface, offsetof(Eina_Model_Interface_Children, get)); EINA_SAFETY_ON_NULL_RETURN_VAL(get, NULL); return get(model, position); @@ -4987,7 +5021,7 @@ EAPI Eina_Bool eina_model_interface_children_set(const Eina_Model_Interface *ifa EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); EINA_MODEL_INSTANCE_CHECK_VAL(child, EINA_FALSE); - set = _eina_model_interface_value_find_offset + set = _eina_model_interface_find_offset (iface, offsetof(Eina_Model_Interface_Children, set)); EINA_SAFETY_ON_NULL_RETURN_VAL(set, EINA_FALSE); return set(model, position, child); @@ -5000,7 +5034,7 @@ eina_model_interface_children_del(const Eina_Model_Interface *iface, Eina_Model EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - del = _eina_model_interface_value_find_offset + del = _eina_model_interface_find_offset (iface, offsetof(Eina_Model_Interface_Children, del)); EINA_SAFETY_ON_NULL_RETURN_VAL(del, EINA_FALSE); return del(model, position); @@ -5015,7 +5049,7 @@ eina_model_interface_children_insert_at(const Eina_Model_Interface *iface, Eina_ EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); EINA_MODEL_INSTANCE_CHECK_VAL(child, EINA_FALSE); - insert_at = _eina_model_interface_value_find_offset + insert_at = _eina_model_interface_find_offset (iface, offsetof(Eina_Model_Interface_Children, insert_at)); EINA_SAFETY_ON_NULL_RETURN_VAL(insert_at, EINA_FALSE); return insert_at(model, position, child); @@ -5029,7 +5063,7 @@ eina_model_interface_children_sort(const Eina_Model_Interface *iface, Eina_Model EINA_SAFETY_ON_NULL_RETURN(compare); EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK(iface, model); - sort = _eina_model_interface_value_find_offset + sort = _eina_model_interface_find_offset (iface, offsetof(Eina_Model_Interface_Children, sort)); EINA_SAFETY_ON_NULL_RETURN(sort); return sort(model, compare); @@ -5040,7 +5074,7 @@ _eina_model_struct_set(Eina_Model *m, const Eina_Value_Struct_Desc *desc, void * { Eina_Value_Struct st = {desc, memory}; Eina_Value *val = eina_model_interface_private_data_get - (m, &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT); + (m, &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base); return eina_value_pset(val, &st); } @@ -5071,7 +5105,7 @@ eina_model_struct_set(Eina_Model *model, const Eina_Value_Struct_Desc *desc, voi EINA_SAFETY_ON_FALSE_RETURN_VAL (desc->version == EINA_VALUE_STRUCT_DESC_VERSION, EINA_FALSE); EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL - (&_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT, model, EINA_FALSE); + (&_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base, model, EINA_FALSE); return _eina_model_struct_set(model, desc, memory); } @@ -5088,10 +5122,10 @@ eina_model_struct_get(const Eina_Model *model, const Eina_Value_Struct_Desc **p_ if (p_memory) *p_memory = NULL; EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL - (&_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT, model, EINA_FALSE); + (&_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base, model, EINA_FALSE); val = eina_model_interface_private_data_get - (model, &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT); + (model, &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base); EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_pget(val, &st), EINA_FALSE); -- 2.7.4