aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/eina/src
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/eina/src')
-rw-r--r--libraries/eina/src/examples/eina_inarray_01.c52
-rw-r--r--libraries/eina/src/examples/eina_model_01.c235
-rw-r--r--libraries/eina/src/examples/eina_model_02.c61
-rw-r--r--libraries/eina/src/examples/eina_model_03.c236
-rw-r--r--libraries/eina/src/examples/eina_model_04_animal.c76
-rw-r--r--libraries/eina/src/examples/eina_model_04_child.c81
-rw-r--r--libraries/eina/src/examples/eina_model_04_human.c157
-rw-r--r--libraries/eina/src/examples/eina_model_04_main.c110
-rw-r--r--libraries/eina/src/examples/eina_model_04_parrot.c95
-rw-r--r--libraries/eina/src/examples/eina_model_04_whistler.c59
-rw-r--r--libraries/eina/src/examples/eina_value_01.c53
-rw-r--r--libraries/eina/src/examples/eina_value_02.c100
-rw-r--r--libraries/eina/src/examples/eina_value_03.c178
-rw-r--r--libraries/eina/src/include/eina_model.h3105
-rw-r--r--libraries/eina/src/lib/eina_model.c5548
-rw-r--r--libraries/eina/src/tests/eina_test_model.c1288
16 files changed, 11434 insertions, 0 deletions
diff --git a/libraries/eina/src/examples/eina_inarray_01.c b/libraries/eina/src/examples/eina_inarray_01.c
new file mode 100644
index 0000000..b9ab4e7
--- /dev/null
+++ b/libraries/eina/src/examples/eina_inarray_01.c
@@ -0,0 +1,52 @@
1//Compile with:
2//gcc -g eina_inarray_01.c -o eina_inarray_01 `pkg-config --cflags --libs eina`
3
4#include <Eina.h>
5
6int
7cmp(const void *a, const void *b)
8{
9 return *(int*)a > *(int*)b;
10}
11
12int main(int argc, char **argv)
13{
14 Eina_Inarray *iarr;
15 char ch, *ch2;
16 int a, *b;
17
18 eina_init();
19 iarr = eina_inarray_new(sizeof(char), 0);
20
21 ch = 'a';
22 eina_inarray_append(iarr, &ch);
23 ch = 'b';
24 eina_inarray_append(iarr, &ch);
25 ch = 'c';
26 eina_inarray_append(iarr, &ch);
27 ch = 'd';
28 eina_inarray_append(iarr, &ch);
29
30 printf("Inline array of chars:\n");
31 EINA_INARRAY_FOREACH(iarr, ch2)
32 printf("char: %c(pointer: %p)\n", *ch2, ch2);
33
34 eina_inarray_flush(iarr);
35 eina_inarray_setup(iarr, sizeof(int), 4);
36
37 a = 97;
38 eina_inarray_append(iarr, &a);
39 a = 98;
40 eina_inarray_append(iarr, &a);
41 a = 100;
42 eina_inarray_append(iarr, &a);
43 a = 99;
44 eina_inarray_insert_sorted(iarr, &a, cmp);
45
46 printf("Inline array of integers with %d elements:\n", eina_inarray_count(iarr));
47 EINA_INARRAY_FOREACH(iarr, b)
48 printf("int: %d(pointer: %p)\n", *b, b);
49
50 eina_inarray_free(iarr);
51 eina_shutdown();
52}
diff --git a/libraries/eina/src/examples/eina_model_01.c b/libraries/eina/src/examples/eina_model_01.c
new file mode 100644
index 0000000..28895aa
--- /dev/null
+++ b/libraries/eina/src/examples/eina_model_01.c
@@ -0,0 +1,235 @@
1/*
2 * Compile with:
3 * gcc -o eina_model_01 eina_model_01.c `pkg-config --cflags --libs eina`
4 */
5
6/*
7 * This example demonstrates the usage of Eina Model by implementing
8 * Bank Account Class, which is inherited from Base Class;
9 * and Credit Card Class, which is inherited from Bank Account Class.
10 *
11 * Base Class(Eina_Model_Type) --> Bank Account Class --> Credit Card Class
12 *
13 * Bank Account Class implements "bank_account_data_set()" and "print()" methods;
14 * Credit Card Class inherits these two and implements "credit_card_data_set()"
15 *
16 *
17 * Bank Account Class::print() calls for "_bank_account_data_print"
18 * Credit Card Class ::print() is reloaded with "_credit_card_data_print()"
19 * which calls for parent function "_bank_account_data_print"
20 *
21 */
22
23
24#include <Eina.h>
25#include <eina_safety_checks.h>
26
27/*
28 * Defining type for new model type
29 * Model will have two methods
30 */
31typedef struct _Bank_Account_Type
32{
33 Eina_Model_Type parent_class;
34 void (*bank_account_data_set)(Eina_Model *, const char *name, const char *number);
35 void (*print)(Eina_Model *);
36} Bank_Account_Type;
37
38/*
39 * Defining type for Bank Account private data
40 */
41typedef struct _Bank_Account_Data
42{
43 char name[30];
44 char number[30];
45} Bank_Account_Data;
46
47/*
48 * Defining type for Credit Card model type, which will be inherited from Bank Account model type
49 * Model will have two parent's methods and additional one
50 */
51typedef struct _Credit_Card_Type
52{
53 Bank_Account_Type parent_class;
54 void (*credit_card_data_set)(Eina_Model *, const char *, const char *, int) ;
55} Credit_Card_Type;
56
57/*
58 * Defining type for Credit Card private data
59 */
60typedef struct _Credit_Card_Data
61{
62 char number[30];
63 char expiry_date[30];
64 int pin;
65} Credit_Card_Data;
66
67static Bank_Account_Type _BANK_ACCOUNT_TYPE;
68static Credit_Card_Type _CREDIT_CARD_TYPE;
69static Eina_Model_Type *BANK_ACCOUNT_TYPE = (Eina_Model_Type *) &_BANK_ACCOUNT_TYPE;
70static Eina_Model_Type *CREDIT_CARD_TYPE = (Eina_Model_Type *) &_CREDIT_CARD_TYPE;
71
72
73/*
74 * Defining method for for Bank Account data
75 */
76static void
77_bank_account_data_set(Eina_Model *mdl, const char *name, const char *number)
78{
79 Bank_Account_Data *bdata = eina_model_type_private_data_get(mdl, BANK_ACCOUNT_TYPE);
80
81 if (!bdata)
82 printf("ERROR\n");
83
84 if (name != NULL)
85 {
86 strncpy(bdata->name, name, sizeof(bdata->name));
87 bdata->name[sizeof(bdata->number) - 1] = '\0';
88 }
89
90 if (number != NULL)
91 {
92 strncpy(bdata->number, number, sizeof(bdata->number));
93 bdata->number[sizeof(bdata->number) - 1] = '\0';
94 }
95
96 printf("%s :: %s %p\n", eina_model_type_name_get(eina_model_type_get(mdl)) ,__func__, mdl);
97}
98
99
100static void
101_credit_card_data_set(Eina_Model *mdl, const char *number, const char *expiry_date, int pin)
102{
103 Credit_Card_Data *cdata = eina_model_type_private_data_get(mdl, CREDIT_CARD_TYPE);
104
105 if (!cdata)
106 printf("ERROR\n");
107
108 if (number != NULL)
109 {
110 strncpy(cdata->number, number, sizeof(cdata->number));
111 cdata->number[sizeof(cdata->number) - 1] = '\0';
112 }
113
114 if (expiry_date != NULL)
115 {
116 strncpy(cdata->expiry_date, expiry_date, sizeof(cdata->expiry_date));
117 cdata->expiry_date[sizeof(cdata->expiry_date) - 1] = '\0';
118 }
119
120 cdata->pin = pin;
121 printf("%s :: %s %p\n", eina_model_type_name_get(eina_model_type_get(mdl)) ,__func__, mdl);
122}
123
124static void
125_bank_account_data_print(Eina_Model *mdl)
126{
127 const Bank_Account_Data *bdata = eina_model_type_private_data_get(mdl, BANK_ACCOUNT_TYPE);
128
129 printf("\n%s :: %s %p \n\tName: %s(%p)\n\tAccount: %s(%p)\n", eina_model_type_name_get(eina_model_type_get(mdl)) ,__func__, mdl
130 , bdata->name, bdata->name, bdata->number, bdata->number);
131}
132
133static void
134_credit_card_data_print(Eina_Model *mdl)
135{
136 void (*pf)(Eina_Model *);
137 const Eina_Model_Type *ptype = eina_model_type_parent_get(eina_model_type_get(mdl));
138 //const Eina_Model_Type *ptype = eina_model_type_get(mdl);
139
140 pf = eina_model_type_method_resolve(ptype, mdl, Bank_Account_Type, print);
141 if (pf)
142 pf(mdl);
143 else
144 printf("ERROR: %d", __LINE__);
145 const Credit_Card_Data *cdata = eina_model_type_private_data_get(mdl, CREDIT_CARD_TYPE);
146 printf("%s :: %s %p \n\tNumber: %s(%p)\n\tCC Expiry Date: %s(%p)\n\tCC PIN: %d(%p)\n", eina_model_type_name_get(eina_model_type_get(mdl)) ,__func__, mdl
147 , cdata->number, cdata->number, cdata->expiry_date, cdata->expiry_date, cdata->pin, &cdata->pin);
148}
149
150#define BANK_ACCOUNT(x) ((Bank_Account_Type *) x)
151#define CREDIT_CARD(x) ((Credit_Card_Type *) x)
152
153void
154bank_account_data_set(Eina_Model *mdl, const char *name, char *number)
155{
156
157 EINA_SAFETY_ON_FALSE_RETURN(eina_model_instance_check(mdl, BANK_ACCOUNT_TYPE));
158
159 void (*pf)(Eina_Model *, const char *, const char *);
160 pf = eina_model_method_resolve(mdl, Bank_Account_Type, bank_account_data_set);
161 if (pf)
162 pf(mdl, name, number);
163 else
164 printf("ERROR %d\n", __LINE__);
165}
166
167void
168data_print(Eina_Model *mdl)
169{
170 EINA_SAFETY_ON_FALSE_RETURN(eina_model_instance_check(mdl, BANK_ACCOUNT_TYPE));
171
172 void (*pf)(Eina_Model *);
173 pf = eina_model_method_resolve(mdl, Bank_Account_Type, print);
174 if (pf)
175 pf(mdl);
176 else
177 printf("ERROR %d\n", __LINE__);
178}
179
180void
181credit_card_data_set(Eina_Model *mdl, const char *number, const char *expiry_date, int pin)
182{
183 EINA_SAFETY_ON_FALSE_RETURN(eina_model_instance_check(mdl, CREDIT_CARD_TYPE));
184
185 void (*pf)(Eina_Model *, const char *, const char *, int);
186 pf = eina_model_method_resolve(mdl, Credit_Card_Type, credit_card_data_set);
187 if (pf)
188 pf(mdl, number, expiry_date, pin);
189 else
190 printf("ERROR %d\n", __LINE__);
191}
192
193int main(void)
194{
195 Eina_Model *b, *cc;
196
197 eina_init();
198
199 memset(&_BANK_ACCOUNT_TYPE, 0, sizeof(_BANK_ACCOUNT_TYPE));
200 memset(&_CREDIT_CARD_TYPE, 0, sizeof(_CREDIT_CARD_TYPE));
201
202 BANK_ACCOUNT_TYPE->version = EINA_MODEL_TYPE_VERSION;
203 BANK_ACCOUNT_TYPE->type_size = sizeof(Bank_Account_Type);
204 BANK_ACCOUNT_TYPE->private_size = sizeof(Bank_Account_Data);
205 BANK_ACCOUNT_TYPE->name = "Bank_Account_Model";
206 BANK_ACCOUNT_TYPE->parent = EINA_MODEL_TYPE_GENERIC;
207 BANK_ACCOUNT(BANK_ACCOUNT_TYPE)->bank_account_data_set = _bank_account_data_set;
208 BANK_ACCOUNT(BANK_ACCOUNT_TYPE)->print = _bank_account_data_print;
209
210 CREDIT_CARD_TYPE->version = EINA_MODEL_TYPE_VERSION;
211 CREDIT_CARD_TYPE->type_size = sizeof(Credit_Card_Type);
212 CREDIT_CARD_TYPE->private_size = sizeof(Credit_Card_Data);
213 CREDIT_CARD_TYPE->name = "Credit_Card_Model";
214 CREDIT_CARD_TYPE->parent = BANK_ACCOUNT_TYPE;
215 CREDIT_CARD(CREDIT_CARD_TYPE)->credit_card_data_set = _credit_card_data_set;
216 BANK_ACCOUNT(CREDIT_CARD_TYPE)->print = _credit_card_data_print;
217
218 b = eina_model_new(BANK_ACCOUNT_TYPE); //creating object of bank class
219 cc = eina_model_new(CREDIT_CARD_TYPE); //creating object of credit card class
220
221 bank_account_data_set(b, "Bill Clark", "8569214756");
222 bank_account_data_set(cc, "John Smith", "3154789");
223
224 credit_card_data_set(cc, "5803 6589 4786 3279 9173", "01/01/2015", 1234);
225
226 data_print(b);
227 data_print(cc);
228
229 eina_model_unref(b);
230 eina_model_unref(cc);
231
232 eina_shutdown();
233
234 return 0;
235}
diff --git a/libraries/eina/src/examples/eina_model_02.c b/libraries/eina/src/examples/eina_model_02.c
new file mode 100644
index 0000000..a2cb693
--- /dev/null
+++ b/libraries/eina/src/examples/eina_model_02.c
@@ -0,0 +1,61 @@
1//Compile with:
2//gcc -g eina_model_02.c -o eina_model_02 `pkg-config --cflags --libs eina`
3
4#include <Eina.h>
5
6static void _cb_on_deleted(void *data, Eina_Model *model, const Eina_Model_Event_Description *desc, void *event_info);
7
8int main(void)
9{
10 Eina_Model *m;
11 char *s;
12 int i;
13
14 eina_init();
15
16 m = eina_model_new(EINA_MODEL_TYPE_GENERIC);
17
18 eina_model_event_callback_add(m, "deleted", _cb_on_deleted, NULL);
19
20 //Adding properties to model
21 for (i = 0; i < 5; i++)
22 {
23 Eina_Value val;
24 char name[2] = {'a'+ i, 0};
25 eina_value_setup(&val, EINA_VALUE_TYPE_INT);
26 eina_value_set(&val, i);
27 eina_model_property_set(m, name, &val);
28 eina_value_flush(&val);
29 }
30
31 //Adding children to model
32 for (i = 0; i < 5; i++)
33 {
34 Eina_Value val;
35 Eina_Model *c = eina_model_new(EINA_MODEL_TYPE_GENERIC);
36 eina_value_setup(&val, EINA_VALUE_TYPE_INT);
37 eina_value_set(&val, i);
38 eina_model_property_set(c, "x", &val);
39
40 eina_model_event_callback_add(c, "deleted", _cb_on_deleted, NULL);
41
42 eina_model_child_append(m, c);
43 //Now that the child has been appended to a model, it's parent will manage it's lifecycle
44 eina_model_unref(c);
45 eina_value_flush(&val);
46 }
47
48 s = eina_model_to_string(m);
49 printf("model as string:\n%s\n", s);
50
51 free(s);
52 eina_model_unref(m);
53 eina_shutdown();
54
55 return 0;
56}
57
58static void _cb_on_deleted(void *data, Eina_Model *model, const Eina_Model_Event_Description *desc, void *event_info)
59{
60 printf("deleted %p\n", model);
61}
diff --git a/libraries/eina/src/examples/eina_model_03.c b/libraries/eina/src/examples/eina_model_03.c
new file mode 100644
index 0000000..a5e2562
--- /dev/null
+++ b/libraries/eina/src/examples/eina_model_03.c
@@ -0,0 +1,236 @@
1//Compile with:
2//gcc -g eina_model_03.c -o eina_model_03 `pkg-config --cflags --libs eina`
3
4#include <Eina.h>
5#include <string.h>
6#include <stdio.h>
7#include <errno.h>
8
9static Eina_Model_Type *ADDRESS_BOOK_TYPE;
10static Eina_Model_Type *PERSON_TYPE;
11
12static void address_book_init(void);
13
14int main(void)
15{
16 Eina_Model *address_book;
17 Eina_Value val;
18 int i, count;
19 char *s;
20
21 eina_init();
22
23 address_book_init();
24
25 address_book = eina_model_new(ADDRESS_BOOK_TYPE);
26
27 eina_value_setup(&val, EINA_VALUE_TYPE_STRING);
28 eina_value_set(&val, "addr_book.txt");
29 eina_model_property_set(address_book, "filename", &val);
30 eina_value_flush(&val);
31
32 eina_model_load(address_book);
33 s = eina_model_to_string(address_book);
34 printf("model as string:\n%s\n\n", s);
35 free(s);
36
37 count = eina_model_child_count(address_book);
38 printf("Address Book with %d entries:\n", count);
39 for (i = 0; i < count; i++)
40 {
41 Eina_Model *person = eina_model_child_get(address_book, i);
42 Eina_Value nameval, emailval;
43 const char *name, *email;
44
45 eina_model_property_get(person, "name", &nameval);
46 eina_model_property_get(person, "email", &emailval);
47
48 eina_value_get(&nameval, &name);
49 eina_value_get(&emailval, &email);
50
51 printf("%02d \"%s\" <%s>\n", i, name, email);
52
53 // We don't need property values anymore
54 eina_value_flush(&nameval);
55 eina_value_flush(&emailval);
56
57 // We don't need our reference to person anymore
58 eina_model_unref(person);
59 }
60
61 eina_model_unref(address_book);
62 eina_shutdown();
63
64 return 0;
65}
66
67// Structure Descriptions are just used internally in the type constructors:
68static Eina_Value_Struct_Desc *ADDRESS_BOOK_DESC;
69static Eina_Value_Struct_Desc *PERSON_DESC;
70
71static Eina_Bool
72_person_constructor(Eina_Model *model)
73{
74 // call parent type constructor, like "super" in other languages:
75 if (!eina_model_type_constructor(EINA_MODEL_TYPE_STRUCT, model))
76 return EINA_FALSE;
77
78 // Do specific setup of our internal structure, letting it know about
79 // our description
80 return eina_model_struct_set(model, PERSON_DESC, NULL);
81}
82
83static Eina_Bool
84_address_book_constructor(Eina_Model *model)
85{
86 // call parent type constructor, like "super" in other languages:
87 if (!eina_model_type_constructor(EINA_MODEL_TYPE_STRUCT, model))
88 return EINA_FALSE;
89
90 // Do specific setup of our internal structure, letting it know about
91 // our description
92 return eina_model_struct_set(model, ADDRESS_BOOK_DESC, NULL);
93}
94
95static Eina_Bool
96_address_book_load(Eina_Model *model)
97{
98 const char *filename;
99 Eina_Value val;
100 char buf[256];
101 FILE *f;
102
103 // We retrieve filename from property of same name:
104 eina_model_property_get(model, "filename", &val);
105 eina_value_get(&val, &filename);
106
107 EINA_SAFETY_ON_NULL_RETURN_VAL(filename, EINA_FALSE);
108
109 f = fopen(filename, "r");
110
111 // Now that we have used filename, we must free its memory holder:
112 eina_value_flush(&val);
113
114 EINA_SAFETY_ON_NULL_RETURN_VAL(f, EINA_FALSE);
115
116 while (fgets(buf, sizeof(buf), f))
117 {
118 Eina_Model *person;
119 char *name, *email;
120
121 if (strlen(buf) <= 1)
122 continue;
123
124 name = strtok(buf, "\t");
125 email = strtok(NULL, "\n");
126
127 if ((!name) || (!email)) continue;
128
129 // Create person
130 person = eina_model_new(PERSON_TYPE);
131
132 // Setup value type as string, as our properties are strings:
133 eina_value_setup(&val, EINA_VALUE_TYPE_STRING);
134
135 // Set string properties:
136 eina_value_set(&val, name);
137 eina_model_property_set(person, "name", &val);
138
139 eina_value_set(&val, email);
140 eina_model_property_set(person, "email", &val);
141
142 // Flush value, free string
143 eina_value_flush(&val);
144
145 // Add person to the end of model children
146 eina_model_child_append(model, person);
147
148 // Model already holds its reference to person, we release ours
149 eina_model_unref(person);
150 }
151
152 fclose(f);
153 return EINA_TRUE;
154}
155
156static void
157address_book_init(void)
158{
159 // Declare type for internal struct, this is just used to easily
160 // create Eina_Value_Struct_Member array for Eina_Value_Struct_Desc.
161 //
162 // We don't need this structure outside address_book_init()
163 // as it is managed automatically by Eina_Value_Struct, used by
164 // Eina_Model_Struct! Handy! :-)
165 typedef struct _Person Person;
166 struct _Person
167 {
168 const char *name;
169 const char *email;
170 };
171 static Eina_Value_Struct_Member person_members[] = {
172 // no eina_value_type as they are not constant initializers, see below.
173 EINA_VALUE_STRUCT_MEMBER(NULL, Person, name),
174 EINA_VALUE_STRUCT_MEMBER(NULL, Person, email)
175 };
176 // Values that cannot be set on static declarations since they are not
177 // constant initializers. It is a nitpick from C that we need to deal with
178 // here and on all our other declarations.
179 person_members[0].type = EINA_VALUE_TYPE_STRING;
180 person_members[1].type = EINA_VALUE_TYPE_STRING;
181
182 static Eina_Value_Struct_Desc person_desc = {
183 EINA_VALUE_STRUCT_DESC_VERSION,
184 NULL, // no special operations
185 person_members,
186 EINA_C_ARRAY_LENGTH(person_members),
187 sizeof(Person)
188 };
189 static Eina_Model_Type person_type = EINA_MODEL_TYPE_INIT_NOPRIVATE
190 ("Person_Type",
191 Eina_Model_Type,
192 NULL, // no type as EINA_MODEL_TYPE_STRUCT is not constant initializer!
193 NULL, // no extra interfaces
194 NULL // no extra events);
195 );
196 person_type.parent = EINA_MODEL_TYPE_STRUCT;
197 // Set our overloaded methods:
198 person_type.constructor = _person_constructor;
199
200 typedef struct _Address_Book Address_Book;
201 struct _Address_Book
202 {
203 const char *filename;
204 };
205 static Eina_Value_Struct_Member address_book_members[] = {
206 // no eina_value_type as they are not constant initializers, see below.
207 EINA_VALUE_STRUCT_MEMBER(NULL, Address_Book, filename)
208 };
209 address_book_members[0].type = EINA_VALUE_TYPE_STRING;
210 static Eina_Value_Struct_Desc address_book_desc = {
211 EINA_VALUE_STRUCT_DESC_VERSION,
212 NULL, // no special operations
213 address_book_members,
214 EINA_C_ARRAY_LENGTH(address_book_members),
215 sizeof(Address_Book)
216 };
217 static Eina_Model_Type address_book_type = EINA_MODEL_TYPE_INIT_NOPRIVATE
218 ("Address_Book_Type",
219 Eina_Model_Type,
220 NULL, // no type as EINA_MODEL_TYPE_STRUCT is not constant initializer!
221 NULL, // no extra interfaces
222 NULL // no extra events);
223 );
224 address_book_type.parent = EINA_MODEL_TYPE_STRUCT;
225 // Set our overloaded methods:
226 address_book_type.constructor = _address_book_constructor;
227 address_book_type.load = _address_book_load;
228
229 // Expose the configured pointers to public usage:
230 // NOTE: they are static, so they live after this function returns!
231 PERSON_TYPE = &person_type;
232 PERSON_DESC = &person_desc;
233
234 ADDRESS_BOOK_TYPE = &address_book_type;
235 ADDRESS_BOOK_DESC = &address_book_desc;
236}
diff --git a/libraries/eina/src/examples/eina_model_04_animal.c b/libraries/eina/src/examples/eina_model_04_animal.c
new file mode 100644
index 0000000..bc9f06b
--- /dev/null
+++ b/libraries/eina/src/examples/eina_model_04_animal.c
@@ -0,0 +1,76 @@
1/*
2 * animal.c
3 */
4
5#include "eina_model_04_animal.h"
6
7static Eina_Bool initialized = EINA_FALSE;
8
9static void
10_animal_eat(Eina_Model *m)
11{
12 printf("%s\t%s", eina_model_type_name_get(eina_model_type_get(m)),
13 __func__);
14 printf("\t\t Eat Animal\n");
15}
16
17static void
18_animal_breathe(Eina_Model *m)
19{
20 printf("%s\t%s", eina_model_type_name_get(eina_model_type_get(m)),
21 __func__);
22 printf("\t\t Breathe Animal\n");
23}
24
25const char *ANIMAL_MODEL_TYPE_NAME = NULL;
26static Animal_Type _ANIMAL_TYPE;
27
28const Eina_Model_Type * const ANIMAL_TYPE = (Eina_Model_Type *) &_ANIMAL_TYPE;
29
30void
31animal_init(void)
32{
33 Eina_Model_Type *type;
34
35 if (initialized) return;
36 initialized = EINA_TRUE;
37
38 ANIMAL_MODEL_TYPE_NAME = "Animal_Model_Type";
39
40 type = (Eina_Model_Type *)&_ANIMAL_TYPE;
41 type->version = EINA_MODEL_TYPE_VERSION;
42 type->name = ANIMAL_MODEL_TYPE_NAME;
43 type->private_size = 0;
44
45 eina_model_type_subclass_setup(type, EINA_MODEL_TYPE_GENERIC);
46
47 /* define extra methods */
48
49 type->type_size = sizeof(Animal_Type);
50 ANIMAL_TYPE(type)->breathe = _animal_breathe;
51 ANIMAL_TYPE(type)->eat = _animal_eat;
52}
53
54void
55animal_breathe(Eina_Model *m)
56{
57 EINA_SAFETY_ON_FALSE_RETURN(eina_model_instance_check(m, ANIMAL_TYPE));
58
59 void (*pf)(Eina_Model *m);
60 pf = eina_model_method_resolve(m, Animal_Type, breathe);
61 EINA_SAFETY_ON_NULL_RETURN(pf);
62 printf("%s() \t", __func__);
63 pf(m);
64}
65
66void
67animal_eat(Eina_Model *m)
68{
69 EINA_SAFETY_ON_FALSE_RETURN(eina_model_instance_check(m, ANIMAL_TYPE));
70
71 void (*pf)(Eina_Model *m);
72 pf = eina_model_method_resolve(m, Animal_Type, eat);
73 EINA_SAFETY_ON_NULL_RETURN(pf);
74 printf("%s() \t", __func__);
75 pf(m);
76}
diff --git a/libraries/eina/src/examples/eina_model_04_child.c b/libraries/eina/src/examples/eina_model_04_child.c
new file mode 100644
index 0000000..59b8aa5
--- /dev/null
+++ b/libraries/eina/src/examples/eina_model_04_child.c
@@ -0,0 +1,81 @@
1/*
2 * child.c
3 */
4
5#include "eina_model_04_child.h"
6#include "eina_model_04_whistler.h"
7
8static Eina_Bool initialized = EINA_FALSE;
9
10static void
11_child_cry(Eina_Model *m)
12{
13 printf("%s\t%s", eina_model_type_name_get(eina_model_type_get(m)),
14 __func__);
15 printf("\t\t Cry Child\n");
16}
17
18static void
19_child_dive(Eina_Model *m)
20{
21 printf("%s\t%s", eina_model_type_name_get(eina_model_type_get(m)),
22 __func__);
23 printf("\t\t Dive Child\n");
24}
25
26const char *CHILD_MODEL_TYPE_NAME = NULL;
27
28static Child_Type _CHILD_TYPE;
29const Eina_Model_Type * const CHILD_TYPE = (Eina_Model_Type *) &_CHILD_TYPE;
30
31static const Diver_Interface _DIVER_INTERFACE;
32static const Eina_Model_Interface * const DIVER_INTERFACE =
33 (Eina_Model_Interface *) &_DIVER_INTERFACE;
34
35static const Eina_Model_Interface * CLASS_INTERFACE_ARRAY[] =
36 { &_DIVER_INTERFACE.base_interface, NULL }; //this array is for model
37
38void
39child_init()
40{
41 Eina_Model_Type *type;
42
43 if (initialized) return;
44 initialized = EINA_TRUE;
45
46 human_init();
47
48 //overriding Diver Interface
49 Eina_Model_Interface * iface = (Eina_Model_Interface *) &_DIVER_INTERFACE;
50 iface->version = EINA_MODEL_INTERFACE_VERSION;
51 iface->interface_size = sizeof(Diver_Interface);
52 iface->name = DIVER_INTERFACE_NAME;
53 DIVER_INTERFACE(iface)->dive = _child_dive;
54
55 //creating instance of Child type
56 CHILD_MODEL_TYPE_NAME = "Child_Model_Type";
57
58 type = (Eina_Model_Type *) &_CHILD_TYPE;
59 type->version = EINA_MODEL_TYPE_VERSION;
60 type->name = CHILD_MODEL_TYPE_NAME;
61
62 eina_model_type_subclass_setup(type, HUMAN_TYPE);
63
64 type->type_size = sizeof(Child_Type);
65 type->interfaces = CLASS_INTERFACE_ARRAY;
66
67 CHILD_TYPE(type)->cry = _child_cry;
68}
69
70//call for implemented Child Class function
71void
72child_cry(Eina_Model *m)
73{
74 EINA_SAFETY_ON_FALSE_RETURN(eina_model_instance_check(m, CHILD_TYPE));
75
76 void (*pf)(Eina_Model *m);
77 pf = eina_model_method_resolve(m, Child_Type, cry);
78 EINA_SAFETY_ON_NULL_RETURN(pf);
79 printf("%s() \t\t", __func__);
80 pf(m);
81}
diff --git a/libraries/eina/src/examples/eina_model_04_human.c b/libraries/eina/src/examples/eina_model_04_human.c
new file mode 100644
index 0000000..d9a10ab
--- /dev/null
+++ b/libraries/eina/src/examples/eina_model_04_human.c
@@ -0,0 +1,157 @@
1/*
2 * human.c
3 *
4 */
5
6#include "eina_model_04_human.h"
7#include "eina_model_04_whistler.h"
8
9static Eina_Bool initialized = EINA_FALSE;
10
11static void
12_human_eat(Eina_Model *m)
13{
14 printf("%s\t%s", eina_model_type_name_get(eina_model_type_get(m)),
15 __func__);
16 printf("\t\t Salad\n");
17}
18
19static void
20_human_walk(Eina_Model *m)
21{
22 printf("%s\t%s", eina_model_type_name_get(eina_model_type_get(m)),
23 __func__);
24 printf("\t\t Walk\n");
25}
26
27static void
28_human_whistle(Eina_Model *m)
29{
30 printf("%s\t%s", eina_model_type_name_get(eina_model_type_get(m)),
31 __func__);
32 printf("\t\t Whistle Human\n");
33}
34
35static void
36_human_swim(Eina_Model *m)
37{
38 printf("%s\t%s", eina_model_type_name_get(eina_model_type_get(m)),
39 __func__);
40 printf("\t\t Swim Human\n");
41}
42
43static void
44_human_dive(Eina_Model *m)
45{
46 printf("%s\t%s", eina_model_type_name_get(eina_model_type_get(m)),
47 __func__);
48 printf("\t\t Dive Human\n");
49}
50/*
51 * defining Human Model Instance
52 * defining Whistler Interface instance
53 * defining Swimmer Interface instance
54 * defining Diver Interface instance
55 */
56
57const char *HUMAN_MODEL_TYPE_NAME = NULL;
58
59static Human_Type _HUMAN_TYPE;
60const Eina_Model_Type * const HUMAN_TYPE = (Eina_Model_Type *) &_HUMAN_TYPE;
61
62static const Whistler_Interface _WHISTLER_INTERFACE;
63static const Eina_Model_Interface * const WHISTLER_INTERFACE =
64 (Eina_Model_Interface *) &_WHISTLER_INTERFACE;
65
66static const Swimmer_Interface _SWIMMER_INTERFACE;
67static const Eina_Model_Interface * const SWIMMER_INTERFACE =
68 (Eina_Model_Interface *) &_SWIMMER_INTERFACE;
69
70static const Diver_Interface _DIVER_INTERFACE;
71static const Eina_Model_Interface * const DIVER_INTERFACE =
72 (Eina_Model_Interface *) &_DIVER_INTERFACE;
73
74/*
75 * defining parent interfaces for Diver Interface instance
76 * defining Interfaces for Human Model instance
77 */
78static const Eina_Model_Interface * PARENT_INTERFACES_ARRAY[] =
79 { &_SWIMMER_INTERFACE.base_interface, NULL }; //this array is for model
80static const Eina_Model_Interface * MODEL_INTERFACES_ARRAY[] =
81 { &_WHISTLER_INTERFACE.base_interface, &_DIVER_INTERFACE.base_interface,
82 NULL }; //this array is for model
83
84void
85human_init()
86{
87 Eina_Model_Type *type;
88
89 if (initialized) return;
90 initialized = EINA_TRUE;
91
92 animal_init();
93
94 /*
95 * Initializing Whistler Interface Instance
96 */
97 Eina_Model_Interface *iface = (Eina_Model_Interface *) &_WHISTLER_INTERFACE;
98 iface->version = EINA_MODEL_INTERFACE_VERSION;
99 iface->interface_size = sizeof(Whistler_Interface);
100 iface->name = WHISTLER_INTERFACE_NAME;
101 WHISTLER_INTERFACE(iface)->whistle = _human_whistle;
102
103 /*
104 * Initializing Swimmer Interface Instance
105 */
106 iface = (Eina_Model_Interface *) &_SWIMMER_INTERFACE;
107 iface->version = EINA_MODEL_INTERFACE_VERSION;
108 iface->interface_size = sizeof(Swimmer_Interface);
109 iface->name = SWIMMER_INTERFACE_NAME;
110 SWIMMER_INTERFACE(iface)->swim = _human_swim;
111
112 /*
113 * Initializing Diver Interface Instance
114 * Diver_Interface is inherited from Swimmer
115 */
116 iface = (Eina_Model_Interface *) &_DIVER_INTERFACE;
117 iface->version = EINA_MODEL_INTERFACE_VERSION;
118 iface->interface_size = sizeof(Diver_Interface);
119 iface->name = DIVER_INTERFACE_NAME;
120 iface->interfaces = PARENT_INTERFACES_ARRAY;
121 DIVER_INTERFACE(iface)->dive = _human_dive;
122
123 /*
124 * Initializing instance of Human Model
125 */
126
127 HUMAN_MODEL_TYPE_NAME = "Human_Model_Type";
128
129 type = (Eina_Model_Type *) &_HUMAN_TYPE;
130 type->version = EINA_MODEL_TYPE_VERSION;
131 type->name = HUMAN_MODEL_TYPE_NAME;
132 type->private_size = 0;
133
134 eina_model_type_subclass_setup(type, ANIMAL_TYPE);
135
136 type->type_size = sizeof(Human_Type);
137 type->interfaces = MODEL_INTERFACES_ARRAY;
138
139 ANIMAL_TYPE(type)->eat = _human_eat;
140 HUMAN_TYPE(type)->walk =_human_walk;
141}
142
143
144/*
145 * call for implemented Human Class function
146 */
147void
148human_walk(Eina_Model *m)
149{
150 EINA_SAFETY_ON_FALSE_RETURN(eina_model_instance_check(m, HUMAN_TYPE));
151
152 void (*pf)(Eina_Model *m);
153 pf = eina_model_method_resolve(m, Human_Type, walk);
154 EINA_SAFETY_ON_NULL_RETURN(pf);
155 printf("%s() \t", __func__);
156 pf(m);
157}
diff --git a/libraries/eina/src/examples/eina_model_04_main.c b/libraries/eina/src/examples/eina_model_04_main.c
new file mode 100644
index 0000000..0e419ec
--- /dev/null
+++ b/libraries/eina/src/examples/eina_model_04_main.c
@@ -0,0 +1,110 @@
1/*
2 * main_animal.c
3 * compile with: gcc eina_model_04_*.c -o eina_model_04 `pkg-config --cflags --libs eina`
4 */
5
6/*
7 * This example demonstrates the extended usage of Eina Model.
8 * Class inheritance and interface implementation
9 *
10 * Animal Class is inherited from BaseClass and implements
11 * "_breathe_animal()" and "_eat_animal()" methods.
12 *
13 * Human Class is inherited from Animal class.
14 * Parrot Class is inherited from Animal class.
15 *
16 * Child Class is inherited from Human class.
17 *
18 * Human Class and Parrot Class implement Whistler Interface.
19 * Human Class implements Diver Interface. Diver Interface inherited from Swimmer Interface
20 *
21 *
22 * Animal Class (inherited from Base Class)
23 * + _breathe_animal()
24 * + _eat_animal()
25 * / -------/ \-------------\
26 * / \
27 * Human Class Parrot Class
28 * inherits inherits
29 * + animal_breathe() + animal_breathe()
30 * overrides overrides
31 * + animal_eat(); + animal_eat();
32 * implements implements
33 * + human_walk(); + parrot_fly();
34 *
35 * implements Whistler, Swimmer, implements Whistler,
36 * Diver Interfaces: + whistler_whistle()
37 * + whistler_whistle()
38 * + swimmer_swim()
39 * + diver_dive()
40 *
41 * ----------------------------------------------------------
42 * | Swim_Interface |
43 * | + swim() |
44 * | | |
45 * | | |
46 * | Dive Intarface (inherited from Swim Interface) |
47 * | + dive() |
48 * ---------------------------------------------------------
49 * |
50 * |
51 * Child Class
52 * + inherits all parent's methods
53 * + implements cry_child()
54 * + overrides dive() interface method
55 */
56
57#include <Eina.h>
58#include "eina_model_04_human.h"
59#include "eina_model_04_parrot.h"
60#include "eina_model_04_child.h"
61#include "eina_model_04_whistler.h"
62
63int
64main()
65{
66 Eina_Model *h, *p, *c;
67
68 eina_init();
69
70 human_init();
71 parrot_init();
72 child_init();
73
74 h = eina_model_new(HUMAN_TYPE);
75 p = eina_model_new(PARROT_TYPE);
76 c = eina_model_new(CHILD_TYPE);
77
78 animal_breathe(p);
79 animal_eat(p);
80 parrot_fly(p);
81 whistler_whistle(p);
82
83 printf("\n");
84 animal_breathe(h);
85 animal_eat(h);
86 human_walk(h);
87 whistler_whistle(h);
88 swimmer_swim(h);
89 diver_dive(h);
90
91 printf("\n");
92 animal_breathe(c);
93 animal_eat(c);
94 human_walk(c);
95 whistler_whistle(c);
96 swimmer_swim(c);
97 diver_dive(c);
98 child_cry(c);
99
100 eina_model_unref(c);
101 eina_model_unref(h);
102 eina_model_unref(p);
103
104 eina_shutdown();
105
106 return 0;
107}
108
109
110
diff --git a/libraries/eina/src/examples/eina_model_04_parrot.c b/libraries/eina/src/examples/eina_model_04_parrot.c
new file mode 100644
index 0000000..ac619ee
--- /dev/null
+++ b/libraries/eina/src/examples/eina_model_04_parrot.c
@@ -0,0 +1,95 @@
1/*
2 * parrot.c
3 */
4
5#include "eina_model_04_parrot.h"
6#include "eina_model_04_whistler.h"
7
8static Eina_Bool initialized = EINA_FALSE;
9
10static void
11_parrot_fly(Eina_Model *m)
12{
13 printf("%s\t%s", eina_model_type_name_get(eina_model_type_get(m)),
14 __func__);
15 printf("\t\t Fly Parrot\n");
16}
17
18static void
19_parrot_eat(Eina_Model *m)
20{
21 printf("%s\t%s", eina_model_type_name_get(eina_model_type_get(m)),
22 __func__);
23 printf("\t\t Grain \n");
24}
25
26static void
27_parrot_whistle(Eina_Model *m)
28{
29 printf("%s\t%s", eina_model_type_name_get(eina_model_type_get(m)),
30 __func__);
31 printf("\t\t Whistle Parrot\n");
32}
33
34/*
35 * defining Parrot Model Instance
36 * defining Whistler Interface instance
37 */
38const char *PARROT_MODEL_TYPE_NAME = NULL;
39
40static Parrot_Type _PARROT_TYPE;
41const Eina_Model_Type * const PARROT_TYPE = (Eina_Model_Type *) &_PARROT_TYPE;
42
43static const Whistler_Interface _WHISTLER_INTERFACE;
44static const Eina_Model_Interface * const WHISTLER_INTERFACE =
45 (Eina_Model_Interface *) &_WHISTLER_INTERFACE;
46
47static const Eina_Model_Interface * MODEL_INTERFACES_ARRAY[] =
48 { &_WHISTLER_INTERFACE.base_interface, NULL }; //this array is for model
49
50void
51parrot_init()
52{
53 Eina_Model_Type *type;
54 if (initialized) return;
55 initialized = EINA_TRUE;
56
57 animal_init();
58 /*
59 *overriding Whistler Interface (creating instance of Whistler Interface)
60 */
61 Eina_Model_Interface *iface = (Eina_Model_Interface *) &_WHISTLER_INTERFACE;
62 iface->version = EINA_MODEL_INTERFACE_VERSION;
63 iface->interface_size = sizeof(Whistler_Interface);
64 iface->name = WHISTLER_INTERFACE_NAME;
65 WHISTLER_INTERFACE(iface)->whistle = _parrot_whistle;
66
67 PARROT_MODEL_TYPE_NAME = "Parrot_Model_Type";
68
69 type = (Eina_Model_Type *)&_PARROT_TYPE;
70 type->version = EINA_MODEL_TYPE_VERSION;
71 type->name = PARROT_MODEL_TYPE_NAME;
72 type->private_size = 0;
73
74 eina_model_type_subclass_setup(type, ANIMAL_TYPE);
75
76 type->type_size = sizeof(Parrot_Type);
77 type->interfaces = MODEL_INTERFACES_ARRAY;
78
79 ANIMAL_TYPE(type)->eat = _parrot_eat;
80 PARROT_TYPE(type)->fly = _parrot_fly;
81}
82
83
84void
85parrot_fly(Eina_Model *m)
86{
87 EINA_SAFETY_ON_FALSE_RETURN(eina_model_instance_check(m, PARROT_TYPE));
88
89 void (*pf)(Eina_Model *m);
90 pf = eina_model_method_resolve(m, Parrot_Type, fly);
91 EINA_SAFETY_ON_NULL_RETURN(pf);
92 printf("%s() \t", __func__);
93 pf(m);
94}
95
diff --git a/libraries/eina/src/examples/eina_model_04_whistler.c b/libraries/eina/src/examples/eina_model_04_whistler.c
new file mode 100644
index 0000000..ed9832f
--- /dev/null
+++ b/libraries/eina/src/examples/eina_model_04_whistler.c
@@ -0,0 +1,59 @@
1/*
2 * whistler.c
3 *
4 */
5
6#include "eina_model_04_whistler.h"
7
8void
9whistler_whistle(Eina_Model *m)
10{
11 const Eina_Model_Interface *iface = NULL;
12 iface = eina_model_interface_get(m, WHISTLER_INTERFACE_NAME);
13
14 EINA_SAFETY_ON_NULL_RETURN(iface);
15
16 void (*pf)(Eina_Model *);
17
18 pf = eina_model_interface_method_resolve(iface, m, Whistler_Interface, whistle);
19 EINA_SAFETY_ON_NULL_RETURN(pf);
20 printf("%s() \t", __func__);
21 pf(m);
22}
23/*
24 * call for overridden Swimmer Interface function
25 */
26void
27swimmer_swim(Eina_Model *m)
28{
29 const Eina_Model_Interface *iface = NULL;
30 iface = eina_model_interface_get(m, SWIMMER_INTERFACE_NAME);
31
32 EINA_SAFETY_ON_NULL_RETURN(iface);
33
34 void (*pf)(Eina_Model *);
35
36 pf = eina_model_interface_method_resolve(iface, m, Swimmer_Interface, swim);
37 EINA_SAFETY_ON_NULL_RETURN(pf);
38 printf("%s() \t", __func__);
39 pf(m);
40}
41
42/*
43 * call for overridden Diver Interface function
44 */
45void
46diver_dive(Eina_Model *m)
47{
48 const Eina_Model_Interface *iface = NULL;
49 iface = eina_model_interface_get(m, DIVER_INTERFACE_NAME);
50
51 EINA_SAFETY_ON_NULL_RETURN(iface);
52
53 void (*pf)(Eina_Model *);
54
55 pf = eina_model_interface_method_resolve(iface, m, Diver_Interface, dive);
56 EINA_SAFETY_ON_NULL_RETURN(pf);
57 printf("%s() \t", __func__);
58 pf(m);
59}
diff --git a/libraries/eina/src/examples/eina_value_01.c b/libraries/eina/src/examples/eina_value_01.c
new file mode 100644
index 0000000..8a20828
--- /dev/null
+++ b/libraries/eina/src/examples/eina_value_01.c
@@ -0,0 +1,53 @@
1//Compile with:
2//gcc eina_value_01.c -o eina_value_01 `pkg-config --cflags --libs eina`
3
4#include <Eina.h>
5
6int main(int argc, char **argv)
7{
8 Eina_Value v;
9 int i;
10 char *newstr;
11
12 eina_init();
13
14 eina_value_setup(&v, EINA_VALUE_TYPE_INT);
15 eina_value_set(&v, 123);
16 eina_value_get(&v, &i);
17 printf("v=%d\n", i);
18
19 newstr = eina_value_to_string(&v);
20 printf("v as string: %s\n", newstr);
21 free(newstr); // it was allocated by eina_value_to_string()
22 eina_value_flush(&v); // destroy v contents, will not use anymore
23
24 const char *s;
25 eina_value_setup(&v, EINA_VALUE_TYPE_STRING);
26 eina_value_set(&v, "My string");
27 eina_value_get(&v, &s);
28 printf("v=%s (pointer: %p)\n", s, s);
29
30 newstr = eina_value_to_string(&v);
31 printf("v as string: %s (pointer: %p)\n", newstr, newstr);
32 free(newstr); // it was allocated by eina_value_to_string()
33 eina_value_flush(&v); // destroy v contents, string 's' is not valid anymore!
34
35 Eina_Value otherv;
36 eina_value_setup(&otherv, EINA_VALUE_TYPE_STRING);
37 eina_value_setup(&v, EINA_VALUE_TYPE_INT);
38
39 // convert from int to string:
40 eina_value_set(&v, 123);
41 eina_value_convert(&v, &otherv);
42 eina_value_get(&otherv, &s);
43 printf("otherv=%s\n", s);
44
45 // and the other way around!
46 eina_value_set(&otherv, "33");
47 eina_value_convert(&otherv, &v);
48 eina_value_get(&v, &i);
49 printf("v=%d\n", i);
50
51 eina_value_flush(&otherv);
52 eina_value_flush(&v);
53}
diff --git a/libraries/eina/src/examples/eina_value_02.c b/libraries/eina/src/examples/eina_value_02.c
new file mode 100644
index 0000000..9c659ec
--- /dev/null
+++ b/libraries/eina/src/examples/eina_value_02.c
@@ -0,0 +1,100 @@
1//Compile with:
2//gcc eina_value_02.c -o eina_value_02 `pkg-config --cflags --libs eina`
3
4#include <Eina.h>
5
6static Eina_Value_Struct_Desc *V1_DESC = NULL;
7static Eina_Value_Struct_Desc *V2_DESC = NULL;
8
9void value_init(void)
10{
11 typedef struct _My_Struct_V1 {
12 int param1;
13 char param2;
14 } My_Struct_V1;
15
16
17 static Eina_Value_Struct_Member v1_members[] = {
18 // no eina_value_type as they are not constant initializers, see below.
19 EINA_VALUE_STRUCT_MEMBER(NULL, My_Struct_V1, param1),
20 EINA_VALUE_STRUCT_MEMBER(NULL, My_Struct_V1, param2)
21 };
22 v1_members[0].type = EINA_VALUE_TYPE_INT;
23 v1_members[1].type = EINA_VALUE_TYPE_CHAR;
24 static Eina_Value_Struct_Desc v1_desc = {
25 EINA_VALUE_STRUCT_DESC_VERSION,
26 NULL, // no special operations
27 v1_members,
28 EINA_C_ARRAY_LENGTH(v1_members),
29 sizeof(My_Struct_V1)
30 };
31 V1_DESC = &v1_desc;
32
33 typedef struct _My_Struct_V2 {
34 int param1;
35 char param2;
36 int param3;
37 } My_Struct_V2;
38 static Eina_Value_Struct_Member v2_members[] = {
39 // no eina_value_type as they are not constant initializers, see below.
40 EINA_VALUE_STRUCT_MEMBER(NULL, My_Struct_V2, param1),
41 EINA_VALUE_STRUCT_MEMBER(NULL, My_Struct_V2, param2),
42 EINA_VALUE_STRUCT_MEMBER(NULL, My_Struct_V2, param3)
43 };
44 v2_members[0].type = EINA_VALUE_TYPE_INT;
45 v2_members[1].type = EINA_VALUE_TYPE_CHAR;
46 v2_members[2].type = EINA_VALUE_TYPE_INT;
47 static Eina_Value_Struct_Desc v2_desc = {
48 EINA_VALUE_STRUCT_DESC_VERSION,
49 NULL, // no special operations
50 v2_members,
51 EINA_C_ARRAY_LENGTH(v2_members),
52 sizeof(My_Struct_V2)
53 };
54 V2_DESC = &v2_desc;
55}
56
57void rand_init(Eina_Value *v)
58{
59 if (v->type != EINA_VALUE_TYPE_STRUCT)
60 return;
61
62 eina_value_struct_set(v, "param1", rand());
63 eina_value_struct_set(v, "param2", rand() % 256);
64 eina_value_struct_set(v, "param3", rand());
65}
66
67void my_struct_use(Eina_Value *params)
68{
69 int p1, p3;
70 char p2;
71
72 eina_value_struct_get(params, "param1", &p1);
73 eina_value_struct_get(params, "param2", &p2);
74 printf("param1: %d\nparam2: %c\n", p1, p2);
75
76 if (eina_value_struct_get(params, "param3", &p3))
77 printf("param3: %d\n", p3);
78}
79
80int main(int argc, char **argv)
81{
82 Eina_Value *v1, *v2;
83
84 eina_init();
85 value_init();
86 srand(time(NULL));
87
88 v1 = eina_value_struct_new(V1_DESC);
89 v2 = eina_value_struct_new(V2_DESC);
90
91 rand_init(v1);
92 my_struct_use(v1);
93
94 rand_init(v2);
95 my_struct_use(v2);
96
97 eina_value_free(v1);
98 eina_value_free(v2);
99 eina_shutdown();
100}
diff --git a/libraries/eina/src/examples/eina_value_03.c b/libraries/eina/src/examples/eina_value_03.c
new file mode 100644
index 0000000..85f42b3
--- /dev/null
+++ b/libraries/eina/src/examples/eina_value_03.c
@@ -0,0 +1,178 @@
1//Compile with:
2//gcc eina_value_03.c -o eina_value_03 `pkg-config --cflags --libs eina`
3
4#include <Eina.h>
5#include <sys/time.h>
6
7static Eina_Bool
8_tz_setup(const Eina_Value_Type *type, void *mem)
9{
10 memset(mem, 0, type->value_size);
11 return EINA_TRUE;
12}
13
14static Eina_Bool
15_tz_flush(const Eina_Value_Type *type, void *mem)
16{
17 return EINA_TRUE;
18}
19
20static Eina_Bool
21_tz_copy(const Eina_Value_Type *type, const void *src, void * dst)
22{
23 struct timezone *tzsrc = src;
24 struct timezone *tzdst = dst;
25 *tzdst = *tzsrc;
26 return EINA_TRUE;
27}
28
29static Eina_Bool
30_tz_compare(const Eina_Value_Type *type, const void *a, const void *b)
31{
32 struct timezone tza = *(struct timezone*)a;
33 struct timezone tzb = *(struct timezone*)b;
34
35 if (tza.tz_minuteswest < tzb.tz_minuteswest)
36 return -1;
37 else if (tza.tz_minuteswest > tzb.tz_minuteswest)
38 return 1;
39 return 0;
40}
41
42static Eina_Bool
43_tz_pset(const Eina_Value_Type *type, void *mem, const void *ptr)
44{
45 *(struct timezone*)mem = *(struct timezone*)ptr;
46 return EINA_TRUE;
47}
48
49static Eina_Bool
50_tz_vset(const Eina_Value_Type *type, void *mem, va_list args)
51{
52 const struct timezone tz = va_arg(args, struct timezone);
53 return _tz_pset(type, mem, &tz);
54}
55
56static Eina_Bool
57_tz_pget(const Eina_Value_Type *type, const void *mem, void *ptr)
58{
59 memcpy(ptr, mem, type->value_size);
60 return EINA_TRUE;
61}
62
63static Eina_Bool
64_tz_convert_to(const Eina_Value_Type *type, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
65{
66 struct timezone v = *(struct timezone*)type_mem;
67
68 eina_error_set(0);
69
70 if (convert == EINA_VALUE_TYPE_UCHAR)
71 {
72 unsigned char other_mem = v.tz_minuteswest;
73 return eina_value_type_pset(convert, convert_mem, &other_mem);
74 }
75 else if (convert == EINA_VALUE_TYPE_USHORT)
76 {
77 unsigned short other_mem = v.tz_minuteswest;
78 return eina_value_type_pset(convert, convert_mem, &other_mem);
79 }
80 else if (convert == EINA_VALUE_TYPE_UINT)
81 {
82 unsigned int other_mem = v.tz_minuteswest;
83 return eina_value_type_pset(convert, convert_mem, &other_mem);
84 }
85 else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP))
86 {
87 unsigned long other_mem = v.tz_minuteswest;
88 return eina_value_type_pset(convert, convert_mem, &other_mem);
89 }
90 else if (convert == EINA_VALUE_TYPE_UINT64)
91 {
92 uint64_t other_mem = v.tz_minuteswest;
93 return eina_value_type_pset(convert, convert_mem, &other_mem);
94 }
95 else if (convert == EINA_VALUE_TYPE_CHAR)
96 {
97 char other_mem = v.tz_minuteswest;
98 return eina_value_type_pset(convert, convert_mem, &other_mem);
99 }
100 else if (convert == EINA_VALUE_TYPE_SHORT)
101 {
102 short other_mem = v.tz_minuteswest;
103 return eina_value_type_pset(convert, convert_mem, &other_mem);
104 }
105 else if (convert == EINA_VALUE_TYPE_INT)
106 {
107 int other_mem = v.tz_minuteswest;
108 return eina_value_type_pset(convert, convert_mem, &other_mem);
109 }
110 else if (convert == EINA_VALUE_TYPE_LONG)
111 {
112 long other_mem = v.tz_minuteswest;
113 return eina_value_type_pset(convert, convert_mem, &other_mem);
114 }
115 else if (convert == EINA_VALUE_TYPE_INT64)
116 {
117 int64_t other_mem = v.tz_minuteswest;
118 return eina_value_type_pset(convert, convert_mem, &other_mem);
119 }
120 else if (convert == EINA_VALUE_TYPE_FLOAT)
121 return eina_value_type_pset(convert, convert_mem, &v.tz_minuteswest);
122 else if (convert == EINA_VALUE_TYPE_DOUBLE)
123 return eina_value_type_pset(convert, convert_mem, &v.tz_minuteswest);
124 else if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
125 convert == EINA_VALUE_TYPE_STRING)
126 {
127 const char *other_mem;
128 char buf[64];
129 snprintf(buf, sizeof(buf), "%d", v.tz_minuteswest);
130 other_mem = buf; /* required due &buf == buf */
131 return eina_value_type_pset(convert, convert_mem, &other_mem);
132 }
133
134 eina_error_set(EINA_ERROR_VALUE_FAILED);
135 return EINA_FALSE;
136}
137
138static Eina_Value_Type TZ_TYPE = {
139 EINA_VALUE_TYPE_VERSION,
140 sizeof(struct timezone),
141 "struct timezone",
142 _tz_setup,
143 _tz_flush,
144 _tz_copy,
145 _tz_compare,
146 _tz_convert_to,
147 NULL, //No convert from
148 _tz_vset,
149 _tz_pset,
150 _tz_pget
151};
152
153int main(int argc, char **argv)
154{
155 Eina_Value vtv, vtz;
156 struct timeval tv;
157 struct timezone tz;
158 char *s;
159
160 eina_init();
161
162 eina_value_setup(&vtv, EINA_VALUE_TYPE_TIMEVAL);
163 eina_value_setup(&vtz, &TZ_TYPE);
164
165 gettimeofday(&tv, &tz);
166 eina_value_set(&vtv, tv);
167 eina_value_set(&vtz, tz);
168
169 s = eina_value_to_string(&vtv);
170 printf("time: %s\n", s);
171 free(s);
172 s = eina_value_to_string(&vtz);
173 printf("timezone: %s\n", s);
174 free(s);
175
176 eina_value_flush(&vtz);
177 eina_value_flush(&vtv);
178}
diff --git a/libraries/eina/src/include/eina_model.h b/libraries/eina/src/include/eina_model.h
new file mode 100644
index 0000000..0a1566e
--- /dev/null
+++ b/libraries/eina/src/include/eina_model.h
@@ -0,0 +1,3105 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2012 ProFUSION embedded systems
3 *
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.
8 *
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.
13 *
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/>.
17 */
18
19#ifndef EINA_MODEL_H_
20#define EINA_MODEL_H_
21
22#include "eina_types.h"
23#include "eina_value.h"
24#include "eina_inlist.h"
25#include <stdarg.h>
26
27/**
28 * @page eina_model_01_c Eina_Model inheritance and function overriding
29 * @include eina_model_01.c
30 */
31
32/**
33 * @page eina_model_04_c Eina_Model inheritance, interfaces, and function overriding
34 * @include eina_model_04_main.c
35 * @include eina_model_04_animal.c
36 * @include eina_model_04_human.c
37 * @include eina_model_04_parrot.c
38 * @include eina_model_04_child.c
39 * @include eina_model_04_main.c
40 * @include eina_model_04_whistler.c
41 * @include eina_model_04_animal.h
42 * @include eina_model_04_human.h
43 * @include eina_model_04_whistler.h
44 * @include eina_model_04_child.h
45 * @include eina_model_04_parrot.h
46 */
47
48/**
49 * @page eina_model_02_example_page Creating a simple model
50 * @dontinclude eina_model_02.c
51 *
52 * This example shows the creation of a model with five properties, named:
53 * 'a', 'b', 'c', 'd' and 'e' with values 0, 1, 2, 3 and 4
54 * respectively. In addition to the 5 properties our model also add 5 children,
55 * and to each child we give a property named 'x' with a value of 1, 2, 3, 4 and
56 * 5.
57 *
58 * In other words this piece of code shows how to use eina_model to store a list
59 * of elements, given that the list itself has some properties.
60 *
61 * Now let's walk through the code and examine the interesting bits.
62 *
63 * This is some pretty standard initialization code.
64 * @until eina_init
65 *
66 * We now create our eina_model, the important detail here is the type of the
67 * model being created, for this example we use the generic type provided by
68 * eina:
69 * @until model_new
70 *
71 * Once our model has been created we can add callbacks to be notified of events
72 * that happen to our model, for this example we are just going to add a
73 * callback for the "delete" event. To get a list of events a given eina model
74 * can emit see @ref eina_model_event_names_list_get().
75 * @until callback_add
76 *
77 * Once we have a model, we need to populate it with information. There are two
78 * types of information we can store on an eina model: properties and eina
79 * models. We are going to start by looking at properties.
80 *
81 * Properties are, simply put, named values. They have a char* identifier and an
82 * Eina_Value value. This means you can store in a property almost any type of
83 * data. For this example we are going to add some very simple numeric
84 * properties which will have single letter identifiers.
85 * @until }
86 * @until }
87 *
88 * Despite being able to store almost any value properties the least flexible
89 * information unit we can put in an eina model. We can add eina models to our
90 * eina model, this allows us to represt complex information hierarchies. This
91 * example adds 5 models(with no children of their own) to our parent model @c
92 * m.
93 * @until }
94 * The code here should be pretty easy to understand, we create a model, much
95 * like we did before, and we then add a property to our model, again a task we
96 * have already done.
97 *
98 * The important issue to note here is that we could have given each of our @c c
99 * child models as complex an structure as we needed, they could each be a list
100 * or a tree on their own right.
101 *
102 * Now that we have a populated model we print a string representation of
103 * it(without forgetting to free the string):
104 * @until free
105 *
106 * And since we are done using our model we release our reference to it(and
107 * since no else holds references to it, it will be freed):
108 * @until }
109 *
110 * Note that we don't need to iterate over the children of @c m unrefing it,
111 * this is because we don't hold references to it, we freed our references right
112 * after we added them to their parent model, so when the parent model dies(and
113 * releases the references to it's children) they will be freed.
114 *
115 * The only thing we are going to look at is the callback we registered for
116 * whenever a model is deleted, since our models don't do anything fancy we are
117 * just going to print the memory address of the model being freed.
118 * @until }
119 *
120 * Note that this means the memory address is still valid, our callback is
121 * called just before the memory is freed so we could still access its
122 * information here.
123 *
124 * The full code can be seen in @ref eina_model_02_c
125 */
126
127/**
128 * @page eina_model_02_c eina_model_02.c
129 * @include eina_model_02.c
130 * @example eina_model_02.c
131 */
132
133/**
134 * @page eina_model_03_example_page Using Eina_Model and inheritance
135 * @dontinclude eina_model_03.c
136 *
137 * This example will use two custom defined eina model types: @c PERSON_TYPE to
138 * represent a person and @c ADDRESS_BOOK_TYPE to represent the an address book.
139 * Both our types inherit from EINA_MODEL_TYPE_STRUCT, and, therefore,
140 * store it's data on a struct. Our address book will be very simple it will
141 * only contain one property, the name of the file where we store our address
142 * book. The person type will contain two fields a name and en email. Let's look
143 * at the code.
144 *
145 * We'll start with declaring the variables and functions we'll need to define
146 * our custom type. This will all be explained when the variables get used.
147 * @until address_book_init
148 *
149 * We then jump into our @c main function, declare a couple of variables and
150 * initialize eina:
151 * @until eina_init
152 *
153 * After eina is initialized we'll @c address_book_init() which will initialize
154 * both our @c PERSON_TYPE and our @c ADDRESS_BOOK_TYPE. Details of this will be
155 * shown latter on:
156 * @until address_book_init
157 *
158 * Now that everything is correctly initialized we can create the model that
159 * will represent our address book's
160 * @until eina_model_new
161 *
162 * Before we can load data into our model we need to tell it where to load from,
163 * we do this by setting it's filename property:
164 * @until value_flush
165 *
166 * We then load data into our model and display it as a string:
167 * @until free
168 *
169 * While @c eina_model_to_string allows you to see the contents of the model,
170 * it's display format is not user friendly, it's best used for debugging. So
171 * let's now print our model in a user friendly way.
172 *
173 * First we see how many people are in our address book and print that:
174 * @until printf
175 *
176 * And now we iterate over every child of our address book model, which
177 * represents a person:
178 * @until person
179 *
180 * But again simply calling @c eina_model_to_string would result in not very
181 * user friendly output, so we'll need to get the properties of the person(name
182 * and email) and print them with some formatting:
183 * @until printf
184 *
185 * We then free the resources we allocated to print this person:
186 * @until }
187 *
188 * And that's it for our main function, now just freeing our resources:
189 * @until }
190 *
191 * This however obviously doesn't conclude our example we need to examine how
192 * the the loading of data works to really understand what is happening in the
193 * @c main function.
194 *
195 * Let's start with the constructors(and the variables they use). Both our
196 * constructors do two very important tasks:
197 * @li Calls our parent's constructor, and
198 * @li Sets the description of the struct on our model
199 *
200 * For these constructors that's all we need to do since most of our
201 * functionality is provided by @c EINA_MODEL_TYPE_STRUCT.
202 * @until }
203 * @until }
204 *
205 * And now we have our load function, it opens the file from which we'll
206 * read the address book:
207 * @until EINA_SAFETY_ON_NULL_RETURN_VAL
208 *
209 * Once the file has been opened we read from it line by line and for each
210 * non-blank line we get a name and an email:
211 * @until email
212 * @until email
213 *
214 * Once we have the name and email we create our person model, set it's
215 * properties and make our person a child of the address book:
216 * @until }
217 *
218 * And now that we're done reading the file we close it:
219 * @until }
220 *
221 * This next function is perphaps the most interesting one of our example, it's
222 * the one that creates the definition of our derived types.
223 *
224 * First thing we'll do is the description of the members of our person type.
225 * @until person_members[1].type
226 * Now the description of the struct itself(which uses the members):
227 * @until }
228 * And finally we define the person type itself:
229 * @until person_type.constructor
230 *
231 * With the person now described we'll do the same process for our address book
232 * type:
233 * @until address_book_type.load
234 *
235 * So far everything we created has been in the scope of our function to make
236 * this available outside(such as in the @c main function where we use @c
237 * ADDRESS_BOOK_TYPE and on @c _address_book_load function where we use @c
238 * PERSON_TYPE) we need to assign our descriptions and type to global variables:
239 * @until }
240 *
241 * This concludes this example. A good exercise for the reader is to extend this
242 * example to have the model save the addres book, for example once it's
243 * unloaded, this can be done by overriding the .unload property of @c
244 * ADDRESS_BOOK_TYPE.
245 *
246 * For the full code see: @ref eina_model_03_c
247 */
248
249/**
250 * @page eina_model_03_c eina_model_03.c
251 * @include eina_model_03.c
252 * @example eina_model_03.c
253 */
254
255/**
256 * @addtogroup Eina_Data_Types_Group Data Types
257 *
258 * @since 1.2
259 *
260 * @{
261 */
262
263/**
264 * @addtogroup Eina_Containers_Group Containers
265 *
266 * @{
267 */
268
269/**
270 * @defgroup Eina_Model_Group Data Model API
271 *
272 * Abstracts data access to hierarchical data in an efficient way,
273 * extensible to different backing stores such as database or remote
274 * access.
275 *
276 * It is heavily based on #Eina_Value, as properties are exchanged
277 * using this data type as interface, although internally models may
278 * store them as they want. See @ref Eina_Value_Group.
279 *
280 * Although extensible and easy to optimize, a simple generic type is
281 * provided as #EINA_MODEL_TYPE_GENERIC. It is recommended that people
282 * use it during development, get the logic right and just then
283 * optimize what is needed (properties or children management).
284 *
285 * Not as generic as #EINA_MODEL_TYPE_GENERIC, but way more efficient
286 * is #EINA_MODEL_TYPE_STRUCT that instead of a hash of properties of
287 * any type, it uses a struct to map properties. Its properties are
288 * fixed set of names and they have fixed type, as defined by the
289 * #Eina_Value_Struct_Desc description used internally.
290 *
291 * Examples:
292 * @li @ref eina_model_01_c inheritance example, uses #EINA_MODEL_TYPE_GENERIC
293 * @li @ref eina_model_02_example_page contains an easy to follow
294 * example that demonstrates several of the important features of
295 * eina_model, uses #EINA_MODEL_TYPE_GENERIC.
296 * @li @ref eina_model_03_example_page walk-through example on how to
297 * inherit types, a suggestion of eina_model_load() usage and uses
298 * #EINA_MODEL_TYPE_STRUCT.
299 * @li @ref eina_model_04_c Advanced inheritance, interfaces and interface
300 * function overloading example.
301 *
302 * @{
303 */
304
305/**
306 * @var EINA_ERROR_MODEL_FAILED
307 * Defined when model-specific errors happens.
308 */
309EAPI extern Eina_Error EINA_ERROR_MODEL_FAILED;
310
311/**
312 * @var EINA_ERROR_MODEL_METHOD_MISSING
313 * Defined when model-specific errors happens.
314 */
315EAPI extern Eina_Error EINA_ERROR_MODEL_METHOD_MISSING;
316
317/**
318 * @typedef Eina_Model
319 * Data Model Object.
320 *
321 * This is an opaque handle that is created with eina_model_new() and
322 * released with eina_model_unref().
323 *
324 * It contains properties, children and may emit events. See
325 * respectively:
326 * @li eina_model_property_get() and eina_model_property_set()
327 * @li eina_model_child_get() and eina_model_child_set()
328 * @li eina_model_event_names_list_get(), eina_model_event_callback_add() and eina_model_event_callback_del()
329 *
330 * @see eina_model_new()
331 * @see eina_model_ref() and eina_model_xref()
332 * @see eina_model_unref(), eina_model_xunref() and eina_model_del()
333 * @see eina_model_type_get() and eina_model_interface_get()
334 * @since 1.2
335 */
336typedef struct _Eina_Model Eina_Model;
337
338/**
339 * @typedef Eina_Model_Type
340 * Data Model Type.
341 *
342 * @see #_Eina_Model_Type explains fields.
343 * @since 1.2
344 */
345typedef struct _Eina_Model_Type Eina_Model_Type;
346
347/**
348 * @typedef Eina_Model_Interface
349 * Data Model Interface.
350 *
351 * @see #_Eina_Model_Interface explains fields.
352 * @since 1.2
353 */
354typedef struct _Eina_Model_Interface Eina_Model_Interface;
355
356/**
357 * @typedef Eina_Model_Event_Description
358 * Data Model Event Description.
359 *
360 * This is used to declare events supported by types and interfaces
361 * and also to provide introspection to receivers of signals so they
362 * can know which data they are receiving as @c event_info.
363 *
364 * @see EINA_MODEL_EVENT_DESCRIPTION()
365 * @see #EINA_MODEL_EVENT_DESCRIPTION_SENTINEL
366 * @see #_Eina_Model_Event_Description explains fields.
367 * @since 1.2
368 */
369typedef struct _Eina_Model_Event_Description Eina_Model_Event_Description;
370
371/**
372 * @brief Creates a new model of type @a Type.
373 * @param type The type of the model to create.
374 * @return If successfull pointer to model, NULL otherwise.
375 *
376 * @see _Eina_Model_Type
377 * @see eina_model_del()
378 * @since 1.2
379 */
380EAPI Eina_Model *eina_model_new(const Eina_Model_Type *type);
381/**
382 * @brief Frees the memory associated with @a model
383 * @param model The model instance.
384 *
385 * @see eina_model_new()
386 * @since 1.2
387 */
388EAPI void eina_model_del(Eina_Model *model) EINA_ARG_NONNULL(1);
389
390/**
391 * @brief Returns the type of @a model.
392 * @param model The model instance.
393 * @return The type of @a model.
394 *
395 * @see eina_model_new()
396 * @see _Eina_Model_Type
397 * @since 1.2
398 */
399EAPI const Eina_Model_Type *eina_model_type_get(const Eina_Model *model) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT EINA_PURE;
400
401/**
402 * @brief Returns the interface named @a name of @a model.
403 * @param model The model instance.
404 * @param name Name of interface to get.
405 * @return If successfull requested interface, NULL otherwise.
406 *
407 * The name of every interface of @a model will be compared to @a name, the
408 * first one to match will be returned.
409 *
410 * @see eina_model_new()
411 * @see _Eina_Model_Interface
412 * @since 1.2
413 */
414EAPI const Eina_Model_Interface *eina_model_interface_get(const Eina_Model *model,
415 const char *name) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT EINA_PURE;
416
417/**
418 * @brief Increases the refcount of @a model.
419 * @param model The model to increase reference.
420 * @return The @a model with reference increased.
421 * @return If successfull pointer to model, NULL otherwise.
422 *
423 * @see eina_model_new()
424 * @see eina_model_unref()
425 * @since 1.2
426 */
427EAPI Eina_Model *eina_model_ref(Eina_Model *model) EINA_ARG_NONNULL(1);
428
429/**
430 * @brief Increases the refcount of @a model, informs reference identifier.
431 * @param model The model to increase reference.
432 * @param id An identifier to mark this reference.
433 * @param label An optional label to help debug, may be @c NULL.
434 * @return The @a model with reference increased.
435 *
436 * This extended version of reference explicitly marks the origin of
437 * the reference and eina_model_xunref() should be used to check and
438 * remove it.
439 *
440 * Usually the @a id is another object, like a parent object, or some
441 * class/structure/file/function that is holding the reference for
442 * some reason.
443 *
444 * Its purpose is to help debuging if Eina was compiled with model
445 * usage debug enabled and environment variable @c EINA_MODEL_DEBUG=1
446 * is set.
447 *
448 * It is recommended to use eina_model_xref() and eina_model_xunref()
449 * pair whenever you want to be sure you released your
450 * references. Both at your own type, or using applications. As an
451 * example #EINA_MODEL_INTERFACE_CHILDREN_INARRAY will use this to
452 * make sure it deleted every managed children.
453 *
454 * In order to debug leaks, consider using eina_model_xrefs_get() or
455 * eina_models_usage_dump() for a global picture. However, some
456 * references are not tracked, namely:
457 *
458 * @li eina_model_new()
459 * @li eina_model_child_get()
460 * @li eina_model_child_iterator_get()
461 * @li eina_model_child_reversed_iterator_get()
462 * @li eina_model_child_sorted_iterator_get()
463 * @li eina_model_child_filtered_iterator_get()
464 * @li eina_model_child_slice_iterator_get()
465 * @li eina_model_child_slice_reversed_iterator_get()
466 * @li eina_model_child_slice_sorted_iterator_get()
467 * @li eina_model_child_slice_filtered_iterator_get()
468 *
469 * @note this function is slower than eina_model_ref() if
470 * @c EINA_MODEL_DEBUG is set to "1" or "backtrace". Otherwise it
471 * should have the same performance cost.
472 *
473 * @see eina_model_ref()
474 * @see eina_model_xunref()
475 * @since 1.2
476 */
477EAPI Eina_Model *eina_model_xref(Eina_Model *model,
478 const void *id,
479 const char *label) EINA_ARG_NONNULL(1, 2);
480
481/**
482 * @brief Decreases the refcount of @a model.
483 * @param model The model to decrease reference.
484 * @return If successfull pointer to model, NULL otherwise.
485 *
486 * After this function returns, consider @a model pointer invalid.
487 *
488 * @see eina_model_ref()
489 * @see eina_model_del()
490 * @since 1.2
491 */
492EAPI void eina_model_unref(Eina_Model *model) EINA_ARG_NONNULL(1);
493
494/**
495 * @brief Decreases the refcount of @a model, informs reference identifier.
496 * @param model The model to decrease reference.
497 * @param id An identifier to mark this reference.
498 * @return If successfull pointer to model, NULL otherwise.
499 *
500 * This function will match eina_model_xref() and the @a id must match
501 * a previously call, otherwise it will produce an error if @c
502 * EINA_MODEL_DEBUG is set to "1" or "backtrace", and the reference is
503 * not decreased!
504 *
505 * After this function returns, consider @a model pointer invalid.
506 *
507 * @note this function is slower than eina_model_unref() if
508 * @c EINA_MODEL_DEBUG is set to "1" or "backtrace". Otherwise it
509 * should have the same performance cost.
510 *
511 * @see eina_model_xref()
512 * @since 1.2
513 */
514EAPI void eina_model_xunref(Eina_Model *model,
515 const void *id) EINA_ARG_NONNULL(1, 2);
516
517
518
519/**
520 * @defgroup Eina_Model_Event_Group Data Model Events
521 * Events and their usage with models.
522 *
523 * Events are specified by each type and interface level using
524 * #Eina_Model_Event_Description. One can know all events supported by
525 * a model with eina_model_event_names_list_get() and then
526 * eina_model_event_description_get() to retrieve details.
527 *
528 * By default the following events are supported in every object:
529 * @li deleted: last reference was released or eina_model_del() was called.
530 * @li freed: memory was destroyed, destructors were called.
531 * @li property,set: eina_model_property_set() was done.
532 * @li property,deleted: eina_model_property_del() was done.
533 * @li children,changed: children was changed somehow (added, modified, deleted)
534 * @li child,inserted: new child was added (eina_model_child_append() or eina_model_child_insert_at())
535 * @li child,set: child was replaced (eina_model_child_set())
536 * @li child,deleted: eina_model_child_del() was done.
537 * @li loaded: eina_model_load() was done.
538 * @li unloaded: eina_model_unload() was done.
539 *
540 * Mix-in interfaces may emit these:
541 * @li properties,loaded
542 * @li properties,unloaded
543 * @li children,loaded
544 * @li children,unloaded
545 *
546 * One can be notified of events with eina_model_event_callback_add().
547 *
548 * Types emit these events with eina_model_event_callback_call(),
549 * these are handled asynchronously unless event is frozen with
550 * eina_model_event_callback_freeze() is blocking it. In this case the
551 * events are ignored. Usually this is used in some cases that want to
552 * avoid storm of events in batch operations.
553 *
554 * @{
555 */
556
557/**
558 * @typedef Eina_Model_Event_Cb
559 * Notifies of events in this model.
560 *
561 * @since 1.2
562 */
563typedef void (*Eina_Model_Event_Cb)(void *data, Eina_Model *model, const Eina_Model_Event_Description *desc, void *event_info);
564
565/**
566 * @brief Add a callback to be called when @a event_name is emited.
567 * @param model The model instance.
568 * @param event_name The name of event for which @a cb will be called.
569 * @param cb The function to be called.
570 * @param data Data @a cb will be called with. May be NULL.
571 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
572 *
573 * @see eina_model_event_callback_del()
574 * @since 1.2
575 */
576EAPI Eina_Bool eina_model_event_callback_add(Eina_Model *model,
577 const char *event_name,
578 Eina_Model_Event_Cb cb,
579 const void *data) EINA_ARG_NONNULL(1, 2, 3);
580/**
581 * @brief Remove a callback that was to be called when @a event_name was emited.
582 * @param model The model instance.
583 * @param event_name The name of event for which to delete callback.
584 * @param cb The function given to eina_model_event_callback_add().
585 * @param data Data given to eina_model_event_callback_add(). A NULL value means
586 * every @a data will not be compared.
587 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
588 *
589 * @see eina_model_event_callback_add()
590 * @since 1.2
591 */
592EAPI Eina_Bool eina_model_event_callback_del(Eina_Model *model,
593 const char *event_name,
594 Eina_Model_Event_Cb cb,
595 const void *data) EINA_ARG_NONNULL(1, 2, 3);
596
597/**
598 * @brief Returns a description of the event named @c event_name
599 * @param model The model instance.
600 * @param event_name Name of event whose description is wanted.
601 * @return Description of event.
602 *
603 * @see Eina_Model_Event_Description
604 * @since 1.2
605 */
606EAPI const Eina_Model_Event_Description *eina_model_event_description_get(const Eina_Model *model,
607 const char *event_name) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT EINA_PURE;
608
609/**
610 * @brief Returns list of events this model may emit.
611 * @param model The model whose events are to be listed.
612 * @return An Eina_List of stringshares with the name of every event. Free the
613 * list with eina_model_event_names_list_free().
614 *
615 * @since 1.2
616 */
617EAPI Eina_List *eina_model_event_names_list_get(const Eina_Model *model) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
618/**
619 * @brief Frees the list of event's names gotten from
620 * eina_model_event_names_list_get().
621 * @param list The list to free.
622 *
623 * @see eina_model_event_names_list_get()
624 * @since 1.2
625 */
626EAPI void eina_model_event_names_list_free(Eina_List *list);
627
628/**
629 * @brief Calls every callback associated to @a name on model @a model with @a
630 * event_info.
631 * @param model The model instance.
632 * @param name The event whose callbacks will be called.
633 * @param event_info The data given to the callback as event_info. May be NULL.
634 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
635 *
636 * @see eina_model_event_callback_add()
637 * @see eina_model_event_callback_del()
638 * @since 1.2
639 */
640EAPI Eina_Bool eina_model_event_callback_call(Eina_Model *model,
641 const char *name,
642 const void *event_info) EINA_ARG_NONNULL(1, 2);
643
644/**
645 * @brief Makes @a model not call the callbacks associated with @a name.
646 * @param model The model instance.
647 * @param name The event whose callbacks are to be frozen.
648 * @return Count of freezes called on this event.
649 *
650 * @see eina_model_event_callback_call()
651 * @see eina_model_event_callback_thaw()
652 * @since 1.2
653 */
654EAPI int eina_model_event_callback_freeze(Eina_Model *model,
655 const char *name) EINA_ARG_NONNULL(1, 2);
656/**
657 * @brief Makes @a model able to call the callbacks associated with @a name.
658 * @param model The model instance.
659 * @param name The event whose callbacks are to be frozen.
660 * @return Count of freezes still valid in this event.
661 *
662 * @warning Behavior is undefined if called on a @a model, @a name not frozen.
663 *
664 * @see eina_model_event_callback_call()
665 * @see eina_model_event_callback_freeze()
666 * @since 1.2
667 */
668EAPI int eina_model_event_callback_thaw(Eina_Model *model,
669 const char *name) EINA_ARG_NONNULL(1, 2);
670
671/**
672 * @}
673 */
674
675
676/**
677 * @brief Makes a shallow copy of @a model.
678 * @param model The model instance.
679 * @return Copied model.
680 *
681 * The returned model will have a copy of the properties of @a model and a
682 * reference to the children of @a model.
683 *
684 * @see eina_model_deep_copy()
685 * @since 1.2
686 */
687EAPI Eina_Model *eina_model_copy(const Eina_Model *model) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT EINA_MALLOC;
688/**
689 * @brief Makes a deep(complete) copy of @a model.
690 * @param model The model instance.
691 * @return Copied model.
692 *
693 * The returned model will have a copy of the properties of @a model, its
694 * children will be created by making a deep copy of the children of @a model.
695 *
696 * @see eina_model_copy()
697 * @since 1.2
698 */
699EAPI Eina_Model *eina_model_deep_copy(const Eina_Model *model) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT EINA_MALLOC;
700
701/**
702 * @brief Compares two models.
703 * @param a The first model to compare.
704 * @param b The second model to compare.
705 * @return Greater than zero if @a a > @a b, zero if @a a == @a b and less than
706 * zero if @a a < @a b
707 *
708 * The default comparison checks that the properties of @a a and @a b all have
709 * the same name and value, and then recursively compares all children.
710 *
711 * A model with less properties or children is considered smaller than one with
712 * more properties.
713 *
714 * @since 1.2
715 */
716EAPI int eina_model_compare(const Eina_Model *a, const Eina_Model *b) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1, 2);
717
718/**
719 * @brief Loads the @a model's data.
720 * @param model The model instance.
721 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
722 *
723 * By convention this means loading data from an external source and populating
724 * the models properties and children with it. For example in the case of file
725 * system backed model, this means opening the relevant files and reading the
726 * data from them(creating the properties and children from it).
727 * @warning This convention should be followed, but no guarantees of behaviour
728 * by user defined types can be given.
729 *
730 * @note The types provided by Eina_Model don't implement this method.
731 * @note Calling this function on a model that doesn't implement it returns @c
732 * EINA_TRUE without any effect on @a model.
733 *
734 * @see eina_model_unload()
735 * @since 1.2
736 */
737EAPI Eina_Bool eina_model_load(Eina_Model *model) EINA_ARG_NONNULL(1);
738/**
739 * @brief Unloads the @a model's data.
740 * @param model The model instance.
741 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
742 *
743 * By convention this means releasing data gotten from an external source. For
744 * example of a database backed model this might mean releasing the iterator for
745 * the currently loaded data or deleting a temporary table.
746 * @warning This convention should be followed, but no guarantees of behaviour
747 * by user defined types can be given.
748 *
749 * @note The types provided by Eina_Model don't implement this method.
750 * @note Calling this function on a model that doesn't implement it returns @c
751 * EINA_TRUE without any effect on @a model.
752 *
753 * @see eina_model_load()
754 * @since 1.2
755 */
756EAPI Eina_Bool eina_model_unload(Eina_Model *model) EINA_ARG_NONNULL(1);
757
758
759/**
760 * @defgroup Eina_Model_Properties_Group Data Model Properties
761 * Properties and their usage with models.
762 *
763 * Properties are attributes of model. They have a name and contain a
764 * data value (@ref Eina_Value_Group).
765 *
766 * The actual values and their types, if it is possible to read and
767 * write them and if new properties can be created or deleted it is up
768 * to the type.
769 *
770 * @{
771 */
772/**
773 * @brief Gets the value of @a model's property named @a name.
774 * @param[in] model The model from which to get the property.
775 * @param[in] name The name of the property whose value is wanted.
776 * @param[out] value A pointer to an Eina_Value to receive the property's value.
777 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
778 *
779 * @return EINA_TRUE if @a model has a property named @a name, EINA_FALSE
780 * otherwise.
781 *
782 * @see eina_model_property_set()
783 * @see eina_model_property_del()
784 * @since 1.2
785 */
786EAPI Eina_Bool eina_model_property_get(const Eina_Model *model,
787 const char *name,
788 Eina_Value *value) EINA_ARG_NONNULL(1, 2, 3);
789/**
790 * @brief Sets the value of @a model's property named @a name to @a value.
791 * @param model The model in which to set the property.
792 * @param name The name of the property whose value is to set.
793 * @param value A pointer to a const Eina_Value to containing the property's
794 * value.
795 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
796 *
797 * @see eina_model_property_get()
798 * @see eina_model_property_del()
799 * @since 1.2
800 */
801EAPI Eina_Bool eina_model_property_set(Eina_Model *model,
802 const char *name,
803 const Eina_Value *value) EINA_ARG_NONNULL(1, 2, 3);
804/**
805 * @brief Deletes @a model's property named @a name.
806 * @param model The model from which to delete the property.
807 * @param name The name of the property to delete.
808 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
809 *
810 * @see eina_model_property_set()
811 * @see eina_model_property_get()
812 * @since 1.2
813 */
814EAPI Eina_Bool eina_model_property_del(Eina_Model *model,
815 const char *name) EINA_ARG_NONNULL(1, 2);
816
817/**
818 * @brief Gets a list of the names of every property of @a model.
819 * @param model The model instance.
820 * @return #Eina_List of names.
821 *
822 * @note The returned list should be freed with @c
823 * eina_model_properties_names_list_free().
824 *
825 * @see eina_model_properties_names_list_free()
826 * @see eina_model_property_get()
827 * @since 1.2
828 */
829EAPI Eina_List *eina_model_properties_names_list_get(const Eina_Model *model) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
830/**
831 * @brief Frees a list of names of properties gotten with @c
832 * eina_model_properties_names_list_get().
833 * @param list The list to free.
834 *
835 * @warning Behavior is undefined if called on a list not gotten from @c
836 * eina_model_properties_names_list_get().
837 *
838 * @see eina_model_properties_names_list_get()
839 * @see eina_model_property_get()
840 * @since 1.2
841 */
842EAPI void eina_model_properties_names_list_free(Eina_List *list);
843
844/**
845 * @}
846 */
847
848/**
849 * @defgroup Eina_Model_Children_Group Data Model Children
850 * Children and their usage with models.
851 *
852 * Children are other model instances that are kept sequentially in
853 * the model. They are accessed by their integer index within the
854 * model. Their index may change if child are inserted or deleted
855 * before them, as in an array.
856 *
857 * @{
858 */
859
860/**
861 * @brief Returns the number of child models in @a model.
862 * @param model The model instance.
863 * @return Number of children in @a model.
864 *
865 * @see eina_model_child_append()
866 * @see eina_model_child_get()
867 * @see eina_model_child_del()
868 * @since 1.2
869 */
870EAPI int eina_model_child_count(const Eina_Model *model) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
871
872/**
873 * @brief Get the child at a given position from a model.
874 * @param model the model instance.
875 * @param position index of child to get.
876 * @return child instance with reference @b increased, or @c NULL on error.
877 *
878 * The given @a position must be valid, otherwise it may fail and
879 * return @c NULL, one should check for a valid position with
880 * eina_model_child_count().
881 *
882 * @warning The returned model has its reference increased, you must release it
883 * with eina_model_unref(). This convention is imposed to avoid the
884 * object being removed before the caller function has time to use it.
885 */
886EAPI Eina_Model *eina_model_child_get(const Eina_Model *model,
887 unsigned int position) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
888
889/**
890 * @brief Set the child at a given position from a model.
891 * @param model the model instance.
892 * @param position index of child to set.
893 * @param child the child to use at given position.
894 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
895 *
896 * The given @a position must be valid, otherwise it may fail and
897 * return #EINA_FALSE, one should check for a valid position with
898 * eina_model_child_count().
899 *
900 * The existing child is replaced. Its reference will be decreased
901 * automatically. To insert a new item instead of replacing, use
902 * eina_model_child_insert_at() or eina_model_child_append().
903 *
904 * The given model will be adopted by @a model, that is, the @a child
905 * will have its reference increased if this call succeeds.
906 *
907 * @see eina_model_child_append()
908 * @see eina_model_child_insert_at()
909 * @since 1.2
910 */
911EAPI Eina_Bool eina_model_child_set(Eina_Model *model,
912 unsigned int position,
913 Eina_Model *child) EINA_ARG_NONNULL(1, 3);
914
915/**
916 * @brief Deletes the child model in @a position-th of @a model.
917 * @param model The model instance.
918 * @param position The position of the child to be deleted.
919 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
920 *
921 * @warning This decrements the reference count of the child being deleted,
922 * which may, or not, cause it to be deconstructed and freed.
923 *
924 * @see eina_model_child_append()
925 * @see eina_model_child_get()
926 * @since 1.2
927 */
928EAPI Eina_Bool eina_model_child_del(Eina_Model *model,
929 unsigned int position) EINA_ARG_NONNULL(1);
930
931/**
932 * @brief Insert @a child in the @a position-th of the list of children of @a
933 * model.
934 * @param model The model instance.
935 * @param position Position in which to insert child.
936 * @param child The child to be inserted.
937 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
938 *
939 * @warning This increments the reference count of the child being inserted, if
940 * it will no longer be used by the inserting code it should call
941 * eina_model_unref() on it.
942 *
943 * @see eina_model_child_append()
944 * @see eina_model_child_set()
945 * @since 1.2
946 */
947EAPI Eina_Bool eina_model_child_insert_at(Eina_Model *model,
948 unsigned int position,
949 Eina_Model *child) EINA_ARG_NONNULL(1, 3);
950
951/**
952 * @brief Appends @a child in @a model.
953 * @param model The model instance.
954 * @param child The child to be appended.
955 * @return The position of the added child, or -1 on failure.
956 *
957 * @warning This increments the reference count of the child being inserted, if
958 * it will no longer be used by the inserting code it should call
959 * eina_model_unref() on it.
960 *
961 * @see eina_model_child_insert_at()
962 * @see eina_model_child_set()
963 * @since 1.2
964 */
965EAPI int eina_model_child_append(Eina_Model *model,
966 Eina_Model *child) EINA_ARG_NONNULL(1, 2);
967
968/**
969 * @brief Returns the position of @a other amongst the children of @a model.
970 * @param model The parent model whose children will be searched.
971 * @param start_position The first children to be compared with @a other.
972 * @param other The model whose position is desired.
973 * @return The position of the searched for child, or -1 if not found.
974 *
975 * @since 1.2
976 */
977EAPI int eina_model_child_find(const Eina_Model *model,
978 unsigned int start_position,
979 const Eina_Model *other) EINA_ARG_NONNULL(1, 3) EINA_WARN_UNUSED_RESULT;
980
981/**
982 * @brief Returns the position of a child of @a model that mathes the criteria.
983 * @param model The model whose children will be searched.
984 * @param start_position The position of the first child to be checked.
985 * @param match The function used to check if a child matches the criteria.
986 * @param data Data given the to the @a match function.
987 * @return The position of the first child to match the criteria or -1 if no
988 * child matches it.
989 *
990 * Returns the position of the first(from @a start_position) child of @a model
991 * to which @a match returns EINA_TRUE.
992 *
993 * @since 1.2
994 */
995EAPI int eina_model_child_criteria_match(const Eina_Model *model,
996 unsigned int start_position,
997 Eina_Each_Cb match,
998 const void *data) EINA_ARG_NONNULL(1, 3) EINA_WARN_UNUSED_RESULT;
999
1000/**
1001 * @brief Sorts the children of @a model according to @a compare.
1002 * @param model The model instance.
1003 * @param compare The function to be used in the comparison.
1004 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1005 *
1006 * The @a compare function receives to const pointer to eina models(const
1007 * *Eina_Model).
1008 *
1009 * @since 1.2
1010 */
1011EAPI Eina_Bool eina_model_child_sort(Eina_Model *model,
1012 Eina_Compare_Cb compare) EINA_ARG_NONNULL(1, 2);
1013
1014/**
1015 * @}
1016 */
1017
1018/**
1019 * @defgroup Eina_Model_Iterators_Group Data Model Iterators
1020 * Iterators and their usage with models.
1021 *
1022 * One of the most common tasks of models is to iterate over their
1023 * children, either forwards or backwards, filtering by some criteria
1024 * or a different ordering function.
1025 *
1026 * @{
1027 */
1028
1029/**
1030 * @brief create an iterator that outputs a child model on each iteration.
1031 * @param model the model instance.
1032 * @return Newly created iterator instance on success or @c NULL on failure.
1033 *
1034 * @code
1035 * Eina_Model *child;
1036 * Eina_Iterator *it = eina_model_child_iterator_get(model);
1037 * EINA_ITERATOR_FOREACH(it, child)
1038 * {
1039 * use_child(child);
1040 * eina_model_unref(child);
1041 * }
1042 * eina_iterator_free(it);
1043 * @endcode
1044 * This code shows how to use iterators to do something (in this example call
1045 * use_child()) on every child element.
1046 *
1047 * @warning Each iteration(call to eina_iterator_next()) gives a child model
1048 * with reference @b increased! You must call eina_model_unref() after you're
1049 * done with it.
1050 *
1051 * @see eina_model_child_slice_iterator_get()
1052 * @see eina_model_child_reversed_iterator_get()
1053 * @see eina_model_child_sorted_iterator_get()
1054 * @see eina_model_child_filtered_iterator_get()
1055 * @since 1.2
1056 */
1057EAPI Eina_Iterator *eina_model_child_iterator_get(Eina_Model *model) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
1058/**
1059 * @brief Gets an iterator to a slice of @a model's children.
1060 * @param model The model whose children to iterate over.
1061 * @param start The first child included in the iterator.
1062 * @param count The number of children included in the iterator.
1063 * @return Newly created iterator instance on success or @c NULL on failure.
1064 *
1065 * @warning Each iteration(call to eina_iterator_next()) gives a child model
1066 * with reference @b increased! You must call eina_model_unref() after you're
1067 * done with it.
1068 *
1069 * @see eina_model_child_iterator_get()
1070 * @see eina_model_child_slice_reversed_iterator_get()
1071 * @since 1.2
1072 */
1073EAPI Eina_Iterator *eina_model_child_slice_iterator_get(Eina_Model *model,
1074 unsigned int start,
1075 unsigned int count) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
1076
1077/**
1078 * @brief create an iterator that outputs a child model in reversed order.
1079 * @param model the model instance.
1080 * @return Newly created iterator instance on success or @c NULL on failure.
1081 *
1082 * Each iteration output a child model with reference @b increased!
1083 * You must call eina_model_unref() after you're done with it.
1084 *
1085 * The order is reversed, that is, the last element is outputted first.
1086 *
1087 * @code
1088 * Eina_Model *child;
1089 * Eina_Iterator *it = eina_model_child_reversed_iterator_get(model);
1090 * EINA_ITERATOR_FOREACH(it, child)
1091 * {
1092 * use_child(child);
1093 * eina_model_unref(child);
1094 * }
1095 * eina_iterator_free(it);
1096 * @endcode
1097 * This code shows how to use iterators to do something (in this example call
1098 * use_child()) on every child element starting from last to first.
1099 *
1100 * @warning Each iteration(call to eina_iterator_next()) gives a child model
1101 * with reference @b increased! You must call eina_model_unref() after you're
1102 * done with it.
1103 *
1104 * @see eina_model_child_slice_iterator_get()
1105 * @see eina_model_child_reversed_iterator_get()
1106 * @see eina_model_child_sorted_iterator_get()
1107 * @see eina_model_child_filtered_iterator_get()
1108 * @since 1.2
1109 */
1110EAPI Eina_Iterator *eina_model_child_reversed_iterator_get(Eina_Model *model) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
1111
1112/**
1113 * @brief Gets a reversed iterator to a slice of @a model's children.
1114 * @param model The model whose children to iterate over.
1115 * @param start The first child included in the iterator.
1116 * @param count The number of children included in the iterator.
1117 * @return Newly created iterator instance on success or @c NULL on failure.
1118 *
1119 * @warning Each iteration(call to eina_iterator_next()) gives a child model
1120 * with reference @b increased! You must call eina_model_unref() after you're
1121 * done with it.
1122 *
1123 * @see eina_model_child_reversed_iterator_get()
1124 * @see eina_model_child_slice_iterator_get()
1125 * @since 1.2
1126 */
1127EAPI Eina_Iterator *eina_model_child_slice_reversed_iterator_get(Eina_Model *model,
1128 unsigned int start,
1129 unsigned int count) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
1130
1131/**
1132 * @brief create an iterator that outputs a child model using sort criteria.
1133 * @param model the model instance.
1134 * @param compare compare function to use as sort criteria.
1135 * @return Newly created iterator instance on success or @c NULL on failure.
1136 *
1137 * Each iteration output a child model with reference @b increased!
1138 * You must call eina_model_unref() after you're done with it.
1139 *
1140 * The sort will not affect the main object @a model, it's just a view
1141 * of it.
1142 *
1143 * @code
1144 * Eina_Model *child;
1145 * Eina_Iterator *it = eina_model_child_sorted_iterator_get(model, EINA_COMPARE_CB(eina_model_compare));
1146 * EINA_ITERATOR_FOREACH(it, child)
1147 * {
1148 * use_child(child);
1149 * eina_model_unref(child);
1150 * }
1151 * eina_iterator_free(it);
1152 * @endcode
1153 * This bit of code shows how to use iterators to do something (in this example
1154 * call use_child()) on every child element in the order given by the @a compare
1155 * function.
1156 *
1157 * @warning Each iteration(call to eina_iterator_next()) gives a child model
1158 * with reference @b increased! You must call eina_model_unref() after you're
1159 * done with it.
1160 *
1161 * @see eina_model_child_slice_iterator_get()
1162 * @see eina_model_child_reversed_iterator_get()
1163 * @see eina_model_child_sorted_iterator_get()
1164 * @see eina_model_child_filtered_iterator_get()
1165 * @since 1.2
1166 */
1167EAPI Eina_Iterator *eina_model_child_sorted_iterator_get(Eina_Model *model,
1168 Eina_Compare_Cb compare) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT;
1169
1170/**
1171 * @brief Returns a sorted iterator to a slice of @a model's children.
1172 * @param model The model whose children to iterate over.
1173 * @param start The position(before sorting) of the first child included in
1174 * the iterator.
1175 * @param count The number of children included in the iterator.
1176 * @param compare The function used to sort the children.
1177 * @return Newly created iterator instance on success or @c NULL on failure.
1178 *
1179 * @warning Each iteration(call to eina_iterator_next()) gives a child model
1180 * with reference @b increased! You must call eina_model_unref() after you're
1181 * done with it.
1182 *
1183 * @see eina_model_child_slice_iterator_get()
1184 * @see eina_model_child_reversed_iterator_get()
1185 * @see eina_model_child_sorted_iterator_get()
1186 * @see eina_model_child_filtered_iterator_get()
1187 * @since 1.2
1188 */
1189EAPI Eina_Iterator *eina_model_child_slice_sorted_iterator_get(Eina_Model *model,
1190 unsigned int start,
1191 unsigned int count,
1192 Eina_Compare_Cb compare) EINA_ARG_NONNULL(1, 4) EINA_WARN_UNUSED_RESULT;
1193
1194/**
1195 * @brief create an iterator that indexes of children that matches.
1196 * @param model the model instance.
1197 * @param match function to select children.
1198 * @param data extra context given to @a match function.
1199 * @return Newly created iterator instance on success or @c NULL on failure.
1200 *
1201 * Unlike other iterators, each iteration output an integer index!
1202 * This is useful if you want to highlight the matching model
1203 * somewhere else.
1204 *
1205 * If no child element matches a valid, and empty, iterator will be returned.
1206 * Indexes returned by this iterator are guaranteed to exists.
1207 *
1208 * @code
1209 * unsigned int idx;
1210 * Eina_Iterator *it = eina_model_child_filtered_iterator_get(model, filter, ctx);
1211 * EINA_ITERATOR_FOREACH(it, idx)
1212 * {
1213 * Eina_Model *child = eina_model_child_get(model, idx);
1214 * printf("matches at %u %p\n", idx, child);
1215 * eina_model_unref(child);
1216 * }
1217 * eina_iterator_free(it);
1218 * @endcode
1219 * This bit of code shows how to use iterators to do something (in this example
1220 * print the address) on child elements that match the criteria given of @a match.
1221 *
1222 * @see eina_model_child_slice_iterator_get()
1223 * @see eina_model_child_reversed_iterator_get()
1224 * @see eina_model_child_sorted_iterator_get()
1225 * @see eina_model_child_filtered_iterator_get()
1226 * @since 1.2
1227 */
1228EAPI Eina_Iterator *eina_model_child_filtered_iterator_get(Eina_Model *model,
1229 Eina_Each_Cb match,
1230 const void *data) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT;
1231
1232/**
1233 * @brief Returns a filtered slice of the @a model's children.
1234 * @param model The model whose children to iterate over.
1235 * @param start The position of the first child to be tested for inclusion in
1236 * the iterator.
1237 * @param count The number of children to be tested for inclusion in the
1238 * iterator.
1239 * @param match The function used to decide which children will be included in
1240 * the iterator.
1241 * @param data Data passed to the @a match function.
1242 * @return Newly created iterator instance on success or @c NULL on failure.
1243 *
1244 * @note Only children for whom @a match returns EINA_TRUE will be included in
1245 * the iterator.
1246 *
1247 * @note Each iteration(call to eina_iterator_next()) gives an integer index!
1248 *
1249 * @warning The iterator may have less than @a count children, but not more.
1250 *
1251 * @see eina_model_child_slice_iterator_get()
1252 * @see eina_model_child_reversed_iterator_get()
1253 * @see eina_model_child_sorted_iterator_get()
1254 * @see eina_model_child_filtered_iterator_get()
1255 * @since 1.2
1256 */
1257EAPI Eina_Iterator *eina_model_child_slice_filtered_iterator_get(Eina_Model *model,
1258 unsigned int start,
1259 unsigned int count,
1260 Eina_Each_Cb match,
1261 const void *data) EINA_ARG_NONNULL(1, 4) EINA_WARN_UNUSED_RESULT;
1262
1263
1264/**
1265 * @}
1266 */
1267
1268/**
1269 * @brief Convert model to string.
1270 * @param model the model instance.
1271 * @return Newly allocated memory or @c NULL on failure.
1272 *
1273 * The default format of the ouput is:
1274 * Type_Name({Property_Name: Property_Value, ...}, [Child0, Child1, ...])
1275 *
1276 * Where:
1277 * @li Type_Name: eina_model_type_name_get(eina_model_type_get(model))
1278 * @li Properties are sorted alphabetically.
1279 * @li Property_Value is created using eina_value_to_string().
1280 * @li Children are converted using eina_model_to_string()
1281 *
1282 * @since 1.2
1283 */
1284EAPI char *eina_model_to_string(const Eina_Model *model) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT EINA_MALLOC;
1285
1286/**
1287 * @defgroup Eina_Model_Type_Group Data Model Type management
1288 *
1289 * Functions and structures related to implementing new types or
1290 * extending existing ones.
1291 *
1292 * All eina_model_type functions takes an Eina_Model_Type or
1293 * Eina_Model_Interface as parameter and may be used to validate or
1294 * query information about them.
1295 *
1296 * The functions with prefix eina_model_type that matches eina_model
1297 * counterparts, such as eina_model_type_compare() and
1298 * eina_model_compare() are used as "super", that is, calls the @c
1299 * compare() method of the given type (or its parent) instead of the
1300 * most specific type of provided Eina_Model.
1301 *
1302 * Examples:
1303 * @li @ref eina_model_02_example_page contains an easy to follow
1304 * example that demonstrates several of the important features of
1305 * eina_model, uses #EINA_MODEL_TYPE_GENERIC.
1306 * @li @ref eina_model_03_example_page walk-through example on how to
1307 * inherit types, a suggestion of eina_model_load() usage and uses
1308 * #EINA_MODEL_TYPE_STRUCT.
1309 *
1310 * @{
1311 */
1312
1313/**
1314 * @def EINA_MODEL_TYPE_VERSION
1315 * Current API version, used to validate #_Eina_Model_Type.
1316 */
1317#define EINA_MODEL_TYPE_VERSION (1)
1318
1319/**
1320 * @struct _Eina_Model_Type
1321 * API to access models.
1322 *
1323 * Each type of the hierarchy and each interface will get its own
1324 * private data of size @c private_size (defined at each subtype or
1325 * interface), this can be retrieved with
1326 * eina_model_type_private_data_get() and
1327 * eina_model_interface_private_data_get().
1328 *
1329 * Private are created @b automatically and should be setup with @c
1330 * setup and flushed with @c flush. All types (or interfaces)
1331 * functions that exist are called! Don't call your parent's @c setup or
1332 * @c flush! The setup is done from parent to child. Flush is done from
1333 * child to parent.
1334 *
1335 * After memory setup was done, @c constructor of the toplevel type
1336 * defining it is called. If desired it may call parent's constructor
1337 * in whatever order is desired. This may be used to create
1338 * properties, children and may use parent's data if needed. The only
1339 * constructor caled is that of the most specialized type, if interface
1340 * constructors should be called, do them in the desired order from the type
1341 * constructor.
1342 *
1343 * When the model is deleted, explicitly with eina_model_del() or
1344 * implicitly with eina_model_unref() on the last reference, the @c
1345 * destructor is called. It must release references to other
1346 * models. When the last reference is dropped, every @c flush is
1347 * called from child to parent, then memory is freed. The only
1348 * destructor caled is that of the most specialized type, if interface
1349 * destructors should be called, do them in the desired order from the type
1350 * destructor.
1351 *
1352 *
1353 * @note The methods @c setup and @c flush should exist if there is
1354 * private data, otherwise memory may be uninitialized or leaks.
1355 * @note It is recommended that @c constructor and @c destructor exist
1356 * to correctly do their roles and call parents in the correct
1357 * order. Whenever they do not exist, their parent pointer is
1358 * called.
1359 * @note a runtime check will enforce just types with ABI version
1360 * #EINA_MODEL_TYPE_VERSION are used by comparing with the @c version
1361 * member.
1362 *
1363 * @since 1.2
1364 */
1365struct _Eina_Model_Type
1366{
1367 unsigned int version; /**< must be #EINA_MODEL_TYPE_VERSION */
1368 unsigned int private_size; /**< used to allocate type private data */
1369 unsigned int type_size; /**< used to know sizeof(Eina_Model_Type) or subtypes (which may be bigger, by including Eina_Model_Type as a header */
1370 const char *name; /**< name for debug and introspection */
1371 const Eina_Model_Type *parent; /**< parent type, must be EINA_MODEL_TYPE_BASE or a child of */
1372 const Eina_Model_Interface **interfaces; /**< null terminated array of interfaces */
1373 const Eina_Model_Event_Description *events; /**< null terminated array of events */
1374 Eina_Bool (*setup)(Eina_Model *model); /**< setup type private data, do @b not call parent type setup! */
1375 Eina_Bool (*flush)(Eina_Model *model); /**< flush type private data, do @b not call parent type flush! */
1376 Eina_Bool (*constructor)(Eina_Model *model); /**< construct type instance, setup was already called. Should call parent's or interfaces' constructor if needed */
1377 Eina_Bool (*destructor)(Eina_Model *model); /**< destruct type instance, flush will be called after it. Should call parent's or interfaces' destructor if needed. Release reference to other models here. */
1378 Eina_Bool (*copy)(const Eina_Model *src, Eina_Model *dst); /**< copy type private data, do @b not call parent type copy! */
1379 Eina_Bool (*deep_copy)(const Eina_Model *src, Eina_Model *dst); /**< deep copy type private data, do @b not call parent type deep copy! */
1380 Eina_Bool (*compare)(const Eina_Model *a, const Eina_Model *b, int *cmp);
1381 Eina_Bool (*load)(Eina_Model *model);
1382 Eina_Bool (*unload)(Eina_Model *model);
1383 Eina_Bool (*property_get)(const Eina_Model *model, const char *name, Eina_Value *value);
1384 Eina_Bool (*property_set)(Eina_Model *model, const char *name, const Eina_Value *value);
1385 Eina_Bool (*property_del)(Eina_Model *model, const char *name);
1386 Eina_List *(*properties_names_list_get)(const Eina_Model *model); /**< list of stringshare */
1387 int (*child_count)(const Eina_Model *model);
1388 Eina_Model *(*child_get)(const Eina_Model *model, unsigned int position);
1389 Eina_Bool (*child_set)(Eina_Model *model, unsigned int position, Eina_Model *child);
1390 Eina_Bool (*child_del)(Eina_Model *model, unsigned int position);
1391 Eina_Bool (*child_insert_at)(Eina_Model *model, unsigned int position, Eina_Model *child);
1392 int (*child_find)(const Eina_Model *model, unsigned int start_position, const Eina_Model *other);
1393 int (*child_criteria_match)(const Eina_Model *model, unsigned int start_position, Eina_Each_Cb match, const void *data);
1394 void (*child_sort)(Eina_Model *model, Eina_Compare_Cb compare);
1395 Eina_Iterator *(*child_iterator_get)(Eina_Model *model, unsigned int start, unsigned int count);
1396 Eina_Iterator *(*child_reversed_iterator_get)(Eina_Model *model, unsigned int start, unsigned int count);
1397 Eina_Iterator *(*child_sorted_iterator_get)(Eina_Model *model, unsigned int start, unsigned int count, Eina_Compare_Cb compare);
1398 Eina_Iterator *(*child_filtered_iterator_get)(Eina_Model *model, unsigned int start, unsigned int count, Eina_Each_Cb match, const void *data);
1399 char *(*to_string)(const Eina_Model *model); /**< used to represent model as string, usually for debug purposes or user convenience */
1400 void *__extension_ptr0; /**< not to be used */
1401 void *__extension_ptr1; /**< not to be used */
1402 void *__extension_ptr2; /**< not to be used */
1403 void *__extension_ptr3; /**< not to be used */
1404};
1405
1406#define EINA_MODEL_TYPE_INIT(name, type, private_type, parent, interfaces, events) \
1407 {EINA_MODEL_TYPE_VERSION, \
1408 sizeof(private_type), \
1409 sizeof(type), \
1410 name, \
1411 parent, \
1412 interfaces, \
1413 events, \
1414 NULL, \
1415 NULL, \
1416 NULL, \
1417 NULL, \
1418 NULL, \
1419 NULL, \
1420 NULL, \
1421 NULL, \
1422 NULL, \
1423 NULL, \
1424 NULL, \
1425 NULL, \
1426 NULL, \
1427 NULL, \
1428 NULL, \
1429 NULL, \
1430 NULL, \
1431 NULL, \
1432 NULL, \
1433 NULL, \
1434 NULL, \
1435 NULL, \
1436 NULL, \
1437 NULL, \
1438 NULL, \
1439 NULL, \
1440 NULL, \
1441 NULL, \
1442 NULL, \
1443 NULL \
1444 }
1445
1446#define EINA_MODEL_TYPE_INIT_NOPRIVATE(name, type, parent, interfaces, events) \
1447 {EINA_MODEL_TYPE_VERSION, \
1448 0, \
1449 sizeof(type), \
1450 name, \
1451 parent, \
1452 interfaces, \
1453 events, \
1454 NULL, \
1455 NULL, \
1456 NULL, \
1457 NULL, \
1458 NULL, \
1459 NULL, \
1460 NULL, \
1461 NULL, \
1462 NULL, \
1463 NULL, \
1464 NULL, \
1465 NULL, \
1466 NULL, \
1467 NULL, \
1468 NULL, \
1469 NULL, \
1470 NULL, \
1471 NULL, \
1472 NULL, \
1473 NULL, \
1474 NULL, \
1475 NULL, \
1476 NULL, \
1477 NULL, \
1478 NULL, \
1479 NULL, \
1480 NULL, \
1481 NULL, \
1482 NULL, \
1483 NULL \
1484 }
1485
1486#define EINA_MODEL_TYPE_INIT_NULL \
1487 {0, \
1488 0, \
1489 0, \
1490 NULL, \
1491 NULL, \
1492 NULL, \
1493 NULL, \
1494 NULL, \
1495 NULL, \
1496 NULL, \
1497 NULL, \
1498 NULL, \
1499 NULL, \
1500 NULL, \
1501 NULL, \
1502 NULL, \
1503 NULL, \
1504 NULL, \
1505 NULL, \
1506 NULL, \
1507 NULL, \
1508 NULL, \
1509 NULL, \
1510 NULL, \
1511 NULL, \
1512 NULL, \
1513 NULL, \
1514 NULL, \
1515 NULL, \
1516 NULL, \
1517 NULL, \
1518 NULL, \
1519 NULL, \
1520 NULL, \
1521 NULL, \
1522 NULL, \
1523 NULL \
1524 }
1525
1526/**
1527 * @brief Calls the constructor of @a type for @a model.
1528 * @param type The type whose constructor will be called.
1529 * @param model The model instance.
1530 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1531 *
1532 * This should be used to call the parent's type constructor, something like:
1533 * @code
1534 * static Eina_Bool my_type_constructor(Eina_Model *m)
1535 * {
1536 * // call parents constructor:
1537 * if (!eina_model_type_constructor(MY_TYPE->parent, m))
1538 * return EINA_FALSE;
1539 * // do my stuff
1540 * return EINA_TRUE;
1541 * }
1542 * @endcode
1543 * @note You should only do your type's initialization after the parent type has
1544 * done his own(this is as to ensure you can call on your parent's methods).
1545 *
1546 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1547 * returns EINA_FALSE.
1548 *
1549 * @see eina_model_new()
1550 * @see _Eina_Model_Type
1551 * @since 1.2
1552 */
1553EAPI Eina_Bool eina_model_type_constructor(const Eina_Model_Type *type,
1554 Eina_Model *model) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT;
1555/**
1556 * @brief Calls the destructor of @a type for @a model.
1557 * @param type The type whose destructor will be called.
1558 * @param model The model instance.
1559 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1560 *
1561 * This should be used to call the parent's type destructor, something like:
1562 * @code
1563 * static Eina_Bool my_type_destructor(Eina_Model *m)
1564 * {
1565 * // do my stuff
1566 * // call parents destructor:
1567 * if (!eina_model_type_destructor(MY_TYPE->parent, m))
1568 * return EINA_FALSE;
1569 * return EINA_TRUE;
1570 * }
1571 * @endcode
1572 * @note It's considered good practice to free your type's resources before
1573 * calling the parent's destructor.
1574 *
1575 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1576 * returns EINA_FALSE.
1577 *
1578 * @see eina_model_del()
1579 * @see _Eina_Model_Type
1580 * @since 1.2
1581 */
1582EAPI Eina_Bool eina_model_type_destructor(const Eina_Model_Type *type,
1583 Eina_Model *model) EINA_ARG_NONNULL(1, 2);
1584/**
1585 * @brief Calls the copy method of @a type for @a model.
1586 * @param type The type whose copy method will be called.
1587 * @param src Pointer to the model to be copied.
1588 * @param dst Pointer to where copy will be put.
1589 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1590 *
1591 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1592 * returns EINA_FALSE.
1593 *
1594 * @see eina_model_copy()
1595 * @see _Eina_Model_Type
1596 * @since 1.2
1597 */
1598EAPI Eina_Bool eina_model_type_copy(const Eina_Model_Type *type,
1599 const Eina_Model *src,
1600 Eina_Model *dst) EINA_ARG_NONNULL(1, 2, 3);
1601/**
1602 * @brief Calls the deep copy method of @a type for @a model.
1603 * @param type The type whose copy method will be called.
1604 * @param src Pointer to the model to be copied.
1605 * @param dst Pointer to where copy will be put.
1606 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1607 *
1608 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1609 * returns EINA_FALSE.
1610 *
1611 * @see eina_model_deep_copy()
1612 * @see _Eina_Model_Type
1613 * @since 1.2
1614 */
1615EAPI Eina_Bool eina_model_type_deep_copy(const Eina_Model_Type *type,
1616 const Eina_Model *src,
1617 Eina_Model *dst) EINA_ARG_NONNULL(1, 2, 3);
1618/**
1619 * @brief Calls the compare method of @a type for @a model.
1620 * @param[in] type The type whose compare method will be called.
1621 * @param[in] a Pointer to the first model to be compared.
1622 * @param[in] b Pointer to the second model to be compared.
1623 * @param[out] cmp The value of the comparison, 1 if @a b is greater than @a a,
1624 * -1 if @a b is smaller than @a a, 0 if @a a and @a b are equal.
1625 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1626 *
1627 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1628 * returns EINA_FALSE.
1629 *
1630 * @see eina_model_compare()
1631 * @see _Eina_Model_Type
1632 * @since 1.2
1633 */
1634EAPI Eina_Bool eina_model_type_compare(const Eina_Model_Type *type,
1635 const Eina_Model *a,
1636 const Eina_Model *b,
1637 int *cmp) EINA_ARG_NONNULL(1, 2, 3, 4);
1638/**
1639 * @brief Calls the load method of @a type for @a model.
1640 * @param type The type whose load method will be called.
1641 * @param model The model instance.
1642 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1643 *
1644 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1645 * returns EINA_FALSE.
1646 *
1647 * @see eina_model_load()
1648 * @see _Eina_Model_Type
1649 * @since 1.2
1650 */
1651EAPI Eina_Bool eina_model_type_load(const Eina_Model_Type *type,
1652 Eina_Model *model) EINA_ARG_NONNULL(1, 2);
1653/**
1654 * @brief Calls the unload method of @a type for @a model.
1655 * @param type The type whose unload method will be called.
1656 * @param model The model instance.
1657 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1658 *
1659 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1660 * returns EINA_FALSE.
1661 *
1662 * @see eina_model_unload()
1663 * @see _Eina_Model_Type
1664 * @since 1.2
1665 */
1666EAPI Eina_Bool eina_model_type_unload(const Eina_Model_Type *type,
1667 Eina_Model *model) EINA_ARG_NONNULL(1, 2);
1668/**
1669 * @brief Calls the property get method of @a type for @a model.
1670 * @param[in] type The type whose property get method will be called.
1671 * @param[in] model The model instance.
1672 * @param[in] name Name of property to get.
1673 * @param[out] value Pointer to where value of property will be placed.
1674 * @return EINA_TRUE if able to get property, EINA_FALSE otherwise.
1675 *
1676 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1677 * returns EINA_FALSE.
1678 *
1679 * @see eina_model_property_get()
1680 * @see _Eina_Model_Type
1681 * @since 1.2
1682 */
1683EAPI Eina_Bool eina_model_type_property_get(const Eina_Model_Type *type,
1684 const Eina_Model *model,
1685 const char *name,
1686 Eina_Value *value) EINA_ARG_NONNULL(1, 2, 3, 4);
1687/**
1688 * @brief Calls the property set method of @a type for @a model.
1689 * @param type The type whose property set method will be called.
1690 * @param model The model instance.
1691 * @param name Name of property whose value will be set.
1692 * @param value The value to be set.
1693 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1694 *
1695 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1696 * returns EINA_FALSE.
1697 *
1698 * @see eina_model_property_set()
1699 * @see _Eina_Model_Type
1700 * @since 1.2
1701 */
1702EAPI Eina_Bool eina_model_type_property_set(const Eina_Model_Type *type,
1703 Eina_Model *model,
1704 const char *name,
1705 const Eina_Value *value) EINA_ARG_NONNULL(1, 2, 3, 4);
1706/**
1707 * @brief Calls the property del method of @a type for @a model.
1708 * @param type The type whose property delete method will be called.
1709 * @param model The model instance.
1710 * @param name The name of the property to be deleted.
1711 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1712 *
1713 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1714 * returns EINA_FALSE.
1715 *
1716 * @see eina_model_property_del()
1717 * @see _Eina_Model_Type
1718 * @since 1.2
1719 */
1720EAPI Eina_Bool eina_model_type_property_del(const Eina_Model_Type *type,
1721 Eina_Model *model,
1722 const char *name) EINA_ARG_NONNULL(1, 2, 3);
1723/**
1724 * @brief Calls the properties name list method of @a type for @a model.
1725 * @param type The type whose property name list get method will be called.
1726 * @param model The model instance.
1727 * @return #Eina_List of properties' names.
1728 *
1729 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1730 * returns EINA_FALSE.
1731 *
1732 * @see eina_model_properties_names_list_get()
1733 * @see _Eina_Model_Type
1734 * @since 1.2
1735 */
1736EAPI Eina_List *eina_model_type_properties_names_list_get(const Eina_Model_Type *type,
1737 const Eina_Model *model) EINA_ARG_NONNULL(1, 2);
1738/**
1739 * @brief Calls the child count method of @a type for @a model.
1740 * @param type The type whose child count method will be called.
1741 * @param model The model instance.
1742 * @return Number of children in @a model.
1743 *
1744 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1745 * returns EINA_FALSE.
1746 *
1747 * @see eina_model_child_count()
1748 * @see _Eina_Model_Type
1749 * @since 1.2
1750 */
1751EAPI int eina_model_type_child_count(const Eina_Model_Type *type,
1752 const Eina_Model *model) EINA_ARG_NONNULL(1, 2);
1753/**
1754 * @brief Calls the child get method of @a type for @a model.
1755 * @param type The type whose child get method will be called.
1756 * @param model The model instance.
1757 * @param position The position of the child to get.
1758 * @return The child model, or NULL on failure.
1759 *
1760 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1761 * returns EINA_FALSE.
1762 *
1763 * @see eina_model_child_get()
1764 * @see _Eina_Model_Type
1765 * @since 1.2
1766 */
1767EAPI Eina_Model *eina_model_type_child_get(const Eina_Model_Type *type,
1768 const Eina_Model *model,
1769 unsigned int position) EINA_ARG_NONNULL(1, 2);
1770/**
1771 * @brief Calls the child set method of @a type for @a model.
1772 * @param type The type whose child set method will be called.
1773 * @param model The model instance.
1774 * @param position The position of the child to be set.
1775 * @param child Pointer to value(child) to be set.
1776 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1777 *
1778 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1779 * returns EINA_FALSE.
1780 *
1781 * @see eina_model_child_set()
1782 * @see _Eina_Model_Type
1783 * @since 1.2
1784 */
1785EAPI Eina_Bool eina_model_type_child_set(const Eina_Model_Type *type,
1786 Eina_Model *model,
1787 unsigned int position,
1788 Eina_Model *child) EINA_ARG_NONNULL(1, 2, 4);
1789/**
1790 * @brief Calls the child del method of @a type for @a model.
1791 * @param type The type whose child delete method will be called.
1792 * @param model The model instance.
1793 * @param position Position of child to be deleted.
1794 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1795 *
1796 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1797 * returns EINA_FALSE.
1798 *
1799 * @see eina_model_child_del()
1800 * @see _Eina_Model_Type
1801 * @since 1.2
1802 */
1803EAPI Eina_Bool eina_model_type_child_del(const Eina_Model_Type *type,
1804 Eina_Model *model,
1805 unsigned int position) EINA_ARG_NONNULL(1, 2);
1806/**
1807 * @brief Calls the child insert at method of @a type for @a model.
1808 * @param type The type whose child insert method will be called.
1809 * @param model The model instance.
1810 * @param position Position in which @a child will be inserted.
1811 * @param child The child to be inserted.
1812 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1813 *
1814 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1815 * returns EINA_FALSE.
1816 *
1817 * @see eina_model_child_insert_at()
1818 * @see _Eina_Model_Type
1819 * @since 1.2
1820 */
1821EAPI Eina_Bool eina_model_type_child_insert_at(const Eina_Model_Type *type,
1822 Eina_Model *model,
1823 unsigned int position,
1824 Eina_Model *child) EINA_ARG_NONNULL(1, 2, 4);
1825/**
1826 * @brief Calls the child find method of @a type for @a model.
1827 * @param type The type whose find method will be called.
1828 * @param model The model instance.
1829 * @param start_position The first position to search for.
1830 * @param other The child being searched for.
1831 * @return The index of the searched child, or -1 if not found.
1832 *
1833 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1834 * returns EINA_FALSE.
1835 *
1836 * @see eina_model_child_find()
1837 * @see _Eina_Model_Type
1838 * @since 1.2
1839 */
1840EAPI int eina_model_type_child_find(const Eina_Model_Type *type,
1841 const Eina_Model *model,
1842 unsigned int start_position,
1843 const Eina_Model *other) EINA_ARG_NONNULL(1, 2, 4);
1844/**
1845 * @brief Calls the child criteria match method of @a type for @a model.
1846 * @param type The type whose child criteria match method will be called.
1847 * @param model The model instance.
1848 * @param start_position The first position to be checked.
1849 * @param match The function used to determine if a child matches the criteria.
1850 * @param data Data given to the @a match function. May be NULL.
1851 * @return The position of the first child to match the criteria or -1 if no
1852 * child matches it.
1853 *
1854 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1855 * returns EINA_FALSE.
1856 *
1857 * @see eina_model_child_criteria_match()
1858 * @see _Eina_Model_Type
1859 * @since 1.2
1860 */
1861EAPI int eina_model_type_child_criteria_match(const Eina_Model_Type *type,
1862 const Eina_Model *model,
1863 unsigned int start_position,
1864 Eina_Each_Cb match,
1865 const void *data) EINA_ARG_NONNULL(1, 2, 4);
1866/**
1867 * @brief Calls the child sort method of @a type for @a model.
1868 * @param type The type whose child sort method will be called.
1869 * @param model The model instance.
1870 * @param compare Function used to compare children.
1871 *
1872 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1873 * returns EINA_FALSE.
1874 *
1875 * @see eina_model_child_sort()
1876 * @see _Eina_Model_Type
1877 * @since 1.2
1878 */
1879EAPI void eina_model_type_child_sort(const Eina_Model_Type *type,
1880 Eina_Model *model,
1881 Eina_Compare_Cb compare) EINA_ARG_NONNULL(1, 2, 3);
1882/**
1883 * @brief Calls the child iterator get method of @a type for @a model.
1884 * @param type The type whose child iterator get method will be called.
1885 * @param model The model instance.
1886 * @param start The first child to be a part of the iterator.
1887 * @param count The number of children included in the iterator.
1888 * @return Newly created iterator instance on success or @c NULL on failure.
1889 *
1890 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1891 * returns EINA_FALSE.
1892 *
1893 * @see eina_model_child_iterator_get()
1894 * @see _Eina_Model_Type
1895 * @since 1.2
1896 */
1897EAPI Eina_Iterator *eina_model_type_child_iterator_get(const Eina_Model_Type *type,
1898 Eina_Model *model,
1899 unsigned int start,
1900 unsigned int count) EINA_ARG_NONNULL(1, 2);
1901/**
1902 * @brief Calls the child reversed iterator get method of @a type for @a model.
1903 * @param type The type whose child reversed iterator get method will be called.
1904 * @param model The model instance.
1905 * @param start The first child to be a part of the iterator.
1906 * @param count The number of children included in the iterator.
1907 * @return Newly created iterator instance on success or @c NULL on failure.
1908 *
1909 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1910 * returns EINA_FALSE.
1911 *
1912 * @see eina_model_child_reversed_iterator_get()
1913 * @see _Eina_Model_Type
1914 * @since 1.2
1915 */
1916EAPI Eina_Iterator *eina_model_type_child_reversed_iterator_get(const Eina_Model_Type *type,
1917 Eina_Model *model,
1918 unsigned int start,
1919 unsigned int count) EINA_ARG_NONNULL(1, 2);
1920/**
1921 * @brief Calls the child sorted iterator get method of @a type for @a model.
1922 * @param type The type whose child sorted iterator get method will be called.
1923 * @param model The model instance.
1924 * @param start The first child to be a part of the iterator.
1925 * @param count The number of children included in the iterator.
1926 * @param compare Function used to compare children.
1927 * @return Newly created iterator instance on success or @c NULL on failure.
1928 *
1929 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1930 * returns EINA_FALSE.
1931 *
1932 * @see eina_model_child_sorted_iterator_get()
1933 * @see _Eina_Model_Type
1934 * @since 1.2
1935 */
1936EAPI Eina_Iterator *eina_model_type_child_sorted_iterator_get(const Eina_Model_Type *type,
1937 Eina_Model *model,
1938 unsigned int start,
1939 unsigned int count,
1940 Eina_Compare_Cb compare) EINA_ARG_NONNULL(1, 2, 5);
1941/**
1942 * @brief Calls the child filtered get method of @a type for @a model.
1943 * @param type The type whose child filtered iterator get method will be called.
1944 * @param model The model instance.
1945 * @param start The first child to be a part of the iterator.
1946 * @param count Number of children to be checked for inclusion in the iterator.
1947 * @param match Function used to check if child will be included in the iterator.
1948 * @param data Data given to the @a match function. May be NULL.
1949 * @return Newly created iterator instance on success or @c NULL on failure.
1950 *
1951 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1952 * returns EINA_FALSE.
1953 *
1954 * @see eina_model_child_filtered_iterator_get()
1955 * @see _Eina_Model_Type
1956 * @since 1.2
1957 */
1958EAPI Eina_Iterator *eina_model_type_child_filtered_iterator_get(const Eina_Model_Type *type,
1959 Eina_Model *model,
1960 unsigned int start,
1961 unsigned int count,
1962 Eina_Each_Cb match,
1963 const void *data) EINA_ARG_NONNULL(1, 2, 5);
1964/**
1965 * @brief Calls the to string method of @a type for @a model.
1966 * @param type The type whose to string method will be called.
1967 * @param model The model instance.
1968 * @return String representationof @a model.
1969 *
1970 * @warning If model doesn't inherit from(or is of) @a type does nothing and
1971 * returns EINA_FALSE.
1972 *
1973 * @see eina_model_to_string()
1974 * @see _Eina_Model_Type
1975 * @since 1.2
1976 */
1977EAPI char *eina_model_type_to_string(const Eina_Model_Type *type,
1978 const Eina_Model *model) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT EINA_MALLOC;
1979
1980
1981/**
1982 * @brief Get resolved method from types that extend Eina_Model_Type given @a offset.
1983 * @param model the model to query the method
1984 * @param offset the byte offset in the structure given as type, it
1985 * must be bigger than Eina_Model_Type itself.
1986 * @return Address to resolved method, or @c NULL if method is not implemented.
1987 *
1988 * The use of this function is discouraged, you should use
1989 * eina_model_method_resolve() instead.
1990 *
1991 * When implementing new types that augments the basic methods from
1992 * Eina_Model_Type, the recommended structure layout is as follow:
1993 * @code
1994 * typedef struct _My_Type My_Type;
1995 * struct _My_Type {
1996 * Eina_Model_Type base;
1997 * int (*my_method)(Eina_Model *model);
1998 * };
1999 *
2000 * int my_type_my_method(Eina_Model *model);
2001 * @endcode
2002 *
2003 * Then the implementation of @c my_type_my_method() needs to get the
2004 * most specific @c my_method that is not @c NULL from type hierarchy,
2005 * also called "resolve the method".
2006 *
2007 * To do this in an efficient way, Eina_Model infrastructure
2008 * pre-resolves all methods and provides this function for efficient
2009 * query. The recommended implementation of my_type_my_method() would
2010 * be:
2011 * @code
2012 * int my_type_my_method(Eina_Model *model)
2013 * {
2014 * int (*meth)(Eina_Model *);
2015 *
2016 * EINA_SAFETY_ON_FALSE_RETURN(eina_model_instance_check(model, MY_TYPE), -1);
2017 *
2018 * meth = eina_model_method_offset_resolve(model, offsetof(My_Type, my_method));
2019 * EINA_SAFETY_ON_NULL_RETURN(meth, -1);
2020 * return meth(model);
2021 * }
2022 * @endcode
2023 *
2024 * @note offset must be bigger than Eina_Model_Type, otherwise use
2025 * specific functions such as eina_model_property_get().
2026 *
2027 * @see eina_model_method_resolve
2028 * @see eina_model_type_method_resolve
2029 * @since 1.2
2030 */
2031EAPI const void *eina_model_method_offset_resolve(const Eina_Model *model, unsigned int offset) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT EINA_PURE;
2032
2033/**
2034 * @brief Gets resolved method from @a type of @a model given @a offset.
2035 * @param type The type whose method offset resolve method will be called.
2036 * @param model The model instance.
2037 * @param offset The offset of the wanted method.
2038 * @return Address to resolved method, or @c NULL if method is not implemented.
2039 *
2040 * @see eina_model_method_offset_resolve()
2041 * @since 1.2
2042 */
2043EAPI const void *eina_model_type_method_offset_resolve(const Eina_Model_Type *type, const Eina_Model *model, unsigned int offset) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT EINA_PURE;
2044
2045#define eina_model_method_resolve(model, struct_type, method) eina_model_method_offset_resolve((model), offsetof(struct_type, method))
2046
2047#define eina_model_type_method_resolve(type, model, struct_type, method) eina_model_type_method_offset_resolve((type), (model), offsetof(struct_type, method))
2048
2049/**
2050 * @def EINA_MODEL_INTERFACE_VERSION
2051 * Current API version, used to validate #_Eina_Model_Interface.
2052 */
2053#define EINA_MODEL_INTERFACE_VERSION (1)
2054
2055/**
2056 * @struct _Eina_Model_Interface
2057 * API to access models.
2058 *
2059 * Interfaces are managed by name, then multiple Eina_Model_Interface
2060 * may have the same name meaning it implements that name.
2061 *
2062 * Each interface will get its own private data of size @c
2063 * private_size (defined at each sub interface), this can be retrieved
2064 * with eina_model_interface_private_data_get().
2065 *
2066 * Private are created @b automatically and should be setup with @c
2067 * setup and flushed with @c flush. All interfaces functions that
2068 * exist are called! Don't call your parent's @c setup or @c flush!
2069 * The setup is done from parent to child. Flush is done from child to
2070 * parent (topological sort is applied to interface graph).
2071 *
2072 * @note The methods @c setup and @c flush should exist if there is
2073 * private data, otherwise memory may be uninitialized or leaks.
2074 * @note It is recommended that @c constructor and @c destructor exist
2075 * to correctly do their roles and call parents in the correct
2076 * order. Whenever they do not exist, their parent pointer is
2077 * called.
2078 * @note Interface's constructor and destructor are only called by
2079 * type counterparts. Unlike setup and flush, they are not
2080 * guaranteed to be called.
2081 * @note use the same name pointer on queries to speed up the lookups!
2082 * @note a runtime check will enforce just types with ABI version
2083 * #EINA_MODEL_INTERFACE_VERSION are used by comparing with the
2084 * @c version member.
2085 *
2086 * @since 1.2
2087 */
2088struct _Eina_Model_Interface
2089{
2090 unsigned int version; /**< must be #EINA_MODEL_INTERFACE_VERSION */
2091 unsigned int private_size; /**< used to allocate interface private data */
2092 unsigned int interface_size; /**< used to know sizeof(Eina_Model_Interface) or subtypes (which may be bigger, by including Eina_Model_Interface as header */
2093 const char *name; /**< name for debug and introspection */
2094 const Eina_Model_Interface **interfaces; /**< null terminated array of parent interfaces */
2095 const Eina_Model_Event_Description *events; /**< null terminated array of events */
2096 Eina_Bool (*setup)(Eina_Model *model); /**< setup interface private data, do @b not call parent interface setup! */
2097 Eina_Bool (*flush)(Eina_Model *model); /**< flush interface private data, do @b not call parent interface flush! */
2098 Eina_Bool (*constructor)(Eina_Model *model); /**< construct interface instance, setup was already called. Should call parent's constructor if needed */
2099 Eina_Bool (*destructor)(Eina_Model *model); /**< destruct interface instance, flush will be called after it. Should call parent's destructor if needed. Release reference to other models here. */
2100 Eina_Bool (*copy)(const Eina_Model *src, Eina_Model *dst); /**< copy interface private data, do @b not call parent interface copy! */
2101 Eina_Bool (*deep_copy)(const Eina_Model *src, Eina_Model *dst); /**< deep copy interface private data, do @b not call parent interface deep copy! */
2102 void *__extension_ptr0; /**< not to be used @internal */
2103 void *__extension_ptr1; /**< not to be used @internal */
2104 void *__extension_ptr2; /**< not to be used @internal */
2105 void *__extension_ptr3; /**< not to be used @internal */
2106};
2107
2108#define EINA_MODEL_INTERFACE_INIT(name, iface, private_type, parent, events) \
2109 {EINA_MODEL_INTERFACE_VERSION, \
2110 sizeof(private_type), \
2111 sizeof(iface), \
2112 name, \
2113 parent, \
2114 events, \
2115 NULL, \
2116 NULL, \
2117 NULL, \
2118 NULL, \
2119 NULL, \
2120 NULL, \
2121 NULL, \
2122 NULL, \
2123 NULL, \
2124 NULL \
2125 }
2126
2127#define EINA_MODEL_INTERFACE_INIT_NOPRIVATE(name, iface, parent, events) \
2128 {EINA_MODEL_INTERFACE_VERSION, \
2129 0, \
2130 sizeof(iface), \
2131 name, \
2132 parent, \
2133 events, \
2134 NULL, \
2135 NULL, \
2136 NULL, \
2137 NULL, \
2138 NULL, \
2139 NULL, \
2140 NULL, \
2141 NULL, \
2142 NULL, \
2143 NULL \
2144 }
2145
2146#define EINA_MODEL_INTERFACE_INIT_NULL \
2147 {0, \
2148 0, \
2149 0, \
2150 NULL, \
2151 NULL, \
2152 NULL, \
2153 NULL, \
2154 NULL, \
2155 NULL, \
2156 NULL, \
2157 NULL, \
2158 NULL, \
2159 NULL, \
2160 NULL, \
2161 NULL, \
2162 NULL \
2163 }
2164
2165/**
2166 * @brief Calls the constructor of @a iface on @a model.
2167 * @param iface The interface whose constructor will be called.
2168 * @param model The model instance.
2169 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2170 *
2171 * @warning If @a model doesn't implement @a iface does nothing and returns
2172 * EINA_FALSE.
2173 *
2174 * @see eina_model_new()
2175 * @see _Eina_Model_Interface
2176 * @since 1.2
2177 */
2178EAPI Eina_Bool eina_model_interface_constructor(const Eina_Model_Interface *iface,
2179 Eina_Model *model) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT;
2180/**
2181 * @brief Calls the destructor of @a iface on @a model.
2182 * @param iface The interface whose destructor will be called.
2183 * @param model The model instance.
2184 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2185 *
2186 * @warning If @a model doesn't implement @a iface does nothing and returns
2187 * EINA_FALSE.
2188 *
2189 * @see eina_model_del()
2190 * @see _Eina_Model_Interface
2191 * @since 1.2
2192 */
2193EAPI Eina_Bool eina_model_interface_destructor(const Eina_Model_Interface *iface,
2194 Eina_Model *model) EINA_ARG_NONNULL(1, 2);
2195/**
2196 * @brief Calls the copy method of @a iface on @a model.
2197 * @param iface The interface whose copy method will be called.
2198 * @param src Pointer to the model to be copied.
2199 * @param dst Pointer to where copy will be put.
2200 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2201 *
2202 * @warning If @a model doesn't implement @a iface does nothing and returns
2203 * EINA_FALSE.
2204 *
2205 * @see eina_model_copy()
2206 * @see _Eina_Model_Interface
2207 * @since 1.2
2208 */
2209EAPI Eina_Bool eina_model_interface_copy(const Eina_Model_Interface *iface,
2210 const Eina_Model *src,
2211 Eina_Model *dst) EINA_ARG_NONNULL(1, 2, 3);
2212/**
2213 * @brief Calls the deep copy method of @a iface on @a model.
2214 * @param iface The interface whose deep copy method will be called.
2215 * @param src Pointer to the model to be copied.
2216 * @param dst Pointer to where copy will be put.
2217 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2218 *
2219 * @warning If @a model doesn't implement @a iface does nothing and returns
2220 * EINA_FALSE.
2221 *
2222 * @see eina_model_deep_copy()
2223 * @see _Eina_Model_Interface
2224 * @since 1.2
2225 */
2226EAPI Eina_Bool eina_model_interface_deep_copy(const Eina_Model_Interface *iface,
2227 const Eina_Model *src,
2228 Eina_Model *dst) EINA_ARG_NONNULL(1, 2, 3);
2229
2230#define eina_model_interface_method_resolve(iface, model, struct_type, method) eina_model_interface_method_offset_resolve((iface), (model), offsetof(struct_type, method))
2231
2232/**
2233 * @brief Gets the @a iface's method for @a model at @a offset.
2234 * @param iface The interface whose method offset resolve method will be called.
2235 * @param model The model instance.
2236 * @param offset The offset of the wanted method.
2237 * @return Address to resolved method, or @c NULL if method is not implemented.
2238 *
2239 * @see eina_model_method_offset_resolve()
2240 * @since 1.2
2241 */
2242EAPI const void *eina_model_interface_method_offset_resolve(const Eina_Model_Interface *iface, const Eina_Model *model, unsigned int offset) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT EINA_PURE;
2243
2244
2245/**
2246 * @struct _Eina_Model_Event_Description
2247 * Data Model Event Description.
2248 *
2249 * @see EINA_MODEL_EVENT_DESCRIPTION()
2250 * @see #EINA_MODEL_EVENT_DESCRIPTION_SENTINEL
2251 * @since 1.2
2252 */
2253struct _Eina_Model_Event_Description
2254{
2255 const char *name; /**< name used for lookups */
2256 const char *type; /**< used for introspection purposes, documents what goes as callback event information (@c event_info) */
2257 const char *doc; /**< documentation for introspection purposes */
2258};
2259
2260/**
2261 * @def EINA_MODEL_EVENT_DESCRIPTION
2262 *
2263 * Helper to define Eina_Model_Event_Description fields.
2264 *
2265 * @since 1.2
2266 */
2267#define EINA_MODEL_EVENT_DESCRIPTION(name, type, doc) {name, type, doc}
2268
2269/**
2270 * @def EINA_MODEL_EVENT_DESCRIPTION_SENTINEL
2271 *
2272 * Helper to define Eina_Model_Event_Description fields for sentinel (last
2273 * item).
2274 *
2275 * @since 1.2
2276 */
2277#define EINA_MODEL_EVENT_DESCRIPTION_SENTINEL {NULL, NULL, NULL}
2278
2279/**
2280 * @brief Check @a type is valid.
2281 * @param type The type to be checked.
2282 * @return #EINA_TRUE on success, #EINA_FALSE otherwise.
2283 *
2284 * @since 1.2
2285 */
2286EAPI Eina_Bool eina_model_type_check(const Eina_Model_Type *type) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT EINA_PURE;
2287/**
2288 * @brief Gets the name @a type.
2289 * @param type The type whose name is wanted.
2290 * @return Name of @a type.
2291 *
2292 * @since 1.2
2293 */
2294EAPI const char *eina_model_type_name_get(const Eina_Model_Type *type) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT EINA_PURE;
2295/**
2296 * @brief Gets the parent type of @a type.
2297 * @param type The type whose parent is wanted.
2298 * @return Type of parent.
2299 *
2300 * @since 1.2
2301 */
2302EAPI const Eina_Model_Type *eina_model_type_parent_get(const Eina_Model_Type *type) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT EINA_PURE;
2303
2304/**
2305 * @brief Setup the type to be a subclass of another parent type.
2306 * @param type type to be modified
2307 * @param parent type to be used as parent
2308 * @return #EINA_TRUE on success, #EINA_FALSE otherwise.
2309 *
2310 * Although @a type is modified, the following properties are not
2311 * touched or they are actually used for validation:
2312 *
2313 * @li @c type->version must be #EINA_MODEL_TYPE_VERSION;
2314 * @li @c type->private_size unmodified, should be set to type's size;
2315 * @li @c type->name unmodified, should be set to type's name.
2316 *
2317 *
2318 * All other fields are modified as follow:
2319 *
2320 * @li @c type->type_size initiated to parent->type_size
2321 * @li @c type->interfaces = NULL;
2322 * @li @c type->events = NULL;
2323 * @li @c type->setup = NULL;
2324 * @li @c type->flush = NULL;
2325 * @li @c type->constructor = NULL;
2326 * @li @c type->destructor = NULL;
2327 * @li @c type->copy = NULL;
2328 * @li @c type->deep_copy = NULL;
2329 * @li @c type->compare = NULL;
2330 * @li @c type->load = NULL;
2331 * @li @c type->unload = NULL;
2332 * @li @c type->property_get = NULL;
2333 * @li @c type->property_set = NULL;
2334 * @li @c type->property_del = NULL;
2335 * @li @c type->properties_names_list_get = NULL;
2336 * @li @c type->child_count = NULL;
2337 * @li @c type->child_get = NULL;
2338 * @li @c type->child_set = NULL;
2339 * @li @c type->child_del = NULL;
2340 * @li @c type->child_insert_at = NULL;
2341 * @li @c type->child_find = NULL;
2342 * @li @c type->child_criteria_match = NULL;
2343 * @li @c type->child_sort = NULL;
2344 * @li @c type->child_iterator_get = NULL;
2345 * @li @c type->child_reversed_iterator_get = NULL;
2346 * @li @c type->child_sorted_iterator_get = NULL;
2347 * @li @c type->child_filtered_iterator_get = NULL;
2348 * @li @c type->to_string = NULL;
2349 *
2350 * If you have custom methods, overload them afterwards
2351 * eina_model_type_subclass_setup() returns with #EINA_TRUE.
2352 *
2353 * @since 1.2
2354 */
2355EAPI Eina_Bool eina_model_type_subclass_setup(Eina_Model_Type *type,
2356 const Eina_Model_Type *parent) EINA_ARG_NONNULL(1, 2);
2357
2358/**
2359 * @brief Checks if @a type is a subclass of(or the same as) @a self_or_parent.
2360 * @param type The type to be checked.
2361 * @param self_or_parent The type being checked for.
2362 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2363 *
2364 * @since 1.2
2365 */
2366EAPI Eina_Bool eina_model_type_subclass_check(const Eina_Model_Type *type,
2367 const Eina_Model_Type *self_or_parent) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT EINA_PURE;
2368
2369
2370/**
2371 * @brief Gets a interface with name @a name from @a type.
2372 * @param type The type instance.
2373 * @param name The name of the desired interface.
2374 * @return The interface implemented by @a type with name @a name, or null if
2375 * this type doesn't implement any interface with name @a name.
2376 *
2377 * @since 1.2
2378 */
2379EAPI const Eina_Model_Interface *eina_model_type_interface_get(const Eina_Model_Type *type,
2380 const char *name) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT EINA_PURE;
2381
2382/**
2383 * @brief Gets the private date of @a model for type @a type.
2384 * @param model The model instance.
2385 * @param type The type whose private data will be gotten.
2386 * @return Pointer to type's private data.
2387 *
2388 * @since 1.2
2389 */
2390EAPI void *eina_model_type_private_data_get(const Eina_Model *model,
2391 const Eina_Model_Type *type) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1, 2) EINA_PURE;
2392
2393/**
2394 * @brief Checks if @a iface is a valid interface.
2395 * @param iface The interface instance.
2396 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2397 *
2398 * @since 1.2
2399 */
2400EAPI Eina_Bool eina_model_interface_check(const Eina_Model_Interface *iface) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT EINA_PURE;
2401
2402/**
2403 * @brief Gets the private date of @a model for interface @a iface.
2404 * @param model The model instance.
2405 * @param iface The interface whose private data will be gotten.
2406 * @return Pointer to interface's private data.
2407 *
2408 * @since 1.2
2409 */
2410EAPI void *eina_model_interface_private_data_get(const Eina_Model *model,
2411 const Eina_Model_Interface *iface) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1, 2) EINA_PURE;
2412
2413/**
2414 * @def EINA_MODEL_INTERFACE_PROPERTIES_VERSION
2415 * Current API version, used to validate #_Eina_Model_Interface_Properties.
2416 */
2417#define EINA_MODEL_INTERFACE_PROPERTIES_VERSION (1)
2418
2419/**
2420 * @typedef Eina_Model_Interface_Properties
2421 * Interface to manage model's properties.
2422 *
2423 * This extends #Eina_Model_Interface as expected by interface name
2424 * #EINA_MODEL_INTERFACE_NAME_PROPERTIES.
2425 *
2426 * This interface is meant to help managing properties of a model, it
2427 * is used by #EINA_MODEL_TYPE_MIXIN in order to configure methods for
2428 * children independently from properties.
2429 *
2430 * @see #_Eina_Model_Interface_Properties explains fields.
2431 * @since 1.2
2432 */
2433typedef struct _Eina_Model_Interface_Properties Eina_Model_Interface_Properties;
2434
2435/**
2436 * @struct _Eina_Model_Interface_Properties
2437 * Interface to manage model's properties.
2438 *
2439 * This extends #Eina_Model_Interface as expected by interface name
2440 * #EINA_MODEL_INTERFACE_NAME_PROPERTIES.
2441 *
2442 * This interface is meant to help managing properties of a model, it
2443 * is used by #EINA_MODEL_TYPE_MIXIN in order to configure methods for
2444 * children independently from properties.
2445 *
2446 * @since 1.2
2447 */
2448struct _Eina_Model_Interface_Properties
2449{
2450 Eina_Model_Interface base; /**< common interface methods */
2451 unsigned int version; /**< must be #EINA_MODEL_INTERFACE_PROPERTIES_VERSION */
2452 Eina_Bool (*compare)(const Eina_Model *a, const Eina_Model *b, int *cmp); /**< How to compare properties of this model */
2453 Eina_Bool (*load)(Eina_Model *model); /**< How to load properties of this model */
2454 Eina_Bool (*unload)(Eina_Model *model); /**< How to unload properties of this model */
2455 Eina_Bool (*get)(const Eina_Model *model, const char *name, Eina_Value *value); /**< Retrieve a property of this model given its name. The value will be returned as a copy and must be flushed with eina_value_flush(). The previous contents of value is ignored. */
2456 Eina_Bool (*set)(Eina_Model *model, const char *name, const Eina_Value *value); /**< Set a property of this model given its name. The value is assumed to be valied and is copied internally, thus it can be safely cleared with eina_value_flush() after this function returns. */
2457 Eina_Bool (*del)(Eina_Model *model, const char *name); /**< Delete a property given its name */
2458 Eina_List *(*names_list_get)(const Eina_Model *model); /**< List of stringshare with known property names */
2459};
2460
2461/**
2462 * @brief Compares properties using @a iface's comparing function.
2463 *
2464 * @param[in] iface The interface used to compare the properties.
2465 * @param[in] a The first model whose properties will be compared.
2466 * @param[in] b The second model whose properties will be compared.
2467 * @param[out] cmp A pointer to an integer which will contain the result of the
2468 * comparison.
2469 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2470 *
2471 * @warning If either model doesn't implement @a iface will do nothing and
2472 * return EINA_FALSE.
2473 *
2474 * @see eina_model_compare()
2475 * @since 1.2
2476 */
2477EAPI Eina_Bool eina_model_interface_properties_compare(const Eina_Model_Interface *iface,
2478 const Eina_Model *a,
2479 const Eina_Model *b,
2480 int *cmp) EINA_ARG_NONNULL(1, 2, 3, 4) EINA_WARN_UNUSED_RESULT;
2481
2482/**
2483 * @brief Loads properties using @a iface's loading function.
2484 * @param iface The properties interface whose load method will be called.
2485 * @param model The model instance.
2486 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2487 *
2488 * @warning If either model doesn't implement @a iface will do nothing and
2489 * return EINA_FALSE.
2490 *
2491 * @see eina_model_load()
2492 * @since 1.2
2493 */
2494EAPI Eina_Bool eina_model_interface_properties_load(const Eina_Model_Interface *iface,
2495 Eina_Model *model) EINA_ARG_NONNULL(1, 2);
2496/**
2497 * @brief Unloads properties using @a iface's unloading function.
2498 * @param iface The properties interface whose unload method will be called.
2499 * @param model The model instance.
2500 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2501 *
2502 * @warning If either model doesn't implement @a iface will do nothing and
2503 * return EINA_FALSE.
2504 *
2505 * @see eina_model_unload()
2506 * @since 1.2
2507 */
2508EAPI Eina_Bool eina_model_interface_properties_unload(const Eina_Model_Interface *iface,
2509 Eina_Model *model) EINA_ARG_NONNULL(1, 2);
2510/**
2511 * @brief Gets property named @a name using @a iface's function to get properties.
2512 * @param iface The properties interface whose property get method will be called.
2513 * @param model The model instance.
2514 * @param name The name of the property to get.
2515 * @param value Pointer to where value will be stored.
2516 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2517 *
2518 * @warning If either model doesn't implement @a iface will do nothing and
2519 * return EINA_FALSE.
2520 *
2521 * @see eina_model_property_get()
2522 * @since 1.2
2523 */
2524EAPI Eina_Bool eina_model_interface_properties_get(const Eina_Model_Interface *iface,
2525 const Eina_Model *model,
2526 const char *name,
2527 Eina_Value *value) EINA_ARG_NONNULL(1, 2, 3, 4);
2528/**
2529 * @brief Sets property named @a name using @a iface's function to set properties.
2530 * @param iface The properties interface whose property set method will be called.
2531 * @param model The model instance.
2532 * @param name The name of the property to set.
2533 * @param value The value to be set.
2534 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2535 *
2536 * @warning If either model doesn't implement @a iface will do nothing and
2537 * return EINA_FALSE.
2538 *
2539 * @see eina_model_property_set()
2540 * @since 1.2
2541 */
2542EAPI Eina_Bool eina_model_interface_properties_set(const Eina_Model_Interface *iface,
2543 Eina_Model *model,
2544 const char *name,
2545 const Eina_Value *value) EINA_ARG_NONNULL(1, 2, 3, 4);
2546/**
2547 * @brief Deletes property named @a name using @a iface's function to delete properties.
2548 * @param iface The properties interface whose property delete method will be called.
2549 * @param model The model instance.
2550 * @param name The name of the property to delete.
2551 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2552 *
2553 * @warning If either model doesn't implement @a iface will do nothing and
2554 * return EINA_FALSE.
2555 *
2556 * @see eina_model_property_del()
2557 * @since 1.2
2558 */
2559EAPI Eina_Bool eina_model_interface_properties_del(const Eina_Model_Interface *iface,
2560 Eina_Model *model,
2561 const char *name) EINA_ARG_NONNULL(1, 2, 3);
2562/**
2563 * @brief Gets properties name list using @a iface's function to get properties
2564 * name list.
2565 * @param iface The properties interface whose property name list get method
2566 * will be called.
2567 * @param model The model instance.
2568 * @return #Eina_List of properties' names.
2569 *
2570 * @warning If either model doesn't implement @a iface will do nothing and
2571 * return EINA_FALSE.
2572 *
2573 * @see eina_model_properties_names_list_get()
2574 * @since 1.2
2575 */
2576EAPI Eina_List *eina_model_interface_properties_names_list_get(const Eina_Model_Interface *iface,
2577 const Eina_Model *model) EINA_ARG_NONNULL(1, 2); /**< list of stringshare */
2578
2579/**
2580 * @typedef Eina_Model_Interface_Children
2581 * Interface to manage model's children.
2582 *
2583 * This extends #Eina_Model_Interface as expected by interface name
2584 * #EINA_MODEL_INTERFACE_NAME_CHILDREN.
2585 *
2586 * This interface is meant to help managing properties of a model, it
2587 * is used by #EINA_MODEL_TYPE_MIXIN in order to configure methods for
2588 * children independently from properties.
2589 *
2590 * @see #_Eina_Model_Interface_Children explains fields.
2591 * @since 1.2
2592 */
2593typedef struct _Eina_Model_Interface_Children Eina_Model_Interface_Children;
2594
2595/**
2596 * @def EINA_MODEL_INTERFACE_CHILDREN_VERSION
2597 * Current API version, used to validate #_Eina_Model_Interface_Children.
2598 */
2599#define EINA_MODEL_INTERFACE_CHILDREN_VERSION (1)
2600
2601/**
2602 * @struct _Eina_Model_Interface_Children
2603 * Interface to manage model's children.
2604 *
2605 * This extends #Eina_Model_Interface as expected by interface name
2606 * #EINA_MODEL_INTERFACE_NAME_CHILDREN.
2607 *
2608 * This interface is meant to help managing properties of a model, it
2609 * is used by #EINA_MODEL_TYPE_MIXIN in order to configure methods for
2610 * children independently from properties.
2611 *
2612 * @since 1.2
2613 */
2614struct _Eina_Model_Interface_Children
2615{
2616 Eina_Model_Interface base; /**< common interface methods */
2617 unsigned int version; /**< must be #EINA_MODEL_INTERFACE_CHILDREN_VERSION */
2618 Eina_Bool (*compare)(const Eina_Model *a, const Eina_Model *b, int *cmp); /**< How to compare children of this model */
2619 Eina_Bool (*load)(Eina_Model *model); /**< How to load children of this model */
2620 Eina_Bool (*unload)(Eina_Model *model); /**< How to unload children of this model */
2621 int (*count)(const Eina_Model *model); /**< How many children of this model */
2622 Eina_Model *(*get)(const Eina_Model *model, unsigned int position); /**< Retrieve a child of this model, returned child must have reference increased! */
2623 Eina_Bool (*set)(Eina_Model *model, unsigned int position, Eina_Model *child); /**< Set (replace) a child of this model, given child will have reference increased! */
2624 Eina_Bool (*del)(Eina_Model *model, unsigned int position); /**< Delete a child of this model. Existing child will have reference decreased! */
2625 Eina_Bool (*insert_at)(Eina_Model *model, unsigned int position, Eina_Model *child); /**< Insert a child into this model, given child will have reference increased! All elements towards the end of the internal list will be shifted to the end to make room for the new child. */
2626 void (*sort)(Eina_Model *model, Eina_Compare_Cb compare); /**< Reorder children to be sorted respecting comparison function @c compare() */
2627};
2628
2629/**
2630 * @brief Compares children using @a iface's comparing function.
2631 *
2632 * @param[in] iface The interface used to compare the properties.
2633 * @param[in] a The first model whose properties will be compared.
2634 * @param[in] b The second model whose properties will be compared.
2635 * @param[out] cmp A pointer to an integer which will contain the result of the
2636 * comparison.
2637 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2638 *
2639 * @warning If either model doesn't implement @a iface will do nothing and
2640 * return EINA_FALSE.
2641 *
2642 * @see eina_model_compare()
2643 * @since 1.2
2644 */
2645EAPI Eina_Bool eina_model_interface_children_compare(const Eina_Model_Interface *iface,
2646 const Eina_Model *a,
2647 const Eina_Model *b,
2648 int *cmp) EINA_ARG_NONNULL(1, 2, 3, 4) EINA_WARN_UNUSED_RESULT;
2649/**
2650 * @brief Loads children using @a iface's loading function.
2651 * @param iface The children interface whose load method will be called.
2652 * @param model The model instance.
2653 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2654 *
2655 * @warning If either model doesn't implement @a iface will do nothing and
2656 * return EINA_FALSE.
2657 *
2658 * @see eina_model_load()
2659 * @since 1.2
2660 */
2661EAPI Eina_Bool eina_model_interface_children_load(const Eina_Model_Interface *iface,
2662 Eina_Model *model) EINA_ARG_NONNULL(1, 2);
2663/**
2664 * @brief Unloads children using @a iface's unloading function.
2665 * @param iface The children interface whose unload method will be called.
2666 * @param model The model instance.
2667 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2668 *
2669 * @warning If either model doesn't implement @a iface will do nothing and
2670 * return EINA_FALSE.
2671 *
2672 * @see eina_model_unload()
2673 * @since 1.2
2674 */
2675EAPI Eina_Bool eina_model_interface_children_unload(const Eina_Model_Interface *iface,
2676 Eina_Model *model) EINA_ARG_NONNULL(1, 2);
2677/**
2678 * @brief Count children using @a iface's counting function.
2679 * @param iface The children interface whose count method will be called.
2680 * @param model The model instance.
2681 * @return Number of children in @a model.
2682 *
2683 * @warning If either model doesn't implement @a iface will do nothing and
2684 * return -1.
2685 *
2686 * @see eina_model_child_count()
2687 * @since 1.2
2688 */
2689EAPI int eina_model_interface_children_count(const Eina_Model_Interface *iface,
2690 const Eina_Model *model) EINA_ARG_NONNULL(1, 2);
2691/**
2692 * @brief Get child using @a iface's function to get children.
2693 * @param iface The children interface whose get method will be called.
2694 * @param model The model instance.
2695 * @param position Position of child to be retrieved.
2696 * @return The requested child.
2697 *
2698 * @warning If either model doesn't implement @a iface will do nothing and
2699 * return -1.
2700 *
2701 * @see eina_model_child_get()
2702 * @since 1.2
2703 */
2704EAPI Eina_Model *eina_model_interface_children_get(const Eina_Model_Interface *iface,
2705 const Eina_Model *model,
2706 unsigned int position) EINA_ARG_NONNULL(1, 2);
2707/**
2708 * @brief Set child using @a iface's function to set children.
2709 * @param iface The children interface whose set method will be called.
2710 * @param model The model instance.
2711 * @param position Position of child to be set.
2712 * @param child Value(child) to be set.
2713 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2714 *
2715 * @warning If either model doesn't implement @a iface will do nothing and
2716 * return -1.
2717 *
2718 * @see eina_model_child_set()
2719 * @since 1.2
2720 */
2721EAPI Eina_Bool eina_model_interface_children_set(const Eina_Model_Interface *iface,
2722 Eina_Model *model,
2723 unsigned int position,
2724 Eina_Model *child) EINA_ARG_NONNULL(1, 2, 4);
2725/**
2726 * @brief Delete child using @a iface's function to delete children.
2727 * @param iface The children interface whose delete method will be called.
2728 * @param model The model instance.
2729 * @param position Position of child to be deleted.
2730 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2731 *
2732 * @warning If either model doesn't implement @a iface will do nothing and
2733 * return -1.
2734 *
2735 * @see eina_model_child_del()
2736 * @since 1.2
2737 */
2738EAPI Eina_Bool eina_model_interface_children_del(const Eina_Model_Interface *iface,
2739 Eina_Model *model,
2740 unsigned int position) EINA_ARG_NONNULL(1, 2);
2741/**
2742 * @brief Insert child using @a iface's function to insert children.
2743 * @param iface The children interface whose insert method will be called.
2744 * @param model The model instance.
2745 * @param position Position in which to insert @a child.
2746 * @param child Value(child) to be inserted.
2747 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2748 *
2749 * @warning If either model doesn't implement @a iface will do nothing and
2750 * return -1.
2751 *
2752 * @see eina_model_child_insert_at()
2753 * @since 1.2
2754 */
2755EAPI Eina_Bool eina_model_interface_children_insert_at(const Eina_Model_Interface *iface,
2756 Eina_Model *model,
2757 unsigned int position,
2758 Eina_Model *child) EINA_ARG_NONNULL(1, 2, 4);
2759/**
2760 * @brief Sort children using @a iface's function to sort children.
2761 * @param iface The children interface whose sort method will be called.
2762 * @param model The model instance.
2763 * @param compare Function used to compare children.
2764 *
2765 * @warning If either model doesn't implement @a iface will do nothing and
2766 * return -1.
2767 *
2768 * @see eina_model_child_sort().
2769 * @since 1.2
2770 */
2771EAPI void eina_model_interface_children_sort(const Eina_Model_Interface *iface,
2772 Eina_Model *model,
2773 Eina_Compare_Cb compare) EINA_ARG_NONNULL(1, 2, 3);
2774
2775
2776/**
2777 * @}
2778 */
2779
2780/**
2781 * @defgroup Eina_Model_Utils_Group Data Model Utilities
2782 *
2783 * Miscellaneous utilities to help usage or debug of @ref Eina_Model_Group.
2784 *
2785 * @{
2786 */
2787
2788/**
2789 * @brief Checks if @a model is an instance of @a type.
2790 * @param model The model instance.
2791 * @param type The type being checked for.
2792 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2793 *
2794 * @see eina_model_new()
2795 * @see _Eina_Model_Type
2796 * @since 1.2
2797 */
2798EAPI Eina_Bool eina_model_instance_check(const Eina_Model *model,
2799 const Eina_Model_Type *type) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT EINA_PURE;
2800
2801/**
2802 * @brief Checks if @a model implements @a iface.
2803 * @param model The model instance.
2804 * @param iface The interface being checked for.
2805 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2806 *
2807 * @see _Eina_Model_Interface
2808 * @since 1.2
2809 */
2810EAPI Eina_Bool eina_model_interface_implemented(const Eina_Model *model, const Eina_Model_Interface *iface) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT EINA_PURE;
2811
2812/**
2813 * @brief Returns the number of references to @a model.
2814 * @param model The model to query number of references.
2815 * @return Number of references to model.
2816 *
2817 * @see eina_model_ref()
2818 * @see eina_model_unref()
2819 * @see eina_model_xref()
2820 * @see eina_model_xunref()
2821 * @see eina_model_xrefs_get()
2822 * @since 1.2
2823 */
2824EAPI int eina_model_refcount(const Eina_Model *model) EINA_ARG_NONNULL(1);
2825
2826/**
2827 * @typedef Eina_Model_XRef
2828 * Extended reference to model.
2829 *
2830 * This is returned by eina_model_xrefs_get() and should never be
2831 * modified. It is managed by eina_model_xref() and
2832 * eina_model_xunref() when @c EINA_MODEL_DEBUG is set to "1" or
2833 * "backtrace".
2834 *
2835 * @see #_Eina_Model_XRef explains fields.
2836 * @since 1.2
2837 */
2838typedef struct _Eina_Model_XRef Eina_Model_XRef;
2839
2840/**
2841 * @struct _Eina_Model_XRef
2842 * Extended reference to model.
2843 *
2844 * This is returned by eina_model_xrefs_get() and should never be
2845 * modified. It is managed by eina_model_xref() and
2846 * eina_model_xunref() when @c EINA_MODEL_DEBUG is set to "1" or
2847 * "backtrace".
2848 *
2849 * @see eina_model_xrefs_get()
2850 * @see eina_models_usage_dump()
2851 * @since 1.2
2852 */
2853struct _Eina_Model_XRef
2854{
2855 EINA_INLIST;
2856 const void *id; /**< as given to eina_model_xref() */
2857 struct {
2858 const void * const *symbols; /**< only if @c EINA_MODEL_DEBUG=backtrace is set, otherwise is @c NULL */
2859 unsigned int count; /**< only if @c EINA_MODEL_DEBUG=backtrace is set, otherwise is 0 */
2860 } backtrace;
2861 char label[]; /**< Any given label given to eina_model_xref(). */
2862};
2863
2864/**
2865 * @brief Returns the current references of this model.
2866 * @param model The model to query references.
2867 * @return List of reference holders as Eina_Model_XRef. This is the internal
2868 * list for speed purposes, do not modify or free it in anyway!
2869 *
2870 * @note This list only exist if environment variable
2871 * @c EINA_MODEL_DEBUG is set to "1" or "backtrace".
2872 *
2873 * @note The backtrace information is only available if environment
2874 * variable @c EINA_MODEL_DEBUG=backtrace is set.
2875 * @since 1.2
2876 */
2877EAPI const Eina_Inlist *eina_model_xrefs_get(const Eina_Model *model) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT EINA_MALLOC;
2878
2879/**
2880 * @brief Dump usage of all existing modules.
2881 * @since 1.2
2882 */
2883EAPI void eina_models_usage_dump(void);
2884
2885/**
2886 * @brief Return a list of all live models.
2887 * @return a newly allocated list of Eina_Model. Free using
2888 * eina_models_list_free()
2889 *
2890 * @note this is meant to debug purposes, do not modify the models in
2891 * any way!
2892 *
2893 * @note due performance reasons, this is only @b enabled when
2894 * @c EINA_MODEL_DEBUG is set to "1" or "backtrace".
2895 *
2896 * @since 1.2
2897 */
2898EAPI Eina_List *eina_models_list_get(void);
2899
2900/**
2901 * @brief Release list returned by eina_models_list_get()
2902 * @param list the list to release.
2903 */
2904EAPI void eina_models_list_free(Eina_List *list);
2905
2906/**
2907 * @}
2908 */
2909
2910/**
2911 * @var EINA_MODEL_INTERFACE_CHILDREN_INARRAY
2912 *
2913 * Implements #Eina_Model_Interface_Children
2914 * (#EINA_MODEL_INTERFACE_NAME_CHILDREN) using #Eina_Inarray. It
2915 * should be efficient in space and time for most operations.
2916 *
2917 * @note it may become slow if eina_model_child_insert_at() is used at(or near)
2918 * the beginning of the array as the members from that position
2919 * to the end must be memmove()d.
2920 *
2921 * @since 1.2
2922 */
2923EAPI extern const Eina_Model_Interface *EINA_MODEL_INTERFACE_CHILDREN_INARRAY;
2924
2925
2926/**
2927 * @var EINA_MODEL_TYPE_BASE
2928 * Base type for all eina model types.
2929 *
2930 * @since 1.2
2931 */
2932EAPI extern const Eina_Model_Type *EINA_MODEL_TYPE_BASE;
2933
2934/**
2935 * @var EINA_MODEL_TYPE_MIXIN
2936 *
2937 * Type that uses #EINA_MODEL_INTERFACE_NAME_PROPERTIES and
2938 * #EINA_MODEL_INTERFACE_NAME_CHILDREN to manage the model.
2939 *
2940 * This is an abstract type, it does not work out of the box as one
2941 * needs to subclass it and define the interface implementations for
2942 * properties and children, as done by #EINA_MODEL_TYPE_GENERIC
2943 *
2944 * @see EINA_MODEL_TYPE_GENERIC
2945 *
2946 * @since 1.2
2947 */
2948EAPI extern const Eina_Model_Type *EINA_MODEL_TYPE_MIXIN;
2949
2950/**
2951 * @var EINA_MODEL_TYPE_GENERIC
2952 *
2953 * Subclass of #EINA_MODEL_TYPE_MIXIN that uses
2954 * #EINA_MODEL_INTERFACE_PROPERTIES_HASH and
2955 * #EINA_MODEL_INTERFACE_CHILDREN_INARRAY.
2956 *
2957 * Should be generic enough to hold lots of items with runtime
2958 * configurable properties of any type.
2959 *
2960 * @see #EINA_MODEL_TYPE_STRUCT
2961 *
2962 * @since 1.2
2963 */
2964EAPI extern const Eina_Model_Type *EINA_MODEL_TYPE_GENERIC;
2965
2966/**
2967 * @var EINA_MODEL_TYPE_STRUCT
2968 *
2969 * Subclass of #EINA_MODEL_TYPE_MIXIN that uses
2970 * #EINA_MODEL_INTERFACE_PROPERTIES_STRUCT and
2971 * #EINA_MODEL_INTERFACE_CHILDREN_INARRAY.
2972 *
2973 * Should be struct enough to hold lots of items with compile time
2974 * configurable properties of any type.
2975 *
2976 * @see #EINA_MODEL_TYPE_GENERIC
2977 *
2978 * @since 1.2
2979 */
2980EAPI extern const Eina_Model_Type *EINA_MODEL_TYPE_STRUCT;
2981
2982/**
2983 * @brief Create and setup an instance of #EINA_MODEL_TYPE_STRUCT.
2984 * @param desc struct description to use for properties.
2985 * @return newly created and set model, or @c NULL on errors.
2986 *
2987 * @see eina_model_type_struct_new()
2988 * @since 1.2
2989 */
2990EAPI Eina_Model *eina_model_struct_new(const Eina_Value_Struct_Desc *desc) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT EINA_MALLOC;
2991
2992/**
2993 * @brief Create and setup an instance of type subclass of #EINA_MODEL_TYPE_STRUCT.
2994 * @param type a type which is subclass of #EINA_MODEL_TYPE_STRUCT.
2995 * @param desc struct description to use for properties.
2996 * @return newly created and set model, or @c NULL on errors.
2997 *
2998 * @see eina_model_struct_new()
2999 * @since 1.2
3000 */
3001EAPI Eina_Model *eina_model_type_struct_new(const Eina_Model_Type *type,
3002 const Eina_Value_Struct_Desc *desc) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT EINA_MALLOC;
3003
3004
3005/**
3006 * @brief Configure the internal properties of model implementing #EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.
3007 * @param model The model instance to configure.
3008 * @param desc The structure description to use.
3009 * @param memory If not @c NULL, will be copied by model.
3010 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
3011 *
3012 * This will setup the internal pointers so that the given @a desc is
3013 * used to manage the properties of this struct.
3014 *
3015 * If a given memory is provided, it will be copied (including
3016 * members) and no references are taken after this function returns.
3017 *
3018 * @see #EINA_VALUE_TYPE_STRUCT
3019 *
3020 * @since 1.2
3021 */
3022EAPI Eina_Bool eina_model_struct_set(Eina_Model *model,
3023 const Eina_Value_Struct_Desc *desc,
3024 void *memory) EINA_ARG_NONNULL(1, 2);
3025/**
3026 * @brief Get the internal properties of model implementing #EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.
3027 * @param model the model instance.
3028 * @param p_desc where to return the structure description in use.
3029 * @param p_memory where to return the structure memory in use.
3030 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
3031 *
3032 * No copies are made! The memory and description may be invalidaded
3033 * by calls to eina_model_struct_set() or eina_model_del().
3034 *
3035 * @since 1.2
3036 */
3037EAPI Eina_Bool eina_model_struct_get(const Eina_Model *model,
3038 const Eina_Value_Struct_Desc **p_desc,
3039 void **p_memory) EINA_ARG_NONNULL(1, 2);
3040
3041/**
3042 * @var EINA_MODEL_INTERFACE_NAME_PROPERTIES
3043 *
3044 * Interface that uses #Eina_Model_Interface_Properties as
3045 * #Eina_Model_Interface and can manage the model properties.
3046 *
3047 * @since 1.2
3048 */
3049EAPI extern const char *EINA_MODEL_INTERFACE_NAME_PROPERTIES;
3050
3051/**
3052 * @var EINA_MODEL_INTERFACE_PROPERTIES_HASH
3053 *
3054 * Implements #Eina_Model_Interface_Properties
3055 * (#EINA_MODEL_INTERFACE_NAME_PROPERTIES) using #Eina_Hash.
3056 *
3057 * @note This function is generic but uses too much space given the
3058 * hash data type. For huge number of elements it's better to
3059 * use custom implementation instead.
3060 *
3061 * @see EINA_MODEL_INTERFACE_PROPERTIES_STRUCT
3062 *
3063 * @since 1.2
3064 */
3065EAPI extern const Eina_Model_Interface *EINA_MODEL_INTERFACE_PROPERTIES_HASH;
3066
3067/**
3068 * @var EINA_MODEL_INTERFACE_PROPERTIES_STRUCT
3069 *
3070 * Implements #Eina_Model_Interface_Properties
3071 * (#EINA_MODEL_INTERFACE_NAME_PROPERTIES) using #Eina_Value_Struct.
3072 *
3073 * The interface private data is #Eina_Value of type
3074 * #EINA_VALUE_TYPE_STRUCT. Properties will be accessed using
3075 * Eina_Value_Struct::desc information that can be set by types such
3076 * as #EINA_MODEL_TYPE_STRUCT
3077 *
3078 * @see EINA_MODEL_INTERFACE_PROPERTIES_HASH
3079 *
3080 * @since 1.2
3081 */
3082EAPI extern const Eina_Model_Interface *EINA_MODEL_INTERFACE_PROPERTIES_STRUCT;
3083
3084/**
3085 * @var EINA_MODEL_INTERFACE_NAME_CHILDREN
3086 *
3087 * Interface that uses #Eina_Model_Interface_Children as
3088 * #Eina_Model_Interface and can manage the model children.
3089 *
3090 * @since 1.2
3091 */
3092EAPI extern const char *EINA_MODEL_INTERFACE_NAME_CHILDREN;
3093
3094/**
3095 * @}
3096 */
3097
3098/**
3099 * @}
3100 */
3101
3102/**
3103 * @}
3104 */
3105#endif
diff --git a/libraries/eina/src/lib/eina_model.c b/libraries/eina/src/lib/eina_model.c
new file mode 100644
index 0000000..ae06c1b
--- /dev/null
+++ b/libraries/eina/src/lib/eina_model.c
@@ -0,0 +1,5548 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2012 ProFUSION embedded systems
3 *
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.
8 *
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.
13 *
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/>.
17 */
18
19#ifdef HAVE_CONFIG_H
20# include "config.h"
21#endif
22
23#ifdef HAVE_ALLOCA_H
24# include <alloca.h>
25#elif defined __GNUC__
26# define alloca __builtin_alloca
27#elif defined _AIX
28# define alloca __alloca
29#elif defined _MSC_VER
30# include <malloc.h>
31# define alloca _alloca
32#else
33# include <stddef.h>
34# ifdef __cplusplus
35extern "C"
36# endif
37void *alloca (size_t);
38#endif
39
40#ifdef HAVE_EXECINFO_H
41#include <execinfo.h>
42#endif
43
44#include "eina_config.h"
45#include "eina_private.h"
46#include "eina_error.h"
47#include "eina_log.h"
48#include "eina_mempool.h"
49#include "eina_lock.h"
50#include "eina_inlist.h"
51#include "eina_strbuf.h"
52
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"
57
58/*============================================================================*
59 * Local *
60 *============================================================================*/
61
62/**
63 * @cond LOCAL
64 */
65
66static Eina_Mempool *_eina_model_mp = NULL;
67static Eina_Hash *_eina_model_inner_mps = NULL;
68static Eina_Lock _eina_model_inner_mps_lock;
69static char *_eina_model_mp_choice = NULL;
70static Eina_Hash *_eina_model_descriptions = NULL;
71static Eina_Lock _eina_model_descriptions_lock;
72static int _eina_model_log_dom = -1;
73static enum {
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;
78static Eina_Lock _eina_model_debug_list_lock;
79static Eina_List *_eina_model_debug_list = NULL;
80
81static const char _eina_model_str_deleted[] = "deleted";
82static const char _eina_model_str_freed[] = "freed";
83static const char _eina_model_str_property_set[] = "property,set";
84static const char _eina_model_str_property_del[] = "property,deleted";
85static const char _eina_model_str_children_changed[] = "children,changed";
86static const char _eina_model_str_child_inserted[] = "child,inserted";
87static const char _eina_model_str_child_set[] = "child,set";
88static const char _eina_model_str_child_del[] = "child,deleted";
89static const char _eina_model_str_loaded[] = "loaded";
90static const char _eina_model_str_unloaded[] = "unloaded";
91static const char _eina_model_str_properties_loaded[] = "properties,loaded";
92static const char _eina_model_str_properties_unloaded[] = "properties,unloaded";
93static const char _eina_model_str_children_loaded[] = "children,loaded";
94static const char _eina_model_str_children_unloaded[] = "children,unloaded";
95
96#ifdef CRITICAL
97#undef CRITICAL
98#endif
99#define CRITICAL(...) EINA_LOG_DOM_CRIT(_eina_model_log_dom, __VA_ARGS__)
100
101#ifdef ERR
102#undef ERR
103#endif
104#define ERR(...) EINA_LOG_DOM_ERR(_eina_model_log_dom, __VA_ARGS__)
105
106#ifdef WRN
107#undef WRN
108#endif
109#define WRN(...) EINA_LOG_DOM_WARN(_eina_model_log_dom, __VA_ARGS__)
110
111#ifdef INF
112#undef INF
113#endif
114#define INF(...) EINA_LOG_DOM_INFO(_eina_model_log_dom, __VA_ARGS__)
115
116#ifdef DBG
117#undef DBG
118#endif
119#define DBG(...) EINA_LOG_DOM_DBG(_eina_model_log_dom, __VA_ARGS__)
120
121
122/* convenience sort array of Eina_Model* giving compare Eina_Model* instead of
123 * Eina_Model**
124 */
125static unsigned int
126_eina_model_array_partition(Eina_Model **array, unsigned int start, unsigned int last, unsigned int pivot, Eina_Compare_Cb compare)
127{
128 Eina_Model **itr, **itr_end, *tmp, *pivot_value;
129
130 pivot_value = tmp = array[pivot];
131 array[pivot] = array[last];
132 array[last] = tmp;
133
134 pivot = start;
135 itr = array + start;
136 itr_end = array + last;
137 for (; itr < itr_end; itr++)
138 {
139 if (compare(*itr, pivot_value) < 0)
140 {
141 tmp = *itr;
142 *itr = array[pivot];
143 array[pivot] = tmp;
144 pivot++;
145 }
146 }
147
148 tmp = array[last];
149 array[last] = array[pivot];
150 array[pivot] = tmp;
151
152 return pivot;
153}
154
155static void
156_eina_model_array_sort(Eina_Model **array, unsigned int start, unsigned int last, Eina_Compare_Cb compare)
157{
158 unsigned int pivot, new_pivot;
159
160 if (last <= start)
161 return;
162
163 pivot = start + (last - start) / 2; /* avoid overflow */
164 new_pivot = _eina_model_array_partition(array, start, last, pivot, compare);
165
166 if (start + 1 < new_pivot)
167 _eina_model_array_sort(array, start, new_pivot - 1, compare);
168
169 if (new_pivot + 1 < last)
170 _eina_model_array_sort(array, new_pivot + 1, last, compare);
171}
172
173/*
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.
176 *
177 * To save on the number of mempools, they are kept per size, not per
178 * type.
179 *
180 * This is done by means of _eina_model_inner_alloc() and
181 * _eina_model_inner_free(), both at thread safe.
182 *
183 */
184typedef struct _Eina_Model_Inner_Mp Eina_Model_Inner_Mp;
185struct _Eina_Model_Inner_Mp
186{
187 Eina_Mempool *mempool;
188 int refcount;
189};
190
191static inline void
192_eina_model_inner_mp_dispose(int size, Eina_Model_Inner_Mp *imp)
193{
194 EINA_SAFETY_ON_FALSE_RETURN(imp->refcount == 0);
195
196 eina_hash_del_by_key(_eina_model_inner_mps, &size);
197 eina_mempool_del(imp->mempool);
198 free(imp);
199}
200
201static inline Eina_Model_Inner_Mp *
202_eina_model_inner_mp_get(int size)
203{
204 Eina_Model_Inner_Mp *imp = eina_hash_find(_eina_model_inner_mps, &size);
205 if (imp) return imp;
206
207 imp = malloc(sizeof(Eina_Model_Inner_Mp));
208 if (!imp)
209 return NULL;
210
211 imp->refcount = 0;
212
213 imp->mempool = eina_mempool_add(_eina_model_mp_choice,
214 "Eina_Model_Inner_Mp", NULL, size, 128);
215 if (!imp->mempool)
216 {
217 free(imp);
218 return NULL;
219 }
220
221 if (!eina_hash_add(_eina_model_inner_mps, &size, imp))
222 {
223 eina_mempool_del(imp->mempool);
224 free(imp);
225 return NULL;
226 }
227
228 return imp;
229}
230
231static inline void *
232_eina_model_inner_alloc_internal(int size)
233{
234 Eina_Model_Inner_Mp *imp;
235 void *mem;
236
237 imp = _eina_model_inner_mp_get(size);
238 if (!imp) return NULL;
239
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);
243
244 return mem;
245}
246
247static inline void
248_eina_model_inner_free_internal(int size, void *mem)
249{
250 Eina_Model_Inner_Mp *imp = eina_hash_find(_eina_model_inner_mps, &size);
251 EINA_SAFETY_ON_NULL_RETURN(imp);
252
253 eina_mempool_free(imp->mempool, mem);
254
255 imp->refcount--;
256 if (imp->refcount > 0) return;
257 _eina_model_inner_mp_dispose(size, imp);
258}
259
260static void *
261_eina_model_inner_alloc(size_t size)
262{
263 void *mem;
264
265 if (size > 512) return malloc(size);
266
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);
270
271 return mem;
272}
273
274static void
275_eina_model_inner_free(size_t size, void *mem)
276{
277 if (size > 512)
278 {
279 free(mem);
280 return;
281 }
282
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);
286}
287
288
289typedef union _Eina_Model_Provider Eina_Model_Provider;
290union _Eina_Model_Provider
291{
292 const Eina_Model_Type *type;
293 const Eina_Model_Interface *iface;
294};
295
296/* store event name to aid searching */
297typedef struct _Eina_Model_Event_Description_Cache Eina_Model_Event_Description_Cache;
298struct _Eina_Model_Event_Description_Cache
299{
300 const char *name;
301 const Eina_Model_Event_Description *desc;
302 Eina_Model_Provider provider;
303};
304
305/* description is an optimized structure for type. It's built at runtime
306 * to avoid user input errors and help declaration.
307 *
308 * lookups (ifaces, events) are sorted for binary search.
309 *
310 * recursion is avoided by expansion of every possible value in "cache"
311 * struct.
312 *
313 * the first usable operation is stopred for type at "ops" struct,
314 * avoiding usage of _eina_model_type_find_offset().
315 *
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
319 * safe.
320 */
321typedef struct _Eina_Model_Description Eina_Model_Description;
322struct _Eina_Model_Description
323{
324 struct {
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 */
329 } cache;
330 struct {
331 /* ops are the topmost operation to use for type/interface */
332 struct {
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;
360 } type;
361 } ops;
362 struct {
363 unsigned int types;
364 unsigned int ifaces;
365 unsigned int privates;
366 unsigned int size; /* sum of all private sizes */
367 unsigned int events;
368 } total;
369 int refcount;
370};
371
372static Eina_Bool
373_eina_model_description_type_fill(Eina_Model_Description *desc, const Eina_Model_Type *type)
374{
375 const Eina_Model_Type *itr, *last_itr = NULL;
376 unsigned int count, child_size = 0;
377
378 for (count = 0, itr = type; itr != NULL; itr = itr->parent, count++)
379 {
380 if (itr->version != EINA_MODEL_TYPE_VERSION)
381 {
382 CRITICAL("Type %p version is %u, expected %u instead.",
383 itr, itr->version, EINA_MODEL_TYPE_VERSION);
384 return EINA_FALSE;
385 }
386 if (!itr->name)
387 {
388 CRITICAL("Type %p provides no name!", itr);
389 return EINA_FALSE;
390 }
391 if (itr->type_size < sizeof(Eina_Model_Type))
392 {
393 CRITICAL("Type %p %s size must be >= sizeof(Eina_Model_Type)!",
394 itr, itr->name);
395 return EINA_FALSE;
396 }
397 if (child_size == 0) child_size = itr->type_size;
398 else if (child_size < itr->type_size)
399 {
400 CRITICAL("Type %p %s size is bigger than its child type %p %s!",
401 itr, itr->name, last_itr, last_itr->name);
402 return EINA_FALSE;
403 }
404 last_itr = itr;
405
406#define DEF_METH(meth) \
407 if (!desc->ops.type.meth) desc->ops.type.meth = itr->meth
408 DEF_METH(setup);
409 DEF_METH(flush);
410 DEF_METH(constructor);
411 DEF_METH(destructor);
412 DEF_METH(copy);
413 DEF_METH(deep_copy);
414 DEF_METH(compare);
415 DEF_METH(load);
416 DEF_METH(unload);
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);
422 DEF_METH(child_get);
423 DEF_METH(child_set);
424 DEF_METH(child_del);
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);
433 DEF_METH(to_string);
434#undef DEF_METH
435
436 if ((!itr->parent) && (itr != EINA_MODEL_TYPE_BASE))
437 {
438 CRITICAL("Type %p (%s) does not inherit from EINA_MODEL_TYPE_BASE!",
439 type, type->name);
440 return EINA_FALSE;
441 }
442 }
443
444#define CK_METH(meth) \
445 if (!desc->ops.type.meth) \
446 { \
447 CRITICAL("Mandatory method "#meth \
448 "() was not provided by type %p (%s).", \
449 type, type->name); \
450 return EINA_FALSE; \
451 }
452 CK_METH(setup);
453 CK_METH(flush);
454 CK_METH(constructor);
455 CK_METH(destructor);
456 CK_METH(property_get);
457#undef CK_METH
458
459 if (child_size <= sizeof(Eina_Model_Type))
460 desc->ops.type.extension = NULL;
461 else
462 {
463 unsigned ext_size = child_size - sizeof(Eina_Model_Type);
464 unsigned ext_count = ext_size / sizeof(void *);
465
466 if (ext_size % sizeof(void *) != 0)
467 {
468 CRITICAL("Extension size %u is not multiple of sizeof(void*)",
469 ext_size);
470 return EINA_FALSE;
471 }
472
473 desc->ops.type.extension = calloc(ext_count, sizeof(void *));
474 EINA_SAFETY_ON_NULL_RETURN_VAL(desc->ops.type.extension, EINA_FALSE);
475
476 for (itr = type; itr != NULL; itr = itr->parent)
477 {
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));
481
482 if (cur_size == 0) break;
483
484 for (i = 0; i < cur_count; i++)
485 {
486 if (desc->ops.type.extension[i]) continue;
487 desc->ops.type.extension[i] = ptr[i];
488 }
489 }
490 }
491
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;
495
496 for (count = 0, itr = type; itr != NULL; itr = itr->parent, count++)
497 desc->cache.types[count] = itr;
498
499 return EINA_TRUE;
500
501 cache_types_failed:
502 free(desc->ops.type.extension);
503 return EINA_FALSE;
504}
505
506static inline Eina_Bool
507_eina_model_interface_implements(const Eina_Model_Interface *iface, const Eina_Model_Interface *query)
508{
509 const Eina_Model_Interface **itr;
510
511 if (iface == query)
512 return EINA_TRUE;
513
514 if (!iface->interfaces)
515 return EINA_FALSE;
516
517 for (itr = iface->interfaces; *itr != NULL; itr++)
518 if (_eina_model_interface_implements(*itr, query))
519 return EINA_TRUE;
520
521 return EINA_FALSE;
522}
523
524/* apply topological sort and remove duplicates */
525/*
526 * TODO: Topological sort will only work for linked interfaces, but
527 * will ignore original ordering provided by types. Consider the
528 * following:
529 *
530 * - A_Type -> X_Iface (name: "MyIface")
531 * - B_Type -> Y_Iface (name: "MyIface")
532 *
533 * Both X_Iface and Y_Iface are different implementations of the
534 * "MyIface".
535 *
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
538 * X_Iface.
539 *
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.
543 *
544 * Thanks to Tasn to report it :-)
545 */
546static Eina_Bool
547_eina_model_description_ifaces_fix(Eina_Model_Description *desc)
548{
549 struct node {
550 const Eina_Model_Interface *iface;
551 unsigned int users;
552 Eina_List *deps;
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;
556
557 nodes = alloca(n_nodes * sizeof(struct node));
558 pending = alloca(n_nodes * sizeof(struct node *));
559 roots = alloca(n_nodes * sizeof(struct node *));
560
561 /* populate */
562 for (i = 0, j = 0; i < n_nodes; i++)
563 {
564 unsigned int k;
565 for (k = 0; k < j; k++)
566 {
567 if (nodes[k].iface == desc->cache.ifaces[i])
568 break;
569 }
570 if (k < j)
571 continue; /* already exists */
572
573 nodes[j].iface = desc->cache.ifaces[i];
574 nodes[j].users = 0;
575 nodes[j].deps = NULL;
576 j++;
577 }
578 n_nodes = j;
579
580 for (i = 0; i < n_nodes; i++)
581 {
582 for (j = 0; j < n_nodes; j++)
583 {
584 if (i == j) continue;
585 if (!_eina_model_interface_implements(nodes[j].iface,
586 nodes[i].iface))
587 continue;
588
589 nodes[i].users++;
590 nodes[j].deps = eina_list_append(nodes[j].deps, nodes + i);
591 }
592 }
593 for (i = 0; i < n_nodes; i++)
594 {
595 if (nodes[i].users == 0)
596 {
597 roots[n_roots] = nodes + i;
598 n_roots++;
599 }
600 else
601 {
602 pending[n_pending] = nodes + i;
603 n_pending++;
604 }
605 }
606
607 /* topological sort */
608 desc->total.ifaces = 0;
609 while (n_roots > 0)
610 {
611 struct node *r, *d;
612
613 /* TODO: sort roots using input order? Or at least study if
614 * it's enough to change roots append to prepend.
615 *
616 * See comments above.
617 */
618 n_roots--;
619 r = roots[n_roots];
620
621 desc->cache.ifaces[desc->total.ifaces] = r->iface;
622 desc->total.ifaces++;
623
624 EINA_LIST_FREE(r->deps, d)
625 {
626 d->users--;
627 if (d->users > 0) continue;
628
629 roots[n_roots] = d;
630 n_roots++;
631
632 /* remove node, it became a root */
633 for (j = 0; j < n_pending; j++)
634 {
635 if (pending[j] == d)
636 {
637 n_pending--;
638 if (j < n_pending)
639 pending[j] = pending[n_pending];
640 break;
641 }
642 }
643 }
644 }
645
646 if (n_pending > 0)
647 {
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);
655 ret = EINA_FALSE;
656 }
657
658 /* likely from still pending (dependency loops) */
659 for (i = 0; i < n_nodes; i++)
660 eina_list_free(nodes[i].deps);
661
662 return ret;
663}
664
665static Eina_Bool
666_eina_model_description_ifaces_validate_and_count(const Eina_Model_Interface *iface, unsigned int *count)
667{
668 if (iface->version != EINA_MODEL_INTERFACE_VERSION)
669 {
670 CRITICAL("Interface %p version is %u, expected %u instead.",
671 iface, iface->version, EINA_MODEL_INTERFACE_VERSION);
672 return EINA_FALSE;
673 }
674
675 if (!iface->name)
676 {
677 CRITICAL("Interface %p provides no name!", iface);
678 return EINA_FALSE;
679 }
680
681 if (iface->interfaces)
682 {
683 const Eina_Model_Interface **itr = iface->interfaces;
684 for (; *itr != NULL; itr++)
685 if (!_eina_model_description_ifaces_validate_and_count(*itr, count))
686 return EINA_FALSE;
687 }
688
689 (*count)++;
690 return EINA_TRUE;
691}
692
693static void
694_eina_model_description_ifaces_populate(Eina_Model_Description *desc, const Eina_Model_Interface *iface)
695{
696 desc->cache.ifaces[desc->total.ifaces] = iface;
697 desc->total.ifaces++;
698
699 if (iface->interfaces)
700 {
701 const Eina_Model_Interface **itr = iface->interfaces;
702 for (; *itr != NULL; itr++)
703 _eina_model_description_ifaces_populate(desc, *itr);
704 }
705}
706
707static Eina_Bool
708_eina_model_description_ifaces_fill(Eina_Model_Description *desc)
709{
710 const Eina_Model_Type **titr, **titr_end;
711 unsigned int count;
712
713 titr = desc->cache.types;
714 titr_end = titr + desc->total.types;
715
716 /* naively count all interfaces, remove duplicates later */
717 for (count = 0; titr < titr_end; titr++)
718 {
719 const Eina_Model_Type *type = *titr;
720 const Eina_Model_Interface **iitr = type->interfaces;
721 if (!type->interfaces) continue;
722
723 for (; *iitr != NULL; iitr++)
724 if (!_eina_model_description_ifaces_validate_and_count(*iitr, &count))
725 return EINA_FALSE;
726 }
727 if (count == 0)
728 {
729 desc->cache.ifaces = NULL;
730 desc->total.ifaces = 0;
731 return EINA_TRUE;
732 }
733
734 desc->cache.ifaces = malloc(count * sizeof(Eina_Model_Interface *));
735 EINA_SAFETY_ON_NULL_RETURN_VAL(desc->cache.ifaces, EINA_FALSE);
736
737 titr = desc->cache.types;
738 desc->total.ifaces = 0;
739 for (; titr < titr_end; titr++)
740 {
741 const Eina_Model_Type *type = *titr;
742 const Eina_Model_Interface **iitr = type->interfaces;
743
744 if (!type->interfaces) continue;
745
746 for (; *iitr != NULL; iitr++)
747 _eina_model_description_ifaces_populate(desc, *iitr);
748 }
749
750 return _eina_model_description_ifaces_fix(desc);
751}
752
753static Eina_Bool
754_eina_model_description_privates_fill(Eina_Model_Description *desc)
755{
756 unsigned int i;
757
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);
762
763 desc->total.size = 0;
764
765 for (i = 0; i < desc->total.types; i++)
766 {
767 const Eina_Model_Type *type = desc->cache.types[i];
768 desc->cache.privates[i].type = type;
769 if (type->private_size > 0)
770 {
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;
775 }
776 }
777
778 for (i = 0; i < desc->total.ifaces; i++)
779 {
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)
783 {
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;
788 }
789 }
790
791 return EINA_TRUE;
792}
793
794static int
795_eina_model_description_events_cmp(const void *pa, const void *pb)
796{
797 const Eina_Model_Event_Description_Cache *a = pa, *b = pb;
798 return strcmp(a->name, b->name);
799}
800
801static int
802_eina_model_description_events_find(const Eina_Model_Description *desc, const Eina_Model_Event_Description *query)
803{
804 unsigned int i;
805 for (i = 0; i < desc->total.events; i++)
806 {
807 const Eina_Model_Event_Description_Cache *itr = desc->cache.events + i;
808 if ((itr->name == query->name) || (strcmp(itr->name, query->name) == 0))
809 return i;
810 }
811
812 return -1;
813}
814
815/* warn and remove duplicates, sort items to speed up lookups */
816static Eina_Bool
817_eina_model_description_events_fill(Eina_Model_Description *desc)
818{
819 unsigned int i, count = 0, type_events;
820
821 for (i = 0; i < desc->total.types; i++)
822 {
823 const Eina_Model_Event_Description *itr = desc->cache.types[i]->events;
824 if (!itr) continue;
825 for (; itr->name != NULL; itr++)
826 {
827 count++;
828 }
829 }
830 type_events = count;
831
832 for (i = 0; i < desc->total.ifaces; i++)
833 {
834 const Eina_Model_Event_Description *itr = desc->cache.ifaces[i]->events;
835 if (!itr) continue;
836 for (; itr->name != NULL; itr++)
837 count++;
838 }
839
840 if (count == 0)
841 {
842 desc->cache.events = NULL;
843 desc->total.events = 0;
844 return EINA_TRUE;
845 }
846
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;
851
852 for (i = 0; i < desc->total.types; i++)
853 {
854 const Eina_Model_Type *mtype = desc->cache.types[i];
855 const Eina_Model_Event_Description *itr = mtype->events;
856 if (!itr) continue;
857 for (; itr->name != NULL; itr++)
858 {
859 int j = _eina_model_description_events_find(desc, itr);
860 if (j >= 0)
861 {
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)",
867 itr->name,
868 itr->type ? itr->type : "",
869 mtype, mtype->name,
870 o->desc->type ? o->desc->type : "",
871 omtype, omtype->name);
872 continue;
873 }
874
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++;
879 }
880 }
881
882 for (i = 0; i < desc->total.ifaces; i++)
883 {
884 const Eina_Model_Interface *miface = desc->cache.ifaces[i];
885 const Eina_Model_Event_Description *itr = desc->cache.ifaces[i]->events;
886 if (!itr) continue;
887 for (; itr->name != NULL; itr++)
888 {
889 int j = _eina_model_description_events_find(desc, itr);
890 if (j >= 0)
891 {
892 const Eina_Model_Event_Description_Cache *o = desc->cache.events + j;
893 if ((unsigned)j < type_events)
894 {
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)",
899 itr->name,
900 itr->type ? itr->type : "",
901 miface, miface->name,
902 o->desc->type ? o->desc->type : "",
903 omtype, omtype->name);
904 }
905 else
906 {
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)",
911 itr->name,
912 itr->type ? itr->type : "",
913 miface, miface->name,
914 o->desc->type ? o->desc->type : "",
915 omiface, omiface->name);
916 }
917 continue;
918 }
919
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++;
924 }
925 }
926
927 qsort(desc->cache.events, desc->total.events,
928 sizeof(Eina_Model_Event_Description_Cache),
929 _eina_model_description_events_cmp);
930
931 return EINA_TRUE;
932}
933
934static const Eina_Model_Description *
935_eina_model_description_get_internal(const Eina_Model_Type *type)
936{
937 Eina_Model_Description *desc;
938
939 desc = eina_hash_find(_eina_model_descriptions, &type);
940 if (desc)
941 {
942 desc->refcount++;
943 return desc;
944 }
945
946 desc = calloc(1, sizeof(Eina_Model_Description));
947 EINA_SAFETY_ON_NULL_RETURN_VAL(desc, NULL);
948
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;
954
955 desc->refcount = 1;
956 return desc;
957
958 failed_hash:
959 free(desc->cache.events);
960 failed_events:
961 free(desc->cache.privates);
962 failed_privates:
963 free(desc->cache.ifaces);
964 failed_ifaces:
965 free(desc->cache.types);
966 free(desc->ops.type.extension);
967 failed_type:
968 free(desc);
969 return NULL;
970}
971
972static void
973_eina_model_description_dispose_internal(Eina_Model_Description *desc)
974{
975 const Eina_Model_Type *type;
976
977 EINA_SAFETY_ON_FALSE_RETURN(desc->refcount > 0);
978 desc->refcount--;
979 if (desc->refcount > 0) return;
980
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!",
984 type, type->name);
985
986 INF("Disposed model description for type %p (%s)", type, type->name);
987
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);
993 free(desc);
994}
995
996static const Eina_Model_Description *
997_eina_model_description_get(const Eina_Model_Type *type)
998{
999 const Eina_Model_Description *desc;
1000
1001 eina_lock_take(&_eina_model_descriptions_lock);
1002 desc = _eina_model_description_get_internal(type);
1003 eina_lock_release(&_eina_model_descriptions_lock);
1004
1005 return desc;
1006}
1007
1008static void
1009_eina_model_description_dispose(const Eina_Model_Description *desc)
1010{
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);
1014}
1015
1016static inline int
1017_eina_model_description_event_id_find(const Eina_Model_Description *desc, const char *event_name)
1018{
1019 const Eina_Model_Event_Description_Cache *cache;
1020 Eina_Model_Event_Description_Cache criteria_match;
1021
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);
1026 if (!cache)
1027 {
1028 ERR("No event named %s for type %p (%s)", event_name,
1029 desc->cache.types[0], desc->cache.types[0]->name);
1030 return -1;
1031 }
1032
1033 return cache - desc->cache.events;
1034}
1035
1036/*
1037 * Model management and book keeping
1038 */
1039typedef struct _Eina_Model_Event_Listener Eina_Model_Event_Listener;
1040struct _Eina_Model_Event_Listener
1041{
1042 EINA_INLIST;
1043 Eina_Model_Event_Cb cb;
1044 const void *data;
1045 Eina_Bool deleted:1;
1046};
1047
1048struct _Eina_Model
1049{
1050 const Eina_Model_Description *desc; /**< optimized model description */
1051 struct {
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 */
1056 } listeners;
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 */
1061 EINA_MAGIC
1062};
1063
1064static inline Eina_Bool
1065_eina_model_type_check(const Eina_Model_Type *type)
1066{
1067 EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE);
1068 EINA_SAFETY_ON_FALSE_RETURN_VAL(type->version == EINA_MODEL_TYPE_VERSION,
1069 EINA_FALSE);
1070 return EINA_TRUE;
1071}
1072
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.
1075 */
1076static const void *
1077_eina_model_type_find_offset(const Eina_Model_Type *type, unsigned int offset)
1078{
1079 const unsigned char *ptr = (const unsigned char *)type;
1080 const void **addr = (const void **)(ptr + offset);
1081
1082 if (*addr) return *addr;
1083 if (!type->parent) return NULL;
1084 return _eina_model_type_find_offset(type->parent, offset);
1085}
1086
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
1089 * parent.
1090 *
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
1094 * situations (k-s)
1095 *
1096 * iface1
1097 * ^
1098 * |
1099 * .---------+---------.
1100 * | | |
1101 * iface2 iface3 iface4
1102 * ^ ^ ^
1103 * | | |
1104 * `---------+---------'
1105 * |
1106 * iface5
1107 *
1108 * It should look: iface5 -> iface2 -> iface3 -> iface4 -> iface1
1109 * Now it does: iface5 -> iface2 -> iface1 -> iface3 -> iface1 -> iface4 -> iface1
1110 *
1111 *
1112 * iface1
1113 * ^
1114 * |
1115 * iface2
1116 * ^
1117 * |
1118 * .---------+---------.
1119 * | |
1120 * iface3 iface4
1121 * ^ ^
1122 * | |
1123 * `---------+---------'
1124 * |
1125 * iface5
1126 *
1127 * It should look: iface5 -> iface3 -> iface4 -> iface2 -> iface1
1128 * Now it does: iface5 -> iface3 -> iface2 -> iface1 -> iface4 -> iface2 -> iface1
1129 *
1130 *
1131 * iface1 iface2
1132 * ^ ^
1133 * | |
1134 * `---------+---------'
1135 * |
1136 * iface3
1137 *
1138 * It should look: iface3 -> iface1 -> iface2
1139 * Now it does: iface3 -> iface1 -> iface2
1140 *
1141 * For the common case it should work, let's see.
1142 */
1143static const void *
1144_eina_model_interface_find_offset(const Eina_Model_Interface *iface, unsigned int offset)
1145{
1146 const Eina_Model_Interface **itr;
1147 const unsigned char *ptr = (const unsigned char *)iface;
1148 const void **addr = (const void **)(ptr + offset);
1149
1150 if (offset + sizeof(void *) > iface->interface_size) return NULL;
1151
1152 if (*addr) return *addr;
1153 if (!iface->interfaces) return NULL;
1154
1155 for (itr = iface->interfaces; *itr != NULL; itr++)
1156 {
1157 const void *r = _eina_model_interface_find_offset(*itr, offset);
1158 if (r)
1159 return r;
1160 }
1161
1162 return NULL;
1163}
1164
1165static void
1166_eina_model_event_callback_free_deleted(Eina_Model *model)
1167{
1168 unsigned int i;
1169
1170 for (i = 0; i < model->desc->total.events; i++)
1171 {
1172 Eina_Model_Event_Listener *el;
1173 EINA_LIST_FREE(model->listeners.deleted[i], el)
1174 {
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);
1178 }
1179 }
1180
1181 _eina_model_inner_free(model->desc->total.events * sizeof(Eina_List *),
1182 model->listeners.deleted);
1183 model->listeners.deleted = NULL;
1184}
1185
1186static inline Eina_Bool
1187_eina_model_event_callback_call(Eina_Model *model, const char *name, const void *event_info)
1188{
1189 Eina_Inlist *lst;
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);
1193
1194 if (event_id < 0) return EINA_FALSE;
1195 if (!model->listeners.entries) return EINA_TRUE;
1196
1197 if ((model->listeners.freeze) && (model->listeners.freeze[event_id]))
1198 {
1199 DBG("Ignored event callback '%s' of model %p (%s): frozen",
1200 name, model, model->desc->cache.types[0]->name);
1201 return EINA_TRUE;
1202 }
1203
1204 lst = model->listeners.entries[event_id];
1205 if (!lst) return EINA_TRUE;
1206
1207 ev_desc = model->desc->cache.events[event_id].desc;
1208
1209 model->listeners.walking++;
1210 EINA_INLIST_FOREACH(lst, el)
1211 {
1212 if (el->deleted) continue;
1213 el->cb((void *)el->data, model, ev_desc, (void *)event_info);
1214 }
1215 model->listeners.walking--;
1216
1217 if ((model->listeners.walking == 0) && (model->listeners.deleted))
1218 _eina_model_event_callback_free_deleted(model);
1219
1220 return EINA_FALSE;
1221}
1222
1223static const char EINA_ERROR_MODEL_FAILED_STR[] = "Model check failed.";
1224static const char EINA_ERROR_MODEL_METHOD_MISSING_STR[] = "Model method is missing.";
1225static const char EINA_MAGIC_MODEL_STR[] = "Eina Model";
1226
1227static void _eina_model_unref(Eina_Model *model);
1228
1229/**
1230 * @endcond
1231 */
1232
1233/* EINA_MODEL_TYPE_BASE: base of all other types **********************/
1234
1235static Eina_Bool
1236_eina_model_type_base_setup(Eina_Model *model)
1237{
1238 DBG("base setup of %p", model);
1239 return EINA_TRUE;
1240}
1241
1242static Eina_Bool
1243_eina_model_type_base_flush(Eina_Model *model)
1244{
1245 DBG("base flush of %p", model);
1246 return EINA_TRUE;
1247}
1248
1249static Eina_Bool
1250_eina_model_type_base_constructor(Eina_Model *model)
1251{
1252 DBG("base constructor of %p", model);
1253 return EINA_TRUE;
1254}
1255
1256static Eina_Bool
1257_eina_model_type_base_destructor(Eina_Model *model)
1258{
1259 DBG("base destructor of %p", model);
1260 return EINA_TRUE;
1261}
1262
1263static Eina_Bool
1264_eina_model_type_base_properties_copy(const Eina_Model *model, Eina_Model *copy)
1265{
1266 Eina_List *l, *props = eina_model_properties_names_list_get(model);
1267 const char *name;
1268 EINA_LIST_FOREACH(props, l, name)
1269 {
1270 Eina_Value tmp;
1271 if (!eina_model_property_get(model, name, &tmp))
1272 {
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);
1276 return EINA_FALSE;
1277 }
1278 if (!eina_model_property_set(copy, name, &tmp))
1279 {
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);
1284 return EINA_FALSE;
1285 }
1286 eina_value_flush(&tmp);
1287 }
1288 eina_model_properties_names_list_free(props);
1289 return EINA_TRUE;
1290}
1291
1292static Eina_Bool
1293_eina_model_type_base_children_copy(const Eina_Model *model, Eina_Model *copy)
1294{
1295 int i, count = eina_model_child_count(model);
1296
1297 if (count < 0)
1298 {
1299 ERR("Could not get children count of model %p (%s)",
1300 model, model->desc->cache.types[0]->name);
1301 return EINA_FALSE;
1302 }
1303
1304 for (i = 0; i < count; i++)
1305 {
1306 Eina_Model *child = eina_model_child_get(model, i);
1307 Eina_Bool ret;
1308
1309 if (!child)
1310 {
1311 ERR("Could not get child #%d from model %p (%s)",
1312 i, model, model->desc->cache.types[0]->name);
1313 return EINA_FALSE;
1314 }
1315
1316 ret = eina_model_child_insert_at(copy, i, child);
1317 _eina_model_unref(child);
1318
1319 if (!ret)
1320 {
1321 ERR("Could not set child #%d on model %p (%s)",
1322 i, copy, copy->desc->cache.types[0]->name);
1323 return EINA_FALSE;
1324 }
1325 }
1326
1327 return EINA_TRUE;
1328}
1329
1330static Eina_Bool
1331_eina_model_type_base_copy(const Eina_Model *model, Eina_Model *copy)
1332{
1333 DBG("base copy of %p to %p", model, copy);
1334
1335 return _eina_model_type_base_properties_copy(model, copy) &&
1336 _eina_model_type_base_children_copy(model, copy);
1337}
1338
1339static Eina_Bool
1340_eina_model_type_base_children_deep_copy(const Eina_Model *model, Eina_Model *copy)
1341{
1342 int i, count = eina_model_child_count(model);
1343
1344 if (count < 0)
1345 {
1346 ERR("Could not get children count of model %p (%s)",
1347 model, model->desc->cache.types[0]->name);
1348 return EINA_FALSE;
1349 }
1350
1351 for (i = 0; i < count; i++)
1352 {
1353 Eina_Model *child_copy, *child = eina_model_child_get(model, i);
1354 Eina_Bool ret;
1355
1356 if (!child)
1357 {
1358 ERR("Could not get child #%d from model %p (%s)",
1359 i, model, model->desc->cache.types[0]->name);
1360 return EINA_FALSE;
1361 }
1362
1363 child_copy = eina_model_deep_copy(child);
1364 if (!child_copy)
1365 {
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);
1370 return EINA_FALSE;
1371 }
1372 _eina_model_unref(child);
1373
1374 ret = eina_model_child_insert_at(copy, i, child_copy);
1375 _eina_model_unref(child_copy);
1376
1377 if (!ret)
1378 {
1379 ERR("Could not set child #%d on model %p (%s)",
1380 i, copy, copy->desc->cache.types[0]->name);
1381 return EINA_FALSE;
1382 }
1383 }
1384
1385 return EINA_TRUE;
1386}
1387
1388static Eina_Bool
1389_eina_model_type_base_deep_copy(const Eina_Model *model, Eina_Model *copy)
1390{
1391 DBG("base deep copy of %p to %p", model, copy);
1392
1393 return _eina_model_type_base_properties_copy(model, copy) &&
1394 _eina_model_type_base_children_deep_copy(model, copy);
1395}
1396
1397static Eina_Bool
1398_eina_model_type_base_properties_compare(const Eina_Model *a, const Eina_Model *b, int *cmp)
1399{
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;
1405
1406 EINA_LIST_FOREACH(aprops, al, aname)
1407 {
1408 EINA_LIST_FOREACH(bprops, bl, bname)
1409 if (strcmp(aname, bname) == 0)
1410 {
1411 props = eina_list_append(props, aname);
1412 break;
1413 }
1414 }
1415
1416 *cmp = 0;
1417 EINA_LIST_FOREACH(props, l, name)
1418 {
1419 Eina_Value atmp, btmp;
1420
1421 if (!eina_model_property_get(a, name, &atmp))
1422 {
1423 ERR("Could not get property %s from model %p (%s)",
1424 name, a, a->desc->cache.types[0]->name);
1425 ret = EINA_FALSE;
1426 *cmp = -1;
1427 break;
1428 }
1429
1430 if (!eina_model_property_get(b, name, &btmp))
1431 {
1432 ERR("Could not get property %s from model %p (%s)",
1433 name, b, b->desc->cache.types[0]->name);
1434 ret = EINA_FALSE;
1435 *cmp = -1;
1436 eina_value_flush(&atmp);
1437 break;
1438 }
1439
1440 *cmp = eina_value_compare(&atmp, &btmp);
1441 if (eina_error_get() != 0)
1442 {
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);
1448 free(astr);
1449 free(bstr);
1450 ret = EINA_FALSE;
1451 *cmp = -1;
1452 }
1453
1454 eina_value_flush(&atmp);
1455 eina_value_flush(&btmp);
1456
1457 if ((!ret) || (*cmp != 0))
1458 break;
1459 }
1460
1461 if ((ret) && (*cmp == 0))
1462 {
1463 int acount = eina_list_count(aprops);
1464 int bcount = eina_list_count(bprops);
1465
1466 if (acount < bcount)
1467 *cmp = -1;
1468 else if (acount > bcount)
1469 *cmp = 1;
1470 }
1471
1472 eina_model_properties_names_list_free(aprops);
1473 eina_model_properties_names_list_free(bprops);
1474 eina_list_free(props);
1475 return ret;
1476}
1477
1478static Eina_Bool
1479_eina_model_type_base_children_compare(const Eina_Model *a, const Eina_Model *b, int *cmp)
1480{
1481 int acount = eina_model_child_count(a);
1482 int bcount = eina_model_child_count(b);
1483 int i, count;
1484 Eina_Bool ret = EINA_TRUE;
1485
1486 if (acount < 0)
1487 {
1488 ERR("Could not get children count of model %p (%s)",
1489 a, a->desc->cache.types[0]->name);
1490 return EINA_FALSE;
1491 }
1492 if (bcount < 0)
1493 {
1494 ERR("Could not get children count of model %p (%s)",
1495 b, b->desc->cache.types[0]->name);
1496 return EINA_FALSE;
1497 }
1498
1499 if (acount < bcount)
1500 count = acount;
1501 else
1502 count = bcount;
1503
1504 for (i = 0; i < count; i++)
1505 {
1506 Eina_Model *achild, *bchild;
1507
1508 achild = eina_model_child_get(a, i);
1509 if (!achild)
1510 {
1511 ERR("Could not get child #%d from model %p (%s)",
1512 i, a, a->desc->cache.types[0]->name);
1513 *cmp = -1;
1514 return EINA_FALSE;
1515 }
1516
1517 bchild = eina_model_child_get(b, i);
1518 if (!bchild)
1519 {
1520 ERR("Could not get child #%d from model %p (%s)",
1521 i, b, b->desc->cache.types[0]->name);
1522 *cmp = -1;
1523 _eina_model_unref(achild);
1524 return EINA_FALSE;
1525 }
1526
1527 *cmp = eina_model_compare(achild, bchild);
1528 if (eina_error_get())
1529 {
1530 ERR("Could not compare children #%d %p (%s) and %p (%s) "
1531 "from models %p (%s) and %p (%s)", i,
1532 achild,
1533 eina_model_type_name_get(eina_model_type_get(achild)),
1534 bchild,
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);
1538 ret = EINA_FALSE;
1539 }
1540 _eina_model_unref(achild);
1541 _eina_model_unref(bchild);
1542
1543 if ((!ret) || (*cmp != 0))
1544 break;
1545 }
1546
1547 if ((ret) && (*cmp == 0))
1548 {
1549 if (acount < bcount)
1550 *cmp = -1;
1551 else if (acount > bcount)
1552 *cmp = 1;
1553 }
1554
1555 return ret;
1556}
1557
1558static Eina_Bool
1559_eina_model_type_base_compare(const Eina_Model *a, const Eina_Model *b, int *cmp)
1560{
1561 *cmp = 0;
1562 DBG("base compare of %p and %p", a, b);
1563
1564 if (!_eina_model_type_base_properties_compare(a, b, cmp))
1565 return EINA_FALSE;
1566
1567 if (*cmp != 0)
1568 return EINA_TRUE;
1569
1570 return _eina_model_type_base_children_compare(a, b, cmp);
1571}
1572
1573static int
1574_eina_model_type_base_child_count(const Eina_Model *model)
1575{
1576 DBG("base child_count of %p", model);
1577 return 0;
1578}
1579
1580static int
1581_eina_model_type_base_child_find(const Eina_Model *model, unsigned int start_position, const Eina_Model *other)
1582{
1583 int x = eina_model_child_count(model);
1584 unsigned int i, count;
1585
1586 DBG("base child_find of %p, %d children", model, x);
1587
1588 if (x < 0)
1589 return -1;
1590
1591 count = x;
1592 for (i = start_position; i < count; i++)
1593 {
1594 Eina_Model *current = eina_model_child_get(model, i);
1595 if (current)
1596 {
1597 _eina_model_unref(current); /* we'll not use it's value anyway */
1598 if (current == other)
1599 return i;
1600 }
1601 }
1602
1603 return -1;
1604}
1605
1606static int
1607_eina_model_type_base_child_criteria_match(const Eina_Model *model, unsigned int start_position, Eina_Each_Cb match, const void *user_data)
1608{
1609 int x = eina_model_child_count(model);
1610 unsigned int i, count;
1611
1612 DBG("base child_criteria_match of %p, %d children", model, x);
1613
1614 if (x < 0)
1615 return -1;
1616
1617 count = x;
1618 for (i = start_position; i < count; i++)
1619 {
1620 Eina_Model *current = eina_model_child_get(model, i);
1621 if (current)
1622 {
1623 Eina_Bool r = match(model, current, (void *)user_data);
1624 _eina_model_unref(current);
1625 if (r)
1626 return i;
1627 }
1628 }
1629
1630 return -1;
1631}
1632
1633typedef struct _Eina_Iterator_Model_Base Eina_Iterator_Model_Base;
1634struct _Eina_Iterator_Model_Base
1635{
1636 Eina_Iterator base;
1637 Eina_Model *model;
1638 unsigned int current;
1639 unsigned int end;
1640};
1641
1642static Eina_Bool
1643_eina_model_type_base_child_iterator_next(Eina_Iterator *base, void **data)
1644{
1645 Eina_Iterator_Model_Base *it;
1646
1647 it = (Eina_Iterator_Model_Base *)base;
1648 if (it->current >= it->end)
1649 return EINA_FALSE;
1650
1651 *data = eina_model_child_get(it->model, it->current);
1652 if (!*data)
1653 return EINA_FALSE;
1654
1655 it->current++;
1656 return EINA_TRUE;
1657}
1658
1659static void *
1660_eina_model_type_base_child_iterator_get_container(Eina_Iterator *base)
1661{
1662 Eina_Iterator_Model_Base *it;
1663 it = (Eina_Iterator_Model_Base *)base;
1664 return it->model;
1665}
1666
1667static void
1668_eina_model_type_base_child_iterator_free(Eina_Iterator *base)
1669{
1670 Eina_Iterator_Model_Base *it;
1671 it = (Eina_Iterator_Model_Base *)base;
1672 eina_model_xunref(it->model, it);
1673 free(it);
1674}
1675
1676static Eina_Iterator *
1677_eina_model_type_base_child_iterator_get(Eina_Model *model, unsigned int start, unsigned int count)
1678{
1679 Eina_Iterator_Model_Base *it = calloc(1, sizeof(*it));
1680 EINA_SAFETY_ON_NULL_RETURN_VAL(it, NULL);
1681
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;
1687
1688 it->model = eina_model_xref(model, it, "eina_model_child_slice_iterator_get");
1689 it->current = start;
1690 it->end = start + count;
1691
1692 return &it->base;
1693}
1694
1695typedef struct _Eina_Iterator_Model_Base_Reversed Eina_Iterator_Model_Base_Reversed;
1696struct _Eina_Iterator_Model_Base_Reversed
1697{
1698 Eina_Iterator base;
1699 Eina_Model *model;
1700 unsigned int current;
1701 unsigned int end;
1702};
1703
1704static Eina_Bool
1705_eina_model_type_base_child_reversed_iterator_next(Eina_Iterator *base, void **data)
1706{
1707 Eina_Iterator_Model_Base_Reversed *it;
1708
1709 it = (Eina_Iterator_Model_Base_Reversed *)base;
1710 if (it->current == it->end)
1711 return EINA_FALSE;
1712
1713 it->current--;
1714 *data = eina_model_child_get(it->model, it->current);
1715 if (!*data)
1716 return EINA_FALSE;
1717
1718 return EINA_TRUE;
1719}
1720
1721static void *
1722_eina_model_type_base_child_reversed_iterator_get_container(Eina_Iterator *base)
1723{
1724 Eina_Iterator_Model_Base_Reversed *it;
1725 it = (Eina_Iterator_Model_Base_Reversed *)base;
1726 return it->model;
1727}
1728
1729static void
1730_eina_model_type_base_child_reversed_iterator_free(Eina_Iterator *base)
1731{
1732 Eina_Iterator_Model_Base_Reversed *it;
1733 it = (Eina_Iterator_Model_Base_Reversed *)base;
1734 eina_model_xunref(it->model, it);
1735 free(it);
1736}
1737
1738static Eina_Iterator *
1739_eina_model_type_base_child_reversed_iterator_get(Eina_Model *model, unsigned int start, unsigned int count)
1740{
1741 Eina_Iterator_Model_Base_Reversed *it;
1742 int children_count;
1743
1744 children_count = eina_model_child_count(model);
1745 if (children_count < 0)
1746 return NULL;
1747
1748 if (start + count > (unsigned int)children_count)
1749 {
1750 if (start >= (unsigned int)children_count)
1751 count = 0;
1752 else
1753 count = children_count - start;
1754 }
1755
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;
1763
1764 it->model = eina_model_xref(model, it, "eina_model_child_slice_reversed_iterator_get");
1765 it->current = start + count;
1766 it->end = start;
1767
1768 return &it->base;
1769}
1770
1771typedef struct _Eina_Iterator_Model_Base_Sorted Eina_Iterator_Model_Base_Sorted;
1772struct _Eina_Iterator_Model_Base_Sorted
1773{
1774 Eina_Iterator base;
1775 Eina_Model *model;
1776 unsigned int current;
1777 unsigned int count;
1778 Eina_Model *elements[];
1779};
1780
1781static Eina_Bool
1782_eina_model_type_base_child_sorted_iterator_next(Eina_Iterator *base, void **data)
1783{
1784 Eina_Iterator_Model_Base_Sorted *it;
1785
1786 it = (Eina_Iterator_Model_Base_Sorted *)base;
1787 if (it->current == it->count)
1788 return EINA_FALSE;
1789
1790 *data = eina_model_ref(it->elements[it->current]);
1791 it->current++;
1792 return EINA_TRUE;
1793}
1794
1795static void *
1796_eina_model_type_base_child_sorted_iterator_get_container(Eina_Iterator *base)
1797{
1798 Eina_Iterator_Model_Base_Sorted *it;
1799 it = (Eina_Iterator_Model_Base_Sorted *)base;
1800 return it->model;
1801}
1802
1803static void
1804_eina_model_type_base_child_sorted_iterator_free(Eina_Iterator *base)
1805{
1806 Eina_Iterator_Model_Base_Sorted *it;
1807 unsigned int i;
1808 it = (Eina_Iterator_Model_Base_Sorted *)base;
1809 eina_model_xunref(it->model, it);
1810
1811 for (i = 0; i < it->count; i++)
1812 _eina_model_unref(it->elements[i]);
1813
1814 free(it);
1815}
1816
1817static Eina_Iterator *
1818_eina_model_type_base_child_sorted_iterator_get(Eina_Model *model, unsigned int start, unsigned int count, Eina_Compare_Cb compare)
1819{
1820 Eina_Iterator_Model_Base_Sorted *it;
1821 int children_count;
1822 unsigned int i;
1823
1824 children_count = eina_model_child_count(model);
1825 if (children_count < 0)
1826 return NULL;
1827
1828 if (start + count > (unsigned int)children_count)
1829 {
1830 if (start >= (unsigned int)children_count)
1831 count = 0;
1832 else
1833 count = children_count - start;
1834 }
1835
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;
1843
1844 it->model = eina_model_xref(model, it, "eina_model_child_slice_sorted_iterator_get");
1845 it->current = 0;
1846 it->count = count;
1847
1848 for (i = 0; i < count; i++)
1849 {
1850 it->elements[i] = eina_model_child_get(model, i + start);
1851 if (!it->elements[i])
1852 {
1853 ERR("Failed to get child %u of model %p (%s)",
1854 i + start, model, model->desc->cache.types[0]->name);
1855 free(it);
1856 return NULL;
1857 }
1858 }
1859
1860 if (count > 1)
1861 _eina_model_array_sort(it->elements, 0, count - 1, compare);
1862
1863 return &it->base;
1864}
1865
1866typedef struct _Eina_Iterator_Model_Base_Filtered Eina_Iterator_Model_Base_Filtered;
1867struct _Eina_Iterator_Model_Base_Filtered
1868{
1869 Eina_Iterator base;
1870 Eina_Model *model;
1871 Eina_Each_Cb match;
1872 const void *data;
1873 unsigned int current;
1874 unsigned int count;
1875};
1876
1877static Eina_Bool
1878_eina_model_type_base_child_filtered_iterator_next(Eina_Iterator *base, void **data)
1879{
1880 Eina_Iterator_Model_Base_Filtered *it;
1881 unsigned int *ret;
1882 int i;
1883
1884 it = (Eina_Iterator_Model_Base_Filtered *)base;
1885 if (it->count == 0) return EINA_FALSE;
1886
1887 i = eina_model_child_criteria_match(it->model, it->current, it->match, it->data);
1888 if (i < 0) return EINA_FALSE;
1889
1890 it->current = i + 1;
1891 it->count--;
1892 ret = (unsigned int *)data;
1893 *ret = i;
1894 return EINA_TRUE;
1895}
1896
1897static void *
1898_eina_model_type_base_child_filtered_iterator_get_container(Eina_Iterator *base)
1899{
1900 Eina_Iterator_Model_Base_Filtered *it;
1901 it = (Eina_Iterator_Model_Base_Filtered *)base;
1902 return it->model;
1903}
1904
1905static void
1906_eina_model_type_base_child_filtered_iterator_free(Eina_Iterator *base)
1907{
1908 Eina_Iterator_Model_Base_Filtered *it;
1909 it = (Eina_Iterator_Model_Base_Filtered *)base;
1910 eina_model_xunref(it->model, it);
1911 free(it);
1912}
1913
1914static 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)
1916{
1917 Eina_Iterator_Model_Base_Filtered *it = calloc(1, sizeof(*it));
1918 EINA_SAFETY_ON_NULL_RETURN_VAL(it, NULL);
1919
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;
1925
1926 it->model = eina_model_xref(model, it, "eina_model_child_slice_filtered_iterator_get");
1927 it->match = match;
1928 it->data = data;
1929 it->current = start;
1930 it->count = count;
1931
1932 return &it->base;
1933}
1934
1935static char *
1936_eina_model_type_base_to_string(const Eina_Model *model)
1937{
1938 Eina_List *l, *props;
1939 const char *name;
1940 Eina_Strbuf *str;
1941 Eina_Bool first;
1942 int i, count;
1943 char *ret;
1944
1945 str = eina_strbuf_new();
1946 EINA_SAFETY_ON_NULL_RETURN_VAL(str, NULL);
1947
1948 eina_strbuf_append_printf(str, "%s({", model->desc->cache.types[0]->name);
1949
1950 props = eina_model_properties_names_list_get(model);
1951 props = eina_list_sort(props, 0, EINA_COMPARE_CB(strcmp));
1952
1953 first = EINA_TRUE;
1954 EINA_LIST_FOREACH(props, l, name)
1955 {
1956 Eina_Value val;
1957
1958 if (!first)
1959 eina_strbuf_append_printf(str, ", %s: ", name);
1960 else
1961 {
1962 eina_strbuf_append_printf(str, "%s: ", name);
1963 first = EINA_FALSE;
1964 }
1965
1966 if (!eina_model_property_get(model, name, &val))
1967 eina_strbuf_append_char(str, '?');
1968 else
1969 {
1970 char *tmp = eina_value_to_string(&val);
1971 eina_strbuf_append(str, tmp ? tmp : "?");
1972 free(tmp);
1973 eina_value_flush(&val);
1974 }
1975 }
1976 eina_list_free(props);
1977
1978 eina_strbuf_append(str, "}, [");
1979
1980 count = eina_model_child_count(model);
1981 first = EINA_TRUE;
1982 for (i = 0; i < count; i++)
1983 {
1984 Eina_Model *c = eina_model_child_get(model, i);
1985 if (!c)
1986 {
1987 if (!first)
1988 eina_strbuf_append(str, ", ?");
1989 else
1990 {
1991 eina_strbuf_append_char(str, '?');
1992 first = EINA_FALSE;
1993 }
1994 }
1995 else
1996 {
1997 char *tmp = eina_model_to_string(c);
1998 if (!first)
1999 eina_strbuf_append_printf(str, ", %s", tmp ? tmp : "?");
2000 else
2001 {
2002 eina_strbuf_append(str, tmp ? tmp : "?");
2003 first = EINA_FALSE;
2004 }
2005 free(tmp);
2006 _eina_model_unref(c);
2007 }
2008 }
2009
2010 eina_strbuf_append(str, "])");
2011
2012 ret = eina_strbuf_string_steal(str);
2013 eina_strbuf_free(str);
2014
2015 return ret;
2016}
2017
2018static 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
2030};
2031
2032static 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,
2047 NULL, /* no load */
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 */
2070};
2071
2072/*
2073 * EINA_MODEL_TYPE_MIXIN:
2074 *
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.
2079 */
2080
2081static const char _EINA_MODEL_INTERFACE_NAME_PROPERTIES[] = "Eina_Model_Interface_Properties";
2082static const char _EINA_MODEL_INTERFACE_NAME_CHILDREN[] = "Eina_Model_Interface_Children";
2083
2084typedef struct _Eina_Model_Type_Mixin_Data Eina_Model_Type_Mixin_Data;
2085struct _Eina_Model_Type_Mixin_Data
2086{
2087 /* just keep interfaces to avoid lookups */
2088 const Eina_Model_Interface *if_properties;
2089 const Eina_Model_Interface *if_children;
2090};
2091
2092static Eina_Bool
2093_eina_model_type_mixin_setup(Eina_Model *model)
2094{
2095 DBG("mix-in setup of %p", model);
2096 return EINA_TRUE;
2097}
2098
2099static Eina_Bool
2100_eina_model_type_mixin_flush(Eina_Model *model)
2101{
2102 DBG("mix-in flush of %p", model);
2103 return EINA_TRUE;
2104}
2105
2106static Eina_Bool
2107_eina_model_type_mixin_constructor(Eina_Model *model)
2108{
2109 Eina_Model_Type_Mixin_Data *priv = eina_model_type_private_data_get
2110 (model, EINA_MODEL_TYPE_MIXIN);
2111
2112 DBG("mix-in constructor of %p (priv=%p)", model, priv);
2113
2114 priv->if_properties = eina_model_interface_get
2115 (model, EINA_MODEL_INTERFACE_NAME_PROPERTIES);
2116 if (priv->if_properties)
2117 {
2118 if (!eina_model_interface_constructor(priv->if_properties, model))
2119 {
2120 ERR("Could not construct properties interface %p of %p (%s)",
2121 model, priv->if_properties, model->desc->cache.types[0]->name);
2122 return EINA_FALSE;
2123 }
2124 }
2125
2126 priv->if_children = eina_model_interface_get
2127 (model, EINA_MODEL_INTERFACE_NAME_CHILDREN);
2128 if (priv->if_children)
2129 {
2130 if (!eina_model_interface_constructor(priv->if_children, model))
2131 {
2132 ERR("Could not construct children interface %p of %p (%s)",
2133 model, priv->if_children, model->desc->cache.types[0]->name);
2134 return EINA_FALSE;
2135 }
2136 }
2137
2138 if ((!priv->if_properties) && (!priv->if_children))
2139 {
2140 ERR("Mix-in model %p (%s) does not implement properties or children "
2141 "interfaces!",
2142 model, model->desc->cache.types[0]->name);
2143 return EINA_FALSE;
2144 }
2145
2146 return EINA_TRUE;
2147}
2148
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)
2152
2153static Eina_Bool
2154_eina_model_type_mixin_destructor(Eina_Model *model)
2155{
2156 EINA_MODEL_TYPE_MIXIN_GET(model);
2157
2158 DBG("mixin destructor of %p", model);
2159
2160 if (priv->if_properties)
2161 eina_model_interface_destructor(priv->if_properties, model);
2162
2163 if (priv->if_children)
2164 eina_model_interface_destructor(priv->if_children, model);
2165
2166 return EINA_TRUE;
2167}
2168
2169static Eina_Bool
2170_eina_model_type_mixin_compare(const Eina_Model *a, const Eina_Model *b, int *cmp)
2171{
2172 Eina_Bool ret = EINA_TRUE, did_prop = EINA_FALSE, did_child = EINA_FALSE;
2173
2174 *cmp = 0;
2175
2176 EINA_MODEL_TYPE_MIXIN_GET(a);
2177
2178 if (priv->if_properties)
2179 {
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));
2184
2185 if (compare)
2186 {
2187 ret &= compare(a, b, cmp);
2188 did_prop = EINA_TRUE;
2189 }
2190 }
2191
2192 if ((ret) && (*cmp == 0))
2193 {
2194 if (priv->if_children)
2195 {
2196 Eina_Bool (*compare)(const Eina_Model*, const Eina_Model*, int *) =
2197 _eina_model_interface_find_offset
2198 (priv->if_children,
2199 offsetof(Eina_Model_Interface_Children, compare));
2200
2201 if (compare)
2202 {
2203 ret &= compare(a, b, cmp);
2204 did_child = EINA_TRUE;
2205 }
2206 }
2207 }
2208
2209 if ((!did_prop) && (!did_child))
2210 return eina_model_type_compare(EINA_MODEL_TYPE_BASE, a, b, cmp);
2211
2212 return ret;
2213}
2214
2215static Eina_Bool
2216_eina_model_type_mixin_load(Eina_Model *model)
2217{
2218 Eina_Bool ret = EINA_TRUE;
2219
2220 EINA_MODEL_TYPE_MIXIN_GET(model);
2221
2222 if (priv->if_properties)
2223 ret &= eina_model_interface_properties_load(priv->if_properties, model);
2224
2225 if (priv->if_children)
2226 ret &= eina_model_interface_children_load(priv->if_children, model);
2227
2228 return ret;
2229}
2230
2231static Eina_Bool
2232_eina_model_type_mixin_unload(Eina_Model *model)
2233{
2234 Eina_Bool ret = EINA_TRUE;
2235
2236 EINA_MODEL_TYPE_MIXIN_GET(model);
2237
2238 if (priv->if_properties)
2239 ret &= eina_model_interface_properties_unload(priv->if_properties, model);
2240
2241 if (priv->if_children)
2242 ret &= eina_model_interface_children_unload(priv->if_children, model);
2243
2244 return ret;
2245}
2246
2247static Eina_Bool
2248_eina_model_type_mixin_property_get(const Eina_Model *model, const char *name, Eina_Value *value)
2249{
2250 Eina_Bool ret = EINA_FALSE;
2251
2252 EINA_MODEL_TYPE_MIXIN_GET(model);
2253
2254 if (priv->if_properties)
2255 ret = eina_model_interface_properties_get
2256 (priv->if_properties, model, name, value);
2257
2258 return ret;
2259}
2260
2261static Eina_Bool
2262_eina_model_type_mixin_property_set(Eina_Model *model, const char *name, const Eina_Value *value)
2263{
2264 Eina_Bool ret = EINA_FALSE;
2265
2266 EINA_MODEL_TYPE_MIXIN_GET(model);
2267
2268 if (priv->if_properties)
2269 ret = eina_model_interface_properties_set
2270 (priv->if_properties, model, name, value);
2271
2272 return ret;
2273}
2274
2275static Eina_Bool
2276_eina_model_type_mixin_property_del(Eina_Model *model, const char *name)
2277{
2278 Eina_Bool ret = EINA_FALSE;
2279
2280 EINA_MODEL_TYPE_MIXIN_GET(model);
2281
2282 if (priv->if_properties)
2283 ret = eina_model_interface_properties_del
2284 (priv->if_properties, model, name);
2285
2286 return ret;
2287}
2288
2289static Eina_List *
2290_eina_model_type_mixin_properties_names_list_get(const Eina_Model *model)
2291{
2292 Eina_List *ret = NULL;
2293
2294 EINA_MODEL_TYPE_MIXIN_GET(model);
2295
2296 if (priv->if_properties)
2297 ret = eina_model_interface_properties_names_list_get
2298 (priv->if_properties, model);
2299
2300 return ret;
2301}
2302
2303static int
2304_eina_model_type_mixin_child_count(const Eina_Model *model)
2305{
2306 EINA_MODEL_TYPE_MIXIN_GET(model);
2307
2308 if (!priv->if_children)
2309 return 0;
2310
2311 return eina_model_interface_children_count(priv->if_children, model);
2312}
2313
2314static Eina_Model *
2315_eina_model_type_mixin_child_get(const Eina_Model *model, unsigned int position)
2316{
2317 EINA_MODEL_TYPE_MIXIN_GET(model);
2318
2319 if (!priv->if_children)
2320 return 0;
2321
2322 return eina_model_interface_children_get(priv->if_children, model, position);
2323}
2324
2325static Eina_Bool
2326_eina_model_type_mixin_child_set(Eina_Model *model, unsigned int position, Eina_Model *child)
2327{
2328 EINA_MODEL_TYPE_MIXIN_GET(model);
2329
2330 if (!priv->if_children)
2331 return 0;
2332
2333 return eina_model_interface_children_set
2334 (priv->if_children, model, position, child);
2335}
2336
2337static Eina_Bool
2338_eina_model_type_mixin_child_del(Eina_Model *model, unsigned int position)
2339{
2340 EINA_MODEL_TYPE_MIXIN_GET(model);
2341
2342 if (!priv->if_children)
2343 return 0;
2344
2345 return eina_model_interface_children_del
2346 (priv->if_children, model, position);
2347}
2348
2349static Eina_Bool
2350_eina_model_type_mixin_child_insert_at(Eina_Model *model, unsigned int position, Eina_Model *child)
2351{
2352 EINA_MODEL_TYPE_MIXIN_GET(model);
2353
2354 if (!priv->if_children)
2355 return 0;
2356
2357 return eina_model_interface_children_insert_at
2358 (priv->if_children, model, position, child);
2359}
2360
2361static void
2362_eina_model_type_mixin_child_sort(Eina_Model *model, Eina_Compare_Cb compare)
2363{
2364 EINA_MODEL_TYPE_MIXIN_GET(model);
2365
2366 if (!priv->if_children)
2367 return;
2368 eina_model_interface_children_sort(priv->if_children, model, compare);
2369}
2370
2371static 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 */
2409};
2410#undef EINA_MODEL_TYPE_MIXIN_GET
2411
2412/* Events for all Properties interface */
2413static 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
2417};
2418
2419/* EINA_MODEL_INTERFACE_PROPERTIES_HASH ******************************/
2420
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)
2424
2425static Eina_Bool
2426_eina_model_interface_properties_hash_setup(Eina_Model *model)
2427{
2428 Eina_Hash **p_priv = eina_model_interface_private_data_get
2429 (model, EINA_MODEL_INTERFACE_PROPERTIES_HASH);
2430
2431 DBG("setup interface properties (hash) at %p model %p (%s)",
2432 p_priv, model, model->desc->cache.types[0]->name);
2433
2434 *p_priv = eina_hash_string_small_new(NULL);
2435 return !!*p_priv;
2436}
2437
2438static Eina_Bool
2439_eina_model_interface_properties_hash_flush(Eina_Model *model)
2440{
2441 EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET(model);
2442
2443 DBG("flush interface properties (hash) at %p model %p (%s)",
2444 priv, model, model->desc->cache.types[0]->name);
2445
2446 if (priv)
2447 {
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);
2451 }
2452
2453 return EINA_TRUE;
2454}
2455
2456static Eina_Bool
2457_eina_model_interface_properties_hash_constructor(Eina_Model *model)
2458{
2459 EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET(model);
2460
2461 DBG("construct interface properties (hash) at %p model %p (%s)",
2462 priv, model, model->desc->cache.types[0]->name);
2463
2464 return EINA_TRUE;
2465}
2466
2467static Eina_Bool
2468_eina_model_interface_properties_hash_destructor_foreach(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
2469{
2470 eina_value_free(data);
2471 return EINA_TRUE;
2472}
2473
2474static Eina_Bool
2475_eina_model_interface_properties_hash_destructor(Eina_Model *model)
2476{
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);
2480
2481 DBG("destroy interface properties (hash) at %p model %p (%s). %d values.",
2482 *p_priv, model, model->desc->cache.types[0]->name, count);
2483
2484 eina_hash_foreach
2485 (*p_priv, _eina_model_interface_properties_hash_destructor_foreach, NULL);
2486 eina_hash_free(*p_priv);
2487 *p_priv = NULL;
2488
2489 return EINA_TRUE;
2490}
2491
2492static Eina_Bool
2493_eina_model_interface_properties_hash_get(const Eina_Model *model, const char *name, Eina_Value *value)
2494{
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);
2499}
2500
2501static Eina_Bool
2502_eina_model_interface_properties_hash_set(Eina_Model *model, const char *name, const Eina_Value *value)
2503{
2504 EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET(model);
2505 Eina_Value *prop, *old = eina_hash_find(priv, name);
2506
2507 prop = eina_value_new(eina_value_type_get(value));
2508 EINA_SAFETY_ON_NULL_RETURN_VAL(prop, EINA_FALSE);
2509
2510 eina_value_flush(prop);
2511 if (!eina_value_copy(value, prop))
2512 {
2513 ERR("Could not copy value '%s' from %p to %p", name, value, prop);
2514 eina_value_free(prop);
2515 return EINA_FALSE;
2516 }
2517
2518 if (!old)
2519 {
2520 if (!eina_hash_add(priv, name, prop))
2521 {
2522 ERR("Could not add value %p to hash as key '%s'", prop, name);
2523 eina_value_free(prop);
2524 return EINA_FALSE;
2525 }
2526 }
2527 else
2528 {
2529 eina_value_free(old);
2530 if (!eina_hash_modify(priv, name, prop))
2531 {
2532 ERR("Could not modify hash key '%s' value from %p to %p",
2533 name, old, prop);
2534 eina_hash_del_by_key(priv, name);
2535 eina_value_free(prop);
2536 return EINA_FALSE;
2537 }
2538 }
2539
2540 return EINA_TRUE;
2541}
2542
2543static Eina_Bool
2544_eina_model_interface_properties_hash_del(Eina_Model *model, const char *name)
2545{
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);
2551}
2552
2553static Eina_Bool
2554_eina_model_interface_properties_hash_names_list_foreach(const Eina_Hash *hash __UNUSED__, const void *key, void *data __UNUSED__, void *fdata)
2555{
2556 Eina_List **p_list = fdata;
2557 *p_list = eina_list_append(*p_list, eina_stringshare_add(key));
2558 return EINA_TRUE;
2559}
2560
2561static Eina_List *
2562_eina_model_interface_properties_hash_names_list(const Eina_Model *model)
2563{
2564 EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET(model);
2565 Eina_List *list = NULL;
2566 eina_hash_foreach
2567 (priv, _eina_model_interface_properties_hash_names_list_foreach, &list);
2568 return list;
2569}
2570#undef EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET
2571
2572static const Eina_Model_Interface_Properties _EINA_MODEL_INTERFACE_PROPERTIES_HASH = {
2573 {
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,
2584 NULL,
2585 NULL,
2586 NULL,
2587 NULL,
2588 NULL,
2589 NULL
2590 },
2591 EINA_MODEL_INTERFACE_PROPERTIES_VERSION,
2592 NULL, /* no compare */
2593 NULL, /* no load */
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
2599};
2600
2601/* EINA_MODEL_INTERFACE_PROPERTIES_STRUCT ******************************/
2602
2603static Eina_Value_Struct *
2604_eina_model_interface_properties_struct_private_get(const Eina_Model *model)
2605{
2606 Eina_Value *val = eina_model_interface_private_data_get
2607 (model, EINA_MODEL_INTERFACE_PROPERTIES_STRUCT);
2608 return eina_value_memory_get(val);
2609}
2610
2611#define EINA_MODEL_INTERFACE_PROPERTIES_STRUCT_GET(model) \
2612 Eina_Value_Struct *priv = \
2613 _eina_model_interface_properties_struct_private_get(model)
2614
2615static Eina_Bool
2616_eina_model_interface_properties_struct_setup(Eina_Model *model)
2617{
2618 Eina_Value *val = eina_model_interface_private_data_get
2619 (model, EINA_MODEL_INTERFACE_PROPERTIES_STRUCT);
2620
2621 DBG("setup interface properties (struct) at %p model %p (%s)",
2622 val, model, model->desc->cache.types[0]->name);
2623
2624 return eina_value_setup(val, EINA_VALUE_TYPE_STRUCT);
2625}
2626
2627static Eina_Bool
2628_eina_model_interface_properties_struct_flush(Eina_Model *model)
2629{
2630 Eina_Value *val = eina_model_interface_private_data_get
2631 (model, EINA_MODEL_INTERFACE_PROPERTIES_STRUCT);
2632
2633 DBG("flush interface properties (struct) at %p model %p (%s)",
2634 val, model, model->desc->cache.types[0]->name);
2635
2636 if (val->type)
2637 {
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);
2641 }
2642
2643 return EINA_TRUE;
2644}
2645
2646static Eina_Bool
2647_eina_model_interface_properties_struct_constructor(Eina_Model *model)
2648{
2649 EINA_MODEL_INTERFACE_PROPERTIES_STRUCT_GET(model);
2650
2651 DBG("construct interface properties (struct) at %p model %p (%s)",
2652 priv, model, model->desc->cache.types[0]->name);
2653
2654 return EINA_TRUE;
2655}
2656
2657static Eina_Bool
2658_eina_model_interface_properties_struct_destructor(Eina_Model *model)
2659{
2660 Eina_Value *val = eina_model_interface_private_data_get
2661 (model, EINA_MODEL_INTERFACE_PROPERTIES_STRUCT);
2662
2663 DBG("destroy interface properties (struct) at %p model %p (%s)",
2664 val, model, model->desc->cache.types[0]->name);
2665
2666 eina_value_flush(val);
2667 val->type = NULL;
2668
2669 return EINA_TRUE;
2670}
2671
2672static Eina_Bool
2673_eina_model_interface_properties_struct_get(const Eina_Model *model, const char *name, Eina_Value *val)
2674{
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);
2678}
2679
2680static Eina_Bool
2681_eina_model_interface_properties_struct_set(Eina_Model *model, const char *name, const Eina_Value *val)
2682{
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);
2686}
2687
2688static Eina_Bool
2689_eina_model_interface_properties_struct_del(Eina_Model *model __UNUSED__, const char *name __UNUSED__)
2690{
2691 return EINA_FALSE; /* not allowed */
2692}
2693
2694static Eina_List *
2695_eina_model_interface_properties_struct_names_list(const Eina_Model *model)
2696{
2697 EINA_MODEL_INTERFACE_PROPERTIES_STRUCT_GET(model);
2698 const Eina_Value_Struct_Member *itr;
2699 Eina_List *list = NULL;
2700
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);
2704
2705 itr = priv->desc->members;
2706 if (priv->desc->member_count)
2707 {
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));
2711 }
2712 else
2713 {
2714 for (; itr->name != NULL; itr++)
2715 list = eina_list_append(list, eina_stringshare_add(itr->name));
2716 }
2717
2718 return list;
2719}
2720#undef EINA_MODEL_INTERFACE_PROPERTIES_STRUCT_GET
2721
2722static const Eina_Model_Interface_Properties _EINA_MODEL_INTERFACE_PROPERTIES_STRUCT = {
2723 {
2724 EINA_MODEL_INTERFACE_VERSION,
2725 sizeof(Eina_Value),
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,
2734 NULL,
2735 NULL,
2736 NULL,
2737 NULL,
2738 NULL,
2739 NULL
2740 },
2741 EINA_MODEL_INTERFACE_PROPERTIES_VERSION,
2742 NULL, /* no compare */
2743 NULL, /* no load */
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
2749};
2750
2751/* Events for all Children interface */
2752static 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
2756};
2757
2758/* EINA_MODEL_INTERFACE_CHILDREN_INARRAY ******************************/
2759
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)
2763
2764static Eina_Bool
2765_eina_model_interface_children_inarray_setup(Eina_Model *model)
2766{
2767 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2768
2769 DBG("setup interface children (inarray) at %p model %p (%s)",
2770 priv, model, model->desc->cache.types[0]->name);
2771
2772 eina_inarray_setup(priv, sizeof(Eina_Model *), 0);
2773 return EINA_TRUE;
2774}
2775
2776static Eina_Bool
2777_eina_model_interface_children_inarray_flush(Eina_Model *model)
2778{
2779 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2780 int count;
2781
2782 DBG("flush interface children (inarray) at %p model %p (%s)",
2783 priv, model, model->desc->cache.types[0]->name);
2784
2785 count = eina_inarray_count(priv);
2786 if (count > 0)
2787 ERR("interface children flushed with %d members! priv=%p, model %p (%s)",
2788 count, priv, model, model->desc->cache.types[0]->name);
2789
2790 eina_inarray_flush(priv);
2791 return EINA_TRUE;
2792}
2793
2794static Eina_Bool
2795_eina_model_interface_children_inarray_constructor(Eina_Model *model)
2796{
2797 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2798
2799 DBG("construct interface children (inarray) at %p model %p (%s)",
2800 priv, model, model->desc->cache.types[0]->name);
2801
2802 return EINA_TRUE;
2803}
2804
2805static Eina_Bool
2806_eina_model_interface_children_inarray_destructor(Eina_Model *model)
2807{
2808 Eina_Model **itr, **itr_end;
2809 int count;
2810
2811 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2812
2813 count = eina_inarray_count(priv);
2814
2815 DBG("destroy interface children (inarray) at %p model %p (%s). %d members.",
2816 priv, model, model->desc->cache.types[0]->name, count);
2817
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);
2823
2824 return EINA_TRUE;
2825}
2826
2827static int
2828_eina_model_interface_children_inarray_count(const Eina_Model *model)
2829{
2830 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2831 return eina_inarray_count(priv);
2832}
2833
2834static Eina_Model *
2835_eina_model_interface_children_inarray_get(const Eina_Model *model, unsigned int position)
2836{
2837 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2838 Eina_Model **child = eina_inarray_nth(priv, position);
2839 if (!child)
2840 return NULL;
2841 return eina_model_ref(*child);
2842}
2843
2844static Eina_Bool
2845_eina_model_interface_children_inarray_set(Eina_Model *model, unsigned int position, Eina_Model *child)
2846{
2847 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2848 Eina_Model **p_old = eina_inarray_nth(priv, position);
2849 Eina_Model *old;
2850
2851 if (!p_old)
2852 return EINA_FALSE;
2853
2854 old = *p_old;
2855 if (!eina_inarray_replace_at(priv, position, &child))
2856 return EINA_FALSE;
2857
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);
2861 return EINA_TRUE;
2862}
2863
2864static Eina_Bool
2865_eina_model_interface_children_inarray_del(Eina_Model *model, unsigned int position)
2866{
2867 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2868 Eina_Model **p_old = eina_inarray_nth(priv, position);
2869 Eina_Model *old;
2870
2871 if (!p_old)
2872 return EINA_FALSE;
2873
2874 old = *p_old;
2875 if (!eina_inarray_remove_at(priv, position))
2876 return EINA_FALSE;
2877
2878 eina_model_xunref(old, EINA_MODEL_INTERFACE_CHILDREN_INARRAY);
2879 return EINA_TRUE;
2880}
2881
2882static Eina_Bool
2883_eina_model_interface_children_inarray_insert_at(Eina_Model *model, unsigned int position, Eina_Model *child)
2884{
2885 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2886
2887 if (!eina_inarray_insert_at(priv, position, &child))
2888 return EINA_FALSE;
2889
2890 eina_model_xref(child, EINA_MODEL_INTERFACE_CHILDREN_INARRAY,
2891 "eina_model_child_insert_at");
2892 return EINA_TRUE;
2893}
2894
2895static void
2896_eina_model_interface_children_inarray_sort(Eina_Model *model, Eina_Compare_Cb compare)
2897{
2898 EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model);
2899 int count = eina_inarray_count(priv);
2900 EINA_SAFETY_ON_FALSE_RETURN(count >= 0);
2901
2902 if (count > 1)
2903 _eina_model_array_sort(priv->members, 0, count - 1, compare);
2904}
2905#undef EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET
2906
2907static const Eina_Model_Interface_Children _EINA_MODEL_INTERFACE_CHILDREN_INARRAY = {
2908 {
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,
2919 NULL,
2920 NULL,
2921 NULL,
2922 NULL,
2923 NULL,
2924 NULL
2925 },
2926 EINA_MODEL_INTERFACE_CHILDREN_VERSION,
2927 NULL, /* no compare */
2928 NULL, /* no load */
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
2936};
2937
2938/* EINA_MODEL_TYPE_GENERIC ********************************************/
2939
2940static const Eina_Model_Interface *_EINA_MODEL_TYPE_GENERIC_IFACES[] = {
2941 &_EINA_MODEL_INTERFACE_PROPERTIES_HASH.base,
2942 &_EINA_MODEL_INTERFACE_CHILDREN_INARRAY.base,
2943 NULL
2944};
2945
2946static const Eina_Model_Type _EINA_MODEL_TYPE_GENERIC =
2947 EINA_MODEL_TYPE_INIT_NOPRIVATE("Eina_Model_Type_Generic",
2948 Eina_Model_Type,
2949 &_EINA_MODEL_TYPE_MIXIN,
2950 _EINA_MODEL_TYPE_GENERIC_IFACES,
2951 NULL);
2952
2953/* EINA_MODEL_TYPE_STRUCT ********************************************/
2954
2955static const Eina_Model_Interface *_EINA_MODEL_TYPE_STRUCT_IFACES[] = {
2956 &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base,
2957 &_EINA_MODEL_INTERFACE_CHILDREN_INARRAY.base,
2958 NULL
2959};
2960
2961static const Eina_Model_Type _EINA_MODEL_TYPE_STRUCT =
2962 EINA_MODEL_TYPE_INIT_NOPRIVATE("Eina_Model_Type_Struct",
2963 Eina_Model_Type,
2964 &_EINA_MODEL_TYPE_MIXIN,
2965 _EINA_MODEL_TYPE_STRUCT_IFACES,
2966 NULL);
2967
2968/**
2969 */
2970
2971/**
2972 * @internal
2973 * @brief Initialize the model module.
2974 *
2975 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
2976 *
2977 * This function sets up the model module of Eina. It is called
2978 * by eina_init().
2979 *
2980 * @see eina_init()
2981 */
2982Eina_Bool
2983eina_model_init(void)
2984{
2985 const char *choice, *tmp;
2986
2987 _eina_model_log_dom = eina_log_domain_register("eina_model",
2988 EINA_LOG_COLOR_DEFAULT);
2989 if (_eina_model_log_dom < 0)
2990 {
2991 EINA_LOG_ERR("Could not register log domain: eina_model");
2992 return EINA_FALSE;
2993 }
2994
2995 choice = getenv("EINA_MODEL_DEBUG");
2996 if (choice)
2997 {
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;
3002 }
3003
3004#ifdef EINA_DEFAULT_MEMPOOL
3005 choice = "pass_through";
3006#else
3007 choice = "chained_mempool";
3008#endif
3009 tmp = getenv("EINA_MEMPOOL");
3010 if (tmp && tmp[0])
3011 choice = tmp;
3012
3013 if (choice)
3014 _eina_model_mp_choice = strdup(choice);
3015
3016 _eina_model_mp = eina_mempool_add
3017 (_eina_model_mp_choice, "model", NULL, sizeof(Eina_Model), 320);
3018 if (!_eina_model_mp)
3019 {
3020 ERR("Mempool for model cannot be allocated in model init.");
3021 goto on_init_fail_mp;
3022 }
3023
3024 if (!eina_lock_new(&_eina_model_inner_mps_lock))
3025 {
3026 ERR("Cannot create inner mempools lock in model init.");
3027 goto on_init_fail_lock_mp;
3028 }
3029 _eina_model_inner_mps = eina_hash_int32_new(NULL);
3030 if (!_eina_model_inner_mps)
3031 {
3032 ERR("Cannot create hash for inner mempools in model init.");
3033 goto on_init_fail_hash_mp;
3034 }
3035
3036 if (!eina_lock_new(&_eina_model_descriptions_lock))
3037 {
3038 ERR("Cannot create model descriptions lock in model init.");
3039 goto on_init_fail_lock_desc;
3040 }
3041 _eina_model_descriptions = eina_hash_pointer_new(NULL);
3042 if (!_eina_model_descriptions)
3043 {
3044 ERR("Cannot create model descriptions hash in model init.");
3045 goto on_init_fail_hash_desc;
3046 }
3047
3048 if (!eina_lock_new(&_eina_model_debug_list_lock))
3049 {
3050 ERR("Cannot create model debug list lock in model init.");
3051 goto on_init_fail_lock_debug;
3052 }
3053
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);
3058
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;
3063
3064 EINA_MODEL_INTERFACE_PROPERTIES_HASH = &_EINA_MODEL_INTERFACE_PROPERTIES_HASH.base;
3065 EINA_MODEL_INTERFACE_PROPERTIES_STRUCT = &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base;
3066
3067 EINA_MODEL_INTERFACE_CHILDREN_INARRAY = &_EINA_MODEL_INTERFACE_CHILDREN_INARRAY.base;
3068
3069 EINA_MODEL_INTERFACE_NAME_PROPERTIES = _EINA_MODEL_INTERFACE_NAME_PROPERTIES;
3070 EINA_MODEL_INTERFACE_NAME_CHILDREN = _EINA_MODEL_INTERFACE_NAME_CHILDREN;
3071
3072 eina_magic_string_static_set(EINA_MAGIC_MODEL, EINA_MAGIC_MODEL_STR);
3073
3074 return EINA_TRUE;
3075
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);
3087 on_init_fail_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;
3092 return EINA_FALSE;
3093}
3094
3095/**
3096 * @internal
3097 * @brief Shut down the model module.
3098 *
3099 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
3100 *
3101 * This function shuts down the model module set up by
3102 * eina_model_init(). It is called by eina_shutdown().
3103 *
3104 * @see eina_shutdown()
3105 */
3106Eina_Bool
3107eina_model_shutdown(void)
3108{
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);
3114
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!");
3118 else
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);
3122
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!");
3126 else
3127 eina_hash_free(_eina_model_descriptions);
3128 eina_lock_release(&_eina_model_descriptions_lock);
3129 eina_lock_free(&_eina_model_descriptions_lock);
3130
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;
3136 return EINA_TRUE;
3137}
3138
3139/*============================================================================*
3140 * Global *
3141 *============================================================================*/
3142
3143/*============================================================================*
3144 * API *
3145 *============================================================================*/
3146
3147
3148EAPI Eina_Error EINA_ERROR_MODEL_FAILED = 0;
3149EAPI Eina_Error EINA_ERROR_MODEL_METHOD_MISSING = 0;
3150
3151EAPI const Eina_Model_Type *EINA_MODEL_TYPE_BASE = NULL;
3152EAPI const Eina_Model_Type *EINA_MODEL_TYPE_MIXIN = NULL;
3153EAPI const Eina_Model_Type *EINA_MODEL_TYPE_GENERIC = NULL;
3154EAPI const Eina_Model_Type *EINA_MODEL_TYPE_STRUCT = NULL;
3155
3156EAPI const Eina_Model_Interface *EINA_MODEL_INTERFACE_PROPERTIES_HASH = NULL;
3157EAPI const Eina_Model_Interface *EINA_MODEL_INTERFACE_PROPERTIES_STRUCT = NULL;
3158EAPI const Eina_Model_Interface *EINA_MODEL_INTERFACE_CHILDREN_INARRAY = NULL;
3159
3160EAPI const char *EINA_MODEL_INTERFACE_NAME_PROPERTIES = "Eina_Model_Interface_Properties";
3161EAPI const char *EINA_MODEL_INTERFACE_NAME_CHILDREN = "Eina_Model_Interface_Children";
3162
3163EAPI Eina_Model *
3164eina_model_new(const Eina_Model_Type *type)
3165{
3166 const Eina_Model_Description *desc;
3167 Eina_Model *model;
3168 unsigned int i;
3169
3170 EINA_SAFETY_ON_NULL_RETURN_VAL(type, NULL);
3171 EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_model_type_check(type), NULL);
3172
3173 desc = _eina_model_description_get(type);
3174 EINA_SAFETY_ON_NULL_RETURN_VAL(desc, NULL);
3175
3176 model = eina_mempool_malloc(_eina_model_mp, sizeof(Eina_Model));
3177 EINA_SAFETY_ON_NULL_GOTO(model, failed_model);
3178
3179 model->desc = desc;
3180 model->listeners.entries = NULL;
3181 model->listeners.deleted = NULL;
3182 model->listeners.freeze = NULL;
3183 model->listeners.walking = 0;
3184
3185 if (desc->total.size == 0)
3186 model->privates = NULL;
3187 else
3188 {
3189 unsigned char *ptr;
3190
3191 model->privates = _eina_model_inner_alloc
3192 (desc->total.privates * sizeof(void *) +
3193 desc->total.size);
3194 EINA_SAFETY_ON_NULL_GOTO(model->privates, failed_privates);
3195
3196 ptr = (unsigned char *)(model->privates + desc->total.privates);
3197 for (i = 0; i < desc->total.privates; i++)
3198 {
3199 unsigned int size;
3200 if (i < desc->total.types)
3201 size = desc->cache.privates[i].type->private_size;
3202 else
3203 size = desc->cache.privates[i].iface->private_size;
3204
3205 if (size == 0)
3206 {
3207 model->privates[i] = NULL;
3208 continue;
3209 }
3210
3211 model->privates[i] = ptr;
3212 memset(ptr, 0, size);
3213
3214 if (size % sizeof(void *) != 0)
3215 size += sizeof(void *) - (size % sizeof(void *));
3216 ptr += size;
3217 }
3218 }
3219
3220 model->refcount = 1;
3221 model->xrefs = NULL;
3222 model->deleted = EINA_FALSE;
3223 EINA_MAGIC_SET(model, EINA_MAGIC_MODEL);
3224
3225 /* call setup of every type in the reverse order,
3226 * they should not call parent's setup.
3227 */
3228 for (i = desc->total.types; i > 0; i--)
3229 {
3230 if (desc->cache.types[i - 1]->setup)
3231 {
3232 if (!desc->cache.types[i - 1]->setup(model))
3233 {
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);
3237 goto failed_types;
3238 }
3239 }
3240 }
3241
3242 /* call setup of every interface in the reverse order,
3243 * they should not call parent's setup.
3244 */
3245 for (i = desc->total.ifaces; i > 0; i--)
3246 {
3247 if (desc->cache.ifaces[i - 1]->setup)
3248 {
3249 if (!desc->cache.ifaces[i - 1]->setup(model))
3250 {
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);
3254 goto failed_ifaces;
3255 }
3256 }
3257 }
3258
3259 if (!desc->ops.type.constructor(model))
3260 {
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;
3264 }
3265
3266 if (EINA_UNLIKELY(_eina_model_debug))
3267 {
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);
3272 }
3273
3274 return model;
3275
3276 failed_constructor:
3277 i = 0;
3278 failed_ifaces:
3279 /* flush every setup interface, natural order */
3280 for (; i < desc->total.ifaces; i++)
3281 desc->cache.ifaces[i]->flush(model);
3282 i = 0;
3283 failed_types:
3284 /* flush every setup type, natural order */
3285 for (; i < desc->total.types; i++)
3286 desc->cache.types[i]->flush(model);
3287
3288 if (model->privates)
3289 _eina_model_inner_free(desc->total.privates * sizeof(void *) +
3290 desc->total.size,
3291 model->privates);
3292
3293 failed_privates:
3294 EINA_MAGIC_SET(model, EINA_MAGIC_NONE);
3295 eina_mempool_free(_eina_model_mp, model);
3296 failed_model:
3297 _eina_model_description_dispose(desc);
3298 return NULL;
3299}
3300
3301static void
3302_eina_model_free(Eina_Model *model)
3303{
3304 const Eina_Model_Description *desc = model->desc;
3305 unsigned int i;
3306
3307 DBG("model %p (%s) refcount=%d deleted=%hhu",
3308 model, model->desc->cache.types[0]->name,
3309 model->refcount, model->deleted);
3310
3311 if (EINA_UNLIKELY(_eina_model_debug))
3312 {
3313 if (model->xrefs)
3314 {
3315 ERR("Model %p (%s) released with references pending:",
3316 model, model->desc->cache.types[0]->name);
3317 while (model->xrefs)
3318 {
3319 Eina_Model_XRef *ref = (Eina_Model_XRef *)model->xrefs;
3320 model->xrefs = eina_inlist_remove(model->xrefs, model->xrefs);
3321
3322 ERR("xref: %p '%s'", ref->id, ref->label);
3323 free(ref);
3324 }
3325 }
3326
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);
3331 }
3332
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);
3337
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);
3342
3343 model->refcount--;
3344 _eina_model_event_callback_call(model, _eina_model_str_freed, NULL);
3345
3346 if (model->privates)
3347 _eina_model_inner_free(desc->total.privates * sizeof(void *) +
3348 desc->total.size,
3349 model->privates);
3350
3351 if (model->listeners.deleted)
3352 _eina_model_event_callback_free_deleted(model);
3353
3354 if (model->listeners.entries)
3355 {
3356 for (i = 0; i < desc->total.events; i++)
3357 {
3358 Eina_Inlist *lst = model->listeners.entries[i];
3359 while (lst)
3360 {
3361 void *tmp = lst;
3362 lst = lst->next;
3363 _eina_model_inner_free(sizeof(Eina_Model_Event_Listener),
3364 tmp);
3365 }
3366 }
3367
3368 _eina_model_inner_free(desc->total.events * sizeof(Eina_Inlist *),
3369 model->listeners.entries);
3370 }
3371
3372 if (model->listeners.freeze)
3373 _eina_model_inner_free(model->desc->total.events * sizeof(int),
3374 model->listeners.freeze);
3375
3376 EINA_MAGIC_SET(model, EINA_MAGIC_NONE);
3377 eina_mempool_free(_eina_model_mp, model);
3378
3379 _eina_model_description_dispose(desc);
3380}
3381
3382static void
3383_eina_model_del(Eina_Model *model)
3384{
3385 const Eina_Model_Description *desc = model->desc;
3386
3387 DBG("model %p (%s) refcount=%d deleted=%hhu",
3388 model, model->desc->cache.types[0]->name,
3389 model->refcount, model->deleted);
3390
3391 EINA_SAFETY_ON_TRUE_RETURN(model->deleted);
3392
3393 model->deleted = EINA_TRUE;
3394 _eina_model_event_callback_call(model, _eina_model_str_deleted, NULL);
3395
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);
3399}
3400
3401static void
3402_eina_model_unref(Eina_Model *model)
3403{
3404 DBG("model %p (%s) refcount=%d deleted=%hhu",
3405 model, model->desc->cache.types[0]->name,
3406 model->refcount, model->deleted);
3407
3408 if (model->refcount > 1)
3409 {
3410 model->refcount--;
3411 return;
3412 }
3413
3414 if (!model->deleted) _eina_model_del(model);
3415 _eina_model_free(model);
3416}
3417
3418#define EINA_MODEL_INSTANCE_CHECK_VAL(inst, retval) \
3419 do \
3420 { \
3421 if (!EINA_MAGIC_CHECK(inst, EINA_MAGIC_MODEL)) \
3422 { \
3423 EINA_MAGIC_FAIL(inst, EINA_MAGIC_MODEL); \
3424 return retval; \
3425 } \
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); \
3429 } \
3430 while (0)
3431
3432#define EINA_MODEL_INSTANCE_CHECK(inst) \
3433 do \
3434 { \
3435 if (!EINA_MAGIC_CHECK(inst, EINA_MAGIC_MODEL)) \
3436 { \
3437 EINA_MAGIC_FAIL(inst, EINA_MAGIC_MODEL); \
3438 return; \
3439 } \
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); \
3443 } \
3444 while (0)
3445
3446#define EINA_MODEL_TYPE_CALL_OPTIONAL_RETURN(model, method, def_retval, ...) \
3447 do \
3448 { \
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; \
3455 } \
3456 while (0)
3457
3458#define EINA_MODEL_TYPE_CALL_OPTIONAL(model, method, ...) \
3459 do \
3460 { \
3461 eina_error_set(0); \
3462 if (model->desc->ops.type.method) \
3463 model->desc->ops.type.method(model, ## __VA_ARGS__); \
3464 else \
3465 DBG("Optional method" # method "() not implemented for model %p (%s)", \
3466 model, model->desc->cache.types[0]->name); \
3467 } \
3468 while (0)
3469
3470#define EINA_MODEL_TYPE_CALL_MANDATORY_RETURN(model, method, def_retval, ...) \
3471 do \
3472 { \
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; \
3480 } \
3481 while (0)
3482
3483#define EINA_MODEL_TYPE_CALL_MANDATORY(model, method, ...) \
3484 do \
3485 { \
3486 eina_error_set(0); \
3487 if (model->desc->ops.type.method) \
3488 model->desc->ops.type.method(model, ## __VA_ARGS__); \
3489 else \
3490 { \
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); \
3494 } \
3495 } \
3496 while (0)
3497
3498
3499#define EINA_MODEL_TYPE_CALL_RETURN(model, method, def_retval, ...) \
3500 do \
3501 { \
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; \
3509 } \
3510 while (0)
3511
3512#define EINA_MODEL_TYPE_CALL(model, method, ...) \
3513 do \
3514 { \
3515 eina_error_set(0); \
3516 if (model->desc->ops.type.method) \
3517 model->desc->ops.type.method(model, ## __VA_ARGS__); \
3518 else \
3519 { \
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); \
3523 } \
3524 } \
3525 while (0)
3526
3527EAPI void
3528eina_model_del(Eina_Model *model)
3529{
3530 EINA_MODEL_INSTANCE_CHECK(model);
3531 _eina_model_del(model);
3532 _eina_model_unref(model);
3533}
3534
3535EAPI const Eina_Model_Type *
3536eina_model_type_get(const Eina_Model *model)
3537{
3538 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
3539 return model->desc->cache.types[0];
3540}
3541
3542EAPI const Eina_Model_Interface *
3543eina_model_interface_get(const Eina_Model *model, const char *name)
3544{
3545 const Eina_Model_Description *desc;
3546 const Eina_Model_Interface **itr, **itr_end;
3547
3548 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
3549 EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
3550
3551 desc = model->desc;
3552 itr = desc->cache.ifaces;
3553 itr_end = itr + desc->total.ifaces;
3554
3555 /* fallback to strcmp if user is lazy about speed */
3556 for (; itr < itr_end; itr++)
3557 if (strcmp((*itr)->name, name) == 0)
3558 return *itr;
3559
3560 return NULL;
3561}
3562
3563static Eina_Bool
3564_eina_model_instance_check(const Eina_Model *model, const Eina_Model_Type *type)
3565{
3566 const Eina_Model_Type **itr, **itr_end;
3567
3568 itr = model->desc->cache.types;
3569 itr_end = itr + model->desc->total.types;
3570
3571 for (; itr < itr_end; itr++)
3572 if (*itr == type)
3573 return EINA_TRUE;
3574
3575 return EINA_FALSE;
3576}
3577
3578EAPI Eina_Bool
3579eina_model_instance_check(const Eina_Model *model, const Eina_Model_Type *type)
3580{
3581 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
3582 EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE);
3583 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), EINA_FALSE);
3584 return _eina_model_instance_check(model, type);
3585}
3586
3587EAPI Eina_Model *
3588eina_model_ref(Eina_Model *model)
3589{
3590 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
3591 DBG("model %p (%s) refcount=%d deleted=%hhu",
3592 model, model->desc->cache.types[0]->name,
3593 model->refcount, model->deleted);
3594 model->refcount++;
3595 return model;
3596}
3597
3598static Eina_Model *
3599_eina_model_xref_add(Eina_Model *model, const void *id, const char *label)
3600{
3601 Eina_Model_XRef *ref;
3602 void *bt[256];
3603 int btlen, labellen;
3604
3605 labellen = label ? strlen(label): 0;
3606 btlen = 0;
3607
3608#ifdef HAVE_BACKTRACE
3609 if (_eina_model_debug == EINA_MODEL_DEBUG_BACKTRACE)
3610 btlen = backtrace(bt, EINA_C_ARRAY_LENGTH(bt));
3611#endif
3612
3613 ref = calloc(1, sizeof(*ref) + (btlen * sizeof(void *)) + (labellen + 1));
3614 EINA_SAFETY_ON_NULL_RETURN_VAL(ref, NULL);
3615
3616 ref->id = id;
3617 memcpy(ref->label, label, labellen);
3618 ref->label[labellen] = '\0';
3619 ref->backtrace.count = btlen;
3620 if (btlen == 0) ref->backtrace.symbols = NULL;
3621 else
3622 {
3623 void *ptr = (unsigned char *)ref + sizeof(*ref) + (labellen + 1);
3624 ref->backtrace.symbols = ptr;
3625 memcpy(ptr, bt, btlen * sizeof(void *));
3626 }
3627
3628 model->xrefs = eina_inlist_append(model->xrefs, EINA_INLIST_GET(ref));
3629 return model;
3630}
3631
3632EAPI Eina_Model *
3633eina_model_xref(Eina_Model *model, const void *id, const char *label)
3634{
3635 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
3636 DBG("model %p (%s) refcount=%d deleted=%hhu id=%p label=%s",
3637 model, model->desc->cache.types[0]->name,
3638 model->refcount, model->deleted, id, label ? label : "");
3639
3640 model->refcount++;
3641
3642 if (EINA_LIKELY(!_eina_model_debug))
3643 return model;
3644
3645 return _eina_model_xref_add(model, id, label);
3646}
3647
3648EAPI void
3649eina_model_unref(Eina_Model *model)
3650{
3651 EINA_MODEL_INSTANCE_CHECK(model);
3652 _eina_model_unref(model);
3653}
3654
3655EAPI void
3656eina_model_xunref(Eina_Model *model, const void *id)
3657{
3658 Eina_Model_XRef *ref;
3659 EINA_MODEL_INSTANCE_CHECK(model);
3660
3661 if (EINA_LIKELY(!_eina_model_debug))
3662 {
3663 _eina_model_unref(model);
3664 return;
3665 }
3666
3667 EINA_INLIST_FOREACH(model->xrefs, ref)
3668 {
3669 if (ref->id != id) continue;
3670
3671 model->xrefs = eina_inlist_remove(model->xrefs, EINA_INLIST_GET(ref));
3672 free(ref);
3673 _eina_model_unref(model);
3674 return;
3675 }
3676
3677 ERR("Could not find existing reference %p to model %p", id, model);
3678}
3679
3680EAPI int
3681eina_model_refcount(const Eina_Model *model)
3682{
3683 EINA_MODEL_INSTANCE_CHECK_VAL(model, -1);
3684 return model->refcount;
3685}
3686
3687EAPI const Eina_Inlist *
3688eina_model_xrefs_get(const Eina_Model *model)
3689{
3690 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
3691 return model->xrefs;
3692}
3693
3694EAPI Eina_Bool
3695eina_model_event_callback_add(Eina_Model *model, const char *event_name, Eina_Model_Event_Cb cb, const void *data)
3696{
3697 const Eina_Model_Description *desc;
3698 Eina_Model_Event_Listener *el;
3699 int event_id;
3700
3701 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
3702 EINA_SAFETY_ON_NULL_RETURN_VAL(event_name, EINA_FALSE);
3703 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE);
3704
3705 desc = model->desc;
3706 event_id = _eina_model_description_event_id_find(desc, event_name);
3707 if (event_id < 0)
3708 {
3709 ERR("No event named %s for model %p (%s)",
3710 event_name, model, model->desc->cache.types[0]->name);
3711 return EINA_FALSE;
3712 }
3713
3714 if (!model->listeners.entries)
3715 {
3716 model->listeners.entries = _eina_model_inner_alloc
3717 (desc->total.events * sizeof(Eina_Inlist *));
3718 EINA_SAFETY_ON_NULL_RETURN_VAL(model->listeners.entries, EINA_FALSE);
3719 memset(model->listeners.entries, 0,
3720 desc->total.events * sizeof(Eina_Inlist *));
3721 }
3722
3723 el = _eina_model_inner_alloc(sizeof(Eina_Model_Event_Listener));
3724 EINA_SAFETY_ON_NULL_RETURN_VAL(el, EINA_FALSE);
3725
3726 el->cb = cb;
3727 el->data = data;
3728 el->deleted = EINA_FALSE;
3729 model->listeners.entries[event_id] = eina_inlist_append
3730 (model->listeners.entries[event_id], EINA_INLIST_GET(el));
3731
3732 return EINA_TRUE;
3733}
3734
3735EAPI Eina_Bool
3736eina_model_event_callback_del(Eina_Model *model, const char *event_name, Eina_Model_Event_Cb cb, const void *data)
3737{
3738 int event_id;
3739 Eina_Inlist *lst;
3740 Eina_Model_Event_Listener *el;
3741
3742 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
3743 EINA_SAFETY_ON_NULL_RETURN_VAL(event_name, EINA_FALSE);
3744 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE);
3745
3746 if (!model->listeners.entries)
3747 {
3748 ERR("No event callbacks for model %p (%s)",
3749 model, model->desc->cache.types[0]->name);
3750 return EINA_FALSE;
3751 }
3752
3753 event_id = _eina_model_description_event_id_find(model->desc, event_name);
3754 if (event_id < 0)
3755 {
3756 ERR("No event named %s for model %p (%s)",
3757 event_name, model, model->desc->cache.types[0]->name);
3758 return EINA_FALSE;
3759 }
3760
3761 lst = model->listeners.entries[event_id];
3762 EINA_INLIST_FOREACH(lst, el)
3763 {
3764 if (el->cb != cb) continue;
3765 if ((data) && (el->data != data)) continue;
3766
3767 if (model->listeners.walking == 0)
3768 {
3769 model->listeners.entries[event_id] = eina_inlist_remove
3770 (model->listeners.entries[event_id], EINA_INLIST_GET(el));
3771 _eina_model_inner_free(sizeof(Eina_Model_Event_Listener), el);
3772 }
3773 else
3774 {
3775 el->deleted = EINA_TRUE;
3776 if (!model->listeners.deleted)
3777 {
3778 model->listeners.deleted = _eina_model_inner_alloc
3779 (model->desc->total.events * sizeof(Eina_List *));
3780 EINA_SAFETY_ON_NULL_RETURN_VAL(model->listeners.deleted,
3781 EINA_FALSE);
3782
3783 memset(model->listeners.deleted, 0,
3784 model->desc->total.events * sizeof(Eina_List *));
3785
3786 }
3787 model->listeners.deleted[event_id] = eina_list_append
3788 (model->listeners.deleted[event_id], el);
3789 }
3790 return EINA_TRUE;
3791 }
3792
3793 ERR("No callback %p data %p found for event named %s for model %p (%s)",
3794 cb, data, event_name, model, model->desc->cache.types[0]->name);
3795 return EINA_FALSE;
3796}
3797
3798EAPI const Eina_Model_Event_Description *
3799eina_model_event_description_get(const Eina_Model *model, const char *event_name)
3800{
3801 const Eina_Model_Description *desc;
3802 int event_id;
3803
3804 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
3805 EINA_SAFETY_ON_NULL_RETURN_VAL(event_name, NULL);
3806
3807 desc = model->desc;
3808 event_id = _eina_model_description_event_id_find(desc, event_name);
3809 if (event_id < 0)
3810 return NULL;
3811
3812 return desc->cache.events[event_id].desc;
3813}
3814
3815EAPI Eina_List *
3816eina_model_event_names_list_get(const Eina_Model *model)
3817{
3818 const Eina_Model_Event_Description_Cache *itr, *itr_end;
3819 Eina_List *lst = NULL;
3820
3821 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
3822
3823 itr = model->desc->cache.events;
3824 itr_end = itr + model->desc->total.events;
3825
3826 for (; itr < itr_end; itr++)
3827 lst = eina_list_append(lst, eina_stringshare_add(itr->name));
3828
3829 return lst;
3830}
3831
3832EAPI void
3833eina_model_event_names_list_free(Eina_List *list)
3834{
3835 const char *str;
3836 EINA_LIST_FREE(list, str)
3837 eina_stringshare_del(str);
3838}
3839
3840EAPI Eina_Bool
3841eina_model_event_callback_call(Eina_Model *model, const char *name, const void *event_info)
3842{
3843 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
3844 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
3845 return _eina_model_event_callback_call(model, name, event_info);
3846}
3847
3848EAPI int
3849eina_model_event_callback_freeze(Eina_Model *model, const char *name)
3850{
3851 int event_id;
3852
3853 EINA_MODEL_INSTANCE_CHECK_VAL(model, -1);
3854 EINA_SAFETY_ON_NULL_RETURN_VAL(name, -1);
3855
3856 event_id = _eina_model_description_event_id_find(model->desc, name);
3857 if (event_id < 0) return -1;
3858
3859 if (!model->listeners.freeze)
3860 {
3861 model->listeners.freeze = _eina_model_inner_alloc
3862 (model->desc->total.events * sizeof(int));
3863 EINA_SAFETY_ON_NULL_RETURN_VAL(model->listeners.freeze, -1);
3864
3865 memset(model->listeners.freeze, 0,
3866 model->desc->total.events * sizeof(int));
3867 }
3868
3869 if (model->listeners.freeze[event_id] == 0)
3870 DBG("model %p (%s) event %s frozen",
3871 model, model->desc->cache.types[0]->name, name);
3872
3873 model->listeners.freeze[event_id]++;
3874 return model->listeners.freeze[event_id];
3875}
3876
3877EAPI int
3878eina_model_event_callback_thaw(Eina_Model *model, const char *name)
3879{
3880 int event_id;
3881
3882 EINA_MODEL_INSTANCE_CHECK_VAL(model, -1);
3883 EINA_SAFETY_ON_NULL_RETURN_VAL(name, -1);
3884 EINA_SAFETY_ON_NULL_RETURN_VAL(model->listeners.freeze, -1);
3885
3886 event_id = _eina_model_description_event_id_find(model->desc, name);
3887 if (event_id < 0) return -1;
3888
3889 model->listeners.freeze[event_id]--;
3890 if (model->listeners.freeze[event_id] == 0)
3891 DBG("model %p (%s) event %s unfrozen",
3892 model, model->desc->cache.types[0]->name, name);
3893 return model->listeners.freeze[event_id];
3894}
3895
3896EAPI Eina_Model *
3897eina_model_copy(const Eina_Model *model)
3898{
3899 const Eina_Model_Description *desc;
3900 Eina_Model *copy;
3901 unsigned int i;
3902
3903 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
3904 desc = model->desc;
3905 copy = eina_model_new(desc->cache.types[0]);
3906 EINA_SAFETY_ON_NULL_RETURN_VAL(copy, NULL);
3907
3908 /* call copy of every type in the reverse order,
3909 * they should not call parent's copy.
3910 */
3911 for (i = desc->total.types; i > 0; i--)
3912 {
3913 if (desc->cache.types[i - 1]->copy)
3914 {
3915 if (!desc->cache.types[i - 1]->copy(model, copy))
3916 goto failed;
3917 }
3918 }
3919
3920 /* call copy of every interface in the reverse order,
3921 * they should not call parent's copy.
3922 */
3923 for (i = desc->total.ifaces; i > 0; i--)
3924 {
3925 if (desc->cache.ifaces[i - 1]->copy)
3926 {
3927 if (!desc->cache.ifaces[i - 1]->copy(model, copy))
3928 goto failed;
3929 }
3930 }
3931
3932 return copy;
3933
3934 failed:
3935 ERR("Failed to copy model %p %s", model, desc->cache.types[0]->name);
3936 eina_model_del(copy);
3937 return NULL;
3938}
3939
3940EAPI Eina_Model *
3941eina_model_deep_copy(const Eina_Model *model)
3942{
3943 const Eina_Model_Description *desc;
3944 Eina_Model *deep_copy;
3945 unsigned int i;
3946
3947 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
3948 desc = model->desc;
3949 deep_copy = eina_model_new(desc->cache.types[0]);
3950 EINA_SAFETY_ON_NULL_RETURN_VAL(deep_copy, NULL);
3951
3952 /* call deep_copy of every type in the reverse order,
3953 * they should not call parent's deep_copy.
3954 */
3955 for (i = desc->total.types; i > 0; i--)
3956 {
3957 if (desc->cache.types[i - 1]->deep_copy)
3958 {
3959 if (!desc->cache.types[i - 1]->deep_copy(model, deep_copy))
3960 goto failed;
3961 }
3962 }
3963
3964 /* call deep_copy of every interface in the reverse order,
3965 * they should not call parent's deep_copy.
3966 */
3967 for (i = desc->total.ifaces; i > 0; i--)
3968 {
3969 if (desc->cache.ifaces[i - 1]->deep_copy)
3970 {
3971 if (!desc->cache.ifaces[i - 1]->deep_copy(model, deep_copy))
3972 goto failed;
3973 }
3974 }
3975
3976 return deep_copy;
3977
3978 failed:
3979 ERR("Failed to deep copy model %p %s", model, desc->cache.types[0]->name);
3980 eina_model_del(deep_copy);
3981 return NULL;
3982}
3983
3984EAPI int
3985eina_model_compare(const Eina_Model *a, const Eina_Model *b)
3986{
3987 const Eina_Model_Description *desc_a, *desc_b;
3988 Eina_Bool ok;
3989 int cmp = -1;
3990
3991 EINA_MODEL_INSTANCE_CHECK_VAL(a, -1);
3992 EINA_MODEL_INSTANCE_CHECK_VAL(b, -1);
3993 desc_a = a->desc;
3994 desc_b = b->desc;
3995
3996 if ((!desc_a->ops.type.compare) && (!desc_b->ops.type.compare))
3997 {
3998 ERR("Models %p (%s) and %p (%s) can't compare",
3999 a, desc_a->cache.types[0]->name,
4000 b, desc_b->cache.types[0]->name);
4001 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
4002 return -1;
4003 }
4004 else if ((desc_a->ops.type.compare) && (desc_b->ops.type.compare))
4005 {
4006 ok = desc_a->ops.type.compare(a, b, &cmp);
4007 if (!ok)
4008 {
4009 ok = desc_b->ops.type.compare(b, a, &cmp);
4010 if (ok)
4011 cmp = -cmp; /* swapped sides! */
4012 }
4013 }
4014 else if (desc_a->ops.type.compare)
4015 ok = desc_a->ops.type.compare(a, b, &cmp);
4016 else
4017 {
4018 ok = desc_b->ops.type.compare(b, a, &cmp);
4019 if (ok)
4020 cmp = -cmp; /* swapped sides! */
4021 }
4022
4023 if (!ok)
4024 {
4025 ERR("Could not compare models %p (%s) and %p (%s)",
4026 a, desc_a->cache.types[0]->name,
4027 b, desc_b->cache.types[0]->name);
4028 eina_error_set(EINA_ERROR_MODEL_FAILED);
4029 return -1;
4030 }
4031
4032 return cmp;
4033}
4034
4035EAPI Eina_Bool
4036eina_model_load(Eina_Model *model)
4037{
4038 Eina_Bool ret;
4039
4040 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
4041
4042 eina_error_set(0);
4043 if (model->desc->ops.type.load)
4044 {
4045 ret = model->desc->ops.type.load(model);
4046 if (ret)
4047 _eina_model_event_callback_call(model, _eina_model_str_loaded, NULL);
4048 }
4049 else
4050 {
4051 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
4052 ret = EINA_FALSE;
4053 ERR("Method load() not implemented for model %p (%s)",
4054 model, model->desc->cache.types[0]->name);
4055 }
4056
4057 return ret;
4058}
4059
4060EAPI Eina_Bool
4061eina_model_unload(Eina_Model *model)
4062{
4063 Eina_Bool ret;
4064
4065 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
4066
4067 eina_error_set(0);
4068 if (model->desc->ops.type.unload)
4069 {
4070 ret = model->desc->ops.type.unload(model);
4071 if (ret)
4072 _eina_model_event_callback_call
4073 (model, _eina_model_str_unloaded, NULL);
4074 }
4075 else
4076 {
4077 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
4078 ret = EINA_FALSE;
4079 ERR("Method unload() not implemented for model %p (%s)",
4080 model, model->desc->cache.types[0]->name);
4081 }
4082
4083 return ret;
4084}
4085
4086EAPI Eina_Bool
4087eina_model_property_get(const Eina_Model *model, const char *name, Eina_Value *value)
4088{
4089 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
4090 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
4091 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
4092 EINA_MODEL_TYPE_CALL_MANDATORY_RETURN(model, property_get, EINA_FALSE,
4093 name, value);
4094}
4095
4096EAPI Eina_Bool
4097eina_model_property_set(Eina_Model *model, const const char *name, const Eina_Value *value)
4098{
4099 Eina_Bool ret;
4100
4101 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
4102 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
4103 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
4104 EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), EINA_FALSE);
4105
4106 eina_error_set(0);
4107 if (model->desc->ops.type.property_set)
4108 {
4109 ret = model->desc->ops.type.property_set(model, name, value);
4110 if (ret)
4111 _eina_model_event_callback_call
4112 (model, _eina_model_str_property_set, name);
4113 }
4114 else
4115 {
4116 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
4117 ret = EINA_FALSE;
4118 ERR("Method property_set() not implemented for model %p (%s)",
4119 model, model->desc->cache.types[0]->name);
4120 }
4121
4122 return ret;
4123}
4124
4125EAPI Eina_Bool
4126eina_model_property_del(Eina_Model *model, const char *name)
4127{
4128 Eina_Bool ret;
4129
4130 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
4131 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
4132
4133 eina_error_set(0);
4134 if (model->desc->ops.type.property_del)
4135 {
4136 ret = model->desc->ops.type.property_del(model, name);
4137 if (ret)
4138 _eina_model_event_callback_call
4139 (model, _eina_model_str_property_del, name);
4140 }
4141 else
4142 {
4143 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
4144 ret = EINA_FALSE;
4145 ERR("Method property_del() not implemented for model %p (%s)",
4146 model, model->desc->cache.types[0]->name);
4147 }
4148
4149 return ret;
4150}
4151
4152EAPI Eina_List *
4153eina_model_properties_names_list_get(const Eina_Model *model)
4154{
4155 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4156 EINA_MODEL_TYPE_CALL_OPTIONAL_RETURN(model, properties_names_list_get, NULL);
4157}
4158
4159EAPI void
4160eina_model_properties_names_list_free(Eina_List *list)
4161{
4162 const char *str;
4163 EINA_LIST_FREE(list, str)
4164 eina_stringshare_del(str);
4165}
4166
4167EAPI int
4168eina_model_child_count(const Eina_Model *model)
4169{
4170 EINA_MODEL_INSTANCE_CHECK_VAL(model, -1);
4171 EINA_MODEL_TYPE_CALL_OPTIONAL_RETURN(model, child_count, 0);
4172}
4173
4174EAPI Eina_Model *
4175eina_model_child_get(const Eina_Model *model, unsigned int position)
4176{
4177 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4178 EINA_MODEL_TYPE_CALL_RETURN(model, child_get, NULL, position);
4179}
4180
4181EAPI Eina_Bool
4182eina_model_child_set(Eina_Model *model, unsigned int position, Eina_Model *child)
4183{
4184 Eina_Bool ret;
4185
4186 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
4187 EINA_MODEL_INSTANCE_CHECK_VAL(child, EINA_FALSE);
4188
4189 eina_error_set(0);
4190 if (model->desc->ops.type.child_set)
4191 {
4192 ret = model->desc->ops.type.child_set(model, position, child);
4193 if (ret)
4194 _eina_model_event_callback_call
4195 (model, _eina_model_str_child_set, &position);
4196 }
4197 else
4198 {
4199 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
4200 ret = EINA_FALSE;
4201 ERR("Method child_set() not implemented for model %p (%s)",
4202 model, model->desc->cache.types[0]->name);
4203 }
4204
4205 return ret;
4206}
4207
4208EAPI Eina_Bool
4209eina_model_child_del(Eina_Model *model, unsigned int position)
4210{
4211 Eina_Bool ret;
4212
4213 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
4214
4215 eina_error_set(0);
4216 if (model->desc->ops.type.child_del)
4217 {
4218 ret = model->desc->ops.type.child_del(model, position);
4219 if (ret)
4220 {
4221 _eina_model_event_callback_call
4222 (model, _eina_model_str_child_del, &position);
4223 _eina_model_event_callback_call
4224 (model, _eina_model_str_children_changed, NULL);
4225 }
4226 }
4227 else
4228 {
4229 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
4230 ret = EINA_FALSE;
4231 ERR("Method child_del() not implemented for model %p (%s)",
4232 model, model->desc->cache.types[0]->name);
4233 }
4234
4235 return ret;
4236}
4237
4238EAPI Eina_Bool
4239eina_model_child_insert_at(Eina_Model *model, unsigned int position, Eina_Model *child)
4240{
4241 Eina_Bool ret;
4242
4243 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
4244 EINA_SAFETY_ON_NULL_RETURN_VAL(child, EINA_FALSE);
4245
4246 eina_error_set(0);
4247 if (model->desc->ops.type.child_insert_at)
4248 {
4249 ret = model->desc->ops.type.child_insert_at(model, position, child);
4250 if (ret)
4251 {
4252 _eina_model_event_callback_call
4253 (model, _eina_model_str_child_inserted, &position);
4254 _eina_model_event_callback_call
4255 (model, _eina_model_str_children_changed, NULL);
4256 }
4257 }
4258 else
4259 {
4260 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
4261 ret = EINA_FALSE;
4262 ERR("Method child_insert_at() not implemented for model %p (%s)",
4263 model, model->desc->cache.types[0]->name);
4264 }
4265
4266 return ret;
4267}
4268
4269EAPI int
4270eina_model_child_append(Eina_Model *model, Eina_Model *child)
4271{
4272 Eina_Bool ret;
4273 int position;
4274
4275 EINA_MODEL_INSTANCE_CHECK_VAL(model, -1);
4276 EINA_SAFETY_ON_NULL_RETURN_VAL(child, -1);
4277
4278 position = eina_model_child_count(model);
4279 if (position < 0)
4280 return -1;
4281
4282 eina_error_set(0);
4283 if (model->desc->ops.type.child_insert_at)
4284 {
4285 ret = model->desc->ops.type.child_insert_at(model, position, child);
4286 if (ret)
4287 {
4288 _eina_model_event_callback_call
4289 (model, _eina_model_str_child_inserted, &position);
4290 _eina_model_event_callback_call
4291 (model, _eina_model_str_children_changed, NULL);
4292 }
4293 }
4294 else
4295 {
4296 eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING);
4297 ret = EINA_FALSE;
4298 ERR("Method child_insert_at() not implemented for model %p (%s)",
4299 model, model->desc->cache.types[0]->name);
4300 }
4301
4302 return ret ? position : -1;
4303}
4304
4305EAPI int
4306eina_model_child_find(const Eina_Model *model, unsigned int start_position, const Eina_Model *other)
4307{
4308 EINA_MODEL_INSTANCE_CHECK_VAL(model, -1);
4309 EINA_SAFETY_ON_NULL_RETURN_VAL(other, -1);
4310 EINA_MODEL_TYPE_CALL_RETURN(model, child_find, -1, start_position, other);
4311}
4312
4313EAPI int
4314eina_model_child_criteria_match(const Eina_Model *model, unsigned int start_position, Eina_Each_Cb match, const void *data)
4315{
4316 EINA_MODEL_INSTANCE_CHECK_VAL(model, -1);
4317 EINA_SAFETY_ON_NULL_RETURN_VAL(match, -1);
4318 EINA_MODEL_TYPE_CALL_RETURN(model, child_criteria_match, -1,
4319 start_position, match, data);
4320}
4321
4322EAPI Eina_Bool
4323eina_model_child_sort(Eina_Model *model, Eina_Compare_Cb compare)
4324{
4325 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
4326 EINA_SAFETY_ON_NULL_RETURN_VAL(compare, EINA_FALSE);
4327 EINA_MODEL_TYPE_CALL(model, child_sort, compare);
4328 _eina_model_event_callback_call
4329 (model, _eina_model_str_children_changed, NULL);
4330 return EINA_TRUE;
4331}
4332
4333EAPI Eina_Iterator *
4334eina_model_child_iterator_get(Eina_Model *model)
4335{
4336 int count;
4337 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4338 count = eina_model_child_count(model);
4339 if (count < 0)
4340 return NULL;
4341 EINA_MODEL_TYPE_CALL_RETURN(model, child_iterator_get, NULL, 0, count);
4342}
4343
4344EAPI Eina_Iterator *
4345eina_model_child_slice_iterator_get(Eina_Model *model, unsigned int start, unsigned int count)
4346{
4347 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4348 EINA_MODEL_TYPE_CALL_RETURN(model, child_iterator_get, NULL, start, count);
4349}
4350
4351EAPI Eina_Iterator *
4352eina_model_child_reversed_iterator_get(Eina_Model *model)
4353{
4354 int count;
4355 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4356 count = eina_model_child_count(model);
4357 if (count < 0)
4358 return NULL;
4359 EINA_MODEL_TYPE_CALL_RETURN(model, child_reversed_iterator_get, NULL,
4360 0, count);
4361}
4362
4363EAPI Eina_Iterator *
4364eina_model_child_slice_reversed_iterator_get(Eina_Model *model, unsigned int start, unsigned int count)
4365{
4366 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4367 EINA_MODEL_TYPE_CALL_RETURN(model, child_reversed_iterator_get, NULL,
4368 start, count);
4369}
4370
4371EAPI Eina_Iterator *
4372eina_model_child_sorted_iterator_get(Eina_Model *model, Eina_Compare_Cb compare)
4373{
4374 int count;
4375 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4376 EINA_SAFETY_ON_NULL_RETURN_VAL(compare, NULL);
4377 count = eina_model_child_count(model);
4378 if (count < 0)
4379 return NULL;
4380 EINA_MODEL_TYPE_CALL_RETURN(model, child_sorted_iterator_get, NULL,
4381 0, count, compare);
4382}
4383
4384EAPI Eina_Iterator *
4385eina_model_child_slice_sorted_iterator_get(Eina_Model *model, unsigned int start, unsigned int count, Eina_Compare_Cb compare)
4386{
4387 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4388 EINA_SAFETY_ON_NULL_RETURN_VAL(compare, NULL);
4389 EINA_MODEL_TYPE_CALL_RETURN(model, child_sorted_iterator_get, NULL,
4390 start, count, compare);
4391}
4392
4393EAPI Eina_Iterator *
4394eina_model_child_filtered_iterator_get(Eina_Model *model, Eina_Each_Cb match, const void *data)
4395{
4396 int count;
4397 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4398 EINA_SAFETY_ON_NULL_RETURN_VAL(match, NULL);
4399 count = eina_model_child_count(model);
4400 if (count < 0)
4401 return NULL;
4402 EINA_MODEL_TYPE_CALL_RETURN(model, child_filtered_iterator_get, NULL,
4403 0, count, match, data);
4404}
4405
4406EAPI Eina_Iterator *
4407eina_model_child_slice_filtered_iterator_get(Eina_Model *model, unsigned int start, unsigned int count, Eina_Each_Cb match, const void *data)
4408{
4409 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4410 EINA_SAFETY_ON_NULL_RETURN_VAL(match, NULL);
4411 EINA_MODEL_TYPE_CALL_RETURN(model, child_filtered_iterator_get, NULL,
4412 start, count, match, data);
4413}
4414
4415EAPI char *
4416eina_model_to_string(const Eina_Model *model)
4417{
4418 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4419 EINA_MODEL_TYPE_CALL_RETURN(model, to_string, NULL);
4420}
4421
4422/* type functions *****************************************************/
4423
4424EAPI Eina_Bool
4425eina_model_type_check(const Eina_Model_Type *type)
4426{
4427 EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE);
4428 return _eina_model_type_check(type);
4429}
4430
4431EAPI const char *
4432eina_model_type_name_get(const Eina_Model_Type *type)
4433{
4434 EINA_SAFETY_ON_NULL_RETURN_VAL(type, NULL);
4435 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), NULL);
4436 return type->name;
4437}
4438
4439EAPI const Eina_Model_Type *
4440eina_model_type_parent_get(const Eina_Model_Type *type)
4441{
4442 EINA_SAFETY_ON_NULL_RETURN_VAL(type, NULL);
4443 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), NULL);
4444 return type->parent;
4445}
4446
4447#define EINA_MODEL_TYPE_INSTANCE_CHECK(type, model) \
4448 EINA_SAFETY_ON_NULL_RETURN(type); \
4449 EINA_SAFETY_ON_FALSE_RETURN(_eina_model_type_check(type)); \
4450 EINA_MODEL_INSTANCE_CHECK(model); \
4451 EINA_SAFETY_ON_FALSE_RETURN(_eina_model_instance_check(model, type));
4452
4453#define EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, retval) \
4454 EINA_SAFETY_ON_NULL_RETURN_VAL(type, retval); \
4455 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), retval); \
4456 EINA_MODEL_INSTANCE_CHECK_VAL(model, retval); \
4457 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_instance_check(model, type), retval);
4458
4459EAPI Eina_Bool
4460eina_model_type_constructor(const Eina_Model_Type *type, Eina_Model *model)
4461{
4462 Eina_Bool (*constructor)(Eina_Model *);
4463
4464 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4465
4466 constructor = _eina_model_type_find_offset
4467 (type, offsetof(Eina_Model_Type, constructor));
4468 EINA_SAFETY_ON_NULL_RETURN_VAL(constructor, EINA_FALSE);
4469
4470 return constructor(model);
4471}
4472
4473EAPI Eina_Bool
4474eina_model_type_destructor(const Eina_Model_Type *type, Eina_Model *model)
4475{
4476 Eina_Bool (*destructor)(Eina_Model *);
4477
4478 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4479
4480 destructor = _eina_model_type_find_offset
4481 (type, offsetof(Eina_Model_Type, destructor));
4482 EINA_SAFETY_ON_NULL_RETURN_VAL(destructor, EINA_FALSE);
4483
4484 return destructor(model);
4485}
4486
4487EAPI Eina_Bool
4488eina_model_type_copy(const Eina_Model_Type *type, const Eina_Model *src, Eina_Model *dst)
4489{
4490 Eina_Bool (*copy)(const Eina_Model *, Eina_Model *);
4491
4492 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, src, EINA_FALSE);
4493 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, dst, EINA_FALSE);
4494
4495 copy = _eina_model_type_find_offset
4496 (type, offsetof(Eina_Model_Type, copy));
4497 EINA_SAFETY_ON_NULL_RETURN_VAL(copy, EINA_FALSE);
4498
4499 return copy(src, dst);
4500}
4501
4502EAPI Eina_Bool
4503eina_model_type_deep_copy(const Eina_Model_Type *type, const Eina_Model *src, Eina_Model *dst)
4504{
4505 Eina_Bool (*deep_copy)(const Eina_Model *, Eina_Model *);
4506
4507 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, src, EINA_FALSE);
4508 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, dst, EINA_FALSE);
4509
4510 deep_copy = _eina_model_type_find_offset
4511 (type, offsetof(Eina_Model_Type, deep_copy));
4512 EINA_SAFETY_ON_NULL_RETURN_VAL(deep_copy, EINA_FALSE);
4513
4514 return deep_copy(src, dst);
4515}
4516
4517EAPI Eina_Bool
4518eina_model_type_compare(const Eina_Model_Type *type, const Eina_Model *a, const Eina_Model *b, int *cmp)
4519{
4520 Eina_Bool (*compare)(const Eina_Model *, const Eina_Model *, int *);
4521
4522 EINA_SAFETY_ON_NULL_RETURN_VAL(cmp, EINA_FALSE);
4523 *cmp = 0;
4524
4525 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, a, EINA_FALSE);
4526 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, b, EINA_FALSE);
4527
4528 compare = _eina_model_type_find_offset
4529 (type, offsetof(Eina_Model_Type, compare));
4530 EINA_SAFETY_ON_NULL_RETURN_VAL(compare, EINA_FALSE);
4531
4532 return compare(a, b, cmp);
4533}
4534
4535EAPI Eina_Bool
4536eina_model_type_load(const Eina_Model_Type *type, Eina_Model *model)
4537{
4538 Eina_Bool (*load)(Eina_Model *);
4539
4540 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4541
4542 load = _eina_model_type_find_offset
4543 (type, offsetof(Eina_Model_Type, load));
4544 EINA_SAFETY_ON_NULL_RETURN_VAL(load, EINA_FALSE);
4545
4546 return load(model);
4547}
4548
4549EAPI Eina_Bool
4550eina_model_type_unload(const Eina_Model_Type *type, Eina_Model *model)
4551{
4552 Eina_Bool (*unload)(Eina_Model *);
4553
4554 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4555
4556 unload = _eina_model_type_find_offset
4557 (type, offsetof(Eina_Model_Type, unload));
4558 EINA_SAFETY_ON_NULL_RETURN_VAL(unload, EINA_FALSE);
4559
4560 return unload(model);
4561}
4562
4563EAPI Eina_Bool
4564eina_model_type_property_get(const Eina_Model_Type *type, const Eina_Model *model, const char *name, Eina_Value *value)
4565{
4566 Eina_Bool (*property_get)(const Eina_Model *, const char *, Eina_Value *);
4567
4568 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
4569 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
4570
4571 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4572
4573 property_get = _eina_model_type_find_offset
4574 (type, offsetof(Eina_Model_Type, property_get));
4575 EINA_SAFETY_ON_NULL_RETURN_VAL(property_get, EINA_FALSE);
4576
4577 return property_get(model, name, value);
4578}
4579
4580EAPI Eina_Bool
4581eina_model_type_property_set(const Eina_Model_Type *type, Eina_Model *model, const char *name, const Eina_Value *value)
4582{
4583 Eina_Bool (*property_set)(Eina_Model *, const char *, const Eina_Value *);
4584
4585 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
4586 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
4587 EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), EINA_FALSE);
4588
4589 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4590
4591 property_set = _eina_model_type_find_offset
4592 (type, offsetof(Eina_Model_Type, property_set));
4593 EINA_SAFETY_ON_NULL_RETURN_VAL(property_set, EINA_FALSE);
4594
4595 return property_set(model, name, value);
4596}
4597
4598EAPI Eina_Bool
4599eina_model_type_property_del(const Eina_Model_Type *type, Eina_Model *model, const char *name)
4600{
4601 Eina_Bool (*property_del)(const Eina_Model *, const char *);
4602
4603 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
4604 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4605
4606 property_del = _eina_model_type_find_offset
4607 (type, offsetof(Eina_Model_Type, property_del));
4608 EINA_SAFETY_ON_NULL_RETURN_VAL(property_del, EINA_FALSE);
4609
4610 return property_del(model, name);
4611}
4612
4613EAPI Eina_List *
4614eina_model_type_properties_names_list_get(const Eina_Model_Type *type, const Eina_Model *model)
4615{
4616 Eina_List *(*properties_names_list_get)(const Eina_Model *);
4617
4618 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL);
4619
4620 properties_names_list_get = _eina_model_type_find_offset
4621 (type, offsetof(Eina_Model_Type, properties_names_list_get));
4622 EINA_SAFETY_ON_NULL_RETURN_VAL(properties_names_list_get, NULL);
4623
4624 return properties_names_list_get(model);
4625}
4626
4627EAPI int
4628eina_model_type_child_count(const Eina_Model_Type *type, const Eina_Model *model)
4629{
4630 int (*child_count)(const Eina_Model *);
4631
4632 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, -1);
4633
4634 child_count = _eina_model_type_find_offset
4635 (type, offsetof(Eina_Model_Type, child_count));
4636 EINA_SAFETY_ON_NULL_RETURN_VAL(child_count, -1);
4637
4638 return child_count(model);
4639}
4640
4641EAPI Eina_Model *
4642eina_model_type_child_get(const Eina_Model_Type *type, const Eina_Model *model, unsigned int position)
4643{
4644 Eina_Model *(*child_get)(const Eina_Model *, unsigned int);
4645
4646 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL);
4647
4648 child_get = _eina_model_type_find_offset
4649 (type, offsetof(Eina_Model_Type, child_get));
4650 EINA_SAFETY_ON_NULL_RETURN_VAL(child_get, NULL);
4651
4652 return child_get(model, position);
4653}
4654
4655EAPI Eina_Bool
4656eina_model_type_child_set(const Eina_Model_Type *type, Eina_Model *model, unsigned int position, Eina_Model *child)
4657{
4658 Eina_Bool (*child_set)(Eina_Model *, unsigned int, Eina_Model *);
4659
4660 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4661 EINA_MODEL_INSTANCE_CHECK_VAL(child, EINA_FALSE);
4662
4663 child_set = _eina_model_type_find_offset
4664 (type, offsetof(Eina_Model_Type, child_set));
4665 EINA_SAFETY_ON_NULL_RETURN_VAL(child_set, EINA_FALSE);
4666
4667 return child_set(model, position, child);
4668}
4669
4670EAPI Eina_Bool
4671eina_model_type_child_del(const Eina_Model_Type *type, Eina_Model *model, unsigned int position)
4672{
4673 Eina_Bool (*child_del)(Eina_Model *, unsigned int);
4674
4675 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4676
4677 child_del = _eina_model_type_find_offset
4678 (type, offsetof(Eina_Model_Type, child_del));
4679 EINA_SAFETY_ON_NULL_RETURN_VAL(child_del, EINA_FALSE);
4680
4681 return child_del(model, position);
4682}
4683
4684EAPI Eina_Bool
4685eina_model_type_child_insert_at(const Eina_Model_Type *type, Eina_Model *model, unsigned int position, Eina_Model *child)
4686{
4687 Eina_Bool (*child_insert_at)(Eina_Model *, unsigned int, Eina_Model *);
4688
4689 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE);
4690 EINA_MODEL_INSTANCE_CHECK_VAL(child, EINA_FALSE);
4691
4692 child_insert_at = _eina_model_type_find_offset
4693 (type, offsetof(Eina_Model_Type, child_insert_at));
4694 EINA_SAFETY_ON_NULL_RETURN_VAL(child_insert_at, EINA_FALSE);
4695
4696 return child_insert_at(model, position, child);
4697}
4698
4699EAPI int
4700eina_model_type_child_find(const Eina_Model_Type *type, const Eina_Model *model, unsigned int start_position, const Eina_Model *other)
4701{
4702 int (*child_find)(const Eina_Model *, unsigned int, const Eina_Model *);
4703
4704 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, -1);
4705 EINA_MODEL_INSTANCE_CHECK_VAL(other, -1);
4706
4707 child_find = _eina_model_type_find_offset
4708 (type, offsetof(Eina_Model_Type, child_find));
4709 EINA_SAFETY_ON_NULL_RETURN_VAL(child_find, -1);
4710
4711 return child_find(model, start_position, other);
4712}
4713
4714EAPI int
4715eina_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)
4716{
4717 int (*child_criteria_match)(const Eina_Model *, unsigned int, Eina_Each_Cb, const void *);
4718
4719 EINA_SAFETY_ON_NULL_RETURN_VAL(match, -1);
4720 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, -1);
4721
4722 child_criteria_match = _eina_model_type_find_offset
4723 (type, offsetof(Eina_Model_Type, child_criteria_match));
4724 EINA_SAFETY_ON_NULL_RETURN_VAL(child_criteria_match, -1);
4725
4726 return child_criteria_match(model, start_position, match, data);
4727}
4728
4729EAPI void
4730eina_model_type_child_sort(const Eina_Model_Type *type, Eina_Model *model, Eina_Compare_Cb compare)
4731{
4732 void (*child_sort)(Eina_Model *, Eina_Compare_Cb);
4733
4734 EINA_SAFETY_ON_NULL_RETURN(compare);
4735 EINA_MODEL_TYPE_INSTANCE_CHECK(type, model);
4736
4737 child_sort = _eina_model_type_find_offset
4738 (type, offsetof(Eina_Model_Type, child_sort));
4739 EINA_SAFETY_ON_NULL_RETURN(child_sort);
4740
4741 return child_sort(model, compare);
4742}
4743
4744EAPI Eina_Iterator *
4745eina_model_type_child_iterator_get(const Eina_Model_Type *type, Eina_Model *model, unsigned int start, unsigned int count)
4746{
4747 Eina_Iterator *(*child_iterator_get)(const Eina_Model *, unsigned int, unsigned int);
4748
4749 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL);
4750
4751 child_iterator_get = _eina_model_type_find_offset
4752 (type, offsetof(Eina_Model_Type, child_iterator_get));
4753 EINA_SAFETY_ON_NULL_RETURN_VAL(child_iterator_get, NULL);
4754
4755 return child_iterator_get(model, start, count);
4756}
4757
4758EAPI Eina_Iterator *
4759eina_model_type_child_reversed_iterator_get(const Eina_Model_Type *type, Eina_Model *model, unsigned int start, unsigned int count)
4760{
4761 Eina_Iterator *(*child_reversed_iterator_get)(const Eina_Model *, unsigned int, unsigned int);
4762
4763 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL);
4764
4765 child_reversed_iterator_get = _eina_model_type_find_offset
4766 (type, offsetof(Eina_Model_Type, child_reversed_iterator_get));
4767 EINA_SAFETY_ON_NULL_RETURN_VAL(child_reversed_iterator_get, NULL);
4768
4769 return child_reversed_iterator_get(model, start, count);
4770}
4771
4772EAPI Eina_Iterator *
4773eina_model_type_child_sorted_iterator_get(const Eina_Model_Type *type, Eina_Model *model, unsigned int start, unsigned int count, Eina_Compare_Cb compare)
4774{
4775 Eina_Iterator *(*child_sorted_iterator_get)(const Eina_Model *, unsigned int, unsigned int, Eina_Compare_Cb);
4776
4777 EINA_SAFETY_ON_NULL_RETURN_VAL(compare, NULL);
4778 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL);
4779
4780 child_sorted_iterator_get = _eina_model_type_find_offset
4781 (type, offsetof(Eina_Model_Type, child_sorted_iterator_get));
4782 EINA_SAFETY_ON_NULL_RETURN_VAL(child_sorted_iterator_get, NULL);
4783
4784 return child_sorted_iterator_get(model, start, count, compare);
4785}
4786
4787EAPI Eina_Iterator *
4788eina_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)
4789{
4790 Eina_Iterator *(*child_filtered_iterator_get)(const Eina_Model *, unsigned int, unsigned int, Eina_Each_Cb, const void *);
4791
4792 EINA_SAFETY_ON_NULL_RETURN_VAL(match, NULL);
4793 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL);
4794
4795 child_filtered_iterator_get = _eina_model_type_find_offset
4796 (type, offsetof(Eina_Model_Type, child_filtered_iterator_get));
4797 EINA_SAFETY_ON_NULL_RETURN_VAL(child_filtered_iterator_get, NULL);
4798
4799 return child_filtered_iterator_get(model, start, count, match, data);
4800}
4801
4802EAPI char *
4803eina_model_type_to_string(const Eina_Model_Type *type, const Eina_Model *model)
4804{
4805 char *(*to_string)(const Eina_Model *);
4806
4807 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL);
4808
4809 to_string = _eina_model_type_find_offset
4810 (type, offsetof(Eina_Model_Type, to_string));
4811 EINA_SAFETY_ON_NULL_RETURN_VAL(to_string, NULL);
4812
4813 return to_string(model);
4814}
4815
4816EAPI Eina_Bool
4817eina_model_type_subclass_setup(Eina_Model_Type *type, const Eina_Model_Type *parent)
4818{
4819 EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE);
4820 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, EINA_FALSE);
4821 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(parent), EINA_FALSE);
4822 EINA_SAFETY_ON_FALSE_RETURN_VAL(type->version == EINA_MODEL_TYPE_VERSION,
4823 EINA_FALSE);
4824
4825 type->parent = parent;
4826 type->type_size = parent->type_size;
4827 type->interfaces = NULL;
4828 type->events = NULL;
4829
4830 type->setup = NULL;
4831 type->flush = NULL;
4832 type->constructor = NULL;
4833 type->destructor = NULL;
4834 type->copy = NULL;
4835 type->deep_copy = NULL;
4836 type->compare = NULL;
4837 type->load = NULL;
4838 type->unload = NULL;
4839 type->property_get = NULL;
4840 type->property_set = NULL;
4841 type->property_del = NULL;
4842 type->properties_names_list_get = NULL;
4843 type->child_count = NULL;
4844 type->child_get = NULL;
4845 type->child_set = NULL;
4846 type->child_del = NULL;
4847 type->child_insert_at = NULL;
4848 type->child_find = NULL;
4849 type->child_criteria_match = NULL;
4850 type->child_sort = NULL;
4851 type->child_iterator_get = NULL;
4852 type->child_reversed_iterator_get = NULL;
4853 type->child_sorted_iterator_get = NULL;
4854 type->child_filtered_iterator_get = NULL;
4855 type->to_string = NULL;
4856 type->__extension_ptr0 = NULL;
4857 type->__extension_ptr1 = NULL;
4858 type->__extension_ptr2 = NULL;
4859 type->__extension_ptr3 = NULL;
4860
4861 if (type->type_size > sizeof(Eina_Model_Type))
4862 {
4863 unsigned char *p = (unsigned char *)type;
4864 p += sizeof(Eina_Model_Type);
4865 memset(p, 0, type->type_size - sizeof(Eina_Model_Type));
4866 }
4867
4868 return EINA_TRUE;
4869}
4870
4871EAPI Eina_Bool
4872eina_model_type_subclass_check(const Eina_Model_Type *type, const Eina_Model_Type *self_or_parent)
4873{
4874 EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE);
4875 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), EINA_FALSE);
4876 EINA_SAFETY_ON_NULL_RETURN_VAL(self_or_parent, EINA_FALSE);
4877
4878 for (; type != NULL; type = type->parent)
4879 {
4880 if (type == self_or_parent)
4881 return EINA_TRUE;
4882 }
4883
4884 return EINA_FALSE;
4885}
4886
4887static inline const Eina_Model_Interface *
4888_eina_model_type_interface_get(const Eina_Model_Type *type, const char *name, Eina_Bool ptr_cmp __UNUSED__)
4889{
4890 const Eina_Model_Interface **itr;
4891
4892 if (!type)
4893 return NULL;
4894
4895 if (!type->interfaces)
4896 return _eina_model_type_interface_get(type->parent, name, ptr_cmp);
4897
4898 {
4899 for (itr = type->interfaces ; itr != NULL ; itr++)
4900 if (strcmp((*itr)->name, name) == 0)
4901 return *itr;
4902 }
4903
4904 return NULL;
4905}
4906
4907static inline Eina_Bool
4908_eina_model_interface_check(const Eina_Model_Interface *iface)
4909{
4910 EINA_SAFETY_ON_FALSE_RETURN_VAL
4911 (iface->version == EINA_MODEL_INTERFACE_VERSION, EINA_FALSE);
4912 return EINA_TRUE;
4913}
4914
4915EAPI const Eina_Model_Interface *
4916eina_model_type_interface_get(const Eina_Model_Type *type, const char *name)
4917{
4918 const Eina_Model_Interface *iface;
4919
4920 EINA_SAFETY_ON_NULL_RETURN_VAL(type, NULL);
4921 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), NULL);
4922
4923 /* search for pointer, make speed-aware users fast */
4924 iface = _eina_model_type_interface_get(type, name, EINA_TRUE);
4925
4926 if (!iface)
4927 {
4928 /* search using strcmp(), slow users don't care */
4929 iface = _eina_model_type_interface_get(type, name, EINA_FALSE);
4930 }
4931 else if (!_eina_model_interface_check(iface))
4932 iface = NULL;
4933
4934 return iface;
4935}
4936
4937EAPI void *
4938eina_model_type_private_data_get(const Eina_Model *model, const Eina_Model_Type *type)
4939{
4940 const Eina_Model_Description *desc;
4941 unsigned int i;
4942
4943 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4944 EINA_SAFETY_ON_NULL_RETURN_VAL(type, NULL);
4945 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), NULL);
4946
4947 desc = model->desc;
4948
4949 for (i = 0; i < desc->total.types; i++)
4950 if (desc->cache.types[i] == type)
4951 return model->privates[i];
4952
4953 CRITICAL("Model %p (%s) is not an instance of type %p (%s)",
4954 model, desc->cache.types[0]->name,
4955 type, type->name);
4956 return NULL;
4957}
4958
4959EAPI const void *
4960eina_model_method_offset_resolve(const Eina_Model *model, unsigned int offset)
4961{
4962 const Eina_Model_Description *desc;
4963
4964 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
4965 EINA_SAFETY_ON_FALSE_RETURN_VAL(offset >= sizeof(Eina_Model_Type), NULL);
4966 EINA_SAFETY_ON_FALSE_RETURN_VAL(offset % sizeof(void *) == 0, NULL);
4967
4968 desc = model->desc;
4969 EINA_SAFETY_ON_FALSE_RETURN_VAL
4970 (offset + sizeof(void *) <= desc->cache.types[0]->type_size, NULL);
4971
4972 offset -= sizeof(Eina_Model_Type);
4973 offset /= sizeof(void *);
4974 return desc->ops.type.extension[offset];
4975}
4976
4977EAPI const void *
4978eina_model_type_method_offset_resolve(const Eina_Model_Type *type, const Eina_Model *model, unsigned int offset)
4979{
4980 const Eina_Model_Description *desc;
4981
4982 EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL);
4983 EINA_SAFETY_ON_FALSE_RETURN_VAL(offset >= sizeof(Eina_Model_Type), NULL);
4984 EINA_SAFETY_ON_FALSE_RETURN_VAL(offset % sizeof(void *) == 0, NULL);
4985
4986 desc = model->desc;
4987 EINA_SAFETY_ON_FALSE_RETURN_VAL
4988 (offset + sizeof(void *) <= desc->cache.types[0]->type_size, NULL);
4989
4990 return _eina_model_type_find_offset(type, offset);
4991}
4992
4993/* interface functions ************************************************/
4994
4995EAPI Eina_Bool
4996eina_model_interface_check(const Eina_Model_Interface *iface)
4997{
4998 EINA_SAFETY_ON_NULL_RETURN_VAL(iface, EINA_FALSE);
4999 return _eina_model_interface_check(iface);
5000}
5001
5002EAPI void *
5003eina_model_interface_private_data_get(const Eina_Model *model, const Eina_Model_Interface *iface)
5004{
5005 const Eina_Model_Description *desc;
5006 unsigned int i;
5007
5008 EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL);
5009 EINA_SAFETY_ON_NULL_RETURN_VAL(iface, NULL);
5010 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_interface_check(iface), NULL);
5011
5012 desc = model->desc;
5013
5014 for (i = 0; i < desc->total.ifaces; i++)
5015 if (desc->cache.ifaces[i] == iface)
5016 return model->privates[desc->total.types + i];
5017
5018 CRITICAL("Model %p (%s) does not implement interface %p (%s)",
5019 model, desc->cache.types[0]->name,
5020 iface, iface->name);
5021 return NULL;
5022}
5023
5024static Eina_Bool
5025_eina_model_interface_implemented(const Eina_Model *model, const Eina_Model_Interface *iface)
5026{
5027 const Eina_Model_Interface **itr, **itr_end;
5028
5029 itr = model->desc->cache.ifaces;
5030 itr_end = itr + model->desc->total.ifaces;
5031
5032 for (; itr < itr_end; itr++)
5033 if (*itr == iface)
5034 return EINA_TRUE;
5035
5036 return EINA_FALSE;
5037}
5038
5039EAPI Eina_Bool
5040eina_model_interface_implemented(const Eina_Model *model, const Eina_Model_Interface *iface)
5041{
5042 EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE);
5043 EINA_SAFETY_ON_NULL_RETURN_VAL(iface, EINA_FALSE);
5044 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_interface_check(iface),
5045 EINA_FALSE);
5046 return _eina_model_interface_implemented(model, iface);
5047}
5048
5049#define EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK(iface, model) \
5050 EINA_SAFETY_ON_NULL_RETURN(iface); \
5051 EINA_SAFETY_ON_FALSE_RETURN(_eina_model_interface_check(iface)); \
5052 EINA_MODEL_INSTANCE_CHECK(model); \
5053 EINA_SAFETY_ON_FALSE_RETURN(_eina_model_interface_implemented(model, iface));
5054
5055#define EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, retval) \
5056 EINA_SAFETY_ON_NULL_RETURN_VAL(iface, retval); \
5057 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_interface_check(iface), retval); \
5058 EINA_MODEL_INSTANCE_CHECK_VAL(model, retval); \
5059 EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_interface_implemented(model, iface), retval);
5060
5061
5062EAPI Eina_Bool
5063eina_model_interface_constructor(const Eina_Model_Interface *iface, Eina_Model *model)
5064{
5065 Eina_Bool (*constructor)(Eina_Model *);
5066
5067 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5068
5069 constructor = _eina_model_interface_find_offset
5070 (iface, offsetof(Eina_Model_Interface, constructor));
5071 EINA_SAFETY_ON_NULL_RETURN_VAL(constructor, EINA_FALSE);
5072 return constructor(model);
5073}
5074
5075EAPI Eina_Bool
5076eina_model_interface_destructor(const Eina_Model_Interface *iface, Eina_Model *model)
5077{
5078 Eina_Bool (*destructor)(Eina_Model *);
5079
5080 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5081
5082 destructor = _eina_model_interface_find_offset
5083 (iface, offsetof(Eina_Model_Interface, destructor));
5084 EINA_SAFETY_ON_NULL_RETURN_VAL(destructor, EINA_FALSE);
5085 return destructor(model);
5086}
5087
5088EAPI Eina_Bool
5089eina_model_interface_copy(const Eina_Model_Interface *iface, const Eina_Model *src, Eina_Model *dst)
5090{
5091 Eina_Bool (*copy)(const Eina_Model *, Eina_Model *);
5092
5093 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, src, EINA_FALSE);
5094 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, dst, EINA_FALSE);
5095
5096 copy = _eina_model_interface_find_offset
5097 (iface, offsetof(Eina_Model_Interface, copy));
5098 EINA_SAFETY_ON_NULL_RETURN_VAL(copy, EINA_FALSE);
5099 return copy(src, dst);
5100}
5101
5102EAPI Eina_Bool
5103eina_model_interface_deep_copy(const Eina_Model_Interface *iface, const Eina_Model *src, Eina_Model *dst)
5104{
5105 Eina_Bool (*deep_copy)(const Eina_Model *, Eina_Model *);
5106
5107 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, src, EINA_FALSE);
5108 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, dst, EINA_FALSE);
5109
5110 deep_copy = _eina_model_interface_find_offset
5111 (iface, offsetof(Eina_Model_Interface, deep_copy));
5112 EINA_SAFETY_ON_NULL_RETURN_VAL(deep_copy, EINA_FALSE);
5113 return deep_copy(src, dst);
5114}
5115
5116EAPI const void
5117*eina_model_interface_method_offset_resolve(const Eina_Model_Interface *iface, const Eina_Model *model, unsigned int offset)
5118{
5119 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, NULL);
5120 EINA_SAFETY_ON_FALSE_RETURN_VAL(offset >= sizeof(Eina_Model_Interface), NULL);
5121 EINA_SAFETY_ON_FALSE_RETURN_VAL(offset % sizeof(void *) == 0, NULL);
5122 return _eina_model_interface_find_offset(iface, offset);
5123}
5124
5125
5126/* Eina_Model_Interface_Properties ************************************/
5127
5128EAPI Eina_Bool
5129eina_model_interface_properties_compare(const Eina_Model_Interface *iface, const Eina_Model *a, const Eina_Model *b, int *cmp)
5130{
5131 Eina_Bool (*compare)(const Eina_Model *, const Eina_Model *, int *cmp);
5132
5133 EINA_SAFETY_ON_NULL_RETURN_VAL(cmp, EINA_FALSE);
5134
5135 *cmp = 0;
5136 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, a, EINA_FALSE);
5137 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, b, EINA_FALSE);
5138
5139 compare = _eina_model_interface_find_offset
5140 (iface, offsetof(Eina_Model_Interface_Properties, compare));
5141 EINA_SAFETY_ON_NULL_RETURN_VAL(compare, EINA_FALSE);
5142 return compare(a, b, cmp);
5143}
5144
5145EAPI Eina_Bool
5146eina_model_interface_properties_load(const Eina_Model_Interface *iface, Eina_Model *model)
5147{
5148 Eina_Bool (*load)(Eina_Model *);
5149 Eina_Bool ret;
5150
5151 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5152
5153 load = _eina_model_interface_find_offset
5154 (iface, offsetof(Eina_Model_Interface_Properties, load));
5155 EINA_SAFETY_ON_NULL_RETURN_VAL(load, EINA_FALSE);
5156 ret = load(model);
5157
5158 if (ret)
5159 _eina_model_event_callback_call
5160 (model, _eina_model_str_properties_loaded, NULL);
5161
5162 return ret;
5163}
5164
5165EAPI Eina_Bool
5166eina_model_interface_properties_unload(const Eina_Model_Interface *iface, Eina_Model *model)
5167{
5168 Eina_Bool (*unload)(Eina_Model *);
5169 Eina_Bool ret;
5170
5171 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5172
5173 unload = _eina_model_interface_find_offset
5174 (iface, offsetof(Eina_Model_Interface_Properties, unload));
5175 EINA_SAFETY_ON_NULL_RETURN_VAL(unload, EINA_FALSE);
5176 ret = unload(model);
5177
5178 if (ret)
5179 _eina_model_event_callback_call
5180 (model, _eina_model_str_properties_unloaded, NULL);
5181
5182 return ret;
5183}
5184
5185EAPI Eina_Bool
5186eina_model_interface_properties_get(const Eina_Model_Interface *iface, const Eina_Model *model, const char *name, Eina_Value *value)
5187{
5188 Eina_Bool (*get)(const Eina_Model *, const char *, Eina_Value *);
5189
5190 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
5191 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
5192 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5193
5194 get = _eina_model_interface_find_offset
5195 (iface, offsetof(Eina_Model_Interface_Properties, get));
5196 EINA_SAFETY_ON_NULL_RETURN_VAL(get, EINA_FALSE);
5197 return get(model, name, value);
5198}
5199
5200EAPI Eina_Bool
5201eina_model_interface_properties_set(const Eina_Model_Interface *iface, Eina_Model *model, const char *name, const Eina_Value *value)
5202{
5203 Eina_Bool (*set)(Eina_Model *, const char *, const Eina_Value *);
5204
5205 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
5206 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
5207 EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), EINA_FALSE);
5208 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5209
5210 set = _eina_model_interface_find_offset
5211 (iface, offsetof(Eina_Model_Interface_Properties, set));
5212 EINA_SAFETY_ON_NULL_RETURN_VAL(set, EINA_FALSE);
5213 return set(model, name, value);
5214}
5215
5216EAPI Eina_Bool
5217eina_model_interface_properties_del(const Eina_Model_Interface *iface, Eina_Model *model, const char *name)
5218{
5219 Eina_Bool (*del)(Eina_Model *, const char *);
5220
5221 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
5222 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5223
5224 del = _eina_model_interface_find_offset
5225 (iface, offsetof(Eina_Model_Interface_Properties, del));
5226 EINA_SAFETY_ON_NULL_RETURN_VAL(del, EINA_FALSE);
5227 return del(model, name);
5228}
5229
5230EAPI Eina_List *
5231eina_model_interface_properties_names_list_get(const Eina_Model_Interface *iface, const Eina_Model *model)
5232{
5233 Eina_List *(*names_list_get)(const Eina_Model *);
5234
5235 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, NULL);
5236
5237 names_list_get = _eina_model_interface_find_offset
5238 (iface, offsetof(Eina_Model_Interface_Properties, names_list_get));
5239 EINA_SAFETY_ON_NULL_RETURN_VAL(names_list_get, NULL);
5240 return names_list_get(model);
5241}
5242
5243/* Eina_Model_Interface_Children **************************************/
5244
5245EAPI Eina_Bool
5246eina_model_interface_children_compare(const Eina_Model_Interface *iface, const Eina_Model *a, const Eina_Model *b, int *cmp)
5247{
5248 Eina_Bool (*compare)(const Eina_Model *, const Eina_Model *, int *);
5249
5250 EINA_SAFETY_ON_NULL_RETURN_VAL(cmp, EINA_FALSE);
5251
5252 *cmp = 0;
5253
5254 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, a, EINA_FALSE);
5255 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, b, EINA_FALSE);
5256
5257 compare = _eina_model_interface_find_offset
5258 (iface, offsetof(Eina_Model_Interface_Children, compare));
5259 EINA_SAFETY_ON_NULL_RETURN_VAL(compare, EINA_FALSE);
5260 return compare(a, b, cmp);
5261}
5262
5263EAPI Eina_Bool
5264eina_model_interface_children_load(const Eina_Model_Interface *iface, Eina_Model *model)
5265{
5266 Eina_Bool (*load)(Eina_Model *);
5267 Eina_Bool ret;
5268
5269 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5270
5271 load = _eina_model_interface_find_offset
5272 (iface, offsetof(Eina_Model_Interface_Children, load));
5273 EINA_SAFETY_ON_NULL_RETURN_VAL(load, EINA_FALSE);
5274 ret = load(model);
5275
5276 if (ret)
5277 _eina_model_event_callback_call
5278 (model, _eina_model_str_children_loaded, NULL);
5279
5280 return ret;
5281}
5282
5283EAPI Eina_Bool
5284eina_model_interface_children_unload(const Eina_Model_Interface *iface, Eina_Model *model)
5285{
5286 Eina_Bool (*unload)(Eina_Model *);
5287 Eina_Bool ret;
5288
5289 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5290
5291 unload = _eina_model_interface_find_offset
5292 (iface, offsetof(Eina_Model_Interface_Children, unload));
5293 EINA_SAFETY_ON_NULL_RETURN_VAL(unload, EINA_FALSE);
5294 ret = unload(model);
5295
5296 if (ret)
5297 _eina_model_event_callback_call
5298 (model, _eina_model_str_children_unloaded, NULL);
5299
5300 return ret;
5301}
5302
5303EAPI int
5304eina_model_interface_children_count(const Eina_Model_Interface *iface, const Eina_Model *model)
5305{
5306 int (*count)(const Eina_Model *);
5307
5308 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, -1);
5309
5310 count = _eina_model_interface_find_offset
5311 (iface, offsetof(Eina_Model_Interface_Children, count));
5312 EINA_SAFETY_ON_NULL_RETURN_VAL(count, -1);
5313 return count(model);
5314}
5315
5316EAPI Eina_Model *
5317eina_model_interface_children_get(const Eina_Model_Interface *iface, const Eina_Model *model, unsigned int position)
5318{
5319 Eina_Model *(*get)(const Eina_Model *, unsigned int);
5320
5321 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, NULL);
5322
5323 get = _eina_model_interface_find_offset
5324 (iface, offsetof(Eina_Model_Interface_Children, get));
5325 EINA_SAFETY_ON_NULL_RETURN_VAL(get, NULL);
5326 return get(model, position);
5327}
5328
5329EAPI Eina_Bool eina_model_interface_children_set(const Eina_Model_Interface *iface, Eina_Model *model, unsigned int position, Eina_Model *child)
5330{
5331 Eina_Bool (*set)(const Eina_Model *, unsigned int, Eina_Model *);
5332
5333 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5334 EINA_MODEL_INSTANCE_CHECK_VAL(child, EINA_FALSE);
5335
5336 set = _eina_model_interface_find_offset
5337 (iface, offsetof(Eina_Model_Interface_Children, set));
5338 EINA_SAFETY_ON_NULL_RETURN_VAL(set, EINA_FALSE);
5339 return set(model, position, child);
5340}
5341
5342EAPI Eina_Bool
5343eina_model_interface_children_del(const Eina_Model_Interface *iface, Eina_Model *model, unsigned int position)
5344{
5345 Eina_Bool (*del)(Eina_Model *, unsigned int);
5346
5347 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5348
5349 del = _eina_model_interface_find_offset
5350 (iface, offsetof(Eina_Model_Interface_Children, del));
5351 EINA_SAFETY_ON_NULL_RETURN_VAL(del, EINA_FALSE);
5352 return del(model, position);
5353}
5354
5355
5356EAPI Eina_Bool
5357eina_model_interface_children_insert_at(const Eina_Model_Interface *iface, Eina_Model *model, unsigned int position, Eina_Model *child)
5358{
5359 Eina_Bool (*insert_at)(const Eina_Model *, unsigned int, Eina_Model *);
5360
5361 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE);
5362 EINA_MODEL_INSTANCE_CHECK_VAL(child, EINA_FALSE);
5363
5364 insert_at = _eina_model_interface_find_offset
5365 (iface, offsetof(Eina_Model_Interface_Children, insert_at));
5366 EINA_SAFETY_ON_NULL_RETURN_VAL(insert_at, EINA_FALSE);
5367 return insert_at(model, position, child);
5368}
5369
5370EAPI void
5371eina_model_interface_children_sort(const Eina_Model_Interface *iface, Eina_Model *model, Eina_Compare_Cb compare)
5372{
5373 void (*sort)(const Eina_Model *, Eina_Compare_Cb);
5374
5375 EINA_SAFETY_ON_NULL_RETURN(compare);
5376 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK(iface, model);
5377
5378 sort = _eina_model_interface_find_offset
5379 (iface, offsetof(Eina_Model_Interface_Children, sort));
5380 EINA_SAFETY_ON_NULL_RETURN(sort);
5381 return sort(model, compare);
5382}
5383
5384static Eina_Bool
5385_eina_model_struct_set(Eina_Model *m, const Eina_Value_Struct_Desc *desc, void *memory)
5386{
5387 Eina_Value_Struct st = {desc, memory};
5388 Eina_Value *val = eina_model_interface_private_data_get
5389 (m, &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base);
5390 return eina_value_pset(val, &st);
5391}
5392
5393EAPI Eina_Model *
5394eina_model_struct_new(const Eina_Value_Struct_Desc *desc)
5395{
5396 Eina_Model *m;
5397
5398 EINA_SAFETY_ON_NULL_RETURN_VAL(desc, NULL);
5399 EINA_SAFETY_ON_FALSE_RETURN_VAL
5400 (desc->version == EINA_VALUE_STRUCT_DESC_VERSION, NULL);
5401
5402 m = eina_model_new(EINA_MODEL_TYPE_STRUCT);
5403 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
5404
5405 EINA_SAFETY_ON_FALSE_GOTO(_eina_model_struct_set(m, desc, NULL), error);
5406 return m;
5407
5408 error:
5409 eina_model_del(m);
5410 return NULL;
5411}
5412
5413EAPI Eina_Model *
5414eina_model_type_struct_new(const Eina_Model_Type *type, const Eina_Value_Struct_Desc *desc)
5415{
5416 Eina_Model *m;
5417
5418 EINA_SAFETY_ON_FALSE_RETURN_VAL
5419 (eina_model_type_subclass_check(type, EINA_MODEL_TYPE_STRUCT), NULL);
5420 EINA_SAFETY_ON_NULL_RETURN_VAL(desc, NULL);
5421 EINA_SAFETY_ON_FALSE_RETURN_VAL
5422 (desc->version == EINA_VALUE_STRUCT_DESC_VERSION, NULL);
5423
5424 m = eina_model_new(type);
5425 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
5426
5427 EINA_SAFETY_ON_FALSE_GOTO(_eina_model_struct_set(m, desc, NULL), error);
5428 return m;
5429
5430 error:
5431 eina_model_del(m);
5432 return NULL;
5433}
5434
5435EAPI Eina_Bool
5436eina_model_struct_set(Eina_Model *model, const Eina_Value_Struct_Desc *desc, void *memory)
5437{
5438 EINA_SAFETY_ON_NULL_RETURN_VAL(desc, EINA_FALSE);
5439 EINA_SAFETY_ON_FALSE_RETURN_VAL
5440 (desc->version == EINA_VALUE_STRUCT_DESC_VERSION, EINA_FALSE);
5441 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL
5442 (&_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base, model, EINA_FALSE);
5443
5444 return _eina_model_struct_set(model, desc, memory);
5445}
5446
5447EAPI Eina_Bool
5448eina_model_struct_get(const Eina_Model *model, const Eina_Value_Struct_Desc **p_desc, void **p_memory)
5449{
5450 const Eina_Value *val;
5451 Eina_Value_Struct st;
5452
5453 EINA_SAFETY_ON_NULL_RETURN_VAL(p_desc, EINA_FALSE);
5454
5455 *p_desc = NULL;
5456 if (p_memory) *p_memory = NULL;
5457
5458 EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL
5459 (&_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base, model, EINA_FALSE);
5460
5461 val = eina_model_interface_private_data_get
5462 (model, &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base);
5463
5464 EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_pget(val, &st), EINA_FALSE);
5465
5466 *p_desc = st.desc;
5467 if (p_memory) *p_memory = st.memory;
5468 return EINA_FALSE;
5469}
5470
5471EAPI void
5472eina_models_usage_dump(void)
5473{
5474 const Eina_List *l;
5475 const Eina_Model *m;
5476
5477 eina_lock_take(&_eina_model_debug_list_lock);
5478
5479 puts("DDD: model refs info (type, holders, backtrace)");
5480 puts("DDD: -------------- -------------- ---------------------------------");
5481
5482 EINA_LIST_FOREACH(_eina_model_debug_list, l, m)
5483 {
5484 Eina_Model_XRef *ref;
5485
5486 printf("DDD: %14p %14d %s\n",
5487 m, m->refcount, m->desc->cache.types[0]->name);
5488
5489 EINA_INLIST_FOREACH(m->xrefs, ref)
5490 {
5491 printf("DDD: id: %p '%s'\n",
5492 ref->id, ref->label);
5493 if (ref->backtrace.count)
5494 {
5495 char **symbols;
5496 unsigned int i;
5497
5498#ifdef HAVE_BACKTRACE_SYMBOLS
5499 symbols = backtrace_symbols((void * const *)ref->backtrace.symbols,
5500 ref->backtrace.count);
5501#else
5502 symbols = NULL;
5503#endif
5504
5505 printf("DDD: Backtrace: Address Symbol\n");
5506 for (i = 0; i < ref->backtrace.count; i++)
5507 printf("DDD: %14p %s\n",
5508 ref->backtrace.symbols[i],
5509 symbols ? symbols[i] : "???");
5510
5511 free(symbols);
5512 puts("DDD:");
5513 }
5514 }
5515 }
5516
5517 eina_lock_release(&_eina_model_debug_list_lock);
5518}
5519
5520EAPI Eina_List *
5521eina_models_list_get(void)
5522{
5523 const Eina_List *l;
5524 Eina_Model *m;
5525 Eina_List *ret = NULL;
5526
5527 eina_lock_take(&_eina_model_debug_list_lock);
5528
5529 EINA_LIST_FOREACH(_eina_model_debug_list, l, m)
5530 {
5531 ret = eina_list_append
5532 (ret, eina_model_xref
5533 (m, eina_models_list_get, "eina_models_list_get"));
5534 }
5535
5536 eina_lock_release(&_eina_model_debug_list_lock);
5537
5538 return ret;
5539}
5540
5541EAPI void
5542eina_models_list_free(Eina_List *list)
5543{
5544 Eina_Model *m;
5545
5546 EINA_LIST_FREE(list, m)
5547 eina_model_xunref(m, eina_models_list_get);
5548}
diff --git a/libraries/eina/src/tests/eina_test_model.c b/libraries/eina/src/tests/eina_test_model.c
new file mode 100644
index 0000000..54a2258
--- /dev/null
+++ b/libraries/eina/src/tests/eina_test_model.c
@@ -0,0 +1,1288 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2012 ProFUSION embedded systems
3 *
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.
8 *
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.
13 *
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/>.
17 */
18
19#ifdef HAVE_CONFIG_H
20# include "config.h"
21#endif
22
23#include <stdio.h>
24#include <inttypes.h>
25
26#include "eina_suite.h"
27#include "Eina.h"
28
29static void
30_eina_test_model_check_safety_null(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args)
31{
32 Eina_Bool *ck = data;
33
34 if ((level == EINA_LOG_LEVEL_ERR) && (strcmp(fmt, "%s") == 0))
35 {
36 const char *str;
37 va_list cp_args;
38
39 va_copy(cp_args, args);
40 str = va_arg(cp_args, const char *);
41 va_end(cp_args);
42 if (eina_str_has_prefix(str, "safety check failed: ") &&
43 eina_str_has_suffix(str, " == NULL"))
44 {
45 *ck = EINA_TRUE;
46 return;
47 }
48 }
49 *ck = EINA_FALSE;
50 eina_log_print_cb_stderr(d, level, file, fnc, line, fmt, NULL, args);
51}
52
53static void
54_eina_test_model_check_safety_false(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args)
55{
56 Eina_Bool *ck = data;
57
58 if ((level == EINA_LOG_LEVEL_ERR) && (strcmp(fmt, "%s") == 0))
59 {
60 const char *str;
61 va_list cp_args;
62
63 va_copy(cp_args, args);
64 str = va_arg(cp_args, const char *);
65 va_end(cp_args);
66 if (eina_str_has_prefix(str, "safety check failed: ") &&
67 eina_str_has_suffix(str, " is false"))
68 {
69 *ck = EINA_TRUE;
70 return;
71 }
72 }
73 *ck = EINA_FALSE;
74 eina_log_print_cb_stderr(d, level, file, fnc, line, fmt, NULL, args);
75}
76
77static void
78_eina_test_model_cb_count(void *data, Eina_Model *model, const Eina_Model_Event_Description *desc, void *event_info)
79{
80 unsigned *count = data;
81 (*count)++;
82#if SHOW_LOG
83 if ((desc->type) && (strcmp(desc->type, "u") == 0))
84 {
85 unsigned *pos = event_info;
86 printf("%2u %p %s at %u\n", *count, model, desc->name, *pos);
87 }
88 else
89 printf("%2u %p %s\n", *count, model, desc->name);
90#else
91 (void)model;
92 (void)desc;
93 (void)event_info;
94#endif
95}
96
97START_TEST(eina_model_test_properties)
98{
99 unsigned int count_del = 0, count_pset = 0, count_pdel = 0;
100 Eina_Model *m;
101 Eina_Value inv, outv;
102 int i;
103 char *s;
104 Eina_List *lst;
105 Eina_Bool ck;
106
107 eina_init();
108
109 m = eina_model_new(EINA_MODEL_TYPE_GENERIC);
110 fail_unless(m != NULL);
111
112 eina_model_event_callback_add
113 (m, "deleted", _eina_test_model_cb_count, &count_del);
114 eina_model_event_callback_add
115 (m, "property,set", _eina_test_model_cb_count, &count_pset);
116 eina_model_event_callback_add
117 (m, "property,deleted", _eina_test_model_cb_count, &count_pdel);
118
119 fail_unless(eina_value_setup(&inv, EINA_VALUE_TYPE_INT));
120 fail_unless(eina_value_set(&inv, 1234));
121 fail_unless(eina_value_get(&inv, &i));
122 ck_assert_int_eq(i, 1234);
123
124 fail_unless(eina_model_property_set(m, "abc", &inv));
125
126 fail_unless(eina_value_set(&inv, 5678));
127 fail_unless(eina_model_property_set(m, "xyz", &inv));
128
129 fail_unless(eina_value_set(&inv, 171));
130 fail_unless(eina_model_property_set(m, "value", &inv));
131
132 lst = eina_model_properties_names_list_get(m);
133 ck_assert_int_eq(eina_list_count(lst), 3);
134
135 lst = eina_list_sort(lst, 0, EINA_COMPARE_CB(strcmp));
136 ck_assert_str_eq("abc", eina_list_nth(lst, 0));
137 ck_assert_str_eq("value", eina_list_nth(lst, 1));
138 ck_assert_str_eq("xyz", eina_list_nth(lst, 2));
139
140 eina_model_properties_names_list_free(lst);
141
142 fail_unless(eina_model_property_get(m, "abc", &outv));
143 fail_unless(eina_value_get(&outv, &i));
144 ck_assert_int_eq(i, 1234);
145 eina_value_flush(&outv);
146
147 fail_unless(eina_model_property_get(m, "xyz", &outv));
148 fail_unless(eina_value_get(&outv, &i));
149 ck_assert_int_eq(i, 5678);
150 eina_value_flush(&outv);
151
152 fail_unless(eina_model_property_get(m, "value", &outv));
153 fail_unless(eina_value_get(&outv, &i));
154 ck_assert_int_eq(i, 171);
155 eina_value_flush(&outv);
156
157 fail_unless(eina_value_set(&inv, 666));
158 fail_unless(eina_model_property_set(m, "value", &inv));
159 fail_unless(eina_model_property_get(m, "value", &outv));
160 fail_unless(eina_value_get(&outv, &i));
161 ck_assert_int_eq(i, 666);
162
163 eina_value_flush(&outv);
164 eina_value_flush(&inv);
165
166 fail_unless(eina_value_setup(&inv, EINA_VALUE_TYPE_STRING));
167 fail_unless(eina_value_set(&inv, "Hello world!"));
168 fail_unless(eina_model_property_set(m, "string", &inv));
169
170 fail_unless(eina_model_property_get(m, "string", &outv));
171 fail_unless(eina_value_get(&outv, &s));
172 fail_unless(s != NULL);
173 ck_assert_str_eq(s, "Hello world!");
174
175 eina_value_flush(&outv);
176 eina_value_flush(&inv);
177
178 fail_unless(eina_value_setup(&inv, EINA_VALUE_TYPE_STRINGSHARE));
179 fail_unless(eina_value_set(&inv, "Hello world-STRINGSHARED!"));
180 fail_unless(eina_model_property_set(m, "stringshare", &inv));
181 /* set twice to see if references drop to zero before new add, shouldn't */
182 fail_unless(eina_model_property_set(m, "stringshare", &inv));
183
184 fail_unless(eina_model_property_get(m, "stringshare", &outv));
185 fail_unless(eina_value_get(&outv, &s));
186 fail_unless(s != NULL);
187 ck_assert_str_eq(s, "Hello world-STRINGSHARED!");
188
189 eina_value_flush(&outv);
190 eina_value_flush(&inv);
191
192 s = eina_model_to_string(m);
193 fail_unless(s != NULL);
194 ck_assert_str_eq(s, "Eina_Model_Type_Generic({abc: 1234, string: Hello world!, stringshare: Hello world-STRINGSHARED!, value: 666, xyz: 5678}, [])");
195 free(s);
196
197 fail_unless(eina_model_property_del(m, "value"));
198
199 /* negative test (check safety was displayed by using print_cb) */
200 eina_log_print_cb_set(_eina_test_model_check_safety_null, &ck);
201
202 ck = EINA_FALSE;
203 fail_if(eina_model_property_get(m, "non-existent", &outv));
204 fail_unless(ck == EINA_TRUE);
205
206 ck = EINA_FALSE;
207 fail_if(eina_model_property_get(m, NULL, &outv));
208 fail_unless(ck == EINA_TRUE);
209
210 ck = EINA_FALSE;
211 fail_if(eina_model_property_del(m, "value"));
212 fail_unless(ck == EINA_TRUE);
213
214 /* revert print_cb to default */
215 eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
216
217 ck_assert_int_eq(eina_model_refcount(m), 1);
218
219 eina_model_unref(m);
220 ck_assert_int_eq(count_del, 1);
221 ck_assert_int_eq(count_pset, 7);
222 ck_assert_int_eq(count_pdel, 1);
223 eina_shutdown();
224}
225END_TEST
226
227static int
228eina_model_test_children_reverse_cmp(const Eina_Model *a, const Eina_Model *b)
229{
230 return - eina_model_compare(a, b);
231}
232
233START_TEST(eina_model_test_children)
234{
235 unsigned int count_del = 0, count_cset = 0, count_cins = 0, count_cdel = 0;
236 Eina_Model *m, *c;
237 char *s;
238 int i;
239
240 eina_init();
241
242 m = eina_model_new(EINA_MODEL_TYPE_GENERIC);
243 fail_unless(m != NULL);
244
245 eina_model_event_callback_add
246 (m, "deleted", _eina_test_model_cb_count, &count_del);
247 eina_model_event_callback_add
248 (m, "child,set", _eina_test_model_cb_count, &count_cset);
249 eina_model_event_callback_add
250 (m, "child,inserted", _eina_test_model_cb_count, &count_cins);
251 eina_model_event_callback_add
252 (m, "child,deleted", _eina_test_model_cb_count, &count_cdel);
253
254 for (i = 0; i < 10; i++)
255 {
256 Eina_Value val;
257
258 c = eina_model_new(EINA_MODEL_TYPE_GENERIC);
259 fail_unless(c != NULL);
260
261 eina_model_event_callback_add
262 (c, "deleted", _eina_test_model_cb_count, &count_del);
263 eina_model_event_callback_add
264 (c, "child,set", _eina_test_model_cb_count, &count_cset);
265 eina_model_event_callback_add
266 (c, "child,inserted", _eina_test_model_cb_count, &count_cins);
267 eina_model_event_callback_add
268 (c, "child,deleted", _eina_test_model_cb_count, &count_cdel);
269
270 fail_unless(eina_value_setup(&val, EINA_VALUE_TYPE_INT));
271 fail_unless(eina_value_set(&val, i));
272 fail_unless(eina_model_property_set(c, "value", &val));
273
274 fail_unless(eina_model_child_append(m, c) >= 0);
275 ck_assert_int_eq(eina_model_refcount(c), 2);
276
277 eina_value_flush(&val);
278 eina_model_unref(c);
279 }
280
281 ck_assert_int_eq(eina_model_child_count(m), 10);
282
283 for (i = 0; i < 10; i++)
284 {
285 Eina_Value val;
286 int x;
287
288 c = eina_model_child_get(m, i);
289 fail_unless(c != NULL);
290 ck_assert_int_eq(eina_model_refcount(c), 2);
291
292 fail_unless(eina_model_property_get(c, "value", &val));
293 fail_unless(eina_value_get(&val, &x));
294 ck_assert_int_eq(x, i);
295
296 eina_value_flush(&val);
297 eina_model_unref(c);
298 }
299
300 eina_model_child_sort(m, EINA_COMPARE_CB(eina_model_test_children_reverse_cmp));
301
302 for (i = 0; i < 10; i++)
303 {
304 Eina_Value val;
305 int x;
306
307 c = eina_model_child_get(m, i);
308 fail_unless(c != NULL);
309 ck_assert_int_eq(eina_model_refcount(c), 2);
310
311 fail_unless(eina_model_property_get(c, "value", &val));
312 fail_unless(eina_value_get(&val, &x));
313 ck_assert_int_eq(x, 10 - i - 1);
314
315 eina_value_flush(&val);
316 eina_model_unref(c);
317 }
318
319 eina_model_child_sort(m, EINA_COMPARE_CB(eina_model_compare));
320
321 s = eina_model_to_string(m);
322 fail_unless(s != NULL);
323 ck_assert_str_eq(s, "Eina_Model_Type_Generic({}, [Eina_Model_Type_Generic({value: 0}, []), Eina_Model_Type_Generic({value: 1}, []), Eina_Model_Type_Generic({value: 2}, []), Eina_Model_Type_Generic({value: 3}, []), Eina_Model_Type_Generic({value: 4}, []), Eina_Model_Type_Generic({value: 5}, []), Eina_Model_Type_Generic({value: 6}, []), Eina_Model_Type_Generic({value: 7}, []), Eina_Model_Type_Generic({value: 8}, []), Eina_Model_Type_Generic({value: 9}, [])])");
324 free(s);
325
326 c = eina_model_child_get(m, 0);
327 eina_model_child_set(m, 1, c);
328 eina_model_unref(c);
329
330 eina_model_child_del(m, 0);
331 eina_model_child_del(m, 8);
332
333 s = eina_model_to_string(m);
334 fail_unless(s != NULL);
335 ck_assert_str_eq(s, "Eina_Model_Type_Generic({}, [Eina_Model_Type_Generic({value: 0}, []), Eina_Model_Type_Generic({value: 2}, []), Eina_Model_Type_Generic({value: 3}, []), Eina_Model_Type_Generic({value: 4}, []), Eina_Model_Type_Generic({value: 5}, []), Eina_Model_Type_Generic({value: 6}, []), Eina_Model_Type_Generic({value: 7}, []), Eina_Model_Type_Generic({value: 8}, [])])");
336 free(s);
337
338 ck_assert_int_eq(eina_model_refcount(m), 1);
339 eina_model_unref(m);
340
341 ck_assert_int_eq(count_del, 11);
342 ck_assert_int_eq(count_cins, 10);
343 ck_assert_int_eq(count_cset, 1);
344 ck_assert_int_eq(count_cdel, 2);
345
346 eina_shutdown();
347}
348END_TEST
349
350START_TEST(eina_model_test_copy)
351{
352 unsigned int count_del = 0;
353 Eina_Model *m, *cp;
354 char *s1, *s2;
355 int i;
356
357 eina_init();
358
359 m = eina_model_new(EINA_MODEL_TYPE_GENERIC);
360 fail_unless(m != NULL);
361
362 eina_model_event_callback_add
363 (m, "deleted", _eina_test_model_cb_count, &count_del);
364
365 for (i = 0; i < 5; i++)
366 {
367 Eina_Value val;
368 char name[2] = {'a'+ i, 0};
369 fail_unless(eina_value_setup(&val, EINA_VALUE_TYPE_INT));
370 fail_unless(eina_value_set(&val, i));
371 fail_unless(eina_model_property_set(m, name, &val));
372 eina_value_flush(&val);
373 }
374
375 for (i = 0; i < 5; i++)
376 {
377 Eina_Value val;
378 Eina_Model *c = eina_model_new(EINA_MODEL_TYPE_GENERIC);
379 fail_unless(c != NULL);
380 fail_unless(eina_value_setup(&val, EINA_VALUE_TYPE_INT));
381 fail_unless(eina_value_set(&val, i));
382 fail_unless(eina_model_property_set(c, "x", &val));
383
384 eina_model_event_callback_add
385 (c, "deleted", _eina_test_model_cb_count, &count_del);
386
387 fail_unless(eina_model_child_append(m, c) >= 0);
388 eina_model_unref(c);
389 eina_value_flush(&val);
390 }
391
392 s1 = eina_model_to_string(m);
393 fail_unless(s1 != NULL);
394 ck_assert_str_eq(s1, "Eina_Model_Type_Generic({a: 0, b: 1, c: 2, d: 3, e: 4}, [Eina_Model_Type_Generic({x: 0}, []), Eina_Model_Type_Generic({x: 1}, []), Eina_Model_Type_Generic({x: 2}, []), Eina_Model_Type_Generic({x: 3}, []), Eina_Model_Type_Generic({x: 4}, [])])");
395
396 cp = eina_model_copy(m);
397 fail_unless(cp != NULL);
398 fail_unless(cp != m);
399
400 eina_model_event_callback_add
401 (cp, "deleted", _eina_test_model_cb_count, &count_del);
402
403 s2 = eina_model_to_string(cp);
404 fail_unless(s2 != NULL);
405 ck_assert_str_eq(s1, s2);
406
407 for (i = 0; i < 5; i++)
408 {
409 Eina_Model *c1 = eina_model_child_get(m, i);
410 Eina_Model *c2 = eina_model_child_get(cp, i);
411
412 fail_unless(c1 != NULL);
413 fail_unless(c1 == c2);
414 ck_assert_int_eq(eina_model_refcount(c1), 4);
415
416 eina_model_unref(c1);
417 eina_model_unref(c2);
418 }
419
420 free(s1);
421 free(s2);
422
423 ck_assert_int_eq(eina_model_refcount(m), 1);
424 eina_model_unref(m);
425
426 ck_assert_int_eq(eina_model_refcount(cp), 1);
427 eina_model_unref(cp);
428
429 ck_assert_int_eq(count_del, 2 + 5);
430
431 eina_shutdown();
432}
433END_TEST
434
435START_TEST(eina_model_test_deep_copy)
436{
437 unsigned int count_del = 0;
438 Eina_Model *m, *cp;
439 char *s1, *s2;
440 int i;
441
442 eina_init();
443
444 m = eina_model_new(EINA_MODEL_TYPE_GENERIC);
445 fail_unless(m != NULL);
446
447 eina_model_event_callback_add
448 (m, "deleted", _eina_test_model_cb_count, &count_del);
449
450 for (i = 0; i < 5; i++)
451 {
452 Eina_Value val;
453 char name[2] = {'a'+ i, 0};
454 fail_unless(eina_value_setup(&val, EINA_VALUE_TYPE_INT));
455 fail_unless(eina_value_set(&val, i));
456 fail_unless(eina_model_property_set(m, name, &val));
457 eina_value_flush(&val);
458 }
459
460 for (i = 0; i < 5; i++)
461 {
462 Eina_Value val;
463 Eina_Model *c = eina_model_new(EINA_MODEL_TYPE_GENERIC);
464 fail_unless(c != NULL);
465 fail_unless(eina_value_setup(&val, EINA_VALUE_TYPE_INT));
466 fail_unless(eina_value_set(&val, i));
467 fail_unless(eina_model_property_set(c, "x", &val));
468
469 eina_model_event_callback_add
470 (c, "deleted", _eina_test_model_cb_count, &count_del);
471
472 fail_unless(eina_model_child_append(m, c) >= 0);
473 eina_model_unref(c);
474 eina_value_flush(&val);
475 }
476
477 s1 = eina_model_to_string(m);
478 fail_unless(s1 != NULL);
479 ck_assert_str_eq(s1, "Eina_Model_Type_Generic({a: 0, b: 1, c: 2, d: 3, e: 4}, [Eina_Model_Type_Generic({x: 0}, []), Eina_Model_Type_Generic({x: 1}, []), Eina_Model_Type_Generic({x: 2}, []), Eina_Model_Type_Generic({x: 3}, []), Eina_Model_Type_Generic({x: 4}, [])])");;
480
481 cp = eina_model_deep_copy(m);
482 fail_unless(cp != NULL);
483 fail_unless(cp != m);
484
485 eina_model_event_callback_add
486 (cp, "deleted", _eina_test_model_cb_count, &count_del);
487
488 s2 = eina_model_to_string(cp);
489 fail_unless(s2 != NULL);
490 ck_assert_str_eq(s1, s2);
491
492 for (i = 0; i < 5; i++)
493 {
494 Eina_Model *c1 = eina_model_child_get(m, i);
495 Eina_Model *c2 = eina_model_child_get(cp, i);
496
497 fail_unless(c1 != NULL);
498 fail_unless(c1 != c2);
499 ck_assert_int_eq(eina_model_refcount(c1), 2);
500 ck_assert_int_eq(eina_model_refcount(c2), 2);
501
502 eina_model_event_callback_add
503 (c2, "deleted", _eina_test_model_cb_count, &count_del);
504
505 eina_model_unref(c1);
506 eina_model_unref(c2);
507 }
508
509 free(s1);
510 free(s2);
511
512 ck_assert_int_eq(eina_model_refcount(m), 1);
513 eina_model_unref(m);
514
515 ck_assert_int_eq(eina_model_refcount(cp), 1);
516 eina_model_unref(cp);
517
518 ck_assert_int_eq(count_del, 2 + 10);
519
520 eina_shutdown();
521}
522END_TEST
523
524static Eina_Model *
525eina_model_test_iterator_setup(unsigned int *count_del)
526{
527 Eina_Model *m;
528 int i;
529
530 m = eina_model_new(EINA_MODEL_TYPE_GENERIC);
531 fail_unless(m != NULL);
532
533 eina_model_event_callback_add
534 (m, "deleted", _eina_test_model_cb_count, count_del);
535
536 for (i = 0; i < 5; i++)
537 {
538 Eina_Value val;
539 Eina_Model *c = eina_model_new(EINA_MODEL_TYPE_GENERIC);
540 fail_unless(c != NULL);
541 fail_unless(eina_value_setup(&val, EINA_VALUE_TYPE_INT));
542 fail_unless(eina_value_set(&val, i));
543 fail_unless(eina_model_property_set(c, "x", &val));
544
545 eina_model_event_callback_add
546 (c, "deleted", _eina_test_model_cb_count, count_del);
547
548 fail_unless(eina_model_child_append(m, c) >= 0);
549 eina_model_unref(c);
550 eina_value_flush(&val);
551 }
552
553 return m;
554}
555
556START_TEST(eina_model_test_child_iterator)
557{
558 unsigned int count_del = 0;
559 Eina_Iterator *it;
560 Eina_Model *m, *c;
561 int i = 0;
562
563 eina_init();
564
565 m = eina_model_test_iterator_setup(&count_del);
566
567 it = eina_model_child_iterator_get(m);
568 fail_unless(it != NULL);
569 EINA_ITERATOR_FOREACH(it, c)
570 {
571 Eina_Value tmp;
572 int x;
573
574 ck_assert_int_eq(eina_model_refcount(c), 2);
575 fail_unless(eina_model_property_get(c, "x", &tmp));
576 fail_unless(eina_value_get(&tmp, &x));
577 ck_assert_int_eq(x, i);
578
579 eina_model_unref(c);
580 i++;
581 }
582 ck_assert_int_eq(i, 5);
583 eina_iterator_free(it);
584
585 ck_assert_int_eq(eina_model_refcount(m), 1);
586 eina_model_unref(m);
587 ck_assert_int_eq(count_del, 6);
588 eina_shutdown();
589}
590END_TEST
591
592START_TEST(eina_model_test_child_reversed_iterator)
593{
594 unsigned int count_del = 0;
595 Eina_Iterator *it;
596 Eina_Model *m, *c;
597 int i = 4;
598
599 eina_init();
600
601 m = eina_model_test_iterator_setup(&count_del);
602
603 it = eina_model_child_reversed_iterator_get(m);
604 fail_unless(it != NULL);
605 EINA_ITERATOR_FOREACH(it, c)
606 {
607 Eina_Value tmp;
608 int x;
609
610 ck_assert_int_eq(eina_model_refcount(c), 2);
611 fail_unless(eina_model_property_get(c, "x", &tmp));
612 fail_unless(eina_value_get(&tmp, &x));
613 ck_assert_int_eq(x, i);
614
615 eina_model_unref(c);
616 i--;
617 }
618 ck_assert_int_eq(i, -1);
619 eina_iterator_free(it);
620
621 ck_assert_int_eq(eina_model_refcount(m), 1);
622 eina_model_unref(m);
623 ck_assert_int_eq(count_del, 6);
624 eina_shutdown();
625}
626END_TEST
627
628START_TEST(eina_model_test_child_sorted_iterator)
629{
630 unsigned int count_del = 0;
631 Eina_Iterator *it;
632 Eina_Model *m, *c;
633 int i = 4;
634
635 eina_init();
636
637 m = eina_model_test_iterator_setup(&count_del);
638
639 it = eina_model_child_sorted_iterator_get
640 (m, EINA_COMPARE_CB(eina_model_test_children_reverse_cmp));
641 fail_unless(it != NULL);
642 EINA_ITERATOR_FOREACH(it, c)
643 {
644 Eina_Value tmp;
645 int x;
646
647 /* 3 because sort takes an extra reference for its temp array */
648 ck_assert_int_eq(eina_model_refcount(c), 3);
649 fail_unless(eina_model_property_get(c, "x", &tmp));
650 fail_unless(eina_value_get(&tmp, &x));
651 ck_assert_int_eq(x, i);
652
653 eina_model_unref(c);
654 i--;
655 }
656 ck_assert_int_eq(i, -1);
657 eina_iterator_free(it);
658
659 it = eina_model_child_sorted_iterator_get
660 (m, EINA_COMPARE_CB(eina_model_compare));
661 fail_unless(it != NULL);
662 i = 0;
663 EINA_ITERATOR_FOREACH(it, c)
664 {
665 Eina_Value tmp;
666 int x;
667
668 /* 3 because sort takes an extra reference for its temp array */
669 ck_assert_int_eq(eina_model_refcount(c), 3);
670 fail_unless(eina_model_property_get(c, "x", &tmp));
671 fail_unless(eina_value_get(&tmp, &x));
672 ck_assert_int_eq(x, i);
673
674 eina_model_unref(c);
675 i++;
676 }
677 ck_assert_int_eq(i, 5);
678 eina_iterator_free(it);
679
680 ck_assert_int_eq(eina_model_refcount(m), 1);
681 eina_model_unref(m);
682 ck_assert_int_eq(count_del, 6);
683 eina_shutdown();
684}
685END_TEST
686
687static Eina_Bool
688eina_model_test_filter_event(const void *m, void *c, void *fdata)
689{
690 Eina_Value tmp;
691 int x;
692 fail_unless(m == fdata);
693 fail_unless(eina_model_property_get(c, "x", &tmp));
694 fail_unless(eina_value_get(&tmp, &x));
695 eina_value_flush(&tmp);
696 return x % 2 == 0;
697}
698
699START_TEST(eina_model_test_child_filtered_iterator)
700{
701 unsigned int count_del = 0;
702 Eina_Iterator *it;
703 Eina_Model *m;
704 int i = 0, idx;
705
706 eina_init();
707
708 m = eina_model_test_iterator_setup(&count_del);
709
710 it = eina_model_child_filtered_iterator_get
711 (m, eina_model_test_filter_event, m);
712 fail_unless(it != NULL);
713 EINA_ITERATOR_FOREACH(it, idx)
714 {
715 Eina_Model *c;
716 Eina_Value tmp;
717 int x;
718
719 ck_assert_int_eq(idx % 2, 0);
720 ck_assert_int_eq(idx, i);
721
722 c = eina_model_child_get(m, idx);
723 fail_unless(c != NULL);
724 ck_assert_int_eq(eina_model_refcount(c), 2);
725 fail_unless(eina_model_property_get(c, "x", &tmp));
726 fail_unless(eina_value_get(&tmp, &x));
727 ck_assert_int_eq(x, i);
728
729 eina_model_unref(c);
730 i += 2;
731 }
732 ck_assert_int_eq(i, 6);
733 eina_iterator_free(it);
734
735 ck_assert_int_eq(eina_model_refcount(m), 1);
736 eina_model_unref(m);
737 ck_assert_int_eq(count_del, 6);
738 eina_shutdown();
739}
740END_TEST
741
742START_TEST(eina_model_test_struct)
743{
744 unsigned int count_del = 0, count_pset = 0, count_pdel = 0;
745 Eina_Model *m;
746 struct myst {
747 int i;
748 char c;
749 };
750 const Eina_Value_Struct_Member myst_members[] = {
751 EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct myst, i),
752 EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_CHAR, struct myst, c)
753 };
754 const Eina_Value_Struct_Desc myst_desc = {
755 EINA_VALUE_STRUCT_DESC_VERSION,
756 NULL, myst_members, EINA_C_ARRAY_LENGTH(myst_members), sizeof(struct myst)
757 };
758 Eina_Value inv, outv;
759 int i;
760 char c, *s;
761 Eina_List *lst;
762 Eina_Bool ck;
763
764 eina_init();
765
766 m = eina_model_struct_new(&myst_desc);
767 fail_unless(m != NULL);
768
769 eina_model_event_callback_add
770 (m, "deleted", _eina_test_model_cb_count, &count_del);
771 eina_model_event_callback_add
772 (m, "property,set", _eina_test_model_cb_count, &count_pset);
773 eina_model_event_callback_add
774 (m, "property,deleted", _eina_test_model_cb_count, &count_pdel);
775
776 fail_unless(eina_value_setup(&inv, EINA_VALUE_TYPE_INT));
777 fail_unless(eina_value_set(&inv, 1234));
778 fail_unless(eina_value_get(&inv, &i));
779 ck_assert_int_eq(i, 1234);
780 fail_unless(eina_model_property_set(m, "i", &inv));
781
782 eina_value_flush(&inv);
783 fail_unless(eina_value_setup(&inv, EINA_VALUE_TYPE_CHAR));
784 fail_unless(eina_value_set(&inv, 33));
785 fail_unless(eina_value_get(&inv, &c));
786 ck_assert_int_eq(c, 33);
787 fail_unless(eina_model_property_set(m, "c", &inv));
788
789 lst = eina_model_properties_names_list_get(m);
790 ck_assert_int_eq(eina_list_count(lst), 2);
791
792 lst = eina_list_sort(lst, 0, EINA_COMPARE_CB(strcmp));
793 ck_assert_str_eq("c", eina_list_nth(lst, 0));
794 ck_assert_str_eq("i", eina_list_nth(lst, 1));
795
796 eina_model_properties_names_list_free(lst);
797
798 fail_unless(eina_model_property_get(m, "i", &outv));
799 fail_unless(outv.type == EINA_VALUE_TYPE_INT);
800 fail_unless(eina_value_get(&outv, &i));
801 ck_assert_int_eq(i, 1234);
802 eina_value_flush(&outv);
803
804 fail_unless(eina_model_property_get(m, "c", &outv));
805 fail_unless(outv.type == EINA_VALUE_TYPE_CHAR);
806 fail_unless(eina_value_get(&outv, &c));
807 ck_assert_int_eq(c, 33);
808 eina_value_flush(&outv);
809
810 eina_value_flush(&inv);
811
812 /* negative test (check safety was displayed by using print_cb) */
813 eina_log_print_cb_set(_eina_test_model_check_safety_null, &ck);
814
815 fail_if(eina_model_property_get(m, "non-existent", &outv));
816
817 ck = EINA_FALSE;
818 fail_if(eina_model_property_get(m, NULL, &outv));
819 fail_unless(ck == EINA_TRUE);
820
821 fail_unless(eina_value_setup(&inv, EINA_VALUE_TYPE_STRING));
822 fail_unless(eina_value_set(&inv, "hello world"));
823
824 eina_log_print_cb_set(_eina_test_model_check_safety_false, &ck);
825
826 ck = EINA_FALSE;
827 fail_if(eina_model_property_set(m, "i", &inv));
828 fail_unless(ck == EINA_TRUE);
829
830 ck = EINA_FALSE;
831 fail_if(eina_model_property_set(m, "c", &inv));
832 fail_unless(ck == EINA_TRUE);
833
834 /* revert print_cb to default */
835 eina_log_print_cb_set(eina_log_print_cb_stderr, NULL);
836
837 fail_if(eina_model_property_del(m, "value"));
838 fail_if(eina_model_property_del(m, "i"));
839 fail_if(eina_model_property_del(m, "c"));
840
841 eina_value_flush(&inv);
842
843 s = eina_model_to_string(m);
844 fail_unless(s != NULL);
845 ck_assert_str_eq(s, "Eina_Model_Type_Struct({c: 33, i: 1234}, [])");
846 free(s);
847
848 ck_assert_int_eq(eina_model_refcount(m), 1);
849
850 eina_model_unref(m);
851 ck_assert_int_eq(count_del, 1);
852 ck_assert_int_eq(count_pset, 2);
853 ck_assert_int_eq(count_pdel, 0);
854 eina_shutdown();
855}
856END_TEST
857
858static Eina_Bool
859_struct_complex_members_constructor(Eina_Model *m)
860{
861 struct myst {
862 Eina_Value_Array a;
863 Eina_Value_List l;
864 Eina_Value_Hash h;
865 Eina_Value_Struct s;
866 } st;
867 struct subst {
868 int i, j;
869 };
870 static Eina_Value_Struct_Member myst_members[] = {
871 EINA_VALUE_STRUCT_MEMBER(NULL, struct myst, a),
872 EINA_VALUE_STRUCT_MEMBER(NULL, struct myst, l),
873 EINA_VALUE_STRUCT_MEMBER(NULL, struct myst, h),
874 EINA_VALUE_STRUCT_MEMBER(NULL, struct myst, s)
875 };
876 static Eina_Value_Struct_Desc myst_desc = {
877 EINA_VALUE_STRUCT_DESC_VERSION,
878 NULL, myst_members, EINA_C_ARRAY_LENGTH(myst_members), sizeof(struct myst)
879 };
880 static Eina_Value_Struct_Member subst_members[] = {
881 EINA_VALUE_STRUCT_MEMBER(NULL, struct subst, i),
882 EINA_VALUE_STRUCT_MEMBER(NULL, struct subst, j)
883 };
884 static Eina_Value_Struct_Desc subst_desc = {
885 EINA_VALUE_STRUCT_DESC_VERSION,
886 NULL, subst_members, EINA_C_ARRAY_LENGTH(subst_members),
887 sizeof(struct subst)
888 };
889
890 if (!myst_members[0].type)
891 {
892 myst_members[0].type = EINA_VALUE_TYPE_ARRAY;
893 myst_members[1].type = EINA_VALUE_TYPE_LIST;
894 myst_members[2].type = EINA_VALUE_TYPE_HASH;
895 myst_members[3].type = EINA_VALUE_TYPE_STRUCT;
896 }
897
898 if (!subst_members[0].type)
899 {
900 subst_members[0].type = EINA_VALUE_TYPE_INT;
901 subst_members[1].type = EINA_VALUE_TYPE_INT;
902 }
903
904 if (!eina_model_type_constructor(EINA_MODEL_TYPE_STRUCT, m))
905 return EINA_FALSE;
906
907 memset(&st, 0, sizeof(st));
908
909 st.a.subtype = EINA_VALUE_TYPE_STRING;
910 st.l.subtype = EINA_VALUE_TYPE_STRING;
911 st.h.subtype = EINA_VALUE_TYPE_STRING;
912 st.s.desc = &subst_desc;
913 if (!eina_model_struct_set(m, &myst_desc, &st))
914 return EINA_FALSE;
915
916 return EINA_TRUE;
917}
918
919START_TEST(eina_model_test_struct_complex_members)
920{
921 Eina_Model *m;
922 Eina_Value outv;
923 char *s;
924 Eina_Model_Type type = EINA_MODEL_TYPE_INIT_NOPRIVATE
925 ("struct_complex_members", Eina_Model_Type, NULL, NULL, NULL);
926
927 eina_init();
928
929 type.constructor = _struct_complex_members_constructor;
930 type.parent = EINA_MODEL_TYPE_STRUCT;
931
932 m = eina_model_new(&type);
933 fail_unless(m != NULL);
934
935 fail_unless(eina_model_property_get(m, "a", &outv));
936 fail_unless(eina_value_array_append(&outv, "Hello"));
937 fail_unless(eina_value_array_append(&outv, "World"));
938 fail_unless(eina_model_property_set(m, "a", &outv));
939 eina_value_flush(&outv);
940
941 fail_unless(eina_model_property_get(m, "l", &outv));
942 fail_unless(eina_value_list_append(&outv, "Some"));
943 fail_unless(eina_value_list_append(&outv, "Thing"));
944 fail_unless(eina_model_property_set(m, "l", &outv));
945 eina_value_flush(&outv);
946
947 fail_unless(eina_model_property_get(m, "h", &outv));
948 fail_unless(eina_value_hash_set(&outv, "key", "value"));
949 fail_unless(eina_model_property_set(m, "h", &outv));
950 eina_value_flush(&outv);
951
952 fail_unless(eina_model_property_get(m, "s", &outv));
953 fail_unless(eina_value_struct_set(&outv, "i", 1234));
954 fail_unless(eina_value_struct_set(&outv, "j", 44));
955 fail_unless(eina_model_property_set(m, "s", &outv));
956 eina_value_flush(&outv);
957
958 s = eina_model_to_string(m);
959 fail_unless(s != NULL);
960 ck_assert_str_eq(s, "struct_complex_members({a: [Hello, World], h: {key: value}, l: [Some, Thing], s: {i: 1234, j: 44}}, [])");
961 free(s);
962
963 ck_assert_int_eq(eina_model_refcount(m), 1);
964
965 eina_model_unref(m);
966 eina_shutdown();
967}
968END_TEST
969
970typedef struct _Animal_Type
971{
972 Eina_Model_Type parent_class;
973 void (*eat)(Eina_Model *mdl);
974} Animal_Type;
975
976typedef struct _Human_Type
977{
978 Animal_Type parent_class;
979 void (*talk)(Eina_Model *mdl);
980} Human_Type;
981
982typedef struct _Pooper_Interface
983{
984 Eina_Model_Interface base_interface;
985 void (*poop)(Eina_Model *mdl);
986} Pooper_Interface;
987
988#define ANIMAL_TYPE(x) ((Animal_Type *) x)
989#define HUMAN_TYPE(x) ((Human_Type *) x)
990#define POOPER_IFACE(x) ((Pooper_Interface *) x)
991#define POOPER_IFACE_NAME "Pooper_Interace"
992
993#define INHER_CB_COUNT(prefix) \
994static int prefix ## _count = 0; \
995static void \
996prefix (Eina_Model *mdl) \
997{ \
998 (void) mdl; \
999 (prefix ## _count)++; \
1000}
1001
1002static void
1003animal_eat(Eina_Model *mdl)
1004{
1005 void (*pf)(Eina_Model *mdl);
1006 pf = eina_model_method_resolve(mdl, Animal_Type, eat);
1007 EINA_SAFETY_ON_NULL_RETURN(pf);
1008 pf(mdl);
1009}
1010
1011static void
1012pooper_poop(Eina_Model *mdl)
1013{
1014 const Eina_Model_Interface *iface = NULL;
1015 iface = eina_model_interface_get(mdl, POOPER_IFACE_NAME);
1016
1017 EINA_SAFETY_ON_NULL_RETURN(iface);
1018
1019 void (*pf)(Eina_Model *);
1020
1021 pf = eina_model_interface_method_resolve(iface, mdl, Pooper_Interface, poop);
1022 EINA_SAFETY_ON_NULL_RETURN(pf);
1023 pf(mdl);
1024}
1025
1026INHER_CB_COUNT(_animal_poop);
1027INHER_CB_COUNT(_human_poop);
1028INHER_CB_COUNT(_animal_eat);
1029INHER_CB_COUNT(_human_eat);
1030
1031START_TEST(eina_model_test_inheritance)
1032{
1033 eina_init();
1034
1035 Pooper_Interface _ANIMAL_POOPER_IFACE;
1036 Eina_Model_Interface *ANIMAL_POOPER_IFACE = (Eina_Model_Interface *) &_ANIMAL_POOPER_IFACE;
1037 memset(&_ANIMAL_POOPER_IFACE, 0, sizeof(_ANIMAL_POOPER_IFACE));
1038 ANIMAL_POOPER_IFACE->version = EINA_MODEL_INTERFACE_VERSION;
1039 ANIMAL_POOPER_IFACE->interface_size = sizeof(Pooper_Interface);
1040 ANIMAL_POOPER_IFACE->name = POOPER_IFACE_NAME;
1041 POOPER_IFACE(ANIMAL_POOPER_IFACE)->poop = _animal_poop;
1042
1043 Pooper_Interface _HUMAN_POOPER_IFACE;
1044 Eina_Model_Interface *HUMAN_POOPER_IFACE = (Eina_Model_Interface *) &_HUMAN_POOPER_IFACE;
1045 const Eina_Model_Interface *HUMAN_POOPER_IFACES[] = {
1046 ANIMAL_POOPER_IFACE, NULL
1047 };
1048 memset(&_HUMAN_POOPER_IFACE, 0, sizeof(_HUMAN_POOPER_IFACE));
1049 HUMAN_POOPER_IFACE->version = EINA_MODEL_INTERFACE_VERSION;
1050 HUMAN_POOPER_IFACE->interface_size = sizeof(Pooper_Interface);
1051 HUMAN_POOPER_IFACE->name = POOPER_IFACE_NAME;
1052 HUMAN_POOPER_IFACE->interfaces = HUMAN_POOPER_IFACES;
1053 POOPER_IFACE(HUMAN_POOPER_IFACE)->poop = _human_poop;
1054
1055 const Eina_Model_Interface *ANIMAL_IFACES[] = {ANIMAL_POOPER_IFACE, NULL};
1056 const Eina_Model_Interface *HUMAN_IFACES[] = {HUMAN_POOPER_IFACE, NULL};
1057
1058 /* Init Animal Type */
1059 Animal_Type _ANIMAL_TYPE;
1060 Eina_Model_Type *ANIMAL_TYPE = (Eina_Model_Type *) &_ANIMAL_TYPE;
1061
1062 memset(&_ANIMAL_TYPE, 0, sizeof(_ANIMAL_TYPE));
1063 Eina_Model_Type *type = (Eina_Model_Type *) &_ANIMAL_TYPE;
1064 type->version = EINA_MODEL_TYPE_VERSION;
1065 type->parent = EINA_MODEL_TYPE_BASE;
1066 type->type_size = sizeof(Animal_Type);
1067 type->name = "Animal_Type";
1068 type->parent = EINA_MODEL_TYPE_GENERIC;
1069 type->interfaces = ANIMAL_IFACES;
1070
1071 ANIMAL_TYPE(type)->eat = _animal_eat;
1072
1073 /* Init Human Type */
1074 Animal_Type _HUMAN_TYPE;
1075 Eina_Model_Type *HUMAN_TYPE = (Eina_Model_Type *) &_HUMAN_TYPE;
1076 memset(&_HUMAN_TYPE, 0, sizeof(_HUMAN_TYPE));
1077 type = (Eina_Model_Type *) &_HUMAN_TYPE;
1078 type->version = EINA_MODEL_TYPE_VERSION;
1079 type->parent = ANIMAL_TYPE;
1080 type->type_size = sizeof(Human_Type);
1081 type->name = "Human_Type";
1082 type->interfaces = HUMAN_IFACES;
1083
1084 ANIMAL_TYPE(type)->eat = _human_eat;
1085
1086 Eina_Model *hm, *am;
1087 am = eina_model_new(ANIMAL_TYPE);
1088 hm = eina_model_new(HUMAN_TYPE);
1089
1090 animal_eat(am);
1091 ck_assert_int_eq(_animal_eat_count, 1);
1092 animal_eat(hm);
1093 ck_assert_int_eq(_human_eat_count, 1);
1094
1095 pooper_poop(am);
1096 ck_assert_int_eq(_animal_poop_count, 1);
1097 pooper_poop(hm);
1098 ck_assert_int_eq(_human_poop_count, 1);
1099
1100 ck_assert_int_eq(_animal_eat_count, 1);
1101 ck_assert_int_eq(_human_eat_count, 1);
1102 ck_assert_int_eq(_animal_poop_count, 1);
1103 ck_assert_int_eq(_human_poop_count, 1);
1104
1105 ck_assert_int_eq(eina_model_refcount(am), 1);
1106 ck_assert_int_eq(eina_model_refcount(hm), 1);
1107
1108 eina_model_unref(am);
1109 eina_model_unref(hm);
1110
1111 eina_shutdown();
1112}
1113END_TEST
1114
1115static Eina_Bool
1116_myproperties_load(Eina_Model *m)
1117{
1118 Eina_Value v;
1119 Eina_Bool ret;
1120 int count;
1121
1122 if (!eina_model_property_get(m, "load_count", &v))
1123 return EINA_FALSE;
1124
1125 eina_value_get(&v, &count);
1126 count++;
1127 eina_value_set(&v, count);
1128
1129 ret = eina_model_property_set(m, "load_count", &v);
1130 eina_value_flush(&v);
1131
1132 return ret;
1133}
1134
1135static Eina_Bool
1136_myproperties_unload(Eina_Model *m)
1137{
1138 Eina_Value v;
1139 Eina_Bool ret;
1140 int count;
1141
1142 if (!eina_model_property_get(m, "load_count", &v))
1143 return EINA_FALSE;
1144
1145 eina_value_get(&v, &count);
1146 count--;
1147 eina_value_set(&v, count);
1148
1149 ret = eina_model_property_set(m, "load_count", &v);
1150 eina_value_flush(&v);
1151
1152 return ret;
1153}
1154
1155static Eina_Bool
1156_mychildren_load(Eina_Model *m)
1157{
1158 Eina_Model *c = eina_model_new(EINA_MODEL_TYPE_GENERIC);
1159 int ret = eina_model_child_append(m, c);
1160 eina_model_unref(c);
1161 return ret >= 0;
1162}
1163
1164static Eina_Bool
1165_mychildren_unload(Eina_Model *m)
1166{
1167 int count = eina_model_child_count(m);
1168 EINA_SAFETY_ON_FALSE_RETURN_VAL(count > 0, EINA_FALSE);
1169 return eina_model_child_del(m, count - 1);
1170}
1171
1172START_TEST(eina_model_test_ifaces_load_unload)
1173{
1174 unsigned int count_loaded = 0, count_unloaded = 0;
1175 unsigned int count_ploaded = 0, count_punloaded = 0;
1176 unsigned int count_cloaded = 0, count_cunloaded = 0;
1177 static Eina_Model_Interface_Properties piface;
1178 static Eina_Model_Interface_Children ciface;
1179 static const Eina_Model_Interface *piface_parents[2] = {NULL, NULL};
1180 static const Eina_Model_Interface *ciface_parents[2] = {NULL, NULL};
1181 static const Eina_Model_Interface *type_ifaces[3] = {
1182 &piface.base, &ciface.base, NULL
1183 };
1184 static Eina_Model_Type type;
1185 Eina_Model *m;
1186 Eina_Value v;
1187 int count;
1188
1189 eina_init();
1190
1191 /* do after eina_init() otherwise interfaces are not set */
1192 piface_parents[0] = EINA_MODEL_INTERFACE_PROPERTIES_HASH;
1193 ciface_parents[0] = EINA_MODEL_INTERFACE_CHILDREN_INARRAY;
1194
1195 memset(&piface, 0, sizeof(piface));
1196 piface.base.version = EINA_MODEL_INTERFACE_VERSION;
1197 piface.base.interface_size = sizeof(piface);
1198 piface.base.name = EINA_MODEL_INTERFACE_NAME_PROPERTIES;
1199 piface.base.interfaces = piface_parents;
1200 piface.load = _myproperties_load;
1201 piface.unload = _myproperties_unload;
1202
1203 memset(&ciface, 0, sizeof(ciface));
1204 ciface.base.version = EINA_MODEL_INTERFACE_VERSION;
1205 ciface.base.interface_size = sizeof(ciface);
1206 ciface.base.name = EINA_MODEL_INTERFACE_NAME_CHILDREN;
1207 ciface.base.interfaces = ciface_parents;
1208 ciface.load = _mychildren_load;
1209 ciface.unload = _mychildren_unload;
1210
1211 type.version = EINA_MODEL_TYPE_VERSION;
1212 type.private_size = 0;
1213 type.name = "MyType";
1214 eina_model_type_subclass_setup(&type, EINA_MODEL_TYPE_GENERIC);
1215 type.interfaces = type_ifaces;
1216
1217 m = eina_model_new(&type);
1218 fail_unless(m != NULL);
1219
1220 eina_model_event_callback_add
1221 (m, "loaded", _eina_test_model_cb_count, &count_loaded);
1222 eina_model_event_callback_add
1223 (m, "unloaded", _eina_test_model_cb_count, &count_unloaded);
1224
1225 eina_model_event_callback_add
1226 (m, "properties,loaded", _eina_test_model_cb_count, &count_ploaded);
1227 eina_model_event_callback_add
1228 (m, "properties,unloaded", _eina_test_model_cb_count, &count_punloaded);
1229
1230 eina_model_event_callback_add
1231 (m, "children,loaded", _eina_test_model_cb_count, &count_cloaded);
1232 eina_model_event_callback_add
1233 (m, "children,unloaded", _eina_test_model_cb_count, &count_cunloaded);
1234
1235 fail_unless(eina_value_setup(&v, EINA_VALUE_TYPE_INT));
1236 fail_unless(eina_value_set(&v, 0));
1237 fail_unless(eina_model_property_set(m, "load_count", &v));
1238 eina_value_flush(&v);
1239
1240 fail_unless(eina_model_load(m));
1241 fail_unless(eina_model_load(m));
1242 fail_unless(eina_model_load(m));
1243
1244 /* each load increments one for load_count property */
1245 fail_unless(eina_model_property_get(m, "load_count", &v));
1246 fail_unless(eina_value_pget(&v, &count));
1247 ck_assert_int_eq(count, 3);
1248 eina_value_flush(&v);
1249
1250 /* each load adds one child */
1251 ck_assert_int_eq(eina_model_child_count(m), 3);
1252
1253 fail_unless(eina_model_unload(m));
1254 fail_unless(eina_model_unload(m));
1255 fail_unless(eina_model_unload(m));
1256
1257 ck_assert_int_eq(count_loaded, 3);
1258 ck_assert_int_eq(count_unloaded, 3);
1259
1260 ck_assert_int_eq(count_ploaded, 3);
1261 ck_assert_int_eq(count_punloaded, 3);
1262
1263 ck_assert_int_eq(count_cloaded, 3);
1264 ck_assert_int_eq(count_cunloaded, 3);
1265
1266 ck_assert_int_eq(eina_model_refcount(m), 1);
1267 eina_model_unref(m);
1268
1269 eina_shutdown();
1270}
1271END_TEST
1272
1273void
1274eina_test_model(TCase *tc)
1275{
1276 tcase_add_test(tc, eina_model_test_properties);
1277 tcase_add_test(tc, eina_model_test_children);
1278 tcase_add_test(tc, eina_model_test_copy);
1279 tcase_add_test(tc, eina_model_test_deep_copy);
1280 tcase_add_test(tc, eina_model_test_child_iterator);
1281 tcase_add_test(tc, eina_model_test_child_reversed_iterator);
1282 tcase_add_test(tc, eina_model_test_child_sorted_iterator);
1283 tcase_add_test(tc, eina_model_test_child_filtered_iterator);
1284 tcase_add_test(tc, eina_model_test_struct);
1285 tcase_add_test(tc, eina_model_test_struct_complex_members);
1286 tcase_add_test(tc, eina_model_test_inheritance);
1287 tcase_add_test(tc, eina_model_test_ifaces_load_unload);
1288}