From 825a3d837a33f226c879cd02ad15c3fba57e8b2c Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Mon, 23 Jan 2012 23:30:42 +1000 Subject: Update the EFL to what I'm actually using, coz I'm using some stuff not yet released. --- libraries/eina/src/lib/Makefile.am | 10 +- libraries/eina/src/lib/Makefile.in | 68 +- libraries/eina/src/lib/eina_array.c | 4 +- libraries/eina/src/lib/eina_binbuf_template_c.x | 9 + libraries/eina/src/lib/eina_cpu.c | 4 +- libraries/eina/src/lib/eina_file.c | 128 +- libraries/eina/src/lib/eina_hash.c | 6 +- libraries/eina/src/lib/eina_inarray.c | 777 ++++ libraries/eina/src/lib/eina_log.c | 145 +- libraries/eina/src/lib/eina_magic.c | 11 +- libraries/eina/src/lib/eina_main.c | 16 +- libraries/eina/src/lib/eina_mmap.c | 5 + libraries/eina/src/lib/eina_module.c | 1 + libraries/eina/src/lib/eina_prefix.c | 37 +- libraries/eina/src/lib/eina_private.h | 6 + libraries/eina/src/lib/eina_rbtree.c | 10 +- libraries/eina/src/lib/eina_simple_xml_parser.c | 19 +- libraries/eina/src/lib/eina_strbuf.c | 6 +- libraries/eina/src/lib/eina_value.c | 4977 +++++++++++++++++++++++ libraries/eina/src/lib/eina_xattr.c | 191 + 20 files changed, 6346 insertions(+), 84 deletions(-) create mode 100644 libraries/eina/src/lib/eina_inarray.c (limited to 'libraries/eina/src/lib') diff --git a/libraries/eina/src/lib/Makefile.am b/libraries/eina/src/lib/Makefile.am index 0537a61..d8c9d20 100644 --- a/libraries/eina/src/lib/Makefile.am +++ b/libraries/eina/src/lib/Makefile.am @@ -22,6 +22,7 @@ eina_error.c \ eina_fp.c \ eina_hamster.c \ eina_hash.c \ +eina_inarray.c \ eina_inlist.c \ eina_iterator.c \ eina_lalloc.c \ @@ -130,12 +131,17 @@ eina_amalgamation.c: $(base_sources) Makefile @echo "#include " >> eina_amalgamation.c @echo "#include " >> eina_amalgamation.c @echo "#include " >> eina_amalgamation.c - @echo "#include " >> eina_amalgamation.c + @echo "#ifdef HAVE_DLOPEN" >> eina_amalgamation.c + @echo "# include " >> eina_amalgamation.c + @echo "#endif" >> eina_amalgamation.c @echo "#include " >> eina_amalgamation.c - @echo "#include " >> eina_amalgamation.c + @echo "#ifdef HAVE_DIRENT_H" >> eina_amalgamation.c + @echo "# include " >> eina_amalgamation.c + @echo "#endif" >> eina_amalgamation.c @echo "#include " >> eina_amalgamation.c @echo "#include " >> eina_amalgamation.c @echo "#include " >> eina_amalgamation.c + @echo "#include " >> eina_amalgamation.c @echo "#ifdef HAVE_EVIL" >> eina_amalgamation.c @echo "# include " >> eina_amalgamation.c diff --git a/libraries/eina/src/lib/Makefile.in b/libraries/eina/src/lib/Makefile.in index 359aba0..878bcbe 100644 --- a/libraries/eina/src/lib/Makefile.in +++ b/libraries/eina/src/lib/Makefile.in @@ -96,15 +96,16 @@ libeina_la_DEPENDENCIES = am__libeina_la_SOURCES_DIST = eina_accessor.c eina_array.c \ eina_benchmark.c eina_binbuf.c eina_binshare.c eina_convert.c \ eina_counter.c eina_cpu.c eina_error.c eina_fp.c \ - eina_hamster.c eina_hash.c eina_inlist.c eina_iterator.c \ - eina_lalloc.c eina_list.c eina_log.c eina_magic.c eina_main.c \ - eina_matrixsparse.c eina_mempool.c eina_mmap.c eina_module.c \ - eina_prefix.c eina_quadtree.c eina_rbtree.c eina_rectangle.c \ - eina_safety_checks.c eina_sched.c eina_share_common.c \ - eina_simple_xml_parser.c eina_str.c eina_strbuf.c \ - eina_strbuf_common.c eina_stringshare.c eina_tiler.c \ - eina_unicode.c eina_ustrbuf.c eina_ustringshare.c eina_value.c \ - eina_xattr.c eina_file_win32.c eina_file.c \ + eina_hamster.c eina_hash.c eina_inarray.c eina_inlist.c \ + eina_iterator.c eina_lalloc.c eina_list.c eina_log.c \ + eina_magic.c eina_main.c eina_matrixsparse.c eina_mempool.c \ + eina_mmap.c eina_module.c eina_prefix.c eina_quadtree.c \ + eina_rbtree.c eina_rectangle.c eina_safety_checks.c \ + eina_sched.c eina_share_common.c eina_simple_xml_parser.c \ + eina_str.c eina_strbuf.c eina_strbuf_common.c \ + eina_stringshare.c eina_tiler.c eina_unicode.c eina_ustrbuf.c \ + eina_ustringshare.c eina_value.c eina_xattr.c \ + eina_file_win32.c eina_file.c \ $(top_srcdir)/src/modules/mp/buddy/eina_buddy.c \ $(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c \ $(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c \ @@ -129,15 +130,16 @@ am__objects_10 = libeina_la-eina_accessor.lo libeina_la-eina_array.lo \ libeina_la-eina_counter.lo libeina_la-eina_cpu.lo \ libeina_la-eina_error.lo libeina_la-eina_fp.lo \ libeina_la-eina_hamster.lo libeina_la-eina_hash.lo \ - libeina_la-eina_inlist.lo libeina_la-eina_iterator.lo \ - libeina_la-eina_lalloc.lo libeina_la-eina_list.lo \ - libeina_la-eina_log.lo libeina_la-eina_magic.lo \ - libeina_la-eina_main.lo libeina_la-eina_matrixsparse.lo \ - libeina_la-eina_mempool.lo libeina_la-eina_mmap.lo \ - libeina_la-eina_module.lo libeina_la-eina_prefix.lo \ - libeina_la-eina_quadtree.lo libeina_la-eina_rbtree.lo \ - libeina_la-eina_rectangle.lo libeina_la-eina_safety_checks.lo \ - libeina_la-eina_sched.lo libeina_la-eina_share_common.lo \ + libeina_la-eina_inarray.lo libeina_la-eina_inlist.lo \ + libeina_la-eina_iterator.lo libeina_la-eina_lalloc.lo \ + libeina_la-eina_list.lo libeina_la-eina_log.lo \ + libeina_la-eina_magic.lo libeina_la-eina_main.lo \ + libeina_la-eina_matrixsparse.lo libeina_la-eina_mempool.lo \ + libeina_la-eina_mmap.lo libeina_la-eina_module.lo \ + libeina_la-eina_prefix.lo libeina_la-eina_quadtree.lo \ + libeina_la-eina_rbtree.lo libeina_la-eina_rectangle.lo \ + libeina_la-eina_safety_checks.lo libeina_la-eina_sched.lo \ + libeina_la-eina_share_common.lo \ libeina_la-eina_simple_xml_parser.lo libeina_la-eina_str.lo \ libeina_la-eina_strbuf.lo libeina_la-eina_strbuf_common.lo \ libeina_la-eina_stringshare.lo libeina_la-eina_tiler.lo \ @@ -231,7 +233,9 @@ EFL_SIMD_FLAGS = @EFL_SIMD_FLAGS@ EGREP = @EGREP@ EINA_CFLAGS = @EINA_CFLAGS@ EINA_CONFIGURE_DEFAULT_MEMPOOL = @EINA_CONFIGURE_DEFAULT_MEMPOOL@ +EINA_CONFIGURE_ENABLE_LOG = @EINA_CONFIGURE_ENABLE_LOG@ EINA_CONFIGURE_HAVE_DEBUG_THREADS = @EINA_CONFIGURE_HAVE_DEBUG_THREADS@ +EINA_CONFIGURE_HAVE_DIRENT_H = @EINA_CONFIGURE_HAVE_DIRENT_H@ EINA_CONFIGURE_HAVE_INTTYPES_H = @EINA_CONFIGURE_HAVE_INTTYPES_H@ EINA_CONFIGURE_HAVE_ON_OFF_THREADS = @EINA_CONFIGURE_HAVE_ON_OFF_THREADS@ EINA_CONFIGURE_HAVE_STDINT_H = @EINA_CONFIGURE_HAVE_STDINT_H@ @@ -283,8 +287,6 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -371,10 +373,10 @@ AM_CPPFLAGS = \ base_sources = eina_accessor.c eina_array.c eina_benchmark.c \ eina_binbuf.c eina_binshare.c eina_convert.c eina_counter.c \ eina_cpu.c eina_error.c eina_fp.c eina_hamster.c eina_hash.c \ - eina_inlist.c eina_iterator.c eina_lalloc.c eina_list.c \ - eina_log.c eina_magic.c eina_main.c eina_matrixsparse.c \ - eina_mempool.c eina_mmap.c eina_module.c eina_prefix.c \ - eina_quadtree.c eina_rbtree.c eina_rectangle.c \ + eina_inarray.c eina_inlist.c eina_iterator.c eina_lalloc.c \ + eina_list.c eina_log.c eina_magic.c eina_main.c \ + eina_matrixsparse.c eina_mempool.c eina_mmap.c eina_module.c \ + eina_prefix.c eina_quadtree.c eina_rbtree.c eina_rectangle.c \ eina_safety_checks.c eina_sched.c eina_share_common.c \ eina_simple_xml_parser.c eina_str.c eina_strbuf.c \ eina_strbuf_common.c eina_stringshare.c eina_tiler.c \ @@ -489,6 +491,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_fp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_hamster.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_hash.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_inarray.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_inlist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_iterator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_lalloc.Plo@am__quote@ @@ -641,6 +644,14 @@ libeina_la-eina_hash.lo: eina_hash.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_hash.lo `test -f 'eina_hash.c' || echo '$(srcdir)/'`eina_hash.c +libeina_la-eina_inarray.lo: eina_inarray.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_inarray.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_inarray.Tpo -c -o libeina_la-eina_inarray.lo `test -f 'eina_inarray.c' || echo '$(srcdir)/'`eina_inarray.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_inarray.Tpo $(DEPDIR)/libeina_la-eina_inarray.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_inarray.c' object='libeina_la-eina_inarray.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -c -o libeina_la-eina_inarray.lo `test -f 'eina_inarray.c' || echo '$(srcdir)/'`eina_inarray.c + libeina_la-eina_inlist.lo: eina_inlist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_inlist.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_inlist.Tpo -c -o libeina_la-eina_inlist.lo `test -f 'eina_inlist.c' || echo '$(srcdir)/'`eina_inlist.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_inlist.Tpo $(DEPDIR)/libeina_la-eina_inlist.Plo @@ -1189,12 +1200,17 @@ uninstall-am: uninstall-libLTLIBRARIES @EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c @EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c @EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c -@EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#ifdef HAVE_DLOPEN" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "# include " >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#endif" >> eina_amalgamation.c @EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c -@EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#ifdef HAVE_DIRENT_H" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "# include " >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#endif" >> eina_amalgamation.c @EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c @EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c @EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c @EINA_AMALGAMATION_TRUE@ @echo "#ifdef HAVE_EVIL" >> eina_amalgamation.c @EINA_AMALGAMATION_TRUE@ @echo "# include " >> eina_amalgamation.c diff --git a/libraries/eina/src/lib/eina_array.c b/libraries/eina/src/lib/eina_array.c index 5a850ac..4bcab61 100644 --- a/libraries/eina/src/lib/eina_array.c +++ b/libraries/eina/src/lib/eina_array.c @@ -119,7 +119,7 @@ eina_array_iterator_next(Eina_Iterator_Array *it, void **data) { EINA_MAGIC_CHECK_ARRAY_ITERATOR(it, EINA_FALSE); - if (!(it->index < eina_array_count_get(it->array))) + if (!(it->index < eina_array_count(it->array))) return EINA_FALSE; if (data) @@ -150,7 +150,7 @@ eina_array_accessor_get_at(Eina_Accessor_Array *it, { EINA_MAGIC_CHECK_ARRAY_ACCESSOR(it, EINA_FALSE); - if (!(idx < eina_array_count_get(it->array))) + if (!(idx < eina_array_count(it->array))) return EINA_FALSE; if (data) diff --git a/libraries/eina/src/lib/eina_binbuf_template_c.x b/libraries/eina/src/lib/eina_binbuf_template_c.x index 613a715..7e0c539 100644 --- a/libraries/eina/src/lib/eina_binbuf_template_c.x +++ b/libraries/eina/src/lib/eina_binbuf_template_c.x @@ -65,6 +65,15 @@ _FUNC_EXPAND(new)(void) return buf; } +EAPI _STRBUF_STRUCT_NAME * +_FUNC_EXPAND(manage_new_length)(_STRBUF_DATA_TYPE *str, size_t length) +{ + _STRBUF_STRUCT_NAME *buf = + eina_strbuf_common_manage_new(_STRBUF_CSIZE, (void *) str, length); + EINA_MAGIC_SET(buf, _STRBUF_MAGIC); + return buf; +} + EAPI void _FUNC_EXPAND(free)(_STRBUF_STRUCT_NAME *buf) { diff --git a/libraries/eina/src/lib/eina_cpu.c b/libraries/eina/src/lib/eina_cpu.c index 8af550d..5b190e4 100644 --- a/libraries/eina/src/lib/eina_cpu.c +++ b/libraries/eina/src/lib/eina_cpu.c @@ -24,7 +24,7 @@ # ifdef _WIN32 # define WIN32_LEAN_AND_MEAN # include -# elif defined (__SUNPRO_C) || defined(__GNU__) +# elif defined (__sun) || defined(__GNU__) # include # elif defined (__FreeBSD__) || defined (__OpenBSD__) || \ defined (__NetBSD__) || defined (__DragonFly__) || defined (__MacOSX__) || \ @@ -140,7 +140,7 @@ EAPI int eina_cpu_count(void) GetSystemInfo(&sysinfo); return sysinfo.dwNumberOfProcessors; -# elif defined (__SUNPRO_C) || defined(__GNU__) +# elif defined (__sun) || defined(__GNU__) /* * _SC_NPROCESSORS_ONLN: number of processors that are online, that is available when sysconf is called. The number diff --git a/libraries/eina/src/lib/eina_file.c b/libraries/eina/src/lib/eina_file.c index 84b9e78..0b836b3 100644 --- a/libraries/eina/src/lib/eina_file.c +++ b/libraries/eina/src/lib/eina_file.c @@ -38,13 +38,18 @@ extern "C" void *alloca (size_t); #endif +#include #include #include -#include +#ifdef HAVE_DIRENT_H +# include +#endif #include #include #include -#include +#ifdef HAVE_SYS_MMAN_H +# include +#endif #include #define PATH_DELIM '/' @@ -60,6 +65,8 @@ void *alloca (size_t); #include "eina_list.h" #include "eina_lock.h" #include "eina_mmap.h" +#include "eina_log.h" +#include "eina_xattr.h" #ifdef HAVE_ESCAPE_H # include @@ -95,9 +102,8 @@ void *alloca (size_t); #define EINA_SMALL_PAGE 4096 # define EINA_HUGE_PAGE 16 * 1024 * 1024 +#ifdef HAVE_DIRENT_H typedef struct _Eina_File_Iterator Eina_File_Iterator; -typedef struct _Eina_File_Map Eina_File_Map; - struct _Eina_File_Iterator { Eina_Iterator iterator; @@ -107,6 +113,7 @@ struct _Eina_File_Iterator char dir[1]; }; +#endif struct _Eina_File { @@ -132,8 +139,10 @@ struct _Eina_File Eina_Bool shared : 1; Eina_Bool delete_me : 1; + Eina_Bool global_faulty : 1; }; +typedef struct _Eina_File_Map Eina_File_Map; struct _Eina_File_Map { void *map; @@ -144,6 +153,7 @@ struct _Eina_File_Map int refcount; Eina_Bool hugetlb : 1; + Eina_Bool faulty : 1; }; static Eina_Hash *_eina_file_cache = NULL; @@ -156,6 +166,7 @@ static int _eina_file_log_dom = -1; * The code and description of the issue can be found at : * http://womble.decadent.org.uk/readdir_r-advisory.html */ +#ifdef HAVE_DIRENT_H static long _eina_name_max(DIR *dirp) { @@ -390,6 +401,7 @@ _eina_file_stat_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data) return EINA_TRUE; } +#endif static void _eina_file_real_close(Eina_File *file) @@ -511,8 +523,8 @@ slprintf(char *str, size_t size, const char *format, ...) va_end(ap); } -static char* -_eina_file_escape(const char* path, int* length) +static char * +_eina_file_escape(const char *path, int *length) { char *result = strdup(path ? path : ""); char *p = result; @@ -738,6 +750,7 @@ eina_file_split(char *path) EAPI Eina_Iterator * eina_file_ls(const char *dir) { +#ifdef HAVE_DIRENT_H Eina_File_Iterator *it; size_t length; @@ -773,11 +786,16 @@ eina_file_ls(const char *dir) it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_ls_iterator_free); return &it->iterator; +#else + (void) dir; + return NULL; +#endif } EAPI Eina_Iterator * eina_file_direct_ls(const char *dir) { +#ifdef HAVE_DIRENT_H Eina_File_Direct_Iterator *it; size_t length; @@ -825,11 +843,16 @@ eina_file_direct_ls(const char *dir) it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_direct_ls_iterator_free); return &it->iterator; +#else + (void) dir; + return NULL; +#endif } EAPI Eina_Iterator * eina_file_stat_ls(const char *dir) { +#ifdef HAVE_DIRENT_H Eina_File_Direct_Iterator *it; size_t length; @@ -877,6 +900,10 @@ eina_file_stat_ls(const char *dir) it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_direct_ls_iterator_free); return &it->iterator; +#else + (void) dir; + return NULL; +#endif } EAPI Eina_File * @@ -887,7 +914,9 @@ eina_file_open(const char *path, Eina_Bool shared) char *filename; struct stat file_stat; int fd = -1; +#ifdef HAVE_EXECVP int flags; +#endif EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL); @@ -1184,4 +1213,91 @@ eina_file_map_free(Eina_File *file, void *map) eina_lock_release(&file->lock); } +EAPI Eina_Bool +eina_file_map_faulted(Eina_File *file, void *map) +{ + Eina_File_Map *em; + + EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE); + + eina_lock_take(&file->lock); + + if (file->global_map == map) return file->global_faulty; + + em = eina_hash_find(file->rmap, &map); + if (!em) return EINA_FALSE; + + return em->faulty; +} + +EAPI Eina_Iterator * +eina_file_xattr_get(Eina_File *file) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); + + return eina_xattr_fd_ls(file->fd); +} + +EAPI Eina_Iterator * +eina_file_xattr_value_get(Eina_File *file) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); + + return eina_xattr_value_fd_ls(file->fd); +} + +void +eina_file_mmap_faulty(void *addr, long page_size) +{ + Eina_File_Map *m; + Eina_File *f; + Eina_Iterator *itf; + Eina_Iterator *itm; + + /* NOTE: I actually don't know if other thread are running, I will try to take the lock. + It may be possible that if other thread are not running and they were in the middle of + accessing an Eina_File this lock are still taken and we will result as a deadlock. */ + eina_lock_take(&_eina_file_lock_cache); + + itf = eina_hash_iterator_data_new(_eina_file_cache); + EINA_ITERATOR_FOREACH(itf, f) + { + Eina_Bool faulty = EINA_FALSE; + + eina_lock_take(&f->lock); + + if (f->global_map) + { + if ((unsigned char *) addr < (((unsigned char *)f->global_map) + f->length) && + (((unsigned char *) addr) + page_size) >= (unsigned char *) f->global_map) + { + f->global_faulty = EINA_TRUE; + faulty = EINA_TRUE; + } + } + + if (!faulty) + { + itm = eina_hash_iterator_data_new(f->map); + EINA_ITERATOR_FOREACH(itm, m) + { + if ((unsigned char *) addr < (((unsigned char *)m->map) + m->length) && + (((unsigned char *) addr) + page_size) >= (unsigned char *) m->map) + { + m->faulty = EINA_TRUE; + faulty = EINA_TRUE; + break; + } + } + eina_iterator_free(itm); + } + + eina_lock_release(&f->lock); + + if (faulty) break; + } + eina_iterator_free(itf); + + eina_lock_release(&_eina_file_lock_cache); +} diff --git a/libraries/eina/src/lib/eina_hash.c b/libraries/eina/src/lib/eina_hash.c index 5df20aa..5196894 100644 --- a/libraries/eina/src/lib/eina_hash.c +++ b/libraries/eina/src/lib/eina_hash.c @@ -854,8 +854,9 @@ eina_hash_free(Eina_Hash *hash) { int i; + if (!hash) return ; + EINA_MAGIC_CHECK_HASH(hash); - EINA_SAFETY_ON_NULL_RETURN(hash); if (hash->buckets) { @@ -871,8 +872,9 @@ eina_hash_free_buckets(Eina_Hash *hash) { int i; + if (!hash) return ; + EINA_MAGIC_CHECK_HASH(hash); - EINA_SAFETY_ON_NULL_RETURN(hash); if (hash->buckets) { diff --git a/libraries/eina/src/lib/eina_inarray.c b/libraries/eina/src/lib/eina_inarray.c new file mode 100644 index 0000000..dc95bc6 --- /dev/null +++ b/libraries/eina/src/lib/eina_inarray.c @@ -0,0 +1,777 @@ +/* EINA - EFL data type library + * Copyright (C) 2012 - ProFUSION embedded systems + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_error.h" +#include "eina_log.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_inarray.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +static const char EINA_MAGIC_INARRAY_STR[] = "Eina Inline Array"; +static const char EINA_MAGIC_INARRAY_ITERATOR_STR[] = "Eina Inline Array Iterator"; +static const char EINA_MAGIC_INARRAY_ACCESSOR_STR[] = "Eina Inline Array Accessor"; + +typedef struct _Eina_Iterator_Inarray Eina_Iterator_Inarray; +typedef struct _Eina_Accessor_Inarray Eina_Accessor_Inarray; + +struct _Eina_Iterator_Inarray +{ + Eina_Iterator iterator; + const Eina_Inarray *array; + unsigned int pos; + EINA_MAGIC +}; + +struct _Eina_Accessor_Inarray +{ + Eina_Accessor accessor; + const Eina_Inarray *array; + EINA_MAGIC +}; + +static int _eina_inarray_log_dom = -1; + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_eina_inarray_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_inarray_log_dom, __VA_ARGS__) + +#define EINA_MAGIC_CHECK_INARRAY(d, ...) \ + do \ + { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_INARRAY)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_INARRAY); \ + return __VA_ARGS__; \ + } \ + eina_error_set(0); \ + } \ + while(0) + +#define EINA_MAGIC_CHECK_INARRAY_ITERATOR(d, ...) \ + do \ + { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_INARRAY_ITERATOR)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_INARRAY_ITERATOR); \ + return __VA_ARGS__; \ + } \ + eina_error_set(0); \ + } \ + while(0) + +#define EINA_MAGIC_CHECK_INARRAY_ACCESSOR(d, ...) \ + do \ + { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_INARRAY_ACCESSOR)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_INARRAY_ACCESSOR); \ + return __VA_ARGS__; \ + } \ + eina_error_set(0); \ + } \ + while(0) + +static void +_eina_inarray_setup(Eina_Inarray *array, unsigned int member_size, unsigned int step) +{ + EINA_MAGIC_SET(array, EINA_MAGIC_INARRAY); + array->member_size = member_size; + array->len = 0; + array->max = 0; + array->step = (step > 0) ? step : 32; + array->members = NULL; +} + +static Eina_Bool +_eina_inarray_resize(Eina_Inarray *array, unsigned int new_size) +{ + unsigned int new_max; + void *tmp; + + if (new_size < array->max) + return EINA_TRUE; + + if (new_size % array->step == 0) + new_max = new_size; + else + new_max = ((new_size / array->step) + 1) * array->step; + + tmp = realloc(array->members, new_max * array->member_size); + if ((!tmp) && (new_max > 0)) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + + array->members = tmp; + array->max = new_max; + return EINA_TRUE; +} + +static inline void * +_eina_inarray_get(const Eina_Inarray *array, unsigned int position) +{ + unsigned int offset = position * array->member_size; + return (unsigned char *)array->members + offset; +} + +static int +_eina_inarray_search(const Eina_Inarray *array, const void *data, Eina_Compare_Cb compare) +{ + const unsigned char *start, *found; + start = array->members; + found = bsearch(data, start, array->len, array->member_size, compare); + if (!found) + return -1; + return (found - start) / array->member_size; +} + +static unsigned int +_eina_inarray_search_sorted_near(const Eina_Inarray *array, const void *data, Eina_Compare_Cb compare, int *cmp) +{ + unsigned int start, last, middle; + + if (array->len == 0) + { + *cmp = -1; + return 0; + } + else if (array->len == 1) + { + *cmp = compare(data, array->members); + return 0; + } + + start = 0; + last = array->len - 1; /* inclusive */ + do + { + void *p; + middle = start + (last - start) / 2; /* avoid overflow */ + p = _eina_inarray_get(array, middle); + *cmp = compare(data, p); + if (*cmp == 0) + return middle; + else if (*cmp > 0) + start = middle + 1; + else if (middle > 0) + last = middle - 1; + else + break; + } + while (start <= last); + return middle; +} + + +static Eina_Bool +_eina_inarray_iterator_next(Eina_Iterator_Inarray *it, void **data) +{ + EINA_MAGIC_CHECK_INARRAY_ITERATOR(it, EINA_FALSE); + + if (it->pos >= it->array->len) + return EINA_FALSE; + + *data = _eina_inarray_get(it->array, it->pos); + it->pos++; + + return EINA_TRUE; +} + +static Eina_Bool +_eina_inarray_iterator_prev(Eina_Iterator_Inarray *it, void **data) +{ + EINA_MAGIC_CHECK_INARRAY_ITERATOR(it, EINA_FALSE); + + if (it->pos == 0) + return EINA_FALSE; + + it->pos--; + *data = _eina_inarray_get(it->array, it->pos); + + return EINA_TRUE; +} + +static Eina_Inarray * +_eina_inarray_iterator_get_container(Eina_Iterator_Inarray *it) +{ + EINA_MAGIC_CHECK_INARRAY_ITERATOR(it, NULL); + return (Eina_Inarray *)it->array; +} + +static void +_eina_inarray_iterator_free(Eina_Iterator_Inarray *it) +{ + EINA_MAGIC_CHECK_INARRAY_ITERATOR(it); + MAGIC_FREE(it); +} + +static Eina_Bool +_eina_inarray_accessor_get_at(Eina_Accessor_Inarray *it, unsigned int pos, void **data) +{ + EINA_MAGIC_CHECK_INARRAY_ACCESSOR(it, EINA_FALSE); + + if (pos >= it->array->len) + return EINA_FALSE; + + *data = _eina_inarray_get(it->array, pos); + return EINA_TRUE; +} + +static Eina_Inarray * +_eina_inarray_accessor_get_container(Eina_Accessor_Inarray *it) +{ + EINA_MAGIC_CHECK_INARRAY_ACCESSOR(it, NULL); + return (Eina_Inarray *)it->array; +} + +static void +_eina_inarray_accessor_free(Eina_Accessor_Inarray *it) +{ + EINA_MAGIC_CHECK_INARRAY_ACCESSOR(it); + MAGIC_FREE(it); +} + +/** + * @endcond + */ + + +/*============================================================================* +* Global * +*============================================================================*/ + +/** + * @internal + * @brief Initialize the inline array module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the inline array module of Eina. It is called + * by eina_init(). + * + * @see eina_init() + */ +Eina_Bool +eina_inarray_init(void) +{ + _eina_inarray_log_dom = eina_log_domain_register("eina_inarray", + EINA_LOG_COLOR_DEFAULT); + if (_eina_inarray_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_inarray"); + return EINA_FALSE; + } + +#define EMS(n) eina_magic_string_static_set(n, n ## _STR) + EMS(EINA_MAGIC_INARRAY); + EMS(EINA_MAGIC_INARRAY_ITERATOR); + EMS(EINA_MAGIC_INARRAY_ACCESSOR); +#undef EMS + + return EINA_TRUE; +} + +/** + * @internal + * @brief Shut down the inline array module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the inline array module set up by + * eina_inarray_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_inarray_shutdown(void) +{ + eina_log_domain_unregister(_eina_inarray_log_dom); + _eina_inarray_log_dom = -1; + return EINA_TRUE; +} + +/*============================================================================* +* API * +*============================================================================*/ +EAPI Eina_Inarray * +eina_inarray_new(unsigned int member_size, unsigned int step) +{ + Eina_Inarray *ret; + + EINA_SAFETY_ON_TRUE_RETURN_VAL(member_size == 0, NULL); + + ret = malloc(sizeof(*ret)); + if (!ret) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + eina_error_set(0); + _eina_inarray_setup(ret, member_size, step); + return ret; +} + +EAPI void +eina_inarray_free(Eina_Inarray *array) +{ + EINA_MAGIC_CHECK_INARRAY(array); + free(array->members); + free(array); +} + +EAPI void +eina_inarray_setup(Eina_Inarray *array, unsigned int member_size, unsigned int step) +{ + EINA_SAFETY_ON_NULL_RETURN(array); + EINA_SAFETY_ON_TRUE_RETURN(member_size == 0); + _eina_inarray_setup(array, member_size, step); +} + +EAPI void +eina_inarray_flush(Eina_Inarray *array) +{ + EINA_MAGIC_CHECK_INARRAY(array); + free(array->members); + array->len = 0; + array->max = 0; + array->members = NULL; +} + +EAPI int +eina_inarray_append(Eina_Inarray *array, const void *data) +{ + void *p; + + EINA_MAGIC_CHECK_INARRAY(array, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1); + + if (!_eina_inarray_resize(array, array->len + 1)) + return -1; + + p = _eina_inarray_get(array, array->len); + memcpy(p, data, array->member_size); + + array->len++; + return array->len - 1; +} + +EAPI int +eina_inarray_insert(Eina_Inarray *array, const void *data, Eina_Compare_Cb compare) +{ + const unsigned char *itr, *itr_end; + unsigned int sz; + + EINA_MAGIC_CHECK_INARRAY(array, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(compare, -1); + + sz = array->member_size; + itr = array->members; + itr_end = itr + array->len * sz; + for (; itr < itr_end; itr += sz) + { + unsigned int offset, position; + int cmp = compare(itr, data); + if (cmp <= 0) + continue; + + offset = itr - (unsigned char *)array->members; + position = offset / sz; + if (!eina_inarray_insert_at(array, position, data)) + return -1; + return position; + } + return eina_inarray_append(array, data); +} + +EAPI int +eina_inarray_insert_sorted(Eina_Inarray *array, const void *data, Eina_Compare_Cb compare) +{ + unsigned int pos; + int cmp; + + EINA_MAGIC_CHECK_INARRAY(array, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(compare, -1); + + pos = _eina_inarray_search_sorted_near(array, data, compare, &cmp); + if (cmp > 0) + pos++; + + if (!eina_inarray_insert_at(array, pos, data)) + return -1; + return pos; +} + +EAPI int +eina_inarray_remove(Eina_Inarray *array, const void *data) +{ + const unsigned char *itr, *itr_end; + unsigned int position, sz; + + EINA_MAGIC_CHECK_INARRAY(array, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1); + + sz = array->member_size; + if ((data >= array->members) && + (data < _eina_inarray_get(array, array->len))) + { + unsigned int offset = ((unsigned char *)data - + (unsigned char *)array->members); + position = offset / sz; + goto found; + } + + itr = array->members; + itr_end = itr + array->len * sz; + for (; itr < itr_end; itr += sz) + { + if (memcmp(data, itr, sz) == 0) + { + unsigned int offset = itr - (unsigned char *)array->members; + position = offset / sz; + goto found; + } + } + return -1; + +found: + if (!eina_inarray_remove_at(array, position)) + return -1; + return position; +} + +EAPI int +eina_inarray_pop(Eina_Inarray *array) +{ + EINA_MAGIC_CHECK_INARRAY(array, -1); + EINA_SAFETY_ON_TRUE_RETURN_VAL(array->len == 0, -1); + if (!_eina_inarray_resize(array, array->len - 1)) + return -1; + array->len--; + return array->len + 1; +} + +EAPI void * +eina_inarray_nth(const Eina_Inarray *array, unsigned int position) +{ + EINA_MAGIC_CHECK_INARRAY(array, NULL); + EINA_SAFETY_ON_TRUE_RETURN_VAL(position >= array->len, NULL); + return _eina_inarray_get(array, position); +} + +EAPI Eina_Bool +eina_inarray_insert_at(Eina_Inarray *array, unsigned int position, const void *data) +{ + unsigned int sz; + unsigned char *p; + + EINA_MAGIC_CHECK_INARRAY(array, EINA_FALSE); + EINA_SAFETY_ON_TRUE_RETURN_VAL(position > array->len, EINA_FALSE); + + if (!_eina_inarray_resize(array, array->len + 1)) + return EINA_FALSE; + + p = _eina_inarray_get(array, position); + sz = array->member_size; + if (array->len > position) + memmove(p + sz, p, (array->len - position) * sz); + memcpy(p, data, sz); + + array->len++; + return EINA_TRUE; +} + +EAPI void * +eina_inarray_alloc_at(Eina_Inarray *array, unsigned int position, unsigned int member_count) +{ + unsigned int sz; + unsigned char *p; + + EINA_MAGIC_CHECK_INARRAY(array, NULL); + EINA_SAFETY_ON_TRUE_RETURN_VAL(position > array->len, NULL); + EINA_SAFETY_ON_TRUE_RETURN_VAL(member_count == 0, NULL); + + if (!_eina_inarray_resize(array, array->len + member_count)) + return NULL; + + p = _eina_inarray_get(array, position); + sz = array->member_size; + if (array->len > position) + memmove(p + member_count * sz, p, (array->len - position) * sz); + + array->len += member_count; + return p; +} + +EAPI Eina_Bool +eina_inarray_replace_at(Eina_Inarray *array, unsigned int position, const void *data) +{ + unsigned char *p; + + EINA_MAGIC_CHECK_INARRAY(array, EINA_FALSE); + EINA_SAFETY_ON_TRUE_RETURN_VAL(position >= array->len, EINA_FALSE); + + p = _eina_inarray_get(array, position); + memcpy(p, data, array->member_size); + + return EINA_TRUE; +} + +EAPI Eina_Bool +eina_inarray_remove_at(Eina_Inarray *array, unsigned int position) +{ + EINA_MAGIC_CHECK_INARRAY(array, EINA_FALSE); + EINA_SAFETY_ON_TRUE_RETURN_VAL(position >= array->len, EINA_FALSE); + + if (position + 1 < array->len) + { + unsigned int sz = array->member_size; + unsigned char *p = _eina_inarray_get(array, position); + memmove(p, p + sz, (array->len - position - 1) * sz); + } + + _eina_inarray_resize(array, array->len - 1); + array->len--; + return EINA_TRUE; +} + +EAPI void +eina_inarray_reverse(Eina_Inarray *array) +{ + size_t sz; + unsigned char *fwd, *rev, *fwd_end; + void *tmp; + + EINA_MAGIC_CHECK_INARRAY(array); + + if (array->len < 2) + return; + + sz = array->member_size; + + tmp = alloca(sz); + EINA_SAFETY_ON_NULL_RETURN(tmp); + + fwd = array->members; + fwd_end = fwd + (array->len / 2) * sz; + + rev = fwd + (array->len - 1) * sz; + + for (; fwd < fwd_end; fwd += sz, rev -= sz) + { + memcpy(tmp, fwd, sz); + memcpy(fwd, rev, sz); + memcpy(rev, tmp, sz); + } +} + +EAPI void +eina_inarray_sort(Eina_Inarray *array, Eina_Compare_Cb compare) +{ + EINA_MAGIC_CHECK_INARRAY(array); + EINA_SAFETY_ON_NULL_RETURN(compare); + qsort(array->members, array->len, array->member_size, compare); +} + +EAPI int +eina_inarray_search(const Eina_Inarray *array, const void *data, Eina_Compare_Cb compare) +{ + EINA_MAGIC_CHECK_INARRAY(array, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(compare, -1); + return _eina_inarray_search(array, data, compare); +} + +EAPI int +eina_inarray_search_sorted(const Eina_Inarray *array, const void *data, Eina_Compare_Cb compare) +{ + unsigned int pos; + int cmp; + + EINA_MAGIC_CHECK_INARRAY(array, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(compare, -1); + + pos = _eina_inarray_search_sorted_near(array, data, compare, &cmp); + if (cmp == 0) + return pos; + return -1; +} + +EAPI Eina_Bool +eina_inarray_foreach(const Eina_Inarray *array, Eina_Each_Cb function, const void *user_data) +{ + unsigned char *itr, *itr_end; + unsigned int sz; + Eina_Bool ret = EINA_TRUE; + + EINA_MAGIC_CHECK_INARRAY(array, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(function, EINA_FALSE); + + sz = array->member_size; + itr = array->members; + itr_end = itr + array->len * sz; + for (; (itr < itr_end) && (ret); itr += sz) + ret = function(array, itr, (void *)user_data); + return ret; +} + +EAPI int +eina_inarray_foreach_remove(Eina_Inarray *array, Eina_Each_Cb match, const void *user_data) +{ + unsigned int i = 0, count = 0; + + EINA_MAGIC_CHECK_INARRAY(array, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(match, -1); + + while (i < array->len) + { + void *p = _eina_inarray_get(array, i); + if (match(array, p, (void *)user_data) == EINA_FALSE) + { + i++; + continue; + } + + eina_inarray_remove_at(array, i); + count++; + } + + return count; +} + +EAPI unsigned int +eina_inarray_count(const Eina_Inarray *array) +{ + EINA_MAGIC_CHECK_INARRAY(array, 0); + return array->len; +} + +EAPI Eina_Iterator * +eina_inarray_iterator_new(const Eina_Inarray *array) +{ + Eina_Iterator_Inarray *it; + + EINA_MAGIC_CHECK_INARRAY(array, NULL); + + eina_error_set(0); + it = calloc(1, sizeof(Eina_Iterator_Inarray)); + if (!it) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + EINA_MAGIC_SET(it, EINA_MAGIC_INARRAY_ITERATOR); + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->array = array; + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_eina_inarray_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER + (_eina_inarray_iterator_get_container); + it->iterator.free = FUNC_ITERATOR_FREE(_eina_inarray_iterator_free); + + return &it->iterator; +} + +EAPI Eina_Iterator * +eina_inarray_iterator_reversed_new(const Eina_Inarray *array) +{ + Eina_Iterator_Inarray *it; + + EINA_MAGIC_CHECK_INARRAY(array, NULL); + + eina_error_set(0); + it = calloc(1, sizeof(Eina_Iterator_Inarray)); + if (!it) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + EINA_MAGIC_SET(it, EINA_MAGIC_INARRAY_ITERATOR); + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->array = array; + it->pos = array->len; + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_eina_inarray_iterator_prev); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER + (_eina_inarray_iterator_get_container); + it->iterator.free = FUNC_ITERATOR_FREE(_eina_inarray_iterator_free); + + return &it->iterator; +} + +EAPI Eina_Accessor * +eina_inarray_accessor_new(const Eina_Inarray *array) +{ + Eina_Accessor_Inarray *ac; + + EINA_MAGIC_CHECK_INARRAY(array, NULL); + + eina_error_set(0); + ac = calloc(1, sizeof(Eina_Accessor_Inarray)); + if (!ac) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + EINA_MAGIC_SET(ac, EINA_MAGIC_INARRAY_ACCESSOR); + EINA_MAGIC_SET(&ac->accessor, EINA_MAGIC_ACCESSOR); + + ac->array = array; + + ac->accessor.version = EINA_ACCESSOR_VERSION; + ac->accessor.get_at = FUNC_ACCESSOR_GET_AT(_eina_inarray_accessor_get_at); + ac->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER + (_eina_inarray_accessor_get_container); + ac->accessor.free = FUNC_ACCESSOR_FREE(_eina_inarray_accessor_free); + + return &ac->accessor; +} diff --git a/libraries/eina/src/lib/eina_log.c b/libraries/eina/src/lib/eina_log.c index dd772d2..4e2bb6d 100644 --- a/libraries/eina/src/lib/eina_log.c +++ b/libraries/eina/src/lib/eina_log.c @@ -71,6 +71,7 @@ #define EINA_LOG_ENV_FILE_DISABLE "EINA_LOG_FILE_DISABLE" #define EINA_LOG_ENV_FUNCTION_DISABLE "EINA_LOG_FUNCTION_DISABLE" +#ifdef EINA_ENABLE_LOG // Structure for storing domain level settings passed from the command line // that will be matched with application-defined domains. @@ -1294,6 +1295,8 @@ eina_log_print_unlocked(int domain, abort(); } +#endif + /** * @endcond */ @@ -1321,6 +1324,7 @@ eina_log_print_unlocked(int domain, Eina_Bool eina_log_init(void) { +#ifdef EINA_ENABLE_LOG const char *level, *tmp; int color_disable; @@ -1392,6 +1396,7 @@ eina_log_init(void) // Parse pending domains passed through EINA_LOG_LEVELS eina_log_domain_parse_pendings(); +#endif return EINA_TRUE; } @@ -1413,6 +1418,7 @@ eina_log_init(void) Eina_Bool eina_log_shutdown(void) { +#ifdef EINA_ENABLE_LOG Eina_Inlist *tmp; while (_log_domains_count--) @@ -1443,6 +1449,7 @@ eina_log_shutdown(void) free(tmp); } +#endif return EINA_TRUE; } @@ -1460,10 +1467,12 @@ eina_log_shutdown(void) void eina_log_threads_init(void) { +#ifdef EINA_ENABLE_LOG if (_threads_inited) return; _main_thread = SELF(); if (!INIT()) return; _threads_inited = EINA_TRUE; +#endif } /** @@ -1478,11 +1487,13 @@ eina_log_threads_init(void) void eina_log_threads_shutdown(void) { +#ifdef EINA_ENABLE_LOG if (!_threads_inited) return; CHECK_MAIN(); SHUTDOWN(); _threads_enabled = EINA_FALSE; _threads_inited = EINA_FALSE; +#endif } #endif @@ -1504,7 +1515,7 @@ EAPI int EINA_LOG_DOMAIN_GLOBAL = 0; EAPI void eina_log_threads_enable(void) { -#ifdef EFL_HAVE_THREADS +#if defined (EFL_HAVE_THREADS) && defined (EINA_ENABLE_LOG) if (_threads_enabled) return; if (!_threads_inited) eina_log_threads_init(); _threads_enabled = EINA_TRUE; @@ -1515,32 +1526,45 @@ eina_log_threads_enable(void) EAPI void eina_log_print_cb_set(Eina_Log_Print_Cb cb, void *data) { +#ifdef EINA_ENABLE_LOG LOG_LOCK(); _print_cb = cb; _print_cb_data = data; eina_log_print_prefix_update(); LOG_UNLOCK(); +#else + (void) cb; + (void) data; +#endif } EAPI void eina_log_level_set(int level) { +#ifdef EINA_ENABLE_LOG _log_level = level; if (EINA_LIKELY((EINA_LOG_DOMAIN_GLOBAL >= 0) && ((unsigned int)EINA_LOG_DOMAIN_GLOBAL < _log_domains_count))) _log_domains[EINA_LOG_DOMAIN_GLOBAL].level = level; +#else + (void) level; +#endif } EAPI int eina_log_level_get(void) { +#ifdef EINA_ENABLE_LOG return _log_level; +#else + return 0; +#endif } EAPI Eina_Bool eina_log_main_thread_check(void) { -#ifdef EFL_HAVE_THREADS +#if defined (EFL_HAVE_THREADS) && defined (EINA_ENABLE_LOG) return ((!_threads_enabled) || IS_MAIN(SELF())); #else return EINA_TRUE; @@ -1550,66 +1574,107 @@ eina_log_main_thread_check(void) EAPI void eina_log_color_disable_set(Eina_Bool disabled) { +#ifdef EINA_ENABLE_LOG _disable_color = disabled; +#else + (void) disabled; +#endif } EAPI Eina_Bool eina_log_color_disable_get(void) { +#ifdef EINA_ENABLE_LOG return _disable_color; +#else + return EINA_TRUE; +#endif } EAPI void eina_log_file_disable_set(Eina_Bool disabled) { +#ifdef EINA_ENABLE_LOG _disable_file = disabled; +#else + (void) disabled; +#endif } EAPI Eina_Bool eina_log_file_disable_get(void) { +#ifdef EINA_ENABLE_LOG return _disable_file; +#else + return EINA_TRUE; +#endif } EAPI void eina_log_function_disable_set(Eina_Bool disabled) { +#ifdef EINA_ENABLE_LOG _disable_function = disabled; +#else + (void) disabled; +#endif } EAPI Eina_Bool eina_log_function_disable_get(void) { +#ifdef EINA_ENABLE_LOG return _disable_function; +#else + return EINA_TRUE; +#endif } EAPI void eina_log_abort_on_critical_set(Eina_Bool abort_on_critical) { +#ifdef EINA_ENABLE_LOG _abort_on_critical = abort_on_critical; +#else + (void) abort_on_critical; +#endif } EAPI Eina_Bool eina_log_abort_on_critical_get(void) { +#ifdef EINA_ENABLE_LOG return _abort_on_critical; +#else + return EINA_FALSE; +#endif } EAPI void eina_log_abort_on_critical_level_set(int critical_level) { +#ifdef EINA_ENABLE_LOG _abort_level_on_critical = critical_level; +#else + (void) critical_level; +#endif } EAPI int eina_log_abort_on_critical_level_get(void) { +#ifdef EINA_ENABLE_LOG return _abort_level_on_critical; +#else + return 0; +#endif } EAPI int eina_log_domain_register(const char *name, const char *color) { +#ifdef EINA_ENABLE_LOG int r; EINA_SAFETY_ON_NULL_RETURN_VAL(name, -1); @@ -1618,20 +1683,30 @@ eina_log_domain_register(const char *name, const char *color) r = eina_log_domain_register_unlocked(name, color); LOG_UNLOCK(); return r; +#else + (void) name; + (void) color; + return 0; +#endif } EAPI void eina_log_domain_unregister(int domain) { +#ifdef EINA_ENABLE_LOG EINA_SAFETY_ON_FALSE_RETURN(domain >= 0); LOG_LOCK(); eina_log_domain_unregister_unlocked(domain); LOG_UNLOCK(); +#else + (void) domain; +#endif } EAPI void eina_log_domain_level_set(const char *domain_name, int level) { +#ifdef EINA_ENABLE_LOG Eina_Log_Domain_Level_Pending *pending; size_t namelen; unsigned int i; @@ -1672,11 +1747,16 @@ eina_log_domain_level_set(const char *domain_name, int level) memcpy(pending->name, domain_name, namelen + 1); _pending_list = eina_inlist_append(_pending_list, EINA_INLIST_GET(pending)); +#else + (void) domain_name; + (void) level; +#endif } EAPI int eina_log_domain_level_get(const char *domain_name) { +#ifdef EINA_ENABLE_LOG Eina_Log_Domain_Level_Pending *pending; size_t namelen; unsigned int i; @@ -1711,17 +1791,26 @@ eina_log_domain_level_get(const char *domain_name) } return _log_level; +#else + (void) domain_name; + return 0; +#endif } EAPI int eina_log_domain_registered_level_get(int domain) { +#ifdef EINA_ENABLE_LOG EINA_SAFETY_ON_FALSE_RETURN_VAL(domain >= 0, EINA_LOG_LEVEL_UNKNOWN); EINA_SAFETY_ON_FALSE_RETURN_VAL((unsigned int)domain < _log_domains_count, EINA_LOG_LEVEL_UNKNOWN); EINA_SAFETY_ON_TRUE_RETURN_VAL(_log_domains[domain].deleted, EINA_LOG_LEVEL_UNKNOWN); return _log_domains[domain].level; +#else + (void) domain; + return 0; +#endif } EAPI void @@ -1734,9 +1823,20 @@ eina_log_print_cb_stderr(const Eina_Log_Domain *d, __UNUSED__ void *data, va_list args) { +#ifdef EINA_ENABLE_LOG _eina_log_print_prefix(stderr, d, level, file, fnc, line); vfprintf(stderr, fmt, args); putc('\n', stderr); +#else + (void) d; + (void) level; + (void) file; + (void) fnc; + (void) line; + (void) fmt; + (void) data; + (void) args; +#endif } EAPI void @@ -1749,9 +1849,20 @@ eina_log_print_cb_stdout(const Eina_Log_Domain *d, __UNUSED__ void *data, va_list args) { +#ifdef EINA_ENABLE_LOG _eina_log_print_prefix(stdout, d, level, file, fnc, line); vprintf(fmt, args); putchar('\n'); +#else + (void) d; + (void) level; + (void) file; + (void) fnc; + (void) line; + (void) fmt; + (void) data; + (void) args; +#endif } EAPI void @@ -1764,6 +1875,7 @@ eina_log_print_cb_file(const Eina_Log_Domain *d, void *data, va_list args) { +#ifdef EINA_ENABLE_LOG FILE *f = data; #ifdef EFL_HAVE_THREADS if (_threads_enabled) @@ -1787,12 +1899,22 @@ end: #endif vfprintf(f, fmt, args); putc('\n', f); +#else + (void) d; + (void) file; + (void) fnc; + (void) line; + (void) fmt; + (void) data; + (void) args; +#endif } EAPI void eina_log_print(int domain, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, ...) { +#ifdef EINA_ENABLE_LOG va_list args; #ifdef EINA_SAFETY_CHECKS @@ -1820,12 +1942,22 @@ eina_log_print(int domain, Eina_Log_Level level, const char *file, eina_log_print_unlocked(domain, level, file, fnc, line, fmt, args); LOG_UNLOCK(); va_end(args); +#else + (void) domain; + (void) level; + (void) file; + (void) fnc; + (void) line; + (void) fmt; +#endif } EAPI void eina_log_vprint(int domain, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, va_list args) { +#ifdef EINA_ENABLE_LOG + #ifdef EINA_SAFETY_CHECKS if (EINA_UNLIKELY(!file)) { @@ -1849,4 +1981,13 @@ eina_log_vprint(int domain, Eina_Log_Level level, const char *file, LOG_LOCK(); eina_log_print_unlocked(domain, level, file, fnc, line, fmt, args); LOG_UNLOCK(); +#else + (void) domain; + (void) level; + (void) file; + (void) fnc; + (void) line; + (void) fmt; + (void) args; +#endif } diff --git a/libraries/eina/src/lib/eina_magic.c b/libraries/eina/src/lib/eina_magic.c index 1adde92..d1f71cc 100644 --- a/libraries/eina/src/lib/eina_magic.c +++ b/libraries/eina/src/lib/eina_magic.c @@ -79,7 +79,7 @@ _eina_magic_strings_sort_cmp(const void *p1, const void *p2) static int _eina_magic_strings_find_cmp(const void *p1, const void *p2) { - Eina_Magic a = (Eina_Magic)p1; + Eina_Magic a = (Eina_Magic)(size_t)p1; const Eina_Magic_String *b = p2; return a - b->magic; } @@ -129,6 +129,10 @@ _eina_magic_strings_alloc(void) * Global * *============================================================================*/ +EAPI Eina_Error EINA_ERROR_MAGIC_FAILED = 0; + +static const char EINA_ERROR_MAGIC_FAILED_STR[] = "Magic check failed."; + /** * @internal * @brief Initialize the magic string module. @@ -150,6 +154,8 @@ eina_magic_string_init(void) EINA_LOG_ERR("Could not register log domain: eina_magic_string"); return EINA_FALSE; } + EINA_ERROR_MAGIC_FAILED = eina_error_msg_static_register( + EINA_ERROR_MAGIC_FAILED_STR); return EINA_TRUE; } @@ -206,7 +212,7 @@ eina_magic_string_get(Eina_Magic magic) _eina_magic_strings_dirty = 0; } - ems = bsearch((void *)magic, _eina_magic_strings, + ems = bsearch((void *)(size_t)magic, _eina_magic_strings, _eina_magic_strings_count, sizeof(Eina_Magic_String), _eina_magic_strings_find_cmp); if (ems) @@ -271,6 +277,7 @@ eina_magic_fail(void *d, const char *fnc, int line) { + eina_error_set(EINA_ERROR_MAGIC_FAILED); if (!d) eina_log_print(EINA_LOG_DOMAIN_GLOBAL, EINA_LOG_LEVEL_CRITICAL, file, fnc, line, diff --git a/libraries/eina/src/lib/eina_main.c b/libraries/eina/src/lib/eina_main.c index 8727f83..79f8a36 100644 --- a/libraries/eina/src/lib/eina_main.c +++ b/libraries/eina/src/lib/eina_main.c @@ -67,6 +67,8 @@ #include "eina_rectangle.h" #include "eina_safety_checks.h" #include "eina_inlist.h" +#include "eina_inarray.h" +#include "eina_value.h" /*============================================================================* * Local * @@ -131,6 +133,7 @@ EAPI Eina_Inlist *_eina_tracking = NULL; S(magic_string); S(iterator); S(accessor); + S(inarray); S(array); S(module); S(mempool); @@ -149,6 +152,7 @@ EAPI Eina_Inlist *_eina_tracking = NULL; S(simple_xml); S(file); S(prefix); + S(value); #undef S struct eina_desc_setup @@ -161,17 +165,18 @@ struct eina_desc_setup static const struct eina_desc_setup _eina_desc_setup[] = { #define S(x) {# x, eina_ ## x ## _init, eina_ ## x ## _shutdown} /* log is a special case as it needs printf */ + S(stringshare), S(error), S(safety_checks), S(magic_string), S(iterator), S(accessor), + S(inarray), S(array), S(module), S(mempool), S(list), S(binshare), - S(stringshare), S(ustringshare), S(matrixsparse), S(convert), @@ -183,7 +188,8 @@ static const struct eina_desc_setup _eina_desc_setup[] = { S(quadtree), S(simple_xml), S(file), - S(prefix) + S(prefix), + S(value) #undef S }; static const size_t _eina_desc_setup_len = sizeof(_eina_desc_setup) / @@ -236,8 +242,8 @@ eina_init(void) _mt_enabled = 1; mtrace(); } -#endif - +#endif + if (!eina_log_init()) { fprintf(stderr, "Could not initialize eina logging system.\n"); @@ -304,7 +310,7 @@ eina_shutdown(void) muntrace(); _mt_enabled = 0; } -#endif +#endif } return _eina_main_count; diff --git a/libraries/eina/src/lib/eina_mmap.c b/libraries/eina/src/lib/eina_mmap.c index fb27bd7..7929f0e 100644 --- a/libraries/eina/src/lib/eina_mmap.c +++ b/libraries/eina/src/lib/eina_mmap.c @@ -110,6 +110,8 @@ _eina_mmap_safe_sigbus(int sig __UNUSED__, errno = perrno; abort(); } + /* Look into mmaped Eina_File if it was one of them, just to remember for later request */ + eina_file_mmap_faulty(addr, _eina_mmap_pagesize); /* restore previous errno */ errno = perrno; } @@ -162,6 +164,9 @@ eina_mmap_safety_enabled_set(Eina_Bool enabled) sa.sa_sigaction = _eina_mmap_safe_sigbus; sa.sa_flags = SA_RESTART | SA_SIGINFO; sigemptyset(&sa.sa_mask); + /* FIXME: This is rubbish. We return EINA_FALSE whether sigaction + * fails or not. And we never set mmap_safe, so we always hit this + * code path. */ if (sigaction(SIGBUS, &sa, NULL) == 0) return EINA_FALSE; /* setup of SIGBUS handler failed, lets close zero page dev and fail */ close(_eina_mmap_zero_fd); diff --git a/libraries/eina/src/lib/eina_module.c b/libraries/eina/src/lib/eina_module.c index 0dd19a6..26df980 100644 --- a/libraries/eina/src/lib/eina_module.c +++ b/libraries/eina/src/lib/eina_module.c @@ -37,6 +37,7 @@ extern "C" void *alloca (size_t); #endif +#include #include #include #include diff --git a/libraries/eina/src/lib/eina_prefix.c b/libraries/eina/src/lib/eina_prefix.c index 9445222..5b4b0c0 100644 --- a/libraries/eina/src/lib/eina_prefix.c +++ b/libraries/eina/src/lib/eina_prefix.c @@ -150,25 +150,24 @@ _fallback(Eina_Prefix *pfx, const char *pkg_bin, const char *pkg_lib, STRDUP_REP(pfx->prefix_path_lib, pkg_lib); STRDUP_REP(pfx->prefix_path_data, pkg_data); STRDUP_REP(pfx->prefix_path_locale, pkg_locale); - fprintf(stderr, - "WARNING: Could not determine its installed prefix for '%s'\n" - " so am falling back on the compiled in default:\n" - " %s\n" - " implied by the following:\n" - " bindir = %s\n" - " libdir = %s\n" - " datadir = %s\n" - " localedir = %s\n" - " Try setting the following environment variables:\n" - " %s_PREFIX - points to the base prefix of install\n" - " or the next 4 variables\n" - " %s_BIN_DIR - provide a specific binary directory\n" - " %s_LIB_DIR - provide a specific library directory\n" - " %s_DATA_DIR - provide a specific data directory\n" - " %s_LOCALE_DIR - provide a specific locale directory\n" - , envprefix, - pfx->prefix_path, pkg_bin, pkg_lib, pkg_data, pkg_locale, - envprefix, envprefix, envprefix, envprefix, envprefix); + WRN("Could not determine its installed prefix for '%s'\n" + " so am falling back on the compiled in default:\n" + " %s\n" + " implied by the following:\n" + " bindir = %s\n" + " libdir = %s\n" + " datadir = %s\n" + " localedir = %s\n" + " Try setting the following environment variables:\n" + " %s_PREFIX - points to the base prefix of install\n" + " or the next 4 variables\n" + " %s_BIN_DIR - provide a specific binary directory\n" + " %s_LIB_DIR - provide a specific library directory\n" + " %s_DATA_DIR - provide a specific data directory\n" + " %s_LOCALE_DIR - provide a specific locale directory", + envprefix, + pfx->prefix_path, pkg_bin, pkg_lib, pkg_data, pkg_locale, + envprefix, envprefix, envprefix, envprefix, envprefix); pfx->fallback = 1; return 1; } diff --git a/libraries/eina/src/lib/eina_private.h b/libraries/eina/src/lib/eina_private.h index d390397..e31ab47 100644 --- a/libraries/eina/src/lib/eina_private.h +++ b/libraries/eina/src/lib/eina_private.h @@ -91,6 +91,10 @@ #define EINA_MAGIC_SIMPLE_XML_DATA 0x98761261 #define EINA_MAGIC_SIMPLE_XML_ATTRIBUTE 0x98761262 +#define EINA_MAGIC_INARRAY 0x98761270 +#define EINA_MAGIC_INARRAY_ITERATOR 0x98761271 +#define EINA_MAGIC_INARRAY_ACCESSOR 0x98761272 + #define EINA_MAGIC_CLASS 0x9877CB30 /* undef the following, we want out version */ @@ -136,5 +140,7 @@ void eina_log_threads_init(void); void eina_log_threads_shutdown(void); #endif +void eina_file_mmap_faulty(void *addr, long page_size); + #endif /* EINA_PRIVATE_H_ */ diff --git a/libraries/eina/src/lib/eina_rbtree.c b/libraries/eina/src/lib/eina_rbtree.c index c0c9f9e..5f1232c 100644 --- a/libraries/eina/src/lib/eina_rbtree.c +++ b/libraries/eina/src/lib/eina_rbtree.c @@ -83,7 +83,7 @@ _eina_rbtree_iterator_list_new(const Eina_Rbtree *tree) static Eina_Rbtree * _eina_rbtree_iterator_get_content(Eina_Iterator_Rbtree *it) { - if (eina_array_count_get(it->stack) <= 0) + if (eina_array_count(it->stack) <= 0) return NULL; return eina_array_data_get(it->stack, 0); @@ -110,10 +110,10 @@ _eina_rbtree_iterator_next(Eina_Iterator_Rbtree *it, void **data) Eina_Iterator_Rbtree_List *new; Eina_Rbtree *tree; - if (eina_array_count_get(it->stack) <= 0) + if (eina_array_count(it->stack) <= 0) return EINA_FALSE; - last = eina_array_data_get(it->stack, eina_array_count_get(it->stack) - 1); + last = eina_array_data_get(it->stack, eina_array_count(it->stack) - 1); tree = last->tree; if (!last->tree || last->up == EINA_TRUE) @@ -128,10 +128,10 @@ _eina_rbtree_iterator_next(Eina_Iterator_Rbtree *it, void **data) { free(last); - if (eina_array_count_get(it->stack) > 0) + if (eina_array_count(it->stack) > 0) { last = eina_array_data_get(it->stack, - eina_array_count_get( + eina_array_count( it-> stack) - 1); diff --git a/libraries/eina/src/lib/eina_simple_xml_parser.c b/libraries/eina/src/lib/eina_simple_xml_parser.c index 08a8259..4e357ba 100644 --- a/libraries/eina/src/lib/eina_simple_xml_parser.c +++ b/libraries/eina/src/lib/eina_simple_xml_parser.c @@ -38,7 +38,10 @@ extern "C" void *alloca (size_t); #endif -#include +#ifdef HAVE_STRINGS_H +# include +#endif +#include #include #include @@ -121,7 +124,7 @@ static inline const char * _eina_simple_xml_whitespace_find(const char *itr, const char *itr_end) { for (; itr < itr_end; itr++) - if (isspace(*itr)) break; + if (isspace((unsigned char)*itr)) break; return itr; } @@ -129,7 +132,7 @@ static inline const char * _eina_simple_xml_whitespace_skip(const char *itr, const char *itr_end) { for (; itr < itr_end; itr++) - if (!isspace(*itr)) break; + if (!isspace((unsigned char)*itr)) break; return itr; } @@ -137,7 +140,7 @@ static inline const char * _eina_simple_xml_whitespace_unskip(const char *itr, const char *itr_start) { for (itr--; itr > itr_start; itr--) - if (!isspace(*itr)) break; + if (!isspace((unsigned char)*itr)) break; return itr + 1; } @@ -309,7 +312,7 @@ eina_simple_xml_parse(const char *buf, unsigned buflen, Eina_Bool strip, Eina_Si (!memcmp(itr + 2, "DOCTYPE", sizeof("DOCTYPE") - 1)) && ((itr[2 + sizeof("DOCTYPE") - 1] == '>') || - (isspace(itr[2 + sizeof("DOCTYPE") - 1])))) + (isspace((unsigned char)itr[2 + sizeof("DOCTYPE") - 1])))) { type = EINA_SIMPLE_XML_DOCTYPE; toff = sizeof("!DOCTYPE") - 1; @@ -455,7 +458,7 @@ eina_simple_xml_tag_attributes_find(const char *buf, unsigned buflen) for (; itr < itr_end; itr++) { - if (!isspace(*itr)) + if (!isspace((unsigned char)*itr)) { /* user skip tagname and already gave it the attributes */ if (*itr == '=') @@ -492,7 +495,7 @@ eina_simple_xml_attributes_parse(const char *buf, unsigned buflen, Eina_Simple_X key = p; for (key_end = key; key_end < itr_end; key_end++) - if ((*key_end == '=') || (isspace(*key_end))) break; + if ((*key_end == '=') || (isspace((unsigned char)*key_end))) break; if (key_end == itr_end) return EINA_FALSE; if (key_end == key) continue; @@ -504,7 +507,7 @@ eina_simple_xml_attributes_parse(const char *buf, unsigned buflen, Eina_Simple_X value++; } for (; value < itr_end; value++) - if (!isspace(*value)) break; + if (!isspace((unsigned char)*value)) break; if (value == itr_end) return EINA_FALSE; if ((*value == '"') || (*value == '\'')) diff --git a/libraries/eina/src/lib/eina_strbuf.c b/libraries/eina/src/lib/eina_strbuf.c index 74b1eb9..828d842 100644 --- a/libraries/eina/src/lib/eina_strbuf.c +++ b/libraries/eina/src/lib/eina_strbuf.c @@ -162,9 +162,9 @@ eina_strbuf_insert_vprintf(Eina_Strbuf *buf, EAPI void eina_strbuf_trim(Eina_Strbuf *buf) { - char *c = buf->buf; + unsigned char *c = buf->buf; - while (buf->len > 0 && isspace(((unsigned char*)(buf->buf))[buf->len - 1])) + while (buf->len > 0 && isspace(c[buf->len - 1])) buf->len--; while (buf->len > 0 && isspace(*c)) { @@ -178,7 +178,7 @@ eina_strbuf_trim(Eina_Strbuf *buf) EAPI void eina_strbuf_ltrim(Eina_Strbuf *buf) { - char *c = buf->buf; + unsigned char *c = buf->buf; while (buf->len > 0 && isspace(*c)) { diff --git a/libraries/eina/src/lib/eina_value.c b/libraries/eina/src/lib/eina_value.c index 554f907..ba8af52 100644 --- a/libraries/eina/src/lib/eina_value.c +++ b/libraries/eina/src/lib/eina_value.c @@ -28,8 +28,4762 @@ # include "config.h" #endif +#ifdef HAVE_ALLOCA_H +# include +#elif defined __GNUC__ +# define alloca __builtin_alloca +#elif defined _AIX +# define alloca __alloca +#elif defined _MSC_VER +# include +# define alloca _alloca +#else +# include +# ifdef __cplusplus +extern "C" +# endif +void *alloca (size_t); +#endif + +#include /* asprintf() */ +#include /* PRId64 and PRIu64 */ +#include /* struct timeval */ + #include "eina_config.h" #include "eina_private.h" +#include "eina_error.h" +#include "eina_log.h" +#include "eina_strbuf.h" +#include "eina_mempool.h" +#include "eina_lock.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_value.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +static Eina_Mempool *_eina_value_mp = NULL; +static Eina_Hash *_eina_value_inner_mps = NULL; +static Eina_Lock _eina_value_inner_mps_lock; +static char *_eina_value_mp_choice = NULL; +static int _eina_value_log_dom = -1; + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_eina_value_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_value_log_dom, __VA_ARGS__) + +static const unsigned char eina_value_uchar_max = 255U; +static const char eina_value_char_max = 127; +static const char eina_value_char_min = -127 - 1; + +static const unsigned short eina_value_ushort_max = 65535U; +static const short eina_value_short_max = 32767; +static const short eina_value_short_min = -32767 - 1; + +static const unsigned int eina_value_uint_max = 4294967295U; +static const int eina_value_int_max = 2147483647; +static const int eina_value_int_min = -2147483647 - 1; + +static const uint64_t eina_value_uint64_max = 18446744073709551615ULL; +static const int64_t eina_value_int64_max = 9223372036854775807LL; +static const int64_t eina_value_int64_min = -9223372036854775807LL - 1LL; + +#if __WORDSIZE == 64 +static const unsigned long eina_value_ulong_max = 18446744073709551615ULL; +static const long eina_value_long_max = 9223372036854775807LL; +static const long eina_value_long_min = -9223372036854775807LL - 1LL; +#else +static const unsigned long eina_value_ulong_max = 4294967295U; +static const long eina_value_long_max = 2147483647; +static const long eina_value_long_min = -2147483647 - 1; +#endif + + +static Eina_Bool +_eina_value_type_uchar_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + unsigned char *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uchar_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uchar_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const unsigned char *s = src; + unsigned char *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_uchar_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const unsigned char *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_uchar_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const unsigned char v = *(const unsigned char *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_USHORT) + { + unsigned short other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT) + { + unsigned int other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v; + if (EINA_UNLIKELY(v > (unsigned char)eina_value_char_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_SHORT) + { + short other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + const char *other_mem; + char buf[64]; + snprintf(buf, sizeof(buf), "%hhu", v); + other_mem = buf; /* required due &buf == buf */ + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uchar_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + unsigned char *tmem = mem; + *tmem = va_arg(args, unsigned int); /* char is promoted to int for va_arg */ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uchar_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + unsigned char *tmem = mem; + const unsigned char *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uchar_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const unsigned char *tmem = mem; + unsigned char *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ushort_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + unsigned short *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ushort_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ushort_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const unsigned short *s = src; + unsigned short *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_ushort_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const unsigned short *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_ushort_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const unsigned short v = *(const unsigned short *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v > eina_value_uchar_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_USHORT) + { + unsigned short other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT) + { + unsigned int other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v; + if (EINA_UNLIKELY(v > (unsigned char)eina_value_char_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_SHORT) + { + short other_mem = v; + if (EINA_UNLIKELY(v > (unsigned short)eina_value_short_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + const char *other_mem; + char buf[64]; + snprintf(buf, sizeof(buf), "%hu", v); + other_mem = buf; /* required due &buf == buf */ + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ushort_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + unsigned short *tmem = mem; + *tmem = va_arg(args, unsigned int); /* short is promoted to int for va_arg */ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ushort_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + unsigned short *tmem = mem; + const unsigned short *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ushort_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const unsigned short *tmem = mem; + unsigned short *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + unsigned int *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const unsigned int *s = src; + unsigned int *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_uint_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const unsigned int *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_uint_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const unsigned int v = *(const unsigned int *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v > eina_value_uchar_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_USHORT) + { + unsigned short other_mem = v; + if (EINA_UNLIKELY(v > eina_value_ushort_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT) + { + unsigned int other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v; + if (EINA_UNLIKELY(v > (unsigned char)eina_value_char_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_SHORT) + { + short other_mem = v; + if (EINA_UNLIKELY(v > (unsigned short)eina_value_short_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem = v; + if (EINA_UNLIKELY(v > (unsigned int)eina_value_int_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + const char *other_mem; + char buf[64]; + snprintf(buf, sizeof(buf), "%u", v); + other_mem = buf; /* required due &buf == buf */ + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + unsigned int *tmem = mem; + *tmem = va_arg(args, unsigned int); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + unsigned int *tmem = mem; + const unsigned int *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const unsigned int *tmem = mem; + unsigned int *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ulong_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + unsigned long *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ulong_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ulong_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const unsigned long *s = src; + unsigned long *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_ulong_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const unsigned long *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_ulong_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const unsigned long v = *(const unsigned long *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v > eina_value_uchar_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_USHORT) + { + unsigned short other_mem = v; + if (EINA_UNLIKELY(v > eina_value_ushort_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT) + { + unsigned int other_mem = v; + if (EINA_UNLIKELY(v > eina_value_uint_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v; + if (EINA_UNLIKELY(v > (unsigned char)eina_value_char_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_SHORT) + { + short other_mem = v; + if (EINA_UNLIKELY(v > (unsigned short)eina_value_short_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem = v; + if (EINA_UNLIKELY(v > (unsigned int)eina_value_int_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v; + if (EINA_UNLIKELY(v > (unsigned long)eina_value_long_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + const char *other_mem; + char buf[64]; + snprintf(buf, sizeof(buf), "%lu", v); + other_mem = buf; /* required due &buf == buf */ + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ulong_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + unsigned long *tmem = mem; + *tmem = va_arg(args, unsigned long); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ulong_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + unsigned long *tmem = mem; + const unsigned long *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ulong_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const unsigned long *tmem = mem; + unsigned long *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint64_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + uint64_t *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint64_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint64_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const uint64_t *s = src; + uint64_t *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_uint64_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const uint64_t *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_uint64_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const uint64_t v = *(const uint64_t *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v > eina_value_uchar_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_USHORT) + { + unsigned short other_mem = v; + if (EINA_UNLIKELY(v > eina_value_ushort_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT) + { + unsigned int other_mem = v; + if (EINA_UNLIKELY(v > eina_value_uint_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem = v; + if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) && + (v > eina_value_ulong_max))) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v; + if (EINA_UNLIKELY(v > (unsigned char)eina_value_char_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_SHORT) + { + short other_mem = v; + if (EINA_UNLIKELY(v > (unsigned short)eina_value_short_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem = v; + if (EINA_UNLIKELY(v > (unsigned int)eina_value_int_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v; + if (EINA_UNLIKELY(v > (unsigned long)eina_value_long_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + if (EINA_UNLIKELY(v > (uint64_t)eina_value_int64_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + const char *other_mem; + char buf[64]; + snprintf(buf, sizeof(buf), "%"PRIu64, v); + other_mem = buf; /* required due &buf == buf */ + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint64_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + uint64_t *tmem = mem; + *tmem = va_arg(args, uint64_t); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint64_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + uint64_t *tmem = mem; + const uint64_t *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint64_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const uint64_t *tmem = mem; + uint64_t *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_char_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + char *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_char_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_char_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const char *s = src; + char *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_char_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const char *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_char_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const signed char v = *(const signed char *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_USHORT) + { + unsigned short other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT) + { + unsigned int other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_SHORT) + { + short other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + const char *other_mem; + char buf[64]; + snprintf(buf, sizeof(buf), "%hhd", v); + other_mem = buf; /* required due &buf == buf */ + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_char_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + char *tmem = mem; + *tmem = va_arg(args, int); /* char is promoted to int for va_arg */ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_char_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + char *tmem = mem; + const char *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_char_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const char *tmem = mem; + char *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_short_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + short *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_short_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_short_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const short *s = src; + short *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_short_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const short *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_short_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const short v = *(const short *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_uchar_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_USHORT) + { + unsigned short other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT) + { + unsigned int other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v; + if (EINA_UNLIKELY(v < eina_value_char_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_char_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_SHORT) + { + short other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + const char *other_mem; + char buf[64]; + snprintf(buf, sizeof(buf), "%hd", v); + other_mem = buf; /* required due &buf == buf */ + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_short_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + short *tmem = mem; + *tmem = va_arg(args, int); /* short int is promoted to int for va_arg */ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_short_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + short *tmem = mem; + const short *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_short_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const short *tmem = mem; + short *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + int *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const int *s = src; + int *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_int_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const int *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_int_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const int v = *(const int *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_uchar_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_USHORT) + { + unsigned short other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_ushort_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT) + { + unsigned int other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v; + if (EINA_UNLIKELY(v < eina_value_char_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_char_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_SHORT) + { + short other_mem = v; + if (EINA_UNLIKELY(v < eina_value_short_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_short_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + const char *other_mem; + char buf[64]; + snprintf(buf, sizeof(buf), "%d", v); + other_mem = buf; /* required due &buf == buf */ + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + int *tmem = mem; + *tmem = va_arg(args, int); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + int *tmem = mem; + const int *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const int *tmem = mem; + int *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_long_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + long *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_long_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_long_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const long *s = src; + long *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_long_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const long *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_long_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const long v = *(const long *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY((unsigned long) v > eina_value_uchar_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_USHORT) + { + unsigned short other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY((unsigned long) v > eina_value_ushort_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT) + { + unsigned int other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY((unsigned long) v > eina_value_uint_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v; + if (EINA_UNLIKELY(v < eina_value_char_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_char_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_SHORT) + { + short other_mem = v; + if (EINA_UNLIKELY(v < eina_value_short_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_short_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem = v; + if (EINA_UNLIKELY(v < eina_value_int_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_int_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + const char *other_mem; + char buf[64]; + snprintf(buf, sizeof(buf), "%ld", v); + other_mem = buf; /* required due &buf == buf */ + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_long_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + long *tmem = mem; + *tmem = va_arg(args, long); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_long_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + long *tmem = mem; + const long *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_long_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const long *tmem = mem; + long *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int64_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + int64_t *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int64_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int64_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const int64_t *s = src; + int64_t *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_int64_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const int64_t *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_int64_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const int64_t v = *(const int64_t *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_uchar_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_USHORT) + { + unsigned short other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_ushort_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT) + { + unsigned int other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_uint_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) && + (v > eina_value_ulong_max))) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v; + if (EINA_UNLIKELY(v < eina_value_char_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_char_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_SHORT) + { + short other_mem = v; + if (EINA_UNLIKELY(v < eina_value_short_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_short_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem = v; + if (EINA_UNLIKELY(v < eina_value_int_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_int_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v; + if (EINA_UNLIKELY(v < eina_value_long_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_long_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + const char *other_mem; + char buf[64]; + snprintf(buf, sizeof(buf), "%"PRId64, v); + other_mem = buf; /* required due &buf == buf */ + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int64_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + int64_t *tmem = mem; + *tmem = va_arg(args, int64_t); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int64_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + int64_t *tmem = mem; + const int64_t *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int64_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const int64_t *tmem = mem; + int64_t *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_float_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + float *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_float_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_float_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const float *s = src; + float *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_float_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const float *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_float_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const float v = *(const float *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_uchar_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_USHORT) + { + unsigned short other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_ushort_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT) + { + unsigned int other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_uint_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) && + (v > eina_value_ulong_max))) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_uint64_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v; + if (EINA_UNLIKELY(v < eina_value_char_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_char_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_SHORT) + { + short other_mem = v; + if (EINA_UNLIKELY(v < eina_value_short_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_short_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem = v; + if (EINA_UNLIKELY(v < eina_value_int_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_int_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v; + if (EINA_UNLIKELY(v < eina_value_long_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_long_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + if (EINA_UNLIKELY(v < eina_value_int64_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_int64_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + const char *other_mem; + char buf[64]; + snprintf(buf, sizeof(buf), "%f", v); + other_mem = buf; /* required due &buf == buf */ + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_float_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + float *tmem = mem; + *tmem = va_arg(args, double); /* float is promoted to double for va_args */ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_float_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + float *tmem = mem; + const float *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_float_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const float *tmem = mem; + float *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_double_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + double *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_double_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_double_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const double *s = src; + double *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_double_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const double *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_double_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const double v = *(const double *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_uchar_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_USHORT) + { + unsigned short other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_ushort_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT) + { + unsigned int other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_uint_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) && + (v > eina_value_ulong_max))) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v; + if (EINA_UNLIKELY(v < eina_value_char_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_char_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_SHORT) + { + short other_mem = v; + if (EINA_UNLIKELY(v < eina_value_short_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_short_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem = v; + if (EINA_UNLIKELY(v < eina_value_int_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_int_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v; + if (EINA_UNLIKELY(v < eina_value_long_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_long_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + const char *other_mem; + char buf[64]; + snprintf(buf, sizeof(buf), "%g", (double)v); + other_mem = buf; /* required due &buf == buf */ + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_double_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + double *tmem = mem; + *tmem = va_arg(args, double); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_double_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + double *tmem = mem; + const double *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_double_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const double *tmem = mem; + double *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_string_common_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + const char **tmem = mem; + *tmem = NULL; + return EINA_TRUE; +} + +static int +_eina_value_type_string_common_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const char *sa = *(const char **)a; + const char *sb = *(const char **)b; + if (sa == sb) + return 0; + if (sa == NULL) + return -1; + if (sb == NULL) + return 1; + return strcmp(sa, sb); +} + +static Eina_Bool +_eina_value_type_string_common_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const char *v = *(const char **)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem; + if ((sscanf(v, "%hhu", &other_mem) != 1) && + (sscanf(v, "%hhx", &other_mem) != 1) && + (sscanf(v, "%hho", &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_USHORT) + { + unsigned short other_mem; + if ((sscanf(v, "%hu", &other_mem) != 1) && + (sscanf(v, "%hx", &other_mem) != 1) && + (sscanf(v, "%ho", &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT) + { + unsigned int other_mem; + if ((sscanf(v, "%u", &other_mem) != 1) && + (sscanf(v, "%x", &other_mem) != 1) && + (sscanf(v, "%o", &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem; + if ((sscanf(v, "%lu", &other_mem) != 1) && + (sscanf(v, "%lx", &other_mem) != 1) && + (sscanf(v, "%lo", &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem; + if ((sscanf(v, "%"SCNu64, &other_mem) != 1) && + (sscanf(v, "%"SCNx64, &other_mem) != 1) && + (sscanf(v, "%"SCNo64, &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem; + if ((sscanf(v, "%hhd", &other_mem) != 1) && + (sscanf(v, "%hhx", &other_mem) != 1) && + (sscanf(v, "%hho", &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_SHORT) + { + short other_mem; + if ((sscanf(v, "%hd", &other_mem) != 1) && + (sscanf(v, "%hx", &other_mem) != 1) && + (sscanf(v, "%ho", &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem; + if ((sscanf(v, "%d", &other_mem) != 1) && + (sscanf(v, "%x", &other_mem) != 1) && + (sscanf(v, "%o", &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem; + if ((sscanf(v, "%ld", &other_mem) != 1) && + (sscanf(v, "%lx", &other_mem) != 1) && + (sscanf(v, "%lo", &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem; + if ((sscanf(v, "%"SCNd64, &other_mem) != 1) && + (sscanf(v, "%"SCNx64, &other_mem) != 1) && + (sscanf(v, "%"SCNo64, &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem; + if (sscanf(v, "%f", &other_mem) != 1) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem; + if (sscanf(v, "%lf", &other_mem) != 1) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + return eina_value_type_pset(convert, convert_mem, &v); + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_string_common_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + memcpy(ptr, mem, sizeof(const char *)); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_stringshare_flush(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + const char **tmem = mem; + if (*tmem) eina_stringshare_del(*tmem); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_stringshare_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const char * const*s = src; + const char **d = dst; + *d = *s; + eina_stringshare_ref(*d); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_stringshare_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + const char *str = va_arg(args, const char *); + return eina_stringshare_replace((const char **)mem, str); +} + +static Eina_Bool +_eina_value_type_stringshare_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + const char * const *str = ptr; + return eina_stringshare_replace((const char **)mem, *str); +} + +static Eina_Bool +_eina_value_type_string_flush(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + char **tmem = mem; + if (*tmem) free(*tmem); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_string_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const char * const *s = src; + char **d = dst; + if (*s == NULL) + *d = NULL; + else + { + *d = strdup(*s); + if (*d == NULL) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + } + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_string_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + char **tmem = mem; + const char *str = va_arg(args, const char *); + free(*tmem); + if (str == NULL) + *tmem = NULL; + else + { + *tmem = strdup(str); + if (*tmem == NULL) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + } + eina_error_set(0); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_string_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + char **tmem = mem; + const char * const *str = ptr; + free(*tmem); + if (*str == NULL) + *tmem = NULL; + else + { + *tmem = strdup(*str); + if (*tmem == NULL) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + } + eina_error_set(0); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_array_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + memset(mem, 0, sizeof(Eina_Value_Array)); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_array_flush_elements(Eina_Value_Array *tmem) +{ + const Eina_Value_Type *subtype = tmem->subtype; + Eina_Bool ret = EINA_TRUE; + unsigned char sz; + char *ptr, *ptr_end; + + if (!tmem->array) return EINA_TRUE; + + sz = tmem->array->member_size; + ptr = tmem->array->members; + ptr_end = ptr + tmem->array->len * sz; + + for (; ptr < ptr_end; ptr += sz) + ret &= eina_value_type_flush(subtype, ptr); + + eina_inarray_flush(tmem->array); + return ret; +} + +static Eina_Bool +_eina_value_type_array_flush(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + Eina_Value_Array *tmem = mem; + Eina_Bool ret =_eina_value_type_array_flush_elements(tmem); + + if (tmem->array) eina_inarray_free(tmem->array); + tmem->array = NULL; + tmem->subtype = NULL; + return ret; +} + +static Eina_Bool +_eina_value_type_array_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const Eina_Value_Type *subtype; + const Eina_Value_Array *s = src; + Eina_Value_Array *d = dst; + unsigned int i, count, sz; + char *ptr, *ptr_end; + + d->subtype = subtype = s->subtype; + d->step = s->step; + + if ((!s->array) || (!s->subtype)) + { + d->array = NULL; + return EINA_TRUE; + } + + if (!subtype->copy) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + d->array = eina_inarray_new(subtype->value_size, s->step); + if (!d->array) + return EINA_FALSE; + + sz = s->array->member_size; + + count = eina_inarray_count(s->array); + ptr = s->array->members; + ptr_end = ptr + (count * sz); + + for (i = 0; ptr < ptr_end; ptr += sz, i++) + { + void *imem = eina_inarray_alloc_at(d->array, i, 1); + if (!imem) goto error; + if (!subtype->copy(subtype, ptr, imem)) + { + eina_inarray_pop(d->array); + goto error; + } + } + + return EINA_TRUE; + + error: + _eina_value_type_array_flush_elements(d); + return EINA_FALSE; +} + +static int +_eina_value_type_array_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const Eina_Value_Type *subtype; + const Eina_Value_Array *eva_a = a, *eva_b = b; + const char *a_ptr, *a_ptr_end, *b_ptr; + unsigned int count_a, count_b, count, sz; + int cmp = 0; + + if (eva_a->subtype != eva_b->subtype) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return -1; + } + + subtype = eva_a->subtype; + if (!subtype->compare) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return 0; + } + + if ((!eva_a->array) && (!eva_b->array)) + return 0; + else if (!eva_a->array) + return -1; + else if (!eva_b->array) + return 1; + + count_a = eina_inarray_count(eva_a->array); + count_b = eina_inarray_count(eva_b->array); + + if (count_a <= count_b) + count = count_a; + else + count = count_b; + + sz = eva_a->array->member_size; + + a_ptr = eva_a->array->members; + a_ptr_end = a_ptr + (count * sz); + b_ptr = eva_b->array->members; + + for (; (cmp == 0) && (a_ptr < a_ptr_end); a_ptr += sz, b_ptr += sz) + cmp = subtype->compare(subtype, a_ptr, b_ptr); + + if (cmp == 0) + { + if (count_a < count_b) + return -1; + else if (count_a > count_b) + return 1; + return 0; + } + + return cmp; +} + +static Eina_Bool +_eina_value_type_array_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const Eina_Value_Array *tmem = type_mem; + Eina_Bool ret = EINA_FALSE; + + if ((convert == EINA_VALUE_TYPE_STRING) || + (convert == EINA_VALUE_TYPE_STRINGSHARE)) + { + Eina_Strbuf *str = eina_strbuf_new(); + if (!tmem->array) eina_strbuf_append(str, "[]"); + else + { + const Eina_Value_Type *subtype = tmem->subtype; + unsigned char sz; + const char *ptr, *ptr_end; + Eina_Value tmp; + Eina_Bool first = EINA_TRUE; + + eina_value_setup(&tmp, EINA_VALUE_TYPE_STRING); + + eina_strbuf_append_char(str, '['); + + sz = tmem->array->member_size; + ptr = tmem->array->members; + ptr_end = ptr + tmem->array->len * sz; + for (; ptr < ptr_end; ptr += sz) + { + Eina_Bool r = EINA_FALSE; + if (subtype->convert_to) + { + r = subtype->convert_to(subtype, EINA_VALUE_TYPE_STRING, + ptr, tmp.value.buf); + if (r) + { + if (first) first = EINA_FALSE; + else eina_strbuf_append_length(str, ", ", 2); + eina_strbuf_append(str, tmp.value.ptr); + free(tmp.value.ptr); + tmp.value.ptr = NULL; + } + } + + if (!r) + { + if (first) + { + first = EINA_FALSE; + eina_strbuf_append_char(str, '?'); + } + else + eina_strbuf_append_length(str, ", ?", 3); + } + } + + eina_strbuf_append_char(str, ']'); + ptr = eina_strbuf_string_get(str); + ret = eina_value_type_pset(convert, convert_mem, &ptr); + eina_strbuf_free(str); + } + } + else if ((tmem->array) && (tmem->array->len == 1)) + { + const Eina_Value_Type *subtype = tmem->subtype; + void *imem = tmem->array->members; + + if (subtype->convert_to) + ret = subtype->convert_to(subtype, convert, imem, convert_mem); + if ((!ret) && (convert->convert_from)) + ret = convert->convert_from(convert, subtype, convert_mem, imem); + } + + if (!ret) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + return EINA_TRUE; +} + +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) +{ + Eina_Value_Array *tmem = type_mem; + Eina_Value_Array desc = {convert, tmem->step, NULL}; + char *buf; + void *imem; + + if (!eina_value_type_pset(type, tmem, &desc)) + return EINA_FALSE; + + buf = alloca(convert->value_size); + if (!eina_value_type_pget(convert, convert_mem, &buf)) + return EINA_FALSE; + + imem = eina_inarray_alloc_at(tmem->array, 0, 1); + if (!imem) + return EINA_FALSE; + + if (!eina_value_type_setup(convert, imem)) goto error_setup; + if (!eina_value_type_pset(convert, imem, &buf)) goto error_set; + return EINA_TRUE; + + error_set: + eina_value_type_flush(convert, imem); + error_setup: + eina_inarray_remove_at(tmem->array, 0); + return EINA_FALSE; +} + +static Eina_Bool +_eina_value_type_array_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + Eina_Value_Array *tmem = mem; + const Eina_Value_Array *desc = ptr; + Eina_Inarray *desc_array; + + if ((!tmem->subtype) && (!desc->subtype)) + return EINA_TRUE; + + desc_array = desc->array; + if (desc_array) + { + EINA_SAFETY_ON_FALSE_RETURN_VAL + (desc_array->member_size == desc->subtype->value_size, EINA_FALSE); + } + + if (tmem->array) + { + _eina_value_type_array_flush_elements(tmem); + if (desc_array) + eina_inarray_free(tmem->array); + else + eina_inarray_setup(tmem->array, desc->subtype->value_size, + desc->step); + } + else if (!desc_array) + { + tmem->array = eina_inarray_new(desc->subtype->value_size, desc->step); + if (!tmem->array) + return EINA_FALSE; + } + + if (desc_array) + tmem->array = desc_array; + + tmem->subtype = desc->subtype; + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_array_vset(const Eina_Value_Type *type, void *mem, va_list args) +{ + const Eina_Value_Array desc = va_arg(args, Eina_Value_Array); + _eina_value_type_array_pset(type, mem, &desc); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_array_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + memcpy(ptr, mem, sizeof(Eina_Value_Array)); + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_ARRAY = { + EINA_VALUE_TYPE_VERSION, + sizeof(Eina_Value_Array), + "Eina_Value_Array", + _eina_value_type_array_setup, + _eina_value_type_array_flush, + _eina_value_type_array_copy, + _eina_value_type_array_compare, + _eina_value_type_array_convert_to, + _eina_value_type_array_convert_from, + _eina_value_type_array_vset, + _eina_value_type_array_pset, + _eina_value_type_array_pget +}; + +static Eina_Bool +_eina_value_type_list_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + memset(mem, 0, sizeof(Eina_Value_List)); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_list_flush_elements(Eina_Value_List *tmem) +{ + const Eina_Value_Type *subtype = tmem->subtype; + Eina_Bool ret = EINA_TRUE; + + if (!tmem->list) return EINA_TRUE; + + while (tmem->list) + { + void *mem = eina_value_list_node_memory_get(tmem->subtype, tmem->list); + ret &= eina_value_type_flush(subtype, mem); + eina_value_list_node_memory_flush(tmem->subtype, tmem->list); + tmem->list = eina_list_remove_list(tmem->list, tmem->list); + } + + return ret; +} + +static Eina_Bool +_eina_value_type_list_flush(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + Eina_Value_List *tmem = mem; + Eina_Bool ret =_eina_value_type_list_flush_elements(tmem); + + if (tmem->list) eina_list_free(tmem->list); + tmem->list = NULL; + tmem->subtype = NULL; + return ret; +} + +static Eina_Bool +_eina_value_type_list_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const Eina_Value_Type *subtype; + const Eina_Value_List *s = src; + Eina_Value_List *d = dst; + const Eina_List *snode; + + d->subtype = subtype = s->subtype; + if ((!s->list) || (!s->subtype)) + { + d->list = NULL; + return EINA_TRUE; + } + + if (!subtype->copy) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + d->list = NULL; + for (snode = s->list; snode != NULL; snode = snode->next) + { + const void *ptr = eina_value_list_node_memory_get(subtype, snode); + Eina_List *dnode; + void *imem; + + d->list = eina_list_append(d->list, (void*)1L); + dnode = eina_list_last(d->list); + EINA_SAFETY_ON_NULL_GOTO(dnode, error); + EINA_SAFETY_ON_FALSE_GOTO(dnode->data == (void*)1L, error); + + imem = eina_value_list_node_memory_setup(subtype, dnode); + if (!subtype->copy(subtype, ptr, imem)) + { + eina_value_list_node_memory_flush(subtype, dnode); + d->list = eina_list_remove_list(d->list, dnode); + goto error; + } + } + return EINA_TRUE; + + error: + _eina_value_type_list_flush_elements(d); + return EINA_FALSE; +} + +static int +_eina_value_type_list_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const Eina_Value_Type *subtype; + const Eina_Value_List *eva_a = a, *eva_b = b; + const Eina_List *anode, *bnode; + int cmp = 0; + + if (eva_a->subtype != eva_b->subtype) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return -1; + } + + subtype = eva_a->subtype; + if (!subtype->compare) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return 0; + } + + if ((!eva_a->list) && (!eva_b->list)) + return 0; + else if (!eva_a->list) + return -1; + else if (!eva_b->list) + return 1; + + for (anode = eva_a->list, bnode = eva_b->list; + (cmp == 0) && (anode) && (bnode); + anode = anode->next, bnode = bnode->next) + { + const void *amem = eina_value_list_node_memory_get(subtype, anode); + const void *bmem = eina_value_list_node_memory_get(subtype, bnode); + cmp = subtype->compare(subtype, amem, bmem); + } + + if (cmp == 0) + { + if ((!anode) && (bnode)) + return -1; + else if ((anode) && (!bnode)) + return 1; + return 0; + } + + return cmp; +} + +static Eina_Bool +_eina_value_type_list_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const Eina_Value_List *tmem = type_mem; + Eina_Bool ret = EINA_FALSE; + + if ((convert == EINA_VALUE_TYPE_STRING) || + (convert == EINA_VALUE_TYPE_STRINGSHARE)) + { + Eina_Strbuf *str = eina_strbuf_new(); + if (!tmem->list) eina_strbuf_append(str, "[]"); + else + { + const Eina_Value_Type *subtype = tmem->subtype; + const Eina_List *node; + Eina_Value tmp; + const char *s; + Eina_Bool first = EINA_TRUE; + + eina_value_setup(&tmp, EINA_VALUE_TYPE_STRING); + + eina_strbuf_append_char(str, '['); + + for (node = tmem->list; node != NULL; node = node->next) + { + Eina_Bool r = EINA_FALSE; + + if (subtype->convert_to) + { + const void *ptr; + ptr = eina_value_list_node_memory_get(subtype, node); + r = subtype->convert_to(subtype, EINA_VALUE_TYPE_STRING, + ptr, tmp.value.buf); + if (r) + { + if (first) first = EINA_FALSE; + else eina_strbuf_append_length(str, ", ", 2); + eina_strbuf_append(str, tmp.value.ptr); + free(tmp.value.ptr); + tmp.value.ptr = NULL; + } + } + + if (!r) + { + if (first) + { + first = EINA_FALSE; + eina_strbuf_append_char(str, '?'); + } + else + eina_strbuf_append_length(str, ", ?", 3); + } + } + + eina_strbuf_append_char(str, ']'); + s = eina_strbuf_string_get(str); + ret = eina_value_type_pset(convert, convert_mem, &s); + eina_strbuf_free(str); + } + } + else if ((tmem->list) && (tmem->list->next == NULL)) + { + const Eina_Value_Type *subtype = tmem->subtype; + void *imem = eina_value_list_node_memory_get(subtype, tmem->list); + + if (subtype->convert_to) + ret = subtype->convert_to(subtype, convert, imem, convert_mem); + if ((!ret) && (convert->convert_from)) + ret = convert->convert_from(convert, subtype, convert_mem, imem); + } + + if (!ret) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + return EINA_TRUE; +} + +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) +{ + Eina_Value_List *tmem = type_mem; + Eina_Value_List desc = {convert, NULL}; + Eina_List *node; + char *buf; + void *imem; + + if (!eina_value_type_pset(type, tmem, &desc)) + return EINA_FALSE; + + buf = alloca(convert->value_size); + if (!eina_value_type_pget(convert, convert_mem, &buf)) + return EINA_FALSE; + + tmem->list = eina_list_append(tmem->list, (void*)1L); + node = eina_list_last(tmem->list); + EINA_SAFETY_ON_NULL_RETURN_VAL(node, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(node->data == (void*)1L, EINA_FALSE); + + imem = eina_value_list_node_memory_setup(tmem->subtype, node); + if (!imem) + { + tmem->list = eina_list_remove_list(tmem->list, node); + return EINA_FALSE; + } + + if (!eina_value_type_setup(tmem->subtype, imem)) goto error_setup; + if (!eina_value_type_pset(tmem->subtype, imem, &buf)) goto error_set; + return EINA_TRUE; + + error_set: + eina_value_type_flush(tmem->subtype, imem); + error_setup: + eina_value_list_node_memory_flush(tmem->subtype, node); + tmem->list = eina_list_remove_list(tmem->list, node); + return EINA_FALSE; +} + +static Eina_Bool +_eina_value_type_list_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + Eina_Value_List *tmem = mem; + const Eina_Value_List *desc = ptr; + + if ((!tmem->subtype) && (!desc->subtype)) + return EINA_TRUE; + + _eina_value_type_list_flush_elements(tmem); + tmem->subtype = desc->subtype; + tmem->list = desc->list; + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_list_vset(const Eina_Value_Type *type, void *mem, va_list args) +{ + const Eina_Value_List desc = va_arg(args, Eina_Value_List); + _eina_value_type_list_pset(type, mem, &desc); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_list_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + memcpy(ptr, mem, sizeof(Eina_Value_List)); + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_LIST = { + EINA_VALUE_TYPE_VERSION, + sizeof(Eina_Value_List), + "Eina_Value_List", + _eina_value_type_list_setup, + _eina_value_type_list_flush, + _eina_value_type_list_copy, + _eina_value_type_list_compare, + _eina_value_type_list_convert_to, + _eina_value_type_list_convert_from, + _eina_value_type_list_vset, + _eina_value_type_list_pset, + _eina_value_type_list_pget +}; + +static Eina_Bool +_eina_value_type_hash_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + memset(mem, 0, sizeof(Eina_Value_Hash)); + return EINA_TRUE; +} + +struct _eina_value_type_hash_flush_each_ctx +{ + const Eina_Value_Type *subtype; + Eina_Bool ret; +}; + +static Eina_Bool +_eina_value_type_hash_flush_each(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *mem, void *user_data) +{ + struct _eina_value_type_hash_flush_each_ctx *ctx = user_data; + ctx->ret &= eina_value_type_flush(ctx->subtype, mem); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_hash_flush_elements(Eina_Value_Hash *tmem) +{ + struct _eina_value_type_hash_flush_each_ctx ctx = { + tmem->subtype, + EINA_TRUE + }; + + if (!tmem->hash) return EINA_TRUE; + + eina_hash_foreach(tmem->hash, _eina_value_type_hash_flush_each, &ctx); + eina_hash_free(tmem->hash); + tmem->hash = NULL; + return ctx.ret; +} + +static Eina_Bool +_eina_value_type_hash_flush(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + Eina_Value_Hash *tmem = mem; + Eina_Bool ret =_eina_value_type_hash_flush_elements(tmem); + tmem->subtype = NULL; + return ret; +} + +static unsigned int +_eina_value_hash_key_length(const void *key) +{ + if (!key) + return 0; + return (int)strlen(key) + 1; +} + +static int +_eina_value_hash_key_cmp(const void *key1, int key1_len, const void *key2, int key2_len) +{ + int r = key1_len - key2_len; + if (r != 0) + return r; + return strcmp(key1, key2); +} + +static Eina_Bool +_eina_value_type_hash_create(Eina_Value_Hash *desc) +{ + if (!desc->buckets_power_size) + desc->buckets_power_size = 5; + + desc->hash = eina_hash_new(_eina_value_hash_key_length, + _eina_value_hash_key_cmp, + EINA_KEY_HASH(eina_hash_superfast), + NULL, desc->buckets_power_size); + return !!desc->hash; +} + +struct _eina_value_type_hash_copy_each_ctx +{ + const Eina_Value_Type *subtype; + Eina_Value_Hash *dest; + Eina_Bool ret; +}; + +static Eina_Bool +_eina_value_type_hash_copy_each(const Eina_Hash *hash __UNUSED__, const void *key, void *_ptr, void *user_data) +{ + struct _eina_value_type_hash_copy_each_ctx *ctx = user_data; + const void *ptr = _ptr; + void *imem = malloc(ctx->subtype->value_size); + if (!imem) + { + ctx->ret = EINA_FALSE; + return EINA_FALSE; + } + if (!ctx->subtype->copy(ctx->subtype, ptr, imem)) + { + free(imem); + ctx->ret = EINA_FALSE; + return EINA_FALSE; + } + if (!eina_hash_add(ctx->dest->hash, key, imem)) + { + eina_value_type_flush(ctx->subtype, imem); + free(imem); + ctx->ret = EINA_FALSE; + return EINA_FALSE; + } + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_hash_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const Eina_Value_Hash *s = src; + Eina_Value_Hash *d = dst; + struct _eina_value_type_hash_copy_each_ctx ctx = {s->subtype, d, EINA_TRUE}; + + d->subtype = s->subtype; + d->buckets_power_size = s->buckets_power_size; + + if ((!s->hash) || (!s->subtype)) + { + d->hash = NULL; + return EINA_TRUE; + } + + if (!s->subtype->copy) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + if (!_eina_value_type_hash_create(d)) + return EINA_FALSE; + + eina_hash_foreach(s->hash, _eina_value_type_hash_copy_each, &ctx); + if (!ctx.ret) + { + _eina_value_type_hash_flush_elements(d); + return EINA_FALSE; + } + return EINA_TRUE; +} + +struct _eina_value_type_hash_compare_each_ctx +{ + const Eina_Value_Type *subtype; + const Eina_Hash *other; + int cmp; +}; + +static Eina_Bool +_eina_value_type_hash_compare_each(const Eina_Hash *hash __UNUSED__, const void *key, void *_ptr, void *user_data) +{ + struct _eina_value_type_hash_compare_each_ctx *ctx = user_data; + const void *self_ptr = _ptr; + const void *other_ptr = eina_hash_find(ctx->other, key); + if (!other_ptr) return EINA_TRUE; + ctx->cmp = ctx->subtype->compare(ctx->subtype, self_ptr, other_ptr); + return ctx->cmp == 0; +} + +static int +_eina_value_type_hash_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const Eina_Value_Hash *eva_a = a, *eva_b = b; + struct _eina_value_type_hash_compare_each_ctx ctx = { + eva_a->subtype, eva_b->hash, 0 + }; + + if (eva_a->subtype != eva_b->subtype) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return -1; + } + + if (!eva_a->subtype->compare) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return 0; + } + + if ((!eva_a->hash) && (!eva_b->hash)) + return 0; + else if (!eva_a->hash) + return -1; + else if (!eva_b->hash) + return 1; + + eina_hash_foreach(eva_a->hash, _eina_value_type_hash_compare_each, &ctx); + if (ctx.cmp == 0) + { + unsigned int count_a = eina_hash_population(eva_a->hash); + unsigned int count_b = eina_hash_population(eva_b->hash); + if (count_a < count_b) + return -1; + else if (count_a > count_b) + return 1; + return 0; + } + + return ctx.cmp; +} + +static Eina_Bool +_eina_value_type_hash_find_first(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *ptr, void *user_data) +{ + void **ret = user_data; + *ret = ptr; + return EINA_FALSE; +} + +struct _eina_value_type_hash_convert_to_string_each_ctx +{ + const Eina_Value_Type *subtype; + Eina_Strbuf *str; + Eina_Value tmp; + Eina_Bool first; +}; + +static Eina_Bool +_eina_value_type_hash_convert_to_string_each(const Eina_Hash *hash __UNUSED__, const void *_key, void *_ptr, void *user_data) +{ + struct _eina_value_type_hash_convert_to_string_each_ctx *ctx = user_data; + const char *key = _key; + const void *ptr = _ptr; + Eina_Bool r = EINA_FALSE; + + if (ctx->first) ctx->first = EINA_FALSE; + else eina_strbuf_append_length(ctx->str, ", ", 2); + + eina_strbuf_append(ctx->str, key); + eina_strbuf_append_length(ctx->str, ": ", 2); + + if (ctx->subtype->convert_to) + { + r = ctx->subtype->convert_to(ctx->subtype, EINA_VALUE_TYPE_STRING, + ptr, ctx->tmp.value.buf); + if (r) + { + eina_strbuf_append(ctx->str, ctx->tmp.value.ptr); + free(ctx->tmp.value.ptr); + ctx->tmp.value.ptr = NULL; + } + } + + if (!r) + eina_strbuf_append_char(ctx->str, '?'); + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_hash_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const Eina_Value_Hash *tmem = type_mem; + Eina_Bool ret = EINA_FALSE; + + if ((convert == EINA_VALUE_TYPE_STRING) || + (convert == EINA_VALUE_TYPE_STRINGSHARE)) + { + Eina_Strbuf *str = eina_strbuf_new(); + if (!tmem->hash) eina_strbuf_append(str, "{}"); + else + { + struct _eina_value_type_hash_convert_to_string_each_ctx ctx; + const char *s; + + ctx.subtype = tmem->subtype; + ctx.str = str; + ctx.first = EINA_TRUE; + eina_value_setup(&ctx.tmp, EINA_VALUE_TYPE_STRING); + + eina_strbuf_append_char(str, '{'); + + eina_hash_foreach(tmem->hash, + _eina_value_type_hash_convert_to_string_each, + &ctx); + + eina_strbuf_append_char(str, '}'); + s = eina_strbuf_string_get(str); + ret = eina_value_type_pset(convert, convert_mem, &s); + eina_strbuf_free(str); + } + } + else if ((tmem->hash) && (eina_hash_population(tmem->hash) == 1)) + { + const Eina_Value_Type *subtype = tmem->subtype; + void *imem = NULL; + + eina_hash_foreach(tmem->hash, _eina_value_type_hash_find_first, &imem); + if (!imem) /* shouldn't happen... */ + ret = EINA_FALSE; + else + { + if (subtype->convert_to) + ret = subtype->convert_to(subtype, convert, imem, convert_mem); + if ((!ret) && (convert->convert_from)) + ret = convert->convert_from(convert, subtype, convert_mem, imem); + } + } + + if (!ret) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_hash_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + Eina_Value_Hash *tmem = mem; + const Eina_Value_Hash *desc = ptr; + + if ((!tmem->subtype) && (!desc->subtype)) + return EINA_TRUE; + + if (tmem->hash) _eina_value_type_hash_flush_elements(tmem); + + if (desc->hash) + tmem->hash = desc->hash; + else if (!_eina_value_type_hash_create(tmem)) + return EINA_FALSE; + + tmem->subtype = desc->subtype; + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_hash_vset(const Eina_Value_Type *type, void *mem, va_list args) +{ + const Eina_Value_Hash desc = va_arg(args, Eina_Value_Hash); + _eina_value_type_hash_pset(type, mem, &desc); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_hash_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + memcpy(ptr, mem, sizeof(Eina_Value_Hash)); + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_HASH = { + EINA_VALUE_TYPE_VERSION, + sizeof(Eina_Value_Hash), + "Eina_Value_Hash", + _eina_value_type_hash_setup, + _eina_value_type_hash_flush, + _eina_value_type_hash_copy, + _eina_value_type_hash_compare, + _eina_value_type_hash_convert_to, + NULL, /* no convert from */ + _eina_value_type_hash_vset, + _eina_value_type_hash_pset, + _eina_value_type_hash_pget +}; + +static Eina_Bool +_eina_value_type_timeval_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + memset(mem, 0, sizeof(struct timeval)); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_timeval_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_timeval_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const struct timeval *s = src; + struct timeval *d = dst; + *d = *s; + return EINA_TRUE; +} + +static inline struct timeval _eina_value_type_timeval_fix(const struct timeval *input) +{ + struct timeval ret = *input; + if (EINA_UNLIKELY(ret.tv_usec < 0)) + { + ret.tv_sec -= 1; + ret.tv_usec += 1e6; + } + return ret; +} + +static int +_eina_value_type_timeval_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + struct timeval va = _eina_value_type_timeval_fix(a); + struct timeval vb = _eina_value_type_timeval_fix(b); + + if (va.tv_sec < vb.tv_sec) + return -1; + else if (va.tv_sec > vb.tv_sec) + return 1; + + if (va.tv_usec < vb.tv_usec) + return -1; + else if (va.tv_usec > vb.tv_usec) + return 1; + + return 0; +} + +static Eina_Bool +_eina_value_type_timeval_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + struct timeval v = _eina_value_type_timeval_fix(type_mem); + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v.tv_sec; + if (EINA_UNLIKELY(v.tv_sec < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v.tv_sec > eina_value_uchar_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_USHORT) + { + unsigned short other_mem = v.tv_sec; + if (EINA_UNLIKELY(v.tv_sec < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v.tv_sec > eina_value_ushort_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT) + { + unsigned int other_mem = v.tv_sec; + if (EINA_UNLIKELY(v.tv_sec < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY((unsigned long) v.tv_sec > eina_value_uint_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem = v.tv_sec; + if (EINA_UNLIKELY(v.tv_sec < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) && + ((unsigned long)v.tv_sec > eina_value_ulong_max))) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem = v.tv_sec; + if (EINA_UNLIKELY(v.tv_sec < 0)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v.tv_sec; + if (EINA_UNLIKELY(v.tv_sec < eina_value_char_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v.tv_sec > eina_value_char_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_SHORT) + { + short other_mem = v.tv_sec; + if (EINA_UNLIKELY(v.tv_sec < eina_value_short_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v.tv_sec > eina_value_short_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem = v.tv_sec; + if (EINA_UNLIKELY(v.tv_sec < eina_value_int_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v.tv_sec > eina_value_int_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v.tv_sec; + if (EINA_UNLIKELY(v.tv_sec < eina_value_long_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v.tv_sec > eina_value_long_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v.tv_sec; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = (float)v.tv_sec + (float)v.tv_usec / 1.0e6; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = (double)v.tv_sec + (double)v.tv_usec / 1.0e6; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + const char *other_mem; + char buf[64]; + snprintf(buf, sizeof(buf), "%ld.%06ld", v.tv_sec, v.tv_usec); + other_mem = buf; /* required due &buf == buf */ + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } +} + +static Eina_Bool +_eina_value_type_timeval_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + struct timeval *tmem = mem; + *tmem = _eina_value_type_timeval_fix(ptr); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_timeval_vset(const Eina_Value_Type *type, void *mem, va_list args) +{ + const struct timeval desc = va_arg(args, struct timeval); + _eina_value_type_timeval_pset(type, mem, &desc); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_timeval_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + memcpy(ptr, mem, sizeof(struct timeval)); + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_TIMEVAL = { + EINA_VALUE_TYPE_VERSION, + sizeof(struct timeval), + "struct timeval", + _eina_value_type_timeval_setup, + _eina_value_type_timeval_flush, + _eina_value_type_timeval_copy, + _eina_value_type_timeval_compare, + _eina_value_type_timeval_convert_to, + NULL, /* no convert from */ + _eina_value_type_timeval_vset, + _eina_value_type_timeval_pset, + _eina_value_type_timeval_pget +}; + +static Eina_Bool +_eina_value_type_blob_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + memset(mem, 0, sizeof(Eina_Value_Blob)); + return EINA_TRUE; +} + +static inline const Eina_Value_Blob_Operations * +_eina_value_type_blob_ops_get(const Eina_Value_Blob *blob) +{ + if (!blob) return NULL; + if (!blob->ops) return NULL; + EINA_SAFETY_ON_FALSE_RETURN_VAL + (blob->ops->version == EINA_VALUE_BLOB_OPERATIONS_VERSION, NULL); + return blob->ops; +} + +static Eina_Bool +_eina_value_type_blob_flush(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + const Eina_Value_Blob_Operations *ops = _eina_value_type_blob_ops_get(mem); + Eina_Value_Blob *tmem = mem; + if ((ops) && (ops->free)) + ops->free(ops, (void *)tmem->memory, tmem->size); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_blob_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const Eina_Value_Blob_Operations *ops = _eina_value_type_blob_ops_get(src); + const Eina_Value_Blob *s = src; + Eina_Value_Blob *d = dst; + + *d = *s; + + if ((ops) && (ops->copy)) + { + d->memory = ops->copy(ops, s->memory, s->size); + if ((d->memory == NULL) && (s->size > 0)) + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static int +_eina_value_type_blob_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const Eina_Value_Blob_Operations *ops = _eina_value_type_blob_ops_get(a); + const Eina_Value_Blob *ta = a, *tb = b; + size_t minsize; + if (ta->ops != tb->ops) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return -1; + } + if ((ops) && (ops->compare)) + return ops->compare(ops, ta->memory, ta->size, tb->memory, tb->size); + + if (ta->size < tb->size) + minsize = ta->size; + else + minsize = tb->size; + + return memcmp(ta->memory, tb->memory, minsize); +} + +static Eina_Bool +_eina_value_type_blob_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const Eina_Value_Blob *tmem = type_mem; + + eina_error_set(0); + if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + const Eina_Value_Blob_Operations *ops; + Eina_Strbuf *str; + const char *other_mem; + Eina_Bool ret = EINA_FALSE, first = EINA_TRUE; + const unsigned char *ptr, *ptr_end; + + ops = _eina_value_type_blob_ops_get(tmem); + if ((ops) && (ops->to_string)) + { + char *x = ops->to_string(ops, tmem->memory, tmem->size); + if (x) + { + ret = eina_value_type_pset(convert, convert_mem, &x); + free(x); + } + return ret; + } + + str = eina_strbuf_new(); + if (!str) + return EINA_FALSE; + + if (!eina_strbuf_append_printf(str, "BLOB(%u, [", tmem->size)) + goto error; + + ptr = tmem->memory; + ptr_end = ptr + tmem->size; + for (; ptr < ptr_end; ptr++) + { + if (first) + { + first = EINA_FALSE; + if (!eina_strbuf_append_printf(str, "%02hhx", *ptr)) + goto error; + } + else + { + if (!eina_strbuf_append_printf(str, " %02hhx", *ptr)) + goto error; + } + } + + if (!eina_strbuf_append(str, "])")) + goto error; + + other_mem = eina_strbuf_string_get(str); + ret = eina_value_type_pset(convert, convert_mem, &other_mem); + + error: + eina_strbuf_free(str); + return ret; + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } +} + +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) +{ + Eina_Value_Blob desc; + char *buf; + + desc.ops = EINA_VALUE_BLOB_OPERATIONS_MALLOC; + + if ((convert == EINA_VALUE_TYPE_STRING) || + (convert == EINA_VALUE_TYPE_STRINGSHARE)) + { + const char *str = *(const char **)convert_mem; + if (!str) + { + desc.size = 0; + desc.memory = NULL; + } + else + { + desc.size = strlen(str) + 1; + desc.memory = buf = malloc(desc.size); + if (!desc.memory) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + memcpy(buf, str, desc.size); + } + } + else if (convert == EINA_VALUE_TYPE_ARRAY) + { + const Eina_Value_Array *a = convert_mem; + if ((!a->array) || (a->array->len == 0)) + { + desc.size = 0; + desc.memory = NULL; + } + else + { + desc.size = a->array->len * a->array->member_size; + desc.memory = buf = malloc(desc.size); + if (!desc.memory) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + memcpy(buf, a->array->members, desc.size); + } + } + else if (convert == EINA_VALUE_TYPE_BLOB) + { + const Eina_Value_Blob *b = convert_mem; + if (b->size == 0) + { + desc.size = 0; + desc.memory = NULL; + } + else + { + desc.size = b->size; + desc.memory = buf = malloc(desc.size); + if (!desc.memory) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + memcpy(buf, b->memory, desc.size); + } + } + else + { + desc.size = convert->value_size; + desc.memory = buf = malloc(convert->value_size); + if (!desc.memory) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + if (!eina_value_type_pget(convert, convert_mem, buf)) + { + free(buf); + return EINA_FALSE; + } + } + return eina_value_type_pset(type, type_mem, &desc); +} + +static Eina_Bool +_eina_value_type_blob_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + const Eina_Value_Blob_Operations *ops = _eina_value_type_blob_ops_get(mem); + Eina_Value_Blob *tmem = mem; + const Eina_Value_Blob *desc = ptr; + + if ((ops) && (ops->free)) + ops->free(ops, (void *)tmem->memory, tmem->size); + + *tmem = *desc; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_blob_vset(const Eina_Value_Type *type, void *mem, va_list args) +{ + const Eina_Value_Blob desc = va_arg(args, Eina_Value_Blob); + _eina_value_type_blob_pset(type, mem, &desc); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_blob_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + memcpy(ptr, mem, sizeof(Eina_Value_Blob)); + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_BLOB = { + EINA_VALUE_TYPE_VERSION, + sizeof(Eina_Value_Blob), + "Eina_Value_Blob", + _eina_value_type_blob_setup, + _eina_value_type_blob_flush, + _eina_value_type_blob_copy, + _eina_value_type_blob_compare, + _eina_value_type_blob_convert_to, + _eina_value_type_blob_convert_from, + _eina_value_type_blob_vset, + _eina_value_type_blob_pset, + _eina_value_type_blob_pget +}; + +static int +_eina_value_struct_operations_binsearch_cmp(const void *pa, const void *pb) +{ + const Eina_Value_Struct_Member *a = pa, *b = pb; + return strcmp(a->name, b->name); +} + +static const Eina_Value_Struct_Member * +_eina_value_struct_operations_binsearch_find_member(const Eina_Value_Struct_Operations *ops __UNUSED__, const Eina_Value_Struct_Desc *desc, const char *name) +{ + unsigned int count = desc->member_count; + Eina_Value_Struct_Member search; + if (count == 0) + { + const Eina_Value_Struct_Member *itr = desc->members; + for (; itr->name != NULL; itr++) + count++; + } + + search.name = name; + return bsearch(&search, desc->members, count, + sizeof(Eina_Value_Struct_Member), + _eina_value_struct_operations_binsearch_cmp); +} + +static Eina_Value_Struct_Operations _EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH = { + EINA_VALUE_STRUCT_OPERATIONS_VERSION, + NULL, /* default alloc */ + NULL, /* default free */ + NULL, /* default copy */ + NULL, /* default compare */ + _eina_value_struct_operations_binsearch_find_member +}; + +static const Eina_Value_Struct_Member * +_eina_value_struct_operations_stringshare_find_member(const Eina_Value_Struct_Operations *ops __UNUSED__, const Eina_Value_Struct_Desc *desc, const char *name) +{ + const Eina_Value_Struct_Member *itr = desc->members; + + /* assumes name is stringshared. + * + * we do this because it's the recommended usage pattern, moreover + * we expect to find the member, as users shouldn't look for + * non-existent members! + */ + if (desc->member_count > 0) + { + const Eina_Value_Struct_Member *itr_end = itr + desc->member_count; + for (; itr < itr_end; itr++) + if (itr->name == name) + return itr; + } + else + { + for (; itr->name != NULL; itr++) + if (itr->name == name) + return itr; + } + + name = eina_stringshare_add(name); + eina_stringshare_del(name); /* we'll not use the contents, this is fine */ + /* stringshare and look again */ + if (desc->member_count > 0) + { + const Eina_Value_Struct_Member *itr_end = itr + desc->member_count; + for (; itr < itr_end; itr++) + if (itr->name == name) + return itr; + } + else + { + for (; itr->name != NULL; itr++) + if (itr->name == name) + return itr; + } + + return NULL; +} + +static Eina_Value_Struct_Operations _EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE = { + EINA_VALUE_STRUCT_OPERATIONS_VERSION, + NULL, /* default alloc */ + NULL, /* default free */ + NULL, /* default copy */ + NULL, /* default compare */ + _eina_value_struct_operations_stringshare_find_member +}; + +static inline const Eina_Value_Struct_Operations * +_eina_value_type_struct_ops_get(const Eina_Value_Struct *st) +{ + if (!st) return NULL; + if (!st->desc) return NULL; + if (!st->desc->ops) return NULL; + EINA_SAFETY_ON_FALSE_RETURN_VAL + (st->desc->ops->version == EINA_VALUE_STRUCT_OPERATIONS_VERSION, NULL); + return st->desc->ops; +} + +EAPI const Eina_Value_Struct_Member * +eina_value_struct_member_find(const Eina_Value_Struct *st, const char *name) +{ + const Eina_Value_Struct_Operations *ops; + const Eina_Value_Struct_Member *itr; + + EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(st->desc, NULL); + + ops = _eina_value_type_struct_ops_get(st); + if ((ops) && (ops->find_member)) + return ops->find_member(ops, st->desc, name); + + itr = st->desc->members; + if (st->desc->member_count) + { + const Eina_Value_Struct_Member *itr_end = itr + st->desc->member_count; + for (; itr < itr_end; itr++) + { + if (strcmp(name, itr->name) == 0) + return itr; + } + return NULL; + } + else + { + for (; itr->name != NULL; itr++) + { + if (strcmp(name, itr->name) == 0) + return itr; + } + return NULL; + } +} + +static Eina_Bool +_eina_value_type_struct_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + memset(mem, 0, sizeof(Eina_Value_Struct)); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_struct_flush_member(const Eina_Value_Struct_Member *member, Eina_Value_Struct *st) +{ + unsigned char *base = st->memory; + return eina_value_type_flush(member->type, base + member->offset); +} + +static Eina_Bool +_eina_value_type_struct_flush(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + const Eina_Value_Struct_Operations *ops; + const Eina_Value_Struct_Member *itr; + Eina_Value_Struct *tmem = mem; + Eina_Bool ret = EINA_TRUE; + + itr = tmem->desc->members; + if (tmem->desc->member_count > 0) + { + const Eina_Value_Struct_Member *itr_end; + itr_end = itr + tmem->desc->member_count; + for (; itr < itr_end; itr++) + ret &= _eina_value_type_struct_flush_member(itr, tmem); + } + else + { + for (; itr->name != NULL; itr++) + ret &= _eina_value_type_struct_flush_member(itr, tmem); + } + + ops = _eina_value_type_struct_ops_get(mem); + if ((ops) && (ops->free)) + ops->free(ops, tmem->desc, tmem->memory); + else + free(tmem->memory); + + return ret; +} + +static Eina_Bool +_eina_value_type_struct_copy_member(const Eina_Value_Struct_Member *member, const Eina_Value_Struct *s, Eina_Value_Struct *d) +{ + const unsigned char *base_s = s->memory; + unsigned char *base_d = d->memory; + return eina_value_type_copy(member->type, + base_s + member->offset, + base_d + member->offset); +} + +static Eina_Bool +_eina_value_type_struct_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const Eina_Value_Struct_Operations *ops; + const Eina_Value_Struct_Member *itr; + const Eina_Value_Struct *s = src; + Eina_Value_Struct *d = dst; + + *d = *s; + + ops = _eina_value_type_struct_ops_get(src); + if ((ops) && (ops->copy)) + { + d->memory = ops->copy(ops, s->desc, s->memory); + if (d->memory == NULL) + return EINA_FALSE; + return EINA_TRUE; + } + + d->memory = malloc(s->desc->size); + if (!d->memory) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + + itr = s->desc->members; + if (s->desc->member_count > 0) + { + const Eina_Value_Struct_Member *itr_end = itr + s->desc->member_count; + for (; itr < itr_end; itr++) + if (!_eina_value_type_struct_copy_member(itr, s, d)) + goto error; + } + else + { + for (; itr->name != NULL; itr++) + if (!_eina_value_type_struct_copy_member(itr, s, d)) + goto error; + } + + + return EINA_TRUE; + + error: + itr--; + for (; itr >= s->desc->members; itr--) + _eina_value_type_struct_flush_member(itr, d); + free(d->memory); + return EINA_FALSE; +} + +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) +{ + const unsigned char *base_a = ta->memory; + const unsigned char *base_b = tb->memory; + return eina_value_type_compare(member->type, + base_a + member->offset, + base_b + member->offset); +} + +static int +_eina_value_type_struct_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const Eina_Value_Struct_Operations *ops = _eina_value_type_struct_ops_get(a); + const Eina_Value_Struct *ta = a, *tb = b; + const Eina_Value_Struct_Member *itr; + int cmp = 0; + + if (ta->desc != tb->desc) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return -1; + } + if (ta->desc->ops != tb->desc->ops) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return -1; + } + if ((!ta->memory) && (!tb->memory)) + return 0; + else if (!ta->memory) + return -1; + else if (!tb->memory) + return 1; + + if ((ops) && (ops->compare)) + return ops->compare(ops, ta->desc, ta->memory, tb->memory); + + itr = ta->desc->members; + if (ta->desc->member_count > 0) + { + const Eina_Value_Struct_Member *itr_end = itr + ta->desc->member_count; + for (; (cmp == 0) && (itr < itr_end); itr++) + cmp = _eina_value_type_struct_compare_member(itr, ta, tb); + } + else + { + for (; (cmp == 0) && (itr->name != NULL); itr++) + cmp = _eina_value_type_struct_compare_member(itr, ta, tb); + } + return cmp; +} + +static void +_eina_value_type_struct_convert_to_string_member(const Eina_Value_Struct *st, const Eina_Value_Struct_Member *member, Eina_Strbuf *str) +{ + const unsigned char *p = st->memory; + Eina_Bool first = st->desc->members == member; + Eina_Bool r = EINA_FALSE; + + if (first) eina_strbuf_append_printf(str, "%s: ", member->name); + else eina_strbuf_append_printf(str, ", %s: ", member->name); + + if ((member->type) && (member->type->convert_to)) + { + const Eina_Value_Type *type = member->type; + char *conv = NULL; + + r = eina_value_type_convert_to(type, EINA_VALUE_TYPE_STRING, + p + member->offset, &conv); + if (r) + { + eina_strbuf_append(str, conv); + free(conv); + } + } + + if (!r) + eina_strbuf_append_char(str, '?'); +} + +static Eina_Bool +_eina_value_type_struct_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const Eina_Value_Struct *tmem = type_mem; + + eina_error_set(0); + if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + Eina_Strbuf *str = eina_strbuf_new(); + const char *s; + Eina_Bool ret; + + if (!tmem->memory) eina_strbuf_append(str, "{}"); + else + { + const Eina_Value_Struct_Member *itr = tmem->desc->members; + + eina_strbuf_append_char(str, '{'); + + if (tmem->desc->member_count > 0) + { + const Eina_Value_Struct_Member *itr_end; + + itr_end = itr + tmem->desc->member_count; + for (; itr < itr_end; itr++) + _eina_value_type_struct_convert_to_string_member + (tmem, itr, str); + } + else + { + for (; itr->name != NULL; itr++) + _eina_value_type_struct_convert_to_string_member + (tmem, itr, str); + } + + eina_strbuf_append_char(str, '}'); + } + s = eina_strbuf_string_get(str); + ret = eina_value_type_pset(convert, convert_mem, &s); + eina_strbuf_free(str); + return ret; + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } +} + +static Eina_Bool +_eina_value_type_struct_desc_check(const Eina_Value_Struct_Desc *desc) +{ + unsigned int minsize = 0; + const Eina_Value_Struct_Member *itr; + + EINA_SAFETY_ON_NULL_RETURN_VAL(desc, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL + (desc->version == EINA_VALUE_STRUCT_DESC_VERSION, EINA_FALSE); + + itr = desc->members; + if (desc->member_count > 0) + { + const Eina_Value_Struct_Member *itr_end = itr + desc->member_count; + for (; itr < itr_end; itr++) + { + unsigned int member_end; + + EINA_SAFETY_ON_FALSE_RETURN_VAL + (eina_value_type_check(itr->type), EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL + (itr->type->value_size > 0, EINA_FALSE); + + member_end = itr->offset + itr->type->value_size; + if (minsize < member_end) + minsize = member_end; + } + } + else + { + for (; itr->name != NULL; itr++) + { + unsigned int member_end; + + EINA_SAFETY_ON_FALSE_RETURN_VAL + (eina_value_type_check(itr->type), EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL + (itr->type->value_size > 0, EINA_FALSE); + + member_end = itr->offset + itr->type->value_size; + if (minsize < member_end) + minsize = member_end; + } + } + + EINA_SAFETY_ON_FALSE_RETURN_VAL(minsize > 0, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(desc->size >= minsize, EINA_FALSE); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_struct_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + const Eina_Value_Struct_Operations *ops = _eina_value_type_struct_ops_get(mem); + Eina_Value_Struct *tmem = mem; + const Eina_Value_Struct *desc = ptr; + + if (!_eina_value_type_struct_desc_check(desc->desc)) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + if ((ops) && (ops->free)) + ops->free(ops, tmem->desc, tmem->memory); + else + free(tmem->memory); + + *tmem = *desc; + + ops = _eina_value_type_struct_ops_get(desc); + if (!tmem->memory) + { + if ((ops) && (ops->alloc)) + tmem->memory = ops->alloc(ops, tmem->desc); + else + tmem->memory = malloc(tmem->desc->size); + + if (!tmem->memory) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + } + + eina_error_set(0); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_struct_vset(const Eina_Value_Type *type, void *mem, va_list args) +{ + const Eina_Value_Struct desc = va_arg(args, Eina_Value_Struct); + _eina_value_type_struct_pset(type, mem, &desc); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_struct_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + memcpy(ptr, mem, sizeof(Eina_Value_Struct)); + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_STRUCT = { + EINA_VALUE_TYPE_VERSION, + sizeof(Eina_Value_Struct), + "Eina_Value_Struct", + _eina_value_type_struct_setup, + _eina_value_type_struct_flush, + _eina_value_type_struct_copy, + _eina_value_type_struct_compare, + _eina_value_type_struct_convert_to, + NULL, /* no convert from */ + _eina_value_type_struct_vset, + _eina_value_type_struct_pset, + _eina_value_type_struct_pget +}; + +/* keep all basic types inlined in an array so we can compare if it's + * a basic type using pointer arithmetic. + * + * NOTE-1: JUST BASIC TYPES, DO NOT ADD MORE TYPES HERE!!! + * NOTE-2: KEEP ORDER, see eina_value_init() + */ +static const Eina_Value_Type _EINA_VALUE_TYPE_BASICS[] = { + { + EINA_VALUE_TYPE_VERSION, + sizeof(unsigned char), + "unsigned char", + _eina_value_type_uchar_setup, + _eina_value_type_uchar_flush, + _eina_value_type_uchar_copy, + _eina_value_type_uchar_compare, + _eina_value_type_uchar_convert_to, + NULL, /* no convert from */ + _eina_value_type_uchar_vset, + _eina_value_type_uchar_pset, + _eina_value_type_uchar_pget + }, + { + EINA_VALUE_TYPE_VERSION, + sizeof(unsigned short), + "unsigned short", + _eina_value_type_ushort_setup, + _eina_value_type_ushort_flush, + _eina_value_type_ushort_copy, + _eina_value_type_ushort_compare, + _eina_value_type_ushort_convert_to, + NULL, /* no convert from */ + _eina_value_type_ushort_vset, + _eina_value_type_ushort_pset, + _eina_value_type_ushort_pget + }, + { + EINA_VALUE_TYPE_VERSION, + sizeof(unsigned int), + "unsigned int", + _eina_value_type_uint_setup, + _eina_value_type_uint_flush, + _eina_value_type_uint_copy, + _eina_value_type_uint_compare, + _eina_value_type_uint_convert_to, + NULL, /* no convert from */ + _eina_value_type_uint_vset, + _eina_value_type_uint_pset, + _eina_value_type_uint_pget + }, + { + EINA_VALUE_TYPE_VERSION, + sizeof(unsigned long), + "unsigned long", + _eina_value_type_ulong_setup, + _eina_value_type_ulong_flush, + _eina_value_type_ulong_copy, + _eina_value_type_ulong_compare, + _eina_value_type_ulong_convert_to, + NULL, /* no convert from */ + _eina_value_type_ulong_vset, + _eina_value_type_ulong_pset, + _eina_value_type_ulong_pget + }, + { + EINA_VALUE_TYPE_VERSION, + sizeof(uint64_t), + "uint64_t", + _eina_value_type_uint64_setup, + _eina_value_type_uint64_flush, + _eina_value_type_uint64_copy, + _eina_value_type_uint64_compare, + _eina_value_type_uint64_convert_to, + NULL, /* no convert from */ + _eina_value_type_uint64_vset, + _eina_value_type_uint64_pset, + _eina_value_type_uint64_pget + }, + { + EINA_VALUE_TYPE_VERSION, + sizeof(char), + "char", + _eina_value_type_char_setup, + _eina_value_type_char_flush, + _eina_value_type_char_copy, + _eina_value_type_char_compare, + _eina_value_type_char_convert_to, + NULL, /* no convert from */ + _eina_value_type_char_vset, + _eina_value_type_char_pset, + _eina_value_type_char_pget + }, + { + EINA_VALUE_TYPE_VERSION, + sizeof(short), + "short", + _eina_value_type_short_setup, + _eina_value_type_short_flush, + _eina_value_type_short_copy, + _eina_value_type_short_compare, + _eina_value_type_short_convert_to, + NULL, /* no convert from */ + _eina_value_type_short_vset, + _eina_value_type_short_pset, + _eina_value_type_short_pget + }, + { + EINA_VALUE_TYPE_VERSION, + sizeof(int), + "int", + _eina_value_type_int_setup, + _eina_value_type_int_flush, + _eina_value_type_int_copy, + _eina_value_type_int_compare, + _eina_value_type_int_convert_to, + NULL, /* no convert from */ + _eina_value_type_int_vset, + _eina_value_type_int_pset, + _eina_value_type_int_pget + }, + { + EINA_VALUE_TYPE_VERSION, + sizeof(long), + "long", + _eina_value_type_long_setup, + _eina_value_type_long_flush, + _eina_value_type_long_copy, + _eina_value_type_long_compare, + _eina_value_type_long_convert_to, + NULL, /* no convert from */ + _eina_value_type_long_vset, + _eina_value_type_long_pset, + _eina_value_type_long_pget + }, + { + EINA_VALUE_TYPE_VERSION, + sizeof(int64_t), + "int64_t", + _eina_value_type_int64_setup, + _eina_value_type_int64_flush, + _eina_value_type_int64_copy, + _eina_value_type_int64_compare, + _eina_value_type_int64_convert_to, + NULL, /* no convert from */ + _eina_value_type_int64_vset, + _eina_value_type_int64_pset, + _eina_value_type_int64_pget + }, + { + EINA_VALUE_TYPE_VERSION, + sizeof(float), + "float", + _eina_value_type_float_setup, + _eina_value_type_float_flush, + _eina_value_type_float_copy, + _eina_value_type_float_compare, + _eina_value_type_float_convert_to, + NULL, /* no convert from */ + _eina_value_type_float_vset, + _eina_value_type_float_pset, + _eina_value_type_float_pget + }, + { + EINA_VALUE_TYPE_VERSION, + sizeof(double), + "double", + _eina_value_type_double_setup, + _eina_value_type_double_flush, + _eina_value_type_double_copy, + _eina_value_type_double_compare, + _eina_value_type_double_convert_to, + NULL, /* no convert from */ + _eina_value_type_double_vset, + _eina_value_type_double_pset, + _eina_value_type_double_pget + }, + { + EINA_VALUE_TYPE_VERSION, + sizeof(const char *), + "stringshare", + _eina_value_type_string_common_setup, + _eina_value_type_stringshare_flush, + _eina_value_type_stringshare_copy, + _eina_value_type_string_common_compare, + _eina_value_type_string_common_convert_to, + NULL, /* no convert from */ + _eina_value_type_stringshare_vset, + _eina_value_type_stringshare_pset, + _eina_value_type_string_common_pget + }, + { + EINA_VALUE_TYPE_VERSION, + sizeof(char *), + "string", + _eina_value_type_string_common_setup, + _eina_value_type_string_flush, + _eina_value_type_string_copy, + _eina_value_type_string_common_compare, + _eina_value_type_string_common_convert_to, + NULL, /* no convert from */ + _eina_value_type_string_vset, + _eina_value_type_string_pset, + _eina_value_type_string_common_pget + } +}; + +static void +_eina_value_blob_operations_malloc_free(const Eina_Value_Blob_Operations *ops __UNUSED__, void *memory, size_t size __UNUSED__) +{ + free(memory); +} + +static void * +_eina_value_blob_operations_malloc_copy(const Eina_Value_Blob_Operations *ops __UNUSED__, const void *memory, size_t size) +{ + void *ret = malloc(size); + if (!ret) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + memcpy(ret, memory, size); + return ret; +} + +static const Eina_Value_Blob_Operations _EINA_VALUE_BLOB_OPERATIONS_MALLOC = { + EINA_VALUE_BLOB_OPERATIONS_VERSION, + _eina_value_blob_operations_malloc_free, + _eina_value_blob_operations_malloc_copy, + NULL, + NULL +}; + +typedef struct _Eina_Value_Inner_Mp Eina_Value_Inner_Mp; +struct _Eina_Value_Inner_Mp +{ + Eina_Mempool *mempool; + int references; +}; + +/** + * @endcond + */ + +static const char EINA_ERROR_VALUE_FAILED_STR[] = "Value check failed."; + +/** + */ + +static inline void +_eina_value_inner_mp_dispose(int size, Eina_Value_Inner_Mp *imp) +{ + EINA_SAFETY_ON_FALSE_RETURN(imp->references == 0); + + eina_hash_del_by_key(_eina_value_inner_mps, &size); + eina_mempool_del(imp->mempool); + free(imp); +} + +static inline Eina_Value_Inner_Mp * +_eina_value_inner_mp_get(int size) +{ + Eina_Value_Inner_Mp *imp = eina_hash_find(_eina_value_inner_mps, &size); + if (imp) return imp; + + imp = malloc(sizeof(Eina_Value_Inner_Mp)); + if (!imp) + return NULL; + + imp->references = 0; + + imp->mempool = eina_mempool_add(_eina_value_mp_choice, + "Eina_Value_Inner_Mp", NULL, size, 128); + if (!imp->mempool) + { + free(imp); + return NULL; + } + + if (!eina_hash_add(_eina_value_inner_mps, &size, imp)) + { + eina_mempool_del(imp->mempool); + free(imp); + return NULL; + } + + return imp; +} + +static inline void * +_eina_value_inner_alloc_internal(int size) +{ + Eina_Value_Inner_Mp *imp; + void *mem; + + imp = _eina_value_inner_mp_get(size); + if (!imp) return NULL; + + mem = eina_mempool_malloc(imp->mempool, size); + if (mem) imp->references++; + else if (imp->references == 0) _eina_value_inner_mp_dispose(size, imp); + + return mem; +} + +static inline void +_eina_value_inner_free_internal(int size, void *mem) +{ + Eina_Value_Inner_Mp *imp = eina_hash_find(_eina_value_inner_mps, &size); + EINA_SAFETY_ON_NULL_RETURN(imp); + + eina_mempool_free(imp->mempool, mem); + + imp->references--; + if (imp->references > 0) return; + _eina_value_inner_mp_dispose(size, imp); +} + +EAPI void * +eina_value_inner_alloc(size_t size) +{ + void *mem; + + if (size > 256) return malloc(size); + + eina_lock_take(&_eina_value_inner_mps_lock); + mem = _eina_value_inner_alloc_internal(size); + eina_lock_release(&_eina_value_inner_mps_lock); + + return mem; +} + +EAPI void +eina_value_inner_free(size_t size, void *mem) +{ + if (size > 256) + { + free(mem); + return; + } + + eina_lock_take(&_eina_value_inner_mps_lock); + _eina_value_inner_free_internal(size, mem); + eina_lock_release(&_eina_value_inner_mps_lock); +} + +/** + * @internal + * @brief Initialize the value module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the value module of Eina. It is called + * by eina_init(). + * + * @see eina_init() + */ +Eina_Bool +eina_value_init(void) +{ + const char *choice, *tmp; + + _eina_value_log_dom = eina_log_domain_register("eina_value", + EINA_LOG_COLOR_DEFAULT); + if (_eina_value_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_value"); + return EINA_FALSE; + } + +#ifdef EINA_DEFAULT_MEMPOOL + choice = "pass_through"; +#else + choice = "chained_mempool"; +#endif + tmp = getenv("EINA_MEMPOOL"); + if (tmp && tmp[0]) + choice = tmp; + + if (choice) + _eina_value_mp_choice = strdup(choice); + + _eina_value_mp = eina_mempool_add + (_eina_value_mp_choice, "value", NULL, sizeof(Eina_Value), 320); + if (!_eina_value_mp) + { + ERR("Mempool for value cannot be allocated in value init."); + goto on_init_fail_mp; + } + + if (!eina_lock_new(&_eina_value_inner_mps_lock)) + { + ERR("Cannot create lock in value init."); + goto on_init_fail_lock; + } + _eina_value_inner_mps = eina_hash_int32_new(NULL); + if (!_eina_value_inner_mps) + { + ERR("Cannot create hash for inner mempools in value init."); + goto on_init_fail_hash; + } + + EINA_ERROR_VALUE_FAILED = eina_error_msg_static_register( + EINA_ERROR_VALUE_FAILED_STR); + + EINA_VALUE_TYPE_UCHAR = _EINA_VALUE_TYPE_BASICS + 0; + EINA_VALUE_TYPE_USHORT = _EINA_VALUE_TYPE_BASICS + 1; + EINA_VALUE_TYPE_UINT = _EINA_VALUE_TYPE_BASICS + 2; + EINA_VALUE_TYPE_ULONG = _EINA_VALUE_TYPE_BASICS + 3; + EINA_VALUE_TYPE_UINT64 = _EINA_VALUE_TYPE_BASICS + 4; + EINA_VALUE_TYPE_CHAR = _EINA_VALUE_TYPE_BASICS + 5; + EINA_VALUE_TYPE_SHORT = _EINA_VALUE_TYPE_BASICS + 6; + EINA_VALUE_TYPE_INT = _EINA_VALUE_TYPE_BASICS + 7; + EINA_VALUE_TYPE_LONG = _EINA_VALUE_TYPE_BASICS + 8; + EINA_VALUE_TYPE_INT64 = _EINA_VALUE_TYPE_BASICS + 9; + EINA_VALUE_TYPE_FLOAT = _EINA_VALUE_TYPE_BASICS + 10; + EINA_VALUE_TYPE_DOUBLE = _EINA_VALUE_TYPE_BASICS + 11; + EINA_VALUE_TYPE_STRINGSHARE = _EINA_VALUE_TYPE_BASICS + 12; + EINA_VALUE_TYPE_STRING = _EINA_VALUE_TYPE_BASICS + 13; + + _EINA_VALUE_TYPE_BASICS_START = _EINA_VALUE_TYPE_BASICS + 0; + _EINA_VALUE_TYPE_BASICS_END = _EINA_VALUE_TYPE_BASICS + 13; + + EINA_SAFETY_ON_FALSE_RETURN_VAL((sizeof(_EINA_VALUE_TYPE_BASICS)/sizeof(_EINA_VALUE_TYPE_BASICS[0])) == 14, EINA_FALSE); + + + EINA_VALUE_TYPE_ARRAY = &_EINA_VALUE_TYPE_ARRAY; + EINA_VALUE_TYPE_LIST = &_EINA_VALUE_TYPE_LIST; + EINA_VALUE_TYPE_HASH = &_EINA_VALUE_TYPE_HASH; + EINA_VALUE_TYPE_TIMEVAL = &_EINA_VALUE_TYPE_TIMEVAL; + EINA_VALUE_TYPE_BLOB = &_EINA_VALUE_TYPE_BLOB; + EINA_VALUE_TYPE_STRUCT = &_EINA_VALUE_TYPE_STRUCT; + + EINA_VALUE_BLOB_OPERATIONS_MALLOC = &_EINA_VALUE_BLOB_OPERATIONS_MALLOC; + + EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH = &_EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH; + EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE = &_EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE; + + return EINA_TRUE; + + on_init_fail_hash: + eina_lock_free(&_eina_value_inner_mps_lock); + on_init_fail_lock: + eina_mempool_del(_eina_value_mp); + on_init_fail_mp: + free(_eina_value_mp_choice); + _eina_value_mp_choice = NULL; + eina_log_domain_unregister(_eina_value_log_dom); + _eina_value_log_dom = -1; + return EINA_FALSE; +} + +/** + * @internal + * @brief Shut down the value module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the value module set up by + * eina_value_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_value_shutdown(void) +{ + eina_lock_take(&_eina_value_inner_mps_lock); + if (eina_hash_population(_eina_value_inner_mps) != 0) + ERR("Cannot free eina_value internal memory pools -- still in use!"); + else + eina_hash_free(_eina_value_inner_mps); + eina_lock_release(&_eina_value_inner_mps_lock); + eina_lock_free(&_eina_value_inner_mps_lock); + + free(_eina_value_mp_choice); + _eina_value_mp_choice = NULL; + eina_mempool_del(_eina_value_mp); + eina_log_domain_unregister(_eina_value_log_dom); + _eina_value_log_dom = -1; + return EINA_TRUE; +} /*============================================================================* * Global * @@ -39,9 +4793,232 @@ * API * *============================================================================*/ +EAPI const Eina_Value_Type *_EINA_VALUE_TYPE_BASICS_START = NULL; +EAPI const Eina_Value_Type *_EINA_VALUE_TYPE_BASICS_END = NULL; + +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_UCHAR = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_USHORT = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_UINT = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_ULONG = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_UINT64 = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_CHAR = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_SHORT = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_INT = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_LONG = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_INT64 = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_FLOAT = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_DOUBLE = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_STRINGSHARE = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_STRING = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_ARRAY = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_LIST = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_HASH = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_TIMEVAL = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_BLOB = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_STRUCT = NULL; + +EAPI const Eina_Value_Blob_Operations *EINA_VALUE_BLOB_OPERATIONS_MALLOC = NULL; + +EAPI const Eina_Value_Struct_Operations *EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH = NULL; +EAPI const Eina_Value_Struct_Operations *EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE = NULL; + +EAPI Eina_Error EINA_ERROR_VALUE_FAILED = 0; + EAPI const unsigned int eina_prime_table[] = { 17, 31, 61, 127, 257, 509, 1021, 2053, 4093, 8191, 16381, 32771, 65537, 131071, 262147, 524287, 1048573, 2097143, 4194301, 8388617, 16777213 }; + +EAPI Eina_Value * +eina_value_new(const Eina_Value_Type *type) +{ + Eina_Value *value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));; + if (!value) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + if (!eina_value_setup(value, type)) + { + free(value); + return NULL; + } + return value; +} + +EAPI void +eina_value_free(Eina_Value *value) +{ + EINA_SAFETY_ON_NULL_RETURN(value); + eina_value_flush(value); + eina_mempool_free(_eina_value_mp, value); +} + + +EAPI Eina_Bool +eina_value_copy(const Eina_Value *value, Eina_Value *copy) +{ + const Eina_Value_Type *type; + const void *src; + void *dst; + Eina_Bool ret; + + EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), + EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(copy, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(value->type->copy, EINA_FALSE); + + type = value->type; + if (!eina_value_setup(copy, type)) + return EINA_FALSE; + + src = eina_value_memory_get(value); + dst = eina_value_memory_get(copy); + ret = type->copy(type, src, dst); + if (!ret) + eina_value_flush(copy); + + return ret; +} + +EAPI Eina_Bool +eina_value_convert(const Eina_Value *value, Eina_Value *convert) +{ + Eina_Bool ret = EINA_FALSE; + const Eina_Value_Type *type, *convert_type; + const void *type_mem; + void *convert_mem; + + EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(convert, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), + EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(convert->type), + EINA_FALSE); + + type = value->type; + convert_type = convert->type; + + type_mem = eina_value_memory_get(value); + convert_mem = eina_value_memory_get(convert); + + if (type->convert_to) + ret = type->convert_to(type, convert_type, type_mem, convert_mem); + + if ((!ret) && (convert_type->convert_from)) + ret = convert_type->convert_from(convert_type, type, convert_mem, + type_mem); + + return ret; +} + +EAPI char * +eina_value_to_string(const Eina_Value *value) +{ + Eina_Value tmp; + + EINA_SAFETY_ON_NULL_RETURN_VAL(value, NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), NULL); + + if (!eina_value_setup(&tmp, EINA_VALUE_TYPE_STRING)) + return NULL; + if (!eina_value_convert(value, &tmp)) + return NULL; + + return tmp.value.ptr; /* steal value */ +} + +EAPI Eina_Value * +eina_value_array_new(const Eina_Value_Type *subtype, unsigned int step) +{ + Eina_Value *value; + + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(subtype), EINA_FALSE); + + value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));; + if (!value) + return NULL; + + if (!eina_value_array_setup(value, subtype, step)) + { + eina_mempool_free(_eina_value_mp, value); + return NULL; + } + + return value; +} + +EAPI Eina_Value * +eina_value_list_new(const Eina_Value_Type *subtype) +{ + Eina_Value *value; + + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(subtype), EINA_FALSE); + + value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));; + if (!value) + return NULL; + + if (!eina_value_list_setup(value, subtype)) + { + eina_mempool_free(_eina_value_mp, value); + return NULL; + } + + return value; +} + +EAPI Eina_Value * +eina_value_hash_new(const Eina_Value_Type *subtype, unsigned int buckets_power_size) +{ + Eina_Value *value; + + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(subtype), EINA_FALSE); + + value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));; + if (!value) + return NULL; + + if (!eina_value_hash_setup(value, subtype, buckets_power_size)) + { + eina_mempool_free(_eina_value_mp, value); + return NULL; + } + + return value; +} + +EAPI Eina_Value * +eina_value_struct_new(const Eina_Value_Struct_Desc *desc) +{ + Eina_Value *value; + + value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));; + if (!value) + return NULL; + + if (!eina_value_struct_setup(value, desc)) + { + eina_mempool_free(_eina_value_mp, value); + return NULL; + } + + return value; +} + +EAPI Eina_Bool +eina_value_type_check(const Eina_Value_Type *type) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE); + return type->version == EINA_VALUE_TYPE_VERSION; +} + +EAPI const char * +eina_value_type_name_get(const Eina_Value_Type *type) +{ + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(type), NULL); + return type->name; +} diff --git a/libraries/eina/src/lib/eina_xattr.c b/libraries/eina/src/lib/eina_xattr.c index bd5b98e..d4ed139 100644 --- a/libraries/eina/src/lib/eina_xattr.c +++ b/libraries/eina/src/lib/eina_xattr.c @@ -20,6 +20,7 @@ # include "config.h" #endif +#include #include #include #include @@ -34,6 +35,7 @@ #include "eina_safety_checks.h" #include "eina_xattr.h" #include "eina_convert.h" +#include "eina_stringshare.h" /*============================================================================* * Local * @@ -49,14 +51,83 @@ struct _Eina_Xattr_Iterator { Eina_Iterator iterator; + const char *file; + Eina_Xattr *attr; + ssize_t length; ssize_t offset; + int fd; + char xattr[1]; }; #ifdef HAVE_XATTR static Eina_Bool +_eina_xattr_value_ls_fd_iterator_next(Eina_Xattr_Iterator *it, void **data) +{ + char *tmp; + + if (it->offset >= it->length) + return EINA_FALSE; + + *data = it->attr; + it->attr->name = it->xattr + it->offset; + + it->attr->length = fgetxattr(it->fd, it->attr->name, NULL, 0); + if (it->attr->length) + { + tmp = realloc((void*) it->attr->value, it->attr->length); + if (!tmp) + { + free((void*) it->attr->value); + it->attr->value = NULL; + it->attr->length = 0; + } + else + { + it->attr->length = fgetxattr(it->fd, it->attr->name, + (void *) it->attr->value, + it->attr->length); + } + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_xattr_value_ls_iterator_next(Eina_Xattr_Iterator *it, void **data) +{ + char *tmp; + + if (it->offset >= it->length) + return EINA_FALSE; + + *data = it->attr; + it->attr->name = it->xattr + it->offset; + + it->attr->length = getxattr(it->file, it->attr->name, NULL, 0); + if (it->attr->length) + { + tmp = realloc((void*) it->attr->value, it->attr->length); + if (!tmp) + { + free((void*) it->attr->value); + it->attr->value = NULL; + it->attr->length = 0; + } + else + { + it->attr->length = getxattr(it->file, it->attr->name, + (void*) it->attr->value, + it->attr->length); + } + } + + return EINA_TRUE; +} + +static Eina_Bool _eina_xattr_ls_iterator_next(Eina_Xattr_Iterator *it, void **data) { if (it->offset >= it->length) @@ -78,6 +149,9 @@ static void _eina_xattr_ls_iterator_free(Eina_Xattr_Iterator *it) { EINA_MAGIC_SET(&it->iterator, 0); + if (it->attr) free((void *) it->attr->value); + eina_stringshare_del(it->file); + free(it->attr); free(it); } #endif @@ -96,6 +170,85 @@ _eina_xattr_ls_iterator_free(Eina_Xattr_Iterator *it) * API * *============================================================================*/ +EAPI Eina_Iterator * +eina_xattr_value_fd_ls(int fd) +{ +#ifdef HAVE_XATTR + Eina_Xattr_Iterator *it; + ssize_t length; + + if (fd < 0) return NULL; + + length = flistxattr(fd, NULL, 0); + if (length <= 0) return NULL; + + it = calloc(1, sizeof (Eina_Xattr_Iterator) + length - 1); + if (!it) return NULL; + + it->attr = calloc(1, sizeof (Eina_Xattr)); + if (!it->attr) + { + free(it); + return NULL; + } + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->fd = fd; + it->length = flistxattr(fd, it->xattr, length); + if (it->length != length) + { + free(it); + return NULL; + } + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_eina_xattr_value_ls_fd_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_xattr_ls_iterator_container); + it->iterator.free = FUNC_ITERATOR_FREE(_eina_xattr_ls_iterator_free); + + return &it->iterator; +#else + return NULL; + (void)fd; +#endif +} + +EAPI Eina_Iterator * +eina_xattr_fd_ls(int fd) +{ +#ifdef HAVE_XATTR + Eina_Xattr_Iterator *it; + ssize_t length; + + if (fd < 0) return NULL; + + length = flistxattr(fd, NULL, 0); + if (length <= 0) return NULL; + + it = calloc(1, sizeof (Eina_Xattr_Iterator) + length - 1); + if (!it) return NULL; + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->length = flistxattr(fd, it->xattr, length); + if (it->length != length) + { + free(it); + return NULL; + } + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_eina_xattr_ls_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_xattr_ls_iterator_container); + it->iterator.free = FUNC_ITERATOR_FREE(_eina_xattr_ls_iterator_free); + + return &it->iterator; +#else + return NULL; + (void)fd; +#endif +} EAPI Eina_Iterator * eina_xattr_ls(const char *file) @@ -133,6 +286,44 @@ eina_xattr_ls(const char *file) #endif } +EAPI Eina_Iterator * +eina_xattr_value_ls(const char *file) +{ +#ifdef HAVE_XATTR + Eina_Xattr_Iterator *it; + ssize_t length; + + EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); + + length = listxattr(file, NULL, 0); + if (length <= 0) return NULL; + + it = calloc(1, sizeof (Eina_Xattr_Iterator) + length - 1); + if (!it) return NULL; + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->length = listxattr(file, it->xattr, length); + if (it->length != length) + { + free(it); + return NULL; + } + + it->file = eina_stringshare_add(file); + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_eina_xattr_value_ls_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_xattr_ls_iterator_container); + it->iterator.free = FUNC_ITERATOR_FREE(_eina_xattr_ls_iterator_free); + + return &it->iterator; +#else + return NULL; + (void)file; +#endif +} + EAPI void * eina_xattr_get(const char *file, const char *attribute, ssize_t *size) { -- cgit v1.1