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