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> /* asprintf() */
24 #include <inttypes.h> /* PRId64 and PRIu64 */
25 #include <sys/time.h> /* struct timeval */
26
27 #include "eina_config.h"
28 #include "eina_private.h"
29 #include "eina_alloca.h"
30 #include "eina_log.h"
31 #include "eina_strbuf.h"
32 #include "eina_mempool.h"
33 #include "eina_lock.h"
34 #include "eina_file.h"
35 #include "eina_rectangle.h"
36 #include "eina_binbuf.h"
37
38 /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
39 #include "eina_safety_checks.h"
40 #include "eina_value.h"
41
42 EAPI Eina_Error EINA_ERROR_VALUE_FAILED = 0;
43
44 /*============================================================================*
45 * Local *
46 *============================================================================*/
47
48 /**
49 * @cond LOCAL
50 */
51
52 static Eina_Mempool *_eina_value_mp = NULL;
53 static Eina_Hash *_eina_value_inner_mps = NULL;
54 static Eina_Lock _eina_value_inner_mps_lock;
55 static char *_eina_value_mp_choice = NULL;
56 static int _eina_value_log_dom = -1;
57 static Eina_Value _eina_value_empty;
58
59 #ifdef ERR
60 #undef ERR
61 #endif
62 #define ERR(...) EINA_LOG_DOM_ERR(_eina_value_log_dom, __VA_ARGS__)
63
64 #ifdef DBG
65 #undef DBG
66 #endif
67 #define DBG(...) EINA_LOG_DOM_DBG(_eina_value_log_dom, __VA_ARGS__)
68
69 static const unsigned char eina_value_uchar_max = 255U;
70 static const char eina_value_char_max = 127;
71 static const signed char eina_value_char_min = -127 - 1;
72
73 static const unsigned short eina_value_ushort_max = 65535U;
74 static const short eina_value_short_max = 32767;
75 static const short eina_value_short_min = -32767 - 1;
76
77 static const unsigned int eina_value_uint_max = 4294967295U;
78 static const int eina_value_int_max = 2147483647;
79 static const int eina_value_int_min = -2147483647 - 1;
80
81 static const uint64_t eina_value_uint64_max = 18446744073709551615ULL;
82 static const int64_t eina_value_int64_max = 9223372036854775807LL;
83 static const int64_t eina_value_int64_min = -9223372036854775807LL - 1LL;
84
85 #if !defined (_WIN32) && (__WORDSIZE == 64)
86 static const unsigned long eina_value_ulong_max = 18446744073709551615ULL;
87 static const long eina_value_long_max = 9223372036854775807LL;
88 static const long eina_value_long_min = -9223372036854775807LL - 1LL;
89 #else
90 static const unsigned long eina_value_ulong_max = 4294967295U;
91 static const long eina_value_long_max = 2147483647;
92 static const long eina_value_long_min = -2147483647 - 1;
93 #endif
94
95
96 static Eina_Bool
_eina_value_type_uchar_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)97 _eina_value_type_uchar_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
98 {
99 unsigned char *tmem = mem;
100 *tmem = 0;
101 return EINA_TRUE;
102 }
103
104 static Eina_Bool
_eina_value_type_uchar_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem EINA_UNUSED)105 _eina_value_type_uchar_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem EINA_UNUSED)
106 {
107 return EINA_TRUE;
108 }
109
110 static Eina_Bool
_eina_value_type_uchar_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)111 _eina_value_type_uchar_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
112 {
113 const unsigned char *s = src;
114 unsigned char *d = dst;
115 *d = *s;
116 return EINA_TRUE;
117 }
118
119 static int
_eina_value_type_uchar_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)120 _eina_value_type_uchar_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
121 {
122 const unsigned char *ta = a, *tb = b;
123 if (*ta < *tb)
124 return -1;
125 else if (*ta > *tb)
126 return 1;
127 return 0;
128 }
129
130 static Eina_Bool
_eina_value_type_uchar_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)131 _eina_value_type_uchar_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
132 {
133 const unsigned char v = *(const unsigned char *)type_mem;
134
135 if (convert == EINA_VALUE_TYPE_UCHAR)
136 {
137 unsigned char other_mem = v;
138 return eina_value_type_pset(convert, convert_mem, &other_mem);
139 }
140 else if (convert == EINA_VALUE_TYPE_USHORT)
141 {
142 unsigned short other_mem = v;
143 return eina_value_type_pset(convert, convert_mem, &other_mem);
144 }
145 else if (convert == EINA_VALUE_TYPE_UINT)
146 {
147 unsigned int other_mem = v;
148 return eina_value_type_pset(convert, convert_mem, &other_mem);
149 }
150 else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP))
151 {
152 unsigned long other_mem = v;
153 return eina_value_type_pset(convert, convert_mem, &other_mem);
154 }
155 else if (convert == EINA_VALUE_TYPE_UINT64)
156 {
157 uint64_t other_mem = v;
158 return eina_value_type_pset(convert, convert_mem, &other_mem);
159 }
160 else if (convert == EINA_VALUE_TYPE_CHAR)
161 {
162 signed char other_mem = v;
163 if (EINA_UNLIKELY(v > (unsigned char)eina_value_char_max))
164 return EINA_FALSE;
165 return eina_value_type_pset(convert, convert_mem, &other_mem);
166 }
167 else if (convert == EINA_VALUE_TYPE_SHORT)
168 {
169 short other_mem = v;
170 return eina_value_type_pset(convert, convert_mem, &other_mem);
171 }
172 else if ((convert == EINA_VALUE_TYPE_INT) || (convert == EINA_VALUE_TYPE_ERROR))
173 {
174 int other_mem = v;
175 return eina_value_type_pset(convert, convert_mem, &other_mem);
176 }
177 else if (convert == EINA_VALUE_TYPE_LONG)
178 {
179 long other_mem = v;
180 return eina_value_type_pset(convert, convert_mem, &other_mem);
181 }
182 else if (convert == EINA_VALUE_TYPE_INT64)
183 {
184 int64_t other_mem = v;
185 return eina_value_type_pset(convert, convert_mem, &other_mem);
186 }
187 else if (convert == EINA_VALUE_TYPE_FLOAT)
188 {
189 float other_mem = v;
190 return eina_value_type_pset(convert, convert_mem, &other_mem);
191 }
192 else if (convert == EINA_VALUE_TYPE_DOUBLE)
193 {
194 double other_mem = v;
195 return eina_value_type_pset(convert, convert_mem, &other_mem);
196 }
197 else if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
198 convert == EINA_VALUE_TYPE_STRING)
199 {
200 const char *other_mem;
201 char buf[64];
202 snprintf(buf, sizeof(buf), "%hhu", v);
203 other_mem = buf; /* required due &buf == buf */
204 return eina_value_type_pset(convert, convert_mem, &other_mem);
205 }
206 else
207 {
208 return EINA_FALSE;
209 }
210
211 return EINA_TRUE;
212 }
213
214 static Eina_Bool
_eina_value_type_uchar_vset(const Eina_Value_Type * type EINA_UNUSED,void * mem,va_list args)215 _eina_value_type_uchar_vset(const Eina_Value_Type *type EINA_UNUSED, void *mem, va_list args)
216 {
217 unsigned char *tmem = mem;
218 *tmem = va_arg(args, unsigned int); /* char is promoted to int for va_arg */
219 return EINA_TRUE;
220 }
221
222 static Eina_Bool
_eina_value_type_uchar_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)223 _eina_value_type_uchar_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
224 {
225 unsigned char *tmem = mem;
226 const unsigned char *p = ptr;
227 *tmem = *p;
228 return EINA_TRUE;
229 }
230
231 static Eina_Bool
_eina_value_type_uchar_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)232 _eina_value_type_uchar_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
233 {
234 const unsigned char *tmem = mem;
235 unsigned char *p = ptr;
236 *p = *tmem;
237 return EINA_TRUE;
238 }
239
240 static Eina_Bool
_eina_value_type_ushort_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)241 _eina_value_type_ushort_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
242 {
243 unsigned short *tmem = mem;
244 *tmem = 0;
245 return EINA_TRUE;
246 }
247
248 static Eina_Bool
_eina_value_type_ushort_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem EINA_UNUSED)249 _eina_value_type_ushort_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem EINA_UNUSED)
250 {
251 return EINA_TRUE;
252 }
253
254 static Eina_Bool
_eina_value_type_ushort_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)255 _eina_value_type_ushort_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
256 {
257 const unsigned short *s = src;
258 unsigned short *d = dst;
259 *d = *s;
260 return EINA_TRUE;
261 }
262
263 static int
_eina_value_type_ushort_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)264 _eina_value_type_ushort_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
265 {
266 const unsigned short *ta = a, *tb = b;
267 if (*ta < *tb)
268 return -1;
269 else if (*ta > *tb)
270 return 1;
271 return 0;
272 }
273
274 static Eina_Bool
_eina_value_type_ushort_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)275 _eina_value_type_ushort_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
276 {
277 const unsigned short v = *(const unsigned short *)type_mem;
278
279 if (convert == EINA_VALUE_TYPE_UCHAR)
280 {
281 unsigned char other_mem = v;
282 if (EINA_UNLIKELY(v > eina_value_uchar_max))
283 return EINA_FALSE;
284 return eina_value_type_pset(convert, convert_mem, &other_mem);
285 }
286 else if (convert == EINA_VALUE_TYPE_USHORT)
287 {
288 unsigned short other_mem = v;
289 return eina_value_type_pset(convert, convert_mem, &other_mem);
290 }
291 else if (convert == EINA_VALUE_TYPE_UINT)
292 {
293 unsigned int other_mem = v;
294 return eina_value_type_pset(convert, convert_mem, &other_mem);
295 }
296 else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP))
297 {
298 unsigned long other_mem = v;
299 return eina_value_type_pset(convert, convert_mem, &other_mem);
300 }
301 else if (convert == EINA_VALUE_TYPE_UINT64)
302 {
303 uint64_t other_mem = v;
304 return eina_value_type_pset(convert, convert_mem, &other_mem);
305 }
306 else if (convert == EINA_VALUE_TYPE_CHAR)
307 {
308 signed char other_mem = v;
309 if (EINA_UNLIKELY(v > (unsigned char)eina_value_char_max))
310 return EINA_FALSE;
311 return eina_value_type_pset(convert, convert_mem, &other_mem);
312 }
313 else if (convert == EINA_VALUE_TYPE_SHORT)
314 {
315 short other_mem = v;
316 if (EINA_UNLIKELY(v > (unsigned short)eina_value_short_max))
317 return EINA_FALSE;
318 return eina_value_type_pset(convert, convert_mem, &other_mem);
319 }
320 else if ((convert == EINA_VALUE_TYPE_INT) || (convert == EINA_VALUE_TYPE_ERROR))
321 {
322 int other_mem = v;
323 return eina_value_type_pset(convert, convert_mem, &other_mem);
324 }
325 else if (convert == EINA_VALUE_TYPE_LONG)
326 {
327 long other_mem = v;
328 return eina_value_type_pset(convert, convert_mem, &other_mem);
329 }
330 else if (convert == EINA_VALUE_TYPE_INT64)
331 {
332 int64_t other_mem = v;
333 return eina_value_type_pset(convert, convert_mem, &other_mem);
334 }
335 else if (convert == EINA_VALUE_TYPE_FLOAT)
336 {
337 float other_mem = v;
338 return eina_value_type_pset(convert, convert_mem, &other_mem);
339 }
340 else if (convert == EINA_VALUE_TYPE_DOUBLE)
341 {
342 double other_mem = v;
343 return eina_value_type_pset(convert, convert_mem, &other_mem);
344 }
345 else if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
346 convert == EINA_VALUE_TYPE_STRING)
347 {
348 const char *other_mem;
349 char buf[64];
350 snprintf(buf, sizeof(buf), "%hu", v);
351 other_mem = buf; /* required due &buf == buf */
352 return eina_value_type_pset(convert, convert_mem, &other_mem);
353 }
354 else
355 {
356 return EINA_FALSE;
357 }
358
359 return EINA_TRUE;
360 }
361
362 static Eina_Bool
_eina_value_type_ushort_vset(const Eina_Value_Type * type EINA_UNUSED,void * mem,va_list args)363 _eina_value_type_ushort_vset(const Eina_Value_Type *type EINA_UNUSED, void *mem, va_list args)
364 {
365 unsigned short *tmem = mem;
366 *tmem = va_arg(args, unsigned int); /* short is promoted to int for va_arg */
367 return EINA_TRUE;
368 }
369
370 static Eina_Bool
_eina_value_type_ushort_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)371 _eina_value_type_ushort_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
372 {
373 unsigned short *tmem = mem;
374 const unsigned short *p = ptr;
375 *tmem = *p;
376 return EINA_TRUE;
377 }
378
379 static Eina_Bool
_eina_value_type_ushort_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)380 _eina_value_type_ushort_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
381 {
382 const unsigned short *tmem = mem;
383 unsigned short *p = ptr;
384 *p = *tmem;
385 return EINA_TRUE;
386 }
387
388 static Eina_Bool
_eina_value_type_uint_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)389 _eina_value_type_uint_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
390 {
391 unsigned int *tmem = mem;
392 *tmem = 0;
393 return EINA_TRUE;
394 }
395
396 static Eina_Bool
_eina_value_type_uint_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem EINA_UNUSED)397 _eina_value_type_uint_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem EINA_UNUSED)
398 {
399 return EINA_TRUE;
400 }
401
402 static Eina_Bool
_eina_value_type_uint_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)403 _eina_value_type_uint_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
404 {
405 const unsigned int *s = src;
406 unsigned int *d = dst;
407 *d = *s;
408 return EINA_TRUE;
409 }
410
411 static int
_eina_value_type_uint_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)412 _eina_value_type_uint_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
413 {
414 const unsigned int *ta = a, *tb = b;
415 if (*ta < *tb)
416 return -1;
417 else if (*ta > *tb)
418 return 1;
419 return 0;
420 }
421
422 static Eina_Bool
_eina_value_type_uint_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)423 _eina_value_type_uint_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
424 {
425 const unsigned int v = *(const unsigned int *)type_mem;
426
427 if (convert == EINA_VALUE_TYPE_UCHAR)
428 {
429 unsigned char other_mem = v;
430 if (EINA_UNLIKELY(v > eina_value_uchar_max))
431 return EINA_FALSE;
432 return eina_value_type_pset(convert, convert_mem, &other_mem);
433 }
434 else if (convert == EINA_VALUE_TYPE_USHORT)
435 {
436 unsigned short other_mem = v;
437 if (EINA_UNLIKELY(v > eina_value_ushort_max))
438 return EINA_FALSE;
439 return eina_value_type_pset(convert, convert_mem, &other_mem);
440 }
441 else if (convert == EINA_VALUE_TYPE_UINT)
442 {
443 unsigned int other_mem = v;
444 return eina_value_type_pset(convert, convert_mem, &other_mem);
445 }
446 else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP))
447 {
448 unsigned long other_mem = v;
449 return eina_value_type_pset(convert, convert_mem, &other_mem);
450 }
451 else if (convert == EINA_VALUE_TYPE_UINT64)
452 {
453 uint64_t other_mem = v;
454 return eina_value_type_pset(convert, convert_mem, &other_mem);
455 }
456 else if (convert == EINA_VALUE_TYPE_CHAR)
457 {
458 signed char other_mem = v;
459 if (EINA_UNLIKELY(v > (unsigned char)eina_value_char_max))
460 return EINA_FALSE;
461 return eina_value_type_pset(convert, convert_mem, &other_mem);
462 }
463 else if (convert == EINA_VALUE_TYPE_SHORT)
464 {
465 short other_mem = v;
466 if (EINA_UNLIKELY(v > (unsigned short)eina_value_short_max))
467 return EINA_FALSE;
468 return eina_value_type_pset(convert, convert_mem, &other_mem);
469 }
470 else if ((convert == EINA_VALUE_TYPE_INT) || (convert == EINA_VALUE_TYPE_ERROR))
471 {
472 int other_mem = v;
473 if (EINA_UNLIKELY(v > (unsigned int)eina_value_int_max))
474 return EINA_FALSE;
475 return eina_value_type_pset(convert, convert_mem, &other_mem);
476 }
477 else if (convert == EINA_VALUE_TYPE_LONG)
478 {
479 long other_mem = v;
480 return eina_value_type_pset(convert, convert_mem, &other_mem);
481 }
482 else if (convert == EINA_VALUE_TYPE_INT64)
483 {
484 int64_t other_mem = v;
485 return eina_value_type_pset(convert, convert_mem, &other_mem);
486 }
487 else if (convert == EINA_VALUE_TYPE_FLOAT)
488 {
489 float other_mem = v;
490 return eina_value_type_pset(convert, convert_mem, &other_mem);
491 }
492 else if (convert == EINA_VALUE_TYPE_DOUBLE)
493 {
494 double other_mem = v;
495 return eina_value_type_pset(convert, convert_mem, &other_mem);
496 }
497 else if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
498 convert == EINA_VALUE_TYPE_STRING)
499 {
500 const char *other_mem;
501 char buf[64];
502 snprintf(buf, sizeof(buf), "%u", v);
503 other_mem = buf; /* required due &buf == buf */
504 return eina_value_type_pset(convert, convert_mem, &other_mem);
505 }
506 else
507 {
508 return EINA_FALSE;
509 }
510
511 return EINA_TRUE;
512 }
513
514 static Eina_Bool
_eina_value_type_uint_vset(const Eina_Value_Type * type EINA_UNUSED,void * mem,va_list args)515 _eina_value_type_uint_vset(const Eina_Value_Type *type EINA_UNUSED, void *mem, va_list args)
516 {
517 unsigned int *tmem = mem;
518 *tmem = va_arg(args, unsigned int);
519 return EINA_TRUE;
520 }
521
522 static Eina_Bool
_eina_value_type_uint_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)523 _eina_value_type_uint_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
524 {
525 unsigned int *tmem = mem;
526 const unsigned int *p = ptr;
527 *tmem = *p;
528 return EINA_TRUE;
529 }
530
531 static Eina_Bool
_eina_value_type_uint_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)532 _eina_value_type_uint_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
533 {
534 const unsigned int *tmem = mem;
535 unsigned int *p = ptr;
536 *p = *tmem;
537 return EINA_TRUE;
538 }
539
540 static Eina_Bool
_eina_value_type_ulong_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)541 _eina_value_type_ulong_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
542 {
543 unsigned long *tmem = mem;
544 *tmem = 0;
545 return EINA_TRUE;
546 }
547
548 static Eina_Bool
_eina_value_type_ulong_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem EINA_UNUSED)549 _eina_value_type_ulong_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem EINA_UNUSED)
550 {
551 return EINA_TRUE;
552 }
553
554 static Eina_Bool
_eina_value_type_ulong_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)555 _eina_value_type_ulong_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
556 {
557 const unsigned long *s = src;
558 unsigned long *d = dst;
559 *d = *s;
560 return EINA_TRUE;
561 }
562
563 static int
_eina_value_type_ulong_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)564 _eina_value_type_ulong_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
565 {
566 const unsigned long *ta = a, *tb = b;
567 if (*ta < *tb)
568 return -1;
569 else if (*ta > *tb)
570 return 1;
571 return 0;
572 }
573
574 static Eina_Bool
_eina_value_type_ulong_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)575 _eina_value_type_ulong_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
576 {
577 const unsigned long v = *(const unsigned long *)type_mem;
578
579 if (convert == EINA_VALUE_TYPE_UCHAR)
580 {
581 unsigned char other_mem = v;
582 if (EINA_UNLIKELY(v > eina_value_uchar_max))
583 return EINA_FALSE;
584 return eina_value_type_pset(convert, convert_mem, &other_mem);
585 }
586 else if (convert == EINA_VALUE_TYPE_USHORT)
587 {
588 unsigned short other_mem = v;
589 if (EINA_UNLIKELY(v > eina_value_ushort_max))
590 return EINA_FALSE;
591 return eina_value_type_pset(convert, convert_mem, &other_mem);
592 }
593 else if (convert == EINA_VALUE_TYPE_UINT)
594 {
595 unsigned int other_mem = v;
596 if (EINA_UNLIKELY(v > eina_value_uint_max))
597 return EINA_FALSE;
598 return eina_value_type_pset(convert, convert_mem, &other_mem);
599 }
600 else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP))
601 {
602 unsigned long other_mem = v;
603 return eina_value_type_pset(convert, convert_mem, &other_mem);
604 }
605 else if (convert == EINA_VALUE_TYPE_UINT64)
606 {
607 uint64_t other_mem = v;
608 return eina_value_type_pset(convert, convert_mem, &other_mem);
609 }
610 else if (convert == EINA_VALUE_TYPE_CHAR)
611 {
612 signed char other_mem = v;
613 if (EINA_UNLIKELY(v > (unsigned char)eina_value_char_max))
614 return EINA_FALSE;
615 return eina_value_type_pset(convert, convert_mem, &other_mem);
616 }
617 else if (convert == EINA_VALUE_TYPE_SHORT)
618 {
619 short other_mem = v;
620 if (EINA_UNLIKELY(v > (unsigned short)eina_value_short_max))
621 return EINA_FALSE;
622 return eina_value_type_pset(convert, convert_mem, &other_mem);
623 }
624 else if ((convert == EINA_VALUE_TYPE_INT) || (convert == EINA_VALUE_TYPE_ERROR))
625 {
626 int other_mem = v;
627 if (EINA_UNLIKELY(v > (unsigned int)eina_value_int_max))
628 return EINA_FALSE;
629 return eina_value_type_pset(convert, convert_mem, &other_mem);
630 }
631 else if (convert == EINA_VALUE_TYPE_LONG)
632 {
633 long other_mem = v;
634 if (EINA_UNLIKELY(v > (unsigned long)eina_value_long_max))
635 return EINA_FALSE;
636 return eina_value_type_pset(convert, convert_mem, &other_mem);
637 }
638 else if (convert == EINA_VALUE_TYPE_INT64)
639 {
640 int64_t other_mem = v;
641 return eina_value_type_pset(convert, convert_mem, &other_mem);
642 }
643 else if (convert == EINA_VALUE_TYPE_FLOAT)
644 {
645 float other_mem = v;
646 return eina_value_type_pset(convert, convert_mem, &other_mem);
647 }
648 else if (convert == EINA_VALUE_TYPE_DOUBLE)
649 {
650 double other_mem = v;
651 return eina_value_type_pset(convert, convert_mem, &other_mem);
652 }
653 else if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
654 convert == EINA_VALUE_TYPE_STRING)
655 {
656 const char *other_mem;
657 char buf[64];
658 snprintf(buf, sizeof(buf), "%lu", v);
659 other_mem = buf; /* required due &buf == buf */
660 return eina_value_type_pset(convert, convert_mem, &other_mem);
661 }
662 else
663 {
664 return EINA_FALSE;
665 }
666
667 return EINA_TRUE;
668 }
669
670 static Eina_Bool
_eina_value_type_ulong_vset(const Eina_Value_Type * type EINA_UNUSED,void * mem,va_list args)671 _eina_value_type_ulong_vset(const Eina_Value_Type *type EINA_UNUSED, void *mem, va_list args)
672 {
673 unsigned long *tmem = mem;
674 *tmem = va_arg(args, unsigned long);
675 return EINA_TRUE;
676 }
677
678 static Eina_Bool
_eina_value_type_ulong_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)679 _eina_value_type_ulong_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
680 {
681 unsigned long *tmem = mem;
682 const unsigned long *p = ptr;
683 *tmem = *p;
684 return EINA_TRUE;
685 }
686
687 static Eina_Bool
_eina_value_type_ulong_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)688 _eina_value_type_ulong_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
689 {
690 const unsigned long *tmem = mem;
691 unsigned long *p = ptr;
692 *p = *tmem;
693 return EINA_TRUE;
694 }
695
696 static Eina_Bool
_eina_value_type_uint64_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)697 _eina_value_type_uint64_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
698 {
699 uint64_t *tmem = mem;
700 *tmem = 0;
701 return EINA_TRUE;
702 }
703
704 static Eina_Bool
_eina_value_type_uint64_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem EINA_UNUSED)705 _eina_value_type_uint64_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem EINA_UNUSED)
706 {
707 return EINA_TRUE;
708 }
709
710 static Eina_Bool
_eina_value_type_uint64_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)711 _eina_value_type_uint64_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
712 {
713 const uint64_t *s = src;
714 uint64_t *d = dst;
715 *d = *s;
716 return EINA_TRUE;
717 }
718
719 static int
_eina_value_type_uint64_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)720 _eina_value_type_uint64_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
721 {
722 const uint64_t *ta = a, *tb = b;
723 if (*ta < *tb)
724 return -1;
725 else if (*ta > *tb)
726 return 1;
727 return 0;
728 }
729
730 static Eina_Bool
_eina_value_type_uint64_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)731 _eina_value_type_uint64_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
732 {
733 const uint64_t v = *(const uint64_t *)type_mem;
734
735 if (convert == EINA_VALUE_TYPE_UCHAR)
736 {
737 unsigned char other_mem = v;
738 if (EINA_UNLIKELY(v > eina_value_uchar_max))
739 return EINA_FALSE;
740 return eina_value_type_pset(convert, convert_mem, &other_mem);
741 }
742 else if (convert == EINA_VALUE_TYPE_USHORT)
743 {
744 unsigned short other_mem = v;
745 if (EINA_UNLIKELY(v > eina_value_ushort_max))
746 return EINA_FALSE;
747 return eina_value_type_pset(convert, convert_mem, &other_mem);
748 }
749 else if (convert == EINA_VALUE_TYPE_UINT)
750 {
751 unsigned int other_mem = v;
752 if (EINA_UNLIKELY(v > eina_value_uint_max))
753 return EINA_FALSE;
754 return eina_value_type_pset(convert, convert_mem, &other_mem);
755 }
756 else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP))
757 {
758 unsigned long other_mem = v;
759 if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) &&
760 (v > eina_value_ulong_max)))
761 return EINA_FALSE;
762 return eina_value_type_pset(convert, convert_mem, &other_mem);
763 }
764 else if (convert == EINA_VALUE_TYPE_UINT64)
765 {
766 uint64_t other_mem = v;
767 return eina_value_type_pset(convert, convert_mem, &other_mem);
768 }
769 else if (convert == EINA_VALUE_TYPE_CHAR)
770 {
771 signed char other_mem = v;
772 if (EINA_UNLIKELY(v > (unsigned char)eina_value_char_max))
773 return EINA_FALSE;
774 return eina_value_type_pset(convert, convert_mem, &other_mem);
775 }
776 else if (convert == EINA_VALUE_TYPE_SHORT)
777 {
778 short other_mem = v;
779 if (EINA_UNLIKELY(v > (unsigned short)eina_value_short_max))
780 return EINA_FALSE;
781 return eina_value_type_pset(convert, convert_mem, &other_mem);
782 }
783 else if ((convert == EINA_VALUE_TYPE_INT) || (convert == EINA_VALUE_TYPE_ERROR))
784 {
785 int other_mem = v;
786 if (EINA_UNLIKELY(v > (unsigned int)eina_value_int_max))
787 return EINA_FALSE;
788 return eina_value_type_pset(convert, convert_mem, &other_mem);
789 }
790 else if (convert == EINA_VALUE_TYPE_LONG)
791 {
792 long other_mem = v;
793 if (EINA_UNLIKELY(v > (unsigned long)eina_value_long_max))
794 return EINA_FALSE;
795 return eina_value_type_pset(convert, convert_mem, &other_mem);
796 }
797 else if (convert == EINA_VALUE_TYPE_INT64)
798 {
799 int64_t other_mem = v;
800 if (EINA_UNLIKELY(v > (uint64_t)eina_value_int64_max))
801 return EINA_FALSE;
802 return eina_value_type_pset(convert, convert_mem, &other_mem);
803 }
804 else if (convert == EINA_VALUE_TYPE_FLOAT)
805 {
806 float other_mem = v;
807 return eina_value_type_pset(convert, convert_mem, &other_mem);
808 }
809 else if (convert == EINA_VALUE_TYPE_DOUBLE)
810 {
811 double other_mem = v;
812 return eina_value_type_pset(convert, convert_mem, &other_mem);
813 }
814 else if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
815 convert == EINA_VALUE_TYPE_STRING)
816 {
817 const char *other_mem;
818 char buf[64];
819 snprintf(buf, sizeof(buf), "%"PRIu64, v);
820 other_mem = buf; /* required due &buf == buf */
821 return eina_value_type_pset(convert, convert_mem, &other_mem);
822 }
823 else
824 {
825 return EINA_FALSE;
826 }
827
828 return EINA_TRUE;
829 }
830
831 static Eina_Bool
_eina_value_type_uint64_vset(const Eina_Value_Type * type EINA_UNUSED,void * mem,va_list args)832 _eina_value_type_uint64_vset(const Eina_Value_Type *type EINA_UNUSED, void *mem, va_list args)
833 {
834 uint64_t *tmem = mem;
835 *tmem = va_arg(args, uint64_t);
836 return EINA_TRUE;
837 }
838
839 static Eina_Bool
_eina_value_type_uint64_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)840 _eina_value_type_uint64_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
841 {
842 uint64_t *tmem = mem;
843 const uint64_t *p = ptr;
844 *tmem = *p;
845 return EINA_TRUE;
846 }
847
848 static Eina_Bool
_eina_value_type_uint64_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)849 _eina_value_type_uint64_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
850 {
851 const uint64_t *tmem = mem;
852 uint64_t *p = ptr;
853 *p = *tmem;
854 return EINA_TRUE;
855 }
856
857 static Eina_Bool
_eina_value_type_char_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)858 _eina_value_type_char_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
859 {
860 char *tmem = mem;
861 *tmem = 0;
862 return EINA_TRUE;
863 }
864
865 static Eina_Bool
_eina_value_type_char_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem EINA_UNUSED)866 _eina_value_type_char_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem EINA_UNUSED)
867 {
868 return EINA_TRUE;
869 }
870
871 static Eina_Bool
_eina_value_type_char_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)872 _eina_value_type_char_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
873 {
874 const char *s = src;
875 char *d = dst;
876 *d = *s;
877 return EINA_TRUE;
878 }
879
880 static int
_eina_value_type_char_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)881 _eina_value_type_char_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
882 {
883 const char *ta = a, *tb = b;
884 if (*ta < *tb)
885 return -1;
886 else if (*ta > *tb)
887 return 1;
888 return 0;
889 }
890
891 static Eina_Bool
_eina_value_type_char_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)892 _eina_value_type_char_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
893 {
894 const signed char v = *(const signed char *)type_mem;
895
896 if (convert == EINA_VALUE_TYPE_UCHAR)
897 {
898 unsigned char other_mem = v;
899 if (EINA_UNLIKELY(v < 0))
900 return EINA_FALSE;
901 return eina_value_type_pset(convert, convert_mem, &other_mem);
902 }
903 else if (convert == EINA_VALUE_TYPE_USHORT)
904 {
905 unsigned short other_mem = v;
906 if (EINA_UNLIKELY(v < 0))
907 return EINA_FALSE;
908 return eina_value_type_pset(convert, convert_mem, &other_mem);
909 }
910 else if (convert == EINA_VALUE_TYPE_UINT)
911 {
912 unsigned int other_mem = v;
913 if (EINA_UNLIKELY(v < 0))
914 return EINA_FALSE;
915 return eina_value_type_pset(convert, convert_mem, &other_mem);
916 }
917 else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP))
918 {
919 unsigned long other_mem = v;
920 if (EINA_UNLIKELY(v < 0))
921 return EINA_FALSE;
922 return eina_value_type_pset(convert, convert_mem, &other_mem);
923 }
924 else if (convert == EINA_VALUE_TYPE_UINT64)
925 {
926 uint64_t other_mem = v;
927 if (EINA_UNLIKELY(v < 0))
928 return EINA_FALSE;
929 return eina_value_type_pset(convert, convert_mem, &other_mem);
930 }
931 else if (convert == EINA_VALUE_TYPE_CHAR)
932 {
933 signed char other_mem = v;
934 return eina_value_type_pset(convert, convert_mem, &other_mem);
935 }
936 else if (convert == EINA_VALUE_TYPE_SHORT)
937 {
938 short other_mem = v;
939 return eina_value_type_pset(convert, convert_mem, &other_mem);
940 }
941 else if ((convert == EINA_VALUE_TYPE_INT) || (convert == EINA_VALUE_TYPE_ERROR))
942 {
943 int other_mem = v;
944 return eina_value_type_pset(convert, convert_mem, &other_mem);
945 }
946 else if (convert == EINA_VALUE_TYPE_LONG)
947 {
948 long other_mem = v;
949 return eina_value_type_pset(convert, convert_mem, &other_mem);
950 }
951 else if (convert == EINA_VALUE_TYPE_INT64)
952 {
953 int64_t other_mem = v;
954 return eina_value_type_pset(convert, convert_mem, &other_mem);
955 }
956 else if (convert == EINA_VALUE_TYPE_FLOAT)
957 {
958 float other_mem = v;
959 return eina_value_type_pset(convert, convert_mem, &other_mem);
960 }
961 else if (convert == EINA_VALUE_TYPE_DOUBLE)
962 {
963 double other_mem = v;
964 return eina_value_type_pset(convert, convert_mem, &other_mem);
965 }
966 else if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
967 convert == EINA_VALUE_TYPE_STRING)
968 {
969 const char *other_mem;
970 char buf[64];
971 snprintf(buf, sizeof(buf), "%hhd", v);
972 other_mem = buf; /* required due &buf == buf */
973 return eina_value_type_pset(convert, convert_mem, &other_mem);
974 }
975 else
976 {
977 return EINA_FALSE;
978 }
979
980 return EINA_TRUE;
981 }
982
983 static Eina_Bool
_eina_value_type_char_vset(const Eina_Value_Type * type EINA_UNUSED,void * mem,va_list args)984 _eina_value_type_char_vset(const Eina_Value_Type *type EINA_UNUSED, void *mem, va_list args)
985 {
986 char *tmem = mem;
987 *tmem = va_arg(args, int); /* char is promoted to int for va_arg */
988 return EINA_TRUE;
989 }
990
991 static Eina_Bool
_eina_value_type_char_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)992 _eina_value_type_char_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
993 {
994 char *tmem = mem;
995 const char *p = ptr;
996 *tmem = *p;
997 return EINA_TRUE;
998 }
999
1000 static Eina_Bool
_eina_value_type_char_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)1001 _eina_value_type_char_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
1002 {
1003 const char *tmem = mem;
1004 char *p = ptr;
1005 *p = *tmem;
1006 return EINA_TRUE;
1007 }
1008
1009 static Eina_Bool
_eina_value_type_short_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)1010 _eina_value_type_short_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
1011 {
1012 short *tmem = mem;
1013 *tmem = 0;
1014 return EINA_TRUE;
1015 }
1016
1017 static Eina_Bool
_eina_value_type_short_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem EINA_UNUSED)1018 _eina_value_type_short_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem EINA_UNUSED)
1019 {
1020 return EINA_TRUE;
1021 }
1022
1023 static Eina_Bool
_eina_value_type_short_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)1024 _eina_value_type_short_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
1025 {
1026 const short *s = src;
1027 short *d = dst;
1028 *d = *s;
1029 return EINA_TRUE;
1030 }
1031
1032 static int
_eina_value_type_short_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)1033 _eina_value_type_short_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
1034 {
1035 const short *ta = a, *tb = b;
1036 if (*ta < *tb)
1037 return -1;
1038 else if (*ta > *tb)
1039 return 1;
1040 return 0;
1041 }
1042
1043 static Eina_Bool
_eina_value_type_short_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)1044 _eina_value_type_short_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
1045 {
1046 const short v = *(const short *)type_mem;
1047
1048 if (convert == EINA_VALUE_TYPE_UCHAR)
1049 {
1050 unsigned char other_mem = v;
1051 if (EINA_UNLIKELY(v < 0))
1052 return EINA_FALSE;
1053 if (EINA_UNLIKELY(v > eina_value_uchar_max))
1054 return EINA_FALSE;
1055 return eina_value_type_pset(convert, convert_mem, &other_mem);
1056 }
1057 else if (convert == EINA_VALUE_TYPE_USHORT)
1058 {
1059 unsigned short other_mem = v;
1060 if (EINA_UNLIKELY(v < 0))
1061 return EINA_FALSE;
1062 return eina_value_type_pset(convert, convert_mem, &other_mem);
1063 }
1064 else if (convert == EINA_VALUE_TYPE_UINT)
1065 {
1066 unsigned int other_mem = v;
1067 if (EINA_UNLIKELY(v < 0))
1068 return EINA_FALSE;
1069 return eina_value_type_pset(convert, convert_mem, &other_mem);
1070 }
1071 else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP))
1072 {
1073 unsigned long other_mem = v;
1074 if (EINA_UNLIKELY(v < 0))
1075 return EINA_FALSE;
1076 return eina_value_type_pset(convert, convert_mem, &other_mem);
1077 }
1078 else if (convert == EINA_VALUE_TYPE_UINT64)
1079 {
1080 uint64_t other_mem = v;
1081 if (EINA_UNLIKELY(v < 0))
1082 return EINA_FALSE;
1083 return eina_value_type_pset(convert, convert_mem, &other_mem);
1084 }
1085 else if (convert == EINA_VALUE_TYPE_CHAR)
1086 {
1087 signed char other_mem = v;
1088 if (EINA_UNLIKELY(v < eina_value_char_min))
1089 return EINA_FALSE;
1090 if (EINA_UNLIKELY(v > eina_value_char_max))
1091 return EINA_FALSE;
1092 return eina_value_type_pset(convert, convert_mem, &other_mem);
1093 }
1094 else if (convert == EINA_VALUE_TYPE_SHORT)
1095 {
1096 short other_mem = v;
1097 return eina_value_type_pset(convert, convert_mem, &other_mem);
1098 }
1099 else if ((convert == EINA_VALUE_TYPE_INT) || (convert == EINA_VALUE_TYPE_ERROR))
1100 {
1101 int other_mem = v;
1102 return eina_value_type_pset(convert, convert_mem, &other_mem);
1103 }
1104 else if (convert == EINA_VALUE_TYPE_LONG)
1105 {
1106 long other_mem = v;
1107 return eina_value_type_pset(convert, convert_mem, &other_mem);
1108 }
1109 else if (convert == EINA_VALUE_TYPE_INT64)
1110 {
1111 int64_t other_mem = v;
1112 return eina_value_type_pset(convert, convert_mem, &other_mem);
1113 }
1114 else if (convert == EINA_VALUE_TYPE_FLOAT)
1115 {
1116 float other_mem = v;
1117 return eina_value_type_pset(convert, convert_mem, &other_mem);
1118 }
1119 else if (convert == EINA_VALUE_TYPE_DOUBLE)
1120 {
1121 double other_mem = v;
1122 return eina_value_type_pset(convert, convert_mem, &other_mem);
1123 }
1124 else if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
1125 convert == EINA_VALUE_TYPE_STRING)
1126 {
1127 const char *other_mem;
1128 char buf[64];
1129 snprintf(buf, sizeof(buf), "%hd", v);
1130 other_mem = buf; /* required due &buf == buf */
1131 return eina_value_type_pset(convert, convert_mem, &other_mem);
1132 }
1133 else
1134 {
1135 return EINA_FALSE;
1136 }
1137
1138 return EINA_TRUE;
1139 }
1140
1141 static Eina_Bool
_eina_value_type_short_vset(const Eina_Value_Type * type EINA_UNUSED,void * mem,va_list args)1142 _eina_value_type_short_vset(const Eina_Value_Type *type EINA_UNUSED, void *mem, va_list args)
1143 {
1144 short *tmem = mem;
1145 *tmem = va_arg(args, int); /* short int is promoted to int for va_arg */
1146 return EINA_TRUE;
1147 }
1148
1149 static Eina_Bool
_eina_value_type_short_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)1150 _eina_value_type_short_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
1151 {
1152 short *tmem = mem;
1153 const short *p = ptr;
1154 *tmem = *p;
1155 return EINA_TRUE;
1156 }
1157
1158 static Eina_Bool
_eina_value_type_short_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)1159 _eina_value_type_short_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
1160 {
1161 const short *tmem = mem;
1162 short *p = ptr;
1163 *p = *tmem;
1164 return EINA_TRUE;
1165 }
1166
1167 static Eina_Bool
_eina_value_type_int_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)1168 _eina_value_type_int_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
1169 {
1170 int *tmem = mem;
1171 *tmem = 0;
1172 return EINA_TRUE;
1173 }
1174
1175 static Eina_Bool
_eina_value_type_int_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem EINA_UNUSED)1176 _eina_value_type_int_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem EINA_UNUSED)
1177 {
1178 return EINA_TRUE;
1179 }
1180
1181 static Eina_Bool
_eina_value_type_int_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)1182 _eina_value_type_int_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
1183 {
1184 const int *s = src;
1185 int *d = dst;
1186 *d = *s;
1187 return EINA_TRUE;
1188 }
1189
1190 static int
_eina_value_type_int_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)1191 _eina_value_type_int_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
1192 {
1193 const int *ta = a, *tb = b;
1194 if (*ta < *tb)
1195 return -1;
1196 else if (*ta > *tb)
1197 return 1;
1198 return 0;
1199 }
1200
1201 static Eina_Bool
_eina_value_type_int_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)1202 _eina_value_type_int_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
1203 {
1204 const int v = *(const int *)type_mem;
1205
1206 if (convert == EINA_VALUE_TYPE_UCHAR)
1207 {
1208 unsigned char other_mem = v;
1209 if (EINA_UNLIKELY(v < 0))
1210 return EINA_FALSE;
1211 if (EINA_UNLIKELY(v > eina_value_uchar_max))
1212 return EINA_FALSE;
1213 return eina_value_type_pset(convert, convert_mem, &other_mem);
1214 }
1215 else if (convert == EINA_VALUE_TYPE_USHORT)
1216 {
1217 unsigned short other_mem = v;
1218 if (EINA_UNLIKELY(v < 0))
1219 return EINA_FALSE;
1220 if (EINA_UNLIKELY(v > eina_value_ushort_max))
1221 return EINA_FALSE;
1222 return eina_value_type_pset(convert, convert_mem, &other_mem);
1223 }
1224 else if (convert == EINA_VALUE_TYPE_UINT)
1225 {
1226 unsigned int other_mem = v;
1227 if (EINA_UNLIKELY(v < 0))
1228 return EINA_FALSE;
1229 return eina_value_type_pset(convert, convert_mem, &other_mem);
1230 }
1231 else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP))
1232 {
1233 unsigned long other_mem = v;
1234 if (EINA_UNLIKELY(v < 0))
1235 return EINA_FALSE;
1236 return eina_value_type_pset(convert, convert_mem, &other_mem);
1237 }
1238 else if (convert == EINA_VALUE_TYPE_UINT64)
1239 {
1240 uint64_t other_mem = v;
1241 if (EINA_UNLIKELY(v < 0))
1242 return EINA_FALSE;
1243 return eina_value_type_pset(convert, convert_mem, &other_mem);
1244 }
1245 else if (convert == EINA_VALUE_TYPE_CHAR)
1246 {
1247 signed char other_mem = v;
1248 if (EINA_UNLIKELY(v < eina_value_char_min))
1249 return EINA_FALSE;
1250 if (EINA_UNLIKELY(v > eina_value_char_max))
1251 return EINA_FALSE;
1252 return eina_value_type_pset(convert, convert_mem, &other_mem);
1253 }
1254 else if (convert == EINA_VALUE_TYPE_SHORT)
1255 {
1256 short other_mem = v;
1257 if (EINA_UNLIKELY(v < eina_value_short_min))
1258 return EINA_FALSE;
1259 if (EINA_UNLIKELY(v > eina_value_short_max))
1260 return EINA_FALSE;
1261 return eina_value_type_pset(convert, convert_mem, &other_mem);
1262 }
1263 else if ((convert == EINA_VALUE_TYPE_INT) || (convert == EINA_VALUE_TYPE_ERROR))
1264 {
1265 int other_mem = v;
1266 return eina_value_type_pset(convert, convert_mem, &other_mem);
1267 }
1268 else if (convert == EINA_VALUE_TYPE_LONG)
1269 {
1270 long other_mem = v;
1271 return eina_value_type_pset(convert, convert_mem, &other_mem);
1272 }
1273 else if (convert == EINA_VALUE_TYPE_INT64)
1274 {
1275 int64_t other_mem = v;
1276 return eina_value_type_pset(convert, convert_mem, &other_mem);
1277 }
1278 else if (convert == EINA_VALUE_TYPE_FLOAT)
1279 {
1280 float other_mem = v;
1281 return eina_value_type_pset(convert, convert_mem, &other_mem);
1282 }
1283 else if (convert == EINA_VALUE_TYPE_DOUBLE)
1284 {
1285 double other_mem = v;
1286 return eina_value_type_pset(convert, convert_mem, &other_mem);
1287 }
1288 else if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
1289 convert == EINA_VALUE_TYPE_STRING)
1290 {
1291 const char *other_mem;
1292 char buf[64];
1293 snprintf(buf, sizeof(buf), "%d", v);
1294 other_mem = buf; /* required due &buf == buf */
1295 return eina_value_type_pset(convert, convert_mem, &other_mem);
1296 }
1297 else
1298 {
1299 return EINA_FALSE;
1300 }
1301
1302 return EINA_TRUE;
1303 }
1304
1305 static Eina_Bool
_eina_value_type_int_vset(const Eina_Value_Type * type EINA_UNUSED,void * mem,va_list args)1306 _eina_value_type_int_vset(const Eina_Value_Type *type EINA_UNUSED, void *mem, va_list args)
1307 {
1308 int *tmem = mem;
1309 *tmem = va_arg(args, int);
1310 return EINA_TRUE;
1311 }
1312
1313 static Eina_Bool
_eina_value_type_int_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)1314 _eina_value_type_int_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
1315 {
1316 int *tmem = mem;
1317 const int *p = ptr;
1318 *tmem = *p;
1319 return EINA_TRUE;
1320 }
1321
1322 static Eina_Bool
_eina_value_type_int_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)1323 _eina_value_type_int_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
1324 {
1325 const int *tmem = mem;
1326 int *p = ptr;
1327 *p = *tmem;
1328 return EINA_TRUE;
1329 }
1330
1331 static Eina_Bool
_eina_value_type_long_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)1332 _eina_value_type_long_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
1333 {
1334 long *tmem = mem;
1335 *tmem = 0;
1336 return EINA_TRUE;
1337 }
1338
1339 static Eina_Bool
_eina_value_type_long_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem EINA_UNUSED)1340 _eina_value_type_long_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem EINA_UNUSED)
1341 {
1342 return EINA_TRUE;
1343 }
1344
1345 static Eina_Bool
_eina_value_type_long_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)1346 _eina_value_type_long_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
1347 {
1348 const long *s = src;
1349 long *d = dst;
1350 *d = *s;
1351 return EINA_TRUE;
1352 }
1353
1354 static int
_eina_value_type_long_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)1355 _eina_value_type_long_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
1356 {
1357 const long *ta = a, *tb = b;
1358 if (*ta < *tb)
1359 return -1;
1360 else if (*ta > *tb)
1361 return 1;
1362 return 0;
1363 }
1364
1365 static Eina_Bool
_eina_value_type_long_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)1366 _eina_value_type_long_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
1367 {
1368 const long v = *(const long *)type_mem;
1369
1370 if (convert == EINA_VALUE_TYPE_UCHAR)
1371 {
1372 unsigned char other_mem = v;
1373 if (EINA_UNLIKELY(v < 0))
1374 return EINA_FALSE;
1375 if (EINA_UNLIKELY((unsigned long) v > eina_value_uchar_max))
1376 return EINA_FALSE;
1377 return eina_value_type_pset(convert, convert_mem, &other_mem);
1378 }
1379 else if (convert == EINA_VALUE_TYPE_USHORT)
1380 {
1381 unsigned short other_mem = v;
1382 if (EINA_UNLIKELY(v < 0))
1383 return EINA_FALSE;
1384 if (EINA_UNLIKELY((unsigned long) v > eina_value_ushort_max))
1385 return EINA_FALSE;
1386 return eina_value_type_pset(convert, convert_mem, &other_mem);
1387 }
1388 else if (convert == EINA_VALUE_TYPE_UINT)
1389 {
1390 unsigned int other_mem = v;
1391 if (EINA_UNLIKELY(v < 0))
1392 return EINA_FALSE;
1393 if (EINA_UNLIKELY((unsigned long) v > eina_value_uint_max))
1394 return EINA_FALSE;
1395 return eina_value_type_pset(convert, convert_mem, &other_mem);
1396 }
1397 else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP))
1398 {
1399 unsigned long other_mem = v;
1400 if (EINA_UNLIKELY(v < 0))
1401 return EINA_FALSE;
1402 return eina_value_type_pset(convert, convert_mem, &other_mem);
1403 }
1404 else if (convert == EINA_VALUE_TYPE_UINT64)
1405 {
1406 uint64_t other_mem = v;
1407 if (EINA_UNLIKELY(v < 0))
1408 return EINA_FALSE;
1409 return eina_value_type_pset(convert, convert_mem, &other_mem);
1410 }
1411 else if (convert == EINA_VALUE_TYPE_CHAR)
1412 {
1413 signed char other_mem = v;
1414 if (EINA_UNLIKELY(v < eina_value_char_min))
1415 return EINA_FALSE;
1416 if (EINA_UNLIKELY(v > eina_value_char_max))
1417 return EINA_FALSE;
1418 return eina_value_type_pset(convert, convert_mem, &other_mem);
1419 }
1420 else if (convert == EINA_VALUE_TYPE_SHORT)
1421 {
1422 short other_mem = v;
1423 if (EINA_UNLIKELY(v < eina_value_short_min))
1424 return EINA_FALSE;
1425 if (EINA_UNLIKELY(v > eina_value_short_max))
1426 return EINA_FALSE;
1427 return eina_value_type_pset(convert, convert_mem, &other_mem);
1428 }
1429 else if ((convert == EINA_VALUE_TYPE_INT) || (convert == EINA_VALUE_TYPE_ERROR))
1430 {
1431 int other_mem = v;
1432 if (EINA_UNLIKELY(v < eina_value_int_min))
1433 return EINA_FALSE;
1434 if (EINA_UNLIKELY(v > eina_value_int_max))
1435 return EINA_FALSE;
1436 return eina_value_type_pset(convert, convert_mem, &other_mem);
1437 }
1438 else if (convert == EINA_VALUE_TYPE_LONG)
1439 {
1440 long other_mem = v;
1441 return eina_value_type_pset(convert, convert_mem, &other_mem);
1442 }
1443 else if (convert == EINA_VALUE_TYPE_INT64)
1444 {
1445 int64_t other_mem = v;
1446 return eina_value_type_pset(convert, convert_mem, &other_mem);
1447 }
1448 else if (convert == EINA_VALUE_TYPE_FLOAT)
1449 {
1450 float other_mem = v;
1451 return eina_value_type_pset(convert, convert_mem, &other_mem);
1452 }
1453 else if (convert == EINA_VALUE_TYPE_DOUBLE)
1454 {
1455 double other_mem = v;
1456 return eina_value_type_pset(convert, convert_mem, &other_mem);
1457 }
1458 else if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
1459 convert == EINA_VALUE_TYPE_STRING)
1460 {
1461 const char *other_mem;
1462 char buf[64];
1463 snprintf(buf, sizeof(buf), "%ld", v);
1464 other_mem = buf; /* required due &buf == buf */
1465 return eina_value_type_pset(convert, convert_mem, &other_mem);
1466 }
1467 else
1468 {
1469 return EINA_FALSE;
1470 }
1471
1472 return EINA_TRUE;
1473 }
1474
1475 static Eina_Bool
_eina_value_type_long_vset(const Eina_Value_Type * type EINA_UNUSED,void * mem,va_list args)1476 _eina_value_type_long_vset(const Eina_Value_Type *type EINA_UNUSED, void *mem, va_list args)
1477 {
1478 long *tmem = mem;
1479 *tmem = va_arg(args, long);
1480 return EINA_TRUE;
1481 }
1482
1483 static Eina_Bool
_eina_value_type_long_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)1484 _eina_value_type_long_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
1485 {
1486 long *tmem = mem;
1487 const long *p = ptr;
1488 *tmem = *p;
1489 return EINA_TRUE;
1490 }
1491
1492 static Eina_Bool
_eina_value_type_long_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)1493 _eina_value_type_long_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
1494 {
1495 const long *tmem = mem;
1496 long *p = ptr;
1497 *p = *tmem;
1498 return EINA_TRUE;
1499 }
1500
1501 static Eina_Bool
_eina_value_type_int64_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)1502 _eina_value_type_int64_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
1503 {
1504 int64_t *tmem = mem;
1505 *tmem = 0;
1506 return EINA_TRUE;
1507 }
1508
1509 static Eina_Bool
_eina_value_type_int64_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem EINA_UNUSED)1510 _eina_value_type_int64_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem EINA_UNUSED)
1511 {
1512 return EINA_TRUE;
1513 }
1514
1515 static Eina_Bool
_eina_value_type_int64_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)1516 _eina_value_type_int64_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
1517 {
1518 const int64_t *s = src;
1519 int64_t *d = dst;
1520 *d = *s;
1521 return EINA_TRUE;
1522 }
1523
1524 static int
_eina_value_type_int64_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)1525 _eina_value_type_int64_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
1526 {
1527 const int64_t *ta = a, *tb = b;
1528 if (*ta < *tb)
1529 return -1;
1530 else if (*ta > *tb)
1531 return 1;
1532 return 0;
1533 }
1534
1535 static Eina_Bool
_eina_value_type_int64_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)1536 _eina_value_type_int64_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
1537 {
1538 const int64_t v = *(const int64_t *)type_mem;
1539
1540 if (convert == EINA_VALUE_TYPE_UCHAR)
1541 {
1542 unsigned char other_mem = v;
1543 if (EINA_UNLIKELY(v < 0))
1544 return EINA_FALSE;
1545 if (EINA_UNLIKELY(v > eina_value_uchar_max))
1546 return EINA_FALSE;
1547 return eina_value_type_pset(convert, convert_mem, &other_mem);
1548 }
1549 else if (convert == EINA_VALUE_TYPE_USHORT)
1550 {
1551 unsigned short other_mem = v;
1552 if (EINA_UNLIKELY(v < 0))
1553 return EINA_FALSE;
1554 if (EINA_UNLIKELY(v > eina_value_ushort_max))
1555 return EINA_FALSE;
1556 return eina_value_type_pset(convert, convert_mem, &other_mem);
1557 }
1558 else if (convert == EINA_VALUE_TYPE_UINT)
1559 {
1560 unsigned int other_mem = v;
1561 if (EINA_UNLIKELY(v < 0))
1562 return EINA_FALSE;
1563 if (EINA_UNLIKELY(v > eina_value_uint_max))
1564 return EINA_FALSE;
1565 return eina_value_type_pset(convert, convert_mem, &other_mem);
1566 }
1567 else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP))
1568 {
1569 unsigned long other_mem = v;
1570 if (EINA_UNLIKELY(v < 0))
1571 return EINA_FALSE;
1572 if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) &&
1573 (v > eina_value_ulong_max)))
1574 return EINA_FALSE;
1575 return eina_value_type_pset(convert, convert_mem, &other_mem);
1576 }
1577 else if (convert == EINA_VALUE_TYPE_UINT64)
1578 {
1579 uint64_t other_mem = v;
1580 if (EINA_UNLIKELY(v < 0))
1581 return EINA_FALSE;
1582 return eina_value_type_pset(convert, convert_mem, &other_mem);
1583 }
1584 else if (convert == EINA_VALUE_TYPE_CHAR)
1585 {
1586 signed char other_mem = v;
1587 if (EINA_UNLIKELY(v < eina_value_char_min))
1588 return EINA_FALSE;
1589 if (EINA_UNLIKELY(v > eina_value_char_max))
1590 return EINA_FALSE;
1591 return eina_value_type_pset(convert, convert_mem, &other_mem);
1592 }
1593 else if (convert == EINA_VALUE_TYPE_SHORT)
1594 {
1595 short other_mem = v;
1596 if (EINA_UNLIKELY(v < eina_value_short_min))
1597 return EINA_FALSE;
1598 if (EINA_UNLIKELY(v > eina_value_short_max))
1599 return EINA_FALSE;
1600 return eina_value_type_pset(convert, convert_mem, &other_mem);
1601 }
1602 else if ((convert == EINA_VALUE_TYPE_INT) || (convert == EINA_VALUE_TYPE_ERROR))
1603 {
1604 int other_mem = v;
1605 if (EINA_UNLIKELY(v < eina_value_int_min))
1606 return EINA_FALSE;
1607 if (EINA_UNLIKELY(v > eina_value_int_max))
1608 return EINA_FALSE;
1609 return eina_value_type_pset(convert, convert_mem, &other_mem);
1610 }
1611 else if (convert == EINA_VALUE_TYPE_LONG)
1612 {
1613 long other_mem = v;
1614 if (EINA_UNLIKELY(v < eina_value_long_min))
1615 return EINA_FALSE;
1616 if (EINA_UNLIKELY(v > eina_value_long_max))
1617 return EINA_FALSE;
1618 return eina_value_type_pset(convert, convert_mem, &other_mem);
1619 }
1620 else if (convert == EINA_VALUE_TYPE_INT64)
1621 {
1622 int64_t other_mem = v;
1623 return eina_value_type_pset(convert, convert_mem, &other_mem);
1624 }
1625 else if (convert == EINA_VALUE_TYPE_FLOAT)
1626 {
1627 float other_mem = v;
1628 return eina_value_type_pset(convert, convert_mem, &other_mem);
1629 }
1630 else if (convert == EINA_VALUE_TYPE_DOUBLE)
1631 {
1632 double other_mem = v;
1633 return eina_value_type_pset(convert, convert_mem, &other_mem);
1634 }
1635 else if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
1636 convert == EINA_VALUE_TYPE_STRING)
1637 {
1638 const char *other_mem;
1639 char buf[64];
1640 snprintf(buf, sizeof(buf), "%"PRId64, v);
1641 other_mem = buf; /* required due &buf == buf */
1642 return eina_value_type_pset(convert, convert_mem, &other_mem);
1643 }
1644 else
1645 {
1646 return EINA_FALSE;
1647 }
1648
1649 return EINA_TRUE;
1650 }
1651
1652 static Eina_Bool
_eina_value_type_int64_vset(const Eina_Value_Type * type EINA_UNUSED,void * mem,va_list args)1653 _eina_value_type_int64_vset(const Eina_Value_Type *type EINA_UNUSED, void *mem, va_list args)
1654 {
1655 int64_t *tmem = mem;
1656 *tmem = va_arg(args, int64_t);
1657 return EINA_TRUE;
1658 }
1659
1660 static Eina_Bool
_eina_value_type_int64_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)1661 _eina_value_type_int64_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
1662 {
1663 int64_t *tmem = mem;
1664 const int64_t *p = ptr;
1665 *tmem = *p;
1666 return EINA_TRUE;
1667 }
1668
1669 static Eina_Bool
_eina_value_type_int64_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)1670 _eina_value_type_int64_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
1671 {
1672 const int64_t *tmem = mem;
1673 int64_t *p = ptr;
1674 *p = *tmem;
1675 return EINA_TRUE;
1676 }
1677
1678 static Eina_Bool
_eina_value_type_float_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)1679 _eina_value_type_float_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
1680 {
1681 float *tmem = mem;
1682 *tmem = 0;
1683 return EINA_TRUE;
1684 }
1685
1686 static Eina_Bool
_eina_value_type_float_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem EINA_UNUSED)1687 _eina_value_type_float_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem EINA_UNUSED)
1688 {
1689 return EINA_TRUE;
1690 }
1691
1692 static Eina_Bool
_eina_value_type_float_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)1693 _eina_value_type_float_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
1694 {
1695 const float *s = src;
1696 float *d = dst;
1697 *d = *s;
1698 return EINA_TRUE;
1699 }
1700
1701 static int
_eina_value_type_float_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)1702 _eina_value_type_float_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
1703 {
1704 const float *ta = a, *tb = b;
1705 if (*ta < *tb)
1706 return -1;
1707 else if (*ta > *tb)
1708 return 1;
1709 return 0;
1710 }
1711
1712 static Eina_Bool
_eina_value_type_float_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)1713 _eina_value_type_float_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
1714 {
1715 const float v = *(const float *)type_mem;
1716
1717 if (convert == EINA_VALUE_TYPE_UCHAR)
1718 {
1719 unsigned char other_mem = v;
1720 if (EINA_UNLIKELY(v < 0))
1721 return EINA_FALSE;
1722 if (EINA_UNLIKELY(v > eina_value_uchar_max))
1723 return EINA_FALSE;
1724 return eina_value_type_pset(convert, convert_mem, &other_mem);
1725 }
1726 else if (convert == EINA_VALUE_TYPE_USHORT)
1727 {
1728 unsigned short other_mem = v;
1729 if (EINA_UNLIKELY(v < 0))
1730 return EINA_FALSE;
1731 if (EINA_UNLIKELY(v > eina_value_ushort_max))
1732 return EINA_FALSE;
1733 return eina_value_type_pset(convert, convert_mem, &other_mem);
1734 }
1735 else if (convert == EINA_VALUE_TYPE_UINT)
1736 {
1737 unsigned int other_mem = v;
1738 if (EINA_UNLIKELY(v < 0))
1739 return EINA_FALSE;
1740 if (EINA_UNLIKELY(v > eina_value_uint_max))
1741 return EINA_FALSE;
1742 return eina_value_type_pset(convert, convert_mem, &other_mem);
1743 }
1744 else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP))
1745 {
1746 unsigned long other_mem = v;
1747 if (EINA_UNLIKELY(v < 0))
1748 return EINA_FALSE;
1749 if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) &&
1750 (v > eina_value_ulong_max)))
1751 return EINA_FALSE;
1752 return eina_value_type_pset(convert, convert_mem, &other_mem);
1753 }
1754 else if (convert == EINA_VALUE_TYPE_UINT64)
1755 {
1756 uint64_t other_mem = v;
1757 if (EINA_UNLIKELY(v < 0))
1758 return EINA_FALSE;
1759 if (EINA_UNLIKELY(v > eina_value_uint64_max))
1760 return EINA_FALSE;
1761 return eina_value_type_pset(convert, convert_mem, &other_mem);
1762 }
1763 else if (convert == EINA_VALUE_TYPE_CHAR)
1764 {
1765 signed char other_mem = v;
1766 if (EINA_UNLIKELY(v < eina_value_char_min))
1767 return EINA_FALSE;
1768 if (EINA_UNLIKELY(v > eina_value_char_max))
1769 return EINA_FALSE;
1770 return eina_value_type_pset(convert, convert_mem, &other_mem);
1771 }
1772 else if (convert == EINA_VALUE_TYPE_SHORT)
1773 {
1774 short other_mem = v;
1775 if (EINA_UNLIKELY(v < eina_value_short_min))
1776 return EINA_FALSE;
1777 if (EINA_UNLIKELY(v > eina_value_short_max))
1778 return EINA_FALSE;
1779 return eina_value_type_pset(convert, convert_mem, &other_mem);
1780 }
1781 else if ((convert == EINA_VALUE_TYPE_INT) || (convert == EINA_VALUE_TYPE_ERROR))
1782 {
1783 int other_mem = v;
1784 if (EINA_UNLIKELY(v < eina_value_int_min))
1785 return EINA_FALSE;
1786 if (EINA_UNLIKELY(v > eina_value_int_max))
1787 return EINA_FALSE;
1788 return eina_value_type_pset(convert, convert_mem, &other_mem);
1789 }
1790 else if (convert == EINA_VALUE_TYPE_LONG)
1791 {
1792 long other_mem = v;
1793 if (EINA_UNLIKELY(v < eina_value_long_min))
1794 return EINA_FALSE;
1795 if (EINA_UNLIKELY(v > eina_value_long_max))
1796 return EINA_FALSE;
1797 return eina_value_type_pset(convert, convert_mem, &other_mem);
1798 }
1799 else if (convert == EINA_VALUE_TYPE_INT64)
1800 {
1801 int64_t other_mem = v;
1802 if (EINA_UNLIKELY(v < eina_value_int64_min))
1803 return EINA_FALSE;
1804 if (EINA_UNLIKELY(v > eina_value_int64_max))
1805 return EINA_FALSE;
1806 return eina_value_type_pset(convert, convert_mem, &other_mem);
1807 }
1808 else if (convert == EINA_VALUE_TYPE_FLOAT)
1809 {
1810 float other_mem = v;
1811 return eina_value_type_pset(convert, convert_mem, &other_mem);
1812 }
1813 else if (convert == EINA_VALUE_TYPE_DOUBLE)
1814 {
1815 double other_mem = v;
1816 return eina_value_type_pset(convert, convert_mem, &other_mem);
1817 }
1818 else if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
1819 convert == EINA_VALUE_TYPE_STRING)
1820 {
1821 const char *other_mem;
1822 char buf[64];
1823 snprintf(buf, sizeof(buf), "%f", v);
1824 other_mem = buf; /* required due &buf == buf */
1825 return eina_value_type_pset(convert, convert_mem, &other_mem);
1826 }
1827 else
1828 {
1829 return EINA_FALSE;
1830 }
1831
1832 return EINA_TRUE;
1833 }
1834
1835 static Eina_Bool
_eina_value_type_float_vset(const Eina_Value_Type * type EINA_UNUSED,void * mem,va_list args)1836 _eina_value_type_float_vset(const Eina_Value_Type *type EINA_UNUSED, void *mem, va_list args)
1837 {
1838 float *tmem = mem;
1839 *tmem = va_arg(args, double); /* float is promoted to double for va_args */
1840 return EINA_TRUE;
1841 }
1842
1843 static Eina_Bool
_eina_value_type_float_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)1844 _eina_value_type_float_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
1845 {
1846 float *tmem = mem;
1847 const float *p = ptr;
1848 *tmem = *p;
1849 return EINA_TRUE;
1850 }
1851
1852 static Eina_Bool
_eina_value_type_float_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)1853 _eina_value_type_float_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
1854 {
1855 const float *tmem = mem;
1856 float *p = ptr;
1857 *p = *tmem;
1858 return EINA_TRUE;
1859 }
1860
1861 static Eina_Bool
_eina_value_type_double_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)1862 _eina_value_type_double_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
1863 {
1864 double *tmem = mem;
1865 *tmem = 0;
1866 return EINA_TRUE;
1867 }
1868
1869 static Eina_Bool
_eina_value_type_double_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem EINA_UNUSED)1870 _eina_value_type_double_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem EINA_UNUSED)
1871 {
1872 return EINA_TRUE;
1873 }
1874
1875 static Eina_Bool
_eina_value_type_double_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)1876 _eina_value_type_double_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
1877 {
1878 const double *s = src;
1879 double *d = dst;
1880 *d = *s;
1881 return EINA_TRUE;
1882 }
1883
1884 static int
_eina_value_type_double_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)1885 _eina_value_type_double_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
1886 {
1887 const double *ta = a, *tb = b;
1888 if (*ta < *tb)
1889 return -1;
1890 else if (*ta > *tb)
1891 return 1;
1892 return 0;
1893 }
1894
1895 static Eina_Bool
_eina_value_type_double_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)1896 _eina_value_type_double_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
1897 {
1898 const double v = *(const double *)type_mem;
1899
1900 if (convert == EINA_VALUE_TYPE_UCHAR)
1901 {
1902 unsigned char other_mem = v;
1903 if (EINA_UNLIKELY(v < 0))
1904 return EINA_FALSE;
1905 if (EINA_UNLIKELY(v > eina_value_uchar_max))
1906 return EINA_FALSE;
1907 return eina_value_type_pset(convert, convert_mem, &other_mem);
1908 }
1909 else if (convert == EINA_VALUE_TYPE_USHORT)
1910 {
1911 unsigned short other_mem = v;
1912 if (EINA_UNLIKELY(v < 0))
1913 return EINA_FALSE;
1914 if (EINA_UNLIKELY(v > eina_value_ushort_max))
1915 return EINA_FALSE;
1916 return eina_value_type_pset(convert, convert_mem, &other_mem);
1917 }
1918 else if (convert == EINA_VALUE_TYPE_UINT)
1919 {
1920 unsigned int other_mem = v;
1921 if (EINA_UNLIKELY(v < 0))
1922 return EINA_FALSE;
1923 if (EINA_UNLIKELY(v > eina_value_uint_max))
1924 return EINA_FALSE;
1925 return eina_value_type_pset(convert, convert_mem, &other_mem);
1926 }
1927 else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP))
1928 {
1929 unsigned long other_mem = v;
1930 if (EINA_UNLIKELY(v < 0))
1931 return EINA_FALSE;
1932 if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) &&
1933 (v > eina_value_ulong_max)))
1934 return EINA_FALSE;
1935 return eina_value_type_pset(convert, convert_mem, &other_mem);
1936 }
1937 else if (convert == EINA_VALUE_TYPE_UINT64)
1938 {
1939 uint64_t other_mem = v;
1940 if (EINA_UNLIKELY(v < 0))
1941 return EINA_FALSE;
1942 return eina_value_type_pset(convert, convert_mem, &other_mem);
1943 }
1944 else if (convert == EINA_VALUE_TYPE_CHAR)
1945 {
1946 signed char other_mem = v;
1947 if (EINA_UNLIKELY(v < eina_value_char_min))
1948 return EINA_FALSE;
1949 if (EINA_UNLIKELY(v > eina_value_char_max))
1950 return EINA_FALSE;
1951 return eina_value_type_pset(convert, convert_mem, &other_mem);
1952 }
1953 else if (convert == EINA_VALUE_TYPE_SHORT)
1954 {
1955 short other_mem = v;
1956 if (EINA_UNLIKELY(v < eina_value_short_min))
1957 return EINA_FALSE;
1958 if (EINA_UNLIKELY(v > eina_value_short_max))
1959 return EINA_FALSE;
1960 return eina_value_type_pset(convert, convert_mem, &other_mem);
1961 }
1962 else if ((convert == EINA_VALUE_TYPE_INT) || (convert == EINA_VALUE_TYPE_ERROR))
1963 {
1964 int other_mem = v;
1965 if (EINA_UNLIKELY(v < eina_value_int_min))
1966 return EINA_FALSE;
1967 if (EINA_UNLIKELY(v > eina_value_int_max))
1968 return EINA_FALSE;
1969 return eina_value_type_pset(convert, convert_mem, &other_mem);
1970 }
1971 else if (convert == EINA_VALUE_TYPE_LONG)
1972 {
1973 long other_mem = v;
1974 if (EINA_UNLIKELY(v < eina_value_long_min))
1975 return EINA_FALSE;
1976 if (EINA_UNLIKELY(v > eina_value_long_max))
1977 return EINA_FALSE;
1978 return eina_value_type_pset(convert, convert_mem, &other_mem);
1979 }
1980 else if (convert == EINA_VALUE_TYPE_INT64)
1981 {
1982 int64_t other_mem = v;
1983 return eina_value_type_pset(convert, convert_mem, &other_mem);
1984 }
1985 else if (convert == EINA_VALUE_TYPE_FLOAT)
1986 {
1987 float other_mem = v;
1988 return eina_value_type_pset(convert, convert_mem, &other_mem);
1989 }
1990 else if (convert == EINA_VALUE_TYPE_DOUBLE)
1991 {
1992 double other_mem = v;
1993 return eina_value_type_pset(convert, convert_mem, &other_mem);
1994 }
1995 else if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
1996 convert == EINA_VALUE_TYPE_STRING)
1997 {
1998 const char *other_mem;
1999 char buf[64];
2000 snprintf(buf, sizeof(buf), "%g", (double)v);
2001 other_mem = buf; /* required due &buf == buf */
2002 return eina_value_type_pset(convert, convert_mem, &other_mem);
2003 }
2004 else
2005 {
2006 return EINA_FALSE;
2007 }
2008
2009 return EINA_TRUE;
2010 }
2011
2012 static Eina_Bool
_eina_value_type_double_vset(const Eina_Value_Type * type EINA_UNUSED,void * mem,va_list args)2013 _eina_value_type_double_vset(const Eina_Value_Type *type EINA_UNUSED, void *mem, va_list args)
2014 {
2015 double *tmem = mem;
2016 *tmem = va_arg(args, double);
2017 return EINA_TRUE;
2018 }
2019
2020 static Eina_Bool
_eina_value_type_double_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)2021 _eina_value_type_double_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
2022 {
2023 double *tmem = mem;
2024 const double *p = ptr;
2025 *tmem = *p;
2026 return EINA_TRUE;
2027 }
2028
2029 static Eina_Bool
_eina_value_type_double_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)2030 _eina_value_type_double_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
2031 {
2032 const double *tmem = mem;
2033 double *p = ptr;
2034 *p = *tmem;
2035 return EINA_TRUE;
2036 }
2037
2038 static Eina_Bool
_eina_value_type_string_common_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)2039 _eina_value_type_string_common_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
2040 {
2041 const char **tmem = mem;
2042 *tmem = NULL;
2043 return EINA_TRUE;
2044 }
2045
2046 static int
_eina_value_type_string_common_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)2047 _eina_value_type_string_common_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
2048 {
2049 const char *sa = *(const char **)a;
2050 const char *sb = *(const char **)b;
2051 if (sa == sb)
2052 return 0;
2053 if (sa == NULL)
2054 return -1;
2055 if (sb == NULL)
2056 return 1;
2057 return strcmp(sa, sb);
2058 }
2059
2060 static Eina_Bool
_eina_value_type_string_common_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)2061 _eina_value_type_string_common_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
2062 {
2063 const char *v = *(const char **)type_mem;
2064
2065 if (convert == EINA_VALUE_TYPE_UCHAR)
2066 {
2067 unsigned char other_mem;
2068 if ((sscanf(v, "%hhu", &other_mem) != 1) &&
2069 (sscanf(v, "%hhx", &other_mem) != 1) &&
2070 (sscanf(v, "%hho", &other_mem) != 1))
2071 return EINA_FALSE;
2072 return eina_value_type_pset(convert, convert_mem, &other_mem);
2073 }
2074 else if (convert == EINA_VALUE_TYPE_USHORT)
2075 {
2076 unsigned short other_mem;
2077 if ((sscanf(v, "%hu", &other_mem) != 1) &&
2078 (sscanf(v, "%hx", &other_mem) != 1) &&
2079 (sscanf(v, "%ho", &other_mem) != 1))
2080 return EINA_FALSE;
2081 return eina_value_type_pset(convert, convert_mem, &other_mem);
2082 }
2083 else if (convert == EINA_VALUE_TYPE_UINT)
2084 {
2085 unsigned int other_mem;
2086 if ((sscanf(v, "%u", &other_mem) != 1) &&
2087 (sscanf(v, "%x", &other_mem) != 1) &&
2088 (sscanf(v, "%o", &other_mem) != 1))
2089 return EINA_FALSE;
2090 return eina_value_type_pset(convert, convert_mem, &other_mem);
2091 }
2092 else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP))
2093 {
2094 unsigned long other_mem;
2095 if ((sscanf(v, "%lu", &other_mem) != 1) &&
2096 (sscanf(v, "%lx", &other_mem) != 1) &&
2097 (sscanf(v, "%lo", &other_mem) != 1))
2098 return EINA_FALSE;
2099 return eina_value_type_pset(convert, convert_mem, &other_mem);
2100 }
2101 else if (convert == EINA_VALUE_TYPE_UINT64)
2102 {
2103 uint64_t other_mem;
2104 if ((sscanf(v, "%"SCNu64, &other_mem) != 1) &&
2105 (sscanf(v, "%"SCNx64, &other_mem) != 1) &&
2106 (sscanf(v, "%"SCNo64, &other_mem) != 1))
2107 return EINA_FALSE;
2108 return eina_value_type_pset(convert, convert_mem, &other_mem);
2109 }
2110 else if (convert == EINA_VALUE_TYPE_CHAR)
2111 {
2112 signed char other_mem;
2113 if ((sscanf(v, "%hhd", &other_mem) != 1) &&
2114 (sscanf(v, "%hhx", &other_mem) != 1) &&
2115 (sscanf(v, "%hho", &other_mem) != 1))
2116 return EINA_FALSE;
2117 return eina_value_type_pset(convert, convert_mem, &other_mem);
2118 }
2119 else if (convert == EINA_VALUE_TYPE_SHORT)
2120 {
2121 short other_mem;
2122 if ((sscanf(v, "%hd", &other_mem) != 1) &&
2123 (sscanf(v, "%hx", &other_mem) != 1) &&
2124 (sscanf(v, "%ho", &other_mem) != 1))
2125 return EINA_FALSE;
2126 return eina_value_type_pset(convert, convert_mem, &other_mem);
2127 }
2128 else if ((convert == EINA_VALUE_TYPE_INT) || (convert == EINA_VALUE_TYPE_ERROR))
2129 {
2130 int other_mem;
2131 if ((sscanf(v, "%d", &other_mem) != 1) &&
2132 (sscanf(v, "%x", &other_mem) != 1) &&
2133 (sscanf(v, "%o", &other_mem) != 1))
2134 return EINA_FALSE;
2135 return eina_value_type_pset(convert, convert_mem, &other_mem);
2136 }
2137 else if (convert == EINA_VALUE_TYPE_LONG)
2138 {
2139 long other_mem;
2140 if ((sscanf(v, "%ld", &other_mem) != 1) &&
2141 (sscanf(v, "%lx", &other_mem) != 1) &&
2142 (sscanf(v, "%lo", &other_mem) != 1))
2143 return EINA_FALSE;
2144 return eina_value_type_pset(convert, convert_mem, &other_mem);
2145 }
2146 else if (convert == EINA_VALUE_TYPE_INT64)
2147 {
2148 int64_t other_mem;
2149 if ((sscanf(v, "%"SCNd64, &other_mem) != 1) &&
2150 (sscanf(v, "%"SCNx64, &other_mem) != 1) &&
2151 (sscanf(v, "%"SCNo64, &other_mem) != 1))
2152 return EINA_FALSE;
2153 return eina_value_type_pset(convert, convert_mem, &other_mem);
2154 }
2155 else if (convert == EINA_VALUE_TYPE_FLOAT)
2156 {
2157 float other_mem;
2158 if (sscanf(v, "%f", &other_mem) != 1)
2159 return EINA_FALSE;
2160 return eina_value_type_pset(convert, convert_mem, &other_mem);
2161 }
2162 else if (convert == EINA_VALUE_TYPE_DOUBLE)
2163 {
2164 double other_mem;
2165 if (sscanf(v, "%lf", &other_mem) != 1)
2166 return EINA_FALSE;
2167 return eina_value_type_pset(convert, convert_mem, &other_mem);
2168 }
2169 else if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
2170 convert == EINA_VALUE_TYPE_STRING)
2171 {
2172 return eina_value_type_pset(convert, convert_mem, &v);
2173 }
2174 else
2175 {
2176 return EINA_FALSE;
2177 }
2178
2179 return EINA_TRUE;
2180 }
2181
2182 static Eina_Bool
_eina_value_type_string_common_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)2183 _eina_value_type_string_common_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
2184 {
2185 memcpy(ptr, mem, sizeof(const char *));
2186 return EINA_TRUE;
2187 }
2188
2189 static Eina_Bool
_eina_value_type_stringshare_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem)2190 _eina_value_type_stringshare_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem)
2191 {
2192 const char **tmem = mem;
2193 if (*tmem)
2194 {
2195 eina_stringshare_del(*tmem);
2196 *tmem = NULL;
2197 }
2198 return EINA_TRUE;
2199 }
2200
2201 static Eina_Bool
_eina_value_type_stringshare_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)2202 _eina_value_type_stringshare_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
2203 {
2204 const char * const*s = src;
2205 const char **d = dst;
2206 *d = eina_stringshare_add(*s);
2207 return EINA_TRUE;
2208 }
2209
2210 static Eina_Bool
_eina_value_type_stringshare_vset(const Eina_Value_Type * type EINA_UNUSED,void * mem,va_list args)2211 _eina_value_type_stringshare_vset(const Eina_Value_Type *type EINA_UNUSED, void *mem, va_list args)
2212 {
2213 const char *str = va_arg(args, const char *);
2214 return eina_stringshare_replace((const char **)mem, str);
2215 }
2216
2217 static Eina_Bool
_eina_value_type_stringshare_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)2218 _eina_value_type_stringshare_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
2219 {
2220 const char * const *str = ptr;
2221 return eina_stringshare_replace((const char **)mem, *str);
2222 }
2223
2224 static Eina_Bool
_eina_value_type_stringshare_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)2225 _eina_value_type_stringshare_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
2226 {
2227 const Eina_Stringshare * const *src = mem;
2228 Eina_Stringshare **dst = ptr;
2229
2230 *dst = eina_stringshare_ref(*src);
2231 return EINA_TRUE;
2232 }
2233
2234 static Eina_Bool
_eina_value_type_string_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem)2235 _eina_value_type_string_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem)
2236 {
2237 char **tmem = mem;
2238 if (*tmem)
2239 {
2240 free(*tmem);
2241 *tmem = NULL;
2242 }
2243 return EINA_TRUE;
2244 }
2245
2246 static Eina_Bool
_eina_value_type_string_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)2247 _eina_value_type_string_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
2248 {
2249 const char * const *s = src;
2250 char **d = dst;
2251 if (*s == NULL)
2252 *d = NULL;
2253 else
2254 {
2255 *d = strdup(*s);
2256 if (*d == NULL)
2257 {
2258 return EINA_FALSE;
2259 }
2260 }
2261 return EINA_TRUE;
2262 }
2263
2264 static Eina_Bool
_eina_value_type_string_vset(const Eina_Value_Type * type EINA_UNUSED,void * mem,va_list args)2265 _eina_value_type_string_vset(const Eina_Value_Type *type EINA_UNUSED, void *mem, va_list args)
2266 {
2267 char **tmem = mem;
2268 const char *str = va_arg(args, const char *);
2269
2270 if (str == *tmem) return EINA_TRUE;
2271 if (!str)
2272 {
2273 free(*tmem);
2274 *tmem = NULL;
2275 }
2276 else
2277 {
2278 char *tmp = strdup(str);
2279 if (!tmp)
2280 {
2281 return EINA_FALSE;
2282 }
2283 free(*tmem);
2284 *tmem = tmp;
2285 }
2286 return EINA_TRUE;
2287 }
2288
2289 static Eina_Bool
_eina_value_type_string_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)2290 _eina_value_type_string_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
2291 {
2292 char **tmem = mem;
2293 const char * const *str = ptr;
2294
2295 if (*str == *tmem) return EINA_TRUE;
2296 if (!*str)
2297 {
2298 free(*tmem);
2299 *tmem = NULL;
2300 }
2301 else
2302 {
2303 char *tmp = strdup(*str);
2304 if (!tmp)
2305 {
2306 return EINA_FALSE;
2307 }
2308 free(*tmem);
2309 *tmem = tmp;
2310 }
2311 return EINA_TRUE;
2312 }
2313
2314 static Eina_Bool
_eina_value_type_array_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)2315 _eina_value_type_array_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
2316 {
2317 memset(mem, 0, sizeof(Eina_Value_Array));
2318 return EINA_TRUE;
2319 }
2320
2321 static Eina_Bool
_eina_value_type_array_flush_elements(Eina_Value_Array * tmem)2322 _eina_value_type_array_flush_elements(Eina_Value_Array *tmem)
2323 {
2324 const Eina_Value_Type *subtype = tmem->subtype;
2325 Eina_Bool ret = EINA_TRUE;
2326 unsigned char sz;
2327 char *ptr, *ptr_end;
2328
2329 if (!tmem->array) return EINA_TRUE;
2330
2331 sz = tmem->array->member_size;
2332 ptr = tmem->array->members;
2333 ptr_end = ptr + tmem->array->len * sz;
2334
2335 for (; ptr < ptr_end; ptr += sz)
2336 ret &= eina_value_type_flush(subtype, ptr);
2337
2338 eina_inarray_flush(tmem->array);
2339 return ret;
2340 }
2341
2342 static Eina_Bool
_eina_value_type_array_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem)2343 _eina_value_type_array_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem)
2344 {
2345 Eina_Value_Array *tmem = mem;
2346 Eina_Bool ret =_eina_value_type_array_flush_elements(tmem);
2347
2348 if (tmem->array) eina_inarray_free(tmem->array);
2349 tmem->array = NULL;
2350 tmem->subtype = NULL;
2351 return ret;
2352 }
2353
2354 static Eina_Bool
_eina_value_type_array_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)2355 _eina_value_type_array_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
2356 {
2357 const Eina_Value_Type *subtype;
2358 const Eina_Value_Array *s = src;
2359 Eina_Value_Array *d = dst;
2360 unsigned int i, count, sz;
2361 char *ptr, *ptr_end;
2362
2363 d->subtype = subtype = s->subtype;
2364 d->step = s->step;
2365
2366 if ((!s->array) || (!s->subtype))
2367 {
2368 d->array = NULL;
2369 return EINA_TRUE;
2370 }
2371
2372 if (!subtype->copy)
2373 {
2374 return EINA_FALSE;
2375 }
2376
2377 d->array = eina_inarray_new(subtype->value_size, s->step);
2378 if (!d->array)
2379 return EINA_FALSE;
2380
2381 sz = s->array->member_size;
2382
2383 count = eina_inarray_count(s->array);
2384 ptr = s->array->members;
2385 ptr_end = ptr + (count * sz);
2386
2387 for (i = 0; ptr < ptr_end; ptr += sz, i++)
2388 {
2389 void *imem = eina_inarray_alloc_at(d->array, i, 1);
2390 if (!imem) goto error;
2391 if (!subtype->copy(subtype, ptr, imem))
2392 {
2393 eina_inarray_pop(d->array);
2394 goto error;
2395 }
2396 }
2397
2398 return EINA_TRUE;
2399
2400 error:
2401 _eina_value_type_array_flush_elements(d);
2402 eina_inarray_free(d->array);
2403 return EINA_FALSE;
2404 }
2405
2406 static int
_eina_value_type_array_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)2407 _eina_value_type_array_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
2408 {
2409 const Eina_Value_Type *subtype;
2410 const Eina_Value_Array *eva_a = a, *eva_b = b;
2411 const char *a_ptr, *a_ptr_end, *b_ptr;
2412 unsigned int count_a, count_b, count, sz;
2413 int cmp = 0;
2414
2415 if (eva_a->subtype != eva_b->subtype)
2416 {
2417 return -1;
2418 }
2419
2420 subtype = eva_a->subtype;
2421 if (!subtype->compare)
2422 {
2423 return 0;
2424 }
2425
2426 if ((!eva_a->array) && (!eva_b->array))
2427 return 0;
2428 else if (!eva_a->array)
2429 return -1;
2430 else if (!eva_b->array)
2431 return 1;
2432
2433 count_a = eina_inarray_count(eva_a->array);
2434 count_b = eina_inarray_count(eva_b->array);
2435
2436 if (count_a <= count_b)
2437 count = count_a;
2438 else
2439 count = count_b;
2440
2441 sz = eva_a->array->member_size;
2442
2443 a_ptr = eva_a->array->members;
2444 a_ptr_end = a_ptr + (count * sz);
2445 b_ptr = eva_b->array->members;
2446
2447 for (; (cmp == 0) && (a_ptr < a_ptr_end); a_ptr += sz, b_ptr += sz)
2448 cmp = subtype->compare(subtype, a_ptr, b_ptr);
2449
2450 if (cmp == 0)
2451 {
2452 if (count_a < count_b)
2453 return -1;
2454 else if (count_a > count_b)
2455 return 1;
2456 return 0;
2457 }
2458
2459 return cmp;
2460 }
2461
2462 static Eina_Bool
_eina_value_type_array_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)2463 _eina_value_type_array_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
2464 {
2465 const Eina_Value_Array *tmem = type_mem;
2466 Eina_Bool ret = EINA_FALSE;
2467
2468 if ((convert == EINA_VALUE_TYPE_STRING) ||
2469 (convert == EINA_VALUE_TYPE_STRINGSHARE))
2470 {
2471 Eina_Strbuf *str = eina_strbuf_new();
2472 const char *ptr;
2473 if (!tmem->array) eina_strbuf_append(str, "[]");
2474 else
2475 {
2476 const Eina_Value_Type *subtype = tmem->subtype;
2477 unsigned char sz;
2478 const char *ptr_end;
2479 Eina_Value tmp;
2480 Eina_Bool first = EINA_TRUE;
2481
2482 eina_value_setup(&tmp, EINA_VALUE_TYPE_STRING);
2483
2484 eina_strbuf_append_char(str, '[');
2485
2486 sz = tmem->array->member_size;
2487 ptr = tmem->array->members;
2488 ptr_end = ptr + tmem->array->len * sz;
2489 for (; ptr < ptr_end; ptr += sz)
2490 {
2491 Eina_Bool r = EINA_FALSE;
2492 if (subtype->convert_to)
2493 {
2494 r = subtype->convert_to(subtype, EINA_VALUE_TYPE_STRING,
2495 ptr, tmp.value.buf);
2496 if (r)
2497 {
2498 if (first) first = EINA_FALSE;
2499 else eina_strbuf_append_length(str, ", ", 2);
2500 eina_strbuf_append(str, tmp.value.ptr);
2501 free(tmp.value.ptr);
2502 tmp.value.ptr = NULL;
2503 }
2504 }
2505
2506 if (!r)
2507 {
2508 if (first)
2509 {
2510 first = EINA_FALSE;
2511 eina_strbuf_append_char(str, '?');
2512 }
2513 else
2514 eina_strbuf_append_length(str, ", ?", 3);
2515 }
2516 }
2517
2518 eina_strbuf_append_char(str, ']');
2519 }
2520 ptr = eina_strbuf_string_get(str);
2521 ret = eina_value_type_pset(convert, convert_mem, &ptr);
2522 eina_strbuf_free(str);
2523 }
2524 else if ((tmem->array) && (tmem->array->len == 1))
2525 {
2526 const Eina_Value_Type *subtype = tmem->subtype;
2527 void *imem = tmem->array->members;
2528
2529 if (subtype->convert_to)
2530 ret = subtype->convert_to(subtype, convert, imem, convert_mem);
2531 if ((!ret) && (convert->convert_from))
2532 ret = convert->convert_from(convert, subtype, convert_mem, imem);
2533 }
2534
2535 if (!ret)
2536 {
2537 return EINA_FALSE;
2538 }
2539 return EINA_TRUE;
2540 }
2541
2542 static Eina_Bool
_eina_value_type_array_convert_from(const Eina_Value_Type * type,const Eina_Value_Type * convert,void * type_mem,const void * convert_mem)2543 _eina_value_type_array_convert_from(const Eina_Value_Type *type, const Eina_Value_Type *convert, void *type_mem, const void *convert_mem)
2544 {
2545 Eina_Value_Array *tmem = type_mem;
2546 Eina_Value_Array desc = {convert, tmem->step, NULL};
2547 char *buf;
2548 void *imem;
2549
2550 if (!eina_value_type_pset(type, tmem, &desc))
2551 return EINA_FALSE;
2552
2553 buf = alloca(convert->value_size);
2554 if (!eina_value_type_pget(convert, convert_mem, &buf))
2555 return EINA_FALSE;
2556
2557 imem = eina_inarray_alloc_at(tmem->array, 0, 1);
2558 if (!imem)
2559 return EINA_FALSE;
2560
2561 if (!eina_value_type_setup(convert, imem)) goto error_setup;
2562 if (!eina_value_type_pset(convert, imem, &buf)) goto error_set;
2563 return EINA_TRUE;
2564
2565 error_set:
2566 eina_value_type_flush(convert, imem);
2567 error_setup:
2568 eina_inarray_remove_at(tmem->array, 0);
2569 return EINA_FALSE;
2570 }
2571
2572 static Eina_Bool
_eina_value_type_array_pset(const Eina_Value_Type * type,void * mem,const void * ptr)2573 _eina_value_type_array_pset(const Eina_Value_Type *type, void *mem, const void *ptr)
2574 {
2575 Eina_Value_Array *tmem = mem;
2576 const Eina_Value_Array *desc = ptr;
2577 Eina_Inarray *desc_array;
2578
2579 if ((!tmem->subtype) && (!desc->subtype))
2580 return EINA_TRUE;
2581
2582 desc_array = desc->array;
2583 if (desc_array)
2584 {
2585 Eina_Value_Array tmp;
2586
2587 EINA_SAFETY_ON_FALSE_RETURN_VAL
2588 (desc_array->member_size == desc->subtype->value_size, EINA_FALSE);
2589
2590 if (desc_array == tmem->array)
2591 {
2592 tmem->subtype = desc->subtype;
2593 return EINA_TRUE;
2594 }
2595
2596 if (!_eina_value_type_array_copy(type, desc, &tmp))
2597 return EINA_FALSE;
2598
2599 _eina_value_type_array_flush(type, tmem);
2600 memcpy(tmem, &tmp, sizeof(tmp));
2601 return EINA_TRUE;
2602 }
2603
2604 if (tmem->array)
2605 {
2606 _eina_value_type_array_flush_elements(tmem);
2607 eina_inarray_step_set(tmem->array, sizeof (Eina_Inarray), desc->subtype->value_size, desc->step);
2608 }
2609 else
2610 {
2611 tmem->array = eina_inarray_new(desc->subtype->value_size, desc->step);
2612 if (!tmem->array)
2613 return EINA_FALSE;
2614 }
2615
2616 tmem->subtype = desc->subtype;
2617 return EINA_TRUE;
2618 }
2619
2620 static Eina_Bool
_eina_value_type_array_vset(const Eina_Value_Type * type,void * mem,va_list args)2621 _eina_value_type_array_vset(const Eina_Value_Type *type, void *mem, va_list args)
2622 {
2623 const Eina_Value_Array desc = va_arg(args, Eina_Value_Array);
2624 _eina_value_type_array_pset(type, mem, &desc);
2625 return EINA_TRUE;
2626 }
2627
2628 static Eina_Bool
_eina_value_type_array_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)2629 _eina_value_type_array_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
2630 {
2631 memcpy(ptr, mem, sizeof(Eina_Value_Array));
2632 return EINA_TRUE;
2633 }
2634
2635 static const Eina_Value_Type _EINA_VALUE_TYPE_ARRAY = {
2636 EINA_VALUE_TYPE_VERSION,
2637 sizeof(Eina_Value_Array),
2638 "Eina_Value_Array",
2639 _eina_value_type_array_setup,
2640 _eina_value_type_array_flush,
2641 _eina_value_type_array_copy,
2642 _eina_value_type_array_compare,
2643 _eina_value_type_array_convert_to,
2644 _eina_value_type_array_convert_from,
2645 _eina_value_type_array_vset,
2646 _eina_value_type_array_pset,
2647 _eina_value_type_array_pget
2648 };
2649
2650 static Eina_Bool
_eina_value_type_list_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)2651 _eina_value_type_list_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
2652 {
2653 memset(mem, 0, sizeof(Eina_Value_List));
2654 return EINA_TRUE;
2655 }
2656
2657 static Eina_Bool
_eina_value_type_list_flush_elements(Eina_Value_List * tmem)2658 _eina_value_type_list_flush_elements(Eina_Value_List *tmem)
2659 {
2660 const Eina_Value_Type *subtype = tmem->subtype;
2661 Eina_Bool ret = EINA_TRUE;
2662
2663 if (!tmem->list) return EINA_TRUE;
2664
2665 while (tmem->list)
2666 {
2667 void *mem = eina_value_list_node_memory_get(tmem->subtype, tmem->list);
2668 ret &= eina_value_type_flush(subtype, mem);
2669 eina_value_list_node_memory_flush(tmem->subtype, tmem->list);
2670 tmem->list = eina_list_remove_list(tmem->list, tmem->list);
2671 }
2672
2673 return ret;
2674 }
2675
2676 static Eina_Bool
_eina_value_type_list_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem)2677 _eina_value_type_list_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem)
2678 {
2679 Eina_Value_List *tmem = mem;
2680 Eina_Bool ret =_eina_value_type_list_flush_elements(tmem);
2681
2682 if (tmem->list) eina_list_free(tmem->list);
2683 tmem->list = NULL;
2684 tmem->subtype = NULL;
2685 return ret;
2686 }
2687
2688 static Eina_Bool
_eina_value_type_list_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)2689 _eina_value_type_list_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
2690 {
2691 const Eina_Value_Type *subtype;
2692 const Eina_Value_List *s = src;
2693 Eina_Value_List *d = dst;
2694 const Eina_List *snode;
2695
2696 d->subtype = subtype = s->subtype;
2697 if ((!s->list) || (!s->subtype))
2698 {
2699 d->list = NULL;
2700 return EINA_TRUE;
2701 }
2702
2703 if (!subtype->copy)
2704 {
2705 return EINA_FALSE;
2706 }
2707
2708 d->list = NULL;
2709 for (snode = s->list; snode != NULL; snode = snode->next)
2710 {
2711 const void *ptr = eina_value_list_node_memory_get(subtype, snode);
2712 Eina_List *dnode;
2713 void *imem;
2714
2715 d->list = eina_list_append(d->list, (void*)1L);
2716 dnode = eina_list_last(d->list);
2717 EINA_SAFETY_ON_NULL_GOTO(dnode, error);
2718 EINA_SAFETY_ON_FALSE_GOTO(dnode->data == (void*)1L, error);
2719
2720 imem = eina_value_list_node_memory_setup(subtype, dnode);
2721 if (!subtype->copy(subtype, ptr, imem))
2722 {
2723 eina_value_list_node_memory_flush(subtype, dnode);
2724 d->list = eina_list_remove_list(d->list, dnode);
2725 goto error;
2726 }
2727 }
2728 return EINA_TRUE;
2729
2730 error:
2731 _eina_value_type_list_flush_elements(d);
2732 return EINA_FALSE;
2733 }
2734
2735 static int
_eina_value_type_list_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)2736 _eina_value_type_list_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
2737 {
2738 const Eina_Value_Type *subtype;
2739 const Eina_Value_List *eva_a = a, *eva_b = b;
2740 const Eina_List *anode, *bnode;
2741 int cmp = 0;
2742
2743 if (eva_a->subtype != eva_b->subtype)
2744 {
2745 return -1;
2746 }
2747
2748 subtype = eva_a->subtype;
2749 if (!subtype->compare)
2750 {
2751 return 0;
2752 }
2753
2754 if ((!eva_a->list) && (!eva_b->list))
2755 return 0;
2756 else if (!eva_a->list)
2757 return -1;
2758 else if (!eva_b->list)
2759 return 1;
2760
2761 for (anode = eva_a->list, bnode = eva_b->list;
2762 (cmp == 0) && (anode) && (bnode);
2763 anode = anode->next, bnode = bnode->next)
2764 {
2765 const void *amem = eina_value_list_node_memory_get(subtype, anode);
2766 const void *bmem = eina_value_list_node_memory_get(subtype, bnode);
2767 cmp = subtype->compare(subtype, amem, bmem);
2768 }
2769
2770 if (cmp == 0)
2771 {
2772 if ((!anode) && (bnode))
2773 return -1;
2774 else if ((anode) && (!bnode))
2775 return 1;
2776 return 0;
2777 }
2778
2779 return cmp;
2780 }
2781
2782 static Eina_Bool
_eina_value_type_list_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)2783 _eina_value_type_list_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
2784 {
2785 const Eina_Value_List *tmem = type_mem;
2786 Eina_Bool ret = EINA_FALSE;
2787
2788 if ((convert == EINA_VALUE_TYPE_STRING) ||
2789 (convert == EINA_VALUE_TYPE_STRINGSHARE))
2790 {
2791 Eina_Strbuf *str = eina_strbuf_new();
2792 const char *s;
2793 if (!tmem->list) eina_strbuf_append(str, "[]");
2794 else
2795 {
2796 const Eina_Value_Type *subtype = tmem->subtype;
2797 const Eina_List *node;
2798 Eina_Value tmp;
2799 Eina_Bool first = EINA_TRUE;
2800
2801 eina_value_setup(&tmp, EINA_VALUE_TYPE_STRING);
2802
2803 eina_strbuf_append_char(str, '[');
2804
2805 for (node = tmem->list; node != NULL; node = node->next)
2806 {
2807 Eina_Bool r = EINA_FALSE;
2808
2809 if (subtype->convert_to)
2810 {
2811 const void *ptr;
2812 ptr = eina_value_list_node_memory_get(subtype, node);
2813 r = subtype->convert_to(subtype, EINA_VALUE_TYPE_STRING,
2814 ptr, tmp.value.buf);
2815 if (r)
2816 {
2817 if (first) first = EINA_FALSE;
2818 else eina_strbuf_append_length(str, ", ", 2);
2819 eina_strbuf_append(str, tmp.value.ptr);
2820 free(tmp.value.ptr);
2821 tmp.value.ptr = NULL;
2822 }
2823 }
2824
2825 if (!r)
2826 {
2827 if (first)
2828 {
2829 first = EINA_FALSE;
2830 eina_strbuf_append_char(str, '?');
2831 }
2832 else
2833 eina_strbuf_append_length(str, ", ?", 3);
2834 }
2835 }
2836
2837 eina_strbuf_append_char(str, ']');
2838 }
2839 s = eina_strbuf_string_get(str);
2840 ret = eina_value_type_pset(convert, convert_mem, &s);
2841 eina_strbuf_free(str);
2842 }
2843 else if ((tmem->list) && (tmem->list->next == NULL))
2844 {
2845 const Eina_Value_Type *subtype = tmem->subtype;
2846 void *imem = eina_value_list_node_memory_get(subtype, tmem->list);
2847
2848 if (subtype->convert_to)
2849 ret = subtype->convert_to(subtype, convert, imem, convert_mem);
2850 if ((!ret) && (convert->convert_from))
2851 ret = convert->convert_from(convert, subtype, convert_mem, imem);
2852 }
2853
2854 if (!ret)
2855 {
2856 return EINA_FALSE;
2857 }
2858 return EINA_TRUE;
2859 }
2860
2861 static Eina_Bool
_eina_value_type_list_convert_from(const Eina_Value_Type * type,const Eina_Value_Type * convert,void * type_mem,const void * convert_mem)2862 _eina_value_type_list_convert_from(const Eina_Value_Type *type, const Eina_Value_Type *convert, void *type_mem, const void *convert_mem)
2863 {
2864 Eina_Value_List *tmem = type_mem;
2865 Eina_Value_List desc = {convert, NULL};
2866 Eina_List *node;
2867 char *buf;
2868 void *imem;
2869
2870 if (!eina_value_type_pset(type, tmem, &desc))
2871 return EINA_FALSE;
2872
2873 buf = alloca(convert->value_size);
2874 if (!eina_value_type_pget(convert, convert_mem, &buf))
2875 return EINA_FALSE;
2876
2877 tmem->list = eina_list_append(tmem->list, (void*)1L);
2878 node = eina_list_last(tmem->list);
2879 EINA_SAFETY_ON_NULL_RETURN_VAL(node, EINA_FALSE);
2880 EINA_SAFETY_ON_FALSE_RETURN_VAL(node->data == (void*)1L, EINA_FALSE);
2881
2882 imem = eina_value_list_node_memory_setup(tmem->subtype, node);
2883 if (!imem)
2884 {
2885 tmem->list = eina_list_remove_list(tmem->list, node);
2886 return EINA_FALSE;
2887 }
2888
2889 if (!eina_value_type_setup(tmem->subtype, imem)) goto error_setup;
2890 if (!eina_value_type_pset(tmem->subtype, imem, &buf)) goto error_set;
2891 return EINA_TRUE;
2892
2893 error_set:
2894 eina_value_type_flush(tmem->subtype, imem);
2895 error_setup:
2896 eina_value_list_node_memory_flush(tmem->subtype, node);
2897 tmem->list = eina_list_remove_list(tmem->list, node);
2898 return EINA_FALSE;
2899 }
2900
2901 static Eina_Bool
_eina_value_type_list_pset(const Eina_Value_Type * type,void * mem,const void * ptr)2902 _eina_value_type_list_pset(const Eina_Value_Type *type, void *mem, const void *ptr)
2903 {
2904 Eina_Value_List *tmem = mem;
2905 const Eina_Value_List *desc = ptr;
2906
2907 if ((!tmem->subtype) && (!desc->subtype))
2908 return EINA_TRUE;
2909
2910 if ((tmem->list) && (tmem->list == desc->list))
2911 {
2912 tmem->subtype = desc->subtype;
2913 return EINA_TRUE;
2914 }
2915
2916 if (desc->list)
2917 {
2918 Eina_Value_List tmp;
2919
2920 if (!_eina_value_type_list_copy(type, desc, &tmp))
2921 return EINA_FALSE;
2922
2923 _eina_value_type_list_flush(type, tmem);
2924 memcpy(tmem, &tmp, sizeof(tmp));
2925 return EINA_TRUE;
2926 }
2927
2928 _eina_value_type_list_flush_elements(tmem);
2929
2930 tmem->subtype = desc->subtype;
2931 return EINA_TRUE;
2932 }
2933
2934 static Eina_Bool
_eina_value_type_list_vset(const Eina_Value_Type * type,void * mem,va_list args)2935 _eina_value_type_list_vset(const Eina_Value_Type *type, void *mem, va_list args)
2936 {
2937 const Eina_Value_List desc = va_arg(args, Eina_Value_List);
2938 _eina_value_type_list_pset(type, mem, &desc);
2939 return EINA_TRUE;
2940 }
2941
2942 static Eina_Bool
_eina_value_type_list_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)2943 _eina_value_type_list_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
2944 {
2945 memcpy(ptr, mem, sizeof(Eina_Value_List));
2946 return EINA_TRUE;
2947 }
2948
2949 static const Eina_Value_Type _EINA_VALUE_TYPE_LIST = {
2950 EINA_VALUE_TYPE_VERSION,
2951 sizeof(Eina_Value_List),
2952 "Eina_Value_List",
2953 _eina_value_type_list_setup,
2954 _eina_value_type_list_flush,
2955 _eina_value_type_list_copy,
2956 _eina_value_type_list_compare,
2957 _eina_value_type_list_convert_to,
2958 _eina_value_type_list_convert_from,
2959 _eina_value_type_list_vset,
2960 _eina_value_type_list_pset,
2961 _eina_value_type_list_pget
2962 };
2963
2964 static Eina_Bool
_eina_value_type_hash_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)2965 _eina_value_type_hash_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
2966 {
2967 memset(mem, 0, sizeof(Eina_Value_Hash));
2968 return EINA_TRUE;
2969 }
2970
2971 struct _eina_value_type_hash_flush_each_ctx
2972 {
2973 const Eina_Value_Type *subtype;
2974 Eina_Bool ret;
2975 };
2976
2977 static Eina_Bool
_eina_value_type_hash_flush_each(const Eina_Hash * hash EINA_UNUSED,const void * key EINA_UNUSED,void * mem,void * user_data)2978 _eina_value_type_hash_flush_each(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *mem, void *user_data)
2979 {
2980 struct _eina_value_type_hash_flush_each_ctx *ctx = user_data;
2981 ctx->ret &= eina_value_type_flush(ctx->subtype, mem);
2982 free(mem);
2983 return EINA_TRUE;
2984 }
2985
2986 static Eina_Bool
_eina_value_type_hash_flush_elements(Eina_Value_Hash * tmem)2987 _eina_value_type_hash_flush_elements(Eina_Value_Hash *tmem)
2988 {
2989 struct _eina_value_type_hash_flush_each_ctx ctx = {
2990 tmem->subtype,
2991 EINA_TRUE
2992 };
2993
2994 if (!tmem->hash) return EINA_TRUE;
2995
2996 eina_hash_foreach(tmem->hash, _eina_value_type_hash_flush_each, &ctx);
2997 eina_hash_free(tmem->hash);
2998 tmem->hash = NULL;
2999 return ctx.ret;
3000 }
3001
3002 static Eina_Bool
_eina_value_type_hash_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem)3003 _eina_value_type_hash_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem)
3004 {
3005 Eina_Value_Hash *tmem = mem;
3006 Eina_Bool ret =_eina_value_type_hash_flush_elements(tmem);
3007 tmem->subtype = NULL;
3008 return ret;
3009 }
3010
3011 static unsigned int
_eina_value_hash_key_length(const void * key)3012 _eina_value_hash_key_length(const void *key)
3013 {
3014 if (!key)
3015 return 0;
3016 return (int)strlen(key) + 1;
3017 }
3018
3019 static int
_eina_value_hash_key_cmp(const void * key1,int key1_len,const void * key2,int key2_len)3020 _eina_value_hash_key_cmp(const void *key1, int key1_len, const void *key2, int key2_len)
3021 {
3022 int r = key1_len - key2_len;
3023 if (r != 0)
3024 return r;
3025 return strcmp(key1, key2);
3026 }
3027
3028 static Eina_Bool
_eina_value_type_hash_create(Eina_Value_Hash * desc)3029 _eina_value_type_hash_create(Eina_Value_Hash *desc)
3030 {
3031 if (!desc->buckets_power_size)
3032 desc->buckets_power_size = 5;
3033
3034 desc->hash = eina_hash_new(_eina_value_hash_key_length,
3035 _eina_value_hash_key_cmp,
3036 EINA_KEY_HASH(eina_hash_superfast),
3037 NULL, desc->buckets_power_size);
3038 return !!desc->hash;
3039 }
3040
3041 struct _eina_value_type_hash_copy_each_ctx
3042 {
3043 const Eina_Value_Type *subtype;
3044 Eina_Value_Hash *dest;
3045 Eina_Bool ret;
3046 };
3047
3048 static Eina_Bool
_eina_value_type_hash_copy_each(const Eina_Hash * hash EINA_UNUSED,const void * key,void * _ptr,void * user_data)3049 _eina_value_type_hash_copy_each(const Eina_Hash *hash EINA_UNUSED, const void *key, void *_ptr, void *user_data)
3050 {
3051 struct _eina_value_type_hash_copy_each_ctx *ctx = user_data;
3052 const void *ptr = _ptr;
3053 void *imem = malloc(ctx->subtype->value_size);
3054 if (!imem)
3055 {
3056 ctx->ret = EINA_FALSE;
3057 return EINA_FALSE;
3058 }
3059 if (!ctx->subtype->copy(ctx->subtype, ptr, imem))
3060 {
3061 free(imem);
3062 ctx->ret = EINA_FALSE;
3063 return EINA_FALSE;
3064 }
3065 if (!eina_hash_add(ctx->dest->hash, key, imem))
3066 {
3067 eina_value_type_flush(ctx->subtype, imem);
3068 free(imem);
3069 ctx->ret = EINA_FALSE;
3070 return EINA_FALSE;
3071 }
3072 return EINA_TRUE;
3073 }
3074
3075 static Eina_Bool
_eina_value_type_hash_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)3076 _eina_value_type_hash_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
3077 {
3078 const Eina_Value_Hash *s = src;
3079 Eina_Value_Hash *d = dst;
3080 struct _eina_value_type_hash_copy_each_ctx ctx = {s->subtype, d, EINA_TRUE};
3081
3082 d->subtype = s->subtype;
3083 d->buckets_power_size = s->buckets_power_size;
3084
3085 if ((!s->hash) || (!s->subtype))
3086 {
3087 d->hash = NULL;
3088 return EINA_TRUE;
3089 }
3090
3091 if (!s->subtype->copy)
3092 {
3093 return EINA_FALSE;
3094 }
3095
3096 if (!_eina_value_type_hash_create(d))
3097 return EINA_FALSE;
3098
3099 eina_hash_foreach(s->hash, _eina_value_type_hash_copy_each, &ctx);
3100 if (!ctx.ret)
3101 {
3102 _eina_value_type_hash_flush_elements(d);
3103 return EINA_FALSE;
3104 }
3105 return EINA_TRUE;
3106 }
3107
3108 struct _eina_value_type_hash_compare_each_ctx
3109 {
3110 const Eina_Value_Type *subtype;
3111 const Eina_Hash *other;
3112 int cmp;
3113 };
3114
3115 static Eina_Bool
_eina_value_type_hash_compare_each(const Eina_Hash * hash EINA_UNUSED,const void * key,void * _ptr,void * user_data)3116 _eina_value_type_hash_compare_each(const Eina_Hash *hash EINA_UNUSED, const void *key, void *_ptr, void *user_data)
3117 {
3118 struct _eina_value_type_hash_compare_each_ctx *ctx = user_data;
3119 const void *self_ptr = _ptr;
3120 const void *other_ptr = eina_hash_find(ctx->other, key);
3121 if (!other_ptr) return EINA_TRUE;
3122 ctx->cmp = ctx->subtype->compare(ctx->subtype, self_ptr, other_ptr);
3123 return ctx->cmp == 0;
3124 }
3125
3126 static int
_eina_value_type_hash_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)3127 _eina_value_type_hash_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
3128 {
3129 const Eina_Value_Hash *eva_a = a, *eva_b = b;
3130 struct _eina_value_type_hash_compare_each_ctx ctx = {
3131 eva_a->subtype, eva_b->hash, 0
3132 };
3133
3134 if (eva_a->subtype != eva_b->subtype)
3135 {
3136 return -1;
3137 }
3138
3139 if (!eva_a->subtype->compare)
3140 {
3141 return 0;
3142 }
3143
3144 if ((!eva_a->hash) && (!eva_b->hash))
3145 return 0;
3146 else if (!eva_a->hash)
3147 return -1;
3148 else if (!eva_b->hash)
3149 return 1;
3150
3151 eina_hash_foreach(eva_a->hash, _eina_value_type_hash_compare_each, &ctx);
3152 if (ctx.cmp == 0)
3153 {
3154 unsigned int count_a = eina_hash_population(eva_a->hash);
3155 unsigned int count_b = eina_hash_population(eva_b->hash);
3156 if (count_a < count_b)
3157 return -1;
3158 else if (count_a > count_b)
3159 return 1;
3160 return 0;
3161 }
3162
3163 return ctx.cmp;
3164 }
3165
3166 struct _eina_value_type_hash_convert_to_string_each_ctx
3167 {
3168 const Eina_Value_Type *subtype;
3169 Eina_Strbuf *str;
3170 Eina_Value tmp;
3171 Eina_Bool first;
3172 };
3173
3174 static Eina_Bool
_eina_value_type_hash_convert_to_string_each(const Eina_Hash * hash EINA_UNUSED,const void * _key,void * _ptr,void * user_data)3175 _eina_value_type_hash_convert_to_string_each(const Eina_Hash *hash EINA_UNUSED, const void *_key, void *_ptr, void *user_data)
3176 {
3177 struct _eina_value_type_hash_convert_to_string_each_ctx *ctx = user_data;
3178 const char *key = _key;
3179 const void *ptr = _ptr;
3180 Eina_Bool r = EINA_FALSE;
3181
3182 if (ctx->first) ctx->first = EINA_FALSE;
3183 else eina_strbuf_append_length(ctx->str, ", ", 2);
3184
3185 eina_strbuf_append(ctx->str, key);
3186 eina_strbuf_append_length(ctx->str, ": ", 2);
3187
3188 if (ctx->subtype->convert_to)
3189 {
3190 r = ctx->subtype->convert_to(ctx->subtype, EINA_VALUE_TYPE_STRING,
3191 ptr, ctx->tmp.value.buf);
3192 if (r)
3193 {
3194 eina_strbuf_append(ctx->str, ctx->tmp.value.ptr);
3195 free(ctx->tmp.value.ptr);
3196 ctx->tmp.value.ptr = NULL;
3197 }
3198 }
3199
3200 if (!r)
3201 eina_strbuf_append_char(ctx->str, '?');
3202
3203 return EINA_TRUE;
3204 }
3205
3206 static Eina_Bool
_eina_value_type_hash_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)3207 _eina_value_type_hash_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
3208 {
3209 const Eina_Value_Hash *tmem = type_mem;
3210 Eina_Bool ret = EINA_FALSE;
3211
3212 if ((convert == EINA_VALUE_TYPE_STRING) ||
3213 (convert == EINA_VALUE_TYPE_STRINGSHARE))
3214 {
3215 Eina_Strbuf *str = eina_strbuf_new();
3216 const char *s;
3217 if (!tmem->hash) eina_strbuf_append(str, "{}");
3218 else
3219 {
3220 struct _eina_value_type_hash_convert_to_string_each_ctx ctx;
3221
3222 ctx.subtype = tmem->subtype;
3223 ctx.str = str;
3224 ctx.first = EINA_TRUE;
3225 eina_value_setup(&ctx.tmp, EINA_VALUE_TYPE_STRING);
3226
3227 eina_strbuf_append_char(str, '{');
3228
3229 eina_hash_foreach(tmem->hash,
3230 _eina_value_type_hash_convert_to_string_each,
3231 &ctx);
3232
3233 eina_strbuf_append_char(str, '}');
3234 }
3235 s = eina_strbuf_string_get(str);
3236 ret = eina_value_type_pset(convert, convert_mem, &s);
3237 eina_strbuf_free(str);
3238 }
3239 else if ((tmem->hash) && (eina_hash_population(tmem->hash) == 1))
3240 {
3241 const Eina_Value_Type *subtype = tmem->subtype;
3242 Eina_Iterator *it;
3243 void *imem = NULL;
3244
3245 it = eina_hash_iterator_data_new(tmem->hash);
3246
3247 if (!it || !eina_iterator_next(it, &imem) || !imem) /* shouldn't happen... */
3248 {
3249 ret = EINA_FALSE;
3250 }
3251 else
3252 {
3253 if (subtype->convert_to)
3254 ret = subtype->convert_to(subtype, convert, imem, convert_mem);
3255 if ((!ret) && (convert->convert_from))
3256 ret = convert->convert_from(convert, subtype, convert_mem, imem);
3257 }
3258 eina_iterator_free(it);
3259 }
3260
3261 if (!ret)
3262 {
3263 return EINA_FALSE;
3264 }
3265 return EINA_TRUE;
3266 }
3267
3268 static Eina_Bool
_eina_value_type_hash_pset(const Eina_Value_Type * type,void * mem,const void * ptr)3269 _eina_value_type_hash_pset(const Eina_Value_Type *type, void *mem, const void *ptr)
3270 {
3271 Eina_Value_Hash *tmem = mem;
3272 const Eina_Value_Hash *desc = ptr;
3273
3274 if ((!tmem->subtype) && (!desc->subtype))
3275 return EINA_TRUE;
3276
3277 if ((tmem->hash) && (tmem->hash == desc->hash))
3278 {
3279 tmem->subtype = desc->subtype;
3280 return EINA_TRUE;
3281 }
3282
3283 if (desc->hash)
3284 {
3285 Eina_Value_Hash tmp;
3286
3287 if (!_eina_value_type_hash_copy(type, desc, &tmp))
3288 return EINA_FALSE;
3289
3290 _eina_value_type_hash_flush(type, tmem);
3291 memcpy(tmem, &tmp, sizeof(tmp));
3292 return EINA_TRUE;
3293 }
3294
3295 if (tmem->hash) _eina_value_type_hash_flush_elements(tmem);
3296
3297 tmem->subtype = desc->subtype;
3298 if (!_eina_value_type_hash_create(tmem))
3299 return EINA_FALSE;
3300
3301 return EINA_TRUE;
3302 }
3303
3304 static Eina_Bool
_eina_value_type_hash_vset(const Eina_Value_Type * type,void * mem,va_list args)3305 _eina_value_type_hash_vset(const Eina_Value_Type *type, void *mem, va_list args)
3306 {
3307 const Eina_Value_Hash desc = va_arg(args, Eina_Value_Hash);
3308 _eina_value_type_hash_pset(type, mem, &desc);
3309 return EINA_TRUE;
3310 }
3311
3312 static Eina_Bool
_eina_value_type_hash_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)3313 _eina_value_type_hash_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
3314 {
3315 memcpy(ptr, mem, sizeof(Eina_Value_Hash));
3316 return EINA_TRUE;
3317 }
3318
3319 static const Eina_Value_Type _EINA_VALUE_TYPE_HASH = {
3320 EINA_VALUE_TYPE_VERSION,
3321 sizeof(Eina_Value_Hash),
3322 "Eina_Value_Hash",
3323 _eina_value_type_hash_setup,
3324 _eina_value_type_hash_flush,
3325 _eina_value_type_hash_copy,
3326 _eina_value_type_hash_compare,
3327 _eina_value_type_hash_convert_to,
3328 NULL, /* no convert from */
3329 _eina_value_type_hash_vset,
3330 _eina_value_type_hash_pset,
3331 _eina_value_type_hash_pget
3332 };
3333
3334 static Eina_Bool
_eina_value_type_timeval_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)3335 _eina_value_type_timeval_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
3336 {
3337 memset(mem, 0, sizeof(struct timeval));
3338 return EINA_TRUE;
3339 }
3340
3341 static Eina_Bool
_eina_value_type_timeval_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem EINA_UNUSED)3342 _eina_value_type_timeval_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem EINA_UNUSED)
3343 {
3344 return EINA_TRUE;
3345 }
3346
3347 static Eina_Bool
_eina_value_type_timeval_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)3348 _eina_value_type_timeval_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
3349 {
3350 const struct timeval *s = src;
3351 struct timeval *d = dst;
3352 *d = *s;
3353 return EINA_TRUE;
3354 }
3355
_eina_value_type_timeval_fix(const struct timeval * input)3356 static inline struct timeval _eina_value_type_timeval_fix(const struct timeval *input)
3357 {
3358 struct timeval ret = *input;
3359 if (EINA_UNLIKELY(ret.tv_usec < 0))
3360 {
3361 ret.tv_sec -= 1;
3362 ret.tv_usec += 1e6;
3363 }
3364 return ret;
3365 }
3366
3367 static int
_eina_value_type_timeval_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)3368 _eina_value_type_timeval_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
3369 {
3370 struct timeval va = _eina_value_type_timeval_fix(a);
3371 struct timeval vb = _eina_value_type_timeval_fix(b);
3372
3373 if (va.tv_sec < vb.tv_sec)
3374 return -1;
3375 else if (va.tv_sec > vb.tv_sec)
3376 return 1;
3377
3378 if (va.tv_usec < vb.tv_usec)
3379 return -1;
3380 else if (va.tv_usec > vb.tv_usec)
3381 return 1;
3382
3383 return 0;
3384 }
3385
3386 static Eina_Bool
_eina_value_type_timeval_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)3387 _eina_value_type_timeval_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
3388 {
3389 struct timeval v = _eina_value_type_timeval_fix(type_mem);
3390
3391 if (convert == EINA_VALUE_TYPE_UCHAR)
3392 {
3393 unsigned char other_mem = v.tv_sec;
3394 if (EINA_UNLIKELY(v.tv_sec < 0))
3395 return EINA_FALSE;
3396 if (EINA_UNLIKELY(v.tv_sec > eina_value_uchar_max))
3397 return EINA_FALSE;
3398 return eina_value_type_pset(convert, convert_mem, &other_mem);
3399 }
3400 else if (convert == EINA_VALUE_TYPE_USHORT)
3401 {
3402 unsigned short other_mem = v.tv_sec;
3403 if (EINA_UNLIKELY(v.tv_sec < 0))
3404 return EINA_FALSE;
3405 if (EINA_UNLIKELY(v.tv_sec > eina_value_ushort_max))
3406 return EINA_FALSE;
3407 return eina_value_type_pset(convert, convert_mem, &other_mem);
3408 }
3409 else if (convert == EINA_VALUE_TYPE_UINT)
3410 {
3411 unsigned int other_mem = v.tv_sec;
3412 if (EINA_UNLIKELY(v.tv_sec < 0))
3413 return EINA_FALSE;
3414 if (EINA_UNLIKELY((unsigned long) v.tv_sec > eina_value_uint_max))
3415 return EINA_FALSE;
3416 return eina_value_type_pset(convert, convert_mem, &other_mem);
3417 }
3418 else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP))
3419 {
3420 unsigned long other_mem = v.tv_sec;
3421 if (EINA_UNLIKELY(v.tv_sec < 0))
3422 return EINA_FALSE;
3423 if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) &&
3424 ((unsigned long)v.tv_sec > eina_value_ulong_max)))
3425 return EINA_FALSE;
3426 return eina_value_type_pset(convert, convert_mem, &other_mem);
3427 }
3428 else if (convert == EINA_VALUE_TYPE_UINT64)
3429 {
3430 uint64_t other_mem = v.tv_sec;
3431 if (EINA_UNLIKELY(v.tv_sec < 0))
3432 return EINA_FALSE;
3433 return eina_value_type_pset(convert, convert_mem, &other_mem);
3434 }
3435 else if (convert == EINA_VALUE_TYPE_CHAR)
3436 {
3437 signed char other_mem = v.tv_sec;
3438 if (EINA_UNLIKELY(v.tv_sec < eina_value_char_min))
3439 return EINA_FALSE;
3440 if (EINA_UNLIKELY(v.tv_sec > eina_value_char_max))
3441 return EINA_FALSE;
3442 return eina_value_type_pset(convert, convert_mem, &other_mem);
3443 }
3444 else if (convert == EINA_VALUE_TYPE_SHORT)
3445 {
3446 short other_mem = v.tv_sec;
3447 if (EINA_UNLIKELY(v.tv_sec < eina_value_short_min))
3448 return EINA_FALSE;
3449 if (EINA_UNLIKELY(v.tv_sec > eina_value_short_max))
3450 return EINA_FALSE;
3451 return eina_value_type_pset(convert, convert_mem, &other_mem);
3452 }
3453 else if ((convert == EINA_VALUE_TYPE_INT) || (convert == EINA_VALUE_TYPE_ERROR))
3454 {
3455 int other_mem = v.tv_sec;
3456 if (EINA_UNLIKELY(v.tv_sec < eina_value_int_min))
3457 return EINA_FALSE;
3458 if (EINA_UNLIKELY(v.tv_sec > eina_value_int_max))
3459 return EINA_FALSE;
3460 return eina_value_type_pset(convert, convert_mem, &other_mem);
3461 }
3462 else if (convert == EINA_VALUE_TYPE_LONG)
3463 {
3464 long other_mem = v.tv_sec;
3465 if (EINA_UNLIKELY(v.tv_sec < eina_value_long_min))
3466 return EINA_FALSE;
3467 if (EINA_UNLIKELY(v.tv_sec > eina_value_long_max))
3468 return EINA_FALSE;
3469 return eina_value_type_pset(convert, convert_mem, &other_mem);
3470 }
3471 else if (convert == EINA_VALUE_TYPE_INT64)
3472 {
3473 int64_t other_mem = v.tv_sec;
3474 return eina_value_type_pset(convert, convert_mem, &other_mem);
3475 }
3476 else if (convert == EINA_VALUE_TYPE_FLOAT)
3477 {
3478 float other_mem = (float)v.tv_sec + (float)v.tv_usec / 1.0e6;
3479 return eina_value_type_pset(convert, convert_mem, &other_mem);
3480 }
3481 else if (convert == EINA_VALUE_TYPE_DOUBLE)
3482 {
3483 double other_mem = (double)v.tv_sec + (double)v.tv_usec / 1.0e6;
3484 return eina_value_type_pset(convert, convert_mem, &other_mem);
3485 }
3486 else if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
3487 convert == EINA_VALUE_TYPE_STRING)
3488 {
3489 char buf[64];
3490 const char *other_mem;
3491 time_t t;
3492
3493 t = v.tv_sec;
3494 strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&t));
3495 other_mem = buf; /* required due &buf == buf */
3496 return eina_value_type_pset(convert, convert_mem, &other_mem);
3497 }
3498 else
3499 {
3500 return EINA_FALSE;
3501 }
3502 }
3503
3504 static Eina_Bool
_eina_value_type_timeval_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)3505 _eina_value_type_timeval_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
3506 {
3507 struct timeval *tmem = mem;
3508 *tmem = _eina_value_type_timeval_fix(ptr);
3509 return EINA_TRUE;
3510 }
3511
3512 static Eina_Bool
_eina_value_type_timeval_vset(const Eina_Value_Type * type,void * mem,va_list args)3513 _eina_value_type_timeval_vset(const Eina_Value_Type *type, void *mem, va_list args)
3514 {
3515 const struct timeval desc = va_arg(args, struct timeval);
3516 _eina_value_type_timeval_pset(type, mem, &desc);
3517 return EINA_TRUE;
3518 }
3519
3520 static Eina_Bool
_eina_value_type_timeval_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)3521 _eina_value_type_timeval_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
3522 {
3523 memcpy(ptr, mem, sizeof(struct timeval));
3524 return EINA_TRUE;
3525 }
3526
3527 static const Eina_Value_Type _EINA_VALUE_TYPE_TIMEVAL = {
3528 EINA_VALUE_TYPE_VERSION,
3529 sizeof(struct timeval),
3530 "struct timeval",
3531 _eina_value_type_timeval_setup,
3532 _eina_value_type_timeval_flush,
3533 _eina_value_type_timeval_copy,
3534 _eina_value_type_timeval_compare,
3535 _eina_value_type_timeval_convert_to,
3536 NULL, /* no convert from */
3537 _eina_value_type_timeval_vset,
3538 _eina_value_type_timeval_pset,
3539 _eina_value_type_timeval_pget
3540 };
3541
3542 static Eina_Bool
_eina_value_type_tm_setup(const Eina_Value_Type * type,void * mem)3543 _eina_value_type_tm_setup(const Eina_Value_Type *type, void *mem)
3544 {
3545 memset(mem, 0, type->value_size);
3546 return EINA_TRUE;
3547 }
3548
3549 static Eina_Bool
_eina_value_type_tm_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem EINA_UNUSED)3550 _eina_value_type_tm_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem EINA_UNUSED)
3551 {
3552 return EINA_TRUE;
3553 }
3554
3555 static Eina_Bool
_eina_value_type_tm_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)3556 _eina_value_type_tm_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void * dst)
3557 {
3558 struct tm *tmsrc = (struct tm *)src;
3559 struct tm *tmdst = dst;
3560 *tmdst = *tmsrc;
3561 return EINA_TRUE;
3562 }
3563
3564 static int
_eina_value_type_tm_compare(const Eina_Value_Type * type,const void * a,const void * b)3565 _eina_value_type_tm_compare(const Eina_Value_Type *type, const void *a, const void *b)
3566 {
3567 struct tm tma = *(struct tm*)a;
3568 struct tm tmb = *(struct tm*)b;
3569 time_t ta, tb;
3570 struct timeval tva = {0}, tvb = {0};
3571
3572 ta = mktime(&tma);
3573 tb = mktime(&tmb);
3574 tva.tv_sec = ta;
3575 tvb.tv_sec = tb;
3576
3577 return _eina_value_type_timeval_compare(type, &tva, &tvb);
3578 }
3579
3580 static Eina_Bool
_eina_value_type_tm_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)3581 _eina_value_type_tm_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
3582 {
3583 *(struct tm*)mem = *(struct tm*)ptr;
3584 return EINA_TRUE;
3585 }
3586
3587 static Eina_Bool
_eina_value_type_tm_vset(const Eina_Value_Type * type,void * mem,va_list args)3588 _eina_value_type_tm_vset(const Eina_Value_Type *type, void *mem, va_list args)
3589 {
3590 const struct tm tm_val = va_arg(args, struct tm);
3591 return _eina_value_type_tm_pset(type, mem, &tm_val);
3592 }
3593
3594 static Eina_Bool
_eina_value_type_tm_pget(const Eina_Value_Type * type,const void * mem,void * ptr)3595 _eina_value_type_tm_pget(const Eina_Value_Type *type, const void *mem, void *ptr)
3596 {
3597 memcpy(ptr, mem, type->value_size);
3598 return EINA_TRUE;
3599 }
3600
3601 static Eina_Bool
_eina_value_type_tm_convert_to(const Eina_Value_Type * type,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)3602 _eina_value_type_tm_convert_to(const Eina_Value_Type *type, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
3603 {
3604 struct tm tmv = *(struct tm *)type_mem;
3605 time_t t = mktime(&tmv);
3606 struct timeval v = {t, 0};
3607
3608 if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
3609 convert == EINA_VALUE_TYPE_STRING)
3610 {
3611 const char *other_mem;
3612 char buf[64];
3613
3614 strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tmv);
3615 other_mem = buf; /* required due &buf == buf */
3616 return eina_value_type_pset(convert, convert_mem, &other_mem);
3617 }
3618 else
3619 return _eina_value_type_timeval_convert_to(type, convert, &v, convert_mem);
3620 }
3621
3622 static const Eina_Value_Type _EINA_VALUE_TYPE_TM = {
3623 EINA_VALUE_TYPE_VERSION,
3624 sizeof(struct tm),
3625 "struct tm",
3626 _eina_value_type_tm_setup,
3627 _eina_value_type_tm_flush,
3628 _eina_value_type_tm_copy,
3629 _eina_value_type_tm_compare,
3630 _eina_value_type_tm_convert_to,
3631 NULL, //No convert from
3632 _eina_value_type_tm_vset,
3633 _eina_value_type_tm_pset,
3634 _eina_value_type_tm_pget
3635 };
3636
3637 static Eina_Bool
_eina_value_type_blob_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)3638 _eina_value_type_blob_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
3639 {
3640 memset(mem, 0, sizeof(Eina_Value_Blob));
3641 return EINA_TRUE;
3642 }
3643
3644 static inline const Eina_Value_Blob_Operations *
_eina_value_type_blob_ops_get(const Eina_Value_Blob * blob)3645 _eina_value_type_blob_ops_get(const Eina_Value_Blob *blob)
3646 {
3647 if (!blob) return NULL;
3648 if (!blob->ops) return NULL;
3649 EINA_SAFETY_ON_FALSE_RETURN_VAL
3650 (blob->ops->version == EINA_VALUE_BLOB_OPERATIONS_VERSION, NULL);
3651 return blob->ops;
3652 }
3653
3654 static Eina_Bool
_eina_value_type_blob_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem)3655 _eina_value_type_blob_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem)
3656 {
3657 const Eina_Value_Blob_Operations *ops = _eina_value_type_blob_ops_get(mem);
3658 Eina_Value_Blob *tmem = mem;
3659 if ((ops) && (ops->free))
3660 ops->free(ops, (void *)tmem->memory, tmem->size);
3661 tmem->memory = NULL;
3662 tmem->size = 0;
3663 return EINA_TRUE;
3664 }
3665
3666 static Eina_Bool
_eina_value_type_blob_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)3667 _eina_value_type_blob_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
3668 {
3669 const Eina_Value_Blob_Operations *ops = _eina_value_type_blob_ops_get(src);
3670 const Eina_Value_Blob *s = src;
3671 Eina_Value_Blob *d = dst;
3672
3673 *d = *s;
3674
3675 if ((ops) && (ops->copy))
3676 {
3677 d->memory = ops->copy(ops, s->memory, s->size);
3678 if ((d->memory == NULL) && (s->size > 0))
3679 return EINA_FALSE;
3680 }
3681
3682 return EINA_TRUE;
3683 }
3684
3685 static int
_eina_value_type_blob_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)3686 _eina_value_type_blob_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
3687 {
3688 const Eina_Value_Blob_Operations *ops = _eina_value_type_blob_ops_get(a);
3689 const Eina_Value_Blob *ta = a, *tb = b;
3690 size_t minsize;
3691 if (ta->ops != tb->ops)
3692 {
3693 return -1;
3694 }
3695 if ((ops) && (ops->compare))
3696 return ops->compare(ops, ta->memory, ta->size, tb->memory, tb->size);
3697
3698 if (ta->size < tb->size)
3699 minsize = ta->size;
3700 else
3701 minsize = tb->size;
3702
3703 return memcmp(ta->memory, tb->memory, minsize);
3704 }
3705
3706 static Eina_Bool
_eina_value_type_blob_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)3707 _eina_value_type_blob_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
3708 {
3709 const Eina_Value_Blob *tmem = type_mem;
3710
3711 if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
3712 convert == EINA_VALUE_TYPE_STRING)
3713 {
3714 const Eina_Value_Blob_Operations *ops;
3715 Eina_Strbuf *str;
3716 const char *other_mem;
3717 Eina_Bool ret = EINA_FALSE, first = EINA_TRUE;
3718 const unsigned char *ptr, *ptr_end;
3719
3720 ops = _eina_value_type_blob_ops_get(tmem);
3721 if ((ops) && (ops->to_string))
3722 {
3723 char *x = ops->to_string(ops, tmem->memory, tmem->size);
3724 if (x)
3725 {
3726 ret = eina_value_type_pset(convert, convert_mem, &x);
3727 free(x);
3728 }
3729 return ret;
3730 }
3731
3732 str = eina_strbuf_new();
3733 if (!str)
3734 return EINA_FALSE;
3735
3736 if (!eina_strbuf_append_printf(str, "BLOB(%u, [", tmem->size))
3737 goto error;
3738
3739 ptr = tmem->memory;
3740 ptr_end = ptr + tmem->size;
3741 for (; ptr < ptr_end; ptr++)
3742 {
3743 if (first)
3744 {
3745 first = EINA_FALSE;
3746 if (!eina_strbuf_append_printf(str, "%02hhx", *ptr))
3747 goto error;
3748 }
3749 else
3750 {
3751 if (!eina_strbuf_append_printf(str, " %02hhx", *ptr))
3752 goto error;
3753 }
3754 }
3755
3756 if (!eina_strbuf_append(str, "])"))
3757 goto error;
3758
3759 other_mem = eina_strbuf_string_get(str);
3760 ret = eina_value_type_pset(convert, convert_mem, &other_mem);
3761
3762 error:
3763 eina_strbuf_free(str);
3764 return ret;
3765 }
3766 else
3767 {
3768 return EINA_FALSE;
3769 }
3770 }
3771
3772 static Eina_Bool
_eina_value_type_blob_convert_from(const Eina_Value_Type * type,const Eina_Value_Type * convert,void * type_mem,const void * convert_mem)3773 _eina_value_type_blob_convert_from(const Eina_Value_Type *type, const Eina_Value_Type *convert, void *type_mem, const void *convert_mem)
3774 {
3775 Eina_Value_Blob desc;
3776 char *buf;
3777
3778 desc.ops = EINA_VALUE_BLOB_OPERATIONS_MALLOC;
3779
3780 if ((convert == EINA_VALUE_TYPE_STRING) ||
3781 (convert == EINA_VALUE_TYPE_STRINGSHARE))
3782 {
3783 const char *str = *(const char **)convert_mem;
3784 if (!str)
3785 {
3786 desc.size = 0;
3787 desc.memory = NULL;
3788 }
3789 else
3790 {
3791 desc.size = strlen(str) + 1;
3792 desc.memory = buf = malloc(desc.size);
3793 if (!desc.memory)
3794 {
3795 return EINA_FALSE;
3796 }
3797 memcpy(buf, str, desc.size);
3798 }
3799 }
3800 else if (convert == EINA_VALUE_TYPE_ARRAY)
3801 {
3802 const Eina_Value_Array *a = convert_mem;
3803 if ((!a->array) || (a->array->len == 0))
3804 {
3805 desc.size = 0;
3806 desc.memory = NULL;
3807 }
3808 else
3809 {
3810 desc.size = a->array->len * a->array->member_size;
3811 desc.memory = buf = malloc(desc.size);
3812 if (!desc.memory)
3813 {
3814 return EINA_FALSE;
3815 }
3816 memcpy(buf, a->array->members, desc.size);
3817 }
3818 }
3819 else if (convert == EINA_VALUE_TYPE_BLOB)
3820 {
3821 const Eina_Value_Blob *b = convert_mem;
3822 if (b->size == 0)
3823 {
3824 desc.size = 0;
3825 desc.memory = NULL;
3826 }
3827 else
3828 {
3829 desc.size = b->size;
3830 desc.memory = buf = malloc(desc.size);
3831 if (!desc.memory)
3832 {
3833 return EINA_FALSE;
3834 }
3835 memcpy(buf, b->memory, desc.size);
3836 }
3837 }
3838 else
3839 {
3840 desc.size = convert->value_size;
3841 desc.memory = buf = malloc(convert->value_size);
3842 if (!desc.memory)
3843 {
3844 return EINA_FALSE;
3845 }
3846 if (!eina_value_type_pget(convert, convert_mem, buf))
3847 {
3848 free(buf);
3849 return EINA_FALSE;
3850 }
3851 }
3852 return eina_value_type_pset(type, type_mem, &desc);
3853 }
3854
3855 static Eina_Bool
_eina_value_type_blob_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)3856 _eina_value_type_blob_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
3857 {
3858 const Eina_Value_Blob_Operations *ops = _eina_value_type_blob_ops_get(mem);
3859 Eina_Value_Blob *tmem = mem;
3860 const Eina_Value_Blob *desc = ptr;
3861
3862 if ((tmem->memory) && (tmem->memory == desc->memory))
3863 {
3864 tmem->ops = desc->ops;
3865 tmem->size = desc->size;
3866 return EINA_TRUE;
3867 }
3868
3869 if ((ops) && (ops->free))
3870 ops->free(ops, (void *)tmem->memory, tmem->size);
3871
3872 *tmem = *desc;
3873 return EINA_TRUE;
3874 }
3875
3876 static Eina_Bool
_eina_value_type_blob_vset(const Eina_Value_Type * type,void * mem,va_list args)3877 _eina_value_type_blob_vset(const Eina_Value_Type *type, void *mem, va_list args)
3878 {
3879 const Eina_Value_Blob desc = va_arg(args, Eina_Value_Blob);
3880 _eina_value_type_blob_pset(type, mem, &desc);
3881 return EINA_TRUE;
3882 }
3883
3884 static Eina_Bool
_eina_value_type_blob_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)3885 _eina_value_type_blob_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
3886 {
3887 memcpy(ptr, mem, sizeof(Eina_Value_Blob));
3888 return EINA_TRUE;
3889 }
3890
3891 static const Eina_Value_Type _EINA_VALUE_TYPE_BLOB = {
3892 EINA_VALUE_TYPE_VERSION,
3893 sizeof(Eina_Value_Blob),
3894 "Eina_Value_Blob",
3895 _eina_value_type_blob_setup,
3896 _eina_value_type_blob_flush,
3897 _eina_value_type_blob_copy,
3898 _eina_value_type_blob_compare,
3899 _eina_value_type_blob_convert_to,
3900 _eina_value_type_blob_convert_from,
3901 _eina_value_type_blob_vset,
3902 _eina_value_type_blob_pset,
3903 _eina_value_type_blob_pget
3904 };
3905
3906 static Eina_Bool
_eina_value_type_value_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)3907 _eina_value_type_value_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
3908 {
3909 Eina_Value *v = mem;
3910 memset(v, 0, sizeof(Eina_Value));
3911 return EINA_TRUE;
3912 }
3913
3914 static Eina_Bool
_eina_value_type_value_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem)3915 _eina_value_type_value_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem)
3916 {
3917 Eina_Value *v = mem;
3918 eina_value_flush(v);
3919 return EINA_TRUE;
3920 }
3921
3922 static Eina_Bool
_eina_value_type_value_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)3923 _eina_value_type_value_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
3924 {
3925 const Eina_Value *v_src = src;
3926 Eina_Value *v_dst = dst;
3927 return eina_value_copy(v_src, v_dst);
3928 }
3929
3930 static int
_eina_value_type_value_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)3931 _eina_value_type_value_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
3932 {
3933 const Eina_Value *v1 = a;
3934 const Eina_Value *v2 = b;
3935 return eina_value_compare(v1, v2);
3936 }
3937
3938 static Eina_Bool
_eina_value_type_value_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)3939 _eina_value_type_value_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
3940 {
3941 const Eina_Value *v = type_mem;
3942 return eina_value_type_convert_to(v->type, convert, eina_value_memory_get(v), convert_mem);
3943 }
3944
3945 static Eina_Bool
_eina_value_type_value_convert_from(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,void * type_mem,const void * convert_mem)3946 _eina_value_type_value_convert_from(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, void *type_mem, const void *convert_mem)
3947 {
3948 Eina_Value *v = type_mem;
3949 return eina_value_type_convert_from(v->type, convert, eina_value_memory_get(v), convert_mem);
3950 }
3951
3952 static Eina_Bool
_eina_value_type_value_vset(const Eina_Value_Type * type EINA_UNUSED,void * mem,va_list args)3953 _eina_value_type_value_vset(const Eina_Value_Type *type EINA_UNUSED, void *mem, va_list args)
3954 {
3955 Eina_Value *dst = mem;
3956 Eina_Value src = va_arg(args, Eina_Value);
3957
3958 return eina_value_copy(&src, dst);
3959 }
3960
3961 static Eina_Bool
_eina_value_type_value_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)3962 _eina_value_type_value_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
3963 {
3964 Eina_Value *dst = mem;
3965 const Eina_Value *src = ptr;
3966
3967 return eina_value_copy(src, dst);
3968 }
3969
3970 static Eina_Bool
_eina_value_type_value_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)3971 _eina_value_type_value_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
3972 {
3973 const Eina_Value *src = mem;
3974 Eina_Value *dst = ptr;
3975 return eina_value_copy(src, dst);
3976 }
3977
3978 static const Eina_Value_Type _EINA_VALUE_TYPE_VALUE = {
3979 EINA_VALUE_TYPE_VERSION,
3980 sizeof(Eina_Value),
3981 "Eina_Value",
3982 _eina_value_type_value_setup,
3983 _eina_value_type_value_flush,
3984 _eina_value_type_value_copy,
3985 _eina_value_type_value_compare,
3986 _eina_value_type_value_convert_to,
3987 _eina_value_type_value_convert_from,
3988 _eina_value_type_value_vset,
3989 _eina_value_type_value_pset,
3990 _eina_value_type_value_pget
3991 };
3992
3993 static int
_eina_value_struct_operations_binsearch_cmp(const void * pa,const void * pb)3994 _eina_value_struct_operations_binsearch_cmp(const void *pa, const void *pb)
3995 {
3996 const Eina_Value_Struct_Member *a = pa, *b = pb;
3997 return strcmp(a->name, b->name);
3998 }
3999
4000 static const Eina_Value_Struct_Member *
_eina_value_struct_operations_binsearch_find_member(const Eina_Value_Struct_Operations * ops EINA_UNUSED,const Eina_Value_Struct_Desc * desc,const char * name)4001 _eina_value_struct_operations_binsearch_find_member(const Eina_Value_Struct_Operations *ops EINA_UNUSED, const Eina_Value_Struct_Desc *desc, const char *name)
4002 {
4003 unsigned int count = desc->member_count;
4004 Eina_Value_Struct_Member search;
4005 if (count == 0)
4006 {
4007 const Eina_Value_Struct_Member *itr = desc->members;
4008 for (; itr->name != NULL; itr++)
4009 count++;
4010 }
4011
4012 search.name = name;
4013 return bsearch(&search, desc->members, count,
4014 sizeof(Eina_Value_Struct_Member),
4015 _eina_value_struct_operations_binsearch_cmp);
4016 }
4017
4018 static Eina_Value_Struct_Operations _EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH = {
4019 EINA_VALUE_STRUCT_OPERATIONS_VERSION,
4020 NULL, /* default alloc */
4021 NULL, /* default free */
4022 NULL, /* default copy */
4023 NULL, /* default compare */
4024 _eina_value_struct_operations_binsearch_find_member
4025 };
4026
4027 static const Eina_Value_Struct_Member *
_eina_value_struct_operations_stringshare_find_member(const Eina_Value_Struct_Operations * ops EINA_UNUSED,const Eina_Value_Struct_Desc * desc,const char * name)4028 _eina_value_struct_operations_stringshare_find_member(const Eina_Value_Struct_Operations *ops EINA_UNUSED, const Eina_Value_Struct_Desc *desc, const char *name)
4029 {
4030 const Eina_Value_Struct_Member *itr = desc->members;
4031
4032 /* assumes name is stringshared.
4033 *
4034 * we do this because it's the recommended usage pattern, moreover
4035 * we expect to find the member, as users shouldn't look for
4036 * non-existent members!
4037 */
4038 if (desc->member_count > 0)
4039 {
4040 const Eina_Value_Struct_Member *itr_end = itr + desc->member_count;
4041 for (; itr < itr_end; itr++)
4042 if (itr->name == name)
4043 return itr;
4044 }
4045 else
4046 {
4047 for (; itr->name != NULL; itr++)
4048 if (itr->name == name)
4049 return itr;
4050 }
4051
4052 itr = desc->members;
4053 name = eina_stringshare_add(name);
4054 eina_stringshare_del(name); /* we'll not use the contents, this is fine */
4055 /* stringshare and look again */
4056 if (desc->member_count > 0)
4057 {
4058 const Eina_Value_Struct_Member *itr_end = itr + desc->member_count;
4059 for (; itr < itr_end; itr++)
4060 if (itr->name == name)
4061 return itr;
4062 }
4063 else
4064 {
4065 for (; itr->name != NULL; itr++)
4066 if (itr->name == name)
4067 return itr;
4068 }
4069
4070 return NULL;
4071 }
4072
4073 static Eina_Value_Struct_Operations _EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE = {
4074 EINA_VALUE_STRUCT_OPERATIONS_VERSION,
4075 NULL, /* default alloc */
4076 NULL, /* default free */
4077 NULL, /* default copy */
4078 NULL, /* default compare */
4079 _eina_value_struct_operations_stringshare_find_member
4080 };
4081
4082 static inline const Eina_Value_Struct_Operations *
_eina_value_type_struct_ops_get(const Eina_Value_Struct * st)4083 _eina_value_type_struct_ops_get(const Eina_Value_Struct *st)
4084 {
4085 if (!st) return NULL;
4086 if (!st->desc) return NULL;
4087 if (!st->desc->ops) return NULL;
4088 EINA_SAFETY_ON_FALSE_RETURN_VAL
4089 (st->desc->ops->version == EINA_VALUE_STRUCT_OPERATIONS_VERSION, NULL);
4090 return st->desc->ops;
4091 }
4092
4093 EAPI const Eina_Value_Struct_Member *
eina_value_struct_member_find(const Eina_Value_Struct * st,const char * name)4094 eina_value_struct_member_find(const Eina_Value_Struct *st, const char *name)
4095 {
4096 const Eina_Value_Struct_Operations *ops;
4097 const Eina_Value_Struct_Member *itr;
4098
4099 EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
4100 EINA_SAFETY_ON_NULL_RETURN_VAL(st->desc, NULL);
4101
4102 ops = _eina_value_type_struct_ops_get(st);
4103 if ((ops) && (ops->find_member))
4104 return ops->find_member(ops, st->desc, name);
4105
4106 itr = st->desc->members;
4107 if (st->desc->member_count)
4108 {
4109 const Eina_Value_Struct_Member *itr_end = itr + st->desc->member_count;
4110 for (; itr < itr_end; itr++)
4111 {
4112 if (strcmp(name, itr->name) == 0)
4113 return itr;
4114 }
4115 return NULL;
4116 }
4117 else
4118 {
4119 for (; itr->name != NULL; itr++)
4120 {
4121 if (strcmp(name, itr->name) == 0)
4122 return itr;
4123 }
4124 return NULL;
4125 }
4126 }
4127
4128 static Eina_Bool
_eina_value_type_struct_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)4129 _eina_value_type_struct_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
4130 {
4131 memset(mem, 0, sizeof(Eina_Value_Struct));
4132 return EINA_TRUE;
4133 }
4134
4135 static Eina_Bool
_eina_value_type_struct_setup_member(const Eina_Value_Struct_Member * member,Eina_Value_Struct * st)4136 _eina_value_type_struct_setup_member(const Eina_Value_Struct_Member *member, Eina_Value_Struct *st)
4137 {
4138 unsigned char *base = st->memory;
4139 return eina_value_type_setup(member->type, base + member->offset);
4140 }
4141
4142 static Eina_Bool
_eina_value_type_struct_flush_member(const Eina_Value_Struct_Member * member,Eina_Value_Struct * st)4143 _eina_value_type_struct_flush_member(const Eina_Value_Struct_Member *member, Eina_Value_Struct *st)
4144 {
4145 unsigned char *base = st->memory;
4146 return eina_value_type_flush(member->type, base + member->offset);
4147 }
4148
4149 static Eina_Bool
_eina_value_type_struct_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem)4150 _eina_value_type_struct_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem)
4151 {
4152 const Eina_Value_Struct_Operations *ops;
4153 const Eina_Value_Struct_Member *itr;
4154 Eina_Value_Struct *tmem = mem;
4155 Eina_Bool ret = EINA_TRUE;
4156
4157 if ((!tmem->desc) || (!tmem->memory))
4158 return EINA_TRUE;
4159
4160 itr = tmem->desc->members;
4161 if (tmem->desc->member_count > 0)
4162 {
4163 const Eina_Value_Struct_Member *itr_end;
4164 itr_end = itr + tmem->desc->member_count;
4165 for (; itr < itr_end; itr++)
4166 ret &= _eina_value_type_struct_flush_member(itr, tmem);
4167 }
4168 else
4169 {
4170 for (; itr->name != NULL; itr++)
4171 ret &= _eina_value_type_struct_flush_member(itr, tmem);
4172 }
4173
4174 ops = _eina_value_type_struct_ops_get(mem);
4175 if ((ops) && (ops->free))
4176 ops->free(ops, tmem->desc, tmem->memory);
4177 else
4178 free(tmem->memory);
4179
4180 tmem->memory = NULL;
4181 tmem->desc = NULL;
4182
4183 return ret;
4184 }
4185
4186 static Eina_Bool
_eina_value_type_struct_copy_member(const Eina_Value_Struct_Member * member,const Eina_Value_Struct * s,Eina_Value_Struct * d)4187 _eina_value_type_struct_copy_member(const Eina_Value_Struct_Member *member, const Eina_Value_Struct *s, Eina_Value_Struct *d)
4188 {
4189 const unsigned char *base_s = s->memory;
4190 unsigned char *base_d = d->memory;
4191 return eina_value_type_copy(member->type,
4192 base_s + member->offset,
4193 base_d + member->offset);
4194 }
4195
4196 static Eina_Bool
_eina_value_type_struct_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)4197 _eina_value_type_struct_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
4198 {
4199 const Eina_Value_Struct_Operations *ops;
4200 const Eina_Value_Struct_Member *itr;
4201 const Eina_Value_Struct *s = src;
4202 Eina_Value_Struct *d = dst;
4203
4204 *d = *s;
4205
4206 if ((!s->desc) || (!s->memory))
4207 return EINA_TRUE;
4208
4209 ops = _eina_value_type_struct_ops_get(src);
4210 if ((ops) && (ops->copy))
4211 {
4212 d->memory = ops->copy(ops, s->desc, s->memory);
4213 if (d->memory == NULL)
4214 return EINA_FALSE;
4215 return EINA_TRUE;
4216 }
4217
4218 if ((ops) && (ops->alloc))
4219 d->memory = ops->alloc(ops, s->desc);
4220 else
4221 d->memory = malloc(s->desc->size);
4222 if (!d->memory)
4223 {
4224 return EINA_FALSE;
4225 }
4226
4227 itr = s->desc->members;
4228 if (s->desc->member_count > 0)
4229 {
4230 const Eina_Value_Struct_Member *itr_end = itr + s->desc->member_count;
4231 for (; itr < itr_end; itr++)
4232 if (!_eina_value_type_struct_copy_member(itr, s, d))
4233 goto error;
4234 }
4235 else
4236 {
4237 for (; itr->name != NULL; itr++)
4238 if (!_eina_value_type_struct_copy_member(itr, s, d))
4239 goto error;
4240 }
4241
4242 return EINA_TRUE;
4243
4244 error:
4245 itr--;
4246 for (; itr >= s->desc->members; itr--)
4247 _eina_value_type_struct_flush_member(itr, d);
4248
4249 if ((ops) && (ops->free))
4250 ops->free(ops, s->desc, d->memory);
4251 else
4252 free(d->memory);
4253 return EINA_FALSE;
4254 }
4255
4256 static inline int
_eina_value_type_struct_compare_member(const Eina_Value_Struct_Member * member,const Eina_Value_Struct * ta,const Eina_Value_Struct * tb)4257 _eina_value_type_struct_compare_member(const Eina_Value_Struct_Member *member, const Eina_Value_Struct *ta, const Eina_Value_Struct *tb)
4258 {
4259 const unsigned char *base_a = ta->memory;
4260 const unsigned char *base_b = tb->memory;
4261 return eina_value_type_compare(member->type,
4262 base_a + member->offset,
4263 base_b + member->offset);
4264 }
4265
4266 static int
_eina_value_type_struct_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)4267 _eina_value_type_struct_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
4268 {
4269 const Eina_Value_Struct_Operations *ops = _eina_value_type_struct_ops_get(a);
4270 const Eina_Value_Struct *ta = a, *tb = b;
4271 const Eina_Value_Struct_Member *itr;
4272 int cmp = 0;
4273
4274 if ((!ta->desc) && (!tb->desc))
4275 return 0;
4276 else if (ta->desc != tb->desc)
4277 {
4278 return -1;
4279 }
4280 if (ta->desc->ops != tb->desc->ops)
4281 {
4282 return -1;
4283 }
4284 if ((!ta->memory) && (!tb->memory))
4285 return 0;
4286 else if (!ta->memory)
4287 return -1;
4288 else if (!tb->memory)
4289 return 1;
4290
4291 if ((ops) && (ops->compare))
4292 return ops->compare(ops, ta->desc, ta->memory, tb->memory);
4293
4294 itr = ta->desc->members;
4295 if (ta->desc->member_count > 0)
4296 {
4297 const Eina_Value_Struct_Member *itr_end = itr + ta->desc->member_count;
4298 for (; (cmp == 0) && (itr < itr_end); itr++)
4299 cmp = _eina_value_type_struct_compare_member(itr, ta, tb);
4300 }
4301 else
4302 {
4303 for (; (cmp == 0) && (itr->name != NULL); itr++)
4304 cmp = _eina_value_type_struct_compare_member(itr, ta, tb);
4305 }
4306 return cmp;
4307 }
4308
4309 static void
_eina_value_type_struct_convert_to_string_member(const Eina_Value_Struct * st,const Eina_Value_Struct_Member * member,Eina_Strbuf * str)4310 _eina_value_type_struct_convert_to_string_member(const Eina_Value_Struct *st, const Eina_Value_Struct_Member *member, Eina_Strbuf *str)
4311 {
4312 const unsigned char *p = st->memory;
4313 Eina_Bool first = st->desc->members == member;
4314 Eina_Bool r = EINA_FALSE;
4315
4316 if (first) eina_strbuf_append_printf(str, "%s: ", member->name);
4317 else eina_strbuf_append_printf(str, ", %s: ", member->name);
4318
4319 if ((member->type) && (member->type->convert_to))
4320 {
4321 const Eina_Value_Type *type = member->type;
4322 char *conv = NULL;
4323
4324 r = eina_value_type_convert_to(type, EINA_VALUE_TYPE_STRING,
4325 p + member->offset, &conv);
4326 if (r)
4327 {
4328 eina_strbuf_append(str, conv);
4329 free(conv);
4330 }
4331 }
4332
4333 if (!r)
4334 eina_strbuf_append_char(str, '?');
4335 }
4336
4337 static Eina_Bool
_eina_value_type_struct_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)4338 _eina_value_type_struct_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
4339 {
4340 const Eina_Value_Struct *tmem = type_mem;
4341
4342 if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
4343 convert == EINA_VALUE_TYPE_STRING)
4344 {
4345 Eina_Strbuf *str = eina_strbuf_new();
4346 const char *s;
4347 Eina_Bool ret;
4348
4349 if (!tmem->memory) eina_strbuf_append(str, "{}");
4350 else
4351 {
4352 const Eina_Value_Struct_Member *itr = tmem->desc->members;
4353
4354 eina_strbuf_append_char(str, '{');
4355
4356 if (tmem->desc->member_count > 0)
4357 {
4358 const Eina_Value_Struct_Member *itr_end;
4359
4360 itr_end = itr + tmem->desc->member_count;
4361 for (; itr < itr_end; itr++)
4362 _eina_value_type_struct_convert_to_string_member
4363 (tmem, itr, str);
4364 }
4365 else
4366 {
4367 for (; itr->name != NULL; itr++)
4368 _eina_value_type_struct_convert_to_string_member
4369 (tmem, itr, str);
4370 }
4371
4372 eina_strbuf_append_char(str, '}');
4373 }
4374 s = eina_strbuf_string_get(str);
4375 ret = eina_value_type_pset(convert, convert_mem, &s);
4376 eina_strbuf_free(str);
4377 return ret;
4378 }
4379 else
4380 {
4381 return EINA_FALSE;
4382 }
4383 }
4384
4385 static Eina_Bool
_eina_value_type_struct_desc_check(const Eina_Value_Struct_Desc * desc)4386 _eina_value_type_struct_desc_check(const Eina_Value_Struct_Desc *desc)
4387 {
4388 unsigned int minsize = 0;
4389 const Eina_Value_Struct_Member *itr;
4390
4391 EINA_SAFETY_ON_NULL_RETURN_VAL(desc, EINA_FALSE);
4392 EINA_SAFETY_ON_FALSE_RETURN_VAL
4393 (desc->version == EINA_VALUE_STRUCT_DESC_VERSION, EINA_FALSE);
4394
4395 itr = desc->members;
4396 if (desc->member_count > 0)
4397 {
4398 const Eina_Value_Struct_Member *itr_end = itr + desc->member_count;
4399 for (; itr < itr_end; itr++)
4400 {
4401 unsigned int member_end;
4402
4403 EINA_SAFETY_ON_FALSE_RETURN_VAL
4404 (eina_value_type_check(itr->type), EINA_FALSE);
4405 EINA_SAFETY_ON_FALSE_RETURN_VAL
4406 (itr->type->value_size > 0, EINA_FALSE);
4407
4408 member_end = itr->offset + itr->type->value_size;
4409 if (minsize < member_end)
4410 minsize = member_end;
4411 }
4412 }
4413 else
4414 {
4415 for (; itr->name != NULL; itr++)
4416 {
4417 unsigned int member_end;
4418
4419 EINA_SAFETY_ON_FALSE_RETURN_VAL
4420 (eina_value_type_check(itr->type), EINA_FALSE);
4421 EINA_SAFETY_ON_FALSE_RETURN_VAL
4422 (itr->type->value_size > 0, EINA_FALSE);
4423
4424 member_end = itr->offset + itr->type->value_size;
4425 if (minsize < member_end)
4426 minsize = member_end;
4427 }
4428 }
4429
4430 EINA_SAFETY_ON_FALSE_RETURN_VAL(minsize > 0, EINA_FALSE);
4431 EINA_SAFETY_ON_FALSE_RETURN_VAL(desc->size >= minsize, EINA_FALSE);
4432 return EINA_TRUE;
4433 }
4434
4435 static Eina_Bool
_eina_value_type_struct_pset(const Eina_Value_Type * type,void * mem,const void * ptr)4436 _eina_value_type_struct_pset(const Eina_Value_Type *type, void *mem, const void *ptr)
4437 {
4438 const Eina_Value_Struct_Operations *ops;
4439 Eina_Value_Struct *tmem = mem;
4440 const Eina_Value_Struct *desc = ptr;
4441 const Eina_Value_Struct_Member *itr;
4442
4443 if (!_eina_value_type_struct_desc_check(desc->desc))
4444 {
4445 return EINA_FALSE;
4446 }
4447
4448 if ((tmem->memory) && (tmem->memory == desc->memory))
4449 {
4450 tmem->desc = desc->desc;
4451 return EINA_TRUE;
4452 }
4453
4454 if (desc->memory)
4455 {
4456 Eina_Value_Struct tmp;
4457
4458 if (!_eina_value_type_struct_copy(type, desc, &tmp))
4459 return EINA_FALSE;
4460
4461 _eina_value_type_struct_flush(type, tmem);
4462 memcpy(tmem, &tmp, sizeof(tmp));
4463 return EINA_TRUE;
4464 }
4465
4466 if (tmem->memory) _eina_value_type_struct_flush(type, mem);
4467
4468 tmem->desc = desc->desc;
4469
4470 ops = _eina_value_type_struct_ops_get(desc);
4471 if ((ops) && (ops->alloc))
4472 tmem->memory = ops->alloc(ops, tmem->desc);
4473 else
4474 tmem->memory = malloc(tmem->desc->size);
4475
4476 if (!tmem->memory)
4477 {
4478 return EINA_FALSE;
4479 }
4480
4481 itr = tmem->desc->members;
4482 if (tmem->desc->member_count > 0)
4483 {
4484 const Eina_Value_Struct_Member *itr_end;
4485 itr_end = itr + tmem->desc->member_count;
4486 for (; itr < itr_end; itr++)
4487 if (!_eina_value_type_struct_setup_member(itr, tmem))
4488 goto error;
4489 }
4490 else
4491 {
4492 for (; itr->name != NULL; itr++)
4493 if (!_eina_value_type_struct_setup_member(itr, tmem))
4494 goto error;
4495 }
4496
4497 return EINA_TRUE;
4498
4499 error:
4500 itr--;
4501 for (; itr >= tmem->desc->members; itr--)
4502 _eina_value_type_struct_flush_member(itr, tmem);
4503
4504 if ((ops) && (ops->free))
4505 ops->free(ops, tmem->desc, tmem->memory);
4506 else
4507 free(tmem->memory);
4508 tmem->memory = NULL;
4509 tmem->desc = NULL;
4510 return EINA_FALSE;
4511 }
4512
4513 static Eina_Bool
_eina_value_type_struct_vset(const Eina_Value_Type * type,void * mem,va_list args)4514 _eina_value_type_struct_vset(const Eina_Value_Type *type, void *mem, va_list args)
4515 {
4516 const Eina_Value_Struct desc = va_arg(args, Eina_Value_Struct);
4517 _eina_value_type_struct_pset(type, mem, &desc);
4518 return EINA_TRUE;
4519 }
4520
4521 static Eina_Bool
_eina_value_type_struct_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)4522 _eina_value_type_struct_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
4523 {
4524 memcpy(ptr, mem, sizeof(Eina_Value_Struct));
4525 return EINA_TRUE;
4526 }
4527
4528 static const Eina_Value_Type _EINA_VALUE_TYPE_STRUCT = {
4529 EINA_VALUE_TYPE_VERSION,
4530 sizeof(Eina_Value_Struct),
4531 "Eina_Value_Struct",
4532 _eina_value_type_struct_setup,
4533 _eina_value_type_struct_flush,
4534 _eina_value_type_struct_copy,
4535 _eina_value_type_struct_compare,
4536 _eina_value_type_struct_convert_to,
4537 NULL, /* no convert from */
4538 _eina_value_type_struct_vset,
4539 _eina_value_type_struct_pset,
4540 _eina_value_type_struct_pget
4541 };
4542
4543 static Eina_Bool
_eina_value_type_optional_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)4544 _eina_value_type_optional_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
4545 {
4546 memset(mem, 0, type->value_size);
4547 return EINA_TRUE;
4548 }
4549
4550 static Eina_Bool
_eina_value_type_optional_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem EINA_UNUSED)4551 _eina_value_type_optional_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem EINA_UNUSED)
4552 {
4553 if(sizeof(Eina_Value_Optional_Outer) <= sizeof(Eina_Value_Union))
4554 {
4555 Eina_Value_Optional_Outer* opt = mem;
4556 if(opt->subtype)
4557 {
4558 if(!eina_value_type_flush(opt->subtype, opt->value))
4559 return EINA_FALSE;
4560 free(opt->value);
4561 memset(mem, 0, sizeof(Eina_Value_Optional_Outer));
4562 }
4563 }
4564 else
4565 {
4566 Eina_Value_Optional_Inner* opt = *(void**)mem;
4567 if(opt)
4568 {
4569 if(!eina_value_type_flush(opt->subtype, opt->value))
4570 return EINA_FALSE;
4571 free(*(void**)mem);
4572 *(void**)mem = NULL;
4573 }
4574 }
4575 return EINA_TRUE;
4576 }
4577
4578 EAPI Eina_Bool
eina_value_optional_reset(Eina_Value * value)4579 eina_value_optional_reset(Eina_Value *value)
4580 {
4581 void *mem = eina_value_memory_get(value);
4582 if (!mem)
4583 return EINA_FALSE;
4584 return _eina_value_type_optional_flush(EINA_VALUE_TYPE_OPTIONAL, mem);
4585 }
4586
4587 EAPI Eina_Value*
eina_value_optional_new(Eina_Value_Type const * subtype,const void * initial_value)4588 eina_value_optional_new(Eina_Value_Type const *subtype,
4589 const void* initial_value) EINA_ARG_NONNULL(1, 2)
4590 {
4591 Eina_Value *value;
4592
4593 value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));
4594 if (!value)
4595 return NULL;
4596
4597 if (!eina_value_setup(value, EINA_VALUE_TYPE_OPTIONAL))
4598 {
4599 eina_mempool_free(_eina_value_mp, value);
4600 return NULL;
4601 }
4602 if (!eina_value_optional_pset(value, subtype, initial_value))
4603 {
4604 eina_mempool_free(_eina_value_mp, value);
4605 return NULL;
4606 }
4607 return value;
4608 }
4609
4610 EAPI Eina_Bool
eina_value_optional_pset(Eina_Value * value,Eina_Value_Type const * subtype,const void * subvalue)4611 eina_value_optional_pset(Eina_Value *value,
4612 Eina_Value_Type const* subtype,
4613 const void *subvalue) EINA_ARG_NONNULL(1, 2, 3)
4614 {
4615 eina_value_optional_reset(value);
4616
4617 if(sizeof(Eina_Value_Optional_Outer) <= sizeof(Eina_Value_Union))
4618 {
4619 Eina_Value_Optional_Outer outer;
4620 outer.subtype = subtype;
4621 outer.value = malloc(subtype->value_size);
4622 eina_value_type_setup(subtype, outer.value);
4623 eina_value_type_pset(subtype, outer.value, subvalue);
4624 if (!eina_value_pset(value, &outer))
4625 {
4626 return EINA_FALSE;
4627 }
4628 }
4629 else
4630 {
4631 Eina_Value_Optional_Inner *inner =
4632 malloc(sizeof(Eina_Value_Optional_Inner) + subtype->value_size);
4633 inner->subtype = subtype;
4634 eina_value_type_setup(subtype, inner->value);
4635 eina_value_type_pset(subtype, inner->value, subvalue);
4636 if (!eina_value_pset(value, &inner))
4637 return EINA_FALSE;
4638 }
4639
4640 return EINA_TRUE;
4641 }
4642
4643 EAPI Eina_Bool
eina_value_optional_pget(Eina_Value * value,void * subvalue)4644 eina_value_optional_pget(Eina_Value *value, void *subvalue) EINA_ARG_NONNULL(1, 2, 3)
4645 {
4646 if(sizeof(Eina_Value_Optional_Outer) <= sizeof(Eina_Value_Union))
4647 {
4648 Eina_Value_Optional_Outer outer;
4649
4650 if (!eina_value_pget(value, &outer))
4651 return EINA_FALSE;
4652
4653 if(outer.subtype)
4654 eina_value_type_copy(outer.subtype, outer.value, subvalue);
4655 else
4656 return EINA_FALSE;
4657 }
4658 else
4659 {
4660 Eina_Value_Optional_Inner *inner;
4661
4662 if (!eina_value_pget(value, &inner))
4663 return EINA_FALSE;
4664
4665 if(inner)
4666 eina_value_type_copy(inner->subtype, inner->value, subvalue);
4667 else
4668 return EINA_FALSE;
4669 }
4670
4671 return EINA_TRUE;
4672 }
4673
4674 static Eina_Bool
_eina_value_type_optional_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src_raw,void * dst_raw)4675 _eina_value_type_optional_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src_raw, void *dst_raw)
4676 {
4677 if(sizeof(Eina_Value_Optional_Outer) <= sizeof(Eina_Value_Union))
4678 {
4679 Eina_Value_Optional_Outer const* src = src_raw;
4680 Eina_Value_Optional_Outer* dst = dst_raw;
4681 if(src->subtype)
4682 {
4683 dst->subtype = src->subtype;
4684 dst->value = malloc(src->subtype->value_size);
4685 eina_value_type_copy(src->subtype, src->value, dst->value);
4686 }
4687 else
4688 memset(dst_raw, 0, sizeof(Eina_Value_Optional_Outer));
4689 }
4690 else if(src_raw)
4691 {
4692 Eina_Value_Optional_Inner* src = *(void**)src_raw;
4693 Eina_Value_Optional_Inner* dst = *(void**)dst_raw
4694 = malloc(sizeof(Eina_Value_Optional_Inner) + src->subtype->value_size);
4695 dst->subtype = src->subtype;
4696
4697 eina_value_type_copy(src->subtype, src->value, dst->value);
4698 }
4699 else
4700 *(void**)dst_raw = NULL;
4701 return EINA_TRUE;
4702 }
4703
4704 static int
_eina_value_type_optional_compare(const Eina_Value_Type * type EINA_UNUSED,const void * lhs_raw,const void * rhs_raw)4705 _eina_value_type_optional_compare(const Eina_Value_Type *type EINA_UNUSED, const void *lhs_raw, const void *rhs_raw)
4706 {
4707 if(sizeof(Eina_Value_Optional_Outer) <= sizeof(Eina_Value_Union))
4708 {
4709 Eina_Value_Optional_Outer const *lhs = lhs_raw
4710 , *rhs = rhs_raw;
4711 if(!lhs->subtype)
4712 return !rhs->subtype ? 0 : -1;
4713 else if(!rhs->subtype)
4714 return 1;
4715 else if(lhs->subtype != rhs->subtype)
4716 return lhs->subtype < rhs->subtype ? -1 : 1;
4717 else
4718 return eina_value_type_compare(lhs->subtype, lhs->value, rhs->value);
4719 }
4720 else
4721 {
4722 Eina_Value_Optional_Inner const * const* lhs_p = lhs_raw;
4723 Eina_Value_Optional_Inner const * const* rhs_p = rhs_raw;
4724
4725 if(!*lhs_p)
4726 return *rhs_p ? -1 : 0;
4727 else if(!*rhs_p)
4728 return 1;
4729 else if((*lhs_p)->subtype != (*rhs_p)->subtype)
4730 return (*lhs_p)->subtype < (*rhs_p)->subtype ? -1 : 1;
4731 else
4732 return eina_value_type_compare((*lhs_p)->subtype, (*lhs_p)->value, (*rhs_p)->value);
4733 }
4734 }
4735
4736 static Eina_Bool
_eina_value_type_optional_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)4737 _eina_value_type_optional_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
4738 {
4739 _eina_value_type_optional_flush(type, mem);
4740 _eina_value_type_optional_copy(type, ptr, mem);
4741 return EINA_TRUE;
4742 }
4743
4744 static Eina_Bool
_eina_value_type_optional_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)4745 _eina_value_type_optional_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
4746 {
4747 memcpy(ptr, mem, sizeof(Eina_Value_Union));
4748 return EINA_TRUE;
4749 }
4750
4751 static Eina_Bool
_eina_value_type_eina_error_convert_to(const Eina_Value_Type * type,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)4752 _eina_value_type_eina_error_convert_to(const Eina_Value_Type *type, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
4753 {
4754 if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
4755 convert == EINA_VALUE_TYPE_STRING)
4756 {
4757 const Eina_Error v = *(const Eina_Error *)type_mem;
4758 const char *msg = eina_error_msg_get(v);
4759 return eina_value_type_pset(convert, convert_mem, &msg);
4760 }
4761
4762 return _eina_value_type_int_convert_to(type, convert, type_mem, convert_mem);
4763 }
4764
4765 EAPI const Eina_Value_Type _EINA_VALUE_TYPE_OPTIONAL = {
4766 EINA_VALUE_TYPE_VERSION,
4767 sizeof(Eina_Value_Union),
4768 "optional",
4769 _eina_value_type_optional_setup,
4770 _eina_value_type_optional_flush,
4771 _eina_value_type_optional_copy,
4772 _eina_value_type_optional_compare,
4773 NULL,
4774 NULL,
4775 NULL,
4776 _eina_value_type_optional_pset,
4777 _eina_value_type_optional_pget
4778 };
4779
4780 static Eina_Bool
_eina_value_type_file_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)4781 _eina_value_type_file_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
4782 {
4783 memset(mem, 0, sizeof(Eina_File *));
4784 return EINA_TRUE;
4785 }
4786
4787 static Eina_Bool
_eina_value_type_file_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem)4788 _eina_value_type_file_flush(const Eina_Value_Type *type EINA_UNUSED, void *mem)
4789 {
4790 Eina_File *f = *(Eina_File **)mem;
4791
4792 if (f) eina_file_close(f);
4793 return EINA_TRUE;
4794 }
4795
4796 static Eina_Bool
_eina_value_type_file_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)4797 _eina_value_type_file_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
4798 {
4799 const Eina_File *f = *(const Eina_File **)src;
4800 Eina_File **d = dst;
4801
4802 *d = eina_file_dup(f);
4803 return !!(*d);
4804 }
4805
4806 static int
_eina_value_type_file_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)4807 _eina_value_type_file_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
4808 {
4809 const Eina_File *ta = *(const Eina_File **)a;
4810 const Eina_File *tb = *(const Eina_File **)b;
4811
4812 if (ta == tb) return 0;
4813 if (!ta) return -1;
4814 if (!tb) return 1;
4815 return -1;
4816 }
4817
4818 static Eina_Bool
_eina_value_type_file_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)4819 _eina_value_type_file_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
4820 {
4821 const Eina_File *f = *(const Eina_File **) type_mem;
4822 Eina_Bool ret = EINA_FALSE;
4823
4824 if ((convert == EINA_VALUE_TYPE_STRING) ||
4825 (convert == EINA_VALUE_TYPE_STRINGSHARE))
4826 {
4827 const char *filename;
4828
4829 filename = eina_file_filename_get(f);
4830 ret = eina_value_type_pset(convert, convert_mem, &filename);
4831 }
4832 else if (convert == EINA_VALUE_TYPE_BLOB)
4833 {
4834 Eina_Value_Blob *c = convert_mem;
4835 const void *m;
4836
4837 m = eina_file_map_all((Eina_File*) f, EINA_FILE_WILLNEED);
4838 if (!m) goto end;
4839
4840 c->ops = EINA_VALUE_BLOB_OPERATIONS_MALLOC;
4841 c->memory = malloc(eina_file_size_get(f));
4842 memcpy((void*)c->memory, m, eina_file_size_get(f));
4843 c->size = eina_file_size_get(f);
4844
4845 eina_file_map_free((Eina_File*)f, (void*)m);
4846
4847 ret = EINA_TRUE;
4848 }
4849
4850 end:
4851 return ret;
4852 }
4853
4854 static Eina_Bool
_eina_value_type_file_convert_from(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,void * type_mem,const void * convert_mem)4855 _eina_value_type_file_convert_from(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, void *type_mem, const void *convert_mem)
4856 {
4857 Eina_File **f = type_mem;
4858
4859 if ((convert == EINA_VALUE_TYPE_STRING) ||
4860 (convert == EINA_VALUE_TYPE_STRINGSHARE))
4861 {
4862 const char *filename = *(const char **)convert_mem;
4863
4864 if (!filename) return EINA_FALSE;
4865 *f = eina_file_open(filename, EINA_FALSE);
4866 return !!(*f);
4867 }
4868
4869 return EINA_FALSE;
4870 }
4871
4872 static Eina_Bool
_eina_value_type_file_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)4873 _eina_value_type_file_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
4874 {
4875 Eina_File **d = mem;
4876 const Eina_File *s = ptr;
4877
4878 *d = eina_file_dup(s);
4879 return EINA_TRUE;
4880 }
4881
4882 static Eina_Bool
_eina_value_type_file_vset(const Eina_Value_Type * type,void * mem,va_list args)4883 _eina_value_type_file_vset(const Eina_Value_Type *type, void *mem, va_list args)
4884 {
4885 const Eina_File *f = va_arg(args, Eina_File *);
4886 return _eina_value_type_file_pset(type, mem, f);
4887 }
4888
4889 static Eina_Bool
_eina_value_type_file_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)4890 _eina_value_type_file_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
4891 {
4892 memcpy(ptr, mem, sizeof (Eina_File*));
4893 return EINA_TRUE;
4894 }
4895
4896 EAPI const Eina_Value_Type _EINA_VALUE_TYPE_FILE = {
4897 EINA_VALUE_TYPE_VERSION,
4898 sizeof (Eina_File *),
4899 "Eina_File",
4900 _eina_value_type_file_setup,
4901 _eina_value_type_file_flush,
4902 _eina_value_type_file_copy,
4903 _eina_value_type_file_compare,
4904 _eina_value_type_file_convert_to,
4905 _eina_value_type_file_convert_from,
4906 _eina_value_type_file_vset,
4907 _eina_value_type_file_pset,
4908 _eina_value_type_file_pget
4909 };
4910
4911 static Eina_Bool
_eina_value_type_rectangle_setup(const Eina_Value_Type * type EINA_UNUSED,void * mem)4912 _eina_value_type_rectangle_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
4913 {
4914 memset(mem, 0, sizeof(Eina_Rectangle));
4915 return EINA_TRUE;
4916 }
4917
4918 static Eina_Bool
_eina_value_type_rectangle_flush(const Eina_Value_Type * type EINA_UNUSED,void * mem EINA_UNUSED)4919 _eina_value_type_rectangle_flush(const Eina_Value_Type *type EINA_UNUSED,
4920 void *mem EINA_UNUSED)
4921 {
4922 return EINA_TRUE;
4923 }
4924
4925 static Eina_Bool
_eina_value_type_rectangle_copy(const Eina_Value_Type * type EINA_UNUSED,const void * src,void * dst)4926 _eina_value_type_rectangle_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
4927 {
4928 memcpy(dst, src, sizeof (Eina_Rectangle));
4929
4930 return EINA_TRUE;
4931 }
4932
4933 static int
_eina_value_type_rectangle_compare(const Eina_Value_Type * type EINA_UNUSED,const void * a,const void * b)4934 _eina_value_type_rectangle_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
4935 {
4936 const Eina_Rectangle *ra = a;
4937 const Eina_Rectangle *rb = b;
4938
4939 if (eina_rectangle_equal(ra, rb)) return 0;
4940 return -1;
4941 }
4942
4943 static Eina_Bool
_eina_value_type_rectangle_convert_to(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,const void * type_mem,void * convert_mem)4944 _eina_value_type_rectangle_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
4945 {
4946 const Eina_Rectangle *tr = type_mem;
4947 Eina_Bool ret = EINA_FALSE;
4948
4949 if ((convert == EINA_VALUE_TYPE_STRING) ||
4950 (convert == EINA_VALUE_TYPE_STRINGSHARE))
4951 {
4952 char str[1024];
4953
4954 snprintf(str, 1024, "[ %i, %i, %i, %i ]",
4955 tr->x, tr->y, tr->w, tr->h);
4956 ret = eina_value_type_pset(convert, convert_mem, str);
4957 }
4958
4959 return ret;
4960 }
4961
4962 static Eina_Bool
_eina_value_type_rectangle_convert_from(const Eina_Value_Type * type EINA_UNUSED,const Eina_Value_Type * convert,void * type_mem,const void * convert_mem)4963 _eina_value_type_rectangle_convert_from(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, void *type_mem, const void *convert_mem)
4964 {
4965 Eina_Rectangle *r = type_mem;
4966
4967 if ((convert == EINA_VALUE_TYPE_STRING) ||
4968 (convert == EINA_VALUE_TYPE_STRINGSHARE))
4969 {
4970 const char *buf = *(const char **)convert_mem;
4971 int ret;
4972
4973 ret = sscanf(buf, "[ %i, %i, %i, %i ]",
4974 &r->x, &r->y, &r->w, &r->h);
4975
4976 if (ret <= 0) return EINA_FALSE;
4977 return EINA_TRUE;
4978 }
4979
4980 return EINA_FALSE;
4981 }
4982
4983 static Eina_Bool
_eina_value_type_rectangle_pset(const Eina_Value_Type * type EINA_UNUSED,void * mem,const void * ptr)4984 _eina_value_type_rectangle_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
4985 {
4986 const Eina_Rectangle *r = ptr;
4987 Eina_Rectangle *tr = mem;
4988
4989 *tr = *r;
4990 return EINA_TRUE;
4991 }
4992
4993 static Eina_Bool
_eina_value_type_rectangle_vset(const Eina_Value_Type * type,void * mem,va_list args)4994 _eina_value_type_rectangle_vset(const Eina_Value_Type *type, void *mem, va_list args)
4995 {
4996 const Eina_Rectangle r = va_arg(args, Eina_Rectangle);
4997 return _eina_value_type_rectangle_pset(type, mem, &r);
4998 }
4999
5000 static Eina_Bool
_eina_value_type_rectangle_pget(const Eina_Value_Type * type EINA_UNUSED,const void * mem,void * ptr)5001 _eina_value_type_rectangle_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
5002 {
5003 const Eina_Rectangle *tr = mem;
5004 Eina_Rectangle *r = ptr;
5005
5006 *r = *tr;
5007 return EINA_TRUE;
5008 }
5009
5010 EAPI const Eina_Value_Type _EINA_VALUE_TYPE_RECTANGLE = {
5011 EINA_VALUE_TYPE_VERSION,
5012 sizeof (Eina_Rectangle),
5013 "Eina_Rectangle",
5014 _eina_value_type_rectangle_setup,
5015 _eina_value_type_rectangle_flush,
5016 _eina_value_type_rectangle_copy,
5017 _eina_value_type_rectangle_compare,
5018 _eina_value_type_rectangle_convert_to,
5019 _eina_value_type_rectangle_convert_from,
5020 _eina_value_type_rectangle_vset,
5021 _eina_value_type_rectangle_pset,
5022 _eina_value_type_rectangle_pget
5023 };
5024
5025 /* keep all basic types inlined in an array so we can compare if it's
5026 * a basic type using pointer arithmetic.
5027 *
5028 * NOTE-1: JUST BASIC TYPES, DO NOT ADD MORE TYPES HERE!!!
5029 * NOTE-2: KEEP ORDER, see eina_value_init()
5030 */
5031 static const Eina_Value_Type _EINA_VALUE_TYPE_BASICS[] = {
5032 {
5033 EINA_VALUE_TYPE_VERSION,
5034 sizeof(unsigned char),
5035 "unsigned char",
5036 _eina_value_type_uchar_setup,
5037 _eina_value_type_uchar_flush,
5038 _eina_value_type_uchar_copy,
5039 _eina_value_type_uchar_compare,
5040 _eina_value_type_uchar_convert_to,
5041 NULL, /* no convert from */
5042 _eina_value_type_uchar_vset,
5043 _eina_value_type_uchar_pset,
5044 _eina_value_type_uchar_pget
5045 },
5046 {
5047 EINA_VALUE_TYPE_VERSION,
5048 sizeof(unsigned short),
5049 "unsigned short",
5050 _eina_value_type_ushort_setup,
5051 _eina_value_type_ushort_flush,
5052 _eina_value_type_ushort_copy,
5053 _eina_value_type_ushort_compare,
5054 _eina_value_type_ushort_convert_to,
5055 NULL, /* no convert from */
5056 _eina_value_type_ushort_vset,
5057 _eina_value_type_ushort_pset,
5058 _eina_value_type_ushort_pget
5059 },
5060 {
5061 EINA_VALUE_TYPE_VERSION,
5062 sizeof(unsigned int),
5063 "unsigned int",
5064 _eina_value_type_uint_setup,
5065 _eina_value_type_uint_flush,
5066 _eina_value_type_uint_copy,
5067 _eina_value_type_uint_compare,
5068 _eina_value_type_uint_convert_to,
5069 NULL, /* no convert from */
5070 _eina_value_type_uint_vset,
5071 _eina_value_type_uint_pset,
5072 _eina_value_type_uint_pget
5073 },
5074 {
5075 EINA_VALUE_TYPE_VERSION,
5076 sizeof(unsigned long),
5077 "unsigned long",
5078 _eina_value_type_ulong_setup,
5079 _eina_value_type_ulong_flush,
5080 _eina_value_type_ulong_copy,
5081 _eina_value_type_ulong_compare,
5082 _eina_value_type_ulong_convert_to,
5083 NULL, /* no convert from */
5084 _eina_value_type_ulong_vset,
5085 _eina_value_type_ulong_pset,
5086 _eina_value_type_ulong_pget
5087 },
5088 {
5089 EINA_VALUE_TYPE_VERSION,
5090 sizeof(uint64_t),
5091 "uint64_t",
5092 _eina_value_type_uint64_setup,
5093 _eina_value_type_uint64_flush,
5094 _eina_value_type_uint64_copy,
5095 _eina_value_type_uint64_compare,
5096 _eina_value_type_uint64_convert_to,
5097 NULL, /* no convert from */
5098 _eina_value_type_uint64_vset,
5099 _eina_value_type_uint64_pset,
5100 _eina_value_type_uint64_pget
5101 },
5102 {
5103 EINA_VALUE_TYPE_VERSION,
5104 sizeof(char),
5105 "char",
5106 _eina_value_type_char_setup,
5107 _eina_value_type_char_flush,
5108 _eina_value_type_char_copy,
5109 _eina_value_type_char_compare,
5110 _eina_value_type_char_convert_to,
5111 NULL, /* no convert from */
5112 _eina_value_type_char_vset,
5113 _eina_value_type_char_pset,
5114 _eina_value_type_char_pget
5115 },
5116 {
5117 EINA_VALUE_TYPE_VERSION,
5118 sizeof(short),
5119 "short",
5120 _eina_value_type_short_setup,
5121 _eina_value_type_short_flush,
5122 _eina_value_type_short_copy,
5123 _eina_value_type_short_compare,
5124 _eina_value_type_short_convert_to,
5125 NULL, /* no convert from */
5126 _eina_value_type_short_vset,
5127 _eina_value_type_short_pset,
5128 _eina_value_type_short_pget
5129 },
5130 {
5131 EINA_VALUE_TYPE_VERSION,
5132 sizeof(int),
5133 "int",
5134 _eina_value_type_int_setup,
5135 _eina_value_type_int_flush,
5136 _eina_value_type_int_copy,
5137 _eina_value_type_int_compare,
5138 _eina_value_type_int_convert_to,
5139 NULL, /* no convert from */
5140 _eina_value_type_int_vset,
5141 _eina_value_type_int_pset,
5142 _eina_value_type_int_pget
5143 },
5144 {
5145 EINA_VALUE_TYPE_VERSION,
5146 sizeof(long),
5147 "long",
5148 _eina_value_type_long_setup,
5149 _eina_value_type_long_flush,
5150 _eina_value_type_long_copy,
5151 _eina_value_type_long_compare,
5152 _eina_value_type_long_convert_to,
5153 NULL, /* no convert from */
5154 _eina_value_type_long_vset,
5155 _eina_value_type_long_pset,
5156 _eina_value_type_long_pget
5157 },
5158 {
5159 EINA_VALUE_TYPE_VERSION,
5160 sizeof(int64_t),
5161 "int64_t",
5162 _eina_value_type_int64_setup,
5163 _eina_value_type_int64_flush,
5164 _eina_value_type_int64_copy,
5165 _eina_value_type_int64_compare,
5166 _eina_value_type_int64_convert_to,
5167 NULL, /* no convert from */
5168 _eina_value_type_int64_vset,
5169 _eina_value_type_int64_pset,
5170 _eina_value_type_int64_pget
5171 },
5172 {
5173 EINA_VALUE_TYPE_VERSION,
5174 sizeof(float),
5175 "float",
5176 _eina_value_type_float_setup,
5177 _eina_value_type_float_flush,
5178 _eina_value_type_float_copy,
5179 _eina_value_type_float_compare,
5180 _eina_value_type_float_convert_to,
5181 NULL, /* no convert from */
5182 _eina_value_type_float_vset,
5183 _eina_value_type_float_pset,
5184 _eina_value_type_float_pget
5185 },
5186 {
5187 EINA_VALUE_TYPE_VERSION,
5188 sizeof(double),
5189 "double",
5190 _eina_value_type_double_setup,
5191 _eina_value_type_double_flush,
5192 _eina_value_type_double_copy,
5193 _eina_value_type_double_compare,
5194 _eina_value_type_double_convert_to,
5195 NULL, /* no convert from */
5196 _eina_value_type_double_vset,
5197 _eina_value_type_double_pset,
5198 _eina_value_type_double_pget
5199 },
5200 {
5201 EINA_VALUE_TYPE_VERSION,
5202 sizeof(const char *),
5203 "stringshare",
5204 _eina_value_type_string_common_setup,
5205 _eina_value_type_stringshare_flush,
5206 _eina_value_type_stringshare_copy,
5207 _eina_value_type_string_common_compare,
5208 _eina_value_type_string_common_convert_to,
5209 NULL, /* no convert from */
5210 _eina_value_type_stringshare_vset,
5211 _eina_value_type_stringshare_pset,
5212 _eina_value_type_stringshare_pget
5213 },
5214 {
5215 EINA_VALUE_TYPE_VERSION,
5216 sizeof(char *),
5217 "string",
5218 _eina_value_type_string_common_setup,
5219 _eina_value_type_string_flush,
5220 _eina_value_type_string_copy,
5221 _eina_value_type_string_common_compare,
5222 _eina_value_type_string_common_convert_to,
5223 NULL, /* no convert from */
5224 _eina_value_type_string_vset,
5225 _eina_value_type_string_pset,
5226 _eina_value_type_string_common_pget
5227 },
5228 {
5229 EINA_VALUE_TYPE_VERSION,
5230 sizeof(unsigned long),
5231 "timestamp",
5232 _eina_value_type_ulong_setup,
5233 _eina_value_type_ulong_flush,
5234 _eina_value_type_ulong_copy,
5235 _eina_value_type_ulong_compare,
5236 _eina_value_type_ulong_convert_to,
5237 NULL, /* no convert from */
5238 _eina_value_type_ulong_vset,
5239 _eina_value_type_ulong_pset,
5240 _eina_value_type_ulong_pget
5241 },
5242 {
5243 EINA_VALUE_TYPE_VERSION,
5244 sizeof(Eina_Error),
5245 "Eina_Error",
5246 _eina_value_type_int_setup,
5247 _eina_value_type_int_flush,
5248 _eina_value_type_int_copy,
5249 _eina_value_type_int_compare,
5250 _eina_value_type_eina_error_convert_to,
5251 NULL, /* no convert from */
5252 _eina_value_type_int_vset,
5253 _eina_value_type_int_pset,
5254 _eina_value_type_int_pget
5255 }
5256 };
5257
5258 static void
_eina_value_blob_operations_malloc_free(const Eina_Value_Blob_Operations * ops EINA_UNUSED,void * memory,size_t size EINA_UNUSED)5259 _eina_value_blob_operations_malloc_free(const Eina_Value_Blob_Operations *ops EINA_UNUSED, void *memory, size_t size EINA_UNUSED)
5260 {
5261 free(memory);
5262 }
5263
5264 static void *
_eina_value_blob_operations_malloc_copy(const Eina_Value_Blob_Operations * ops EINA_UNUSED,const void * memory,size_t size)5265 _eina_value_blob_operations_malloc_copy(const Eina_Value_Blob_Operations *ops EINA_UNUSED, const void *memory, size_t size)
5266 {
5267 void *ret = malloc(size);
5268 if (!ret) return NULL;
5269 memcpy(ret, memory, size);
5270 return ret;
5271 }
5272
5273 static const Eina_Value_Blob_Operations _EINA_VALUE_BLOB_OPERATIONS_MALLOC = {
5274 EINA_VALUE_BLOB_OPERATIONS_VERSION,
5275 _eina_value_blob_operations_malloc_free,
5276 _eina_value_blob_operations_malloc_copy,
5277 NULL,
5278 NULL
5279 };
5280
5281 typedef struct _Eina_Value_Inner_Mp Eina_Value_Inner_Mp;
5282 struct _Eina_Value_Inner_Mp
5283 {
5284 Eina_Mempool *mempool;
5285 #ifdef DEBUG
5286 int size;
5287 #endif
5288 int references;
5289 };
5290
5291 /**
5292 * @endcond
5293 */
5294
5295 /**
5296 */
5297
5298 static inline void
_eina_value_inner_mp_dispose(int size,Eina_Value_Inner_Mp * imp)5299 _eina_value_inner_mp_dispose(int size, Eina_Value_Inner_Mp *imp)
5300 {
5301 EINA_SAFETY_ON_FALSE_RETURN(imp->references == 0);
5302
5303 eina_hash_del_by_key(_eina_value_inner_mps, &size);
5304 eina_mempool_del(imp->mempool);
5305 free(imp);
5306 }
5307
5308 static inline Eina_Value_Inner_Mp *
_eina_value_inner_mp_get(int size)5309 _eina_value_inner_mp_get(int size)
5310 {
5311 Eina_Value_Inner_Mp *imp = eina_hash_find(_eina_value_inner_mps, &size);
5312 if (imp) return imp;
5313
5314 imp = malloc(sizeof(Eina_Value_Inner_Mp));
5315 if (!imp)
5316 return NULL;
5317
5318 imp->references = 0;
5319 #ifdef DEBUG
5320 imp->size = size;
5321 #endif
5322
5323 imp->mempool = eina_mempool_add(_eina_value_mp_choice,
5324 "Eina_Value_Inner_Mp", NULL, size, 16);
5325 if (!imp->mempool)
5326 {
5327 free(imp);
5328 return NULL;
5329 }
5330
5331 if (!eina_hash_add(_eina_value_inner_mps, &size, imp))
5332 {
5333 eina_mempool_del(imp->mempool);
5334 free(imp);
5335 return NULL;
5336 }
5337
5338 return imp;
5339 }
5340
5341 static inline void *
_eina_value_inner_alloc_internal(int size)5342 _eina_value_inner_alloc_internal(int size)
5343 {
5344 Eina_Value_Inner_Mp *imp;
5345 void *mem;
5346
5347 imp = _eina_value_inner_mp_get(size);
5348 if (!imp) return NULL;
5349
5350 mem = eina_mempool_malloc(imp->mempool, size);
5351 if (mem) imp->references++;
5352 else if (imp->references == 0) _eina_value_inner_mp_dispose(size, imp);
5353
5354 return mem;
5355 }
5356
5357 static inline void
_eina_value_inner_free_internal(int size,void * mem)5358 _eina_value_inner_free_internal(int size, void *mem)
5359 {
5360 Eina_Value_Inner_Mp *imp = eina_hash_find(_eina_value_inner_mps, &size);
5361 EINA_SAFETY_ON_NULL_RETURN(imp);
5362
5363 eina_mempool_free(imp->mempool, mem);
5364
5365 imp->references--;
5366 if (imp->references > 0) return;
5367 _eina_value_inner_mp_dispose(size, imp);
5368 }
5369
5370 EAPI void *
eina_value_inner_alloc(size_t size)5371 eina_value_inner_alloc(size_t size)
5372 {
5373 void *mem;
5374
5375 if (size > 256) return malloc(size);
5376
5377 eina_lock_take(&_eina_value_inner_mps_lock);
5378 mem = _eina_value_inner_alloc_internal(size);
5379 eina_lock_release(&_eina_value_inner_mps_lock);
5380
5381 return mem;
5382 }
5383
5384 EAPI void
eina_value_inner_free(size_t size,void * mem)5385 eina_value_inner_free(size_t size, void *mem)
5386 {
5387 if (size > 256)
5388 {
5389 free(mem);
5390 return;
5391 }
5392
5393 eina_lock_take(&_eina_value_inner_mps_lock);
5394 _eina_value_inner_free_internal(size, mem);
5395 eina_lock_release(&_eina_value_inner_mps_lock);
5396 }
5397
5398 /**
5399 * @internal
5400 * @brief Initialize the value module.
5401 *
5402 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
5403 *
5404 * This function sets up the value module of Eina. It is called
5405 * by eina_init().
5406 *
5407 * @see eina_init()
5408 */
5409 Eina_Bool
eina_value_init(void)5410 eina_value_init(void)
5411 {
5412 const Eina_Value empty = EINA_VALUE_EMPTY;
5413 const char *choice, *tmp;
5414
5415 _eina_value_log_dom = eina_log_domain_register("eina_value",
5416 EINA_LOG_COLOR_DEFAULT);
5417 if (_eina_value_log_dom < 0)
5418 {
5419 EINA_LOG_ERR("Could not register log domain: eina_value");
5420 return EINA_FALSE;
5421 }
5422
5423 #ifdef EINA_DEFAULT_MEMPOOL
5424 choice = "pass_through";
5425 #else
5426 choice = "chained_mempool";
5427 #endif
5428 tmp = getenv("EINA_MEMPOOL");
5429 if (tmp && tmp[0])
5430 choice = tmp;
5431
5432 _eina_value_mp_choice = strdup(choice);
5433
5434 _eina_value_mp = eina_mempool_add
5435 (_eina_value_mp_choice, "value", NULL, sizeof(Eina_Value), 32);
5436 if (!_eina_value_mp)
5437 {
5438 ERR("Mempool for value cannot be allocated in value init.");
5439 goto on_init_fail_mp;
5440 }
5441
5442 if (!eina_lock_new(&_eina_value_inner_mps_lock))
5443 {
5444 ERR("Cannot create lock in value init.");
5445 goto on_init_fail_lock;
5446 }
5447 _eina_value_inner_mps = eina_hash_int32_new(NULL);
5448 if (!_eina_value_inner_mps)
5449 {
5450 ERR("Cannot create hash for inner mempools in value init.");
5451 goto on_init_fail_hash;
5452 }
5453
5454 EINA_VALUE_TYPE_UCHAR = _EINA_VALUE_TYPE_BASICS + 0;
5455 EINA_VALUE_TYPE_BOOL = EINA_VALUE_TYPE_UCHAR;
5456 EINA_VALUE_TYPE_USHORT = _EINA_VALUE_TYPE_BASICS + 1;
5457 EINA_VALUE_TYPE_UINT = _EINA_VALUE_TYPE_BASICS + 2;
5458 EINA_VALUE_TYPE_ULONG = _EINA_VALUE_TYPE_BASICS + 3;
5459 EINA_VALUE_TYPE_UINT64 = _EINA_VALUE_TYPE_BASICS + 4;
5460 EINA_VALUE_TYPE_CHAR = _EINA_VALUE_TYPE_BASICS + 5;
5461 EINA_VALUE_TYPE_SHORT = _EINA_VALUE_TYPE_BASICS + 6;
5462 EINA_VALUE_TYPE_INT = _EINA_VALUE_TYPE_BASICS + 7;
5463 EINA_VALUE_TYPE_LONG = _EINA_VALUE_TYPE_BASICS + 8;
5464 EINA_VALUE_TYPE_INT64 = _EINA_VALUE_TYPE_BASICS + 9;
5465 EINA_VALUE_TYPE_FLOAT = _EINA_VALUE_TYPE_BASICS + 10;
5466 EINA_VALUE_TYPE_DOUBLE = _EINA_VALUE_TYPE_BASICS + 11;
5467 EINA_VALUE_TYPE_STRINGSHARE = _EINA_VALUE_TYPE_BASICS + 12;
5468 EINA_VALUE_TYPE_STRING = _EINA_VALUE_TYPE_BASICS + 13;
5469 EINA_VALUE_TYPE_TIMESTAMP = _EINA_VALUE_TYPE_BASICS + 14;
5470 EINA_VALUE_TYPE_ERROR = _EINA_VALUE_TYPE_BASICS + 15;
5471
5472 _EINA_VALUE_TYPE_BASICS_START = _EINA_VALUE_TYPE_BASICS + 0;
5473 _EINA_VALUE_TYPE_BASICS_END = _EINA_VALUE_TYPE_BASICS + 15;
5474
5475 EINA_SAFETY_ON_FALSE_RETURN_VAL((sizeof(_EINA_VALUE_TYPE_BASICS)/sizeof(_EINA_VALUE_TYPE_BASICS[0])) == 16, EINA_FALSE);
5476
5477
5478 EINA_VALUE_TYPE_ARRAY = &_EINA_VALUE_TYPE_ARRAY;
5479 EINA_VALUE_TYPE_LIST = &_EINA_VALUE_TYPE_LIST;
5480 EINA_VALUE_TYPE_HASH = &_EINA_VALUE_TYPE_HASH;
5481 EINA_VALUE_TYPE_TIMEVAL = &_EINA_VALUE_TYPE_TIMEVAL;
5482 EINA_VALUE_TYPE_TM = &_EINA_VALUE_TYPE_TM;
5483 EINA_VALUE_TYPE_BLOB = &_EINA_VALUE_TYPE_BLOB;
5484 EINA_VALUE_TYPE_STRUCT = &_EINA_VALUE_TYPE_STRUCT;
5485
5486 EINA_VALUE_TYPE_OPTIONAL = &_EINA_VALUE_TYPE_OPTIONAL;
5487 EINA_VALUE_TYPE_FILE = &_EINA_VALUE_TYPE_FILE;
5488 EINA_VALUE_TYPE_RECTANGLE = &_EINA_VALUE_TYPE_RECTANGLE;
5489
5490 EINA_VALUE_BLOB_OPERATIONS_MALLOC = &_EINA_VALUE_BLOB_OPERATIONS_MALLOC;
5491
5492 EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH = &_EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH;
5493 EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE = &_EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE;
5494
5495 EINA_VALUE_TYPE_VALUE = &_EINA_VALUE_TYPE_VALUE;
5496
5497 EINA_ERROR_VALUE_FAILED = eina_error_msg_static_register("Eina_Value failed to copy/convert.");
5498
5499 memcpy(&_eina_value_empty, &empty, sizeof (empty));
5500
5501 return EINA_TRUE;
5502
5503 on_init_fail_hash:
5504 eina_lock_free(&_eina_value_inner_mps_lock);
5505 on_init_fail_lock:
5506 eina_mempool_del(_eina_value_mp);
5507 on_init_fail_mp:
5508 free(_eina_value_mp_choice);
5509 _eina_value_mp_choice = NULL;
5510 eina_log_domain_unregister(_eina_value_log_dom);
5511 _eina_value_log_dom = -1;
5512 return EINA_FALSE;
5513 }
5514
5515 /**
5516 * @internal
5517 * @brief Shut down the value module.
5518 *
5519 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
5520 *
5521 * This function shuts down the value module set up by
5522 * eina_value_init(). It is called by eina_shutdown().
5523 *
5524 * @see eina_shutdown()
5525 */
5526 Eina_Bool
eina_value_shutdown(void)5527 eina_value_shutdown(void)
5528 {
5529 #ifdef DEBUG
5530 Eina_Iterator *it;
5531 Eina_Value_Inner_Mp *imp;
5532 #endif
5533
5534 eina_lock_take(&_eina_value_inner_mps_lock);
5535
5536 #ifdef DEBUG
5537 it = eina_hash_iterator_data_new(_eina_value_inner_mps);
5538 EINA_ITERATOR_FOREACH(it, imp)
5539 {
5540 Eina_Iterator *mit;
5541 Eina_Value *value;
5542
5543 fprintf(stderr, "There is still %i Eina_Value in pool of size %i\n",
5544 imp->references, imp->size);
5545 mit = eina_mempool_iterator_new(imp->mempool);
5546 EINA_ITERATOR_FOREACH(mit, value)
5547 {
5548 if (value->type)
5549 {
5550 char *str = eina_value_to_string(value);
5551 fprintf(stderr, "Value %p of type '%s' containing '%s' still allocated.\n",
5552 value, value->type->name, str);
5553 free(str);
5554 }
5555 else
5556 {
5557 fprintf(stderr, "Unknown type found for value %p\n", value);
5558 }
5559 }
5560 eina_iterator_free(mit);
5561 }
5562 eina_iterator_free(it);
5563 #endif
5564
5565 if (eina_hash_population(_eina_value_inner_mps) != 0)
5566 ERR("Cannot free eina_value internal memory pools -- still in use!");
5567 else
5568 eina_hash_free(_eina_value_inner_mps);
5569 eina_lock_release(&_eina_value_inner_mps_lock);
5570 eina_lock_free(&_eina_value_inner_mps_lock);
5571
5572 free(_eina_value_mp_choice);
5573 _eina_value_mp_choice = NULL;
5574 eina_mempool_del(_eina_value_mp);
5575 eina_log_domain_unregister(_eina_value_log_dom);
5576 _eina_value_log_dom = -1;
5577 return EINA_TRUE;
5578 }
5579
5580 /*============================================================================*
5581 * Global *
5582 *============================================================================*/
5583
5584 /*============================================================================*
5585 * API *
5586 *============================================================================*/
5587
5588 EAPI const Eina_Value_Type *_EINA_VALUE_TYPE_BASICS_START = NULL;
5589 EAPI const Eina_Value_Type *_EINA_VALUE_TYPE_BASICS_END = NULL;
5590
5591 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_VALUE = NULL;
5592 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_ERROR = NULL;
5593 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_UCHAR = NULL;
5594 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_BOOL = NULL;
5595 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_USHORT = NULL;
5596 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_UINT = NULL;
5597 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_ULONG = NULL;
5598 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_TIMESTAMP = NULL;
5599 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_UINT64 = NULL;
5600 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_CHAR = NULL;
5601 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_SHORT = NULL;
5602 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_INT = NULL;
5603 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_LONG = NULL;
5604 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_INT64 = NULL;
5605 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_FLOAT = NULL;
5606 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_DOUBLE = NULL;
5607 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_STRINGSHARE = NULL;
5608 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_STRING = NULL;
5609 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_ARRAY = NULL;
5610 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_LIST = NULL;
5611 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_HASH = NULL;
5612 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_TIMEVAL = NULL;
5613 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_BLOB = NULL;
5614 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_STRUCT = NULL;
5615 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_OPTIONAL = NULL;
5616 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_FILE = NULL;
5617 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_RECTANGLE = NULL;
5618 EAPI const Eina_Value_Type *EINA_VALUE_TYPE_TM = NULL;
5619
5620
5621 EAPI const Eina_Value_Blob_Operations *EINA_VALUE_BLOB_OPERATIONS_MALLOC = NULL;
5622
5623 EAPI const Eina_Value_Struct_Operations *EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH = NULL;
5624 EAPI const Eina_Value_Struct_Operations *EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE = NULL;
5625
5626 EAPI Eina_Value *
eina_value_new(const Eina_Value_Type * type)5627 eina_value_new(const Eina_Value_Type *type)
5628 {
5629 Eina_Value *value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));
5630 if (!value) return NULL;
5631 if (!type)
5632 {
5633 memcpy(value, &_eina_value_empty, sizeof (_eina_value_empty));
5634 return value;
5635 }
5636 if (!eina_value_setup(value, type))
5637 {
5638 eina_mempool_free(_eina_value_mp, value);
5639 return NULL;
5640 }
5641 return value;
5642 }
5643
5644 EAPI void
eina_value_free(Eina_Value * value)5645 eina_value_free(Eina_Value *value)
5646 {
5647 if (!value) return;
5648 eina_value_flush(value);
5649 eina_mempool_free(_eina_value_mp, value);
5650 }
5651
5652
5653 EAPI Eina_Bool
eina_value_copy(const Eina_Value * value,Eina_Value * copy)5654 eina_value_copy(const Eina_Value *value, Eina_Value *copy)
5655 {
5656 const Eina_Value_Type *type;
5657 const void *src;
5658 void *dst;
5659 Eina_Bool ret;
5660
5661 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
5662
5663 if (value->type == NULL)
5664 {
5665 memcpy(copy, &_eina_value_empty, sizeof (Eina_Value));
5666 return EINA_TRUE;
5667 }
5668
5669 EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type),
5670 EINA_FALSE);
5671 EINA_SAFETY_ON_NULL_RETURN_VAL(copy, EINA_FALSE);
5672 EINA_SAFETY_ON_NULL_RETURN_VAL(value->type->copy, EINA_FALSE);
5673
5674 type = value->type;
5675 if (!eina_value_setup(copy, type))
5676 return EINA_FALSE;
5677
5678 src = eina_value_memory_get(value);
5679 dst = eina_value_memory_get(copy);
5680 ret = type->copy(type, src, dst);
5681 if (!ret)
5682 eina_value_flush(copy);
5683
5684 return ret;
5685 }
5686
5687 EAPI Eina_Bool
eina_value_convert(const Eina_Value * value,Eina_Value * convert)5688 eina_value_convert(const Eina_Value *value, Eina_Value *convert)
5689 {
5690 Eina_Bool ret = EINA_FALSE;
5691 const Eina_Value_Type *type, *convert_type;
5692 const void *type_mem;
5693 void *convert_mem;
5694
5695 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
5696 EINA_SAFETY_ON_NULL_RETURN_VAL(convert, EINA_FALSE);
5697 EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type),
5698 EINA_FALSE);
5699 EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(convert->type),
5700 EINA_FALSE);
5701
5702 type = value->type;
5703 convert_type = convert->type;
5704
5705 type_mem = eina_value_memory_get(value);
5706 convert_mem = eina_value_memory_get(convert);
5707
5708 if (type->convert_to)
5709 ret = type->convert_to(type, convert_type, type_mem, convert_mem);
5710
5711 if ((!ret) && (convert_type->convert_from))
5712 ret = convert_type->convert_from(convert_type, type, convert_mem,
5713 type_mem);
5714
5715 return ret;
5716 }
5717
5718 EAPI char *
eina_value_to_string(const Eina_Value * value)5719 eina_value_to_string(const Eina_Value *value)
5720 {
5721 Eina_Value tmp;
5722
5723 EINA_SAFETY_ON_NULL_RETURN_VAL(value, NULL);
5724 EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), NULL);
5725
5726 if (!eina_value_setup(&tmp, EINA_VALUE_TYPE_STRING))
5727 return NULL;
5728 if (!eina_value_convert(value, &tmp))
5729 return NULL;
5730
5731 return tmp.value.ptr; /* steal value */
5732 }
5733
5734 EAPI Eina_Binbuf *
eina_value_to_binbuf(Eina_Value * value)5735 eina_value_to_binbuf(Eina_Value *value)
5736 {
5737 Eina_Value tmp = EINA_VALUE_EMPTY;
5738 Eina_Value_Blob out;
5739 Eina_Binbuf *buf;
5740
5741 if (value->type != EINA_VALUE_TYPE_BLOB)
5742 {
5743 eina_value_setup(&tmp, EINA_VALUE_TYPE_BLOB);
5744
5745 if (!eina_value_convert(value, &tmp))
5746 return NULL;
5747
5748 value = &tmp;
5749 }
5750
5751 eina_value_get(value, &out);
5752 if (!out.memory) return NULL;
5753
5754 buf = eina_binbuf_new();
5755 eina_binbuf_append_length(buf, out.memory, out.size);
5756
5757 eina_value_flush(&tmp);
5758
5759 return buf;
5760 }
5761
5762 EAPI Eina_Value *
eina_value_array_new(const Eina_Value_Type * subtype,unsigned int step)5763 eina_value_array_new(const Eina_Value_Type *subtype, unsigned int step)
5764 {
5765 Eina_Value *value;
5766
5767 EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(subtype), NULL);
5768
5769 value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));
5770 if (!value)
5771 return NULL;
5772
5773 if (!eina_value_array_setup(value, subtype, step))
5774 {
5775 eina_mempool_free(_eina_value_mp, value);
5776 return NULL;
5777 }
5778
5779 return value;
5780 }
5781
5782 EAPI Eina_Value *
eina_value_list_new(const Eina_Value_Type * subtype)5783 eina_value_list_new(const Eina_Value_Type *subtype)
5784 {
5785 Eina_Value *value;
5786
5787 EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(subtype), NULL);
5788
5789 value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));
5790 if (!value)
5791 return NULL;
5792
5793 if (!eina_value_list_setup(value, subtype))
5794 {
5795 eina_mempool_free(_eina_value_mp, value);
5796 return NULL;
5797 }
5798
5799 return value;
5800 }
5801
5802 EAPI Eina_Value *
eina_value_hash_new(const Eina_Value_Type * subtype,unsigned int buckets_power_size)5803 eina_value_hash_new(const Eina_Value_Type *subtype, unsigned int buckets_power_size)
5804 {
5805 Eina_Value *value;
5806
5807 EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(subtype), NULL);
5808
5809 value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));
5810 if (!value)
5811 return NULL;
5812
5813 if (!eina_value_hash_setup(value, subtype, buckets_power_size))
5814 {
5815 eina_mempool_free(_eina_value_mp, value);
5816 return NULL;
5817 }
5818
5819 return value;
5820 }
5821
5822 EAPI Eina_Value *
eina_value_struct_new(const Eina_Value_Struct_Desc * desc)5823 eina_value_struct_new(const Eina_Value_Struct_Desc *desc)
5824 {
5825 Eina_Value *value;
5826
5827 value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));
5828 if (!value)
5829 return NULL;
5830
5831 if (!eina_value_struct_setup(value, desc))
5832 {
5833 eina_mempool_free(_eina_value_mp, value);
5834 return NULL;
5835 }
5836
5837 return value;
5838 }
5839
5840 EAPI Eina_Bool
eina_value_type_check(const Eina_Value_Type * type)5841 eina_value_type_check(const Eina_Value_Type *type)
5842 {
5843 EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE);
5844 return type->version == EINA_VALUE_TYPE_VERSION;
5845 }
5846
5847 EAPI const char *
eina_value_type_name_get(const Eina_Value_Type * type)5848 eina_value_type_name_get(const Eina_Value_Type *type)
5849 {
5850 EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(type), NULL);
5851 return type->name;
5852 }
5853