1 /* EINA - EFL data type library
2 * Copyright (C) 2012 ProFUSION embedded systems
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
25 #elif defined __GNUC__
26 # define alloca __builtin_alloca
28 # define alloca __alloca
29 #elif defined _MSC_VER
31 # define alloca _alloca
37 void *alloca (size_t);
40 #ifdef HAVE_EXECINFO_H
44 #include "eina_config.h"
45 #include "eina_private.h"
46 #include "eina_error.h"
48 #include "eina_mempool.h"
49 #include "eina_lock.h"
50 #include "eina_inlist.h"
51 #include "eina_strbuf.h"
53 /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
54 #include "eina_safety_checks.h"
55 #include "eina_value.h" /* eina-safety used in inline.x */
56 #include "eina_model.h"
58 /*============================================================================*
60 *============================================================================*/
66 static Eina_Mempool *_eina_model_mp = NULL;
67 static Eina_Hash *_eina_model_inner_mps = NULL;
68 static Eina_Lock _eina_model_inner_mps_lock;
69 static char *_eina_model_mp_choice = NULL;
70 static Eina_Hash *_eina_model_descriptions = NULL;
71 static Eina_Lock _eina_model_descriptions_lock;
72 static int _eina_model_log_dom = -1;
74 EINA_MODEL_DEBUG_NONE = 0,
75 EINA_MODEL_DEBUG_CHECK = 1,
76 EINA_MODEL_DEBUG_BACKTRACE = 2,
77 } _eina_model_debug = EINA_MODEL_DEBUG_NONE;
78 static Eina_Lock _eina_model_debug_list_lock;
79 static Eina_List *_eina_model_debug_list = NULL;
81 static const char _eina_model_str_deleted[] = "deleted";
82 static const char _eina_model_str_freed[] = "freed";
83 static const char _eina_model_str_property_set[] = "property,set";
84 static const char _eina_model_str_property_del[] = "property,deleted";
85 static const char _eina_model_str_children_changed[] = "children,changed";
86 static const char _eina_model_str_child_inserted[] = "child,inserted";
87 static const char _eina_model_str_child_set[] = "child,set";
88 static const char _eina_model_str_child_del[] = "child,deleted";
89 static const char _eina_model_str_loaded[] = "loaded";
90 static const char _eina_model_str_unloaded[] = "unloaded";
91 static const char _eina_model_str_properties_loaded[] = "properties,loaded";
92 static const char _eina_model_str_properties_unloaded[] = "properties,unloaded";
93 static const char _eina_model_str_children_loaded[] = "children,loaded";
94 static const char _eina_model_str_children_unloaded[] = "children,unloaded";
99 #define CRITICAL(...) EINA_LOG_DOM_CRIT(_eina_model_log_dom, __VA_ARGS__)
104 #define ERR(...) EINA_LOG_DOM_ERR(_eina_model_log_dom, __VA_ARGS__)
109 #define WRN(...) EINA_LOG_DOM_WARN(_eina_model_log_dom, __VA_ARGS__)
114 #define INF(...) EINA_LOG_DOM_INFO(_eina_model_log_dom, __VA_ARGS__)
119 #define DBG(...) EINA_LOG_DOM_DBG(_eina_model_log_dom, __VA_ARGS__)
122 /* convenience sort array of Eina_Model* giving compare Eina_Model* instead of
126 _eina_model_array_partition(Eina_Model **array, unsigned int start, unsigned int last, unsigned int pivot, Eina_Compare_Cb compare)
128 Eina_Model **itr, **itr_end, *tmp, *pivot_value;
130 pivot_value = tmp = array[pivot];
131 array[pivot] = array[last];
136 itr_end = array + last;
137 for (; itr < itr_end; itr++)
139 if (compare(*itr, pivot_value) < 0)
149 array[last] = array[pivot];
156 _eina_model_array_sort(Eina_Model **array, unsigned int start, unsigned int last, Eina_Compare_Cb compare)
158 unsigned int pivot, new_pivot;
163 pivot = start + (last - start) / 2; /* avoid overflow */
164 new_pivot = _eina_model_array_partition(array, start, last, pivot, compare);
166 if (start + 1 < new_pivot)
167 _eina_model_array_sort(array, start, new_pivot - 1, compare);
169 if (new_pivot + 1 < last)
170 _eina_model_array_sort(array, new_pivot + 1, last, compare);
174 * Most of inner allocations are made with internal mempools, types
175 * and thus instace private data will repeat and it's good to use them.
177 * To save on the number of mempools, they are kept per size, not per
180 * This is done by means of _eina_model_inner_alloc() and
181 * _eina_model_inner_free(), both at thread safe.
184 typedef struct _Eina_Model_Inner_Mp Eina_Model_Inner_Mp;
185 struct _Eina_Model_Inner_Mp
187 Eina_Mempool *mempool;
192 _eina_model_inner_mp_dispose(int size, Eina_Model_Inner_Mp *imp)
194 EINA_SAFETY_ON_FALSE_RETURN(imp->refcount == 0);
196 eina_hash_del_by_key(_eina_model_inner_mps, &size);
197 eina_mempool_del(imp->mempool);
201 static inline Eina_Model_Inner_Mp *
202 _eina_model_inner_mp_get(int size)
204 Eina_Model_Inner_Mp *imp = eina_hash_find(_eina_model_inner_mps, &size);
207 imp = malloc(sizeof(Eina_Model_Inner_Mp));
213 imp->mempool = eina_mempool_add(_eina_model_mp_choice,
214 "Eina_Model_Inner_Mp", NULL, size, 16);
221 if (!eina_hash_add(_eina_model_inner_mps, &size, imp))
223 eina_mempool_del(imp->mempool);
232 _eina_model_inner_alloc_internal(int size)
234 Eina_Model_Inner_Mp *imp;
237 imp = _eina_model_inner_mp_get(size);
238 if (!imp) return NULL;
240 mem = eina_mempool_malloc(imp->mempool, size);
241 if (mem) imp->refcount++;
242 else if (imp->refcount == 0) _eina_model_inner_mp_dispose(size, imp);
248 _eina_model_inner_free_internal(int size, void *mem)
250 Eina_Model_Inner_Mp *imp = eina_hash_find(_eina_model_inner_mps, &size);
251 EINA_SAFETY_ON_NULL_RETURN(imp);
253 eina_mempool_free(imp->mempool, mem);
256 if (imp->refcount > 0) return;
257 _eina_model_inner_mp_dispose(size, imp);
261 _eina_model_inner_alloc(size_t size)
265 if (size > 512) return malloc(size);
267 eina_lock_take(&_eina_model_inner_mps_lock);
268 mem = _eina_model_inner_alloc_internal(size);
269 eina_lock_release(&_eina_model_inner_mps_lock);
275 _eina_model_inner_free(size_t size, void *mem)
283 eina_lock_take(&_eina_model_inner_mps_lock);
284 _eina_model_inner_free_internal(size, mem);
285 eina_lock_release(&_eina_model_inner_mps_lock);
289 typedef union _Eina_Model_Provider Eina_Model_Provider;
290 union _Eina_Model_Provider
292 const Eina_Model_Type *type;
293 const Eina_Model_Interface *iface;
296 /* store event name to aid searching */
297 typedef struct _Eina_Model_Event_Description_Cache Eina_Model_Event_Description_Cache;
298 struct _Eina_Model_Event_Description_Cache
301 const Eina_Model_Event_Description *desc;
302 Eina_Model_Provider provider;
305 /* description is an optimized structure for type. It's built at runtime
306 * to avoid user input errors and help declaration.
308 * lookups (ifaces, events) are sorted for binary search.
310 * recursion is avoided by expansion of every possible value in "cache"
313 * the first usable operation is stopred for type at "ops" struct,
314 * avoiding usage of _eina_model_type_find_offset().
316 * Get a model type description using _eina_model_description_get(),
317 * when it's not used anymore use
318 * _eina_model_description_dispose(). These operations are thread
321 typedef struct _Eina_Model_Description Eina_Model_Description;
322 struct _Eina_Model_Description
325 const Eina_Model_Type **types; /* size = total.types */
326 const Eina_Model_Interface **ifaces; /* sorted, size = total.ifaces */
327 Eina_Model_Provider *privates; /* size = total.privates (types + ifaces) */
328 Eina_Model_Event_Description_Cache *events; /* size = total.events */
331 /* ops are the topmost operation to use for type/interface */
333 Eina_Bool (*setup)(Eina_Model *model);
334 Eina_Bool (*flush)(Eina_Model *model);
335 Eina_Bool (*constructor)(Eina_Model *model);
336 Eina_Bool (*destructor)(Eina_Model *model);
337 Eina_Bool (*copy)(const Eina_Model *src, Eina_Model *dst);
338 Eina_Bool (*deep_copy)(const Eina_Model *src, Eina_Model *dst);
339 Eina_Bool (*compare)(const Eina_Model *a, const Eina_Model *b, int *cmp);
340 Eina_Bool (*load)(Eina_Model *model);
341 Eina_Bool (*unload)(Eina_Model *model);
342 Eina_Bool (*property_get)(const Eina_Model *model, const char *name, Eina_Value *value);
343 Eina_Bool (*property_set)(Eina_Model *model, const char *name, const Eina_Value *value);
344 Eina_Bool (*property_del)(Eina_Model *model, const char *name);
345 Eina_List *(*properties_names_list_get)(const Eina_Model *model);
346 int (*child_count)(const Eina_Model *model);
347 Eina_Model *(*child_get)(const Eina_Model *model, unsigned int position);
348 Eina_Bool (*child_set)(Eina_Model *model, unsigned int position, Eina_Model *child);
349 Eina_Bool (*child_del)(Eina_Model *model, unsigned int position);
350 Eina_Bool (*child_insert_at)(Eina_Model *model, unsigned int position, Eina_Model *child);
351 int (*child_find)(const Eina_Model *model, unsigned int start_position, const Eina_Model *other);
352 int (*child_criteria_match)(const Eina_Model *model, unsigned int start_position, Eina_Each_Cb match, const void *data);
353 void (*child_sort)(Eina_Model *model, Eina_Compare_Cb compare);
354 Eina_Iterator *(*child_iterator_get)(Eina_Model *model, unsigned int start, unsigned int count);
355 Eina_Iterator *(*child_reversed_iterator_get)(Eina_Model *model, unsigned int start, unsigned int count);
356 Eina_Iterator *(*child_sorted_iterator_get)(Eina_Model *model, unsigned int start, unsigned int count, Eina_Compare_Cb compare);
357 Eina_Iterator *(*child_filtered_iterator_get)(Eina_Model *model, unsigned int start, unsigned int count, Eina_Each_Cb match, const void *data);
358 char *(*to_string)(const Eina_Model *model); /**< used to represent model as string, usually for debug purposes or user convenience */
359 const void **extension;
365 unsigned int privates;
366 unsigned int size; /* sum of all private sizes */
373 _eina_model_description_type_fill(Eina_Model_Description *desc, const Eina_Model_Type *type)
375 const Eina_Model_Type *itr, *last_itr = NULL;
376 unsigned int count, child_size = 0;
378 for (count = 0, itr = type; itr != NULL; itr = itr->parent, count++)
380 if (itr->version != EINA_MODEL_TYPE_VERSION)
382 CRITICAL("Type %p version is %u, expected %u instead.",
383 itr, itr->version, EINA_MODEL_TYPE_VERSION);
388 CRITICAL("Type %p provides no name!", itr);
391 if (itr->type_size < sizeof(Eina_Model_Type))
393 CRITICAL("Type %p %s size must be >= sizeof(Eina_Model_Type)!",
397 if (child_size == 0) child_size = itr->type_size;
398 else if (child_size < itr->type_size)
400 CRITICAL("Type %p %s size is bigger than its child type %p %s!",
401 itr, itr->name, last_itr, last_itr->name);
406 #define DEF_METH(meth) \
407 if (!desc->ops.type.meth) desc->ops.type.meth = itr->meth
410 DEF_METH(constructor);
411 DEF_METH(destructor);
417 DEF_METH(property_get);
418 DEF_METH(property_set);
419 DEF_METH(property_del);
420 DEF_METH(properties_names_list_get);
421 DEF_METH(child_count);
425 DEF_METH(child_insert_at);
426 DEF_METH(child_find);
427 DEF_METH(child_criteria_match);
428 DEF_METH(child_sort);
429 DEF_METH(child_iterator_get);
430 DEF_METH(child_reversed_iterator_get);
431 DEF_METH(child_sorted_iterator_get);
432 DEF_METH(child_filtered_iterator_get);
436 if ((!itr->parent) && (itr != EINA_MODEL_TYPE_BASE))
438 CRITICAL("Type %p (%s) does not inherit from EINA_MODEL_TYPE_BASE!",
444 #define CK_METH(meth) \
445 if (!desc->ops.type.meth) \
447 CRITICAL("Mandatory method "#meth \
448 "() was not provided by type %p (%s).", \
454 CK_METH(constructor);
456 CK_METH(property_get);
459 if (child_size <= sizeof(Eina_Model_Type))
460 desc->ops.type.extension = NULL;
463 unsigned ext_size = child_size - sizeof(Eina_Model_Type);
464 unsigned ext_count = ext_size / sizeof(void *);
466 if (ext_size % sizeof(void *) != 0)
468 CRITICAL("Extension size %u is not multiple of sizeof(void*)",
473 desc->ops.type.extension = calloc(ext_count, sizeof(void *));
474 EINA_SAFETY_ON_NULL_RETURN_VAL(desc->ops.type.extension, EINA_FALSE);
476 for (itr = type; itr != NULL; itr = itr->parent)
478 unsigned cur_size = itr->type_size - sizeof(Eina_Model_Type);
479 unsigned i, cur_count = cur_size / sizeof(void *);
480 const void * const *ptr = (const void **)((const char *)itr + sizeof(Eina_Model_Type));
482 if (cur_size == 0) break;
484 for (i = 0; i < cur_count; i++)
486 if (desc->ops.type.extension[i]) continue;
487 desc->ops.type.extension[i] = ptr[i];
492 desc->cache.types = malloc(count * sizeof(Eina_Model_Type *));
493 EINA_SAFETY_ON_NULL_GOTO(desc->cache.types, cache_types_failed);
494 desc->total.types = count;
496 for (count = 0, itr = type; itr != NULL; itr = itr->parent, count++)
497 desc->cache.types[count] = itr;
502 free(desc->ops.type.extension);
506 static inline Eina_Bool
507 _eina_model_interface_implements(const Eina_Model_Interface *iface, const Eina_Model_Interface *query)
509 const Eina_Model_Interface **itr;
514 if (!iface->interfaces)
517 for (itr = iface->interfaces; *itr != NULL; itr++)
518 if (_eina_model_interface_implements(*itr, query))
524 /* apply topological sort and remove duplicates */
526 * TODO: Topological sort will only work for linked interfaces, but
527 * will ignore original ordering provided by types. Consider the
530 * - A_Type -> X_Iface (name: "MyIface")
531 * - B_Type -> Y_Iface (name: "MyIface")
533 * Both X_Iface and Y_Iface are different implementations of the
536 * B_Type inherits from A_Type, then Y_Iface must be looked up
537 * first, even though there is no link between Y_Iface and
540 * However, the way the current topological sort behaves, the
541 * roots may come out in any order. We need a stable version
542 * that sorts roots before removing them from graph.
544 * Thanks to Tasn to report it :-)
547 _eina_model_description_ifaces_fix(Eina_Model_Description *desc)
550 const Eina_Model_Interface *iface;
553 } *nodes, **pending, **roots;
554 unsigned int n_nodes = desc->total.ifaces, n_pending = 0, n_roots = 0, i, j;
555 Eina_Bool ret = EINA_TRUE;
557 nodes = alloca(n_nodes * sizeof(struct node));
558 pending = alloca(n_nodes * sizeof(struct node *));
559 roots = alloca(n_nodes * sizeof(struct node *));
562 for (i = 0, j = 0; i < n_nodes; i++)
565 for (k = 0; k < j; k++)
567 if (nodes[k].iface == desc->cache.ifaces[i])
571 continue; /* already exists */
573 nodes[j].iface = desc->cache.ifaces[i];
575 nodes[j].deps = NULL;
580 for (i = 0; i < n_nodes; i++)
582 for (j = 0; j < n_nodes; j++)
584 if (i == j) continue;
585 if (!_eina_model_interface_implements(nodes[j].iface,
590 nodes[j].deps = eina_list_append(nodes[j].deps, nodes + i);
593 for (i = 0; i < n_nodes; i++)
595 if (nodes[i].users == 0)
597 roots[n_roots] = nodes + i;
602 pending[n_pending] = nodes + i;
607 /* topological sort */
608 desc->total.ifaces = 0;
613 /* TODO: sort roots using input order? Or at least study if
614 * it's enough to change roots append to prepend.
616 * See comments above.
621 desc->cache.ifaces[desc->total.ifaces] = r->iface;
622 desc->total.ifaces++;
624 EINA_LIST_FREE(r->deps, d)
627 if (d->users > 0) continue;
632 /* remove node, it became a root */
633 for (j = 0; j < n_pending; j++)
639 pending[j] = pending[n_pending];
648 ERR("Dependency loop found for interfaces!");
649 for (i = 0; i < n_pending; i++)
650 ERR("%p (%s) is part of dependency loop!",
651 pending[i]->iface, pending[i]->iface->name);
652 CRITICAL("Cannot use type %p (%s) with broken interfaces!",
653 desc->cache.types[0], desc->cache.types[0]->name);
654 free(desc->cache.ifaces);
658 /* likely from still pending (dependency loops) */
659 for (i = 0; i < n_nodes; i++)
660 eina_list_free(nodes[i].deps);
666 _eina_model_description_ifaces_validate_and_count(const Eina_Model_Interface *iface, unsigned int *count)
668 if (iface->version != EINA_MODEL_INTERFACE_VERSION)
670 CRITICAL("Interface %p version is %u, expected %u instead.",
671 iface, iface->version, EINA_MODEL_INTERFACE_VERSION);
677 CRITICAL("Interface %p provides no name!", iface);
681 if (iface->interfaces)
683 const Eina_Model_Interface **itr = iface->interfaces;
684 for (; *itr != NULL; itr++)
685 if (!_eina_model_description_ifaces_validate_and_count(*itr, count))
694 _eina_model_description_ifaces_populate(Eina_Model_Description *desc, const Eina_Model_Interface *iface)
696 desc->cache.ifaces[desc->total.ifaces] = iface;
697 desc->total.ifaces++;
699 if (iface->interfaces)
701 const Eina_Model_Interface **itr = iface->interfaces;
702 for (; *itr != NULL; itr++)
703 _eina_model_description_ifaces_populate(desc, *itr);
708 _eina_model_description_ifaces_fill(Eina_Model_Description *desc)
710 const Eina_Model_Type **titr, **titr_end;
713 titr = desc->cache.types;
714 titr_end = titr + desc->total.types;
716 /* naively count all interfaces, remove duplicates later */
717 for (count = 0; titr < titr_end; titr++)
719 const Eina_Model_Type *type = *titr;
720 const Eina_Model_Interface **iitr = type->interfaces;
721 if (!type->interfaces) continue;
723 for (; *iitr != NULL; iitr++)
724 if (!_eina_model_description_ifaces_validate_and_count(*iitr, &count))
729 desc->cache.ifaces = NULL;
730 desc->total.ifaces = 0;
734 desc->cache.ifaces = malloc(count * sizeof(Eina_Model_Interface *));
735 EINA_SAFETY_ON_NULL_RETURN_VAL(desc->cache.ifaces, EINA_FALSE);
737 titr = desc->cache.types;
738 desc->total.ifaces = 0;
739 for (; titr < titr_end; titr++)
741 const Eina_Model_Type *type = *titr;
742 const Eina_Model_Interface **iitr = type->interfaces;
744 if (!type->interfaces) continue;
746 for (; *iitr != NULL; iitr++)
747 _eina_model_description_ifaces_populate(desc, *iitr);
750 return _eina_model_description_ifaces_fix(desc);
754 _eina_model_description_privates_fill(Eina_Model_Description *desc)
758 desc->total.privates = desc->total.types + desc->total.ifaces;
759 desc->cache.privates = malloc(desc->total.privates *
760 sizeof(Eina_Model_Provider));
761 EINA_SAFETY_ON_NULL_RETURN_VAL(desc->cache.privates, EINA_FALSE);
763 desc->total.size = 0;
765 for (i = 0; i < desc->total.types; i++)
767 const Eina_Model_Type *type = desc->cache.types[i];
768 desc->cache.privates[i].type = type;
769 if (type->private_size > 0)
771 unsigned int size = type->private_size;
772 if (size % sizeof(void *) != 0)
773 size += sizeof(void *) - (size % sizeof(void *));
774 desc->total.size += size;
778 for (i = 0; i < desc->total.ifaces; i++)
780 const Eina_Model_Interface *iface = desc->cache.ifaces[i];
781 desc->cache.privates[desc->total.types + i].iface = iface;
782 if (iface->private_size > 0)
784 unsigned int size = iface->private_size;
785 if (size % sizeof(void *) != 0)
786 size += sizeof(void *) - (size % sizeof(void *));
787 desc->total.size += size;
795 _eina_model_description_events_cmp(const void *pa, const void *pb)
797 const Eina_Model_Event_Description_Cache *a = pa, *b = pb;
798 return strcmp(a->name, b->name);
802 _eina_model_description_events_find(const Eina_Model_Description *desc, const Eina_Model_Event_Description *query)
805 for (i = 0; i < desc->total.events; i++)
807 const Eina_Model_Event_Description_Cache *itr = desc->cache.events + i;
808 if ((itr->name == query->name) || (strcmp(itr->name, query->name) == 0))
815 /* warn and remove duplicates, sort items to speed up lookups */
817 _eina_model_description_events_fill(Eina_Model_Description *desc)
819 unsigned int i, count = 0, type_events;
821 for (i = 0; i < desc->total.types; i++)
823 const Eina_Model_Event_Description *itr = desc->cache.types[i]->events;
825 for (; itr->name != NULL; itr++)
832 for (i = 0; i < desc->total.ifaces; i++)
834 const Eina_Model_Event_Description *itr = desc->cache.ifaces[i]->events;
836 for (; itr->name != NULL; itr++)
842 desc->cache.events = NULL;
843 desc->total.events = 0;
847 desc->cache.events = malloc(count *
848 sizeof(Eina_Model_Event_Description_Cache));
849 EINA_SAFETY_ON_NULL_RETURN_VAL(desc->cache.events, EINA_FALSE);
850 desc->total.events = 0;
852 for (i = 0; i < desc->total.types; i++)
854 const Eina_Model_Type *mtype = desc->cache.types[i];
855 const Eina_Model_Event_Description *itr = mtype->events;
857 for (; itr->name != NULL; itr++)
859 int j = _eina_model_description_events_find(desc, itr);
862 const Eina_Model_Event_Description_Cache *o = desc->cache.events + j;
863 const Eina_Model_Type *omtype = o->provider.type;
864 WRN("Ignored duplicated event '%s' (type: '%s') from "
865 "model type %p (%s): already exists with type '%s' "
866 "from model type %p (%s)",
868 itr->type ? itr->type : "",
870 o->desc->type ? o->desc->type : "",
871 omtype, omtype->name);
875 desc->cache.events[desc->total.events].name = itr->name;
876 desc->cache.events[desc->total.events].desc = itr;
877 desc->cache.events[desc->total.events].provider.type = mtype;
878 desc->total.events++;
882 for (i = 0; i < desc->total.ifaces; i++)
884 const Eina_Model_Interface *miface = desc->cache.ifaces[i];
885 const Eina_Model_Event_Description *itr = desc->cache.ifaces[i]->events;
887 for (; itr->name != NULL; itr++)
889 int j = _eina_model_description_events_find(desc, itr);
892 const Eina_Model_Event_Description_Cache *o = desc->cache.events + j;
893 if ((unsigned)j < type_events)
895 const Eina_Model_Type *omtype = o->provider.type;
896 WRN("Ignored duplicated event '%s' (type: '%s') from "
897 "model interface %p (%s): already exists with "
898 "type '%s' from model interface %p (%s)",
900 itr->type ? itr->type : "",
901 miface, miface->name,
902 o->desc->type ? o->desc->type : "",
903 omtype, omtype->name);
907 const Eina_Model_Interface *omiface = o->provider.iface;
908 WRN("Ignored duplicated event '%s' (iface: '%s') from "
909 "model interface %p (%s): already exists with "
910 "interface '%s' from model interface %p (%s)",
912 itr->type ? itr->type : "",
913 miface, miface->name,
914 o->desc->type ? o->desc->type : "",
915 omiface, omiface->name);
920 desc->cache.events[desc->total.events].name = itr->name;
921 desc->cache.events[desc->total.events].desc = itr;
922 desc->cache.events[desc->total.events].provider.iface = miface;
923 desc->total.events++;
927 qsort(desc->cache.events, desc->total.events,
928 sizeof(Eina_Model_Event_Description_Cache),
929 _eina_model_description_events_cmp);
934 static const Eina_Model_Description *
935 _eina_model_description_get_internal(const Eina_Model_Type *type)
937 Eina_Model_Description *desc;
939 desc = eina_hash_find(_eina_model_descriptions, &type);
946 desc = calloc(1, sizeof(Eina_Model_Description));
947 EINA_SAFETY_ON_NULL_RETURN_VAL(desc, NULL);
949 if (!_eina_model_description_type_fill(desc, type)) goto failed_type;
950 if (!_eina_model_description_ifaces_fill(desc)) goto failed_ifaces;
951 if (!_eina_model_description_privates_fill(desc)) goto failed_privates;
952 if (!_eina_model_description_events_fill(desc)) goto failed_events;
953 if (!eina_hash_add(_eina_model_descriptions, &type, desc)) goto failed_hash;
959 free(desc->cache.events);
961 free(desc->cache.privates);
963 free(desc->cache.ifaces);
965 free(desc->cache.types);
966 free(desc->ops.type.extension);
973 _eina_model_description_dispose_internal(Eina_Model_Description *desc)
975 const Eina_Model_Type *type;
977 EINA_SAFETY_ON_FALSE_RETURN(desc->refcount > 0);
979 if (desc->refcount > 0) return;
981 type = desc->cache.types[0];
982 if (!eina_hash_del_by_key(_eina_model_descriptions, &type))
983 ERR("Cannot find type %p (%s) in descriptions hash!",
986 INF("Disposed model description for type %p (%s)", type, type->name);
988 free(desc->ops.type.extension);
989 free(desc->cache.types);
990 free(desc->cache.ifaces);
991 free(desc->cache.privates);
992 free(desc->cache.events);
996 static const Eina_Model_Description *
997 _eina_model_description_get(const Eina_Model_Type *type)
999 const Eina_Model_Description *desc;
1001 eina_lock_take(&_eina_model_descriptions_lock);
1002 desc = _eina_model_description_get_internal(type);
1003 eina_lock_release(&_eina_model_descriptions_lock);
1009 _eina_model_description_dispose(const Eina_Model_Description *desc)
1011 eina_lock_take(&_eina_model_descriptions_lock);
1012 _eina_model_description_dispose_internal((Eina_Model_Description *)desc);
1013 eina_lock_release(&_eina_model_descriptions_lock);
1017 _eina_model_description_event_id_find(const Eina_Model_Description *desc, const char *event_name)
1019 const Eina_Model_Event_Description_Cache *cache;
1020 Eina_Model_Event_Description_Cache criteria_match;
1022 criteria_match.name = event_name;
1023 cache = bsearch(&criteria_match, desc->cache.events, desc->total.events,
1024 sizeof(Eina_Model_Event_Description_Cache),
1025 _eina_model_description_events_cmp);
1028 ERR("No event named %s for type %p (%s)", event_name,
1029 desc->cache.types[0], desc->cache.types[0]->name);
1033 return cache - desc->cache.events;
1037 * Model management and book keeping
1039 typedef struct _Eina_Model_Event_Listener Eina_Model_Event_Listener;
1040 struct _Eina_Model_Event_Listener
1043 Eina_Model_Event_Cb cb;
1045 Eina_Bool deleted:1;
1050 const Eina_Model_Description *desc; /**< optimized model description */
1052 Eina_Inlist **entries; /**< connected/listeners for each event, array of lists of Eina_Model_Event_Listener */
1053 Eina_List **deleted; /**< deleted listeners while was walking. array of lists of Eina_Model_Event_Listener with deleted flag */
1054 int *freeze; /**< freeze count for each event */
1055 int walking; /**< increased while walking entries lists */
1057 void **privates; /**< private data per type and interface, each level gets its own stuff */
1058 Eina_Inlist *xrefs; /**< if EINA_MODEL_DEBUG and eina_model_xref() is used */
1059 int refcount; /**< number of users of this model instance */
1060 Eina_Bool deleted:1; /**< if deleted but still have references */
1064 static inline Eina_Bool
1065 _eina_model_type_check(const Eina_Model_Type *type)
1067 EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE);
1068 EINA_SAFETY_ON_FALSE_RETURN_VAL(type->version == EINA_MODEL_TYPE_VERSION,
1073 /* find in type hierarchy the first one that the given offset is not a null
1074 * pointer. Use this to discover which method to call on a parent.
1077 _eina_model_type_find_offset(const Eina_Model_Type *type, unsigned int offset)
1079 const unsigned char *ptr = (const unsigned char *)type;
1080 const void **addr = (const void **)(ptr + offset);
1082 if (*addr) return *addr;
1083 if (!type->parent) return NULL;
1084 return _eina_model_type_find_offset(type->parent, offset);
1087 /* find in interface hierarchy the first one that the given offset is
1088 * not a null pointer. Use this to discover which method to call on a
1091 * TODO: Keep Eina_Model_Interface_Description with topological sorted
1092 * entries for each interface?
1093 * I smell problems with the current code in more complex
1099 * .---------+---------.
1101 * iface2 iface3 iface4
1104 * `---------+---------'
1108 * It should look: iface5 -> iface2 -> iface3 -> iface4 -> iface1
1109 * Now it does: iface5 -> iface2 -> iface1 -> iface3 -> iface1 -> iface4 -> iface1
1118 * .---------+---------.
1123 * `---------+---------'
1127 * It should look: iface5 -> iface3 -> iface4 -> iface2 -> iface1
1128 * Now it does: iface5 -> iface3 -> iface2 -> iface1 -> iface4 -> iface2 -> iface1
1134 * `---------+---------'
1138 * It should look: iface3 -> iface1 -> iface2
1139 * Now it does: iface3 -> iface1 -> iface2
1141 * For the common case it should work, let's see.
1144 _eina_model_interface_find_offset(const Eina_Model_Interface *iface, unsigned int offset)
1146 const Eina_Model_Interface **itr;
1147 const unsigned char *ptr = (const unsigned char *)iface;
1148 const void **addr = (const void **)(ptr + offset);
1150 if (offset + sizeof(void *) > iface->interface_size) return NULL;
1152 if (*addr) return *addr;
1153 if (!iface->interfaces) return NULL;
1155 for (itr = iface->interfaces; *itr != NULL; itr++)
1157 const void *r = _eina_model_interface_find_offset(*itr, offset);
1166 _eina_model_event_callback_free_deleted(Eina_Model *model)
1170 for (i = 0; i < model->desc->total.events; i++)
1172 Eina_Model_Event_Listener *el;
1173 EINA_LIST_FREE(model->listeners.deleted[i], el)
1175 model->listeners.entries[i] = eina_inlist_remove
1176 (model->listeners.entries[i], EINA_INLIST_GET(el));
1177 _eina_model_inner_free(sizeof(Eina_Model_Event_Listener), el);
1181 _eina_model_inner_free(model->desc->total.events * sizeof(Eina_List *),
1182 model->listeners.deleted);
1183 model->listeners.deleted = NULL;
1186 static inline Eina_Bool
1187 _eina_model_event_callback_call(Eina_Model *model, const char *name, const void *event_info)
1190 Eina_Model_Event_Listener *el;
1191 const Eina_Model_Event_Description *ev_desc;
1192 int event_id = _eina_model_description_event_id_find(model->desc, name);
1194 if (event_id < 0) return EINA_FALSE;
1195 if (!model->listeners.entries) return EINA_TRUE;
1197 if ((model->listeners.freeze) && (model->listeners.freeze[event_id]))
1199 DBG("Ignored event callback '%s' of model %p (%s): frozen",
1200 name, model, model->desc->cache.types[0]->name);
1204 lst = model->listeners.entries[event_id];
1205 if (!lst) return EINA_TRUE;
1207 ev_desc = model->desc->cache.events[event_id].desc;
1209 model->listeners.walking++;
1210 EINA_INLIST_FOREACH(lst, el)
1212 if (el->deleted) continue;
1213 el->cb((void *)el->data, model, ev_desc, (void *)event_info);
1215 model->listeners.walking--;
1217 if ((model->listeners.walking == 0) && (model->listeners.deleted))
1218 _eina_model_event_callback_free_deleted(model);
1223 static const char EINA_ERROR_MODEL_FAILED_STR[] = "Model check failed.";
1224 static const char EINA_ERROR_MODEL_METHOD_MISSING_STR[] = "Model method is missing.";
1225 static const char EINA_MAGIC_MODEL_STR[] = "Eina Model";
1227 static void _eina_model_unref(Eina_Model *model);
1233 /* EINA_MODEL_TYPE_BASE: base of all other types **********************/
1236 _eina_model_type_base_setup(Eina_Model *model)
1238 DBG("base setup of %p", model);
1243 _eina_model_type_base_flush(Eina_Model *model)
1245 DBG("base flush of %p", model);
1250 _eina_model_type_base_constructor(Eina_Model *model)
1252 DBG("base constructor of %p", model);
1257 _eina_model_type_base_destructor(Eina_Model *model)
1259 DBG("base destructor of %p", model);
1264 _eina_model_type_base_properties_copy(const Eina_Model *model, Eina_Model *copy)
1266 Eina_List *l, *props = eina_model_properties_names_list_get(model);
1268 EINA_LIST_FOREACH(props, l, name)
1271 if (!eina_model_property_get(model, name, &tmp))
1273 ERR("Could not get property %s from model %p (%s)",
1274 name, model, model->desc->cache.types[0]->name);
1275 eina_model_properties_names_list_free(props);
1278 if (!eina_model_property_set(copy, name, &tmp))
1280 ERR("Could not set property %s on model %p (%s)",
1281 name, copy, copy->desc->cache.types[0]->name);
1282 eina_value_flush(&tmp);
1283 eina_model_properties_names_list_free(props);
1286 eina_value_flush(&tmp);
1288 eina_model_properties_names_list_free(props);
1293 _eina_model_type_base_children_copy(const Eina_Model *model, Eina_Model *copy)
1295 int i, count = eina_model_child_count(model);
1299 ERR("Could not get children count of model %p (%s)",
1300 model, model->desc->cache.types[0]->name);
1304 for (i = 0; i < count; i++)
1306 Eina_Model *child = eina_model_child_get(model, i);
1311 ERR("Could not get child #%d from model %p (%s)",
1312 i, model, model->desc->cache.types[0]->name);
1316 ret = eina_model_child_insert_at(copy, i, child);
1317 _eina_model_unref(child);
1321 ERR("Could not set child #%d on model %p (%s)",
1322 i, copy, copy->desc->cache.types[0]->name);
1331 _eina_model_type_base_copy(const Eina_Model *model, Eina_Model *copy)
1333 DBG("base copy of %p to %p", model, copy);
1335 return _eina_model_type_base_properties_copy(model, copy) &&
1336 _eina_model_type_base_children_copy(model, copy);
1340 _eina_model_type_base_children_deep_copy(const Eina_Model *model, Eina_Model *copy)
1342 int i, count = eina_model_child_count(model);
1346 ERR("Could not get children count of model %p (%s)",
1347 model, model->desc->cache.types[0]->name);
1351 for (i = 0; i < count; i++)
1353 Eina_Model *child_copy, *child = eina_model_child_get(model, i);
1358 ERR("Could not get child #%d from model %p (%s)",
1359 i, model, model->desc->cache.types[0]->name);
1363 child_copy = eina_model_deep_copy(child);
1366 ERR("Could not deep copy child #%d %p (%s) from model %p (%s)", i,
1367 child, child->desc->cache.types[0]->name,
1368 model, model->desc->cache.types[0]->name);
1369 _eina_model_unref(child);
1372 _eina_model_unref(child);
1374 ret = eina_model_child_insert_at(copy, i, child_copy);
1375 _eina_model_unref(child_copy);
1379 ERR("Could not set child #%d on model %p (%s)",
1380 i, copy, copy->desc->cache.types[0]->name);
1389 _eina_model_type_base_deep_copy(const Eina_Model *model, Eina_Model *copy)
1391 DBG("base deep copy of %p to %p", model, copy);
1393 return _eina_model_type_base_properties_copy(model, copy) &&
1394 _eina_model_type_base_children_deep_copy(model, copy);
1398 _eina_model_type_base_properties_compare(const Eina_Model *a, const Eina_Model *b, int *cmp)
1400 Eina_List *al, *aprops = eina_model_properties_names_list_get(a);
1401 Eina_List *bl, *bprops = eina_model_properties_names_list_get(b);
1402 Eina_List *l, *props = NULL;
1403 const char *aname, *bname, *name;
1404 Eina_Bool ret = EINA_TRUE;
1406 EINA_LIST_FOREACH(aprops, al, aname)
1408 EINA_LIST_FOREACH(bprops, bl, bname)
1409 if (strcmp(aname, bname) == 0)
1411 props = eina_list_append(props, aname);
1417 EINA_LIST_FOREACH(props, l, name)
1419 Eina_Value atmp, btmp;
1421 if (!eina_model_property_get(a, name, &atmp))
1423 ERR("Could not get property %s from model %p (%s)",
1424 name, a, a->desc->cache.types[0]->name);
1430 if (!eina_model_property_get(b, name, &btmp))
1432 ERR("Could not get property %s from model %p (%s)",
1433 name, b, b->desc->cache.types[0]->name);
1436 eina_value_flush(&atmp);
1440 *cmp = eina_value_compare(&atmp, &btmp);
1441 if (eina_error_get() != 0)
1443 char *astr = eina_value_to_string(&atmp);
1444 char *bstr = eina_value_to_string(&btmp);
1445 ERR("Could not compare property %s: %s=%s, %s=%s", name,
1446 eina_value_type_name_get(eina_value_type_get(&atmp)), astr,
1447 eina_value_type_name_get(eina_value_type_get(&btmp)), bstr);
1454 eina_value_flush(&atmp);
1455 eina_value_flush(&btmp);
1457 if ((!ret) || (*cmp != 0))
1461 if ((ret) && (*cmp == 0))
1463 int acount = eina_list_count(aprops);
1464 int bcount = eina_list_count(bprops);
1466 if (acount < bcount)
1468 else if (acount > bcount)
1472 eina_model_properties_names_list_free(aprops);
1473 eina_model_properties_names_list_free(bprops);
1474 eina_list_free(props);
1479 _eina_model_type_base_children_compare(const Eina_Model *a, const Eina_Model *b, int *cmp)
1481 int acount = eina_model_child_count(a);
1482 int bcount = eina_model_child_count(b);
1484 Eina_Bool ret = EINA_TRUE;
1488 ERR("Could not get children count of model %p (%s)",
1489 a, a->desc->cache.types[0]->name);
1494 ERR("Could not get children count of model %p (%s)",
1495 b, b->desc->cache.types[0]->name);
1499 if (acount < bcount)
1504 for (i = 0; i < count; i++)
1506 Eina_Model *achild, *bchild;
1508 achild = eina_model_child_get(a, i);
1511 ERR("Could not get child #%d from model %p (%s)",
1512 i, a, a->desc->cache.types[0]->name);
1517 bchild = eina_model_child_get(b, i);
1520 ERR("Could not get child #%d from model %p (%s)",
1521 i, b, b->desc->cache.types[0]->name);
1523 _eina_model_unref(achild);
1527 *cmp = eina_model_compare(achild, bchild);
1528 if (eina_error_get())
1530 ERR("Could not compare children #%d %p (%s) and %p (%s) "
1531 "from models %p (%s) and %p (%s)", i,
1533 eina_model_type_name_get(eina_model_type_get(achild)),
1535 eina_model_type_name_get(eina_model_type_get(bchild)),
1536 a, a->desc->cache.types[0]->name,
1537 b, b->desc->cache.types[0]->name);
1540 _eina_model_unref(achild);
1541 _eina_model_unref(bchild);
1543 if ((!ret) || (*cmp != 0))
1547 if ((ret) && (*cmp == 0))
1549 if (acount < bcount)
1551 else if (acount > bcount)
1559 _eina_model_type_base_compare(const Eina_Model *a, const Eina_Model *b, int *cmp)
1562 DBG("base compare of %p and %p", a, b);
1564 if (!_eina_model_type_base_properties_compare(a, b, cmp))
1570 return _eina_model_type_base_children_compare(a, b, cmp);
1574 _eina_model_type_base_child_count(const Eina_Model *model)
1576 DBG("base child_count of %p", model);
1581 _eina_model_type_base_child_find(const Eina_Model *model, unsigned int start_position, const Eina_Model *other)
1583 int x = eina_model_child_count(model);
1584 unsigned int i, count;
1586 DBG("base child_find of %p, %d children", model, x);
1592 for (i = start_position; i < count; i++)
1594 Eina_Model *current = eina_model_child_get(model, i);
1597 _eina_model_unref(current); /* we'll not use it's value anyway */
1598 if (current == other)
1607 _eina_model_type_base_child_criteria_match(const Eina_Model *model, unsigned int start_position, Eina_Each_Cb match, const void *user_data)
1609 int x = eina_model_child_count(model);
1610 unsigned int i, count;
1612 DBG("base child_criteria_match of %p, %d children", model, x);
1618 for (i = start_position; i < count; i++)
1620 Eina_Model *current = eina_model_child_get(model, i);
1623 Eina_Bool r = match(model, current, (void *)user_data);
1624 _eina_model_unref(current);
1633 typedef struct _Eina_Iterator_Model_Base Eina_Iterator_Model_Base;
1634 struct _Eina_Iterator_Model_Base
1638 unsigned int current;
1643 _eina_model_type_base_child_iterator_next(Eina_Iterator *base, void **data)
1645 Eina_Iterator_Model_Base *it;
1647 it = (Eina_Iterator_Model_Base *)base;
1648 if (it->current >= it->end)
1651 *data = eina_model_child_get(it->model, it->current);
1660 _eina_model_type_base_child_iterator_get_container(Eina_Iterator *base)
1662 Eina_Iterator_Model_Base *it;
1663 it = (Eina_Iterator_Model_Base *)base;
1668 _eina_model_type_base_child_iterator_free(Eina_Iterator *base)
1670 Eina_Iterator_Model_Base *it;
1671 it = (Eina_Iterator_Model_Base *)base;
1672 eina_model_xunref(it->model, it);
1676 static Eina_Iterator *
1677 _eina_model_type_base_child_iterator_get(Eina_Model *model, unsigned int start, unsigned int count)
1679 Eina_Iterator_Model_Base *it = calloc(1, sizeof(*it));
1680 EINA_SAFETY_ON_NULL_RETURN_VAL(it, NULL);
1682 EINA_MAGIC_SET(&it->base, EINA_MAGIC_ITERATOR);
1683 it->base.version = EINA_ITERATOR_VERSION;
1684 it->base.next = _eina_model_type_base_child_iterator_next;
1685 it->base.get_container = _eina_model_type_base_child_iterator_get_container;
1686 it->base.free = _eina_model_type_base_child_iterator_free;
1688 it->model = eina_model_xref(model, it, "eina_model_child_slice_iterator_get");
1689 it->current = start;
1690 it->end = start + count;
1695 typedef struct _Eina_Iterator_Model_Base_Reversed Eina_Iterator_Model_Base_Reversed;
1696 struct _Eina_Iterator_Model_Base_Reversed
1700 unsigned int current;
1705 _eina_model_type_base_child_reversed_iterator_next(Eina_Iterator *base, void **data)
1707 Eina_Iterator_Model_Base_Reversed *it;
1709 it = (Eina_Iterator_Model_Base_Reversed *)base;
1710 if (it->current == it->end)
1714 *data = eina_model_child_get(it->model, it->current);
1722 _eina_model_type_base_child_reversed_iterator_get_container(Eina_Iterator *base)
1724 Eina_Iterator_Model_Base_Reversed *it;
1725 it = (Eina_Iterator_Model_Base_Reversed *)base;
1730 _eina_model_type_base_child_reversed_iterator_free(Eina_Iterator *base)
1732 Eina_Iterator_Model_Base_Reversed *it;
1733 it = (Eina_Iterator_Model_Base_Reversed *)base;
1734 eina_model_xunref(it->model, it);
1738 static Eina_Iterator *
1739 _eina_model_type_base_child_reversed_iterator_get(Eina_Model *model, unsigned int start, unsigned int count)
1741 Eina_Iterator_Model_Base_Reversed *it;
1744 children_count = eina_model_child_count(model);
1745 if (children_count < 0)
1748 if (start + count > (unsigned int)children_count)
1750 if (start >= (unsigned int)children_count)
1753 count = children_count - start;
1756 it = calloc(1, sizeof(*it));
1757 EINA_SAFETY_ON_NULL_RETURN_VAL(it, NULL);
1758 EINA_MAGIC_SET(&it->base, EINA_MAGIC_ITERATOR);
1759 it->base.version = EINA_ITERATOR_VERSION;
1760 it->base.next = _eina_model_type_base_child_reversed_iterator_next;
1761 it->base.get_container = _eina_model_type_base_child_reversed_iterator_get_container;
1762 it->base.free = _eina_model_type_base_child_reversed_iterator_free;
1764 it->model = eina_model_xref(model, it, "eina_model_child_slice_reversed_iterator_get");
1765 it->current = start + count;
1771 typedef struct _Eina_Iterator_Model_Base_Sorted Eina_Iterator_Model_Base_Sorted;
1772 struct _Eina_Iterator_Model_Base_Sorted
1776 unsigned int current;
1778 Eina_Model *elements[];
1782 _eina_model_type_base_child_sorted_iterator_next(Eina_Iterator *base, void **data)
1784 Eina_Iterator_Model_Base_Sorted *it;
1786 it = (Eina_Iterator_Model_Base_Sorted *)base;
1787 if (it->current == it->count)
1790 *data = eina_model_ref(it->elements[it->current]);
1796 _eina_model_type_base_child_sorted_iterator_get_container(Eina_Iterator *base)
1798 Eina_Iterator_Model_Base_Sorted *it;
1799 it = (Eina_Iterator_Model_Base_Sorted *)base;
1804 _eina_model_type_base_child_sorted_iterator_free(Eina_Iterator *base)
1806 Eina_Iterator_Model_Base_Sorted *it;
1808 it = (Eina_Iterator_Model_Base_Sorted *)base;
1809 eina_model_xunref(it->model, it);
1811 for (i = 0; i < it->count; i++)
1812 _eina_model_unref(it->elements[i]);
1817 static Eina_Iterator *
1818 _eina_model_type_base_child_sorted_iterator_get(Eina_Model *model, unsigned int start, unsigned int count, Eina_Compare_Cb compare)
1820 Eina_Iterator_Model_Base_Sorted *it;
1824 children_count = eina_model_child_count(model);
1825 if (children_count < 0)
1828 if (start + count > (unsigned int)children_count)
1830 if (start >= (unsigned int)children_count)
1833 count = children_count - start;
1836 it = calloc(1, sizeof(*it) + count * sizeof(Eina_Model *));
1837 EINA_SAFETY_ON_NULL_RETURN_VAL(it, NULL);
1838 EINA_MAGIC_SET(&it->base, EINA_MAGIC_ITERATOR);
1839 it->base.version = EINA_ITERATOR_VERSION;
1840 it->base.next = _eina_model_type_base_child_sorted_iterator_next;
1841 it->base.get_container = _eina_model_type_base_child_sorted_iterator_get_container;
1842 it->base.free = _eina_model_type_base_child_sorted_iterator_free;
1844 it->model = eina_model_xref(model, it, "eina_model_child_slice_sorted_iterator_get");
1848 for (i = 0; i < count; i++)
1850 it->elements[i] = eina_model_child_get(model, i + start);
1851 if (!it->elements[i])
1853 ERR("Failed to get child %u of model %p (%s)",
1854 i + start, model, model->desc->cache.types[0]->name);
1861 _eina_model_array_sort(it->elements, 0, count - 1, compare);
1866 typedef struct _Eina_Iterator_Model_Base_Filtered Eina_Iterator_Model_Base_Filtered;
1867 struct _Eina_Iterator_Model_Base_Filtered
1873 unsigned int current;
1878 _eina_model_type_base_child_filtered_iterator_next(Eina_Iterator *base, void **data)
1880 Eina_Iterator_Model_Base_Filtered *it;
1884 it = (Eina_Iterator_Model_Base_Filtered *)base;
1885 if (it->count == 0) return EINA_FALSE;
1887 i = eina_model_child_criteria_match(it->model, it->current, it->match, it->data);
1888 if (i < 0) return EINA_FALSE;
1890 it->current = i + 1;
1892 ret = (unsigned int *)data;
1898 _eina_model_type_base_child_filtered_iterator_get_container(Eina_Iterator *base)
1900 Eina_Iterator_Model_Base_Filtered *it;
1901 it = (Eina_Iterator_Model_Base_Filtered *)base;
1906 _eina_model_type_base_child_filtered_iterator_free(Eina_Iterator *base)
1908 Eina_Iterator_Model_Base_Filtered *it;
1909 it = (Eina_Iterator_Model_Base_Filtered *)base;
1910 eina_model_xunref(it->model, it);
1914 static Eina_Iterator *
1915 _eina_model_type_base_child_filtered_iterator_get(Eina_Model *model, unsigned int start, unsigned int count, Eina_Each_Cb match, const void *data)
1917 Eina_Iterator_Model_Base_Filtered *it = calloc(1, sizeof(*it));
1918 EINA_SAFETY_ON_NULL_RETURN_VAL(it, NULL);
1920 EINA_MAGIC_SET(&it->base, EINA_MAGIC_ITERATOR);
1921 it->base.version = EINA_ITERATOR_VERSION;
1922 it->base.next = _eina_model_type_base_child_filtered_iterator_next;
1923 it->base.get_container = _eina_model_type_base_child_filtered_iterator_get_container;
1924 it->base.free = _eina_model_type_base_child_filtered_iterator_free;
1926 it->model = eina_model_xref(model, it, "eina_model_child_slice_filtered_iterator_get");
1929 it->current = start;
1936 _eina_model_type_base_to_string(const Eina_Model *model)
1938 Eina_List *l, *props;
1945 str = eina_strbuf_new();
1946 EINA_SAFETY_ON_NULL_RETURN_VAL(str, NULL);
1948 eina_strbuf_append_printf(str, "%s({", model->desc->cache.types[0]->name);
1950 props = eina_model_properties_names_list_get(model);
1951 props = eina_list_sort(props, 0, EINA_COMPARE_CB(strcmp));
1954 EINA_LIST_FOREACH(props, l, name)
1959 eina_strbuf_append_printf(str, ", %s: ", name);
1962 eina_strbuf_append_printf(str, "%s: ", name);
1966 if (!eina_model_property_get(model, name, &val))
1967 eina_strbuf_append_char(str, '?');
1970 char *tmp = eina_value_to_string(&val);
1971 eina_strbuf_append(str, tmp ? tmp : "?");
1973 eina_value_flush(&val);
1976 eina_list_free(props);
1978 eina_strbuf_append(str, "}, [");
1980 count = eina_model_child_count(model);
1982 for (i = 0; i < count; i++)
1984 Eina_Model *c = eina_model_child_get(model, i);
1988 eina_strbuf_append(str, ", ?");
1991 eina_strbuf_append_char(str, '?');
1997 char *tmp = eina_model_to_string(c);
1999 eina_strbuf_append_printf(str, ", %s", tmp ? tmp : "?");
2002 eina_strbuf_append(str, tmp ? tmp : "?");
2006 _eina_model_unref(c);
2010 eina_strbuf_append(str, "])");
2012 ret = eina_strbuf_string_steal(str);
2013 eina_strbuf_free(str);
2018 static const Eina_Model_Event_Description _eina_model_type_base_events[] = {
2019 EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_deleted, "", "model was deleted"),
2020 EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_freed, "", "model memory was released"),
2021 EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_property_set, "s", "model data was set, data name given as event information."),
2022 EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_property_del, "s", "model data was deleted, data name given as event information."),
2023 EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_children_changed, "", "model children changed (deleted, inserted)."),
2024 EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_child_inserted, "u", "model child was inserted, child position is given."),
2025 EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_child_set, "u", "model child was set, child position is given."),
2026 EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_child_del, "u", "model child was deleted, child position is given."),
2027 EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_loaded, "", "model was loaded"),
2028 EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_unloaded, "", "model was unloaded"),
2029 EINA_MODEL_EVENT_DESCRIPTION_SENTINEL
2032 static const Eina_Model_Type _EINA_MODEL_TYPE_BASE = {
2033 EINA_MODEL_TYPE_VERSION,
2034 0, /* there is no private data */
2035 sizeof(Eina_Model_Type),
2036 "Eina_Model_Type_Base",
2037 NULL, /* should be the only type with NULL here! */
2038 NULL, /* no interfaces implemented */
2039 _eina_model_type_base_events,
2040 _eina_model_type_base_setup,
2041 _eina_model_type_base_flush,
2042 _eina_model_type_base_constructor,
2043 _eina_model_type_base_destructor,
2044 _eina_model_type_base_copy,
2045 _eina_model_type_base_deep_copy,
2046 _eina_model_type_base_compare,
2048 NULL, /* no unload */
2049 NULL, /* no property value get */
2050 NULL, /* no property value set */
2051 NULL, /* no property del */
2052 NULL, /* no properties names list */
2053 _eina_model_type_base_child_count,
2054 NULL, /* no child get */
2055 NULL, /* no child set */
2056 NULL, /* no child del */
2057 NULL, /* no child insert */
2058 _eina_model_type_base_child_find,
2059 _eina_model_type_base_child_criteria_match,
2060 NULL, /* no child sort */
2061 _eina_model_type_base_child_iterator_get,
2062 _eina_model_type_base_child_reversed_iterator_get,
2063 _eina_model_type_base_child_sorted_iterator_get,
2064 _eina_model_type_base_child_filtered_iterator_get,
2065 _eina_model_type_base_to_string,
2066 NULL, /* extension pointer */
2067 NULL, /* extension pointer */
2068 NULL, /* extension pointer */
2069 NULL /* extension pointer */
2073 * EINA_MODEL_TYPE_MIXIN:
2075 * Mix-in is a type that uses 2 interfaces, one for properties,
2076 * another for children. Users should inherit this model and implement
2077 * at least onf of the interfaces to get an usable model without
2078 * defining the methods.
2081 static const char _EINA_MODEL_INTERFACE_NAME_PROPERTIES[] = "Eina_Model_Interface_Properties";
2082 static const char _EINA_MODEL_INTERFACE_NAME_CHILDREN[] = "Eina_Model_Interface_Children";
2084 typedef struct _Eina_Model_Type_Mixin_Data Eina_Model_Type_Mixin_Data;
2085 struct _Eina_Model_Type_Mixin_Data
2087 /* just keep interfaces to avoid lookups */
2088 const Eina_Model_Interface *if_properties;
2089 const Eina_Model_Interface *if_children;
2093 _eina_model_type_mixin_setup(Eina_Model *model)
2095 DBG("mix-in setup of %p", model);
2100 _eina_model_type_mixin_flush(Eina_Model *model)
2102 DBG("mix-in flush of %p", model);
2107 _eina_model_type_mixin_constructor(Eina_Model *model)
2109 Eina_Model_Type_Mixin_Data *priv = eina_model_type_private_data_get
2110 (model, EINA_MODEL_TYPE_MIXIN);
2112 DBG("mix-in constructor of %p (priv=%p)", model, priv);
2114 priv->if_properties = eina_model_interface_get
2115 (model, EINA_MODEL_INTERFACE_NAME_PROPERTIES);
2116 if (priv->if_properties)
2118 if (!eina_model_interface_constructor(priv->if_properties, model))
2120 ERR("Could not construct properties interface %p of %p (%s)",
2121 model, priv->if_properties, model->desc->cache.types[0]->name);
2126 priv->if_children = eina_model_interface_get
2127 (model, EINA_MODEL_INTERFACE_NAME_CHILDREN);
2128 if (priv->if_children)
2130 if (!eina_model_interface_constructor(priv->if_children, model))
2132 ERR("Could not construct children interface %p of %p (%s)",
2133 model, priv->if_children, model->desc->cache.types[0]->name);
2138 if ((!priv->if_properties) && (!priv->if_children))
2140 ERR("Mix-in model %p (%s) does not implement properties or children "
2142 model, model->desc->cache.types[0]->name);
2149 #define EINA_MODEL_TYPE_MIXIN_GET(model) \
2150 Eina_Model_Type_Mixin_Data *priv = eina_model_type_private_data_get \
2151 (model, EINA_MODEL_TYPE_MIXIN)
2154 _eina_model_type_mixin_destructor(Eina_Model *model)
2156 EINA_MODEL_TYPE_MIXIN_GET(model);
2158 DBG("mixin destructor of %p", model);
2160 if (priv->if_properties)
2161 eina_model_interface_destructor(priv->if_properties, model);
2163 if (priv->if_children)
2164 eina_model_interface_destructor(priv->if_children, model);
2170 _eina_model_type_mixin_compare(const Eina_Model *a, const Eina_Model *b, int *cmp)
2172 Eina_Bool ret = EINA_TRUE, did_prop = EINA_FALSE, did_child = EINA_FALSE;
2176 EINA_MODEL_TYPE_MIXIN_GET(a);
2178 if (priv->if_properties)
2180 Eina_Bool (*compare)(const Eina_Model*, const Eina_Model*, int *) =
2181 _eina_model_interface_find_offset
2182 (priv->if_properties,
2183 offsetof(Eina_Model_Interface_Properties, compare));
2187 ret &= compare(a, b, cmp);
2188 did_prop = EINA_TRUE;
2192 if ((ret) && (*cmp == 0))
2194 if (priv->if_children)
2196 Eina_Bool (*compare)(const Eina_Model*, const Eina_Model*, int *) =
2197 _eina_model_interface_find_offset
2199 offsetof(Eina_Model_Interface_Children, compare));
2203 ret &= compare(a, b, cmp);
2204 did_child = EINA_TRUE;
2209 if ((!did_prop) && (!did_child))
2210 return eina_model_type_compare(EINA_MODEL_TYPE_BASE, a, b, cmp);
2216 _eina_model_type_mixin_load(Eina_Model *model)
2218 Eina_Bool ret = EINA_TRUE;
2220 EINA_MODEL_TYPE_MIXIN_GET(model);
2222 if (priv->if_properties)
2223 ret &= eina_model_interface_properties_load(priv->if_properties, model);
2225 if (priv->if_children)
2226 ret &= eina_model_interface_children_load(priv->if_children, model);
2232 _eina_model_type_mixin_unload(Eina_Model *model)
2234 Eina_Bool ret = EINA_TRUE;
2236 EINA_MODEL_TYPE_MIXIN_GET(model);
2238 if (priv->if_properties)
2239 ret &= eina_model_interface_properties_unload(priv->if_properties, model);
2241 if (priv->if_children)
2242 ret &= eina_model_interface_children_unload(priv->if_children, model);
2248 _eina_model_type_mixin_property_get(const Eina_Model *model, const char *name, Eina_Value *value)
2250 Eina_Bool ret = EINA_FALSE;
2252 EINA_MODEL_TYPE_MIXIN_GET(model);
2254 if (priv->if_properties)
2255 ret = eina_model_interface_properties_get
2256 (priv->if_properties, model, name, value);
2262 _eina_model_type_mixin_property_set(Eina_Model *model, const char *name, const Eina_Value *value)
2264 Eina_Bool ret = EINA_FALSE;
2266 EINA_MODEL_TYPE_MIXIN_GET(model);
2268 if (priv->if_properties)
2269 ret = eina_model_interface_properties_set
2270 (priv->if_properties, model, name, value);
2276 _eina_model_type_mixin_property_del(Eina_Model *model, const char *name)
2278 Eina_Bool ret = EINA_FALSE;
2280 EINA_MODEL_TYPE_MIXIN_GET(model);
2282 if (priv->if_properties)
2283 ret = eina_model_interface_properties_del
2284 (priv->if_properties, model, name);
2290 _eina_model_type_mixin_properties_names_list_get(const Eina_Model *model)
2292 Eina_List *ret = NULL;
2294 EINA_MODEL_TYPE_MIXIN_GET(model);
2296 if (priv->if_properties)
2297 ret = eina_model_interface_properties_names_list_get
2298 (priv->if_properties, model);
2304 _eina_model_type_mixin_child_count(const Eina_Model *model)
2306 EINA_MODEL_TYPE_MIXIN_GET(model);
2308 if (!priv->if_children)
2311 return eina_model_interface_children_count(priv->if_children, model);
2315 _eina_model_type_mixin_child_get(const Eina_Model *model, unsigned int position)
2317 EINA_MODEL_TYPE_MIXIN_GET(model);
2319 if (!priv->if_children)
2322 return eina_model_interface_children_get(priv->if_children, model, position);
2326 _eina_model_type_mixin_child_set(Eina_Model *model, unsigned int position, Eina_Model *child)
2328 EINA_MODEL_TYPE_MIXIN_GET(model);
2330 if (!priv->if_children)
2333 return eina_model_interface_children_set
2334 (priv->if_children, model, position, child);
2338 _eina_model_type_mixin_child_del(Eina_Model *model, unsigned int position)
2340 EINA_MODEL_TYPE_MIXIN_GET(model);
2342 if (!priv->if_children)
2345 return eina_model_interface_children_del
2346 (priv->if_children, model, position);
2350 _eina_model_type_mixin_child_insert_at(Eina_Model *model, unsigned int position, Eina_Model *child)
2352 EINA_MODEL_TYPE_MIXIN_GET(model);
2354 if (!priv->if_children)
2357 return eina_model_interface_children_insert_at
2358 (priv->if_children, model, position, child);
2362 _eina_model_type_mixin_child_sort(Eina_Model *model, Eina_Compare_Cb compare)
2364 EINA_MODEL_TYPE_MIXIN_GET(model);
2366 if (!priv->if_children)
2368 eina_model_interface_children_sort(priv->if_children, model, compare);
2371 static const Eina_Model_Type _EINA_MODEL_TYPE_MIXIN = {
2372 EINA_MODEL_TYPE_VERSION,
2373 sizeof(Eina_Model_Type_Mixin_Data),
2374 sizeof(Eina_Model_Type),
2375 "Eina_Model_Type_Mixin",
2376 &_EINA_MODEL_TYPE_BASE,
2377 NULL, /* no interfaces implemented */
2378 NULL, /* no extra events */
2379 _eina_model_type_mixin_setup,
2380 _eina_model_type_mixin_flush,
2381 _eina_model_type_mixin_constructor,
2382 _eina_model_type_mixin_destructor,
2383 NULL, /* no copy, as interface is called automatically */
2384 NULL, /* no deep copy, as interface is called automatically */
2385 _eina_model_type_mixin_compare,
2386 _eina_model_type_mixin_load,
2387 _eina_model_type_mixin_unload,
2388 _eina_model_type_mixin_property_get,
2389 _eina_model_type_mixin_property_set,
2390 _eina_model_type_mixin_property_del,
2391 _eina_model_type_mixin_properties_names_list_get,
2392 _eina_model_type_mixin_child_count,
2393 _eina_model_type_mixin_child_get,
2394 _eina_model_type_mixin_child_set,
2395 _eina_model_type_mixin_child_del,
2396 _eina_model_type_mixin_child_insert_at,
2397 NULL, /* use default find */
2398 NULL, /* use default criteria_match */
2399 _eina_model_type_mixin_child_sort,
2400 NULL, /* use default iterator get */
2401 NULL, /* use default reversed iterator get */
2402 NULL, /* use default sorted iterator get */
2403 NULL, /* use default filtered iterator get */
2404 NULL, /* use default to string */
2405 NULL, /* extension pointer */
2406 NULL, /* extension pointer */
2407 NULL, /* extension pointer */
2408 NULL /* extension pointer */
2410 #undef EINA_MODEL_TYPE_MIXIN_GET
2412 /* Events for all Properties interface */
2413 static const Eina_Model_Event_Description _eina_model_interface_properties_events[] = {
2414 EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_properties_loaded, "", "model properties were loaded"),
2415 EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_properties_unloaded, "", "model properties were unloaded"),
2416 EINA_MODEL_EVENT_DESCRIPTION_SENTINEL
2419 /* EINA_MODEL_INTERFACE_PROPERTIES_HASH ******************************/
2421 #define EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET(model) \
2422 Eina_Hash *priv = *(Eina_Hash **)eina_model_interface_private_data_get \
2423 (model, EINA_MODEL_INTERFACE_PROPERTIES_HASH)
2426 _eina_model_interface_properties_hash_setup(Eina_Model *model)
2428 Eina_Hash **p_priv = eina_model_interface_private_data_get
2429 (model, EINA_MODEL_INTERFACE_PROPERTIES_HASH);
2431 DBG("setup interface properties (hash) at %p model %p (%s)",
2432 p_priv, model, model->desc->cache.types[0]->name);
2434 *p_priv = eina_hash_string_small_new(NULL);
2439 _eina_model_interface_properties_hash_flush(Eina_Model *model)
2441 EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET(model);
2443 DBG("flush interface properties (hash) at %p model %p (%s)",
2444 priv, model, model->desc->cache.types[0]->name);
2448 ERR("interface properties flushed with values! priv=%p, model %p (%s)",
2449 priv, model, model->desc->cache.types[0]->name);
2450 eina_hash_free(priv);
2457 _eina_model_interface_properties_hash_constructor(Eina_Model *model)
2459 EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET(model);
2461 DBG("construct interface properties (hash) at %p model %p (%s)",
2462 priv, model, model->desc->cache.types[0]->name);
2468 _eina_model_interface_properties_hash_destructor_foreach(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
2470 eina_value_free(data);
2475 _eina_model_interface_properties_hash_destructor(Eina_Model *model)
2477 Eina_Hash **p_priv = eina_model_interface_private_data_get
2478 (model, EINA_MODEL_INTERFACE_PROPERTIES_HASH);
2479 int count = eina_hash_population(*p_priv);
2481 DBG("destroy interface properties (hash) at %p model %p (%s). %d values.",
2482 *p_priv, model, model->desc->cache.types[0]->name, count);
2485 (*p_priv, _eina_model_interface_properties_hash_destructor_foreach, NULL);
2486 eina_hash_free(*p_priv);
2493 _eina_model_interface_properties_hash_get(const Eina_Model *model, const char *name, Eina_Value *value)
2495 EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET(model);
2496 const Eina_Value *prop = eina_hash_find(priv, name);
2497 EINA_SAFETY_ON_NULL_RETURN_VAL(prop, EINA_FALSE);
2498 return eina_value_copy(prop, value);
2502 _eina_model_interface_properties_hash_set(Eina_Model *model, const char *name, const Eina_Value *value)
2504 EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET(model);
2505 Eina_Value *prop, *old = eina_hash_find(priv, name);
2507 prop = eina_value_new(eina_value_type_get(value));
2508 EINA_SAFETY_ON_NULL_RETURN_VAL(prop, EINA_FALSE);
2510 eina_value_flush(prop);
2511 if (!eina_value_copy(value, prop))
2513 ERR("Could not copy value '%s' from %p to %p", name, value, prop);
2514 eina_value_free(prop);
2520 if (!eina_hash_add(priv, name, prop))
2522 ERR("Could not add value %p to hash as key '%s'", prop, name);
2523 eina_value_free(prop);
2529 eina_value_free(old);
2530 if (!eina_hash_modify(priv, name, prop))
2532 ERR("Could not modify hash key '%s' value from %p to %p",
2534 eina_hash_del_by_key(priv, name);
2535 eina_value_free(prop);
2544 _eina_model_interface_properties_hash_del(Eina_Model *model, const char *name)
2546 EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET(model);
2547 Eina_Value *old = eina_hash_find(priv, name);
2548 EINA_SAFETY_ON_NULL_RETURN_VAL(old, EINA_FALSE);
2549 eina_value_free(old);
2550 return eina_hash_del_by_key(priv, name);
2554 _eina_model_interface_properties_hash_names_list_foreach(const Eina_Hash *hash __UNUSED__, const void *key, void *data __UNUSED__, void *fdata)
2556 Eina_List **p_list = fdata;
2557 *p_list = eina_list_append(*p_list, eina_stringshare_add(key));
2562 _eina_model_interface_properties_hash_names_list(const Eina_Model *model)
2564 EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET(model);
2565 Eina_List *list = NULL;
2567 (priv, _eina_model_interface_properties_hash_names_list_foreach, &list);
2570 #undef EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET
2572 static const Eina_Model_Interface_Properties _EINA_MODEL_INTERFACE_PROPERTIES_HASH = {
2574 EINA_MODEL_INTERFACE_VERSION,
2575 sizeof(Eina_Hash *),
2576 sizeof(Eina_Model_Interface_Properties),
2577 _EINA_MODEL_INTERFACE_NAME_PROPERTIES,
2578 NULL, /* no parent interfaces */
2579 _eina_model_interface_properties_events,
2580 _eina_model_interface_properties_hash_setup,
2581 _eina_model_interface_properties_hash_flush,
2582 _eina_model_interface_properties_hash_constructor,
2583 _eina_model_interface_properties_hash_destructor,
2591 EINA_MODEL_INTERFACE_PROPERTIES_VERSION,
2592 NULL, /* no compare */
2594 NULL, /* no unload */
2595 _eina_model_interface_properties_hash_get,
2596 _eina_model_interface_properties_hash_set,
2597 _eina_model_interface_properties_hash_del,
2598 _eina_model_interface_properties_hash_names_list
2601 /* EINA_MODEL_INTERFACE_PROPERTIES_STRUCT ******************************/
2603 static Eina_Value_Struct *
2604 _eina_model_interface_properties_struct_private_get(const Eina_Model *model)
2606 Eina_Value *val = eina_model_interface_private_data_get
2607 (model, EINA_MODEL_INTERFACE_PROPERTIES_STRUCT);
2608 return eina_value_memory_get(val);
2611 #define EINA_MODEL_INTERFACE_PROPERTIES_STRUCT_GET(model) \
2612 Eina_Value_Struct *priv = \
2613 _eina_model_interface_properties_struct_private_get(model)
2616 _eina_model_interface_properties_struct_setup(Eina_Model *model)
2618 Eina_Value *val = eina_model_interface_private_data_get
2619 (model, EINA_MODEL_INTERFACE_PROPERTIES_STRUCT);
2621 DBG("setup interface properties (struct) at %p model %p (%s)",
2622 val, model, model->desc->cache.types[0]->name);
2624 return eina_value_setup(val, EINA_VALUE_TYPE_STRUCT);
2628 _eina_model_interface_properties_struct_flush(Eina_Model *model)
2630 Eina_Value *val = eina_model_interface_private_data_get
2631 (model, EINA_MODEL_INTERFACE_PROPERTIES_STRUCT);
2633 DBG("flush interface properties (struct) at %p model %p (%s)",
2634 val, model, model->desc->cache.types[0]->name);
2638 ERR("interface properties flushed with values! val=%p, model %p (%s)",
2639 val, model, model->desc->cache.types[0]->name);
2640 eina_value_flush(val);
2647 _eina_model_interface_properties_struct_constructor(Eina_Model *model)
2649 EINA_MODEL_INTERFACE_PROPERTIES_STRUCT_GET(model);
2651 DBG("construct interface properties (struct) at %p model %p (%s)",
2652 priv, model, model->desc->cache.types[0]->name);
2658 _eina_model_interface_properties_struct_destructor(Eina_Model *model)
2660 Eina_Value *val = eina_model_interface_private_data_get
2661 (model, EINA_MODEL_INTERFACE_PROPERTIES_STRUCT);
2663 DBG("destroy interface properties (struct) at %p model %p (%s)",
2664 val, model, model->desc->cache.types[0]->name);
2666 eina_value_flush(val);
2673 _eina_model_interface_properties_struct_get(const Eina_Model *model, const char *name, Eina_Value *val)
2675 const Eina_Value *v = eina_model_interface_private_data_get
2676 (model, EINA_MODEL_INTERFACE_PROPERTIES_STRUCT);
2677 return eina_value_struct_value_get(v, name, val);
2681 _eina_model_interface_properties_struct_set(Eina_Model *model, const char *name, const Eina_Value *val)
2683 Eina_Value *v = eina_model_interface_private_data_get
2684 (model, EINA_MODEL_INTERFACE_PROPERTIES_STRUCT);
2685 return eina_value_struct_value_set(v, name, val);
2689 _eina_model_interface_properties_struct_del(Eina_Model *model __UNUSED__, const char *name __UNUSED__)
2691 return EINA_FALSE; /* not allowed */
2695 _eina_model_interface_properties_struct_names_list(const Eina_Model *model)
2697 EINA_MODEL_INTERFACE_PROPERTIES_STRUCT_GET(model);
2698 const Eina_Value_Struct_Member *itr;
2699 Eina_List *list = NULL;
2701 EINA_SAFETY_ON_NULL_RETURN_VAL(priv, NULL);
2702 EINA_SAFETY_ON_NULL_RETURN_VAL(priv->desc, NULL);
2703 EINA_SAFETY_ON_NULL_RETURN_VAL(priv->desc->members, NULL);
2705 itr = priv->desc->members;
2706 if (priv->desc->member_count)
2708 const Eina_Value_Struct_Member *end = itr + priv->desc->member_count;
2709 for (; itr < end; itr++)
2710 list = eina_list_append(list, eina_stringshare_add(itr->name));
2714 for (; itr->name != NULL; itr++)
2715 list = eina_list_append(list, eina_stringshare_add(itr->name));
2720 #undef EINA_MODEL_INTERFACE_PROPERTIES_STRUCT_GET
2722 static const Eina_Model_Interface_Properties _EINA_MODEL_INTERFACE_PROPERTIES_STRUCT = {
2724 EINA_MODEL_INTERFACE_VERSION,
2726 sizeof(Eina_Model_Interface_Properties),
2727 _EINA_MODEL_INTERFACE_NAME_PROPERTIES,
2728 NULL, /* no parent interfaces */
2729 _eina_model_interface_properties_events,
2730 _eina_model_interface_properties_struct_setup,
2731 _eina_model_interface_properties_struct_flush,
2732 _eina_model_interface_properties_struct_constructor,
2733 _eina_model_interface_properties_struct_destructor,
2741 EINA_MODEL_INTERFACE_PROPERTIES_VERSION,
2742 NULL, /* no compare */
2744 NULL, /* no unload */
2745 _eina_model_interface_properties_struct_get,
2746 _eina_model_interface_properties_struct_set,
2747 _eina_model_interface_properties_struct_del,
2748 _eina_model_interface_properties_struct_names_list
2751 /* Events for all Children interface */
2752 static const Eina_Model_Event_Description _eina_model_interface_children_events[] = {
2753 EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_children_loaded, "", "model children were loaded"),
2754 EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_children_unloaded, "", "model children were unloaded"),
2755 EINA_MODEL_EVENT_DESCRIPTION_SENTINEL
2758 /* EINA_MODEL_INTERFACE_CHILDREN_INARRAY ******************************/
2760 #define EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model) \
2761 Eina_Inarray *priv = eina_model_interface_private_data_get \
2762 (model, EINA_MODEL_INTERFACE_CHILDREN_INARRAY)
2765 _eina_model_interface_children_inarray_setup(Eina_Model *model)
2767 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2769 DBG("setup interface children (inarray) at %p model %p (%s)",
2770 priv, model, model->desc->cache.types[0]->name);
2772 eina_inarray_step_set(priv, sizeof(Eina_Inarray), sizeof(Eina_Model *), 0);
2777 _eina_model_interface_children_inarray_flush(Eina_Model *model)
2779 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2782 DBG("flush interface children (inarray) at %p model %p (%s)",
2783 priv, model, model->desc->cache.types[0]->name);
2785 count = eina_inarray_count(priv);
2787 ERR("interface children flushed with %d members! priv=%p, model %p (%s)",
2788 count, priv, model, model->desc->cache.types[0]->name);
2790 eina_inarray_flush(priv);
2795 _eina_model_interface_children_inarray_constructor(Eina_Model *model)
2797 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2799 DBG("construct interface children (inarray) at %p model %p (%s)",
2800 priv, model, model->desc->cache.types[0]->name);
2806 _eina_model_interface_children_inarray_destructor(Eina_Model *model)
2808 Eina_Model **itr, **itr_end;
2811 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2813 count = eina_inarray_count(priv);
2815 DBG("destroy interface children (inarray) at %p model %p (%s). %d members.",
2816 priv, model, model->desc->cache.types[0]->name, count);
2818 itr = priv->members;
2819 itr_end = itr + count;
2820 for (; itr < itr_end; itr++)
2821 eina_model_xunref(*itr, EINA_MODEL_INTERFACE_CHILDREN_INARRAY);
2822 eina_inarray_flush(priv);
2828 _eina_model_interface_children_inarray_count(const Eina_Model *model)
2830 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2831 return eina_inarray_count(priv);
2835 _eina_model_interface_children_inarray_get(const Eina_Model *model, unsigned int position)
2837 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2838 Eina_Model **child = eina_inarray_nth(priv, position);
2841 return eina_model_ref(*child);
2845 _eina_model_interface_children_inarray_set(Eina_Model *model, unsigned int position, Eina_Model *child)
2847 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2848 Eina_Model **p_old = eina_inarray_nth(priv, position);
2855 if (!eina_inarray_replace_at(priv, position, &child))
2858 eina_model_xref(child, EINA_MODEL_INTERFACE_CHILDREN_INARRAY,
2859 "eina_model_child_set");
2860 eina_model_xunref(old, EINA_MODEL_INTERFACE_CHILDREN_INARRAY);
2865 _eina_model_interface_children_inarray_del(Eina_Model *model, unsigned int position)
2867 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2868 Eina_Model **p_old = eina_inarray_nth(priv, position);
2875 if (!eina_inarray_remove_at(priv, position))
2878 eina_model_xunref(old, EINA_MODEL_INTERFACE_CHILDREN_INARRAY);
2883 _eina_model_interface_children_inarray_insert_at(Eina_Model *model, unsigned int position, Eina_Model *child)
2885 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2887 if (!eina_inarray_insert_at(priv, position, &child))
2890 eina_model_xref(child, EINA_MODEL_INTERFACE_CHILDREN_INARRAY,
2891 "eina_model_child_insert_at");
2896 _eina_model_interface_children_inarray_sort(Eina_Model *model, Eina_Compare_Cb compare)
2898 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2899 int count = eina_inarray_count(priv);
2900 EINA_SAFETY_ON_FALSE_RETURN(count >= 0);
2903 _eina_model_array_sort(priv->members, 0, count - 1, compare);
2905 #undef EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET
2907 static const Eina_Model_Interface_Children _EINA_MODEL_INTERFACE_CHILDREN_INARRAY = {
2909 EINA_MODEL_INTERFACE_VERSION,
2910 sizeof(Eina_Inarray),
2911 sizeof(Eina_Model_Interface_Children),
2912 _EINA_MODEL_INTERFACE_NAME_CHILDREN,
2913 NULL, /* no parent interfaces */
2914 _eina_model_interface_children_events,
2915 _eina_model_interface_children_inarray_setup,
2916 _eina_model_interface_children_inarray_flush,
2917 _eina_model_interface_children_inarray_constructor,
2918 _eina_model_interface_children_inarray_destructor,
2926 EINA_MODEL_INTERFACE_CHILDREN_VERSION,
2927 NULL, /* no compare */
2929 NULL, /* no unload */
2930 _eina_model_interface_children_inarray_count,
2931 _eina_model_interface_children_inarray_get,
2932 _eina_model_interface_children_inarray_set,
2933 _eina_model_interface_children_inarray_del,
2934 _eina_model_interface_children_inarray_insert_at,
2935 _eina_model_interface_children_inarray_sort
2938 /* EINA_MODEL_TYPE_GENERIC ********************************************/
2940 static const Eina_Model_Interface *_EINA_MODEL_TYPE_GENERIC_IFACES[] = {
2941 &_EINA_MODEL_INTERFACE_PROPERTIES_HASH.base,
2942 &_EINA_MODEL_INTERFACE_CHILDREN_INARRAY.base,
2946 static const Eina_Model_Type _EINA_MODEL_TYPE_GENERIC =
2947 EINA_MODEL_TYPE_INIT_NOPRIVATE("Eina_Model_Type_Generic",
2949 &_EINA_MODEL_TYPE_MIXIN,
2950 _EINA_MODEL_TYPE_GENERIC_IFACES,
2953 /* EINA_MODEL_TYPE_STRUCT ********************************************/
2955 static const Eina_Model_Interface *_EINA_MODEL_TYPE_STRUCT_IFACES[] = {
2956 &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base,
2957 &_EINA_MODEL_INTERFACE_CHILDREN_INARRAY.base,
2961 static const Eina_Model_Type _EINA_MODEL_TYPE_STRUCT =
2962 EINA_MODEL_TYPE_INIT_NOPRIVATE("Eina_Model_Type_Struct",
2964 &_EINA_MODEL_TYPE_MIXIN,
2965 _EINA_MODEL_TYPE_STRUCT_IFACES,
2973 * @brief Initialize the model module.
2975 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2977 * This function sets up the model module of Eina. It is called
2983 eina_model_init(void)
2985 const char *choice, *tmp;
2987 _eina_model_log_dom = eina_log_domain_register("eina_model",
2988 EINA_LOG_COLOR_DEFAULT);
2989 if (_eina_model_log_dom < 0)
2991 EINA_LOG_ERR("Could not register log domain: eina_model");
2995 choice = getenv("EINA_MODEL_DEBUG");
2998 if (strcmp(choice, "1") == 0)
2999 _eina_model_debug = EINA_MODEL_DEBUG_CHECK;
3000 else if (strcmp(choice, "backtrace") == 0)
3001 _eina_model_debug = EINA_MODEL_DEBUG_BACKTRACE;
3004 #ifdef EINA_DEFAULT_MEMPOOL
3005 choice = "pass_through";
3007 choice = "chained_mempool";
3009 tmp = getenv("EINA_MEMPOOL");
3014 _eina_model_mp_choice = strdup(choice);
3016 _eina_model_mp = eina_mempool_add
3017 (_eina_model_mp_choice, "model", NULL, sizeof(Eina_Model), 32);
3018 if (!_eina_model_mp)
3020 ERR("Mempool for model cannot be allocated in model init.");
3021 goto on_init_fail_mp;
3024 if (!eina_lock_new(&_eina_model_inner_mps_lock))
3026 ERR("Cannot create inner mempools lock in model init.");
3027 goto on_init_fail_lock_mp;
3029 _eina_model_inner_mps = eina_hash_int32_new(NULL);
3030 if (!_eina_model_inner_mps)
3032 ERR("Cannot create hash for inner mempools in model init.");
3033 goto on_init_fail_hash_mp;
3036 if (!eina_lock_new(&_eina_model_descriptions_lock))
3038 ERR("Cannot create model descriptions lock in model init.");
3039 goto on_init_fail_lock_desc;
3041 _eina_model_descriptions = eina_hash_pointer_new(NULL);
3042 if (!_eina_model_descriptions)
3044 ERR("Cannot create model descriptions hash in model init.");
3045 goto on_init_fail_hash_desc;
3048 if (!eina_lock_new(&_eina_model_debug_list_lock))
3050 ERR("Cannot create model debug list lock in model init.");
3051 goto on_init_fail_lock_debug;
3054 EINA_ERROR_MODEL_FAILED = eina_error_msg_static_register(
3055 EINA_ERROR_MODEL_FAILED_STR);
3056 EINA_ERROR_MODEL_METHOD_MISSING = eina_error_msg_static_register(
3057 EINA_ERROR_MODEL_METHOD_MISSING_STR);
3059 EINA_MODEL_TYPE_BASE = &_EINA_MODEL_TYPE_BASE;
3060 EINA_MODEL_TYPE_MIXIN = &_EINA_MODEL_TYPE_MIXIN;
3061 EINA_MODEL_TYPE_GENERIC = &_EINA_MODEL_TYPE_GENERIC;
3062 EINA_MODEL_TYPE_STRUCT = &_EINA_MODEL_TYPE_STRUCT;
3064 EINA_MODEL_INTERFACE_PROPERTIES_HASH = &_EINA_MODEL_INTERFACE_PROPERTIES_HASH.base;
3065 EINA_MODEL_INTERFACE_PROPERTIES_STRUCT = &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base;
3067 EINA_MODEL_INTERFACE_CHILDREN_INARRAY = &_EINA_MODEL_INTERFACE_CHILDREN_INARRAY.base;
3069 EINA_MODEL_INTERFACE_NAME_PROPERTIES = _EINA_MODEL_INTERFACE_NAME_PROPERTIES;
3070 EINA_MODEL_INTERFACE_NAME_CHILDREN = _EINA_MODEL_INTERFACE_NAME_CHILDREN;
3072 eina_magic_string_static_set(EINA_MAGIC_MODEL, EINA_MAGIC_MODEL_STR);
3076 on_init_fail_lock_debug:
3077 eina_hash_free(_eina_model_descriptions);
3078 on_init_fail_hash_desc:
3079 eina_lock_free(&_eina_model_descriptions_lock);
3080 on_init_fail_lock_desc:
3081 eina_hash_free(_eina_model_inner_mps);
3082 _eina_model_inner_mps = NULL;
3083 on_init_fail_hash_mp:
3084 eina_lock_free(&_eina_model_inner_mps_lock);
3085 on_init_fail_lock_mp:
3086 eina_mempool_del(_eina_model_mp);
3088 free(_eina_model_mp_choice);
3089 _eina_model_mp_choice = NULL;
3090 eina_log_domain_unregister(_eina_model_log_dom);
3091 _eina_model_log_dom = -1;
3097 * @brief Shut down the model module.
3099 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
3101 * This function shuts down the model module set up by
3102 * eina_model_init(). It is called by eina_shutdown().
3104 * @see eina_shutdown()
3107 eina_model_shutdown(void)
3109 eina_lock_take(&_eina_model_debug_list_lock);
3110 if (eina_list_count(_eina_model_debug_list) > 0)
3111 ERR("%d models are still alive!", eina_list_count(_eina_model_debug_list));
3112 eina_lock_release(&_eina_model_debug_list_lock);
3113 eina_lock_free(&_eina_model_debug_list_lock);
3115 eina_lock_take(&_eina_model_inner_mps_lock);
3116 if (eina_hash_population(_eina_model_inner_mps) != 0)
3117 ERR("Cannot free eina_model internal memory pools -- still in use!");
3119 eina_hash_free(_eina_model_inner_mps);
3120 eina_lock_release(&_eina_model_inner_mps_lock);
3121 eina_lock_free(&_eina_model_inner_mps_lock);
3123 eina_lock_take(&_eina_model_descriptions_lock);
3124 if (eina_hash_population(_eina_model_descriptions) != 0)
3125 ERR("Cannot free eina_model internal descriptions -- still in use!");
3127 eina_hash_free(_eina_model_descriptions);
3128 eina_lock_release(&_eina_model_descriptions_lock);
3129 eina_lock_free(&_eina_model_descriptions_lock);
3131 free(_eina_model_mp_choice);
3132 _eina_model_mp_choice = NULL;
3133 eina_mempool_del(_eina_model_mp);
3134 eina_log_domain_unregister(_eina_model_log_dom);
3135 _eina_model_log_dom = -1;
3139 /*============================================================================*
3141 *============================================================================*/
3143 /*============================================================================*
3145 *============================================================================*/
3148 EAPI Eina_Error EINA_ERROR_MODEL_FAILED = 0;
3149 EAPI Eina_Error EINA_ERROR_MODEL_METHOD_MISSING = 0;
3151 EAPI const Eina_Model_Type *EINA_MODEL_TYPE_BASE = NULL;
3152 EAPI const Eina_Model_Type *EINA_MODEL_TYPE_MIXIN = NULL;
3153 EAPI const Eina_Model_Type *EINA_MODEL_TYPE_GENERIC = NULL;
3154 EAPI const Eina_Model_Type *EINA_MODEL_TYPE_STRUCT = NULL;
3156 EAPI const Eina_Model_Interface *EINA_MODEL_INTERFACE_PROPERTIES_HASH = NULL;
3157 EAPI const Eina_Model_Interface *EINA_MODEL_INTERFACE_PROPERTIES_STRUCT = NULL;
3158 EAPI const Eina_Model_Interface *EINA_MODEL_INTERFACE_CHILDREN_INARRAY = NULL;
3160 EAPI const char *EINA_MODEL_INTERFACE_NAME_PROPERTIES = "Eina_Model_Interface_Properties";
3161 EAPI const char *EINA_MODEL_INTERFACE_NAME_CHILDREN = "Eina_Model_Interface_Children";
3164 eina_model_new(const Eina_Model_Type *type)
3166 const Eina_Model_Description *desc;
3170 EINA_SAFETY_ON_NULL_RETURN_VAL(type, NULL);
3171 EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_model_type_check(type), NULL);
3173 desc = _eina_model_description_get(type);
3174 EINA_SAFETY_ON_NULL_RETURN_VAL(desc, NULL);
3176 model = eina_mempool_malloc(_eina_model_mp, sizeof(Eina_Model));
3177 EINA_SAFETY_ON_NULL_GOTO(model, failed_model);
3180 model->listeners.entries = NULL;
3181 model->listeners.deleted = NULL;
3182 model->listeners.freeze = NULL;
3183 model->listeners.walking = 0;
3185 if (desc->total.size == 0)
3186 model->privates = NULL;
3191 model->privates = _eina_model_inner_alloc
3192 (desc->total.privates * sizeof(void *) +
3194 EINA_SAFETY_ON_NULL_GOTO(model->privates, failed_privates);
3196 ptr = (unsigned char *)(model->privates + desc->total.privates);
3197 for (i = 0; i < desc->total.privates; i++)
3200 if (i < desc->total.types)
3201 size = desc->cache.privates[i].type->private_size;
3203 size = desc->cache.privates[i].iface->private_size;
3207 model->privates[i] = NULL;
3211 model->privates[i] = ptr;
3212 memset(ptr, 0, size);
3214 if (size % sizeof(void *) != 0)
3215 size += sizeof(void *) - (size % sizeof(void *));
3220 model->refcount = 1;
3221 model->xrefs = NULL;
3222 model->deleted = EINA_FALSE;
3223 EINA_MAGIC_SET(model, EINA_MAGIC_MODEL);
3225 /* call setup of every type in the reverse order,
3226 * they should not call parent's setup.
3228 for (i = desc->total.types; i > 0; i--)
3230 if (desc->cache.types[i - 1]->setup)
3232 if (!desc->cache.types[i - 1]->setup(model))
3234 ERR("Failed to setup model %p at type %p (%s)",
3235 model, desc->cache.types[i - 1],
3236 desc->cache.types[i - 1]->name);
3242 /* call setup of every interface in the reverse order,
3243 * they should not call parent's setup.
3245 for (i = desc->total.ifaces; i > 0; i--)
3247 if (desc->cache.ifaces[i - 1]->setup)
3249 if (!desc->cache.ifaces[i - 1]->setup(model))
3251 ERR("Failed to setup model %p at interface %p (%s)",
3252 model, desc->cache.ifaces[i - 1],
3253 desc->cache.ifaces[i - 1]->name);
3259 if (!desc->ops.type.constructor(model))
3261 ERR("Failed to construct model %p, type %p (%s)",
3262 model, desc->cache.types[0], desc->cache.types[0]->name);
3263 goto failed_constructor;
3266 if (EINA_UNLIKELY(_eina_model_debug))
3268 eina_lock_take(&_eina_model_debug_list_lock);
3269 _eina_model_debug_list = eina_list_append
3270 (_eina_model_debug_list, model);
3271 eina_lock_release(&_eina_model_debug_list_lock);
3279 /* flush every setup interface, natural order */
3280 for (; i < desc->total.ifaces; i++)
3281 desc->cache.ifaces[i]->flush(model);
3284 /* flush every setup type, natural order */
3285 for (; i < desc->total.types; i++)
3286 desc->cache.types[i]->flush(model);
3288 if (model->privates)
3289 _eina_model_inner_free(desc->total.privates * sizeof(void *) +
3294 EINA_MAGIC_SET(model, EINA_MAGIC_NONE);
3295 eina_mempool_free(_eina_model_mp, model);
3297 _eina_model_description_dispose(desc);
3302 _eina_model_free(Eina_Model *model)
3304 const Eina_Model_Description *desc = model->desc;
3307 DBG("model %p (%s) refcount=%d deleted=%hhu",
3308 model, model->desc->cache.types[0]->name,
3309 model->refcount, model->deleted);
3311 if (EINA_UNLIKELY(_eina_model_debug))
3315 ERR("Model %p (%s) released with references pending:",
3316 model, model->desc->cache.types[0]->name);
3317 while (model->xrefs)
3319 Eina_Model_XRef *ref = (Eina_Model_XRef *)model->xrefs;
3320 model->xrefs = eina_inlist_remove(model->xrefs, model->xrefs);
3322 ERR("xref: %p '%s'", ref->id, ref->label);
3327 eina_lock_take(&_eina_model_debug_list_lock);
3328 _eina_model_debug_list = eina_list_remove
3329 (_eina_model_debug_list, model);
3330 eina_lock_release(&_eina_model_debug_list_lock);
3333 /* flush every interface, natural order */
3334 for (i = 0; i < desc->total.ifaces; i++)
3335 if (desc->cache.ifaces[i]->flush)
3336 desc->cache.ifaces[i]->flush(model);
3338 /* flush every type, natural order */
3339 for (i = 0; i < desc->total.types; i++)
3340 if (desc->cache.types[i]->flush)
3341 desc->cache.types[i]->flush(model);
3344 _eina_model_event_callback_call(model, _eina_model_str_freed, NULL);
3346 if (model->privates)
3347 _eina_model_inner_free(desc->total.privates * sizeof(void *) +
3351 if (model->listeners.deleted)
3352 _eina_model_event_callback_free_deleted(model);
3354 if (model->listeners.entries)
3356 for (i = 0; i < desc->total.events; i++)
3358 Eina_Inlist *lst = model->listeners.entries[i];
3363 _eina_model_inner_free(sizeof(Eina_Model_Event_Listener),
3368 _eina_model_inner_free(desc->total.events * sizeof(Eina_Inlist *),
3369 model->listeners.entries);
3372 if (model->listeners.freeze)
3373 _eina_model_inner_free(model->desc->total.events * sizeof(int),
3374 model->listeners.freeze);
3376 EINA_MAGIC_SET(model, EINA_MAGIC_NONE);
3377 eina_mempool_free(_eina_model_mp, model);
3379 _eina_model_description_dispose(desc);
3383 _eina_model_del(Eina_Model *model)
3385 const Eina_Model_Description *desc = model->desc;
3387 DBG("model %p (%s) refcount=%d deleted=%hhu",
3388 model, model->desc->cache.types[0]->name,
3389 model->refcount, model->deleted);
3391 EINA_SAFETY_ON_TRUE_RETURN(model->deleted);
3393 model->deleted = EINA_TRUE;
3394 _eina_model_event_callback_call(model, _eina_model_str_deleted, NULL);
3396 if (!desc->ops.type.destructor(model))
3397 ERR("Failed to destroy model %p, type %p (%s)",
3398 model, desc->cache.types[0], desc->cache.types[0]->name);
3402 _eina_model_unref(Eina_Model *model)
3404 DBG("model %p (%s) refcount=%d deleted=%hhu",
3405 model, model->desc->cache.types[0]->name,
3406 model->refcount, model->deleted);
3408 if (model->refcount > 1)
3414 if (!model->deleted) _eina_model_del(model);
3415 _eina_model_free(model);
3418 #define EINA_MODEL_INSTANCE_CHECK_VAL(inst, retval) \
3421 if (!EINA_MAGIC_CHECK(inst, EINA_MAGIC_MODEL)) \
3423 EINA_MAGIC_FAIL(inst, EINA_MAGIC_MODEL); \
3426 EINA_SAFETY_ON_NULL_RETURN_VAL(inst->desc, retval); \
3427 EINA_SAFETY_ON_FALSE_RETURN_VAL(inst->refcount > 0, retval); \
3428 EINA_SAFETY_ON_FALSE_RETURN_VAL(inst->desc->refcount > 0, retval); \
3432 #define EINA_MODEL_INSTANCE_CHECK(inst) \
3435 if (!EINA_MAGIC_CHECK(inst, EINA_MAGIC_MODEL)) \
3437 EINA_MAGIC_FAIL(inst, EINA_MAGIC_MODEL); \
3440 EINA_SAFETY_ON_NULL_RETURN(inst->desc); \
3441 EINA_SAFETY_ON_FALSE_RETURN(inst->refcount > 0); \
3442 EINA_SAFETY_ON_FALSE_RETURN(inst->desc->refcount > 0); \
3446 #define EINA_MODEL_TYPE_CALL_OPTIONAL_RETURN(model, method, def_retval, ...) \
3449 eina_error_set(0); \
3450 if (model->desc->ops.type.method) \
3451 return model->desc->ops.type.method(model, ## __VA_ARGS__); \
3452 DBG("Optional method" # method "() not implemented for model %p (%s)", \
3453 model, model->desc->cache.types[0]->name); \
3454 return def_retval; \
3458 #define EINA_MODEL_TYPE_CALL_OPTIONAL(model, method, ...) \
3461 eina_error_set(0); \
3462 if (model->desc->ops.type.method) \
3463 model->desc->ops.type.method(model, ## __VA_ARGS__); \
3465 DBG("Optional method" # method "() not implemented for model %p (%s)", \
3466 model, model->desc->cache.types[0]->name); \
3470 #define EINA_MODEL_TYPE_CALL_MANDATORY_RETURN(model, method, def_retval, ...) \
3473 eina_error_set(0); \
3474 if (model->desc->ops.type.method) \
3475 return model->desc->ops.type.method(model, ## __VA_ARGS__); \
3476 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING); \
3477 CRITICAL("Mandatory method" # method "() not implemented for model %p (%s)", \
3478 model, model->desc->cache.types[0]->name); \
3479 return def_retval; \
3483 #define EINA_MODEL_TYPE_CALL_MANDATORY(model, method, ...) \
3486 eina_error_set(0); \
3487 if (model->desc->ops.type.method) \
3488 model->desc->ops.type.method(model, ## __VA_ARGS__); \
3491 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING); \
3492 CRITICAL("Mandatory method" # method "() not implemented for model %p (%s)", \
3493 model, model->desc->cache.types[0]->name); \
3499 #define EINA_MODEL_TYPE_CALL_RETURN(model, method, def_retval, ...) \
3502 eina_error_set(0); \
3503 if (model->desc->ops.type.method) \
3504 return model->desc->ops.type.method(model, ## __VA_ARGS__); \
3505 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING); \
3506 ERR("Method" # method "() not implemented for model %p (%s)", \
3507 model, model->desc->cache.types[0]->name); \
3508 return def_retval; \
3512 #define EINA_MODEL_TYPE_CALL(model, method, ...) \
3515 eina_error_set(0); \
3516 if (model->desc->ops.type.method) \
3517 model->desc->ops.type.method(model, ## __VA_ARGS__); \
3520 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING); \
3521 ERR("Method" # method "() not implemented for model %p (%s)", \
3522 model, model->desc->cache.types[0]->name); \
3528 eina_model_del(Eina_Model *model)
3533 EINA_MODEL_INSTANCE_CHECK(model);
3534 _eina_model_del(model);
3535 _eina_model_unref(model);
3538 EAPI const Eina_Model_Type *
3539 eina_model_type_get(const Eina_Model *model)
3541 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
3542 return model->desc->cache.types[0];
3545 EAPI const Eina_Model_Interface *
3546 eina_model_interface_get(const Eina_Model *model, const char *name)
3548 const Eina_Model_Description *desc;
3549 const Eina_Model_Interface **itr, **itr_end;
3551 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
3552 EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
3555 itr = desc->cache.ifaces;
3556 itr_end = itr + desc->total.ifaces;
3558 /* fallback to strcmp if user is lazy about speed */
3559 for (; itr < itr_end; itr++)
3560 if (strcmp((*itr)->name, name) == 0)
3567 _eina_model_instance_check(const Eina_Model *model, const Eina_Model_Type *type)
3569 const Eina_Model_Type **itr, **itr_end;
3571 itr = model->desc->cache.types;
3572 itr_end = itr + model->desc->total.types;
3574 for (; itr < itr_end; itr++)
3582 eina_model_instance_check(const Eina_Model *model, const Eina_Model_Type *type)
3584 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
3585 EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE);
3586 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), EINA_FALSE);
3587 return _eina_model_instance_check(model, type);
3591 eina_model_ref(Eina_Model *model)
3593 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
3594 DBG("model %p (%s) refcount=%d deleted=%hhu",
3595 model, model->desc->cache.types[0]->name,
3596 model->refcount, model->deleted);
3602 _eina_model_xref_add(Eina_Model *model, const void *id, const char *label)
3604 Eina_Model_XRef *ref;
3606 int btlen, labellen;
3608 labellen = label ? strlen(label): 0;
3611 #ifdef HAVE_BACKTRACE
3612 if (_eina_model_debug == EINA_MODEL_DEBUG_BACKTRACE)
3613 btlen = backtrace(bt, EINA_C_ARRAY_LENGTH(bt));
3616 ref = calloc(1, sizeof(*ref) + (btlen * sizeof(void *)) + (labellen + 1));
3617 EINA_SAFETY_ON_NULL_RETURN_VAL(ref, NULL);
3620 memcpy(ref->label, label, labellen);
3621 ref->label[labellen] = '\0';
3622 ref->backtrace.count = btlen;
3623 if (btlen == 0) ref->backtrace.symbols = NULL;
3626 void *ptr = (unsigned char *)ref + sizeof(*ref) + (labellen + 1);
3627 ref->backtrace.symbols = ptr;
3628 memcpy(ptr, bt, btlen * sizeof(void *));
3631 model->xrefs = eina_inlist_append(model->xrefs, EINA_INLIST_GET(ref));
3636 eina_model_xref(Eina_Model *model, const void *id, const char *label)
3638 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
3639 DBG("model %p (%s) refcount=%d deleted=%hhu id=%p label=%s",
3640 model, model->desc->cache.types[0]->name,
3641 model->refcount, model->deleted, id, label ? label : "");
3645 if (EINA_LIKELY(!_eina_model_debug))
3648 return _eina_model_xref_add(model, id, label);
3652 eina_model_unref(Eina_Model *model)
3654 EINA_MODEL_INSTANCE_CHECK(model);
3655 _eina_model_unref(model);
3659 eina_model_xunref(Eina_Model *model, const void *id)
3661 Eina_Model_XRef *ref;
3662 EINA_MODEL_INSTANCE_CHECK(model);
3664 if (EINA_LIKELY(!_eina_model_debug))
3666 _eina_model_unref(model);
3670 EINA_INLIST_FOREACH(model->xrefs, ref)
3672 if (ref->id != id) continue;
3674 model->xrefs = eina_inlist_remove(model->xrefs, EINA_INLIST_GET(ref));
3676 _eina_model_unref(model);
3680 ERR("Could not find existing reference %p to model %p", id, model);
3684 eina_model_refcount(const Eina_Model *model)
3686 EINA_MODEL_INSTANCE_CHECK_VAL(model, -1);
3687 return model->refcount;
3690 EAPI const Eina_Inlist *
3691 eina_model_xrefs_get(const Eina_Model *model)
3693 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
3694 return model->xrefs;
3698 eina_model_event_callback_add(Eina_Model *model, const char *event_name, Eina_Model_Event_Cb cb, const void *data)
3700 const Eina_Model_Description *desc;
3701 Eina_Model_Event_Listener *el;
3704 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
3705 EINA_SAFETY_ON_NULL_RETURN_VAL(event_name, EINA_FALSE);
3706 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE);
3709 event_id = _eina_model_description_event_id_find(desc, event_name);
3712 ERR("No event named %s for model %p (%s)",
3713 event_name, model, model->desc->cache.types[0]->name);
3717 if (!model->listeners.entries)
3719 model->listeners.entries = _eina_model_inner_alloc
3720 (desc->total.events * sizeof(Eina_Inlist *));
3721 EINA_SAFETY_ON_NULL_RETURN_VAL(model->listeners.entries, EINA_FALSE);
3722 memset(model->listeners.entries, 0,
3723 desc->total.events * sizeof(Eina_Inlist *));
3726 el = _eina_model_inner_alloc(sizeof(Eina_Model_Event_Listener));
3727 EINA_SAFETY_ON_NULL_RETURN_VAL(el, EINA_FALSE);
3731 el->deleted = EINA_FALSE;
3732 model->listeners.entries[event_id] = eina_inlist_append
3733 (model->listeners.entries[event_id], EINA_INLIST_GET(el));
3739 eina_model_event_callback_del(Eina_Model *model, const char *event_name, Eina_Model_Event_Cb cb, const void *data)
3743 Eina_Model_Event_Listener *el;
3745 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
3746 EINA_SAFETY_ON_NULL_RETURN_VAL(event_name, EINA_FALSE);
3747 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE);
3749 if (!model->listeners.entries)
3751 ERR("No event callbacks for model %p (%s)",
3752 model, model->desc->cache.types[0]->name);
3756 event_id = _eina_model_description_event_id_find(model->desc, event_name);
3759 ERR("No event named %s for model %p (%s)",
3760 event_name, model, model->desc->cache.types[0]->name);
3764 lst = model->listeners.entries[event_id];
3765 EINA_INLIST_FOREACH(lst, el)
3767 if (el->cb != cb) continue;
3768 if ((data) && (el->data != data)) continue;
3770 if (model->listeners.walking == 0)
3772 model->listeners.entries[event_id] = eina_inlist_remove
3773 (model->listeners.entries[event_id], EINA_INLIST_GET(el));
3774 _eina_model_inner_free(sizeof(Eina_Model_Event_Listener), el);
3778 el->deleted = EINA_TRUE;
3779 if (!model->listeners.deleted)
3781 model->listeners.deleted = _eina_model_inner_alloc
3782 (model->desc->total.events * sizeof(Eina_List *));
3783 EINA_SAFETY_ON_NULL_RETURN_VAL(model->listeners.deleted,
3786 memset(model->listeners.deleted, 0,
3787 model->desc->total.events * sizeof(Eina_List *));
3790 model->listeners.deleted[event_id] = eina_list_append
3791 (model->listeners.deleted[event_id], el);
3796 ERR("No callback %p data %p found for event named %s for model %p (%s)",
3797 cb, data, event_name, model, model->desc->cache.types[0]->name);
3801 EAPI const Eina_Model_Event_Description *
3802 eina_model_event_description_get(const Eina_Model *model, const char *event_name)
3804 const Eina_Model_Description *desc;
3807 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
3808 EINA_SAFETY_ON_NULL_RETURN_VAL(event_name, NULL);
3811 event_id = _eina_model_description_event_id_find(desc, event_name);
3815 return desc->cache.events[event_id].desc;
3819 eina_model_event_names_list_get(const Eina_Model *model)
3821 const Eina_Model_Event_Description_Cache *itr, *itr_end;
3822 Eina_List *lst = NULL;
3824 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
3826 itr = model->desc->cache.events;
3827 itr_end = itr + model->desc->total.events;
3829 for (; itr < itr_end; itr++)
3830 lst = eina_list_append(lst, eina_stringshare_add(itr->name));
3836 eina_model_event_names_list_free(Eina_List *list)
3839 EINA_LIST_FREE(list, str)
3840 eina_stringshare_del(str);
3844 eina_model_event_callback_call(Eina_Model *model, const char *name, const void *event_info)
3846 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
3847 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
3848 return _eina_model_event_callback_call(model, name, event_info);
3852 eina_model_event_callback_freeze(Eina_Model *model, const char *name)
3856 EINA_MODEL_INSTANCE_CHECK_VAL(model, -1);
3857 EINA_SAFETY_ON_NULL_RETURN_VAL(name, -1);
3859 event_id = _eina_model_description_event_id_find(model->desc, name);
3860 if (event_id < 0) return -1;
3862 if (!model->listeners.freeze)
3864 model->listeners.freeze = _eina_model_inner_alloc
3865 (model->desc->total.events * sizeof(int));
3866 EINA_SAFETY_ON_NULL_RETURN_VAL(model->listeners.freeze, -1);
3868 memset(model->listeners.freeze, 0,
3869 model->desc->total.events * sizeof(int));
3872 if (model->listeners.freeze[event_id] == 0)
3873 DBG("model %p (%s) event %s frozen",
3874 model, model->desc->cache.types[0]->name, name);
3876 model->listeners.freeze[event_id]++;
3877 return model->listeners.freeze[event_id];
3881 eina_model_event_callback_thaw(Eina_Model *model, const char *name)
3885 EINA_MODEL_INSTANCE_CHECK_VAL(model, -1);
3886 EINA_SAFETY_ON_NULL_RETURN_VAL(name, -1);
3887 EINA_SAFETY_ON_NULL_RETURN_VAL(model->listeners.freeze, -1);
3889 event_id = _eina_model_description_event_id_find(model->desc, name);
3890 if (event_id < 0) return -1;
3892 model->listeners.freeze[event_id]--;
3893 if (model->listeners.freeze[event_id] == 0)
3894 DBG("model %p (%s) event %s unfrozen",
3895 model, model->desc->cache.types[0]->name, name);
3896 return model->listeners.freeze[event_id];
3900 eina_model_copy(const Eina_Model *model)
3902 const Eina_Model_Description *desc;
3906 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
3908 copy = eina_model_new(desc->cache.types[0]);
3909 EINA_SAFETY_ON_NULL_RETURN_VAL(copy, NULL);
3911 /* call copy of every type in the reverse order,
3912 * they should not call parent's copy.
3914 for (i = desc->total.types; i > 0; i--)
3916 if (desc->cache.types[i - 1]->copy)
3918 if (!desc->cache.types[i - 1]->copy(model, copy))
3923 /* call copy of every interface in the reverse order,
3924 * they should not call parent's copy.
3926 for (i = desc->total.ifaces; i > 0; i--)
3928 if (desc->cache.ifaces[i - 1]->copy)
3930 if (!desc->cache.ifaces[i - 1]->copy(model, copy))
3938 ERR("Failed to copy model %p %s", model, desc->cache.types[0]->name);
3939 eina_model_del(copy);
3944 eina_model_deep_copy(const Eina_Model *model)
3946 const Eina_Model_Description *desc;
3947 Eina_Model *deep_copy;
3950 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
3952 deep_copy = eina_model_new(desc->cache.types[0]);
3953 EINA_SAFETY_ON_NULL_RETURN_VAL(deep_copy, NULL);
3955 /* call deep_copy of every type in the reverse order,
3956 * they should not call parent's deep_copy.
3958 for (i = desc->total.types; i > 0; i--)
3960 if (desc->cache.types[i - 1]->deep_copy)
3962 if (!desc->cache.types[i - 1]->deep_copy(model, deep_copy))
3967 /* call deep_copy of every interface in the reverse order,
3968 * they should not call parent's deep_copy.
3970 for (i = desc->total.ifaces; i > 0; i--)
3972 if (desc->cache.ifaces[i - 1]->deep_copy)
3974 if (!desc->cache.ifaces[i - 1]->deep_copy(model, deep_copy))
3982 ERR("Failed to deep copy model %p %s", model, desc->cache.types[0]->name);
3983 eina_model_del(deep_copy);
3988 eina_model_compare(const Eina_Model *a, const Eina_Model *b)
3990 const Eina_Model_Description *desc_a, *desc_b;
3994 EINA_MODEL_INSTANCE_CHECK_VAL(a, -1);
3995 EINA_MODEL_INSTANCE_CHECK_VAL(b, -1);
3999 if ((!desc_a->ops.type.compare) && (!desc_b->ops.type.compare))
4001 ERR("Models %p (%s) and %p (%s) can't compare",
4002 a, desc_a->cache.types[0]->name,
4003 b, desc_b->cache.types[0]->name);
4004 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
4007 else if ((desc_a->ops.type.compare) && (desc_b->ops.type.compare))
4009 ok = desc_a->ops.type.compare(a, b, &cmp);
4012 ok = desc_b->ops.type.compare(b, a, &cmp);
4014 cmp = -cmp; /* swapped sides! */
4017 else if (desc_a->ops.type.compare)
4018 ok = desc_a->ops.type.compare(a, b, &cmp);
4021 ok = desc_b->ops.type.compare(b, a, &cmp);
4023 cmp = -cmp; /* swapped sides! */
4028 ERR("Could not compare models %p (%s) and %p (%s)",
4029 a, desc_a->cache.types[0]->name,
4030 b, desc_b->cache.types[0]->name);
4031 eina_error_set(EINA_ERROR_MODEL_FAILED);
4039 eina_model_load(Eina_Model *model)
4043 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
4046 if (model->desc->ops.type.load)
4048 ret = model->desc->ops.type.load(model);
4050 _eina_model_event_callback_call(model, _eina_model_str_loaded, NULL);
4054 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
4056 ERR("Method load() not implemented for model %p (%s)",
4057 model, model->desc->cache.types[0]->name);
4064 eina_model_unload(Eina_Model *model)
4068 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
4071 if (model->desc->ops.type.unload)
4073 ret = model->desc->ops.type.unload(model);
4075 _eina_model_event_callback_call
4076 (model, _eina_model_str_unloaded, NULL);
4080 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
4082 ERR("Method unload() not implemented for model %p (%s)",
4083 model, model->desc->cache.types[0]->name);
4090 eina_model_property_get(const Eina_Model *model, const char *name, Eina_Value *value)
4092 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
4093 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
4094 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
4095 EINA_MODEL_TYPE_CALL_MANDATORY_RETURN(model, property_get, EINA_FALSE,
4100 eina_model_property_set(Eina_Model *model, const const char *name, const Eina_Value *value)
4104 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
4105 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
4106 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
4107 EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), EINA_FALSE);
4110 if (model->desc->ops.type.property_set)
4112 ret = model->desc->ops.type.property_set(model, name, value);
4114 _eina_model_event_callback_call
4115 (model, _eina_model_str_property_set, name);
4119 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
4121 ERR("Method property_set() not implemented for model %p (%s)",
4122 model, model->desc->cache.types[0]->name);
4129 eina_model_property_del(Eina_Model *model, const char *name)
4133 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
4134 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
4137 if (model->desc->ops.type.property_del)
4139 ret = model->desc->ops.type.property_del(model, name);
4141 _eina_model_event_callback_call
4142 (model, _eina_model_str_property_del, name);
4146 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
4148 ERR("Method property_del() not implemented for model %p (%s)",
4149 model, model->desc->cache.types[0]->name);
4156 eina_model_properties_names_list_get(const Eina_Model *model)
4158 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4159 EINA_MODEL_TYPE_CALL_OPTIONAL_RETURN(model, properties_names_list_get, NULL);
4163 eina_model_properties_names_list_free(Eina_List *list)
4166 EINA_LIST_FREE(list, str)
4167 eina_stringshare_del(str);
4171 eina_model_child_count(const Eina_Model *model)
4173 EINA_MODEL_INSTANCE_CHECK_VAL(model, -1);
4174 EINA_MODEL_TYPE_CALL_OPTIONAL_RETURN(model, child_count, 0);
4178 eina_model_child_get(const Eina_Model *model, unsigned int position)
4180 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4181 EINA_MODEL_TYPE_CALL_RETURN(model, child_get, NULL, position);
4185 eina_model_child_set(Eina_Model *model, unsigned int position, Eina_Model *child)
4189 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
4190 EINA_MODEL_INSTANCE_CHECK_VAL(child, EINA_FALSE);
4193 if (model->desc->ops.type.child_set)
4195 ret = model->desc->ops.type.child_set(model, position, child);
4197 _eina_model_event_callback_call
4198 (model, _eina_model_str_child_set, &position);
4202 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
4204 ERR("Method child_set() not implemented for model %p (%s)",
4205 model, model->desc->cache.types[0]->name);
4212 eina_model_child_del(Eina_Model *model, unsigned int position)
4216 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
4219 if (model->desc->ops.type.child_del)
4221 ret = model->desc->ops.type.child_del(model, position);
4224 _eina_model_event_callback_call
4225 (model, _eina_model_str_child_del, &position);
4226 _eina_model_event_callback_call
4227 (model, _eina_model_str_children_changed, NULL);
4232 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
4234 ERR("Method child_del() not implemented for model %p (%s)",
4235 model, model->desc->cache.types[0]->name);
4242 eina_model_child_insert_at(Eina_Model *model, unsigned int position, Eina_Model *child)
4246 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
4247 EINA_SAFETY_ON_NULL_RETURN_VAL(child, EINA_FALSE);
4250 if (model->desc->ops.type.child_insert_at)
4252 ret = model->desc->ops.type.child_insert_at(model, position, child);
4255 _eina_model_event_callback_call
4256 (model, _eina_model_str_child_inserted, &position);
4257 _eina_model_event_callback_call
4258 (model, _eina_model_str_children_changed, NULL);
4263 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
4265 ERR("Method child_insert_at() not implemented for model %p (%s)",
4266 model, model->desc->cache.types[0]->name);
4273 eina_model_child_append(Eina_Model *model, Eina_Model *child)
4278 EINA_MODEL_INSTANCE_CHECK_VAL(model, -1);
4279 EINA_SAFETY_ON_NULL_RETURN_VAL(child, -1);
4281 position = eina_model_child_count(model);
4286 if (model->desc->ops.type.child_insert_at)
4288 ret = model->desc->ops.type.child_insert_at(model, position, child);
4291 _eina_model_event_callback_call
4292 (model, _eina_model_str_child_inserted, &position);
4293 _eina_model_event_callback_call
4294 (model, _eina_model_str_children_changed, NULL);
4299 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
4301 ERR("Method child_insert_at() not implemented for model %p (%s)",
4302 model, model->desc->cache.types[0]->name);
4305 return ret ? position : -1;
4309 eina_model_child_find(const Eina_Model *model, unsigned int start_position, const Eina_Model *other)
4311 EINA_MODEL_INSTANCE_CHECK_VAL(model, -1);
4312 EINA_SAFETY_ON_NULL_RETURN_VAL(other, -1);
4313 EINA_MODEL_TYPE_CALL_RETURN(model, child_find, -1, start_position, other);
4317 eina_model_child_criteria_match(const Eina_Model *model, unsigned int start_position, Eina_Each_Cb match, const void *data)
4319 EINA_MODEL_INSTANCE_CHECK_VAL(model, -1);
4320 EINA_SAFETY_ON_NULL_RETURN_VAL(match, -1);
4321 EINA_MODEL_TYPE_CALL_RETURN(model, child_criteria_match, -1,
4322 start_position, match, data);
4326 eina_model_child_sort(Eina_Model *model, Eina_Compare_Cb compare)
4328 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
4329 EINA_SAFETY_ON_NULL_RETURN_VAL(compare, EINA_FALSE);
4330 EINA_MODEL_TYPE_CALL(model, child_sort, compare);
4331 _eina_model_event_callback_call
4332 (model, _eina_model_str_children_changed, NULL);
4336 EAPI Eina_Iterator *
4337 eina_model_child_iterator_get(Eina_Model *model)
4340 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4341 count = eina_model_child_count(model);
4344 EINA_MODEL_TYPE_CALL_RETURN(model, child_iterator_get, NULL, 0, count);
4347 EAPI Eina_Iterator *
4348 eina_model_child_slice_iterator_get(Eina_Model *model, unsigned int start, unsigned int count)
4350 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4351 EINA_MODEL_TYPE_CALL_RETURN(model, child_iterator_get, NULL, start, count);
4354 EAPI Eina_Iterator *
4355 eina_model_child_reversed_iterator_get(Eina_Model *model)
4358 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4359 count = eina_model_child_count(model);
4362 EINA_MODEL_TYPE_CALL_RETURN(model, child_reversed_iterator_get, NULL,
4366 EAPI Eina_Iterator *
4367 eina_model_child_slice_reversed_iterator_get(Eina_Model *model, unsigned int start, unsigned int count)
4369 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4370 EINA_MODEL_TYPE_CALL_RETURN(model, child_reversed_iterator_get, NULL,
4374 EAPI Eina_Iterator *
4375 eina_model_child_sorted_iterator_get(Eina_Model *model, Eina_Compare_Cb compare)
4378 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4379 EINA_SAFETY_ON_NULL_RETURN_VAL(compare, NULL);
4380 count = eina_model_child_count(model);
4383 EINA_MODEL_TYPE_CALL_RETURN(model, child_sorted_iterator_get, NULL,
4387 EAPI Eina_Iterator *
4388 eina_model_child_slice_sorted_iterator_get(Eina_Model *model, unsigned int start, unsigned int count, Eina_Compare_Cb compare)
4390 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4391 EINA_SAFETY_ON_NULL_RETURN_VAL(compare, NULL);
4392 EINA_MODEL_TYPE_CALL_RETURN(model, child_sorted_iterator_get, NULL,
4393 start, count, compare);
4396 EAPI Eina_Iterator *
4397 eina_model_child_filtered_iterator_get(Eina_Model *model, Eina_Each_Cb match, const void *data)
4400 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4401 EINA_SAFETY_ON_NULL_RETURN_VAL(match, NULL);
4402 count = eina_model_child_count(model);
4405 EINA_MODEL_TYPE_CALL_RETURN(model, child_filtered_iterator_get, NULL,
4406 0, count, match, data);
4409 EAPI Eina_Iterator *
4410 eina_model_child_slice_filtered_iterator_get(Eina_Model *model, unsigned int start, unsigned int count, Eina_Each_Cb match, const void *data)
4412 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4413 EINA_SAFETY_ON_NULL_RETURN_VAL(match, NULL);
4414 EINA_MODEL_TYPE_CALL_RETURN(model, child_filtered_iterator_get, NULL,
4415 start, count, match, data);
4419 eina_model_to_string(const Eina_Model *model)
4421 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4422 EINA_MODEL_TYPE_CALL_RETURN(model, to_string, NULL);
4425 /* type functions *****************************************************/
4428 eina_model_type_check(const Eina_Model_Type *type)
4430 EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE);
4431 return _eina_model_type_check(type);
4435 eina_model_type_name_get(const Eina_Model_Type *type)
4437 EINA_SAFETY_ON_NULL_RETURN_VAL(type, NULL);
4438 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), NULL);
4442 EAPI const Eina_Model_Type *
4443 eina_model_type_parent_get(const Eina_Model_Type *type)
4445 EINA_SAFETY_ON_NULL_RETURN_VAL(type, NULL);
4446 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), NULL);
4447 return type->parent;
4450 #define EINA_MODEL_TYPE_INSTANCE_CHECK(type, model) \
4451 EINA_SAFETY_ON_NULL_RETURN(type); \
4452 EINA_SAFETY_ON_FALSE_RETURN(_eina_model_type_check(type)); \
4453 EINA_MODEL_INSTANCE_CHECK(model); \
4454 EINA_SAFETY_ON_FALSE_RETURN(_eina_model_instance_check(model, type));
4456 #define EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, retval) \
4457 EINA_SAFETY_ON_NULL_RETURN_VAL(type, retval); \
4458 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), retval); \
4459 EINA_MODEL_INSTANCE_CHECK_VAL(model, retval); \
4460 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_instance_check(model, type), retval);
4463 eina_model_type_constructor(const Eina_Model_Type *type, Eina_Model *model)
4465 Eina_Bool (*constructor)(Eina_Model *);
4467 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4469 constructor = _eina_model_type_find_offset
4470 (type, offsetof(Eina_Model_Type, constructor));
4471 EINA_SAFETY_ON_NULL_RETURN_VAL(constructor, EINA_FALSE);
4473 return constructor(model);
4477 eina_model_type_destructor(const Eina_Model_Type *type, Eina_Model *model)
4479 Eina_Bool (*destructor)(Eina_Model *);
4481 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4483 destructor = _eina_model_type_find_offset
4484 (type, offsetof(Eina_Model_Type, destructor));
4485 EINA_SAFETY_ON_NULL_RETURN_VAL(destructor, EINA_FALSE);
4487 return destructor(model);
4491 eina_model_type_copy(const Eina_Model_Type *type, const Eina_Model *src, Eina_Model *dst)
4493 Eina_Bool (*copy)(const Eina_Model *, Eina_Model *);
4495 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, src, EINA_FALSE);
4496 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, dst, EINA_FALSE);
4498 copy = _eina_model_type_find_offset
4499 (type, offsetof(Eina_Model_Type, copy));
4500 EINA_SAFETY_ON_NULL_RETURN_VAL(copy, EINA_FALSE);
4502 return copy(src, dst);
4506 eina_model_type_deep_copy(const Eina_Model_Type *type, const Eina_Model *src, Eina_Model *dst)
4508 Eina_Bool (*deep_copy)(const Eina_Model *, Eina_Model *);
4510 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, src, EINA_FALSE);
4511 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, dst, EINA_FALSE);
4513 deep_copy = _eina_model_type_find_offset
4514 (type, offsetof(Eina_Model_Type, deep_copy));
4515 EINA_SAFETY_ON_NULL_RETURN_VAL(deep_copy, EINA_FALSE);
4517 return deep_copy(src, dst);
4521 eina_model_type_compare(const Eina_Model_Type *type, const Eina_Model *a, const Eina_Model *b, int *cmp)
4523 Eina_Bool (*compare)(const Eina_Model *, const Eina_Model *, int *);
4525 EINA_SAFETY_ON_NULL_RETURN_VAL(cmp, EINA_FALSE);
4528 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, a, EINA_FALSE);
4529 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, b, EINA_FALSE);
4531 compare = _eina_model_type_find_offset
4532 (type, offsetof(Eina_Model_Type, compare));
4533 EINA_SAFETY_ON_NULL_RETURN_VAL(compare, EINA_FALSE);
4535 return compare(a, b, cmp);
4539 eina_model_type_load(const Eina_Model_Type *type, Eina_Model *model)
4541 Eina_Bool (*load)(Eina_Model *);
4543 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4545 load = _eina_model_type_find_offset
4546 (type, offsetof(Eina_Model_Type, load));
4547 EINA_SAFETY_ON_NULL_RETURN_VAL(load, EINA_FALSE);
4553 eina_model_type_unload(const Eina_Model_Type *type, Eina_Model *model)
4555 Eina_Bool (*unload)(Eina_Model *);
4557 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4559 unload = _eina_model_type_find_offset
4560 (type, offsetof(Eina_Model_Type, unload));
4561 EINA_SAFETY_ON_NULL_RETURN_VAL(unload, EINA_FALSE);
4563 return unload(model);
4567 eina_model_type_property_get(const Eina_Model_Type *type, const Eina_Model *model, const char *name, Eina_Value *value)
4569 Eina_Bool (*property_get)(const Eina_Model *, const char *, Eina_Value *);
4571 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
4572 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
4574 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4576 property_get = _eina_model_type_find_offset
4577 (type, offsetof(Eina_Model_Type, property_get));
4578 EINA_SAFETY_ON_NULL_RETURN_VAL(property_get, EINA_FALSE);
4580 return property_get(model, name, value);
4584 eina_model_type_property_set(const Eina_Model_Type *type, Eina_Model *model, const char *name, const Eina_Value *value)
4586 Eina_Bool (*property_set)(Eina_Model *, const char *, const Eina_Value *);
4588 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
4589 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
4590 EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), EINA_FALSE);
4592 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4594 property_set = _eina_model_type_find_offset
4595 (type, offsetof(Eina_Model_Type, property_set));
4596 EINA_SAFETY_ON_NULL_RETURN_VAL(property_set, EINA_FALSE);
4598 return property_set(model, name, value);
4602 eina_model_type_property_del(const Eina_Model_Type *type, Eina_Model *model, const char *name)
4604 Eina_Bool (*property_del)(const Eina_Model *, const char *);
4606 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
4607 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4609 property_del = _eina_model_type_find_offset
4610 (type, offsetof(Eina_Model_Type, property_del));
4611 EINA_SAFETY_ON_NULL_RETURN_VAL(property_del, EINA_FALSE);
4613 return property_del(model, name);
4617 eina_model_type_properties_names_list_get(const Eina_Model_Type *type, const Eina_Model *model)
4619 Eina_List *(*properties_names_list_get)(const Eina_Model *);
4621 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL);
4623 properties_names_list_get = _eina_model_type_find_offset
4624 (type, offsetof(Eina_Model_Type, properties_names_list_get));
4625 EINA_SAFETY_ON_NULL_RETURN_VAL(properties_names_list_get, NULL);
4627 return properties_names_list_get(model);
4631 eina_model_type_child_count(const Eina_Model_Type *type, const Eina_Model *model)
4633 int (*child_count)(const Eina_Model *);
4635 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, -1);
4637 child_count = _eina_model_type_find_offset
4638 (type, offsetof(Eina_Model_Type, child_count));
4639 EINA_SAFETY_ON_NULL_RETURN_VAL(child_count, -1);
4641 return child_count(model);
4645 eina_model_type_child_get(const Eina_Model_Type *type, const Eina_Model *model, unsigned int position)
4647 Eina_Model *(*child_get)(const Eina_Model *, unsigned int);
4649 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL);
4651 child_get = _eina_model_type_find_offset
4652 (type, offsetof(Eina_Model_Type, child_get));
4653 EINA_SAFETY_ON_NULL_RETURN_VAL(child_get, NULL);
4655 return child_get(model, position);
4659 eina_model_type_child_set(const Eina_Model_Type *type, Eina_Model *model, unsigned int position, Eina_Model *child)
4661 Eina_Bool (*child_set)(Eina_Model *, unsigned int, Eina_Model *);
4663 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4664 EINA_MODEL_INSTANCE_CHECK_VAL(child, EINA_FALSE);
4666 child_set = _eina_model_type_find_offset
4667 (type, offsetof(Eina_Model_Type, child_set));
4668 EINA_SAFETY_ON_NULL_RETURN_VAL(child_set, EINA_FALSE);
4670 return child_set(model, position, child);
4674 eina_model_type_child_del(const Eina_Model_Type *type, Eina_Model *model, unsigned int position)
4676 Eina_Bool (*child_del)(Eina_Model *, unsigned int);
4678 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4680 child_del = _eina_model_type_find_offset
4681 (type, offsetof(Eina_Model_Type, child_del));
4682 EINA_SAFETY_ON_NULL_RETURN_VAL(child_del, EINA_FALSE);
4684 return child_del(model, position);
4688 eina_model_type_child_insert_at(const Eina_Model_Type *type, Eina_Model *model, unsigned int position, Eina_Model *child)
4690 Eina_Bool (*child_insert_at)(Eina_Model *, unsigned int, Eina_Model *);
4692 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4693 EINA_MODEL_INSTANCE_CHECK_VAL(child, EINA_FALSE);
4695 child_insert_at = _eina_model_type_find_offset
4696 (type, offsetof(Eina_Model_Type, child_insert_at));
4697 EINA_SAFETY_ON_NULL_RETURN_VAL(child_insert_at, EINA_FALSE);
4699 return child_insert_at(model, position, child);
4703 eina_model_type_child_find(const Eina_Model_Type *type, const Eina_Model *model, unsigned int start_position, const Eina_Model *other)
4705 int (*child_find)(const Eina_Model *, unsigned int, const Eina_Model *);
4707 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, -1);
4708 EINA_MODEL_INSTANCE_CHECK_VAL(other, -1);
4710 child_find = _eina_model_type_find_offset
4711 (type, offsetof(Eina_Model_Type, child_find));
4712 EINA_SAFETY_ON_NULL_RETURN_VAL(child_find, -1);
4714 return child_find(model, start_position, other);
4718 eina_model_type_child_criteria_match(const Eina_Model_Type *type, const Eina_Model *model, unsigned int start_position, Eina_Each_Cb match, const void *data)
4720 int (*child_criteria_match)(const Eina_Model *, unsigned int, Eina_Each_Cb, const void *);
4722 EINA_SAFETY_ON_NULL_RETURN_VAL(match, -1);
4723 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, -1);
4725 child_criteria_match = _eina_model_type_find_offset
4726 (type, offsetof(Eina_Model_Type, child_criteria_match));
4727 EINA_SAFETY_ON_NULL_RETURN_VAL(child_criteria_match, -1);
4729 return child_criteria_match(model, start_position, match, data);
4733 eina_model_type_child_sort(const Eina_Model_Type *type, Eina_Model *model, Eina_Compare_Cb compare)
4735 void (*child_sort)(Eina_Model *, Eina_Compare_Cb);
4737 EINA_SAFETY_ON_NULL_RETURN(compare);
4738 EINA_MODEL_TYPE_INSTANCE_CHECK(type, model);
4740 child_sort = _eina_model_type_find_offset
4741 (type, offsetof(Eina_Model_Type, child_sort));
4742 EINA_SAFETY_ON_NULL_RETURN(child_sort);
4744 return child_sort(model, compare);
4747 EAPI Eina_Iterator *
4748 eina_model_type_child_iterator_get(const Eina_Model_Type *type, Eina_Model *model, unsigned int start, unsigned int count)
4750 Eina_Iterator *(*child_iterator_get)(const Eina_Model *, unsigned int, unsigned int);
4752 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL);
4754 child_iterator_get = _eina_model_type_find_offset
4755 (type, offsetof(Eina_Model_Type, child_iterator_get));
4756 EINA_SAFETY_ON_NULL_RETURN_VAL(child_iterator_get, NULL);
4758 return child_iterator_get(model, start, count);
4761 EAPI Eina_Iterator *
4762 eina_model_type_child_reversed_iterator_get(const Eina_Model_Type *type, Eina_Model *model, unsigned int start, unsigned int count)
4764 Eina_Iterator *(*child_reversed_iterator_get)(const Eina_Model *, unsigned int, unsigned int);
4766 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL);
4768 child_reversed_iterator_get = _eina_model_type_find_offset
4769 (type, offsetof(Eina_Model_Type, child_reversed_iterator_get));
4770 EINA_SAFETY_ON_NULL_RETURN_VAL(child_reversed_iterator_get, NULL);
4772 return child_reversed_iterator_get(model, start, count);
4775 EAPI Eina_Iterator *
4776 eina_model_type_child_sorted_iterator_get(const Eina_Model_Type *type, Eina_Model *model, unsigned int start, unsigned int count, Eina_Compare_Cb compare)
4778 Eina_Iterator *(*child_sorted_iterator_get)(const Eina_Model *, unsigned int, unsigned int, Eina_Compare_Cb);
4780 EINA_SAFETY_ON_NULL_RETURN_VAL(compare, NULL);
4781 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL);
4783 child_sorted_iterator_get = _eina_model_type_find_offset
4784 (type, offsetof(Eina_Model_Type, child_sorted_iterator_get));
4785 EINA_SAFETY_ON_NULL_RETURN_VAL(child_sorted_iterator_get, NULL);
4787 return child_sorted_iterator_get(model, start, count, compare);
4790 EAPI Eina_Iterator *
4791 eina_model_type_child_filtered_iterator_get(const Eina_Model_Type *type, Eina_Model *model, unsigned int start, unsigned int count, Eina_Each_Cb match, const void *data)
4793 Eina_Iterator *(*child_filtered_iterator_get)(const Eina_Model *, unsigned int, unsigned int, Eina_Each_Cb, const void *);
4795 EINA_SAFETY_ON_NULL_RETURN_VAL(match, NULL);
4796 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL);
4798 child_filtered_iterator_get = _eina_model_type_find_offset
4799 (type, offsetof(Eina_Model_Type, child_filtered_iterator_get));
4800 EINA_SAFETY_ON_NULL_RETURN_VAL(child_filtered_iterator_get, NULL);
4802 return child_filtered_iterator_get(model, start, count, match, data);
4806 eina_model_type_to_string(const Eina_Model_Type *type, const Eina_Model *model)
4808 char *(*to_string)(const Eina_Model *);
4810 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL);
4812 to_string = _eina_model_type_find_offset
4813 (type, offsetof(Eina_Model_Type, to_string));
4814 EINA_SAFETY_ON_NULL_RETURN_VAL(to_string, NULL);
4816 return to_string(model);
4820 eina_model_type_subclass_setup(Eina_Model_Type *type, const Eina_Model_Type *parent)
4822 EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE);
4823 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, EINA_FALSE);
4824 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(parent), EINA_FALSE);
4825 EINA_SAFETY_ON_FALSE_RETURN_VAL(type->version == EINA_MODEL_TYPE_VERSION,
4828 type->parent = parent;
4829 type->type_size = parent->type_size;
4830 type->interfaces = NULL;
4831 type->events = NULL;
4835 type->constructor = NULL;
4836 type->destructor = NULL;
4838 type->deep_copy = NULL;
4839 type->compare = NULL;
4841 type->unload = NULL;
4842 type->property_get = NULL;
4843 type->property_set = NULL;
4844 type->property_del = NULL;
4845 type->properties_names_list_get = NULL;
4846 type->child_count = NULL;
4847 type->child_get = NULL;
4848 type->child_set = NULL;
4849 type->child_del = NULL;
4850 type->child_insert_at = NULL;
4851 type->child_find = NULL;
4852 type->child_criteria_match = NULL;
4853 type->child_sort = NULL;
4854 type->child_iterator_get = NULL;
4855 type->child_reversed_iterator_get = NULL;
4856 type->child_sorted_iterator_get = NULL;
4857 type->child_filtered_iterator_get = NULL;
4858 type->to_string = NULL;
4859 type->__extension_ptr0 = NULL;
4860 type->__extension_ptr1 = NULL;
4861 type->__extension_ptr2 = NULL;
4862 type->__extension_ptr3 = NULL;
4864 if (type->type_size > sizeof(Eina_Model_Type))
4866 unsigned char *p = (unsigned char *)type;
4867 p += sizeof(Eina_Model_Type);
4868 memset(p, 0, type->type_size - sizeof(Eina_Model_Type));
4875 eina_model_type_subclass_check(const Eina_Model_Type *type, const Eina_Model_Type *self_or_parent)
4877 EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE);
4878 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), EINA_FALSE);
4879 EINA_SAFETY_ON_NULL_RETURN_VAL(self_or_parent, EINA_FALSE);
4881 for (; type != NULL; type = type->parent)
4883 if (type == self_or_parent)
4890 static inline const Eina_Model_Interface *
4891 _eina_model_type_interface_get(const Eina_Model_Type *type, const char *name, Eina_Bool ptr_cmp __UNUSED__)
4893 const Eina_Model_Interface **itr;
4898 if (!type->interfaces)
4899 return _eina_model_type_interface_get(type->parent, name, ptr_cmp);
4902 for (itr = type->interfaces ; itr != NULL ; itr++)
4903 if (strcmp((*itr)->name, name) == 0)
4910 static inline Eina_Bool
4911 _eina_model_interface_check(const Eina_Model_Interface *iface)
4913 EINA_SAFETY_ON_FALSE_RETURN_VAL
4914 (iface->version == EINA_MODEL_INTERFACE_VERSION, EINA_FALSE);
4918 EAPI const Eina_Model_Interface *
4919 eina_model_type_interface_get(const Eina_Model_Type *type, const char *name)
4921 const Eina_Model_Interface *iface;
4923 EINA_SAFETY_ON_NULL_RETURN_VAL(type, NULL);
4924 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), NULL);
4926 /* search for pointer, make speed-aware users fast */
4927 iface = _eina_model_type_interface_get(type, name, EINA_TRUE);
4931 /* search using strcmp(), slow users don't care */
4932 iface = _eina_model_type_interface_get(type, name, EINA_FALSE);
4934 else if (!_eina_model_interface_check(iface))
4941 eina_model_type_private_data_get(const Eina_Model *model, const Eina_Model_Type *type)
4943 const Eina_Model_Description *desc;
4946 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4947 EINA_SAFETY_ON_NULL_RETURN_VAL(type, NULL);
4948 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), NULL);
4952 for (i = 0; i < desc->total.types; i++)
4953 if (desc->cache.types[i] == type)
4954 return model->privates[i];
4956 CRITICAL("Model %p (%s) is not an instance of type %p (%s)",
4957 model, desc->cache.types[0]->name,
4963 eina_model_method_offset_resolve(const Eina_Model *model, unsigned int offset)
4965 const Eina_Model_Description *desc;
4967 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4968 EINA_SAFETY_ON_FALSE_RETURN_VAL(offset >= sizeof(Eina_Model_Type), NULL);
4969 EINA_SAFETY_ON_FALSE_RETURN_VAL(offset % sizeof(void *) == 0, NULL);
4972 EINA_SAFETY_ON_FALSE_RETURN_VAL
4973 (offset + sizeof(void *) <= desc->cache.types[0]->type_size, NULL);
4975 offset -= sizeof(Eina_Model_Type);
4976 offset /= sizeof(void *);
4977 return desc->ops.type.extension[offset];
4981 eina_model_type_method_offset_resolve(const Eina_Model_Type *type, const Eina_Model *model, unsigned int offset)
4983 const Eina_Model_Description *desc;
4985 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL);
4986 EINA_SAFETY_ON_FALSE_RETURN_VAL(offset >= sizeof(Eina_Model_Type), NULL);
4987 EINA_SAFETY_ON_FALSE_RETURN_VAL(offset % sizeof(void *) == 0, NULL);
4990 EINA_SAFETY_ON_FALSE_RETURN_VAL
4991 (offset + sizeof(void *) <= desc->cache.types[0]->type_size, NULL);
4993 return _eina_model_type_find_offset(type, offset);
4996 /* interface functions ************************************************/
4999 eina_model_interface_check(const Eina_Model_Interface *iface)
5001 EINA_SAFETY_ON_NULL_RETURN_VAL(iface, EINA_FALSE);
5002 return _eina_model_interface_check(iface);
5006 eina_model_interface_private_data_get(const Eina_Model *model, const Eina_Model_Interface *iface)
5008 const Eina_Model_Description *desc;
5011 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
5012 EINA_SAFETY_ON_NULL_RETURN_VAL(iface, NULL);
5013 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_interface_check(iface), NULL);
5017 for (i = 0; i < desc->total.ifaces; i++)
5018 if (desc->cache.ifaces[i] == iface)
5019 return model->privates[desc->total.types + i];
5021 CRITICAL("Model %p (%s) does not implement interface %p (%s)",
5022 model, desc->cache.types[0]->name,
5023 iface, iface->name);
5028 _eina_model_interface_implemented(const Eina_Model *model, const Eina_Model_Interface *iface)
5030 const Eina_Model_Interface **itr, **itr_end;
5032 itr = model->desc->cache.ifaces;
5033 itr_end = itr + model->desc->total.ifaces;
5035 for (; itr < itr_end; itr++)
5043 eina_model_interface_implemented(const Eina_Model *model, const Eina_Model_Interface *iface)
5045 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
5046 EINA_SAFETY_ON_NULL_RETURN_VAL(iface, EINA_FALSE);
5047 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_interface_check(iface),
5049 return _eina_model_interface_implemented(model, iface);
5052 #define EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK(iface, model) \
5053 EINA_SAFETY_ON_NULL_RETURN(iface); \
5054 EINA_SAFETY_ON_FALSE_RETURN(_eina_model_interface_check(iface)); \
5055 EINA_MODEL_INSTANCE_CHECK(model); \
5056 EINA_SAFETY_ON_FALSE_RETURN(_eina_model_interface_implemented(model, iface));
5058 #define EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, retval) \
5059 EINA_SAFETY_ON_NULL_RETURN_VAL(iface, retval); \
5060 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_interface_check(iface), retval); \
5061 EINA_MODEL_INSTANCE_CHECK_VAL(model, retval); \
5062 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_interface_implemented(model, iface), retval);
5066 eina_model_interface_constructor(const Eina_Model_Interface *iface, Eina_Model *model)
5068 Eina_Bool (*constructor)(Eina_Model *);
5070 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5072 constructor = _eina_model_interface_find_offset
5073 (iface, offsetof(Eina_Model_Interface, constructor));
5074 EINA_SAFETY_ON_NULL_RETURN_VAL(constructor, EINA_FALSE);
5075 return constructor(model);
5079 eina_model_interface_destructor(const Eina_Model_Interface *iface, Eina_Model *model)
5081 Eina_Bool (*destructor)(Eina_Model *);
5083 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5085 destructor = _eina_model_interface_find_offset
5086 (iface, offsetof(Eina_Model_Interface, destructor));
5087 EINA_SAFETY_ON_NULL_RETURN_VAL(destructor, EINA_FALSE);
5088 return destructor(model);
5092 eina_model_interface_copy(const Eina_Model_Interface *iface, const Eina_Model *src, Eina_Model *dst)
5094 Eina_Bool (*copy)(const Eina_Model *, Eina_Model *);
5096 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, src, EINA_FALSE);
5097 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, dst, EINA_FALSE);
5099 copy = _eina_model_interface_find_offset
5100 (iface, offsetof(Eina_Model_Interface, copy));
5101 EINA_SAFETY_ON_NULL_RETURN_VAL(copy, EINA_FALSE);
5102 return copy(src, dst);
5106 eina_model_interface_deep_copy(const Eina_Model_Interface *iface, const Eina_Model *src, Eina_Model *dst)
5108 Eina_Bool (*deep_copy)(const Eina_Model *, Eina_Model *);
5110 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, src, EINA_FALSE);
5111 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, dst, EINA_FALSE);
5113 deep_copy = _eina_model_interface_find_offset
5114 (iface, offsetof(Eina_Model_Interface, deep_copy));
5115 EINA_SAFETY_ON_NULL_RETURN_VAL(deep_copy, EINA_FALSE);
5116 return deep_copy(src, dst);
5120 *eina_model_interface_method_offset_resolve(const Eina_Model_Interface *iface, const Eina_Model *model, unsigned int offset)
5122 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, NULL);
5123 EINA_SAFETY_ON_FALSE_RETURN_VAL(offset >= sizeof(Eina_Model_Interface), NULL);
5124 EINA_SAFETY_ON_FALSE_RETURN_VAL(offset % sizeof(void *) == 0, NULL);
5125 return _eina_model_interface_find_offset(iface, offset);
5129 /* Eina_Model_Interface_Properties ************************************/
5132 eina_model_interface_properties_compare(const Eina_Model_Interface *iface, const Eina_Model *a, const Eina_Model *b, int *cmp)
5134 Eina_Bool (*compare)(const Eina_Model *, const Eina_Model *, int *cmp);
5136 EINA_SAFETY_ON_NULL_RETURN_VAL(cmp, EINA_FALSE);
5139 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, a, EINA_FALSE);
5140 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, b, EINA_FALSE);
5142 compare = _eina_model_interface_find_offset
5143 (iface, offsetof(Eina_Model_Interface_Properties, compare));
5144 EINA_SAFETY_ON_NULL_RETURN_VAL(compare, EINA_FALSE);
5145 return compare(a, b, cmp);
5149 eina_model_interface_properties_load(const Eina_Model_Interface *iface, Eina_Model *model)
5151 Eina_Bool (*load)(Eina_Model *);
5154 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5156 load = _eina_model_interface_find_offset
5157 (iface, offsetof(Eina_Model_Interface_Properties, load));
5158 EINA_SAFETY_ON_NULL_RETURN_VAL(load, EINA_FALSE);
5162 _eina_model_event_callback_call
5163 (model, _eina_model_str_properties_loaded, NULL);
5169 eina_model_interface_properties_unload(const Eina_Model_Interface *iface, Eina_Model *model)
5171 Eina_Bool (*unload)(Eina_Model *);
5174 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5176 unload = _eina_model_interface_find_offset
5177 (iface, offsetof(Eina_Model_Interface_Properties, unload));
5178 EINA_SAFETY_ON_NULL_RETURN_VAL(unload, EINA_FALSE);
5179 ret = unload(model);
5182 _eina_model_event_callback_call
5183 (model, _eina_model_str_properties_unloaded, NULL);
5189 eina_model_interface_properties_get(const Eina_Model_Interface *iface, const Eina_Model *model, const char *name, Eina_Value *value)
5191 Eina_Bool (*get)(const Eina_Model *, const char *, Eina_Value *);
5193 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
5194 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
5195 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5197 get = _eina_model_interface_find_offset
5198 (iface, offsetof(Eina_Model_Interface_Properties, get));
5199 EINA_SAFETY_ON_NULL_RETURN_VAL(get, EINA_FALSE);
5200 return get(model, name, value);
5204 eina_model_interface_properties_set(const Eina_Model_Interface *iface, Eina_Model *model, const char *name, const Eina_Value *value)
5206 Eina_Bool (*set)(Eina_Model *, const char *, const Eina_Value *);
5208 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
5209 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
5210 EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), EINA_FALSE);
5211 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5213 set = _eina_model_interface_find_offset
5214 (iface, offsetof(Eina_Model_Interface_Properties, set));
5215 EINA_SAFETY_ON_NULL_RETURN_VAL(set, EINA_FALSE);
5216 return set(model, name, value);
5220 eina_model_interface_properties_del(const Eina_Model_Interface *iface, Eina_Model *model, const char *name)
5222 Eina_Bool (*del)(Eina_Model *, const char *);
5224 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
5225 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5227 del = _eina_model_interface_find_offset
5228 (iface, offsetof(Eina_Model_Interface_Properties, del));
5229 EINA_SAFETY_ON_NULL_RETURN_VAL(del, EINA_FALSE);
5230 return del(model, name);
5234 eina_model_interface_properties_names_list_get(const Eina_Model_Interface *iface, const Eina_Model *model)
5236 Eina_List *(*names_list_get)(const Eina_Model *);
5238 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, NULL);
5240 names_list_get = _eina_model_interface_find_offset
5241 (iface, offsetof(Eina_Model_Interface_Properties, names_list_get));
5242 EINA_SAFETY_ON_NULL_RETURN_VAL(names_list_get, NULL);
5243 return names_list_get(model);
5246 /* Eina_Model_Interface_Children **************************************/
5249 eina_model_interface_children_compare(const Eina_Model_Interface *iface, const Eina_Model *a, const Eina_Model *b, int *cmp)
5251 Eina_Bool (*compare)(const Eina_Model *, const Eina_Model *, int *);
5253 EINA_SAFETY_ON_NULL_RETURN_VAL(cmp, EINA_FALSE);
5257 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, a, EINA_FALSE);
5258 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, b, EINA_FALSE);
5260 compare = _eina_model_interface_find_offset
5261 (iface, offsetof(Eina_Model_Interface_Children, compare));
5262 EINA_SAFETY_ON_NULL_RETURN_VAL(compare, EINA_FALSE);
5263 return compare(a, b, cmp);
5267 eina_model_interface_children_load(const Eina_Model_Interface *iface, Eina_Model *model)
5269 Eina_Bool (*load)(Eina_Model *);
5272 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5274 load = _eina_model_interface_find_offset
5275 (iface, offsetof(Eina_Model_Interface_Children, load));
5276 EINA_SAFETY_ON_NULL_RETURN_VAL(load, EINA_FALSE);
5280 _eina_model_event_callback_call
5281 (model, _eina_model_str_children_loaded, NULL);
5287 eina_model_interface_children_unload(const Eina_Model_Interface *iface, Eina_Model *model)
5289 Eina_Bool (*unload)(Eina_Model *);
5292 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5294 unload = _eina_model_interface_find_offset
5295 (iface, offsetof(Eina_Model_Interface_Children, unload));
5296 EINA_SAFETY_ON_NULL_RETURN_VAL(unload, EINA_FALSE);
5297 ret = unload(model);
5300 _eina_model_event_callback_call
5301 (model, _eina_model_str_children_unloaded, NULL);
5307 eina_model_interface_children_count(const Eina_Model_Interface *iface, const Eina_Model *model)
5309 int (*count)(const Eina_Model *);
5311 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, -1);
5313 count = _eina_model_interface_find_offset
5314 (iface, offsetof(Eina_Model_Interface_Children, count));
5315 EINA_SAFETY_ON_NULL_RETURN_VAL(count, -1);
5316 return count(model);
5320 eina_model_interface_children_get(const Eina_Model_Interface *iface, const Eina_Model *model, unsigned int position)
5322 Eina_Model *(*get)(const Eina_Model *, unsigned int);
5324 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, NULL);
5326 get = _eina_model_interface_find_offset
5327 (iface, offsetof(Eina_Model_Interface_Children, get));
5328 EINA_SAFETY_ON_NULL_RETURN_VAL(get, NULL);
5329 return get(model, position);
5332 EAPI Eina_Bool eina_model_interface_children_set(const Eina_Model_Interface *iface, Eina_Model *model, unsigned int position, Eina_Model *child)
5334 Eina_Bool (*set)(const Eina_Model *, unsigned int, Eina_Model *);
5336 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5337 EINA_MODEL_INSTANCE_CHECK_VAL(child, EINA_FALSE);
5339 set = _eina_model_interface_find_offset
5340 (iface, offsetof(Eina_Model_Interface_Children, set));
5341 EINA_SAFETY_ON_NULL_RETURN_VAL(set, EINA_FALSE);
5342 return set(model, position, child);
5346 eina_model_interface_children_del(const Eina_Model_Interface *iface, Eina_Model *model, unsigned int position)
5348 Eina_Bool (*del)(Eina_Model *, unsigned int);
5350 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5352 del = _eina_model_interface_find_offset
5353 (iface, offsetof(Eina_Model_Interface_Children, del));
5354 EINA_SAFETY_ON_NULL_RETURN_VAL(del, EINA_FALSE);
5355 return del(model, position);
5360 eina_model_interface_children_insert_at(const Eina_Model_Interface *iface, Eina_Model *model, unsigned int position, Eina_Model *child)
5362 Eina_Bool (*insert_at)(const Eina_Model *, unsigned int, Eina_Model *);
5364 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5365 EINA_MODEL_INSTANCE_CHECK_VAL(child, EINA_FALSE);
5367 insert_at = _eina_model_interface_find_offset
5368 (iface, offsetof(Eina_Model_Interface_Children, insert_at));
5369 EINA_SAFETY_ON_NULL_RETURN_VAL(insert_at, EINA_FALSE);
5370 return insert_at(model, position, child);
5374 eina_model_interface_children_sort(const Eina_Model_Interface *iface, Eina_Model *model, Eina_Compare_Cb compare)
5376 void (*sort)(const Eina_Model *, Eina_Compare_Cb);
5378 EINA_SAFETY_ON_NULL_RETURN(compare);
5379 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK(iface, model);
5381 sort = _eina_model_interface_find_offset
5382 (iface, offsetof(Eina_Model_Interface_Children, sort));
5383 EINA_SAFETY_ON_NULL_RETURN(sort);
5384 return sort(model, compare);
5388 _eina_model_struct_set(Eina_Model *m, const Eina_Value_Struct_Desc *desc, void *memory)
5390 Eina_Value_Struct st = {desc, memory};
5391 Eina_Value *val = eina_model_interface_private_data_get
5392 (m, &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base);
5393 return eina_value_pset(val, &st);
5397 eina_model_struct_new(const Eina_Value_Struct_Desc *desc)
5401 EINA_SAFETY_ON_NULL_RETURN_VAL(desc, NULL);
5402 EINA_SAFETY_ON_FALSE_RETURN_VAL
5403 (desc->version == EINA_VALUE_STRUCT_DESC_VERSION, NULL);
5405 m = eina_model_new(EINA_MODEL_TYPE_STRUCT);
5406 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
5408 EINA_SAFETY_ON_FALSE_GOTO(_eina_model_struct_set(m, desc, NULL), error);
5417 eina_model_type_struct_new(const Eina_Model_Type *type, const Eina_Value_Struct_Desc *desc)
5421 EINA_SAFETY_ON_FALSE_RETURN_VAL
5422 (eina_model_type_subclass_check(type, EINA_MODEL_TYPE_STRUCT), NULL);
5423 EINA_SAFETY_ON_NULL_RETURN_VAL(desc, NULL);
5424 EINA_SAFETY_ON_FALSE_RETURN_VAL
5425 (desc->version == EINA_VALUE_STRUCT_DESC_VERSION, NULL);
5427 m = eina_model_new(type);
5428 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
5430 EINA_SAFETY_ON_FALSE_GOTO(_eina_model_struct_set(m, desc, NULL), error);
5439 eina_model_struct_set(Eina_Model *model, const Eina_Value_Struct_Desc *desc, void *memory)
5441 EINA_SAFETY_ON_NULL_RETURN_VAL(desc, EINA_FALSE);
5442 EINA_SAFETY_ON_FALSE_RETURN_VAL
5443 (desc->version == EINA_VALUE_STRUCT_DESC_VERSION, EINA_FALSE);
5444 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL
5445 (&_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base, model, EINA_FALSE);
5447 return _eina_model_struct_set(model, desc, memory);
5451 eina_model_struct_get(const Eina_Model *model, const Eina_Value_Struct_Desc **p_desc, void **p_memory)
5453 const Eina_Value *val;
5454 Eina_Value_Struct st;
5456 EINA_SAFETY_ON_NULL_RETURN_VAL(p_desc, EINA_FALSE);
5459 if (p_memory) *p_memory = NULL;
5461 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL
5462 (&_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base, model, EINA_FALSE);
5464 val = eina_model_interface_private_data_get
5465 (model, &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base);
5467 EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_pget(val, &st), EINA_FALSE);
5470 if (p_memory) *p_memory = st.memory;
5475 eina_models_usage_dump(void)
5478 const Eina_Model *m;
5480 eina_lock_take(&_eina_model_debug_list_lock);
5482 puts("DDD: model refs info (type, holders, backtrace)");
5483 puts("DDD: -------------- -------------- ---------------------------------");
5485 EINA_LIST_FOREACH(_eina_model_debug_list, l, m)
5487 Eina_Model_XRef *ref;
5489 printf("DDD: %14p %14d %s\n",
5490 m, m->refcount, m->desc->cache.types[0]->name);
5492 EINA_INLIST_FOREACH(m->xrefs, ref)
5494 printf("DDD: id: %p '%s'\n",
5495 ref->id, ref->label);
5496 if (ref->backtrace.count)
5501 #ifdef HAVE_BACKTRACE_SYMBOLS
5502 symbols = backtrace_symbols((void * const *)ref->backtrace.symbols,
5503 ref->backtrace.count);
5508 printf("DDD: Backtrace: Address Symbol\n");
5509 for (i = 0; i < ref->backtrace.count; i++)
5510 printf("DDD: %14p %s\n",
5511 ref->backtrace.symbols[i],
5512 symbols ? symbols[i] : "???");
5520 eina_lock_release(&_eina_model_debug_list_lock);
5524 eina_models_list_get(void)
5528 Eina_List *ret = NULL;
5530 eina_lock_take(&_eina_model_debug_list_lock);
5532 EINA_LIST_FOREACH(_eina_model_debug_list, l, m)
5534 ret = eina_list_append
5535 (ret, eina_model_xref
5536 (m, eina_models_list_get, "eina_models_list_get"));
5539 eina_lock_release(&_eina_model_debug_list_lock);
5545 eina_models_list_free(Eina_List *list)
5549 EINA_LIST_FREE(list, m)
5550 eina_model_xunref(m, eina_models_list_get);