Eobj: s/__UNUSED__/EINA_UNUSED/ I had no idea that exists.
[profile/ivi/eobj.git] / lib / eobj_base_class.c
1 #include <Eina.h>
2
3 #include "Eobj.h"
4 #include "eobj_private.h"
5
6 #include "config.h"
7
8 EAPI Eobj_Op EOBJ_BASE_BASE_ID = EOBJ_NOOP;
9
10 typedef struct
11 {
12    Eina_Inlist *generic_data;
13 } Private_Data;
14
15 typedef struct
16 {
17    EINA_INLIST;
18    Eina_Stringshare *key;
19    void *data;
20    eobj_base_data_free_func free_func;
21 } Eobj_Generic_Data_Node;
22
23 static void
24 _eobj_generic_data_node_free(Eobj_Generic_Data_Node *node)
25 {
26    eina_stringshare_del(node->key);
27    if (node->free_func)
28       node->free_func(node->data);
29    free(node);
30 }
31
32 static void
33 _eobj_generic_data_del_all(Private_Data *pd)
34 {
35    Eina_Inlist *nnode;
36    Eobj_Generic_Data_Node *node;
37
38    EINA_INLIST_FOREACH_SAFE(pd->generic_data, nnode, node)
39      {
40         pd->generic_data = eina_inlist_remove(pd->generic_data,
41               EINA_INLIST_GET(node));
42
43         _eobj_generic_data_node_free(node);
44      }
45 }
46
47 static void
48 _data_set(Eobj *obj, void *class_data, va_list *list)
49 {
50    Private_Data *pd = class_data;
51    const char *key = va_arg(*list, const char *);
52    const void *data = va_arg(*list, const void *);
53    eobj_base_data_free_func free_func = va_arg(*list, eobj_base_data_free_func);
54
55    Eobj_Generic_Data_Node *node;
56
57    if (!key) return;
58
59    eobj_do(obj, EOBJ_BASE_DATA_DEL(key));
60
61    node = malloc(sizeof(Eobj_Generic_Data_Node));
62    node->key = eina_stringshare_add(key);
63    node->data = (void *) data;
64    node->free_func = free_func;
65    pd->generic_data = eina_inlist_prepend(pd->generic_data,
66          EINA_INLIST_GET(node));
67 }
68
69 static void
70 _data_get(Eobj *obj EINA_UNUSED, void *class_data, va_list *list)
71 {
72    Private_Data *pd = class_data;
73    const char *key = va_arg(*list, const char *);
74    void **data = va_arg(*list, void **);
75    Eobj_Generic_Data_Node *node;
76
77    if (!data) return;
78    *data = NULL;
79
80    if (!key) return;
81
82    EINA_INLIST_FOREACH(pd->generic_data, node)
83      {
84         if (!strcmp(node->key, key))
85           {
86              pd->generic_data =
87                 eina_inlist_promote(pd->generic_data, EINA_INLIST_GET(node));
88              *data = node->data;
89              return;
90           }
91      }
92 }
93
94 static void
95 _data_del(Eobj *obj EINA_UNUSED, void *class_data, va_list *list)
96 {
97    Private_Data *pd = class_data;
98    const char *key = va_arg(*list, const char *);
99
100    Eobj_Generic_Data_Node *node;
101
102    if (!key) return;
103
104    EINA_INLIST_FOREACH(pd->generic_data, node)
105      {
106         if (!strcmp(node->key, key))
107           {
108              pd->generic_data = eina_inlist_remove(pd->generic_data,
109                    EINA_INLIST_GET(node));
110              _eobj_generic_data_node_free(node);
111              return;
112           }
113      }
114 }
115
116 /* EOBJ_BASE_CLASS stuff */
117 static const Eobj_Class *_my_class = NULL;
118
119 /* FIXME: Set proper type descriptions. */
120 EAPI const Eobj_Event_Description _EOBJ_EV_CALLBACK_ADD =
121    EOBJ_EVENT_DESCRIPTION("callback,add", "?", "A callback was added.");
122 EAPI const Eobj_Event_Description _EOBJ_EV_CALLBACK_DEL =
123    EOBJ_EVENT_DESCRIPTION("callback,del", "?", "A callback was deleted.");
124 EAPI const Eobj_Event_Description _EOBJ_EV_FREE =
125    EOBJ_EVENT_DESCRIPTION("free", "", "Obj is being freed.");
126 EAPI const Eobj_Event_Description _EOBJ_EV_DEL =
127    EOBJ_EVENT_DESCRIPTION("del", "", "Obj is being deleted.");
128
129 static void
130 _constructor(Eobj *obj, void *class_data EINA_UNUSED)
131 {
132    DBG("%p - %s.", obj, eobj_class_name_get(_my_class));
133 }
134
135 static void
136 _destructor(Eobj *obj, void *class_data)
137 {
138    DBG("%p - %s.", obj, eobj_class_name_get(_my_class));
139
140    _eobj_generic_data_del_all(class_data);
141 }
142
143 static void
144 _class_constructor(Eobj_Class *klass)
145 {
146    const Eobj_Op_Func_Description func_desc[] = {
147         EOBJ_OP_FUNC(EOBJ_BASE_ID(EOBJ_BASE_SUB_ID_DATA_SET), _data_set),
148         EOBJ_OP_FUNC(EOBJ_BASE_ID(EOBJ_BASE_SUB_ID_DATA_GET), _data_get),
149         EOBJ_OP_FUNC(EOBJ_BASE_ID(EOBJ_BASE_SUB_ID_DATA_DEL), _data_del),
150         EOBJ_OP_FUNC_SENTINEL
151    };
152
153    eobj_class_funcs_set(klass, func_desc);
154 }
155
156 EAPI const Eobj_Class *
157 eobj_base_class_get(void)
158 {
159    if (_my_class) return _my_class;
160
161    static const Eobj_Op_Description op_desc[] = {
162         EOBJ_OP_DESCRIPTION(EOBJ_BASE_SUB_ID_DATA_SET, "?", "Set data for key."),
163         EOBJ_OP_DESCRIPTION(EOBJ_BASE_SUB_ID_DATA_GET, "?", "Get data for key."),
164         EOBJ_OP_DESCRIPTION(EOBJ_BASE_SUB_ID_DATA_DEL, "?", "Del key."),
165         EOBJ_OP_DESCRIPTION_SENTINEL
166    };
167
168    static const Eobj_Event_Description *event_desc[] = {
169         EOBJ_EV_CALLBACK_ADD,
170         EOBJ_EV_CALLBACK_DEL,
171         EOBJ_EV_FREE,
172         EOBJ_EV_DEL,
173         NULL
174    };
175
176    static const Eobj_Class_Description class_desc = {
177         "Eobj Base",
178         EOBJ_CLASS_TYPE_REGULAR_NO_INSTANT,
179         EOBJ_CLASS_DESCRIPTION_OPS(&EOBJ_BASE_BASE_ID, op_desc, EOBJ_BASE_SUB_ID_LAST),
180         event_desc,
181         sizeof(Private_Data),
182         _constructor,
183         _destructor,
184         _class_constructor,
185         NULL
186    };
187
188    return _my_class = eobj_class_new(&class_desc, NULL, NULL);
189 }
190