From c963d75dfdeec11f82e79e727062fbf89afa2c04 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Sun, 22 Apr 2012 09:19:23 +1000 Subject: Update EFL to latest beta. --- libraries/eina/src/lib/Makefile.am | 5 +- libraries/eina/src/lib/Makefile.in | 94 +- libraries/eina/src/lib/eina_binshare.c | 69 +- libraries/eina/src/lib/eina_file.c | 232 +-- libraries/eina/src/lib/eina_file_win32.c | 2235 +++++++++++++++------------- libraries/eina/src/lib/eina_inlist.c | 5 + libraries/eina/src/lib/eina_list.c | 15 +- libraries/eina/src/lib/eina_magic.c | 5 - libraries/eina/src/lib/eina_main.c | 5 +- libraries/eina/src/lib/eina_matrixsparse.c | 2 + libraries/eina/src/lib/eina_module.c | 4 + libraries/eina/src/lib/eina_prefix.c | 22 +- libraries/eina/src/lib/eina_private.h | 2 + libraries/eina/src/lib/eina_rbtree.c | 365 ++--- libraries/eina/src/lib/eina_sched.c | 19 +- libraries/eina/src/lib/eina_share_common.c | 42 +- libraries/eina/src/lib/eina_share_common.h | 21 +- libraries/eina/src/lib/eina_stringshare.c | 77 +- libraries/eina/src/lib/eina_unicode.c | 55 +- libraries/eina/src/lib/eina_ustringshare.c | 69 +- libraries/eina/src/lib/eina_value.c | 453 ++++-- 21 files changed, 2261 insertions(+), 1535 deletions(-) (limited to 'libraries/eina/src/lib') diff --git a/libraries/eina/src/lib/Makefile.am b/libraries/eina/src/lib/Makefile.am index d8c9d20..5de2848 100644 --- a/libraries/eina/src/lib/Makefile.am +++ b/libraries/eina/src/lib/Makefile.am @@ -6,8 +6,8 @@ AM_CPPFLAGS = \ -DPACKAGE_BIN_DIR=\"$(bindir)\" \ -DPACKAGE_LIB_DIR=\"$(libdir)\" \ -DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ -@EINA_CPPFLAGS@ \ -@EFL_EINA_BUILD@ +@EFL_EINA_BUILD@ \ +@VALGRIND_CFLAGS@ base_sources = \ eina_accessor.c \ @@ -33,6 +33,7 @@ eina_main.c \ eina_matrixsparse.c \ eina_mempool.c \ eina_mmap.c \ +eina_model.c \ eina_module.c \ eina_prefix.c \ eina_quadtree.c \ diff --git a/libraries/eina/src/lib/Makefile.in b/libraries/eina/src/lib/Makefile.in index 878bcbe..f15bb00 100644 --- a/libraries/eina/src/lib/Makefile.in +++ b/libraries/eina/src/lib/Makefile.in @@ -49,20 +49,24 @@ host_triplet = @host@ subdir = src/lib DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/efl_attribute.m4 \ - $(top_srcdir)/m4/efl_benchmark.m4 \ - $(top_srcdir)/m4/efl_compiler_flag.m4 \ - $(top_srcdir)/m4/efl_coverage.m4 $(top_srcdir)/m4/efl_cpu.m4 \ - $(top_srcdir)/m4/efl_doxygen.m4 \ - $(top_srcdir)/m4/efl_examples.m4 \ - $(top_srcdir)/m4/efl_fnmatch.m4 \ - $(top_srcdir)/m4/efl_path_max.m4 $(top_srcdir)/m4/efl_tests.m4 \ - $(top_srcdir)/m4/efl_threads.m4 \ - $(top_srcdir)/m4/efl_voltron.m4 $(top_srcdir)/m4/eina_bench.m4 \ - $(top_srcdir)/m4/eina_check.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__aclocal_m4_deps = $(top_srcdir)/m4/eina/eina_bench.m4 \ + $(top_srcdir)/m4/eina/eina_check.m4 \ + $(top_srcdir)/m4/common/efl_attribute.m4 \ + $(top_srcdir)/m4/common/efl_benchmark.m4 \ + $(top_srcdir)/m4/common/efl_compiler_flag.m4 \ + $(top_srcdir)/m4/common/efl_coverage.m4 \ + $(top_srcdir)/m4/common/efl_cpu.m4 \ + $(top_srcdir)/m4/common/efl_doxygen.m4 \ + $(top_srcdir)/m4/common/efl_examples.m4 \ + $(top_srcdir)/m4/common/efl_fnmatch.m4 \ + $(top_srcdir)/m4/common/efl_path_max.m4 \ + $(top_srcdir)/m4/common/efl_tests.m4 \ + $(top_srcdir)/m4/common/efl_threads.m4 \ + $(top_srcdir)/m4/common/efl_voltron.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -99,13 +103,13 @@ am__libeina_la_SOURCES_DIST = eina_accessor.c eina_array.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 \ + eina_mmap.c eina_model.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 \ @@ -135,11 +139,11 @@ am__objects_10 = libeina_la-eina_accessor.lo libeina_la-eina_array.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_mmap.lo libeina_la-eina_model.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 \ @@ -236,13 +240,13 @@ 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_EXOTIC = @EINA_CONFIGURE_HAVE_EXOTIC@ 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@ EINA_CONFIGURE_HAVE_THREADS = @EINA_CONFIGURE_HAVE_THREADS@ EINA_CONFIGURE_MAGIC_DEBUG = @EINA_CONFIGURE_MAGIC_DEBUG@ EINA_CONFIGURE_SAFETY_CHECKS = @EINA_CONFIGURE_SAFETY_CHECKS@ -EINA_CPPFLAGS = @EINA_CPPFLAGS@ EINA_LIBS = @EINA_LIBS@ EINA_SIZEOF_WCHAR_T = @EINA_SIZEOF_WCHAR_T@ EMEMOA_CFLAGS = @EMEMOA_CFLAGS@ @@ -252,6 +256,8 @@ ESCAPE_LIBS = @ESCAPE_LIBS@ EVIL_CFLAGS = @EVIL_CFLAGS@ EVIL_LIBS = @EVIL_LIBS@ EXEEXT = @EXEEXT@ +EXOTIC_CFLAGS = @EXOTIC_CFLAGS@ +EXOTIC_LIBS = @EXOTIC_LIBS@ FGREP = @FGREP@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ @@ -287,6 +293,8 @@ 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@ @@ -367,23 +375,24 @@ AM_CPPFLAGS = \ -DPACKAGE_BIN_DIR=\"$(bindir)\" \ -DPACKAGE_LIB_DIR=\"$(libdir)\" \ -DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ -@EINA_CPPFLAGS@ \ -@EFL_EINA_BUILD@ +@EFL_EINA_BUILD@ \ +@VALGRIND_CFLAGS@ 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_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 $(am__append_1) $(am__append_2) $(am__append_3) \ - $(am__append_4) $(am__append_5) $(am__append_6) \ - $(am__append_7) $(am__append_8) $(am__append_9) + eina_matrixsparse.c eina_mempool.c eina_mmap.c eina_model.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 $(am__append_1) $(am__append_2) \ + $(am__append_3) $(am__append_4) $(am__append_5) \ + $(am__append_6) $(am__append_7) $(am__append_8) \ + $(am__append_9) EXTRA_DIST = \ eina_share_common.h \ eina_private.h \ @@ -502,6 +511,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_matrixsparse.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_mempool.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_mmap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_model.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_module.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_one_big.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_pass_through.Plo@am__quote@ @@ -732,6 +742,14 @@ libeina_la-eina_mmap.lo: eina_mmap.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_mmap.lo `test -f 'eina_mmap.c' || echo '$(srcdir)/'`eina_mmap.c +libeina_la-eina_model.lo: eina_model.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_model.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_model.Tpo -c -o libeina_la-eina_model.lo `test -f 'eina_model.c' || echo '$(srcdir)/'`eina_model.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_model.Tpo $(DEPDIR)/libeina_la-eina_model.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_model.c' object='libeina_la-eina_model.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_model.lo `test -f 'eina_model.c' || echo '$(srcdir)/'`eina_model.c + libeina_la-eina_module.lo: eina_module.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_module.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_module.Tpo -c -o libeina_la-eina_module.lo `test -f 'eina_module.c' || echo '$(srcdir)/'`eina_module.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_module.Tpo $(DEPDIR)/libeina_la-eina_module.Plo diff --git a/libraries/eina/src/lib/eina_binshare.c b/libraries/eina/src/lib/eina_binshare.c index 68a82fc..01e8046 100644 --- a/libraries/eina/src/lib/eina_binshare.c +++ b/libraries/eina/src/lib/eina_binshare.c @@ -21,9 +21,18 @@ */ -#include "eina_share_common.h" -#include "eina_unicode.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "eina_config.h" #include "eina_private.h" +#include "eina_unicode.h" +#include "eina_log.h" +#include "eina_share_common.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" #include "eina_binshare.h" /*============================================================================* @@ -34,6 +43,23 @@ * @cond LOCAL */ +#ifdef CRITICAL +#undef CRITICAL +#endif +#define CRITICAL(...) EINA_LOG_DOM_CRIT(_eina_share_binshare_log_dom, __VA_ARGS__) + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_eina_share_binshare_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_share_binshare_log_dom, __VA_ARGS__) + +static int _eina_share_binshare_log_dom = -1; + /* The actual share */ static Eina_Share *binshare_share; static const char EINA_MAGIC_BINSHARE_NODE_STR[] = "Eina Binshare Node"; @@ -42,7 +68,6 @@ static const char EINA_MAGIC_BINSHARE_NODE_STR[] = "Eina Binshare Node"; * @endcond */ - /*============================================================================* * Global * *============================================================================*/ @@ -61,9 +86,31 @@ static const char EINA_MAGIC_BINSHARE_NODE_STR[] = "Eina Binshare Node"; EAPI Eina_Bool eina_binshare_init(void) { - return eina_share_common_init(&binshare_share, - EINA_MAGIC_BINSHARE_NODE, - EINA_MAGIC_BINSHARE_NODE_STR); + Eina_Bool ret; + + if (_eina_share_binshare_log_dom < 0) + { + _eina_share_binshare_log_dom = eina_log_domain_register + ("eina_binshare", EINA_LOG_COLOR_DEFAULT); + + if (_eina_share_binshare_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_binshare"); + return EINA_FALSE; + } + } + + ret = eina_share_common_init(&binshare_share, + EINA_MAGIC_BINSHARE_NODE, + EINA_MAGIC_BINSHARE_NODE_STR); + + if (!ret) + { + eina_log_domain_unregister(_eina_share_binshare_log_dom); + _eina_share_binshare_log_dom = -1; + } + + return ret; } /** @@ -82,6 +129,13 @@ eina_binshare_shutdown(void) { Eina_Bool ret; ret = eina_share_common_shutdown(&binshare_share); + + if (_eina_share_binshare_log_dom > 0) + { + eina_log_domain_unregister(_eina_share_binshare_log_dom); + _eina_share_binshare_log_dom = -1; + } + return ret; } @@ -96,7 +150,8 @@ eina_binshare_del(const void *obj) if (!obj) return; - eina_share_common_del(binshare_share, obj); + if (!eina_share_common_del(binshare_share, obj)) + CRITICAL("EEEK trying to del non-shared binshare %p", obj); } EAPI const void * diff --git a/libraries/eina/src/lib/eina_file.c b/libraries/eina/src/lib/eina_file.c index 0b836b3..c465301 100644 --- a/libraries/eina/src/lib/eina_file.c +++ b/libraries/eina/src/lib/eina_file.c @@ -362,41 +362,15 @@ _eina_file_direct_ls_iterator_free(Eina_File_Direct_Iterator *it) static Eina_Bool _eina_file_stat_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data) { - struct stat st; + Eina_Stat st; if (!_eina_file_direct_ls_iterator_next(it, data)) return EINA_FALSE; if (it->info.type == EINA_FILE_UNKNOWN) { -#ifdef HAVE_FSTATAT - int fd; - - fd = dirfd(it->dirp); - if (fstatat(fd, it->info.path + it->info.name_start, &st, 0)) -#else - if (stat(it->info.path, &st)) -#endif + if (eina_file_statat(it->dirp, &it->info, &st) != 0) it->info.type = EINA_FILE_UNKNOWN; - else - { - if (S_ISREG(st.st_mode)) - it->info.type = EINA_FILE_REG; - else if (S_ISDIR(st.st_mode)) - it->info.type = EINA_FILE_DIR; - else if (S_ISCHR(st.st_mode)) - it->info.type = EINA_FILE_CHR; - else if (S_ISBLK(st.st_mode)) - it->info.type = EINA_FILE_BLK; - else if (S_ISFIFO(st.st_mode)) - it->info.type = EINA_FILE_FIFO; - else if (S_ISLNK(st.st_mode)) - it->info.type = EINA_FILE_LNK; - else if (S_ISSOCK(st.st_mode)) - it->info.type = EINA_FILE_SOCK; - else - it->info.type = EINA_FILE_UNKNOWN; - } } return EINA_TRUE; @@ -593,6 +567,14 @@ _eina_file_escape(const char *path, int *length) return result; } +/** + * @endcond + */ + +/*============================================================================* + * Global * + *============================================================================*/ + Eina_Bool eina_file_init(void) { @@ -641,13 +623,60 @@ eina_file_shutdown(void) return EINA_TRUE; } -/** - * @endcond - */ +void +eina_file_mmap_faulty(void *addr, long page_size) +{ + Eina_File_Map *m; + Eina_File *f; + Eina_Iterator *itf; + Eina_Iterator *itm; -/*============================================================================* - * Global * - *============================================================================*/ + /* 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); +} /*============================================================================* * API * @@ -950,7 +979,7 @@ eina_file_open(const char *path, Eina_Bool shared) eina_lock_take(&_eina_file_lock_cache); file = eina_hash_find(_eina_file_cache, filename); - if ((file) && _eina_file_timestamp_compare(file, &file_stat)) + if ((file) && !_eina_file_timestamp_compare(file, &file_stat)) { file->delete_me = EINA_TRUE; eina_hash_del(_eina_file_cache, file->filename, file); @@ -1029,7 +1058,7 @@ eina_file_close(Eina_File *file) eina_hash_del(_eina_file_cache, file->filename, file); _eina_file_real_close(file); - + eina_lock_release(&_eina_file_lock_cache); } @@ -1196,7 +1225,7 @@ eina_file_map_free(Eina_File *file, void *map) unsigned long int key[2]; em = eina_hash_find(file->rmap, &map); - if (!em) return ; + if (!em) goto on_exit; em->refcount--; @@ -1217,17 +1246,25 @@ EAPI Eina_Bool eina_file_map_faulted(Eina_File *file, void *map) { Eina_File_Map *em; + Eina_Bool r = EINA_FALSE; EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE); eina_lock_take(&file->lock); - if (file->global_map == map) return file->global_faulty; + if (file->global_map == map) + { + r = file->global_faulty; + } + else + { + em = eina_hash_find(file->rmap, &map); + if (em) r = em->faulty; + } - em = eina_hash_find(file->rmap, &map); - if (!em) return EINA_FALSE; + eina_lock_release(&file->lock); - return em->faulty; + return r; } EAPI Eina_Iterator * @@ -1246,58 +1283,77 @@ eina_file_xattr_value_get(Eina_File *file) return eina_xattr_value_fd_ls(file->fd); } -void -eina_file_mmap_faulty(void *addr, long page_size) +EAPI int +eina_file_statat(void *container, Eina_File_Direct_Info *info, Eina_Stat *st) { - Eina_File_Map *m; - Eina_File *f; - Eina_Iterator *itf; - Eina_Iterator *itm; + struct stat buf; +#ifdef HAVE_FSTATAT + int fd; +#endif - /* 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); + EINA_SAFETY_ON_NULL_RETURN_VAL(info, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(st, -1); - itf = eina_hash_iterator_data_new(_eina_file_cache); - EINA_ITERATOR_FOREACH(itf, f) +#ifdef HAVE_FSTATAT + fd = dirfd((DIR*) container); + if (fstatat(fd, info->path + info->name_start, &buf, 0)) +#else + (void)container; + if (stat(info->path, &buf)) +#endif { - 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 (info->type != EINA_FILE_LNK) + info->type = EINA_FILE_UNKNOWN; + return -1; + } - if (faulty) break; + if (info->type == EINA_FILE_UNKNOWN) + { + if (S_ISREG(buf.st_mode)) + info->type = EINA_FILE_REG; + else if (S_ISDIR(buf.st_mode)) + info->type = EINA_FILE_DIR; + else if (S_ISCHR(buf.st_mode)) + info->type = EINA_FILE_CHR; + else if (S_ISBLK(buf.st_mode)) + info->type = EINA_FILE_BLK; + else if (S_ISFIFO(buf.st_mode)) + info->type = EINA_FILE_FIFO; + else if (S_ISLNK(buf.st_mode)) + info->type = EINA_FILE_LNK; + else if (S_ISSOCK(buf.st_mode)) + info->type = EINA_FILE_SOCK; + else + info->type = EINA_FILE_UNKNOWN; } - eina_iterator_free(itf); - eina_lock_release(&_eina_file_lock_cache); + st->dev = buf.st_dev; + st->ino = buf.st_ino; + st->mode = buf.st_mode; + st->nlink = buf.st_nlink; + st->uid = buf.st_uid; + st->gid = buf.st_gid; + st->rdev = buf.st_rdev; + st->size = buf.st_size; + st->blksize = buf.st_blksize; + st->blocks = buf.st_blocks; + st->atime = buf.st_atime; + st->mtime = buf.st_mtime; + st->ctime = buf.st_ctime; +#ifdef _STAT_VER_LINUX +# if (defined __USE_MISC && defined st_mtime) + st->atimensec = buf.st_atim.tv_nsec; + st->mtimensec = buf.st_mtim.tv_nsec; + st->ctimensec = buf.st_ctim.tv_nsec; +# else + st->atimensec = buf.st_atimensec; + st->mtimensec = buf.st_mtimensec; + st->ctimensec = buf.st_ctimensec; +# endif +#else + st->atimensec = 0; + st->mtimensec = 0; + st->ctimensec = 0; +#endif + return 0; } - diff --git a/libraries/eina/src/lib/eina_file_win32.c b/libraries/eina/src/lib/eina_file_win32.c index 1cd8665..5c20fdd 100644 --- a/libraries/eina/src/lib/eina_file_win32.c +++ b/libraries/eina/src/lib/eina_file_win32.c @@ -1,1021 +1,1214 @@ -/* EINA - EFL data type library - * Copyright (C) 2010 Vincent Torri - * - * 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 - -#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 - -#define WIN32_LEAN_AND_MEAN -#include -#undef WIN32_LEAN_AND_MEAN - -//#include - -#include "eina_config.h" -#include "eina_private.h" - -/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ -#include "eina_safety_checks.h" -#include "eina_file.h" -#include "eina_stringshare.h" -#include "eina_hash.h" -#include "eina_list.h" - -/*============================================================================* - * Local * - *============================================================================*/ - -/** - * @cond LOCAL - */ - -#ifndef EINA_LOG_COLOR_DEFAULT -#define EINA_LOG_COLOR_DEFAULT EINA_COLOR_CYAN -#endif - -#ifdef ERR -#undef ERR -#endif -#define ERR(...) EINA_LOG_DOM_ERR(_eina_file_log_dom, __VA_ARGS__) - -#ifdef WRN -#undef WRN -#endif -#define WRN(...) EINA_LOG_DOM_WARN(_eina_file_log_dom, __VA_ARGS__) - -#ifdef DBG -#undef DBG -#endif -#define DBG(...) EINA_LOG_DOM_DBG(_eina_file_log_dom, __VA_ARGS__) - -#ifdef MAP_FAILED -# undef MAP_FAILED -#endif -#define MAP_FAILED ((void *)-1) - -typedef struct _Eina_File_Iterator Eina_File_Iterator; -typedef struct _Eina_File_Direct_Iterator Eina_File_Direct_Iterator; -typedef struct _Eina_File_Map Eina_File_Map; - -struct _Eina_File_Iterator -{ - Eina_Iterator iterator; - - WIN32_FIND_DATA data; - HANDLE handle; - size_t length; - Eina_Bool is_last : 1; - - char dir[1]; -}; - -struct _Eina_File_Direct_Iterator -{ - Eina_Iterator iterator; - - WIN32_FIND_DATA data; - HANDLE handle; - size_t length; - Eina_Bool is_last : 1; - - Eina_File_Direct_Info info; - - char dir[1]; -}; - -struct _Eina_File -{ - const char *filename; - - Eina_Hash *map; - Eina_Hash *rmap; - void *global_map; - - ULONGLONG length; - ULONGLONG mtime; - - int refcount; - int global_refcount; - - HANDLE handle; - HANDLE fm; - - Eina_Bool shared : 1; - Eina_Bool delete_me : 1; -}; - -struct _Eina_File_Map -{ - void *map; - - unsigned long int offset; - unsigned long int length; - - int refcount; -}; - -static Eina_Hash *_eina_file_cache = NULL; -static Eina_List *_eina_file_cache_lru = NULL; -static Eina_List *_eina_file_cache_delete = NULL; - -static int _eina_file_log_dom = -1; - -static void -_eina_file_win32_backslash_change(char *dir) -{ - char *tmp; - - tmp = dir; - while (*tmp) - { - if (*tmp == '/') *tmp = '\\'; - tmp++; - } -} - -static Eina_Bool -_eina_file_win32_is_dir(const char *dir) -{ -#ifdef UNICODE - wchar_t *wdir = NULL; -#endif - DWORD attr; - - /* check if it's a directory */ -#ifdef UNICODE - wdir = evil_char_to_wchar(dir); - if (!wdir) - return EINA_FALSE; - - attr = GetFileAttributes(wdir); - free(wdir); -#else - attr = GetFileAttributes(dir); -#endif - - if (attr == 0xFFFFFFFF) - return EINA_FALSE; - - if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) - return EINA_FALSE; - - return EINA_TRUE; -} - -static char * -_eina_file_win32_dir_new(const char *dir) -{ - char *new_dir; - size_t length; - - length = strlen(dir); - - new_dir = (char *)malloc(sizeof(char) * length + 5); - if (!new_dir) - return NULL; - - memcpy(new_dir, dir, length); - memcpy(new_dir + length, "\\*.*", 5); - _eina_file_win32_backslash_change(new_dir); - - return new_dir; -} - -static HANDLE -_eina_file_win32_first_file(const char *dir, WIN32_FIND_DATA *fd) -{ - HANDLE h; -#ifdef UNICODE - wchar_t *wdir = NULL; - - wdir = evil_char_to_wchar(dir); - if (!wdir) - return NULL; - - h = FindFirstFile(wdir, fd); - free(wdir); -#else - h = FindFirstFile(dir, fd); -#endif - - if (!h) - return NULL; - - while ((fd->cFileName[0] == '.') && - ((fd->cFileName[1] == '\0') || - ((fd->cFileName[1] == '.') && (fd->cFileName[2] == '\0')))) - { - if (!FindNextFile(h, fd)) - return NULL; - } - - return h; -} - -static Eina_Bool -_eina_file_win32_ls_iterator_next(Eina_File_Iterator *it, void **data) -{ -#ifdef UNICODE - wchar_t *old_name; -#else - char *old_name; -#endif - char *name; - char *cname; - size_t length; - Eina_Bool is_last; - Eina_Bool res = EINA_TRUE; - - if (it->handle == INVALID_HANDLE_VALUE) - return EINA_FALSE; - - is_last = it->is_last; -#ifdef UNICODE - old_name = _wcsdup(it->data.cFileName); -#else - old_name = _strdup(it->data.cFileName); -#endif - if (!old_name) - return EINA_FALSE; - - do { - if (!FindNextFile(it->handle, &it->data)) - { - if (GetLastError() == ERROR_NO_MORE_FILES) - it->is_last = EINA_TRUE; - else - res = EINA_FALSE; - } - } while ((it->data.cFileName[0] == '.') && - ((it->data.cFileName[1] == '\0') || - ((it->data.cFileName[1] == '.') && (it->data.cFileName[2] == '\0')))); /* FIXME: what about UNICODE ? */ - -#ifdef UNICODE - cname = evil_wchar_to_char(old_name); - if (!cname) - return EINA_FALSE; -#else - cname = old_name; -#endif - - length = strlen(cname); - name = alloca(length + 2 + it->length); - - memcpy(name, it->dir, it->length); - memcpy(name + it->length, "\\", 1); - memcpy(name + it->length + 1, cname, length + 1); - - *data = (char *)eina_stringshare_add(name); - -#ifdef UNICODE - free(cname); -#endif - free(old_name); - - if (is_last) - res = EINA_FALSE; - - return res; -} - -static HANDLE -_eina_file_win32_ls_iterator_container(Eina_File_Iterator *it) -{ - return it->handle; -} - -static void -_eina_file_win32_ls_iterator_free(Eina_File_Iterator *it) -{ - if (it->handle != INVALID_HANDLE_VALUE) - FindClose(it->handle); - - EINA_MAGIC_SET(&it->iterator, 0); - free(it); -} - -static Eina_Bool -_eina_file_win32_direct_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data) -{ -#ifdef UNICODE - wchar_t *old_name; -#else - char *old_name; -#endif - char *cname; - size_t length; - DWORD attr; - Eina_Bool is_last; - Eina_Bool res = EINA_TRUE; - - if (it->handle == INVALID_HANDLE_VALUE) - return EINA_FALSE; - - attr = it->data.dwFileAttributes; - is_last = it->is_last; -#ifdef UNICODE - old_name = _wcsdup(it->data.cFileName); -#else - old_name = _strdup(it->data.cFileName); -#endif - if (!old_name) - return EINA_FALSE; - - do { - if (!FindNextFile(it->handle, &it->data)) - { - if (GetLastError() == ERROR_NO_MORE_FILES) - it->is_last = EINA_TRUE; - else - res = EINA_FALSE; - } - -#ifdef UNICODE - length = wcslen(old_name); -#else - length = strlen(old_name); -#endif - if (it->info.name_start + length + 1 >= PATH_MAX) - { - free(old_name); -#ifdef UNICODE - old_name = _wcsdup(it->data.cFileName); -#else - old_name = _strdup(it->data.cFileName); -#endif - continue; - } - - } while ((it->data.cFileName[0] == '.') && - ((it->data.cFileName[1] == '\0') || - ((it->data.cFileName[1] == '.') && (it->data.cFileName[2] == '\0')))); /* FIXME: what about UNICODE ? */ - -#ifdef UNICODE - cname = evil_wchar_to_char(old_name); - if (!cname) - return EINA_FALSE; -#else - cname = old_name; -#endif - - memcpy(it->info.path + it->info.name_start, cname, length); - it->info.name_length = length; - it->info.path_length = it->info.name_start + length; - it->info.path[it->info.path_length] = '\0'; - - if (attr & FILE_ATTRIBUTE_DIRECTORY) - it->info.type = EINA_FILE_DIR; - else if (attr & FILE_ATTRIBUTE_REPARSE_POINT) - it->info.type = EINA_FILE_LNK; - else if (attr & (FILE_ATTRIBUTE_ARCHIVE | - FILE_ATTRIBUTE_COMPRESSED | - FILE_ATTRIBUTE_COMPRESSED | - FILE_ATTRIBUTE_HIDDEN | - FILE_ATTRIBUTE_NORMAL | - FILE_ATTRIBUTE_SPARSE_FILE | - FILE_ATTRIBUTE_TEMPORARY)) - it->info.type = EINA_FILE_REG; - else - it->info.type = EINA_FILE_UNKNOWN; - - *data = &it->info; - -#ifdef UNICODE - free(cname); -#endif - - free(old_name); - - if (is_last) - res = EINA_FALSE; - - return res; -} - -static HANDLE -_eina_file_win32_direct_ls_iterator_container(Eina_File_Direct_Iterator *it) -{ - return it->handle; -} - -static void -_eina_file_win32_direct_ls_iterator_free(Eina_File_Direct_Iterator *it) -{ - if (it->handle != INVALID_HANDLE_VALUE) - FindClose(it->handle); - - EINA_MAGIC_SET(&it->iterator, 0); - free(it); -} - -static void -_eina_file_real_close(Eina_File *file) -{ - eina_hash_free(file->rmap); - eina_hash_free(file->map); - - if (file->global_map != MAP_FAILED) - UnmapViewOfFile(file->global_map); - - CloseHandle(file->fm); - CloseHandle(file->handle); - - eina_stringshare_del(file->filename); - - free(file); -} - -static void -_eina_file_map_close(Eina_File_Map *map) -{ - if (map->map != MAP_FAILED) - UnmapViewOfFile(map->map); - free(map); -} - -static unsigned int -_eina_file_map_key_length(const void *key __UNUSED__) -{ - return sizeof (unsigned long int) * 2; -} - -static int -_eina_file_map_key_cmp(const unsigned long int *key1, int key1_length __UNUSED__, - const unsigned long int *key2, int key2_length __UNUSED__) -{ - if (key1[0] - key2[0] == 0) return key1[1] - key2[1]; - return key1[0] - key2[0]; -} - -static int -_eina_file_map_key_hash(const unsigned long int *key, int key_length __UNUSED__) -{ - return eina_hash_int64(&key[0], sizeof (unsigned long int)) - ^ eina_hash_int64(&key[1], sizeof (unsigned long int)); -} - -Eina_Bool -eina_file_init(void) -{ - _eina_file_log_dom = eina_log_domain_register("eina_file", - EINA_LOG_COLOR_DEFAULT); - if (_eina_file_log_dom < 0) - { - EINA_LOG_ERR("Could not register log domain: eina_file"); - return EINA_FALSE; - } - - _eina_file_cache = eina_hash_string_djb2_new(EINA_FREE_CB(_eina_file_real_close)); - if (!_eina_file_cache) - { - ERR("Could not create cache."); - eina_log_domain_unregister(_eina_file_log_dom); - _eina_file_log_dom = -1; - return EINA_FALSE; - } - - return EINA_TRUE; -} - -Eina_Bool -eina_file_shutdown(void) -{ - Eina_File *f; - Eina_List *l; - - EINA_LIST_FREE(_eina_file_cache_delete, f) - _eina_file_real_close(f); - - EINA_LIST_FOREACH(_eina_file_cache_lru, l, f) - eina_hash_del(_eina_file_cache, f->filename, f); - - if (eina_hash_population(_eina_file_cache) > 0) - { - Eina_Iterator *it; - const char *key; - - it = eina_hash_iterator_key_new(_eina_file_cache); - EINA_ITERATOR_FOREACH(it, key) - ERR("File [%s] still open !", key); - eina_iterator_free(it); - } - - eina_hash_free(_eina_file_cache); - - eina_log_domain_unregister(_eina_file_log_dom); - _eina_file_log_dom = -1; - return EINA_TRUE; -} - - -/** - * @endcond - */ - -/*============================================================================* - * Global * - *============================================================================*/ - -/*============================================================================* - * API * - *============================================================================*/ - -EAPI Eina_Bool -eina_file_dir_list(const char *dir, - Eina_Bool recursive, - Eina_File_Dir_List_Cb cb, - void *data) -{ - WIN32_FIND_DATA file; - HANDLE h; - char *new_dir; - - EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(dir, EINA_FALSE); - EINA_SAFETY_ON_TRUE_RETURN_VAL(dir[0] == '\0', EINA_FALSE); - - if (!_eina_file_win32_is_dir(dir)) - return EINA_FALSE; - - new_dir = _eina_file_win32_dir_new(dir); - if (!new_dir) - return EINA_FALSE; - - h = _eina_file_win32_first_file(new_dir, &file); - - if (h == INVALID_HANDLE_VALUE) - return EINA_FALSE; - - do - { - char *filename; - -# ifdef UNICODE - filename = evil_wchar_to_char(file.cFileName); -# else - filename = file.cFileName; -# endif /* ! UNICODE */ - if (!strcmp(filename, ".") || !strcmp(filename, "..")) - continue; - - cb(filename, dir, data); - - if (recursive == EINA_TRUE) - { - char *path; - - path = alloca(strlen(dir) + strlen(filename) + 2); - strcpy(path, dir); - strcat(path, "/"); - strcat(path, filename); - - if (!(file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) - continue; - - eina_file_dir_list(path, recursive, cb, data); - } - -# ifdef UNICODE - free(filename); -# endif /* UNICODE */ - - } while (FindNextFile(h, &file)); - FindClose(h); - - return EINA_TRUE; -} - -EAPI Eina_Array * -eina_file_split(char *path) -{ - Eina_Array *ea; - char *current; - size_t length; - - EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL); - - ea = eina_array_new(16); - - if (!ea) - return NULL; - - for (current = strchr(path, '\\'); - current; - path = current + 1, current = strchr(path, '\\')) - { - length = current - path; - - if (length <= 0) - continue; - - eina_array_push(ea, path); - *current = '\0'; - } - - if (*path != '\0') - eina_array_push(ea, path); - - return ea; -} - -EAPI Eina_Iterator * -eina_file_ls(const char *dir) -{ - Eina_File_Iterator *it; - char *new_dir; - size_t length; - - if (!dir || !*dir) - return NULL; - - if (!_eina_file_win32_is_dir(dir)) - return NULL; - - length = strlen(dir); - - it = calloc(1, sizeof (Eina_File_Iterator) + length); - if (!it) - return NULL; - - EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); - - new_dir = _eina_file_win32_dir_new(dir); - if (!new_dir) - goto free_it; - - it->handle = _eina_file_win32_first_file(new_dir, &it->data); - free(new_dir); - if (it->handle == INVALID_HANDLE_VALUE) - goto free_it; - - memcpy(it->dir, dir, length + 1); - if (dir[length - 1] != '\\') - it->length = length; - else - it->length = length - 1; - _eina_file_win32_backslash_change(it->dir); - - it->iterator.version = EINA_ITERATOR_VERSION; - it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_win32_ls_iterator_next); - it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_win32_ls_iterator_container); - it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_win32_ls_iterator_free); - - return &it->iterator; - - free_it: - free(it); - - return NULL; -} - -EAPI Eina_Iterator * -eina_file_direct_ls(const char *dir) -{ - Eina_File_Direct_Iterator *it; - char *new_dir; - size_t length; - - if (!dir || !*dir) - return NULL; - - length = strlen(dir); - - if (length + 12 + 2 >= MAX_PATH) - return NULL; - - it = calloc(1, sizeof(Eina_File_Direct_Iterator) + length); - if (!it) - return NULL; - - EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); - - new_dir = _eina_file_win32_dir_new(dir); - if (!new_dir) - goto free_it; - - it->handle = _eina_file_win32_first_file(new_dir, &it->data); - free(new_dir); - if (it->handle == INVALID_HANDLE_VALUE) - goto free_it; - - memcpy(it->dir, dir, length + 1); - it->length = length; - _eina_file_win32_backslash_change(it->dir); - - memcpy(it->info.path, dir, length); - if (dir[length - 1] == '\\') - it->info.name_start = length; - else - { - it->info.path[length] = '\\'; - it->info.name_start = length + 1; - } - _eina_file_win32_backslash_change(it->info.path); - - it->iterator.version = EINA_ITERATOR_VERSION; - it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_win32_direct_ls_iterator_next); - it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_win32_direct_ls_iterator_container); - it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_win32_direct_ls_iterator_free); - - return &it->iterator; - - free_it: - free(it); - - return NULL; -} - -EAPI Eina_Iterator * -eina_file_stat_ls(const char *dir) -{ - return eina_file_direct_ls(dir); -} - -EAPI Eina_File * -eina_file_open(const char *filename, Eina_Bool shared) -{ - Eina_File *file; - Eina_File *n; - HANDLE handle; - HANDLE fm; - WIN32_FILE_ATTRIBUTE_DATA fad; - ULARGE_INTEGER length; - ULARGE_INTEGER mtime; - Eina_Bool create = EINA_FALSE; - - /* FIXME: always open absolute path (need to fix filename according to current - directory) */ - - /* FIXME: how to emulate shm_open ? Just OpenFileMapping ? */ -#if 0 - if (shared) - handle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, - NULL); - else -#endif - handle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, - NULL); - - if (handle == INVALID_HANDLE_VALUE) - return NULL; - - fm = CreateFileMapping(handle, NULL, PAGE_READONLY, 0, 0, NULL); - if (!fm) - goto close_handle; - - if (!GetFileAttributesEx(filename, GetFileExInfoStandard, &fad)) - goto close_fm; - - length.u.LowPart = fad.nFileSizeLow; - length.u.HighPart = fad.nFileSizeHigh; - mtime.u.LowPart = fad.ftLastWriteTime.dwLowDateTime; - mtime.u.HighPart = fad.ftLastWriteTime.dwHighDateTime; - - file = eina_hash_find(_eina_file_cache, filename); - if (file && - (file->mtime != mtime.QuadPart || file->length != length.QuadPart)) - { - create = EINA_TRUE; - - if (file->refcount == 0) - { - _eina_file_cache_lru = eina_list_prepend(_eina_file_cache_lru, file); - eina_hash_del(_eina_file_cache, file->filename, file); - - file = NULL; - } - else if (!file->delete_me) - { - file->delete_me = EINA_TRUE; - _eina_file_cache_delete = eina_list_prepend(_eina_file_cache_delete, file); - } - } - - if (!file || create) - { - n = calloc(1, sizeof (Eina_File)); - if (!n) - goto close_fm; - - n->filename = eina_stringshare_add(filename); - n->map = eina_hash_new(EINA_KEY_LENGTH(_eina_file_map_key_length), - EINA_KEY_CMP(_eina_file_map_key_cmp), - EINA_KEY_HASH(_eina_file_map_key_hash), - EINA_FREE_CB(_eina_file_map_close), - 3); - n->rmap = eina_hash_pointer_new(NULL); - n->global_map = MAP_FAILED; - n->length = length.QuadPart; - n->mtime = mtime.QuadPart; - n->refcount = 0; - n->handle = handle; - n->fm = fm; - n->shared = shared; - n->delete_me = EINA_FALSE; - - eina_hash_set(_eina_file_cache, filename, n); - } - else - { - CloseHandle(fm); - CloseHandle(handle); - - n = file; - - if (n->refcount == 0) - _eina_file_cache_lru = eina_list_remove(_eina_file_cache_lru, n); - } - - n->refcount++; - - return n; - - close_fm: - CloseHandle(fm); - close_handle: - CloseHandle(handle); - - return NULL; -} - -EAPI void -eina_file_close(Eina_File *file) -{ - file->refcount--; - - if (file->refcount != 0) return ; - - if (file->delete_me) - { - _eina_file_cache_delete = eina_list_remove(_eina_file_cache_delete, file); - _eina_file_real_close(file); - } - else - { - _eina_file_cache_lru = eina_list_prepend(_eina_file_cache_lru, file); - } -} - -EAPI size_t -eina_file_size_get(Eina_File *file) -{ - return file->length; -} - -EAPI time_t -eina_file_mtime_get(Eina_File *file) -{ - return file->mtime; -} - -EAPI const char * -eina_file_filename_get(Eina_File *file) -{ - return file->filename; -} - -EAPI void * -eina_file_map_all(Eina_File *file, Eina_File_Populate rule __UNUSED__) -{ - if (file->global_map == MAP_FAILED) - { - void *data; - - data = MapViewOfFile(file->fm, FILE_MAP_READ, - 0, 0, file->length); - if (!data) - file->global_map = MAP_FAILED; - else - file->global_map = data; - } - - if (file->global_map != MAP_FAILED) - { - file->global_refcount++; - return file->global_map; - } - - return NULL; -} - -EAPI void * -eina_file_map_new(Eina_File *file, Eina_File_Populate rule, - unsigned long int offset, unsigned long int length) -{ - Eina_File_Map *map; - unsigned long int key[2]; - - if (offset > file->length) - return NULL; - if (offset + length > file->length) - return NULL; - - if (offset == 0 && length == file->length) - return eina_file_map_all(file, rule); - - key[0] = offset; - key[1] = length; - - map = eina_hash_find(file->map, &key); - if (!map) - { - void *data; - - map = malloc(sizeof (Eina_File_Map)); - if (!map) return NULL; - - data = MapViewOfFile(file->fm, FILE_MAP_READ, - offset & 0xffff0000, - offset & 0x0000ffff, - length); - if (!data) - map->map = MAP_FAILED; - else - map->map = data; - - map->offset = offset; - map->length = length; - map->refcount = 0; - - if (map->map == MAP_FAILED) - { - free(map); - return NULL; - } - - eina_hash_add(file->map, &key, map); - eina_hash_direct_add(file->rmap, map->map, map); - } - - map->refcount++; - - return map->map; -} - -EAPI void -eina_file_map_free(Eina_File *file, void *map) -{ - if (file->global_map == map) - { - file->global_refcount--; - - if (file->global_refcount > 0) return ; - - /* FIXME: are we sure that file->global_map != MAP_FAILED ? */ - if (file->global_map != MAP_FAILED) - UnmapViewOfFile(file->global_map); - file->global_map = MAP_FAILED; - } - else - { - Eina_File_Map *em; - unsigned long int key[2]; - - em = eina_hash_find(file->rmap, &map); - if (!em) return ; - - em->refcount--; - - if (em->refcount > 0) return ; - - key[0] = em->offset; - key[1] = em->length; - - eina_hash_del(file->rmap, &map, em); - eina_hash_del(file->map, &key, em); - } -} +/* EINA - EFL data type library + * Copyright (C) 2010 Vincent Torri + * + * 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 + +#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 +#include + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN + +#include + +#include "eina_config.h" +#include "eina_private.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_file.h" +#include "eina_stringshare.h" +#include "eina_hash.h" +#include "eina_list.h" +#include "eina_lock.h" +#include "eina_log.h" + +/*============================================================================* + * Local * + *============================================================================*/ + +/** + * @cond LOCAL + */ + +#ifndef EINA_LOG_COLOR_DEFAULT +#define EINA_LOG_COLOR_DEFAULT EINA_COLOR_CYAN +#endif + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_eina_file_log_dom, __VA_ARGS__) + +#ifdef WRN +#undef WRN +#endif +#define WRN(...) EINA_LOG_DOM_WARN(_eina_file_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_file_log_dom, __VA_ARGS__) + +#ifdef MAP_FAILED +# undef MAP_FAILED +#endif +#define MAP_FAILED ((void *)-1) + +typedef struct _Eina_File_Iterator Eina_File_Iterator; +typedef struct _Eina_File_Direct_Iterator Eina_File_Direct_Iterator; +typedef struct _Eina_File_Map Eina_File_Map; + +struct _Eina_File_Iterator +{ + Eina_Iterator iterator; + + WIN32_FIND_DATA data; + HANDLE handle; + size_t length; + Eina_Bool is_last : 1; + + char dir[1]; +}; + +struct _Eina_File_Direct_Iterator +{ + Eina_Iterator iterator; + + WIN32_FIND_DATA data; + HANDLE handle; + size_t length; + Eina_Bool is_last : 1; + + Eina_File_Direct_Info info; + + char dir[1]; +}; + +struct _Eina_File +{ + const char *filename; + + Eina_Hash *map; + Eina_Hash *rmap; + void *global_map; + + Eina_Lock lock; + + ULONGLONG length; + ULONGLONG mtime; + + int refcount; + int global_refcount; + + HANDLE handle; + HANDLE fm; + + Eina_Bool shared : 1; + Eina_Bool delete_me : 1; +}; + +struct _Eina_File_Map +{ + void *map; + + unsigned long int offset; + unsigned long int length; + + int refcount; +}; + +static Eina_Hash *_eina_file_cache = NULL; +static Eina_Lock _eina_file_lock_cache; + +static int _eina_file_log_dom = -1; + +static void +_eina_file_win32_backslash_change(char *dir) +{ + char *tmp; + + tmp = dir; + while (*tmp) + { + if (*tmp == '/') *tmp = '\\'; + tmp++; + } +} + +static Eina_Bool +_eina_file_win32_is_dir(const char *dir) +{ +#ifdef UNICODE + wchar_t *wdir = NULL; +#endif + DWORD attr; + + /* check if it's a directory */ +#ifdef UNICODE + wdir = evil_char_to_wchar(dir); + if (!wdir) + return EINA_FALSE; + + attr = GetFileAttributes(wdir); + free(wdir); +#else + attr = GetFileAttributes(dir); +#endif + + if (attr == 0xFFFFFFFF) + return EINA_FALSE; + + if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) + return EINA_FALSE; + + return EINA_TRUE; +} + +static char * +_eina_file_win32_dir_new(const char *dir) +{ + char *new_dir; + size_t length; + + length = strlen(dir); + + new_dir = (char *)malloc(sizeof(char) * length + 5); + if (!new_dir) + return NULL; + + memcpy(new_dir, dir, length); + memcpy(new_dir + length, "\\*.*", 5); + _eina_file_win32_backslash_change(new_dir); + + return new_dir; +} + +static HANDLE +_eina_file_win32_first_file(const char *dir, WIN32_FIND_DATA *fd) +{ + HANDLE h; +#ifdef UNICODE + wchar_t *wdir = NULL; + + wdir = evil_char_to_wchar(dir); + if (!wdir) + return NULL; + + h = FindFirstFile(wdir, fd); + free(wdir); +#else + h = FindFirstFile(dir, fd); +#endif + + if (!h) + return NULL; + + while ((fd->cFileName[0] == '.') && + ((fd->cFileName[1] == '\0') || + ((fd->cFileName[1] == '.') && (fd->cFileName[2] == '\0')))) + { + if (!FindNextFile(h, fd)) + return NULL; + } + + return h; +} + +static Eina_Bool +_eina_file_win32_ls_iterator_next(Eina_File_Iterator *it, void **data) +{ +#ifdef UNICODE + wchar_t *old_name; +#else + char *old_name; +#endif + char *name; + char *cname; + size_t length; + Eina_Bool is_last; + Eina_Bool res = EINA_TRUE; + + if (it->handle == INVALID_HANDLE_VALUE) + return EINA_FALSE; + + is_last = it->is_last; +#ifdef UNICODE + old_name = _wcsdup(it->data.cFileName); +#else + old_name = _strdup(it->data.cFileName); +#endif + if (!old_name) + return EINA_FALSE; + + do { + if (!FindNextFile(it->handle, &it->data)) + { + if (GetLastError() == ERROR_NO_MORE_FILES) + it->is_last = EINA_TRUE; + else + res = EINA_FALSE; + } + } while ((it->data.cFileName[0] == '.') && + ((it->data.cFileName[1] == '\0') || + ((it->data.cFileName[1] == '.') && (it->data.cFileName[2] == '\0')))); /* FIXME: what about UNICODE ? */ + +#ifdef UNICODE + cname = evil_wchar_to_char(old_name); + if (!cname) + return EINA_FALSE; +#else + cname = old_name; +#endif + + length = strlen(cname); + name = alloca(length + 2 + it->length); + + memcpy(name, it->dir, it->length); + memcpy(name + it->length, "\\", 1); + memcpy(name + it->length + 1, cname, length + 1); + + *data = (char *)eina_stringshare_add(name); + +#ifdef UNICODE + free(cname); +#endif + free(old_name); + + if (is_last) + res = EINA_FALSE; + + return res; +} + +static HANDLE +_eina_file_win32_ls_iterator_container(Eina_File_Iterator *it) +{ + return it->handle; +} + +static void +_eina_file_win32_ls_iterator_free(Eina_File_Iterator *it) +{ + if (it->handle != INVALID_HANDLE_VALUE) + FindClose(it->handle); + + EINA_MAGIC_SET(&it->iterator, 0); + free(it); +} + +static Eina_Bool +_eina_file_win32_direct_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data) +{ +#ifdef UNICODE + wchar_t *old_name; +#else + char *old_name; +#endif + char *cname; + size_t length; + DWORD attr; + Eina_Bool is_last; + Eina_Bool res = EINA_TRUE; + + if (it->handle == INVALID_HANDLE_VALUE) + return EINA_FALSE; + + attr = it->data.dwFileAttributes; + is_last = it->is_last; +#ifdef UNICODE + old_name = _wcsdup(it->data.cFileName); +#else + old_name = _strdup(it->data.cFileName); +#endif + if (!old_name) + return EINA_FALSE; + + do { + if (!FindNextFile(it->handle, &it->data)) + { + if (GetLastError() == ERROR_NO_MORE_FILES) + it->is_last = EINA_TRUE; + else + res = EINA_FALSE; + } + +#ifdef UNICODE + length = wcslen(old_name); +#else + length = strlen(old_name); +#endif + if (it->info.name_start + length + 1 >= PATH_MAX) + { + free(old_name); +#ifdef UNICODE + old_name = _wcsdup(it->data.cFileName); +#else + old_name = _strdup(it->data.cFileName); +#endif + continue; + } + + } while ((it->data.cFileName[0] == '.') && + ((it->data.cFileName[1] == '\0') || + ((it->data.cFileName[1] == '.') && (it->data.cFileName[2] == '\0')))); /* FIXME: what about UNICODE ? */ + +#ifdef UNICODE + cname = evil_wchar_to_char(old_name); + if (!cname) + return EINA_FALSE; +#else + cname = old_name; +#endif + + memcpy(it->info.path + it->info.name_start, cname, length); + it->info.name_length = length; + it->info.path_length = it->info.name_start + length; + it->info.path[it->info.path_length] = '\0'; + + if (attr & FILE_ATTRIBUTE_DIRECTORY) + it->info.type = EINA_FILE_DIR; + else if (attr & FILE_ATTRIBUTE_REPARSE_POINT) + it->info.type = EINA_FILE_LNK; + else if (attr & (FILE_ATTRIBUTE_ARCHIVE | + FILE_ATTRIBUTE_COMPRESSED | + FILE_ATTRIBUTE_COMPRESSED | + FILE_ATTRIBUTE_HIDDEN | + FILE_ATTRIBUTE_NORMAL | + FILE_ATTRIBUTE_SPARSE_FILE | + FILE_ATTRIBUTE_TEMPORARY)) + it->info.type = EINA_FILE_REG; + else + it->info.type = EINA_FILE_UNKNOWN; + + *data = &it->info; + +#ifdef UNICODE + free(cname); +#endif + + free(old_name); + + if (is_last) + res = EINA_FALSE; + + return res; +} + +static HANDLE +_eina_file_win32_direct_ls_iterator_container(Eina_File_Direct_Iterator *it) +{ + return it->handle; +} + +static void +_eina_file_win32_direct_ls_iterator_free(Eina_File_Direct_Iterator *it) +{ + if (it->handle != INVALID_HANDLE_VALUE) + FindClose(it->handle); + + EINA_MAGIC_SET(&it->iterator, 0); + free(it); +} + +static void +_eina_file_real_close(Eina_File *file) +{ + eina_hash_free(file->rmap); + eina_hash_free(file->map); + + if (file->global_map != MAP_FAILED) + UnmapViewOfFile(file->global_map); + + CloseHandle(file->fm); + CloseHandle(file->handle); + + free(file); +} + +static void +_eina_file_map_close(Eina_File_Map *map) +{ + if (map->map != MAP_FAILED) + UnmapViewOfFile(map->map); + free(map); +} + +static unsigned int +_eina_file_map_key_length(const void *key __UNUSED__) +{ + return sizeof (unsigned long int) * 2; +} + +static int +_eina_file_map_key_cmp(const unsigned long int *key1, int key1_length __UNUSED__, + const unsigned long int *key2, int key2_length __UNUSED__) +{ + if (key1[0] - key2[0] == 0) return key1[1] - key2[1]; + return key1[0] - key2[0]; +} + +static int +_eina_file_map_key_hash(const unsigned long int *key, int key_length __UNUSED__) +{ + return eina_hash_int64(&key[0], sizeof (unsigned long int)) + ^ eina_hash_int64(&key[1], sizeof (unsigned long int)); +} + +static char * +_eina_file_win32_escape(const char *path, size_t *length) +{ + char *result = strdup(path ? path : ""); + char *p = result; + char *q = result; + size_t len; + + if (!result) + return NULL; + + if (length) len = *length; + else len = strlen(result); + + while ((p = strchr(p, '/'))) + { + // remove double `/' + if (p[1] == '/') + { + memmove(p, p + 1, --len - (p - result)); + result[len] = '\0'; + } + else + if (p[1] == '.' + && p[2] == '.') + { + // remove `/../' + if (p[3] == '/') + { + char tmp; + + len -= p + 3 - q; + memmove(q, p + 3, len - (q - result)); + result[len] = '\0'; + p = q; + + /* Update q correctly. */ + tmp = *p; + *p = '\0'; + q = strrchr(result, '/'); + if (!q) q = result; + *p = tmp; + } + else + // remove '/..$' + if (p[3] == '\0') + { + len -= p + 2 - q; + result[len] = '\0'; + q = p; + ++p; + } + else + { + q = p; + ++p; + } + } + else + { + q = p; + ++p; + } + } + + if (length) + *length = len; + + return result; +} + + +/** + * @endcond + */ + +/*============================================================================* + * Global * + *============================================================================*/ + +Eina_Bool +eina_file_init(void) +{ + _eina_file_log_dom = eina_log_domain_register("eina_file", + EINA_LOG_COLOR_DEFAULT); + if (_eina_file_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_file"); + return EINA_FALSE; + } + + _eina_file_cache = eina_hash_string_djb2_new(NULL); + if (!_eina_file_cache) + { + ERR("Could not create cache."); + eina_log_domain_unregister(_eina_file_log_dom); + _eina_file_log_dom = -1; + return EINA_FALSE; + } + + eina_lock_new(&_eina_file_lock_cache); + + return EINA_TRUE; +} + +Eina_Bool +eina_file_shutdown(void) +{ + if (eina_hash_population(_eina_file_cache) > 0) + { + Eina_Iterator *it; + const char *key; + + it = eina_hash_iterator_key_new(_eina_file_cache); + EINA_ITERATOR_FOREACH(it, key) + ERR("File [%s] still open !", key); + eina_iterator_free(it); + } + + eina_hash_free(_eina_file_cache); + + eina_lock_free(&_eina_file_lock_cache); + + eina_log_domain_unregister(_eina_file_log_dom); + _eina_file_log_dom = -1; + return EINA_TRUE; +} + +/*============================================================================* + * API * + *============================================================================*/ + + +EAPI char * +eina_file_path_sanitize(const char *path) +{ + char *result = NULL; + size_t len; + + if (!path) return NULL; + + len = strlen(path); + if (len < 3) return NULL; + + if (!evil_path_is_absolute(path)) + { + DWORD l; + + l = GetCurrentDirectory(0, NULL); + if (l > 0) + { + char *cwd; + DWORD l2; + + cwd = alloca(sizeof(char) * (l + 1)); + l2 = GetCurrentDirectory(l + 1, cwd); + if (l2 == l) + { + char *tmp; + + len += l + 2; + tmp = alloca(sizeof (char) * len); + snprintf(tmp, len, "%s/%s", cwd, path); + tmp[len - 1] = '\0'; + result = tmp; + } + } + } + + return _eina_file_win32_escape(result ? result : path, &len); +} + +EAPI Eina_Bool +eina_file_dir_list(const char *dir, + Eina_Bool recursive, + Eina_File_Dir_List_Cb cb, + void *data) +{ + WIN32_FIND_DATA file; + HANDLE h; + char *new_dir; + + EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(dir, EINA_FALSE); + EINA_SAFETY_ON_TRUE_RETURN_VAL(dir[0] == '\0', EINA_FALSE); + + if (!_eina_file_win32_is_dir(dir)) + return EINA_FALSE; + + new_dir = _eina_file_win32_dir_new(dir); + if (!new_dir) + return EINA_FALSE; + + h = _eina_file_win32_first_file(new_dir, &file); + + if (h == INVALID_HANDLE_VALUE) + return EINA_FALSE; + + do + { + char *filename; + +# ifdef UNICODE + filename = evil_wchar_to_char(file.cFileName); +# else + filename = file.cFileName; +# endif /* ! UNICODE */ + if (!strcmp(filename, ".") || !strcmp(filename, "..")) + continue; + + cb(filename, dir, data); + + if (recursive == EINA_TRUE) + { + char *path; + + path = alloca(strlen(dir) + strlen(filename) + 2); + strcpy(path, dir); + strcat(path, "/"); + strcat(path, filename); + + if (!(file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + continue; + + eina_file_dir_list(path, recursive, cb, data); + } + +# ifdef UNICODE + free(filename); +# endif /* UNICODE */ + + } while (FindNextFile(h, &file)); + FindClose(h); + + return EINA_TRUE; +} + +EAPI Eina_Array * +eina_file_split(char *path) +{ + Eina_Array *ea; + char *current; + size_t length; + + EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL); + + ea = eina_array_new(16); + + if (!ea) + return NULL; + + for (current = strchr(path, '\\'); + current; + path = current + 1, current = strchr(path, '\\')) + { + length = current - path; + + if (length <= 0) + continue; + + eina_array_push(ea, path); + *current = '\0'; + } + + if (*path != '\0') + eina_array_push(ea, path); + + return ea; +} + +EAPI Eina_Iterator * +eina_file_ls(const char *dir) +{ + Eina_File_Iterator *it; + char *new_dir; + size_t length; + + EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL); + + if (!dir || !*dir) + return NULL; + + if (!_eina_file_win32_is_dir(dir)) + return NULL; + + length = strlen(dir); + + it = calloc(1, sizeof (Eina_File_Iterator) + length); + if (!it) + return NULL; + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + new_dir = _eina_file_win32_dir_new(dir); + if (!new_dir) + goto free_it; + + it->handle = _eina_file_win32_first_file(new_dir, &it->data); + free(new_dir); + if (it->handle == INVALID_HANDLE_VALUE) + goto free_it; + + memcpy(it->dir, dir, length + 1); + if (dir[length - 1] != '\\') + it->length = length; + else + it->length = length - 1; + _eina_file_win32_backslash_change(it->dir); + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_win32_ls_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_win32_ls_iterator_container); + it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_win32_ls_iterator_free); + + return &it->iterator; + + free_it: + free(it); + + return NULL; +} + +EAPI Eina_Iterator * +eina_file_direct_ls(const char *dir) +{ + Eina_File_Direct_Iterator *it; + char *new_dir; + size_t length; + + EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL); + + if (!dir || !*dir) + return NULL; + + length = strlen(dir); + + if (length + 12 + 2 >= MAX_PATH) + return NULL; + + it = calloc(1, sizeof(Eina_File_Direct_Iterator) + length); + if (!it) + return NULL; + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + new_dir = _eina_file_win32_dir_new(dir); + if (!new_dir) + goto free_it; + + it->handle = _eina_file_win32_first_file(new_dir, &it->data); + free(new_dir); + if (it->handle == INVALID_HANDLE_VALUE) + goto free_it; + + memcpy(it->dir, dir, length + 1); + it->length = length; + _eina_file_win32_backslash_change(it->dir); + + memcpy(it->info.path, dir, length); + if (dir[length - 1] == '\\') + it->info.name_start = length; + else + { + it->info.path[length] = '\\'; + it->info.name_start = length + 1; + } + _eina_file_win32_backslash_change(it->info.path); + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_win32_direct_ls_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_win32_direct_ls_iterator_container); + it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_win32_direct_ls_iterator_free); + + return &it->iterator; + + free_it: + free(it); + + return NULL; +} + +EAPI Eina_Iterator * +eina_file_stat_ls(const char *dir) +{ + return eina_file_direct_ls(dir); +} + +EAPI Eina_File * +eina_file_open(const char *path, Eina_Bool shared) +{ + Eina_File *file; + Eina_File *n; + char *filename; + HANDLE handle; + HANDLE fm; + WIN32_FILE_ATTRIBUTE_DATA fad; + ULARGE_INTEGER length; + ULARGE_INTEGER mtime; + + EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL); + + filename = eina_file_path_sanitize(path); + if (!filename) return NULL; + + /* FIXME: how to emulate shm_open ? Just OpenFileMapping ? */ +#if 0 + if (shared) + handle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, + NULL); + else +#endif + handle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, + NULL); + + if (handle == INVALID_HANDLE_VALUE) + return NULL; + + fm = CreateFileMapping(handle, NULL, PAGE_READONLY, 0, 0, NULL); + if (!fm) + goto close_handle; + + if (!GetFileAttributesEx(filename, GetFileExInfoStandard, &fad)) + goto close_fm; + + length.u.LowPart = fad.nFileSizeLow; + length.u.HighPart = fad.nFileSizeHigh; + mtime.u.LowPart = fad.ftLastWriteTime.dwLowDateTime; + mtime.u.HighPart = fad.ftLastWriteTime.dwHighDateTime; + + eina_lock_take(&_eina_file_lock_cache); + + file = eina_hash_find(_eina_file_cache, filename); + if (file && + (file->mtime != mtime.QuadPart || file->length != length.QuadPart)) + { + file->delete_me = EINA_TRUE; + eina_hash_del(_eina_file_cache, file->filename, file); + _eina_file_real_close(file); + file = NULL; + } + + if (!file) + { + n = malloc(sizeof (Eina_File) + strlen(filename) + 1); + if (!n) + { + eina_lock_release(&_eina_file_lock_cache); + goto close_fm; + } + + n->filename = (char*) (n + 1); + strcpy((char*) n->filename, filename); + n->map = eina_hash_new(EINA_KEY_LENGTH(_eina_file_map_key_length), + EINA_KEY_CMP(_eina_file_map_key_cmp), + EINA_KEY_HASH(_eina_file_map_key_hash), + EINA_FREE_CB(_eina_file_map_close), + 3); + n->rmap = eina_hash_pointer_new(NULL); + n->global_map = MAP_FAILED; + n->global_refcount = 0; + n->length = length.QuadPart; + n->mtime = mtime.QuadPart; + n->refcount = 0; + n->handle = handle; + n->fm = fm; + n->shared = shared; + n->delete_me = EINA_FALSE; + eina_lock_new(&n->lock); + eina_hash_direct_add(_eina_file_cache, n->filename, n); + } + else + { + CloseHandle(fm); + CloseHandle(handle); + + n = file; + } + eina_lock_take(&n->lock); + n->refcount++; + eina_lock_release(&n->lock); + + eina_lock_release(&_eina_file_lock_cache); + + free(filename); + + return n; + + close_fm: + CloseHandle(fm); + close_handle: + CloseHandle(handle); + + return NULL; +} + +EAPI void +eina_file_close(Eina_File *file) +{ + EINA_SAFETY_ON_NULL_RETURN(file); + + eina_lock_take(&file->lock); + file->refcount--; + eina_lock_release(&file->lock); + + if (file->refcount != 0) return ; + eina_lock_take(&_eina_file_lock_cache); + + eina_hash_del(_eina_file_cache, file->filename, file); + _eina_file_real_close(file); + + eina_lock_release(&_eina_file_lock_cache); +} + +EAPI size_t +eina_file_size_get(Eina_File *file) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0); + return file->length; +} + +EAPI time_t +eina_file_mtime_get(Eina_File *file) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0); + return file->mtime; +} + +EAPI const char * +eina_file_filename_get(Eina_File *file) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); + return file->filename; +} + +EAPI Eina_Iterator *eina_file_xattr_get(Eina_File *file __UNUSED__) +{ + return NULL; +} + +EAPI Eina_Iterator *eina_file_xattr_value_get(Eina_File *file __UNUSED__) +{ + return NULL; +} + +EAPI void * +eina_file_map_all(Eina_File *file, Eina_File_Populate rule __UNUSED__) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); + + eina_lock_take(&file->lock); + if (file->global_map == MAP_FAILED) + { + void *data; + + data = MapViewOfFile(file->fm, FILE_MAP_READ, + 0, 0, file->length); + if (!data) + file->global_map = MAP_FAILED; + else + file->global_map = data; + } + + if (file->global_map != MAP_FAILED) + { + file->global_refcount++; + return file->global_map; + } + + eina_lock_release(&file->lock); + return NULL; +} + +EAPI void * +eina_file_map_new(Eina_File *file, Eina_File_Populate rule, + unsigned long int offset, unsigned long int length) +{ + Eina_File_Map *map; + unsigned long int key[2]; + + EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); + + if (offset > file->length) + return NULL; + if (offset + length > file->length) + return NULL; + + if (offset == 0 && length == file->length) + return eina_file_map_all(file, rule); + + key[0] = offset; + key[1] = length; + + eina_lock_take(&file->lock); + + map = eina_hash_find(file->map, &key); + if (!map) + { + void *data; + + map = malloc(sizeof (Eina_File_Map)); + if (!map) + { + eina_lock_release(&file->lock); + return NULL; + } + + data = MapViewOfFile(file->fm, FILE_MAP_READ, + offset & 0xffff0000, + offset & 0x0000ffff, + length); + if (!data) + map->map = MAP_FAILED; + else + map->map = data; + + map->offset = offset; + map->length = length; + map->refcount = 0; + + if (map->map == MAP_FAILED) + { + free(map); + eina_lock_release(&file->lock); + return NULL; + } + + eina_hash_add(file->map, &key, map); + eina_hash_direct_add(file->rmap, map->map, map); + } + + map->refcount++; + + eina_lock_release(&file->lock); + + return map->map; +} + +EAPI void +eina_file_map_free(Eina_File *file, void *map) +{ + EINA_SAFETY_ON_NULL_RETURN(file); + + eina_lock_take(&file->lock); + + if (file->global_map == map) + { + file->global_refcount--; + + if (file->global_refcount > 0) goto on_exit; + + UnmapViewOfFile(file->global_map); + file->global_map = MAP_FAILED; + } + else + { + Eina_File_Map *em; + unsigned long int key[2]; + + em = eina_hash_find(file->rmap, &map); + if (!em) goto on_exit; + + em->refcount--; + + if (em->refcount > 0) goto on_exit; + + key[0] = em->offset; + key[1] = em->length; + + eina_hash_del(file->rmap, &map, em); + eina_hash_del(file->map, &key, em); + } + + on_exit: + eina_lock_release(&file->lock); +} + +EAPI int +eina_file_statat(void *container __UNUSED__, Eina_File_Direct_Info *info, Eina_Stat *st) +{ + struct __stat64 buf; + + EINA_SAFETY_ON_NULL_RETURN_VAL(info, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(st, -1); + + if (stat64(info->path, &buf)) + { + if (info->type != EINA_FILE_LNK) + info->type = EINA_FILE_UNKNOWN; + return -1; + } + + if (info->type == EINA_FILE_UNKNOWN) + { + if (S_ISREG(buf.st_mode)) + info->type = EINA_FILE_REG; + else if (S_ISDIR(buf.st_mode)) + info->type = EINA_FILE_DIR; + else + info->type = EINA_FILE_UNKNOWN; + } + + st->dev = buf.st_dev; + st->ino = buf.st_ino; + st->mode = buf.st_mode; + st->nlink = buf.st_nlink; + st->uid = buf.st_uid; + st->gid = buf.st_gid; + st->rdev = buf.st_rdev; + st->size = buf.st_size; + st->blksize = 0; + st->blocks = 0; + st->atime = buf.st_atime; + st->mtime = buf.st_mtime; + st->ctime = buf.st_ctime; + st->atimensec = 0; + st->mtimensec = 0; + st->ctimensec = 0; + + return 0; +} diff --git a/libraries/eina/src/lib/eina_inlist.c b/libraries/eina/src/lib/eina_inlist.c index 75a2cc1..c80f87b 100644 --- a/libraries/eina/src/lib/eina_inlist.c +++ b/libraries/eina/src/lib/eina_inlist.c @@ -430,6 +430,8 @@ eina_inlist_find(Eina_Inlist *list, Eina_Inlist *item) { Eina_Inlist *l; + EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL); + for (l = list; l; l = l->next) { if (l == item) return item; @@ -559,6 +561,9 @@ eina_inlist_sorted_insert(Eina_Inlist *list, int cur = 0; int count; + EINA_SAFETY_ON_NULL_RETURN_VAL(item, list); + EINA_SAFETY_ON_NULL_RETURN_VAL(func, list); + if (!list) return eina_inlist_append(NULL, item); if (!list->next) diff --git a/libraries/eina/src/lib/eina_list.c b/libraries/eina/src/lib/eina_list.c index d45cffd..c85855f 100644 --- a/libraries/eina/src/lib/eina_list.c +++ b/libraries/eina/src/lib/eina_list.c @@ -1026,7 +1026,7 @@ eina_list_clone(const Eina_List *list) } EAPI Eina_List * -eina_list_sort(Eina_List *list, unsigned int size, Eina_Compare_Cb func) +eina_list_sort(Eina_List *list, unsigned int limit, Eina_Compare_Cb func) { unsigned int i = 0; unsigned int n = 0; @@ -1040,14 +1040,14 @@ eina_list_sort(Eina_List *list, unsigned int size, Eina_Compare_Cb func) EINA_MAGIC_CHECK_LIST(list, NULL); - /* if the caller specified an invalid size, sort the whole list */ - if ((size == 0) || - (size > list->accounting->count)) - size = list->accounting->count; + /* if the caller specified an invalid limit, sort the whole list */ + if ((limit == 0) || + (limit > list->accounting->count)) + limit = list->accounting->count; - if (size != list->accounting->count) + if (limit != list->accounting->count) { - unsort = eina_list_nth_list(list, size); + unsort = eina_list_nth_list(list, limit); if (unsort) unsort->prev->next = NULL; } @@ -1172,6 +1172,7 @@ eina_list_split_list(Eina_List *list, Eina_List *relative, Eina_List **right) next->prev = NULL; next->accounting = _eina_list_mempool_accounting_new(next); next->accounting->last = list->accounting->last; + next->accounting->count = 0; *right = next; itr = next; diff --git a/libraries/eina/src/lib/eina_magic.c b/libraries/eina/src/lib/eina_magic.c index d1f71cc..a42db2d 100644 --- a/libraries/eina/src/lib/eina_magic.c +++ b/libraries/eina/src/lib/eina_magic.c @@ -102,13 +102,8 @@ _eina_magic_strings_alloc(void) tmp = realloc(_eina_magic_strings, sizeof(Eina_Magic_String) * size); if (!tmp) { -#ifdef _WIN32 - ERR("could not realloc magic_strings from %Iu to %Iu buckets.", - _eina_magic_strings_allocated, size); -#else ERR("could not realloc magic_strings from %zu to %zu buckets.", _eina_magic_strings_allocated, size); -#endif return NULL; } diff --git a/libraries/eina/src/lib/eina_main.c b/libraries/eina/src/lib/eina_main.c index 79f8a36..f233929 100644 --- a/libraries/eina/src/lib/eina_main.c +++ b/libraries/eina/src/lib/eina_main.c @@ -69,6 +69,7 @@ #include "eina_inlist.h" #include "eina_inarray.h" #include "eina_value.h" +#include "eina_model.h" /*============================================================================* * Local * @@ -153,6 +154,7 @@ EAPI Eina_Inlist *_eina_tracking = NULL; S(file); S(prefix); S(value); + S(model); #undef S struct eina_desc_setup @@ -189,7 +191,8 @@ static const struct eina_desc_setup _eina_desc_setup[] = { S(simple_xml), S(file), S(prefix), - S(value) + S(value), + S(model) #undef S }; static const size_t _eina_desc_setup_len = sizeof(_eina_desc_setup) / diff --git a/libraries/eina/src/lib/eina_matrixsparse.c b/libraries/eina/src/lib/eina_matrixsparse.c index 3ac0439..59cd66b 100644 --- a/libraries/eina/src/lib/eina_matrixsparse.c +++ b/libraries/eina/src/lib/eina_matrixsparse.c @@ -1078,6 +1078,8 @@ eina_matrixsparse_size_set(Eina_Matrixsparse *m, r = r->next; _eina_matrixsparse_row_free(r_aux, free_func, user_data); + if ((update_last_used_row) && (m->last_used == r_aux)) + m->last_used = r; } else { diff --git a/libraries/eina/src/lib/eina_module.c b/libraries/eina/src/lib/eina_module.c index 26df980..f4f3242 100644 --- a/libraries/eina/src/lib/eina_module.c +++ b/libraries/eina/src/lib/eina_module.c @@ -58,6 +58,10 @@ void *alloca (size_t); # include #endif +#ifdef HAVE_EXOTIC_H +# include +#endif + #include "eina_config.h" #include "eina_private.h" #include "eina_error.h" diff --git a/libraries/eina/src/lib/eina_prefix.c b/libraries/eina/src/lib/eina_prefix.c index 5b4b0c0..2322311 100644 --- a/libraries/eina/src/lib/eina_prefix.c +++ b/libraries/eina/src/lib/eina_prefix.c @@ -30,15 +30,15 @@ #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 -# ifndef HAVE_ALLOCA +#elif !defined alloca +# ifdef __GNUC__ +# define alloca __builtin_alloca +# elif defined _AIX +# define alloca __alloca +# elif defined _MSC_VER +# include +# define alloca _alloca +# elif !defined HAVE_ALLOCA # ifdef __cplusplus extern "C" # endif @@ -237,7 +237,7 @@ _try_argv(Eina_Prefix *pfx, const char *argv0) DBG("Try argv0 = %s", argv0); /* 1. is argv0 abs path? */ #ifdef _WIN32 - if (argv0[0] && (argv0[1] == ':')) + if (evil_path_is_absolute(argv0)) #else if (argv0[0] == DSEP_C) #endif @@ -533,7 +533,7 @@ eina_prefix_new(const char *argv0, void *symbol, const char *envprefix, { DBG("Dlinfo dli_fname = %s", info_dl.dli_fname); # ifdef _WIN32 - if (info_dl.dli_fname[0] && (info_dl.dli_fname[1] == ':')) + if (evil_path_is_absolute(info_dl.dli_fname)) # else if (info_dl.dli_fname[0] == DSEP_C) # endif diff --git a/libraries/eina/src/lib/eina_private.h b/libraries/eina/src/lib/eina_private.h index e31ab47..49df565 100644 --- a/libraries/eina/src/lib/eina_private.h +++ b/libraries/eina/src/lib/eina_private.h @@ -95,6 +95,8 @@ #define EINA_MAGIC_INARRAY_ITERATOR 0x98761271 #define EINA_MAGIC_INARRAY_ACCESSOR 0x98761272 +#define EINA_MAGIC_MODEL 0x98761280 + #define EINA_MAGIC_CLASS 0x9877CB30 /* undef the following, we want out version */ diff --git a/libraries/eina/src/lib/eina_rbtree.c b/libraries/eina/src/lib/eina_rbtree.c index 5f1232c..a9d777a 100644 --- a/libraries/eina/src/lib/eina_rbtree.c +++ b/libraries/eina/src/lib/eina_rbtree.c @@ -1,5 +1,6 @@ /* EINA - EFL data type library * Copyright (C) 2008 Cedric Bail + * Copyright (C) 2011 Alexandre Becoulet * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,6 +24,7 @@ #include #include #include +#include #include "eina_config.h" #include "eina_private.h" @@ -244,9 +246,9 @@ static inline Eina_Rbtree * _eina_rbtree_inline_single_rotation(Eina_Rbtree *node, Eina_Rbtree_Direction dir) { - Eina_Rbtree *save = node->son[!dir]; + Eina_Rbtree *save = node->son[dir ^ 1]; - node->son[!dir] = save->son[dir]; + node->son[dir ^ 1] = save->son[dir]; save->son[dir] = node; node->color = EINA_RBTREE_RED; @@ -259,7 +261,7 @@ static inline Eina_Rbtree * _eina_rbtree_inline_double_rotation(Eina_Rbtree *node, Eina_Rbtree_Direction dir) { - node->son[!dir] = _eina_rbtree_inline_single_rotation(node->son[!dir], !dir); + node->son[dir ^ 1] = _eina_rbtree_inline_single_rotation(node->son[dir ^ 1], dir ^ 1); return _eina_rbtree_inline_single_rotation(node, dir); } @@ -277,87 +279,64 @@ eina_rbtree_inline_insert(Eina_Rbtree *root, Eina_Rbtree_Cmp_Node_Cb cmp, const void *data) { - Eina_Rbtree head; - Eina_Rbtree *g, *t; /* Grandparent & parent */ - Eina_Rbtree *p, *q; /* Iterator & parent */ - /* WARNING: - Compiler is not able to understand the underlying algorithm and don't know that - first top node is always black, so it will never use last before running the loop - one time. - */ - Eina_Rbtree_Direction dir, last; + Eina_Rbtree **r = &root; + Eina_Rbtree *q = root; + uintptr_t stack[48]; + unsigned int s = 0; EINA_SAFETY_ON_NULL_RETURN_VAL(node, root); EINA_SAFETY_ON_NULL_RETURN_VAL( cmp, root); - if (!node) - return root; - - _eina_rbtree_node_init(node); - - if (!root) - { - root = node; - goto end_add; - } - - memset(&head, 0, sizeof (Eina_Rbtree)); - last = dir = EINA_RBTREE_LEFT; - - /* Set up helpers */ - t = &head; - g = p = NULL; - q = t->son[1] = root; - - /* Search down the tree */ - for (;; ) - { - if (!q) - /* Insert new node at the bottom */ - p->son[dir] = q = node; - else if (_eina_rbtree_is_red(q->son[0]) - && _eina_rbtree_is_red(q->son[1])) - { - /* Color flip */ - q->color = EINA_RBTREE_RED; - q->son[0]->color = EINA_RBTREE_BLACK; - q->son[1]->color = EINA_RBTREE_BLACK; - } - - /* Fix red violation */ - if (_eina_rbtree_is_red(q) && _eina_rbtree_is_red(p)) - { - Eina_Rbtree_Direction dir2; + /* Find insertion leaf */ + while (q != NULL) + { + Eina_Rbtree_Direction dir = cmp(q, node, (void *)data); - dir2 = (t->son[1] == g) ? EINA_RBTREE_RIGHT : EINA_RBTREE_LEFT; + /* Keep path in stack */ + stack[s++] = (uintptr_t)r | dir; - if (q == p->son[last]) - t->son[dir2] = _eina_rbtree_inline_single_rotation(g, !last); - else - t->son[dir2] = _eina_rbtree_inline_double_rotation(g, !last); - } - - /* Stop if found */ - if (q == node) - break; - - last = dir; - dir = cmp(q, node, (void *)data); + r = q->son + dir; + q = *r; + } - /* Update helpers */ - if ( g ) - t = g; - - g = p, p = q; - q = q->son[dir]; - } + /* Insert */ + *r = node; + _eina_rbtree_node_init(node); - root = head.son[1]; + /* Rebalance */ + while (s > 0) + { + Eina_Rbtree *a, *b; + uintptr_t top = stack[--s]; /* Pop link pointer and direction */ + Eina_Rbtree_Direction dir = top & 1; + + r = (Eina_Rbtree **)(top & ~(uintptr_t)1); + q = *r; + + a = q->son[dir]; + /* Rebalance done ? */ + if (a == NULL || a->color == EINA_RBTREE_BLACK) + break; + + b = q->son[dir ^ 1]; + if (b != NULL && b->color == EINA_RBTREE_RED) + { + q->color = EINA_RBTREE_RED; + b->color = a->color = EINA_RBTREE_BLACK; + } + else + { + Eina_Rbtree *c = a->son[dir]; + Eina_Rbtree *d = a->son[dir ^ 1]; + + if (c != NULL && c->color == EINA_RBTREE_RED) + *r = _eina_rbtree_inline_single_rotation(*r, dir ^ 1); + else if (d != NULL && d->color == EINA_RBTREE_RED) + *r = _eina_rbtree_inline_double_rotation(*r, dir ^ 1); + } + } -end_add: - /* Make root black */ root->color = EINA_RBTREE_BLACK; - return root; } @@ -367,122 +346,144 @@ eina_rbtree_inline_remove(Eina_Rbtree *root, Eina_Rbtree_Cmp_Node_Cb cmp, const void *data) { - Eina_Rbtree head; - Eina_Rbtree *q, *p; - Eina_Rbtree *f = NULL; + Eina_Rbtree *l0, *l1, *r, **rt = &root; Eina_Rbtree_Direction dir; + uintptr_t stack[48]; + unsigned int s = 0; EINA_SAFETY_ON_NULL_RETURN_VAL(node, root); EINA_SAFETY_ON_NULL_RETURN_VAL( cmp, root); - if (!root || !node) - return root; - - memset(&head, 0, sizeof(Eina_Rbtree)); - - dir = EINA_RBTREE_RIGHT; - q = &head; - p = NULL; - q->son[EINA_RBTREE_RIGHT] = root; - - /* Search and push a red down */ - while (q->son[dir]) - { - Eina_Rbtree_Direction last = dir; - Eina_Rbtree *g; - - /* Update helpers */ - g = p; p = q; - q = q->son[dir]; - dir = cmp(q, node, (void *)data); - - /* Save parent node found */ - if (q == node) - f = p; + /* Item search loop */ + for (r = *rt; r != NULL; r = *rt) + { + if (r == node) + goto found; - /* Push the red node down */ - if (!_eina_rbtree_is_red(q) - && !_eina_rbtree_is_red(q->son[dir])) - { - if (_eina_rbtree_is_red(q->son[!dir])) - q = p->son[last] = _eina_rbtree_inline_single_rotation(q, dir); - else if (!_eina_rbtree_is_red(q->son[!dir])) - { - Eina_Rbtree *s = p->son[!last]; - - if (s) - { - if (!_eina_rbtree_is_red(s->son[EINA_RBTREE_LEFT]) - && !_eina_rbtree_is_red(s->son[EINA_RBTREE_RIGHT])) - { -/* Color flip */ - p->color = EINA_RBTREE_BLACK; - p->son[EINA_RBTREE_LEFT]->color = EINA_RBTREE_RED; - p->son[EINA_RBTREE_RIGHT]->color = EINA_RBTREE_RED; - } - else - { - Eina_Rbtree_Direction dir2; - - dir2 = g->son[1] == - p ? EINA_RBTREE_RIGHT : EINA_RBTREE_LEFT; - - if (_eina_rbtree_is_red(s->son[last])) - { - g->son[dir2] = - _eina_rbtree_inline_double_rotation(p, last); - if (f == g) - { - p = g->son[dir2]->son[last]; - f = g->son[dir2]; - } - } - else if (_eina_rbtree_is_red(s->son[!last])) - { - g->son[dir2] = - _eina_rbtree_inline_single_rotation(p, last); - if (f == g) - { - p = g->son[dir2]->son[last]; - f = g->son[dir2]; - } - } - -/* Ensure correct coloring */ - q->color = g->son[dir2]->color = EINA_RBTREE_RED; - g->son[dir2]->son[EINA_RBTREE_LEFT]->color = - EINA_RBTREE_BLACK; - g->son[dir2]->son[EINA_RBTREE_RIGHT]->color = - EINA_RBTREE_BLACK; - } - } - } - } - } - - /* Replace and remove if found */ - if (f) - { - /* 'q' should take the place of 'node' parent */ - f->son[f->son[1] == node] = q; - - /* Switch the link from the parent to q's son */ - p->son[p->son[1] == q] = q->son[!q->son[0]]; - - /* Put q at the place of node */ - q->son[0] = node->son[0]; - q->son[1] = node->son[1]; - q->color = node->color; - - /* Reset node link */ - node->son[0] = NULL; - node->son[1] = NULL; - } + dir = cmp(r, node, (void*)data); + stack[s++] = (uintptr_t)rt | dir; + rt = r->son + dir; + } + return root; - root = head.son[1]; - if (root) + found: + /* remove entry */ + l0 = node->son[0]; + l1 = node->son[1]; + + if (l0 != NULL && l1 != NULL) /* two links case */ + { + Eina_Rbtree *q, **t, **p; + uintptr_t ss; + + stack[s++] = (uintptr_t)rt | 1; + ss = s; /* keep predecessor right link stack index */ + + /* find predecessor */ + p = node->son + 1; + q = *p; + + while (1) + { + t = q->son; + q = *t; + if (q == NULL) + break; + stack[s++] = (uintptr_t)p | 0; + p = t; + } + + /* detach predecessor */ + q = *p; + *p = q->son[1]; + + int c = q->color; + + /* replace entry by predecessor */ + memcpy(q, node, sizeof(Eina_Rbtree)); + *rt = q; + + if (c == EINA_RBTREE_RED) + goto end; + + /* fix stack for replaced entry */ + if (s > ss) + stack[ss] = (uintptr_t)(q->son + 1) | 0; + } + else /* single link case */ + { + if (l0 == NULL) + l0 = l1; + + *rt = l0; + + if (node->color == EINA_RBTREE_RED) + goto end; /* removed red */ + + if (l0 != NULL && l0->color == EINA_RBTREE_RED) + { + /* red child replace removed black */ + l0->color = EINA_RBTREE_BLACK; + goto end; + } + } + + /* rebalance */ + while (s > 0) + { + Eina_Rbtree *q; + uintptr_t st = stack[--s]; + + rt = (Eina_Rbtree**)(st & ~(uintptr_t)1); + dir = st & 1; + r = *rt; + q = r->son[dir ^ 1]; + + if (q != NULL && q->color == EINA_RBTREE_RED) + { + *rt = _eina_rbtree_inline_single_rotation(*rt, dir); + q = r->son[dir ^ 1]; + rt = (*rt)->son + dir; + } + + if (q != NULL) + { + int r_color = r->color; + Eina_Rbtree *nd = q->son[dir ^ 1]; + + if (nd != NULL && nd->color == EINA_RBTREE_RED) + { + *rt = _eina_rbtree_inline_single_rotation(*rt, dir); + } + else + { + Eina_Rbtree *d = q->son[dir]; + + if (d != NULL && d->color == EINA_RBTREE_RED) + { + *rt = _eina_rbtree_inline_double_rotation(*rt, dir); + } + else + { + r->color = EINA_RBTREE_BLACK; + q->color = EINA_RBTREE_RED; + if (r_color == EINA_RBTREE_RED) + break; + continue; + } + } + + r = *rt; + r->color = r_color; + r->son[1]->color = r->son[0]->color = EINA_RBTREE_BLACK; + + break; + } + } + + end: + if (root != NULL) root->color = EINA_RBTREE_BLACK; - return root; } diff --git a/libraries/eina/src/lib/eina_sched.c b/libraries/eina/src/lib/eina_sched.c index 8c7f7fe..b8e7000 100644 --- a/libraries/eina/src/lib/eina_sched.c +++ b/libraries/eina/src/lib/eina_sched.c @@ -41,7 +41,7 @@ #include "eina_sched.h" #include "eina_log.h" -#define RTNICENESS 5 +#define RTNICENESS 1 #define NICENESS 5 EAPI void @@ -62,10 +62,14 @@ eina_sched_prio_drop(void) if (EINA_UNLIKELY(pol == SCHED_RR || pol == SCHED_FIFO)) { - prio = sched_get_priority_max(pol); - param.sched_priority += RTNICENESS; - if (prio > 0 && param.sched_priority > prio) - param.sched_priority = prio; + param.sched_priority -= RTNICENESS; + + /* We don't change the policy */ + if (param.sched_priority < 1) + { + EINA_LOG_INFO("RT prio < 1, setting to 1 instead"); + param.sched_priority = 1; + } pthread_setschedparam(pthread_id, pol, ¶m); } @@ -78,7 +82,10 @@ eina_sched_prio_drop(void) { prio += NICENESS; if (prio > 19) - prio = 19; + { + EINA_LOG_INFO("Max niceness reached; keeping max (19)"); + prio = 19; + } setpriority(PRIO_PROCESS, 0, prio); } diff --git a/libraries/eina/src/lib/eina_share_common.c b/libraries/eina/src/lib/eina_share_common.c index 90e1868..776e429 100644 --- a/libraries/eina/src/lib/eina_share_common.c +++ b/libraries/eina/src/lib/eina_share_common.c @@ -76,7 +76,6 @@ #include "eina_hash.h" #include "eina_rbtree.h" #include "eina_error.h" -#include "eina_log.h" #include "eina_lock.h" /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ @@ -126,8 +125,6 @@ typedef struct _Eina_Share_Common Eina_Share_Common; typedef struct _Eina_Share_Common_Node Eina_Share_Common_Node; typedef struct _Eina_Share_Common_Head Eina_Share_Common_Head; -int _eina_share_common_log_dom = -1; - struct _Eina_Share { Eina_Share_Common *share; @@ -600,28 +597,8 @@ eina_share_common_init(Eina_Share **_share, share = *_share = calloc(sizeof(Eina_Share), 1); if (!share) goto on_error; - if (_eina_share_common_log_dom < 0) /*Only register if not already */ - _eina_share_common_log_dom = eina_log_domain_register( - "eina_share", - EINA_LOG_COLOR_DEFAULT); - - if (_eina_share_common_log_dom < 0) - { - EINA_LOG_ERR("Could not register log domain: eina_share_common"); - goto on_error; - } - share->share = calloc(1, sizeof(Eina_Share_Common)); - if (!share->share) - { - if (_eina_share_common_log_dom > 0) - { - eina_log_domain_unregister(_eina_share_common_log_dom); - _eina_share_common_log_dom = -1; - } - - goto on_error; - } + if (!share->share) goto on_error; share->node_magic = node_magic; #define EMS(n) eina_magic_string_static_set(n, n ## _STR) @@ -678,11 +655,6 @@ eina_share_common_shutdown(Eina_Share **_share) MAGIC_FREE(share->share); _eina_share_common_population_shutdown(share); - if (_eina_share_common_log_dom > 0) /* Only free if necessary */ - { - eina_log_domain_unregister(_eina_share_common_log_dom); - _eina_share_common_log_dom = -1; - } eina_lock_release(&_mutex_big); @@ -833,7 +805,7 @@ eina_share_common_ref(Eina_Share *share, const char *str) } -void +Eina_Bool eina_share_common_del(Eina_Share *share, const char *str) { unsigned int slen; @@ -843,7 +815,7 @@ eina_share_common_del(Eina_Share *share, const char *str) int hash_num, hash; if (!str) - return; + return EINA_TRUE; eina_lock_take(&_mutex_big); @@ -857,7 +829,7 @@ eina_share_common_del(Eina_Share *share, const char *str) { node->references--; eina_lock_release(&_mutex_big); - return; + return EINA_TRUE; } node->references = 0; @@ -871,7 +843,7 @@ eina_share_common_del(Eina_Share *share, const char *str) if (!ed) goto on_error; - EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, eina_lock_release(&_mutex_big)); + EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, eina_lock_release(&_mutex_big), EINA_FALSE); if (!_eina_share_common_head_remove_node(ed, node)) goto on_error; @@ -886,12 +858,12 @@ eina_share_common_del(Eina_Share *share, const char *str) eina_lock_release(&_mutex_big); - return; + return EINA_TRUE; on_error: eina_lock_release(&_mutex_big); /* possible segfault happened before here, but... */ - CRITICAL("EEEK trying to del non-shared share_common \"%s\"", str); + return EINA_FALSE; } int diff --git a/libraries/eina/src/lib/eina_share_common.h b/libraries/eina/src/lib/eina_share_common.h index 002c652..6bc11ef 100644 --- a/libraries/eina/src/lib/eina_share_common.h +++ b/libraries/eina/src/lib/eina_share_common.h @@ -71,7 +71,7 @@ const char *eina_share_common_add_length(Eina_Share *share, unsigned int null_size) EINA_WARN_UNUSED_RESULT; const char *eina_share_common_ref(Eina_Share *share, const char *str); -void eina_share_common_del(Eina_Share *share, const char *str); +Eina_Bool eina_share_common_del(Eina_Share *share, const char *str) EINA_WARN_UNUSED_RESULT; int eina_share_common_length(Eina_Share *share, const char *str) EINA_CONST EINA_WARN_UNUSED_RESULT; @@ -83,21 +83,4 @@ void eina_share_common_dump(Eina_Share *share, void (*additional_dump)( void eina_share_common_population_add(Eina_Share *share, int slen); void eina_share_common_population_del(Eina_Share *share, int slen); -/* Share logging */ -#ifdef CRITICAL -#undef CRITICAL -#endif -#define CRITICAL(...) EINA_LOG_DOM_CRIT(_eina_share_common_log_dom, __VA_ARGS__) - -#ifdef ERR -#undef ERR -#endif -#define ERR(...) EINA_LOG_DOM_ERR(_eina_share_common_log_dom, __VA_ARGS__) - -#ifdef DBG -#undef DBG -#endif -#define DBG(...) EINA_LOG_DOM_DBG(_eina_share_common_log_dom, __VA_ARGS__) -extern int _eina_share_common_log_dom; - -#endif /* EINA_STRINGSHARE_H_ */ +#endif /* EINA_SHARE_COMMON_H_ */ diff --git a/libraries/eina/src/lib/eina_stringshare.c b/libraries/eina/src/lib/eina_stringshare.c index 478b300..f371fcd 100644 --- a/libraries/eina/src/lib/eina_stringshare.c +++ b/libraries/eina/src/lib/eina_stringshare.c @@ -55,12 +55,30 @@ void *alloca (size_t); #include "eina_private.h" #include "eina_error.h" #include "eina_log.h" -#include "eina_stringshare.h" #include "eina_lock.h" +#include "eina_share_common.h" /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ #include "eina_safety_checks.h" -#include "eina_share_common.h" +#include "eina_stringshare.h" + + +#ifdef CRITICAL +#undef CRITICAL +#endif +#define CRITICAL(...) EINA_LOG_DOM_CRIT(_eina_share_stringshare_log_dom, __VA_ARGS__) + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_eina_share_stringshare_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_share_stringshare_log_dom, __VA_ARGS__) + +static int _eina_share_stringshare_log_dom = -1; /* The actual share */ static Eina_Share *stringshare_share; @@ -447,11 +465,8 @@ _eina_stringshare_small_bucket_dump(Eina_Stringshare_Small_Bucket *bucket, for (i = 0; i < bucket->count; i++, s++, l++, r++) { int dups; -#ifdef _WIN32 - printf("DDD: %5hu %5hu '%s'\n", *l, *r, *s); -#else + printf("DDD: %5hhu %5hu '%s'\n", *l, *r, *s); -#endif dups = (*r - 1); @@ -500,11 +515,29 @@ Eina_Bool eina_stringshare_init(void) { Eina_Bool ret; + + if (_eina_share_stringshare_log_dom < 0) + { + _eina_share_stringshare_log_dom = eina_log_domain_register + ("eina_stringshare", EINA_LOG_COLOR_DEFAULT); + + if (_eina_share_stringshare_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_stringshare"); + return EINA_FALSE; + } + } + ret = eina_share_common_init(&stringshare_share, EINA_MAGIC_STRINGSHARE_NODE, EINA_MAGIC_STRINGSHARE_NODE_STR); if (ret) _eina_stringshare_small_init(); + else + { + eina_log_domain_unregister(_eina_share_stringshare_log_dom); + _eina_share_stringshare_log_dom = -1; + } return ret; } @@ -526,6 +559,13 @@ eina_stringshare_shutdown(void) Eina_Bool ret; _eina_stringshare_small_shutdown(); ret = eina_share_common_shutdown(&stringshare_share); + + if (_eina_share_stringshare_log_dom >= 0) + { + eina_log_domain_unregister(_eina_share_stringshare_log_dom); + _eina_share_stringshare_log_dom = -1; + } + return ret; } @@ -534,7 +574,7 @@ eina_stringshare_shutdown(void) *============================================================================*/ EAPI void -eina_stringshare_del(const char *str) +eina_stringshare_del(Eina_Stringshare *str) { int slen; @@ -564,16 +604,17 @@ eina_stringshare_del(const char *str) return; } - eina_share_common_del(stringshare_share, str); + if (!eina_share_common_del(stringshare_share, str)) + CRITICAL("EEEK trying to del non-shared stringshare \"%s\"", str); } -EAPI const char * +EAPI Eina_Stringshare * eina_stringshare_add_length(const char *str, unsigned int slen) { if ((!str) || (slen <= 0)) return ""; else if (slen == 1) - return (const char *)_eina_stringshare_single + ((*str) << 1); + return (Eina_Stringshare *) _eina_stringshare_single + ((*str) << 1); else if (slen < 4) { const char *s; @@ -588,7 +629,7 @@ eina_stringshare_add_length(const char *str, unsigned int slen) sizeof(char), sizeof(char)); } -EAPI const char * +EAPI Eina_Stringshare * eina_stringshare_add(const char *str) { int slen; @@ -609,7 +650,7 @@ eina_stringshare_add(const char *str) return eina_stringshare_add_length(str, slen); } -EAPI const char * +EAPI Eina_Stringshare * eina_stringshare_printf(const char *fmt, ...) { va_list args; @@ -633,7 +674,7 @@ eina_stringshare_printf(const char *fmt, ...) return ret; } -EAPI const char * +EAPI Eina_Stringshare * eina_stringshare_vprintf(const char *fmt, va_list args) { char *tmp; @@ -654,7 +695,7 @@ eina_stringshare_vprintf(const char *fmt, va_list args) return ret; } -EAPI const char * +EAPI Eina_Stringshare * eina_stringshare_nprintf(unsigned int len, const char *fmt, ...) { va_list args; @@ -679,8 +720,8 @@ eina_stringshare_nprintf(unsigned int len, const char *fmt, ...) return eina_stringshare_add_length(tmp, len); } -EAPI const char * -eina_stringshare_ref(const char *str) +EAPI Eina_Stringshare * +eina_stringshare_ref(Eina_Stringshare *str) { int slen; @@ -721,7 +762,7 @@ eina_stringshare_ref(const char *str) } EAPI int -eina_stringshare_strlen(const char *str) +eina_stringshare_strlen(Eina_Stringshare *str) { int len; /* special cases */ @@ -737,7 +778,7 @@ eina_stringshare_strlen(const char *str) if (str[3] == '\0') return 3; - len = eina_share_common_length(stringshare_share, (const char *)str); + len = eina_share_common_length(stringshare_share, (Eina_Stringshare *) str); len = (len > 0) ? len / (int)sizeof(char) : -1; return len; } diff --git a/libraries/eina/src/lib/eina_unicode.c b/libraries/eina/src/lib/eina_unicode.c index 342e3cb..7505906 100644 --- a/libraries/eina/src/lib/eina_unicode.c +++ b/libraries/eina/src/lib/eina_unicode.c @@ -15,10 +15,18 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; * if not, see . - */ -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "eina_config.h" +#include "eina_private.h" +#include + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" #include "eina_unicode.h" /* FIXME: check if sizeof(wchar_t) == sizeof(Eina_Unicode) if so, @@ -30,6 +38,9 @@ EAPI const Eina_Unicode *EINA_UNICODE_EMPTY_STRING = _EINA_UNICODE_EMPTY_STRING; EAPI int eina_unicode_strcmp(const Eina_Unicode *a, const Eina_Unicode *b) { + EINA_SAFETY_ON_NULL_RETURN_VAL(a, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(b, -1); + for (; *a && *a == *b; a++, b++) ; if (*a == *b) @@ -45,6 +56,9 @@ eina_unicode_strcpy(Eina_Unicode *dest, const Eina_Unicode *source) { Eina_Unicode *ret = dest; + EINA_SAFETY_ON_NULL_RETURN_VAL(dest, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(source, NULL); + while (*source) *dest++ = *source++; *dest = 0; @@ -56,6 +70,9 @@ eina_unicode_strncpy(Eina_Unicode *dest, const Eina_Unicode *source, size_t n) { Eina_Unicode *ret = dest; + EINA_SAFETY_ON_NULL_RETURN_VAL(dest, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(source, NULL); + for ( ; n && *source ; n--) *dest++ = *source++; for (; n; n--) @@ -67,6 +84,9 @@ EAPI size_t eina_unicode_strlen(const Eina_Unicode *ustr) { const Eina_Unicode *end; + + EINA_SAFETY_ON_NULL_RETURN_VAL(ustr, 0); + for (end = ustr; *end; end++) ; return end - ustr; @@ -77,6 +97,9 @@ eina_unicode_strnlen(const Eina_Unicode *ustr, int n) { const Eina_Unicode *end; const Eina_Unicode *last = ustr + n; /* technically not portable ;-) */ + + EINA_SAFETY_ON_NULL_RETURN_VAL(ustr, 0); + for (end = ustr; end < last && *end; end++) ; return end - ustr; @@ -90,7 +113,9 @@ eina_unicode_strndup(const Eina_Unicode *text, size_t n) { Eina_Unicode *ustr; - ustr = (Eina_Unicode *) malloc((n + 1) * sizeof(Eina_Unicode)); + EINA_SAFETY_ON_NULL_RETURN_VAL(text, NULL); + + ustr = malloc((n + 1) * sizeof(Eina_Unicode)); memcpy(ustr, text, n * sizeof(Eina_Unicode)); ustr[n] = 0; return ustr; @@ -101,6 +126,8 @@ eina_unicode_strdup(const Eina_Unicode *text) { size_t len; + EINA_SAFETY_ON_NULL_RETURN_VAL(text, NULL); + len = eina_unicode_strlen(text); return eina_unicode_strndup(text, len); } @@ -110,6 +137,9 @@ eina_unicode_strstr(const Eina_Unicode *haystack, const Eina_Unicode *needle) { const Eina_Unicode *i, *j; + EINA_SAFETY_ON_NULL_RETURN_VAL(haystack, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(needle, NULL); + for (i = haystack; *i; i++) { haystack = i; /* set this location as the base position */ @@ -131,6 +161,8 @@ eina_unicode_escape(const Eina_Unicode *str) Eina_Unicode *s2, *d; const Eina_Unicode *s; + EINA_SAFETY_ON_NULL_RETURN_VAL(str, NULL); + s2 = malloc((eina_unicode_strlen(str) * 2) + 1); if (!s2) return NULL; @@ -165,6 +197,9 @@ eina_unicode_utf8_get_next(const char *buf, int *iindex) Eina_Unicode r; unsigned char d; + EINA_SAFETY_ON_NULL_RETURN_VAL(buf, 0); + EINA_SAFETY_ON_NULL_RETURN_VAL(iindex, 0); + /* if this char is the null terminator, exit */ if ((d = buf[ind++]) == 0) return 0; @@ -266,8 +301,12 @@ error: EAPI Eina_Unicode eina_unicode_utf8_get_prev(const char *buf, int *iindex) { - int r; - int ind = *iindex; + int r, ind; + + EINA_SAFETY_ON_NULL_RETURN_VAL(buf, 0); + EINA_SAFETY_ON_NULL_RETURN_VAL(iindex, 0); + + ind = *iindex; /* First obtain the codepoint at iindex */ r = eina_unicode_utf8_get_next(buf, &ind); @@ -292,6 +331,8 @@ eina_unicode_utf8_get_len(const char *buf) /* returns the number of utf8 characters (not bytes) in the string */ int i = 0, len = 0; + EINA_SAFETY_ON_NULL_RETURN_VAL(buf, 0); + while (eina_unicode_utf8_get_next(buf, &i)) len++; @@ -306,6 +347,8 @@ eina_unicode_utf8_to_unicode(const char *utf, int *_len) int ind; Eina_Unicode *buf, *uind; + EINA_SAFETY_ON_NULL_RETURN_VAL(utf, NULL); + len = eina_unicode_utf8_get_len(utf); if (_len) *_len = len; @@ -328,6 +371,8 @@ eina_unicode_unicode_to_utf8(const Eina_Unicode *uni, int *_len) char *ind; int ulen, len; + EINA_SAFETY_ON_NULL_RETURN_VAL(uni, NULL); + ulen = eina_unicode_strlen(uni); buf = (char *) calloc(ulen + 1, EINA_UNICODE_UTF8_BYTES_PER_CHAR); diff --git a/libraries/eina/src/lib/eina_ustringshare.c b/libraries/eina/src/lib/eina_ustringshare.c index 3992dc6..33be242 100644 --- a/libraries/eina/src/lib/eina_ustringshare.c +++ b/libraries/eina/src/lib/eina_ustringshare.c @@ -27,11 +27,38 @@ * */ -#include "eina_share_common.h" -#include "eina_unicode.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "eina_config.h" #include "eina_private.h" +#include "eina_unicode.h" +#include "eina_log.h" +#include "eina_share_common.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" #include "eina_ustringshare.h" + +#ifdef CRITICAL +#undef CRITICAL +#endif +#define CRITICAL(...) EINA_LOG_DOM_CRIT(_eina_share_ustringshare_log_dom, __VA_ARGS__) + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_eina_share_ustringshare_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_share_ustringshare_log_dom, __VA_ARGS__) + +static int _eina_share_ustringshare_log_dom = -1; + /* The actual share */ static Eina_Share *ustringshare_share; static const char EINA_MAGIC_USTRINGSHARE_NODE_STR[] = "Eina UStringshare Node"; @@ -54,9 +81,31 @@ static const char EINA_MAGIC_USTRINGSHARE_NODE_STR[] = "Eina UStringshare Node"; Eina_Bool eina_ustringshare_init(void) { - return eina_share_common_init(&ustringshare_share, - EINA_MAGIC_USTRINGSHARE_NODE, - EINA_MAGIC_USTRINGSHARE_NODE_STR); + Eina_Bool ret; + + if (_eina_share_ustringshare_log_dom < 0) + { + _eina_share_ustringshare_log_dom = eina_log_domain_register + ("eina_ustringshare", EINA_LOG_COLOR_DEFAULT); + + if (_eina_share_ustringshare_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_ustringshare"); + return EINA_FALSE; + } + } + + ret = eina_share_common_init(&ustringshare_share, + EINA_MAGIC_USTRINGSHARE_NODE, + EINA_MAGIC_USTRINGSHARE_NODE_STR); + + if (!ret) + { + eina_log_domain_unregister(_eina_share_ustringshare_log_dom); + _eina_share_ustringshare_log_dom = -1; + } + + return ret; } /** @@ -75,6 +124,13 @@ eina_ustringshare_shutdown(void) { Eina_Bool ret; ret = eina_share_common_shutdown(&ustringshare_share); + + if (_eina_share_ustringshare_log_dom >= 0) + { + eina_log_domain_unregister(_eina_share_ustringshare_log_dom); + _eina_share_ustringshare_log_dom = -1; + } + return ret; } @@ -88,7 +144,8 @@ eina_ustringshare_del(const Eina_Unicode *str) if (!str) return; - eina_share_common_del(ustringshare_share,(const char *)str); + if (!eina_share_common_del(ustringshare_share, (const char *)str)) + CRITICAL("EEEK trying to del non-shared ustringshare \"%s\"", (const char *)str); } EAPI const Eina_Unicode * diff --git a/libraries/eina/src/lib/eina_value.c b/libraries/eina/src/lib/eina_value.c index ba8af52..b8df693 100644 --- a/libraries/eina/src/lib/eina_value.c +++ b/libraries/eina/src/lib/eina_value.c @@ -49,6 +49,10 @@ void *alloca (size_t); #include /* PRId64 and PRIu64 */ #include /* struct timeval */ +#ifdef HAVE_EVIL +# include +#endif + #include "eina_config.h" #include "eina_private.h" #include "eina_error.h" @@ -60,6 +64,7 @@ void *alloca (size_t); /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ #include "eina_safety_checks.h" #include "eina_value.h" +#include "eina_model.h" /* uses eina_value.h */ /*============================================================================* * Local * @@ -168,7 +173,7 @@ _eina_value_type_uchar_convert_to(const Eina_Value_Type *type __UNUSED__, const unsigned int other_mem = v; return eina_value_type_pset(convert, convert_mem, &other_mem); } - else if (convert == EINA_VALUE_TYPE_ULONG) + else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) { unsigned long other_mem = v; return eina_value_type_pset(convert, convert_mem, &other_mem); @@ -317,7 +322,7 @@ _eina_value_type_ushort_convert_to(const Eina_Value_Type *type __UNUSED__, const unsigned int other_mem = v; return eina_value_type_pset(convert, convert_mem, &other_mem); } - else if (convert == EINA_VALUE_TYPE_ULONG) + else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) { unsigned long other_mem = v; return eina_value_type_pset(convert, convert_mem, &other_mem); @@ -470,7 +475,7 @@ _eina_value_type_uint_convert_to(const Eina_Value_Type *type __UNUSED__, const E unsigned int other_mem = v; return eina_value_type_pset(convert, convert_mem, &other_mem); } - else if (convert == EINA_VALUE_TYPE_ULONG) + else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) { unsigned long other_mem = v; return eina_value_type_pset(convert, convert_mem, &other_mem); @@ -627,7 +632,7 @@ _eina_value_type_ulong_convert_to(const Eina_Value_Type *type __UNUSED__, const return EINA_FALSE; return eina_value_type_pset(convert, convert_mem, &other_mem); } - else if (convert == EINA_VALUE_TYPE_ULONG) + else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) { unsigned long other_mem = v; return eina_value_type_pset(convert, convert_mem, &other_mem); @@ -786,7 +791,7 @@ _eina_value_type_uint64_convert_to(const Eina_Value_Type *type __UNUSED__, const return EINA_FALSE; return eina_value_type_pset(convert, convert_mem, &other_mem); } - else if (convert == EINA_VALUE_TYPE_ULONG) + else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) { unsigned long other_mem = v; if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) && @@ -950,7 +955,7 @@ _eina_value_type_char_convert_to(const Eina_Value_Type *type __UNUSED__, const E return EINA_FALSE; return eina_value_type_pset(convert, convert_mem, &other_mem); } - else if (convert == EINA_VALUE_TYPE_ULONG) + else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) { unsigned long other_mem = v; if (EINA_UNLIKELY(v < 0)) @@ -1107,7 +1112,7 @@ _eina_value_type_short_convert_to(const Eina_Value_Type *type __UNUSED__, const return EINA_FALSE; return eina_value_type_pset(convert, convert_mem, &other_mem); } - else if (convert == EINA_VALUE_TYPE_ULONG) + else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) { unsigned long other_mem = v; if (EINA_UNLIKELY(v < 0)) @@ -1270,7 +1275,7 @@ _eina_value_type_int_convert_to(const Eina_Value_Type *type __UNUSED__, const Ei return EINA_FALSE; return eina_value_type_pset(convert, convert_mem, &other_mem); } - else if (convert == EINA_VALUE_TYPE_ULONG) + else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) { unsigned long other_mem = v; if (EINA_UNLIKELY(v < 0)) @@ -1439,7 +1444,7 @@ _eina_value_type_long_convert_to(const Eina_Value_Type *type __UNUSED__, const E return EINA_FALSE; return eina_value_type_pset(convert, convert_mem, &other_mem); } - else if (convert == EINA_VALUE_TYPE_ULONG) + else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) { unsigned long other_mem = v; if (EINA_UNLIKELY(v < 0)) @@ -1612,7 +1617,7 @@ _eina_value_type_int64_convert_to(const Eina_Value_Type *type __UNUSED__, const return EINA_FALSE; return eina_value_type_pset(convert, convert_mem, &other_mem); } - else if (convert == EINA_VALUE_TYPE_ULONG) + else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) { unsigned long other_mem = v; if (EINA_UNLIKELY(v < 0)) @@ -1792,7 +1797,7 @@ _eina_value_type_float_convert_to(const Eina_Value_Type *type __UNUSED__, const return EINA_FALSE; return eina_value_type_pset(convert, convert_mem, &other_mem); } - else if (convert == EINA_VALUE_TYPE_ULONG) + else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) { unsigned long other_mem = v; if (EINA_UNLIKELY(v < 0)) @@ -1978,7 +1983,7 @@ _eina_value_type_double_convert_to(const Eina_Value_Type *type __UNUSED__, const return EINA_FALSE; return eina_value_type_pset(convert, convert_mem, &other_mem); } - else if (convert == EINA_VALUE_TYPE_ULONG) + else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) { unsigned long other_mem = v; if (EINA_UNLIKELY(v < 0)) @@ -2146,7 +2151,7 @@ _eina_value_type_string_common_convert_to(const Eina_Value_Type *type __UNUSED__ return EINA_FALSE; return eina_value_type_pset(convert, convert_mem, &other_mem); } - else if (convert == EINA_VALUE_TYPE_ULONG) + else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) { unsigned long other_mem; if ((sscanf(v, "%lu", &other_mem) != 1) && @@ -2248,7 +2253,11 @@ 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); + if (*tmem) + { + eina_stringshare_del(*tmem); + *tmem = NULL; + } return EINA_TRUE; } @@ -2257,8 +2266,7 @@ _eina_value_type_stringshare_copy(const Eina_Value_Type *type __UNUSED__, const { const char * const*s = src; const char **d = dst; - *d = *s; - eina_stringshare_ref(*d); + *d = eina_stringshare_add(*s); return EINA_TRUE; } @@ -2280,7 +2288,11 @@ static Eina_Bool _eina_value_type_string_flush(const Eina_Value_Type *type __UNUSED__, void *mem) { char **tmem = mem; - if (*tmem) free(*tmem); + if (*tmem) + { + free(*tmem); + *tmem = NULL; + } return EINA_TRUE; } @@ -2308,19 +2320,24 @@ _eina_value_type_string_vset(const Eina_Value_Type *type __UNUSED__, void *mem, { char **tmem = mem; const char *str = va_arg(args, const char *); - free(*tmem); - if (str == NULL) - *tmem = NULL; + eina_error_set(0); + if (str == *tmem) return EINA_TRUE; + if (!str) + { + free(*tmem); + *tmem = NULL; + } else { - *tmem = strdup(str); - if (*tmem == NULL) + char *tmp = strdup(str); + if (!tmp) { eina_error_set(EINA_ERROR_OUT_OF_MEMORY); return EINA_FALSE; } + free(*tmem); + *tmem = tmp; } - eina_error_set(0); return EINA_TRUE; } @@ -2329,19 +2346,24 @@ _eina_value_type_string_pset(const Eina_Value_Type *type __UNUSED__, void *mem, { char **tmem = mem; const char * const *str = ptr; - free(*tmem); - if (*str == NULL) - *tmem = NULL; + eina_error_set(0); + if (*str == *tmem) return EINA_TRUE; + if (!*str) + { + free(*tmem); + *tmem = NULL; + } else { - *tmem = strdup(*str); - if (*tmem == NULL) + char *tmp = strdup(*str); + if (!tmp) { eina_error_set(EINA_ERROR_OUT_OF_MEMORY); return EINA_FALSE; } + free(*tmem); + *tmem = tmp; } - eina_error_set(0); return EINA_TRUE; } @@ -2505,12 +2527,13 @@ _eina_value_type_array_convert_to(const Eina_Value_Type *type __UNUSED__, const (convert == EINA_VALUE_TYPE_STRINGSHARE)) { Eina_Strbuf *str = eina_strbuf_new(); + const char *ptr; if (!tmem->array) eina_strbuf_append(str, "[]"); else { const Eina_Value_Type *subtype = tmem->subtype; unsigned char sz; - const char *ptr, *ptr_end; + const char *ptr_end; Eina_Value tmp; Eina_Bool first = EINA_TRUE; @@ -2551,10 +2574,10 @@ _eina_value_type_array_convert_to(const Eina_Value_Type *type __UNUSED__, const } eina_strbuf_append_char(str, ']'); - ptr = eina_strbuf_string_get(str); - ret = eina_value_type_pset(convert, convert_mem, &ptr); - eina_strbuf_free(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)) { @@ -2606,43 +2629,51 @@ _eina_value_type_array_convert_from(const Eina_Value_Type *type, const Eina_Valu } static Eina_Bool -_eina_value_type_array_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +_eina_value_type_array_pset(const Eina_Value_Type *type, void *mem, const void *ptr) { Eina_Value_Array *tmem = mem; const Eina_Value_Array *desc = ptr; Eina_Inarray *desc_array; + eina_error_set(0); if ((!tmem->subtype) && (!desc->subtype)) return EINA_TRUE; desc_array = desc->array; if (desc_array) { + Eina_Value_Array tmp; + EINA_SAFETY_ON_FALSE_RETURN_VAL (desc_array->member_size == desc->subtype->value_size, EINA_FALSE); + + if (desc_array == tmem->array) + { + tmem->subtype = desc->subtype; + return EINA_TRUE; + } + + if (!_eina_value_type_array_copy(type, desc, &tmp)) + return EINA_FALSE; + + _eina_value_type_array_flush(type, tmem); + memcpy(tmem, &tmp, sizeof(tmp)); + return EINA_TRUE; } 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); + eina_inarray_setup(tmem->array, desc->subtype->value_size, desc->step); } - else if (!desc_array) + else { 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; } @@ -2821,13 +2852,13 @@ _eina_value_type_list_convert_to(const Eina_Value_Type *type __UNUSED__, const E (convert == EINA_VALUE_TYPE_STRINGSHARE)) { Eina_Strbuf *str = eina_strbuf_new(); + const char *s; 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); @@ -2867,10 +2898,10 @@ _eina_value_type_list_convert_to(const Eina_Value_Type *type __UNUSED__, const E } eina_strbuf_append_char(str, ']'); - s = eina_strbuf_string_get(str); - ret = eina_value_type_pset(convert, convert_mem, &s); - eina_strbuf_free(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)) { @@ -2932,18 +2963,36 @@ _eina_value_type_list_convert_from(const Eina_Value_Type *type, const Eina_Value } static Eina_Bool -_eina_value_type_list_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +_eina_value_type_list_pset(const Eina_Value_Type *type, void *mem, const void *ptr) { Eina_Value_List *tmem = mem; const Eina_Value_List *desc = ptr; + eina_error_set(0); if ((!tmem->subtype) && (!desc->subtype)) return EINA_TRUE; + if ((tmem->list) && (tmem->list == desc->list)) + { + tmem->subtype = desc->subtype; + return EINA_TRUE; + } + + if (desc->list) + { + Eina_Value_List tmp; + + if (!_eina_value_type_list_copy(type, desc, &tmp)) + return EINA_FALSE; + + _eina_value_type_list_flush(type, tmem); + memcpy(tmem, &tmp, sizeof(tmp)); + return EINA_TRUE; + } + _eina_value_type_list_flush_elements(tmem); - tmem->subtype = desc->subtype; - tmem->list = desc->list; + tmem->subtype = desc->subtype; return EINA_TRUE; } @@ -2995,6 +3044,7 @@ _eina_value_type_hash_flush_each(const Eina_Hash *hash __UNUSED__, const void *k { struct _eina_value_type_hash_flush_each_ctx *ctx = user_data; ctx->ret &= eina_value_type_flush(ctx->subtype, mem); + free(mem); return EINA_TRUE; } @@ -3239,11 +3289,11 @@ _eina_value_type_hash_convert_to(const Eina_Value_Type *type __UNUSED__, const E (convert == EINA_VALUE_TYPE_STRINGSHARE)) { Eina_Strbuf *str = eina_strbuf_new(); + const char *s; 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; @@ -3257,10 +3307,10 @@ _eina_value_type_hash_convert_to(const Eina_Value_Type *type __UNUSED__, const E &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); } + 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)) { @@ -3288,22 +3338,38 @@ _eina_value_type_hash_convert_to(const Eina_Value_Type *type __UNUSED__, const E } static Eina_Bool -_eina_value_type_hash_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +_eina_value_type_hash_pset(const Eina_Value_Type *type, void *mem, const void *ptr) { Eina_Value_Hash *tmem = mem; const Eina_Value_Hash *desc = ptr; + eina_error_set(0); if ((!tmem->subtype) && (!desc->subtype)) return EINA_TRUE; - if (tmem->hash) _eina_value_type_hash_flush_elements(tmem); + if ((tmem->hash) && (tmem->hash == desc->hash)) + { + tmem->subtype = desc->subtype; + return EINA_TRUE; + } if (desc->hash) - tmem->hash = desc->hash; - else if (!_eina_value_type_hash_create(tmem)) - return EINA_FALSE; + { + Eina_Value_Hash tmp; + + if (!_eina_value_type_hash_copy(type, desc, &tmp)) + return EINA_FALSE; + + _eina_value_type_hash_flush(type, tmem); + memcpy(tmem, &tmp, sizeof(tmp)); + return EINA_TRUE; + } + + if (tmem->hash) _eina_value_type_hash_flush_elements(tmem); tmem->subtype = desc->subtype; + if (!_eina_value_type_hash_create(tmem)) + return EINA_FALSE; return EINA_TRUE; } @@ -3424,7 +3490,7 @@ _eina_value_type_timeval_convert_to(const Eina_Value_Type *type __UNUSED__, cons return EINA_FALSE; return eina_value_type_pset(convert, convert_mem, &other_mem); } - else if (convert == EINA_VALUE_TYPE_ULONG) + else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) { unsigned long other_mem = v.tv_sec; if (EINA_UNLIKELY(v.tv_sec < 0)) @@ -3570,6 +3636,8 @@ _eina_value_type_blob_flush(const Eina_Value_Type *type __UNUSED__, void *mem) Eina_Value_Blob *tmem = mem; if ((ops) && (ops->free)) ops->free(ops, (void *)tmem->memory, tmem->size); + tmem->memory = NULL; + tmem->size = 0; return EINA_TRUE; } @@ -3776,6 +3844,14 @@ _eina_value_type_blob_pset(const Eina_Value_Type *type __UNUSED__, void *mem, co Eina_Value_Blob *tmem = mem; const Eina_Value_Blob *desc = ptr; + eina_error_set(0); + if ((tmem->memory) && (tmem->memory == desc->memory)) + { + tmem->ops = desc->ops; + tmem->size = desc->size; + return EINA_TRUE; + } + if ((ops) && (ops->free)) ops->free(ops, (void *)tmem->memory, tmem->size); @@ -3872,6 +3948,7 @@ _eina_value_struct_operations_stringshare_find_member(const Eina_Value_Struct_Op return itr; } + itr = desc->members; name = eina_stringshare_add(name); eina_stringshare_del(name); /* we'll not use the contents, this is fine */ /* stringshare and look again */ @@ -3955,6 +4032,13 @@ _eina_value_type_struct_setup(const Eina_Value_Type *type __UNUSED__, void *mem) } static Eina_Bool +_eina_value_type_struct_setup_member(const Eina_Value_Struct_Member *member, Eina_Value_Struct *st) +{ + unsigned char *base = st->memory; + return eina_value_type_setup(member->type, base + member->offset); +} + +static Eina_Bool _eina_value_type_struct_flush_member(const Eina_Value_Struct_Member *member, Eina_Value_Struct *st) { unsigned char *base = st->memory; @@ -3969,6 +4053,9 @@ _eina_value_type_struct_flush(const Eina_Value_Type *type __UNUSED__, void *mem) Eina_Value_Struct *tmem = mem; Eina_Bool ret = EINA_TRUE; + if ((!tmem->desc) || (!tmem->memory)) + return EINA_TRUE; + itr = tmem->desc->members; if (tmem->desc->member_count > 0) { @@ -3989,6 +4076,9 @@ _eina_value_type_struct_flush(const Eina_Value_Type *type __UNUSED__, void *mem) else free(tmem->memory); + tmem->memory = NULL; + tmem->desc = NULL; + return ret; } @@ -4012,6 +4102,9 @@ _eina_value_type_struct_copy(const Eina_Value_Type *type __UNUSED__, const void *d = *s; + if ((!s->desc) || (!s->memory)) + return EINA_TRUE; + ops = _eina_value_type_struct_ops_get(src); if ((ops) && (ops->copy)) { @@ -4021,7 +4114,10 @@ _eina_value_type_struct_copy(const Eina_Value_Type *type __UNUSED__, const void return EINA_TRUE; } - d->memory = malloc(s->desc->size); + if ((ops) && (ops->alloc)) + d->memory = ops->alloc(ops, s->desc); + else + d->memory = malloc(s->desc->size); if (!d->memory) { eina_error_set(EINA_ERROR_OUT_OF_MEMORY); @@ -4043,14 +4139,17 @@ _eina_value_type_struct_copy(const Eina_Value_Type *type __UNUSED__, const void goto error; } - return EINA_TRUE; error: itr--; for (; itr >= s->desc->members; itr--) _eina_value_type_struct_flush_member(itr, d); - free(d->memory); + + if ((ops) && (ops->free)) + ops->free(ops, s->desc, d->memory); + else + free(d->memory); return EINA_FALSE; } @@ -4072,7 +4171,9 @@ _eina_value_type_struct_compare(const Eina_Value_Type *type __UNUSED__, const vo const Eina_Value_Struct_Member *itr; int cmp = 0; - if (ta->desc != tb->desc) + if ((!ta->desc) && (!tb->desc)) + return 0; + else if (ta->desc != tb->desc) { eina_error_set(EINA_ERROR_VALUE_FAILED); return -1; @@ -4236,11 +4337,12 @@ _eina_value_type_struct_desc_check(const Eina_Value_Struct_Desc *desc) } static Eina_Bool -_eina_value_type_struct_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +_eina_value_type_struct_pset(const Eina_Value_Type *type, void *mem, const void *ptr) { - const Eina_Value_Struct_Operations *ops = _eina_value_type_struct_ops_get(mem); + const Eina_Value_Struct_Operations *ops; Eina_Value_Struct *tmem = mem; const Eina_Value_Struct *desc = ptr; + const Eina_Value_Struct_Member *itr; if (!_eina_value_type_struct_desc_check(desc->desc)) { @@ -4248,30 +4350,71 @@ _eina_value_type_struct_pset(const Eina_Value_Type *type __UNUSED__, void *mem, return EINA_FALSE; } - if ((ops) && (ops->free)) - ops->free(ops, tmem->desc, tmem->memory); - else - free(tmem->memory); + eina_error_set(0); + if ((tmem->memory) && (tmem->memory == desc->memory)) + { + tmem->desc = desc->desc; + return EINA_TRUE; + } - *tmem = *desc; + if (desc->memory) + { + Eina_Value_Struct tmp; + + if (!_eina_value_type_struct_copy(type, desc, &tmp)) + return EINA_FALSE; + + _eina_value_type_struct_flush(type, tmem); + memcpy(tmem, &tmp, sizeof(tmp)); + return EINA_TRUE; + } + + if (tmem->memory) _eina_value_type_struct_flush(type, mem); + + tmem->desc = desc->desc; ops = _eina_value_type_struct_ops_get(desc); + if ((ops) && (ops->alloc)) + tmem->memory = ops->alloc(ops, tmem->desc); + else + tmem->memory = malloc(tmem->desc->size); + if (!tmem->memory) { - if ((ops) && (ops->alloc)) - tmem->memory = ops->alloc(ops, tmem->desc); - else - tmem->memory = malloc(tmem->desc->size); + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } - if (!tmem->memory) - { - eina_error_set(EINA_ERROR_OUT_OF_MEMORY); - return EINA_FALSE; - } + 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++) + if (!_eina_value_type_struct_setup_member(itr, tmem)) + goto error; + } + else + { + for (; itr->name != NULL; itr++) + if (!_eina_value_type_struct_setup_member(itr, tmem)) + goto error; } - eina_error_set(0); return EINA_TRUE; + + error: + itr--; + for (; itr >= tmem->desc->members; itr--) + _eina_value_type_struct_flush_member(itr, tmem); + + if ((ops) && (ops->free)) + ops->free(ops, tmem->desc, tmem->memory); + else + free(tmem->memory); + tmem->memory = NULL; + tmem->desc = NULL; + return EINA_FALSE; } static Eina_Bool @@ -4304,6 +4447,130 @@ static const Eina_Value_Type _EINA_VALUE_TYPE_STRUCT = { _eina_value_type_struct_pget }; +static Eina_Bool +_eina_value_type_model_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + Eina_Model **tmem = mem; + *tmem = NULL; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_model_flush(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + Eina_Model **tmem = mem; + if (*tmem) + { + eina_model_unref(*tmem); + *tmem = NULL; + } + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_model_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const Eina_Model * const *s = src; + Eina_Model **d = dst; + if (*s) + *d = eina_model_copy(*s); /* is it better to deep-copy? */ + else + *d = NULL; + return EINA_TRUE; +} + +static int +_eina_value_type_model_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const Eina_Model * const *ta = a; + const Eina_Model * const *tb = b; + + if ((!*ta) && (!*tb)) return 0; + else if (!*ta) return 1; + else if (!*tb) return -1; + else return eina_model_compare(*ta, *tb); +} + +static Eina_Bool +_eina_value_type_model_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const Eina_Model *v = *(const Eina_Model **)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + char *other_mem = v ? eina_model_to_string(v) : NULL; + Eina_Bool ret = eina_value_type_pset(convert, convert_mem, &other_mem); + free(other_mem); + return ret; + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_model_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + Eina_Model **tmem = mem, *tmp; + + tmp = va_arg(args, Eina_Model *); + + if (tmp) eina_model_ref(tmp); + if (*tmem) eina_model_unref(*tmem); + + *tmem = tmp; + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_model_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + Eina_Model **tmem = mem; + Eina_Model **p = (Eina_Model **)ptr; + + eina_error_set(0); + if (*tmem == *p) return EINA_TRUE; + + if (*p) eina_model_ref(*p); + if (*tmem) eina_model_unref(*tmem); + + *tmem = *p; + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_model_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + Eina_Model **tmem = (Eina_Model **)mem; + Eina_Model **p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_MODEL = { + EINA_VALUE_TYPE_VERSION, + sizeof(Eina_Model *), + "Eina_Model", + _eina_value_type_model_setup, + _eina_value_type_model_flush, + _eina_value_type_model_copy, + _eina_value_type_model_compare, + _eina_value_type_model_convert_to, + NULL, /* no convert from */ + _eina_value_type_model_vset, + _eina_value_type_model_pset, + _eina_value_type_model_pget +}; + /* keep all basic types inlined in an array so we can compare if it's * a basic type using pointer arithmetic. * @@ -4506,6 +4773,20 @@ static const Eina_Value_Type _EINA_VALUE_TYPE_BASICS[] = { _eina_value_type_string_vset, _eina_value_type_string_pset, _eina_value_type_string_common_pget + }, + { + EINA_VALUE_TYPE_VERSION, + sizeof(unsigned long), + "timestamp", + _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 } }; @@ -4722,11 +5003,12 @@ eina_value_init(void) 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_TIMESTAMP = _EINA_VALUE_TYPE_BASICS + 14; _EINA_VALUE_TYPE_BASICS_START = _EINA_VALUE_TYPE_BASICS + 0; - _EINA_VALUE_TYPE_BASICS_END = _EINA_VALUE_TYPE_BASICS + 13; + _EINA_VALUE_TYPE_BASICS_END = _EINA_VALUE_TYPE_BASICS + 14; - EINA_SAFETY_ON_FALSE_RETURN_VAL((sizeof(_EINA_VALUE_TYPE_BASICS)/sizeof(_EINA_VALUE_TYPE_BASICS[0])) == 14, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL((sizeof(_EINA_VALUE_TYPE_BASICS)/sizeof(_EINA_VALUE_TYPE_BASICS[0])) == 15, EINA_FALSE); EINA_VALUE_TYPE_ARRAY = &_EINA_VALUE_TYPE_ARRAY; @@ -4735,6 +5017,7 @@ eina_value_init(void) 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_TYPE_MODEL = &_EINA_VALUE_TYPE_MODEL; EINA_VALUE_BLOB_OPERATIONS_MALLOC = &_EINA_VALUE_BLOB_OPERATIONS_MALLOC; @@ -4800,6 +5083,7 @@ 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_TIMESTAMP = 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; @@ -4816,6 +5100,7 @@ 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_Type *EINA_VALUE_TYPE_MODEL = NULL; EAPI const Eina_Value_Blob_Operations *EINA_VALUE_BLOB_OPERATIONS_MALLOC = NULL; -- cgit v1.1