From dd7595a3475407a7fa96a97393bae8c5220e8762 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Wed, 4 Jan 2012 18:41:13 +1000 Subject: Add the base Enlightenment Foundation Libraries - eina, eet, evas, ecore, embryo, and edje. Note that embryo wont be used, but I'm not sure yet if you can build edje without it. --- libraries/eina/src/lib/Makefile.am | 171 +++ libraries/eina/src/lib/Makefile.in | 1226 +++++++++++++++ libraries/eina/src/lib/eina_accessor.c | 176 +++ libraries/eina/src/lib/eina_array.c | 491 ++++++ libraries/eina/src/lib/eina_benchmark.c | 372 +++++ libraries/eina/src/lib/eina_binbuf.c | 62 + libraries/eina/src/lib/eina_binbuf_template_c.x | 144 ++ libraries/eina/src/lib/eina_binshare.c | 127 ++ libraries/eina/src/lib/eina_convert.c | 483 ++++++ libraries/eina/src/lib/eina_counter.c | 362 +++++ libraries/eina/src/lib/eina_cpu.c | 207 +++ libraries/eina/src/lib/eina_error.c | 279 ++++ libraries/eina/src/lib/eina_file.c | 1187 +++++++++++++++ libraries/eina/src/lib/eina_file_win32.c | 1021 +++++++++++++ libraries/eina/src/lib/eina_fp.c | 532 +++++++ libraries/eina/src/lib/eina_hamster.c | 113 ++ libraries/eina/src/lib/eina_hash.c | 1375 +++++++++++++++++ libraries/eina/src/lib/eina_inlist.c | 909 +++++++++++ libraries/eina/src/lib/eina_iterator.c | 172 +++ libraries/eina/src/lib/eina_lalloc.c | 158 ++ libraries/eina/src/lib/eina_list.c | 1490 ++++++++++++++++++ libraries/eina/src/lib/eina_log.c | 1852 +++++++++++++++++++++++ libraries/eina/src/lib/eina_magic.c | 320 ++++ libraries/eina/src/lib/eina_main.c | 431 ++++++ libraries/eina/src/lib/eina_matrixsparse.c | 1421 +++++++++++++++++ libraries/eina/src/lib/eina_mempool.c | 387 +++++ libraries/eina/src/lib/eina_mmap.c | 185 +++ libraries/eina/src/lib/eina_module.c | 599 ++++++++ libraries/eina/src/lib/eina_prefix.c | 727 +++++++++ libraries/eina/src/lib/eina_private.h | 140 ++ libraries/eina/src/lib/eina_quadtree.c | 935 ++++++++++++ libraries/eina/src/lib/eina_rbtree.c | 518 +++++++ libraries/eina/src/lib/eina_rectangle.c | 568 +++++++ libraries/eina/src/lib/eina_safety_checks.c | 90 ++ libraries/eina/src/lib/eina_sched.c | 94 ++ libraries/eina/src/lib/eina_share_common.c | 977 ++++++++++++ libraries/eina/src/lib/eina_share_common.h | 103 ++ libraries/eina/src/lib/eina_simple_xml_parser.c | 1070 +++++++++++++ libraries/eina/src/lib/eina_str.c | 462 ++++++ libraries/eina/src/lib/eina_strbuf.c | 202 +++ libraries/eina/src/lib/eina_strbuf_common.c | 874 +++++++++++ libraries/eina/src/lib/eina_strbuf_common.h | 120 ++ libraries/eina/src/lib/eina_strbuf_template_c.x | 97 ++ libraries/eina/src/lib/eina_stringshare.c | 751 +++++++++ libraries/eina/src/lib/eina_tiler.c | 1276 ++++++++++++++++ libraries/eina/src/lib/eina_unicode.c | 405 +++++ libraries/eina/src/lib/eina_ustrbuf.c | 74 + libraries/eina/src/lib/eina_ustringshare.c | 132 ++ libraries/eina/src/lib/eina_value.c | 47 + libraries/eina/src/lib/eina_xattr.c | 292 ++++ 50 files changed, 26206 insertions(+) create mode 100644 libraries/eina/src/lib/Makefile.am create mode 100644 libraries/eina/src/lib/Makefile.in create mode 100644 libraries/eina/src/lib/eina_accessor.c create mode 100644 libraries/eina/src/lib/eina_array.c create mode 100644 libraries/eina/src/lib/eina_benchmark.c create mode 100644 libraries/eina/src/lib/eina_binbuf.c create mode 100644 libraries/eina/src/lib/eina_binbuf_template_c.x create mode 100644 libraries/eina/src/lib/eina_binshare.c create mode 100644 libraries/eina/src/lib/eina_convert.c create mode 100644 libraries/eina/src/lib/eina_counter.c create mode 100644 libraries/eina/src/lib/eina_cpu.c create mode 100644 libraries/eina/src/lib/eina_error.c create mode 100644 libraries/eina/src/lib/eina_file.c create mode 100644 libraries/eina/src/lib/eina_file_win32.c create mode 100644 libraries/eina/src/lib/eina_fp.c create mode 100644 libraries/eina/src/lib/eina_hamster.c create mode 100644 libraries/eina/src/lib/eina_hash.c create mode 100644 libraries/eina/src/lib/eina_inlist.c create mode 100644 libraries/eina/src/lib/eina_iterator.c create mode 100644 libraries/eina/src/lib/eina_lalloc.c create mode 100644 libraries/eina/src/lib/eina_list.c create mode 100644 libraries/eina/src/lib/eina_log.c create mode 100644 libraries/eina/src/lib/eina_magic.c create mode 100644 libraries/eina/src/lib/eina_main.c create mode 100644 libraries/eina/src/lib/eina_matrixsparse.c create mode 100644 libraries/eina/src/lib/eina_mempool.c create mode 100644 libraries/eina/src/lib/eina_mmap.c create mode 100644 libraries/eina/src/lib/eina_module.c create mode 100644 libraries/eina/src/lib/eina_prefix.c create mode 100644 libraries/eina/src/lib/eina_private.h create mode 100644 libraries/eina/src/lib/eina_quadtree.c create mode 100644 libraries/eina/src/lib/eina_rbtree.c create mode 100644 libraries/eina/src/lib/eina_rectangle.c create mode 100644 libraries/eina/src/lib/eina_safety_checks.c create mode 100644 libraries/eina/src/lib/eina_sched.c create mode 100644 libraries/eina/src/lib/eina_share_common.c create mode 100644 libraries/eina/src/lib/eina_share_common.h create mode 100644 libraries/eina/src/lib/eina_simple_xml_parser.c create mode 100644 libraries/eina/src/lib/eina_str.c create mode 100644 libraries/eina/src/lib/eina_strbuf.c create mode 100644 libraries/eina/src/lib/eina_strbuf_common.c create mode 100644 libraries/eina/src/lib/eina_strbuf_common.h create mode 100644 libraries/eina/src/lib/eina_strbuf_template_c.x create mode 100644 libraries/eina/src/lib/eina_stringshare.c create mode 100644 libraries/eina/src/lib/eina_tiler.c create mode 100644 libraries/eina/src/lib/eina_unicode.c create mode 100644 libraries/eina/src/lib/eina_ustrbuf.c create mode 100644 libraries/eina/src/lib/eina_ustringshare.c create mode 100644 libraries/eina/src/lib/eina_value.c create mode 100644 libraries/eina/src/lib/eina_xattr.c (limited to 'libraries/eina/src/lib') diff --git a/libraries/eina/src/lib/Makefile.am b/libraries/eina/src/lib/Makefile.am new file mode 100644 index 0000000..0537a61 --- /dev/null +++ b/libraries/eina/src/lib/Makefile.am @@ -0,0 +1,171 @@ +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I$(top_srcdir)/src/include \ +-I$(top_builddir)/src/include \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" \ +-DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ +@EINA_CPPFLAGS@ \ +@EFL_EINA_BUILD@ + +base_sources = \ +eina_accessor.c \ +eina_array.c \ +eina_benchmark.c \ +eina_binbuf.c \ +eina_binshare.c \ +eina_convert.c \ +eina_counter.c \ +eina_cpu.c \ +eina_error.c \ +eina_fp.c \ +eina_hamster.c \ +eina_hash.c \ +eina_inlist.c \ +eina_iterator.c \ +eina_lalloc.c \ +eina_list.c \ +eina_log.c \ +eina_magic.c \ +eina_main.c \ +eina_matrixsparse.c \ +eina_mempool.c \ +eina_mmap.c \ +eina_module.c \ +eina_prefix.c \ +eina_quadtree.c \ +eina_rbtree.c \ +eina_rectangle.c \ +eina_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 + +# Will be back for developper after 1.1 +# eina_object.c + +if EINA_HAVE_WIN32 +base_sources += eina_file_win32.c +else +base_sources += eina_file.c +endif + +EXTRA_DIST = \ +eina_share_common.h \ +eina_private.h \ +eina_strbuf_common.h \ +eina_strbuf_template_c.x \ +eina_binbuf_template_c.x + + + +if EINA_STATIC_BUILD_BUDDY +base_sources += $(top_srcdir)/src/modules/mp/buddy/eina_buddy.c +endif + +if EINA_STATIC_BUILD_CHAINED_POOL +base_sources += $(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c +endif + +if EINA_STATIC_BUILD_EMEMOA_FIXED +base_sources += $(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c +endif + +if EINA_STATIC_BUILD_EMEMOA_UNKNOWN +base_sources += $(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c +endif + +if EINA_STATIC_BUILD_FIXED_BITMAP +base_sources += $(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c +endif + +if EINA_STATIC_BUILD_ONE_BIG +base_sources += $(top_srcdir)/src/modules/mp/one_big/eina_one_big.c +endif + +if EINA_STATIC_BUILD_PASS_THROUGH +base_sources += $(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.c +endif + +lib_LTLIBRARIES = libeina.la + +if EINA_AMALGAMATION +nodist_libeina_la_SOURCES = eina_amalgamation.c + +eina_amalgamation.c: $(base_sources) Makefile + -rm -f eina_amalgamation.c + + @echo "#ifdef HAVE_CONFIG_H" >> eina_amalgamation.c + @echo "#include \"config.h\"" >> eina_amalgamation.c + @echo "#endif" >> eina_amalgamation.c + + @echo "#ifdef HAVE_ALLOCA_H" >> eina_amalgamation.c + @echo "# include " >> eina_amalgamation.c + @echo "#elif defined __GNUC__" >> eina_amalgamation.c + @echo "# define alloca __builtin_alloca" >> eina_amalgamation.c + @echo "#elif defined _AIX" >> eina_amalgamation.c + @echo "# define alloca __alloca" >> eina_amalgamation.c + @echo "#elif defined _MSC_VER" >> eina_amalgamation.c + @echo "# include " >> eina_amalgamation.c + @echo "# define alloca _alloca" >> eina_amalgamation.c + @echo "#else" >> eina_amalgamation.c + @echo "# include " >> eina_amalgamation.c + @echo "# ifdef __cplusplus" >> eina_amalgamation.c + @echo "#extern \"C\"" >> eina_amalgamation.c + @echo "# endif" >> eina_amalgamation.c + @echo "#void *alloca (size_t);" >> eina_amalgamation.c + @echo "#endif" >> eina_amalgamation.c + + @echo "#include " >> eina_amalgamation.c + @echo "#include " >> eina_amalgamation.c + @echo "#include " >> eina_amalgamation.c + @echo "#include " >> eina_amalgamation.c + @echo "#include " >> eina_amalgamation.c + @echo "#include " >> eina_amalgamation.c + @echo "#include " >> eina_amalgamation.c + @echo "#include " >> eina_amalgamation.c + @echo "#include " >> eina_amalgamation.c + + @echo "#ifdef HAVE_EVIL" >> eina_amalgamation.c + @echo "# include " >> eina_amalgamation.c + @echo "#endif" >> eina_amalgamation.c + + @echo "#include \"eina_config.h\"" >> eina_amalgamation.c + @echo "#include \"eina_private.h\"" >> eina_amalgamation.c + @echo "#include \"eina_safety_checks.h\"" >> eina_amalgamation.c + @echo "#include \"Eina.h\"" >> eina_amalgamation.c + @echo "#include \"eina_strbuf_common.h\"" >> eina_amalgamation.c + @echo "#include \"eina_share_common.h\"" >> eina_amalgamation.c + + @for f in $(base_sources); do \ + if [ `echo $$f | sed -e 's/^...\(.\).*/\1/'` != '/' ]; then \ + file="$(srcdir)/$$f" ; \ + else \ + file="$$f" ; \ + fi ; \ + echo "/* file: $$file */" >> eina_amalgamation.c; \ + grep -v -e '^# *include \+.\(config\|eina_[a-z_]\+\|Evil\|stdio\|stdlib\|string\|dlfcn\|dirent\|assert\|errno\|fnmatch\)[.]h.*' $$file >> eina_amalgamation.c; \ + done + @echo "eina_amalgamation.c generated" + +else +libeina_la_SOURCES = $(base_sources) +endif + +libeina_la_LIBADD = @iconv_libs@ @rt_libs@ @EINA_LIBS@ @dlopen_libs@ +libeina_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@ @EFL_PTHREAD_LIBS@ +libeina_la_CFLAGS = @EINA_CFLAGS@ @EFL_PTHREAD_CFLAGS@ + +clean-local: + rm -rf *.gcno eina_amalgamation.c diff --git a/libraries/eina/src/lib/Makefile.in b/libraries/eina/src/lib/Makefile.in new file mode 100644 index 0000000..359aba0 --- /dev/null +++ b/libraries/eina/src/lib/Makefile.in @@ -0,0 +1,1226 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ + +# Will be back for developper after 1.1 +# eina_object.c +@EINA_HAVE_WIN32_TRUE@am__append_1 = eina_file_win32.c +@EINA_HAVE_WIN32_FALSE@am__append_2 = eina_file.c +@EINA_STATIC_BUILD_BUDDY_TRUE@am__append_3 = $(top_srcdir)/src/modules/mp/buddy/eina_buddy.c +@EINA_STATIC_BUILD_CHAINED_POOL_TRUE@am__append_4 = $(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c +@EINA_STATIC_BUILD_EMEMOA_FIXED_TRUE@am__append_5 = $(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c +@EINA_STATIC_BUILD_EMEMOA_UNKNOWN_TRUE@am__append_6 = $(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c +@EINA_STATIC_BUILD_FIXED_BITMAP_TRUE@am__append_7 = $(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c +@EINA_STATIC_BUILD_ONE_BIG_TRUE@am__append_8 = $(top_srcdir)/src/modules/mp/one_big/eina_one_big.c +@EINA_STATIC_BUILD_PASS_THROUGH_TRUE@am__append_9 = $(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.c +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__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(libdir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +libeina_la_DEPENDENCIES = +am__libeina_la_SOURCES_DIST = eina_accessor.c eina_array.c \ + eina_benchmark.c eina_binbuf.c eina_binshare.c eina_convert.c \ + eina_counter.c eina_cpu.c eina_error.c eina_fp.c \ + eina_hamster.c eina_hash.c eina_inlist.c eina_iterator.c \ + eina_lalloc.c eina_list.c eina_log.c eina_magic.c eina_main.c \ + eina_matrixsparse.c eina_mempool.c eina_mmap.c eina_module.c \ + eina_prefix.c eina_quadtree.c eina_rbtree.c eina_rectangle.c \ + eina_safety_checks.c eina_sched.c eina_share_common.c \ + eina_simple_xml_parser.c eina_str.c eina_strbuf.c \ + eina_strbuf_common.c eina_stringshare.c eina_tiler.c \ + eina_unicode.c eina_ustrbuf.c eina_ustringshare.c eina_value.c \ + eina_xattr.c eina_file_win32.c eina_file.c \ + $(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 \ + $(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c \ + $(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c \ + $(top_srcdir)/src/modules/mp/one_big/eina_one_big.c \ + $(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.c +@EINA_HAVE_WIN32_TRUE@am__objects_1 = libeina_la-eina_file_win32.lo +@EINA_HAVE_WIN32_FALSE@am__objects_2 = libeina_la-eina_file.lo +@EINA_STATIC_BUILD_BUDDY_TRUE@am__objects_3 = \ +@EINA_STATIC_BUILD_BUDDY_TRUE@ libeina_la-eina_buddy.lo +@EINA_STATIC_BUILD_CHAINED_POOL_TRUE@am__objects_4 = libeina_la-eina_chained_mempool.lo +@EINA_STATIC_BUILD_EMEMOA_FIXED_TRUE@am__objects_5 = libeina_la-eina_ememoa_fixed.lo +@EINA_STATIC_BUILD_EMEMOA_UNKNOWN_TRUE@am__objects_6 = libeina_la-eina_ememoa_unknown.lo +@EINA_STATIC_BUILD_FIXED_BITMAP_TRUE@am__objects_7 = libeina_la-eina_fixed_bitmap.lo +@EINA_STATIC_BUILD_ONE_BIG_TRUE@am__objects_8 = \ +@EINA_STATIC_BUILD_ONE_BIG_TRUE@ libeina_la-eina_one_big.lo +@EINA_STATIC_BUILD_PASS_THROUGH_TRUE@am__objects_9 = libeina_la-eina_pass_through.lo +am__objects_10 = libeina_la-eina_accessor.lo libeina_la-eina_array.lo \ + libeina_la-eina_benchmark.lo libeina_la-eina_binbuf.lo \ + libeina_la-eina_binshare.lo libeina_la-eina_convert.lo \ + libeina_la-eina_counter.lo libeina_la-eina_cpu.lo \ + libeina_la-eina_error.lo libeina_la-eina_fp.lo \ + libeina_la-eina_hamster.lo libeina_la-eina_hash.lo \ + libeina_la-eina_inlist.lo libeina_la-eina_iterator.lo \ + libeina_la-eina_lalloc.lo libeina_la-eina_list.lo \ + libeina_la-eina_log.lo libeina_la-eina_magic.lo \ + libeina_la-eina_main.lo libeina_la-eina_matrixsparse.lo \ + libeina_la-eina_mempool.lo libeina_la-eina_mmap.lo \ + libeina_la-eina_module.lo libeina_la-eina_prefix.lo \ + libeina_la-eina_quadtree.lo libeina_la-eina_rbtree.lo \ + libeina_la-eina_rectangle.lo libeina_la-eina_safety_checks.lo \ + libeina_la-eina_sched.lo libeina_la-eina_share_common.lo \ + libeina_la-eina_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 \ + libeina_la-eina_unicode.lo libeina_la-eina_ustrbuf.lo \ + libeina_la-eina_ustringshare.lo libeina_la-eina_value.lo \ + libeina_la-eina_xattr.lo $(am__objects_1) $(am__objects_2) \ + $(am__objects_3) $(am__objects_4) $(am__objects_5) \ + $(am__objects_6) $(am__objects_7) $(am__objects_8) \ + $(am__objects_9) +@EINA_AMALGAMATION_FALSE@am_libeina_la_OBJECTS = $(am__objects_10) +@EINA_AMALGAMATION_TRUE@nodist_libeina_la_OBJECTS = \ +@EINA_AMALGAMATION_TRUE@ libeina_la-eina_amalgamation.lo +libeina_la_OBJECTS = $(am_libeina_la_OBJECTS) \ + $(nodist_libeina_la_OBJECTS) +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +libeina_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libeina_la_CFLAGS) \ + $(CFLAGS) $(libeina_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libeina_la_SOURCES) $(nodist_libeina_la_SOURCES) +DIST_SOURCES = $(am__libeina_la_SOURCES_DIST) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CHECK_CFLAGS = @CHECK_CFLAGS@ +CHECK_LIBS = @CHECK_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +ECORE_EVAS_CFLAGS = @ECORE_EVAS_CFLAGS@ +ECORE_EVAS_LIBS = @ECORE_EVAS_LIBS@ +EFL_COVERAGE_CFLAGS = @EFL_COVERAGE_CFLAGS@ +EFL_COVERAGE_LIBS = @EFL_COVERAGE_LIBS@ +EFL_EINA_BUILD = @EFL_EINA_BUILD@ +EFL_FNMATCH_LIBS = @EFL_FNMATCH_LIBS@ +EFL_PTHREAD_CFLAGS = @EFL_PTHREAD_CFLAGS@ +EFL_PTHREAD_LIBS = @EFL_PTHREAD_LIBS@ +EFL_SIMD_FLAGS = @EFL_SIMD_FLAGS@ +EGREP = @EGREP@ +EINA_CFLAGS = @EINA_CFLAGS@ +EINA_CONFIGURE_DEFAULT_MEMPOOL = @EINA_CONFIGURE_DEFAULT_MEMPOOL@ +EINA_CONFIGURE_HAVE_DEBUG_THREADS = @EINA_CONFIGURE_HAVE_DEBUG_THREADS@ +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@ +EMEMOA_LIBS = @EMEMOA_LIBS@ +ESCAPE_CFLAGS = @ESCAPE_CFLAGS@ +ESCAPE_LIBS = @ESCAPE_LIBS@ +EVIL_CFLAGS = @EVIL_CFLAGS@ +EVIL_LIBS = @EVIL_LIBS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_LIBS = @GLIB_LIBS@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MODULE_ARCH = @MODULE_ARCH@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +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@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VERSION = @VERSION@ +VMAJ = @VMAJ@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dlopen_libs = @dlopen_libs@ +docdir = @docdir@ +dvidir = @dvidir@ +efl_doxygen = @efl_doxygen@ +efl_have_doxygen = @efl_have_doxygen@ +exec_prefix = @exec_prefix@ +have_lcov = @have_lcov@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +iconv_libs = @iconv_libs@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +lt_enable_auto_import = @lt_enable_auto_import@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgconfig_requires_private = @pkgconfig_requires_private@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +release_info = @release_info@ +requirement_eina = @requirement_eina@ +rt_libs = @rt_libs@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +version_info = @version_info@ +MAINTAINERCLEANFILES = Makefile.in +AM_CPPFLAGS = \ +-I$(top_srcdir)/src/include \ +-I$(top_builddir)/src/include \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" \ +-DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ +@EINA_CPPFLAGS@ \ +@EFL_EINA_BUILD@ + +base_sources = eina_accessor.c eina_array.c eina_benchmark.c \ + eina_binbuf.c eina_binshare.c eina_convert.c eina_counter.c \ + eina_cpu.c eina_error.c eina_fp.c eina_hamster.c eina_hash.c \ + eina_inlist.c eina_iterator.c eina_lalloc.c eina_list.c \ + eina_log.c eina_magic.c eina_main.c eina_matrixsparse.c \ + eina_mempool.c eina_mmap.c eina_module.c eina_prefix.c \ + eina_quadtree.c eina_rbtree.c eina_rectangle.c \ + eina_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 \ +eina_strbuf_common.h \ +eina_strbuf_template_c.x \ +eina_binbuf_template_c.x + +lib_LTLIBRARIES = libeina.la +@EINA_AMALGAMATION_TRUE@nodist_libeina_la_SOURCES = eina_amalgamation.c +@EINA_AMALGAMATION_FALSE@libeina_la_SOURCES = $(base_sources) +libeina_la_LIBADD = @iconv_libs@ @rt_libs@ @EINA_LIBS@ @dlopen_libs@ +libeina_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@ @EFL_PTHREAD_LIBS@ +libeina_la_CFLAGS = @EINA_CFLAGS@ @EFL_PTHREAD_CFLAGS@ +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/lib/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/lib/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libeina.la: $(libeina_la_OBJECTS) $(libeina_la_DEPENDENCIES) + $(AM_V_CCLD)$(libeina_la_LINK) -rpath $(libdir) $(libeina_la_OBJECTS) $(libeina_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_accessor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_amalgamation.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_array.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_benchmark.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_binbuf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_binshare.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_buddy.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_chained_mempool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_convert.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_counter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_cpu.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_ememoa_fixed.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_ememoa_unknown.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_error.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_file.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_file_win32.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_fixed_bitmap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_fp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_hamster.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_hash.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_inlist.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_iterator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_lalloc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_list.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_log.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_magic.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_main.Plo@am__quote@ +@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_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@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_prefix.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_quadtree.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_rbtree.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_rectangle.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_safety_checks.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_sched.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_share_common.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_simple_xml_parser.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_str.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_strbuf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_strbuf_common.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_stringshare.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_tiler.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_unicode.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_ustrbuf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_ustringshare.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_value.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeina_la-eina_xattr.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +libeina_la-eina_accessor.lo: eina_accessor.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_accessor.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_accessor.Tpo -c -o libeina_la-eina_accessor.lo `test -f 'eina_accessor.c' || echo '$(srcdir)/'`eina_accessor.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_accessor.Tpo $(DEPDIR)/libeina_la-eina_accessor.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_accessor.c' object='libeina_la-eina_accessor.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_accessor.lo `test -f 'eina_accessor.c' || echo '$(srcdir)/'`eina_accessor.c + +libeina_la-eina_array.lo: eina_array.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_array.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_array.Tpo -c -o libeina_la-eina_array.lo `test -f 'eina_array.c' || echo '$(srcdir)/'`eina_array.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_array.Tpo $(DEPDIR)/libeina_la-eina_array.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_array.c' object='libeina_la-eina_array.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_array.lo `test -f 'eina_array.c' || echo '$(srcdir)/'`eina_array.c + +libeina_la-eina_benchmark.lo: eina_benchmark.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_benchmark.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_benchmark.Tpo -c -o libeina_la-eina_benchmark.lo `test -f 'eina_benchmark.c' || echo '$(srcdir)/'`eina_benchmark.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_benchmark.Tpo $(DEPDIR)/libeina_la-eina_benchmark.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_benchmark.c' object='libeina_la-eina_benchmark.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_benchmark.lo `test -f 'eina_benchmark.c' || echo '$(srcdir)/'`eina_benchmark.c + +libeina_la-eina_binbuf.lo: eina_binbuf.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_binbuf.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_binbuf.Tpo -c -o libeina_la-eina_binbuf.lo `test -f 'eina_binbuf.c' || echo '$(srcdir)/'`eina_binbuf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_binbuf.Tpo $(DEPDIR)/libeina_la-eina_binbuf.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_binbuf.c' object='libeina_la-eina_binbuf.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_binbuf.lo `test -f 'eina_binbuf.c' || echo '$(srcdir)/'`eina_binbuf.c + +libeina_la-eina_binshare.lo: eina_binshare.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_binshare.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_binshare.Tpo -c -o libeina_la-eina_binshare.lo `test -f 'eina_binshare.c' || echo '$(srcdir)/'`eina_binshare.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_binshare.Tpo $(DEPDIR)/libeina_la-eina_binshare.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_binshare.c' object='libeina_la-eina_binshare.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_binshare.lo `test -f 'eina_binshare.c' || echo '$(srcdir)/'`eina_binshare.c + +libeina_la-eina_convert.lo: eina_convert.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_convert.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_convert.Tpo -c -o libeina_la-eina_convert.lo `test -f 'eina_convert.c' || echo '$(srcdir)/'`eina_convert.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_convert.Tpo $(DEPDIR)/libeina_la-eina_convert.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_convert.c' object='libeina_la-eina_convert.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_convert.lo `test -f 'eina_convert.c' || echo '$(srcdir)/'`eina_convert.c + +libeina_la-eina_counter.lo: eina_counter.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_counter.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_counter.Tpo -c -o libeina_la-eina_counter.lo `test -f 'eina_counter.c' || echo '$(srcdir)/'`eina_counter.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_counter.Tpo $(DEPDIR)/libeina_la-eina_counter.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_counter.c' object='libeina_la-eina_counter.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_counter.lo `test -f 'eina_counter.c' || echo '$(srcdir)/'`eina_counter.c + +libeina_la-eina_cpu.lo: eina_cpu.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_cpu.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_cpu.Tpo -c -o libeina_la-eina_cpu.lo `test -f 'eina_cpu.c' || echo '$(srcdir)/'`eina_cpu.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_cpu.Tpo $(DEPDIR)/libeina_la-eina_cpu.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_cpu.c' object='libeina_la-eina_cpu.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_cpu.lo `test -f 'eina_cpu.c' || echo '$(srcdir)/'`eina_cpu.c + +libeina_la-eina_error.lo: eina_error.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_error.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_error.Tpo -c -o libeina_la-eina_error.lo `test -f 'eina_error.c' || echo '$(srcdir)/'`eina_error.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_error.Tpo $(DEPDIR)/libeina_la-eina_error.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_error.c' object='libeina_la-eina_error.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_error.lo `test -f 'eina_error.c' || echo '$(srcdir)/'`eina_error.c + +libeina_la-eina_fp.lo: eina_fp.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_fp.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_fp.Tpo -c -o libeina_la-eina_fp.lo `test -f 'eina_fp.c' || echo '$(srcdir)/'`eina_fp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_fp.Tpo $(DEPDIR)/libeina_la-eina_fp.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_fp.c' object='libeina_la-eina_fp.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_fp.lo `test -f 'eina_fp.c' || echo '$(srcdir)/'`eina_fp.c + +libeina_la-eina_hamster.lo: eina_hamster.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_hamster.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_hamster.Tpo -c -o libeina_la-eina_hamster.lo `test -f 'eina_hamster.c' || echo '$(srcdir)/'`eina_hamster.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_hamster.Tpo $(DEPDIR)/libeina_la-eina_hamster.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_hamster.c' object='libeina_la-eina_hamster.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_hamster.lo `test -f 'eina_hamster.c' || echo '$(srcdir)/'`eina_hamster.c + +libeina_la-eina_hash.lo: eina_hash.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_hash.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_hash.Tpo -c -o libeina_la-eina_hash.lo `test -f 'eina_hash.c' || echo '$(srcdir)/'`eina_hash.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_hash.Tpo $(DEPDIR)/libeina_la-eina_hash.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_hash.c' object='libeina_la-eina_hash.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_hash.lo `test -f 'eina_hash.c' || echo '$(srcdir)/'`eina_hash.c + +libeina_la-eina_inlist.lo: eina_inlist.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeina_la_CFLAGS) $(CFLAGS) -MT libeina_la-eina_inlist.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_inlist.Tpo -c -o libeina_la-eina_inlist.lo `test -f 'eina_inlist.c' || echo '$(srcdir)/'`eina_inlist.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_inlist.Tpo $(DEPDIR)/libeina_la-eina_inlist.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_inlist.c' object='libeina_la-eina_inlist.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_inlist.lo `test -f 'eina_inlist.c' || echo '$(srcdir)/'`eina_inlist.c + +libeina_la-eina_iterator.lo: eina_iterator.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_iterator.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_iterator.Tpo -c -o libeina_la-eina_iterator.lo `test -f 'eina_iterator.c' || echo '$(srcdir)/'`eina_iterator.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_iterator.Tpo $(DEPDIR)/libeina_la-eina_iterator.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_iterator.c' object='libeina_la-eina_iterator.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_iterator.lo `test -f 'eina_iterator.c' || echo '$(srcdir)/'`eina_iterator.c + +libeina_la-eina_lalloc.lo: eina_lalloc.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_lalloc.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_lalloc.Tpo -c -o libeina_la-eina_lalloc.lo `test -f 'eina_lalloc.c' || echo '$(srcdir)/'`eina_lalloc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_lalloc.Tpo $(DEPDIR)/libeina_la-eina_lalloc.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_lalloc.c' object='libeina_la-eina_lalloc.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_lalloc.lo `test -f 'eina_lalloc.c' || echo '$(srcdir)/'`eina_lalloc.c + +libeina_la-eina_list.lo: eina_list.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_list.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_list.Tpo -c -o libeina_la-eina_list.lo `test -f 'eina_list.c' || echo '$(srcdir)/'`eina_list.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_list.Tpo $(DEPDIR)/libeina_la-eina_list.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_list.c' object='libeina_la-eina_list.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_list.lo `test -f 'eina_list.c' || echo '$(srcdir)/'`eina_list.c + +libeina_la-eina_log.lo: eina_log.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_log.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_log.Tpo -c -o libeina_la-eina_log.lo `test -f 'eina_log.c' || echo '$(srcdir)/'`eina_log.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_log.Tpo $(DEPDIR)/libeina_la-eina_log.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_log.c' object='libeina_la-eina_log.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_log.lo `test -f 'eina_log.c' || echo '$(srcdir)/'`eina_log.c + +libeina_la-eina_magic.lo: eina_magic.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_magic.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_magic.Tpo -c -o libeina_la-eina_magic.lo `test -f 'eina_magic.c' || echo '$(srcdir)/'`eina_magic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_magic.Tpo $(DEPDIR)/libeina_la-eina_magic.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_magic.c' object='libeina_la-eina_magic.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_magic.lo `test -f 'eina_magic.c' || echo '$(srcdir)/'`eina_magic.c + +libeina_la-eina_main.lo: eina_main.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_main.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_main.Tpo -c -o libeina_la-eina_main.lo `test -f 'eina_main.c' || echo '$(srcdir)/'`eina_main.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_main.Tpo $(DEPDIR)/libeina_la-eina_main.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_main.c' object='libeina_la-eina_main.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_main.lo `test -f 'eina_main.c' || echo '$(srcdir)/'`eina_main.c + +libeina_la-eina_matrixsparse.lo: eina_matrixsparse.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_matrixsparse.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_matrixsparse.Tpo -c -o libeina_la-eina_matrixsparse.lo `test -f 'eina_matrixsparse.c' || echo '$(srcdir)/'`eina_matrixsparse.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_matrixsparse.Tpo $(DEPDIR)/libeina_la-eina_matrixsparse.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_matrixsparse.c' object='libeina_la-eina_matrixsparse.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_matrixsparse.lo `test -f 'eina_matrixsparse.c' || echo '$(srcdir)/'`eina_matrixsparse.c + +libeina_la-eina_mempool.lo: eina_mempool.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_mempool.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_mempool.Tpo -c -o libeina_la-eina_mempool.lo `test -f 'eina_mempool.c' || echo '$(srcdir)/'`eina_mempool.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_mempool.Tpo $(DEPDIR)/libeina_la-eina_mempool.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_mempool.c' object='libeina_la-eina_mempool.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_mempool.lo `test -f 'eina_mempool.c' || echo '$(srcdir)/'`eina_mempool.c + +libeina_la-eina_mmap.lo: eina_mmap.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_mmap.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_mmap.Tpo -c -o libeina_la-eina_mmap.lo `test -f 'eina_mmap.c' || echo '$(srcdir)/'`eina_mmap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_mmap.Tpo $(DEPDIR)/libeina_la-eina_mmap.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_mmap.c' object='libeina_la-eina_mmap.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_mmap.lo `test -f 'eina_mmap.c' || echo '$(srcdir)/'`eina_mmap.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 +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_module.c' object='libeina_la-eina_module.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_module.lo `test -f 'eina_module.c' || echo '$(srcdir)/'`eina_module.c + +libeina_la-eina_prefix.lo: eina_prefix.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_prefix.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_prefix.Tpo -c -o libeina_la-eina_prefix.lo `test -f 'eina_prefix.c' || echo '$(srcdir)/'`eina_prefix.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_prefix.Tpo $(DEPDIR)/libeina_la-eina_prefix.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_prefix.c' object='libeina_la-eina_prefix.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_prefix.lo `test -f 'eina_prefix.c' || echo '$(srcdir)/'`eina_prefix.c + +libeina_la-eina_quadtree.lo: eina_quadtree.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_quadtree.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_quadtree.Tpo -c -o libeina_la-eina_quadtree.lo `test -f 'eina_quadtree.c' || echo '$(srcdir)/'`eina_quadtree.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_quadtree.Tpo $(DEPDIR)/libeina_la-eina_quadtree.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_quadtree.c' object='libeina_la-eina_quadtree.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_quadtree.lo `test -f 'eina_quadtree.c' || echo '$(srcdir)/'`eina_quadtree.c + +libeina_la-eina_rbtree.lo: eina_rbtree.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_rbtree.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_rbtree.Tpo -c -o libeina_la-eina_rbtree.lo `test -f 'eina_rbtree.c' || echo '$(srcdir)/'`eina_rbtree.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_rbtree.Tpo $(DEPDIR)/libeina_la-eina_rbtree.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_rbtree.c' object='libeina_la-eina_rbtree.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_rbtree.lo `test -f 'eina_rbtree.c' || echo '$(srcdir)/'`eina_rbtree.c + +libeina_la-eina_rectangle.lo: eina_rectangle.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_rectangle.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_rectangle.Tpo -c -o libeina_la-eina_rectangle.lo `test -f 'eina_rectangle.c' || echo '$(srcdir)/'`eina_rectangle.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_rectangle.Tpo $(DEPDIR)/libeina_la-eina_rectangle.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_rectangle.c' object='libeina_la-eina_rectangle.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_rectangle.lo `test -f 'eina_rectangle.c' || echo '$(srcdir)/'`eina_rectangle.c + +libeina_la-eina_safety_checks.lo: eina_safety_checks.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_safety_checks.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_safety_checks.Tpo -c -o libeina_la-eina_safety_checks.lo `test -f 'eina_safety_checks.c' || echo '$(srcdir)/'`eina_safety_checks.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_safety_checks.Tpo $(DEPDIR)/libeina_la-eina_safety_checks.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_safety_checks.c' object='libeina_la-eina_safety_checks.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_safety_checks.lo `test -f 'eina_safety_checks.c' || echo '$(srcdir)/'`eina_safety_checks.c + +libeina_la-eina_sched.lo: eina_sched.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_sched.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_sched.Tpo -c -o libeina_la-eina_sched.lo `test -f 'eina_sched.c' || echo '$(srcdir)/'`eina_sched.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_sched.Tpo $(DEPDIR)/libeina_la-eina_sched.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_sched.c' object='libeina_la-eina_sched.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_sched.lo `test -f 'eina_sched.c' || echo '$(srcdir)/'`eina_sched.c + +libeina_la-eina_share_common.lo: eina_share_common.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_share_common.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_share_common.Tpo -c -o libeina_la-eina_share_common.lo `test -f 'eina_share_common.c' || echo '$(srcdir)/'`eina_share_common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_share_common.Tpo $(DEPDIR)/libeina_la-eina_share_common.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_share_common.c' object='libeina_la-eina_share_common.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_share_common.lo `test -f 'eina_share_common.c' || echo '$(srcdir)/'`eina_share_common.c + +libeina_la-eina_simple_xml_parser.lo: eina_simple_xml_parser.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_simple_xml_parser.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_simple_xml_parser.Tpo -c -o libeina_la-eina_simple_xml_parser.lo `test -f 'eina_simple_xml_parser.c' || echo '$(srcdir)/'`eina_simple_xml_parser.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_simple_xml_parser.Tpo $(DEPDIR)/libeina_la-eina_simple_xml_parser.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_simple_xml_parser.c' object='libeina_la-eina_simple_xml_parser.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_simple_xml_parser.lo `test -f 'eina_simple_xml_parser.c' || echo '$(srcdir)/'`eina_simple_xml_parser.c + +libeina_la-eina_str.lo: eina_str.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_str.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_str.Tpo -c -o libeina_la-eina_str.lo `test -f 'eina_str.c' || echo '$(srcdir)/'`eina_str.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_str.Tpo $(DEPDIR)/libeina_la-eina_str.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_str.c' object='libeina_la-eina_str.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_str.lo `test -f 'eina_str.c' || echo '$(srcdir)/'`eina_str.c + +libeina_la-eina_strbuf.lo: eina_strbuf.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_strbuf.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_strbuf.Tpo -c -o libeina_la-eina_strbuf.lo `test -f 'eina_strbuf.c' || echo '$(srcdir)/'`eina_strbuf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_strbuf.Tpo $(DEPDIR)/libeina_la-eina_strbuf.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_strbuf.c' object='libeina_la-eina_strbuf.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_strbuf.lo `test -f 'eina_strbuf.c' || echo '$(srcdir)/'`eina_strbuf.c + +libeina_la-eina_strbuf_common.lo: eina_strbuf_common.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_strbuf_common.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_strbuf_common.Tpo -c -o libeina_la-eina_strbuf_common.lo `test -f 'eina_strbuf_common.c' || echo '$(srcdir)/'`eina_strbuf_common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_strbuf_common.Tpo $(DEPDIR)/libeina_la-eina_strbuf_common.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_strbuf_common.c' object='libeina_la-eina_strbuf_common.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_strbuf_common.lo `test -f 'eina_strbuf_common.c' || echo '$(srcdir)/'`eina_strbuf_common.c + +libeina_la-eina_stringshare.lo: eina_stringshare.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_stringshare.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_stringshare.Tpo -c -o libeina_la-eina_stringshare.lo `test -f 'eina_stringshare.c' || echo '$(srcdir)/'`eina_stringshare.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_stringshare.Tpo $(DEPDIR)/libeina_la-eina_stringshare.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_stringshare.c' object='libeina_la-eina_stringshare.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_stringshare.lo `test -f 'eina_stringshare.c' || echo '$(srcdir)/'`eina_stringshare.c + +libeina_la-eina_tiler.lo: eina_tiler.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_tiler.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_tiler.Tpo -c -o libeina_la-eina_tiler.lo `test -f 'eina_tiler.c' || echo '$(srcdir)/'`eina_tiler.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_tiler.Tpo $(DEPDIR)/libeina_la-eina_tiler.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_tiler.c' object='libeina_la-eina_tiler.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_tiler.lo `test -f 'eina_tiler.c' || echo '$(srcdir)/'`eina_tiler.c + +libeina_la-eina_unicode.lo: eina_unicode.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_unicode.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_unicode.Tpo -c -o libeina_la-eina_unicode.lo `test -f 'eina_unicode.c' || echo '$(srcdir)/'`eina_unicode.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_unicode.Tpo $(DEPDIR)/libeina_la-eina_unicode.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_unicode.c' object='libeina_la-eina_unicode.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_unicode.lo `test -f 'eina_unicode.c' || echo '$(srcdir)/'`eina_unicode.c + +libeina_la-eina_ustrbuf.lo: eina_ustrbuf.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_ustrbuf.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_ustrbuf.Tpo -c -o libeina_la-eina_ustrbuf.lo `test -f 'eina_ustrbuf.c' || echo '$(srcdir)/'`eina_ustrbuf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_ustrbuf.Tpo $(DEPDIR)/libeina_la-eina_ustrbuf.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_ustrbuf.c' object='libeina_la-eina_ustrbuf.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_ustrbuf.lo `test -f 'eina_ustrbuf.c' || echo '$(srcdir)/'`eina_ustrbuf.c + +libeina_la-eina_ustringshare.lo: eina_ustringshare.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_ustringshare.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_ustringshare.Tpo -c -o libeina_la-eina_ustringshare.lo `test -f 'eina_ustringshare.c' || echo '$(srcdir)/'`eina_ustringshare.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_ustringshare.Tpo $(DEPDIR)/libeina_la-eina_ustringshare.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_ustringshare.c' object='libeina_la-eina_ustringshare.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_ustringshare.lo `test -f 'eina_ustringshare.c' || echo '$(srcdir)/'`eina_ustringshare.c + +libeina_la-eina_value.lo: eina_value.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_value.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_value.Tpo -c -o libeina_la-eina_value.lo `test -f 'eina_value.c' || echo '$(srcdir)/'`eina_value.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_value.Tpo $(DEPDIR)/libeina_la-eina_value.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_value.c' object='libeina_la-eina_value.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_value.lo `test -f 'eina_value.c' || echo '$(srcdir)/'`eina_value.c + +libeina_la-eina_xattr.lo: eina_xattr.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_xattr.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_xattr.Tpo -c -o libeina_la-eina_xattr.lo `test -f 'eina_xattr.c' || echo '$(srcdir)/'`eina_xattr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_xattr.Tpo $(DEPDIR)/libeina_la-eina_xattr.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_xattr.c' object='libeina_la-eina_xattr.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_xattr.lo `test -f 'eina_xattr.c' || echo '$(srcdir)/'`eina_xattr.c + +libeina_la-eina_file_win32.lo: eina_file_win32.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_file_win32.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_file_win32.Tpo -c -o libeina_la-eina_file_win32.lo `test -f 'eina_file_win32.c' || echo '$(srcdir)/'`eina_file_win32.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_file_win32.Tpo $(DEPDIR)/libeina_la-eina_file_win32.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_file_win32.c' object='libeina_la-eina_file_win32.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_file_win32.lo `test -f 'eina_file_win32.c' || echo '$(srcdir)/'`eina_file_win32.c + +libeina_la-eina_file.lo: eina_file.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_file.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_file.Tpo -c -o libeina_la-eina_file.lo `test -f 'eina_file.c' || echo '$(srcdir)/'`eina_file.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_file.Tpo $(DEPDIR)/libeina_la-eina_file.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_file.c' object='libeina_la-eina_file.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_file.lo `test -f 'eina_file.c' || echo '$(srcdir)/'`eina_file.c + +libeina_la-eina_buddy.lo: $(top_srcdir)/src/modules/mp/buddy/eina_buddy.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_buddy.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_buddy.Tpo -c -o libeina_la-eina_buddy.lo `test -f '$(top_srcdir)/src/modules/mp/buddy/eina_buddy.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/buddy/eina_buddy.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_buddy.Tpo $(DEPDIR)/libeina_la-eina_buddy.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/src/modules/mp/buddy/eina_buddy.c' object='libeina_la-eina_buddy.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_buddy.lo `test -f '$(top_srcdir)/src/modules/mp/buddy/eina_buddy.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/buddy/eina_buddy.c + +libeina_la-eina_chained_mempool.lo: $(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.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_chained_mempool.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_chained_mempool.Tpo -c -o libeina_la-eina_chained_mempool.lo `test -f '$(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_chained_mempool.Tpo $(DEPDIR)/libeina_la-eina_chained_mempool.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c' object='libeina_la-eina_chained_mempool.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_chained_mempool.lo `test -f '$(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/chained_pool/eina_chained_mempool.c + +libeina_la-eina_ememoa_fixed.lo: $(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.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_ememoa_fixed.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_ememoa_fixed.Tpo -c -o libeina_la-eina_ememoa_fixed.lo `test -f '$(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_ememoa_fixed.Tpo $(DEPDIR)/libeina_la-eina_ememoa_fixed.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c' object='libeina_la-eina_ememoa_fixed.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_ememoa_fixed.lo `test -f '$(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/ememoa_fixed/eina_ememoa_fixed.c + +libeina_la-eina_ememoa_unknown.lo: $(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.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_ememoa_unknown.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_ememoa_unknown.Tpo -c -o libeina_la-eina_ememoa_unknown.lo `test -f '$(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_ememoa_unknown.Tpo $(DEPDIR)/libeina_la-eina_ememoa_unknown.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c' object='libeina_la-eina_ememoa_unknown.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_ememoa_unknown.lo `test -f '$(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/ememoa_unknown/eina_ememoa_unknown.c + +libeina_la-eina_fixed_bitmap.lo: $(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.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_fixed_bitmap.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_fixed_bitmap.Tpo -c -o libeina_la-eina_fixed_bitmap.lo `test -f '$(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_fixed_bitmap.Tpo $(DEPDIR)/libeina_la-eina_fixed_bitmap.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c' object='libeina_la-eina_fixed_bitmap.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_fixed_bitmap.lo `test -f '$(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c + +libeina_la-eina_one_big.lo: $(top_srcdir)/src/modules/mp/one_big/eina_one_big.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_one_big.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_one_big.Tpo -c -o libeina_la-eina_one_big.lo `test -f '$(top_srcdir)/src/modules/mp/one_big/eina_one_big.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/one_big/eina_one_big.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_one_big.Tpo $(DEPDIR)/libeina_la-eina_one_big.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/src/modules/mp/one_big/eina_one_big.c' object='libeina_la-eina_one_big.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_one_big.lo `test -f '$(top_srcdir)/src/modules/mp/one_big/eina_one_big.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/one_big/eina_one_big.c + +libeina_la-eina_pass_through.lo: $(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.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_pass_through.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_pass_through.Tpo -c -o libeina_la-eina_pass_through.lo `test -f '$(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_pass_through.Tpo $(DEPDIR)/libeina_la-eina_pass_through.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.c' object='libeina_la-eina_pass_through.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_pass_through.lo `test -f '$(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.c' || echo '$(srcdir)/'`$(top_srcdir)/src/modules/mp/pass_through/eina_pass_through.c + +libeina_la-eina_amalgamation.lo: eina_amalgamation.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_amalgamation.lo -MD -MP -MF $(DEPDIR)/libeina_la-eina_amalgamation.Tpo -c -o libeina_la-eina_amalgamation.lo `test -f 'eina_amalgamation.c' || echo '$(srcdir)/'`eina_amalgamation.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeina_la-eina_amalgamation.Tpo $(DEPDIR)/libeina_la-eina_amalgamation.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eina_amalgamation.c' object='libeina_la-eina_amalgamation.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_amalgamation.lo `test -f 'eina_amalgamation.c' || echo '$(srcdir)/'`eina_amalgamation.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool clean-local ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-libLTLIBRARIES + + +@EINA_AMALGAMATION_TRUE@eina_amalgamation.c: $(base_sources) Makefile +@EINA_AMALGAMATION_TRUE@ -rm -f eina_amalgamation.c + +@EINA_AMALGAMATION_TRUE@ @echo "#ifdef HAVE_CONFIG_H" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#include \"config.h\"" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#endif" >> eina_amalgamation.c + +@EINA_AMALGAMATION_TRUE@ @echo "#ifdef HAVE_ALLOCA_H" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "# include " >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#elif defined __GNUC__" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "# define alloca __builtin_alloca" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#elif defined _AIX" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "# define alloca __alloca" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#elif defined _MSC_VER" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "# include " >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "# define alloca _alloca" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#else" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "# include " >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "# ifdef __cplusplus" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#extern \"C\"" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "# endif" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#void *alloca (size_t);" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#endif" >> eina_amalgamation.c + +@EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#include " >> eina_amalgamation.c + +@EINA_AMALGAMATION_TRUE@ @echo "#ifdef HAVE_EVIL" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "# include " >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#endif" >> eina_amalgamation.c + +@EINA_AMALGAMATION_TRUE@ @echo "#include \"eina_config.h\"" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#include \"eina_private.h\"" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#include \"eina_safety_checks.h\"" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#include \"Eina.h\"" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#include \"eina_strbuf_common.h\"" >> eina_amalgamation.c +@EINA_AMALGAMATION_TRUE@ @echo "#include \"eina_share_common.h\"" >> eina_amalgamation.c + +@EINA_AMALGAMATION_TRUE@ @for f in $(base_sources); do \ +@EINA_AMALGAMATION_TRUE@ if [ `echo $$f | sed -e 's/^...\(.\).*/\1/'` != '/' ]; then \ +@EINA_AMALGAMATION_TRUE@ file="$(srcdir)/$$f" ; \ +@EINA_AMALGAMATION_TRUE@ else \ +@EINA_AMALGAMATION_TRUE@ file="$$f" ; \ +@EINA_AMALGAMATION_TRUE@ fi ; \ +@EINA_AMALGAMATION_TRUE@ echo "/* file: $$file */" >> eina_amalgamation.c; \ +@EINA_AMALGAMATION_TRUE@ grep -v -e '^# *include \+.\(config\|eina_[a-z_]\+\|Evil\|stdio\|stdlib\|string\|dlfcn\|dirent\|assert\|errno\|fnmatch\)[.]h.*' $$file >> eina_amalgamation.c; \ +@EINA_AMALGAMATION_TRUE@ done +@EINA_AMALGAMATION_TRUE@ @echo "eina_amalgamation.c generated" + +clean-local: + rm -rf *.gcno eina_amalgamation.c + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libraries/eina/src/lib/eina_accessor.c b/libraries/eina/src/lib/eina_accessor.c new file mode 100644 index 0000000..aec44ef --- /dev/null +++ b/libraries/eina/src/lib/eina_accessor.c @@ -0,0 +1,176 @@ +/* EINA - EFL data type library + * Copyright (C) 2002-2008 Cedric Bail + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "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_accessor.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +static const char EINA_MAGIC_ACCESSOR_STR[] = "Eina Accessor"; + +#define EINA_MAGIC_CHECK_ACCESSOR(d) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_ACCESSOR)) { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_ACCESSOR); } \ + } while(0) + +/** + * @endcond + */ + +/*============================================================================* +* Global * +*============================================================================*/ + +/** + * @internal + * @brief Initialize the accessor module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the accessor module of Eina. It is called by + * eina_init(). + * + * @see eina_init() + */ +Eina_Bool +eina_accessor_init(void) +{ + return eina_magic_string_set(EINA_MAGIC_ACCESSOR, EINA_MAGIC_ACCESSOR_STR); +} + +/** + * @internal + * @brief Shut down the accessor module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the accessor module set up by + * eina_accessor_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_accessor_shutdown(void) +{ + return EINA_TRUE; +} + +/*============================================================================* +* API * +*============================================================================*/ + + +EAPI void +eina_accessor_free(Eina_Accessor *accessor) +{ + EINA_MAGIC_CHECK_ACCESSOR(accessor); + EINA_SAFETY_ON_NULL_RETURN(accessor); + EINA_SAFETY_ON_NULL_RETURN(accessor->free); + accessor->free(accessor); +} + +EAPI void * +eina_accessor_container_get(Eina_Accessor *accessor) +{ + EINA_MAGIC_CHECK_ACCESSOR(accessor); + EINA_SAFETY_ON_NULL_RETURN_VAL(accessor, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(accessor->get_container, NULL); + return accessor->get_container(accessor); +} + +EAPI Eina_Bool +eina_accessor_data_get(Eina_Accessor *accessor, + unsigned int position, + void **data) +{ + EINA_MAGIC_CHECK_ACCESSOR(accessor); + EINA_SAFETY_ON_NULL_RETURN_VAL(accessor, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(accessor->get_at, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE); + return accessor->get_at(accessor, position, data); +} + +EAPI void +eina_accessor_over(Eina_Accessor *accessor, + Eina_Each_Cb cb, + unsigned int start, + unsigned int end, + const void *fdata) +{ + const void *container; + void *data; + unsigned int i; + + EINA_MAGIC_CHECK_ACCESSOR(accessor); + EINA_SAFETY_ON_NULL_RETURN(accessor); + EINA_SAFETY_ON_NULL_RETURN(accessor->get_container); + EINA_SAFETY_ON_NULL_RETURN(accessor->get_at); + EINA_SAFETY_ON_NULL_RETURN(cb); + EINA_SAFETY_ON_FALSE_RETURN(start < end); + + if (!eina_accessor_lock(accessor)) + return ; + + container = accessor->get_container(accessor); + for (i = start; i < end && accessor->get_at(accessor, i, &data) == EINA_TRUE; + ++i) + if (cb(container, data, (void *)fdata) != EINA_TRUE) + goto on_exit; + + on_exit: + (void) eina_accessor_unlock(accessor); +} + +EAPI Eina_Bool +eina_accessor_lock(Eina_Accessor *accessor) +{ + EINA_MAGIC_CHECK_ACCESSOR(accessor); + EINA_SAFETY_ON_NULL_RETURN_VAL(accessor, EINA_FALSE); + + if (accessor->lock) + return accessor->lock(accessor); + return EINA_TRUE; +} + +EAPI Eina_Bool +eina_accessor_unlock(Eina_Accessor *accessor) +{ + EINA_MAGIC_CHECK_ACCESSOR(accessor); + EINA_SAFETY_ON_NULL_RETURN_VAL(accessor, EINA_FALSE); + + if (accessor->unlock) + return accessor->unlock(accessor); + return EINA_TRUE; +} diff --git a/libraries/eina/src/lib/eina_array.c b/libraries/eina/src/lib/eina_array.c new file mode 100644 index 0000000..5a850ac --- /dev/null +++ b/libraries/eina/src/lib/eina_array.c @@ -0,0 +1,491 @@ +/* EINA - EFL data type library + * Copyright (C) 2008 Cedric Bail + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_error.h" +#include "eina_log.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_array.h" + +/*============================================================================* + * Local * + *============================================================================*/ + +/** + * @cond LOCAL + */ + +static const char EINA_MAGIC_ARRAY_STR[] = "Eina Array"; +static const char EINA_MAGIC_ARRAY_ITERATOR_STR[] = "Eina Array Iterator"; +static const char EINA_MAGIC_ARRAY_ACCESSOR_STR[] = "Eina Array Accessor"; + +#define EINA_MAGIC_CHECK_ARRAY(d) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_ARRAY)) { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_ARRAY); } \ + } while (0) + +#define EINA_MAGIC_CHECK_ARRAY_ITERATOR(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_ARRAY_ITERATOR)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_ARRAY_ITERATOR); \ + return __VA_ARGS__; \ + } \ + } while (0) + +#define EINA_MAGIC_CHECK_ARRAY_ACCESSOR(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_ARRAY_ACCESSOR)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_ACCESSOR); \ + return __VA_ARGS__; \ + } \ + } while (0) + + +typedef struct _Eina_Iterator_Array Eina_Iterator_Array; +struct _Eina_Iterator_Array +{ + Eina_Iterator iterator; + + const Eina_Array *array; + unsigned int index; + + EINA_MAGIC +}; + +typedef struct _Eina_Accessor_Array Eina_Accessor_Array; +struct _Eina_Accessor_Array +{ + Eina_Accessor accessor; + const Eina_Array *array; + EINA_MAGIC +}; + +static int _eina_array_log_dom = -1; + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_eina_array_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_array_log_dom, __VA_ARGS__) + +static void eina_array_iterator_free(Eina_Iterator_Array *it) EINA_ARG_NONNULL(1); +static Eina_Array *eina_array_iterator_get_container(Eina_Iterator_Array *it) EINA_ARG_NONNULL(1); +static Eina_Bool eina_array_iterator_next(Eina_Iterator_Array *it, + void **data) EINA_ARG_NONNULL(1); + +static Eina_Bool eina_array_accessor_get_at(Eina_Accessor_Array *it, + unsigned int idx, + void **data) EINA_ARG_NONNULL(1); +static Eina_Array *eina_array_accessor_get_container(Eina_Accessor_Array *it) EINA_ARG_NONNULL(1); +static void eina_array_accessor_free(Eina_Accessor_Array *it) EINA_ARG_NONNULL(1); + +static Eina_Bool +eina_array_iterator_next(Eina_Iterator_Array *it, void **data) +{ + EINA_MAGIC_CHECK_ARRAY_ITERATOR(it, EINA_FALSE); + + if (!(it->index < eina_array_count_get(it->array))) + return EINA_FALSE; + + if (data) + *data = eina_array_data_get(it->array, it->index); + + it->index++; + return EINA_TRUE; +} + +static Eina_Array * +eina_array_iterator_get_container(Eina_Iterator_Array *it) +{ + EINA_MAGIC_CHECK_ARRAY_ITERATOR(it, NULL); + return (Eina_Array *)it->array; +} + +static void +eina_array_iterator_free(Eina_Iterator_Array *it) +{ + EINA_MAGIC_CHECK_ARRAY_ITERATOR(it); + MAGIC_FREE(it); +} + +static Eina_Bool +eina_array_accessor_get_at(Eina_Accessor_Array *it, + unsigned int idx, + void **data) +{ + EINA_MAGIC_CHECK_ARRAY_ACCESSOR(it, EINA_FALSE); + + if (!(idx < eina_array_count_get(it->array))) + return EINA_FALSE; + + if (data) + *data = eina_array_data_get(it->array, idx); + + return EINA_TRUE; +} + +static Eina_Array * +eina_array_accessor_get_container(Eina_Accessor_Array *it) +{ + EINA_MAGIC_CHECK_ARRAY_ACCESSOR(it, NULL); + return (Eina_Array *)it->array; +} + +static void +eina_array_accessor_free(Eina_Accessor_Array *it) +{ + EINA_MAGIC_CHECK_ARRAY_ACCESSOR(it); + MAGIC_FREE(it); +} + +/* used from eina_inline_array.x, thus a needed symbol */ +EAPI Eina_Bool +eina_array_grow(Eina_Array *array) +{ + void **tmp; + unsigned int total; + + EINA_SAFETY_ON_NULL_RETURN_VAL(array, EINA_FALSE); + + EINA_MAGIC_CHECK_ARRAY(array); + + total = array->total + array->step; + eina_error_set(0); + tmp = realloc(array->data, sizeof (void *) * total); + if (EINA_UNLIKELY(!tmp)) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return 0; + } + + array->total = total; + array->data = tmp; + + return 1; +} + +/** + * @endcond + */ + + +/*============================================================================* + * Global * + *============================================================================*/ + +/** + * @internal + * @brief Initialize the array module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the error and magic modules or Eina. It is + * called by eina_init(). + * + * @see eina_init() + */ +Eina_Bool +eina_array_init(void) +{ + _eina_array_log_dom = eina_log_domain_register("eina_array", + EINA_LOG_COLOR_DEFAULT); + if (_eina_array_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_array"); + return EINA_FALSE; + } + +#define EMS(n) eina_magic_string_static_set(n, n ## _STR) + EMS(EINA_MAGIC_ARRAY); + EMS(EINA_MAGIC_ARRAY_ITERATOR); + EMS(EINA_MAGIC_ARRAY_ACCESSOR); +#undef EMS + return EINA_TRUE; +} + +/** + * @internal + * @brief Shut down the array module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the array module set up by + * eina_array_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_array_shutdown(void) +{ + eina_log_domain_unregister(_eina_array_log_dom); + _eina_array_log_dom = -1; + return EINA_TRUE; +} + +/*============================================================================* + * API * + *============================================================================*/ + +EAPI Eina_Array * +eina_array_new(unsigned int step) +{ + Eina_Array *array; + + eina_error_set(0); + array = malloc(sizeof (Eina_Array)); + if (!array) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + EINA_MAGIC_SET(array, EINA_MAGIC_ARRAY); + + array->version = EINA_ARRAY_VERSION; + array->data = NULL; + array->total = 0; + array->count = 0; + array->step = step; + + return array; +} + +EAPI void +eina_array_free(Eina_Array *array) +{ + eina_array_flush(array); + + EINA_SAFETY_ON_NULL_RETURN(array); + EINA_MAGIC_CHECK_ARRAY(array); + MAGIC_FREE(array); +} + +EAPI void +eina_array_step_set(Eina_Array *array, + unsigned int sizeof_eina_array, + unsigned int step) +{ + EINA_SAFETY_ON_NULL_RETURN(array); + + if (sizeof (Eina_Array) != sizeof_eina_array) + { + ERR("Unknow Eina_Array size ! Got %i, expected %i !\n", + sizeof_eina_array, + (int) sizeof (Eina_Array)); + /* Force memory to zero to provide a small layer of security */ + memset(array, 0, sizeof_eina_array); + return ; + } + + array->version = EINA_ARRAY_VERSION; + array->data = NULL; + array->total = 0; + array->count = 0; + array->step = step; + EINA_MAGIC_SET(array, EINA_MAGIC_ARRAY); +} + +EAPI void +eina_array_flush(Eina_Array *array) +{ + EINA_SAFETY_ON_NULL_RETURN(array); + EINA_MAGIC_CHECK_ARRAY(array); + + array->count = 0; + array->total = 0; + + if (!array->data) + return; + + free(array->data); + array->data = NULL; +} + +EAPI Eina_Bool +eina_array_remove(Eina_Array *array, Eina_Bool (*keep)(void *data, + void *gdata), + void *gdata) +{ + void **tmp; + /* WARNING: + The algorithm does exit before using unitialized data. So compiler is + giving you a false positiv here too. + */ + void *data = NULL; + unsigned int total = 0; + unsigned int limit; + unsigned int i; + + EINA_SAFETY_ON_NULL_RETURN_VAL(array, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(keep, EINA_FALSE); + EINA_MAGIC_CHECK_ARRAY(array); + + if (array->total == 0) + return EINA_TRUE; + + for (i = 0; i < array->count; ++i) + { + data = eina_array_data_get(array, i); + + if (keep(data, gdata) == EINA_FALSE) + break; + } + limit = i; + if (i < array->count) + ++i; + + for (; i < array->count; ++i) + { + data = eina_array_data_get(array, i); + + if (keep(data, gdata) == EINA_TRUE) + break; + } + /* Special case all objects that need to stay are at the beginning of the array. */ + if (i == array->count) + { + array->count = limit; + if (array->count == 0) + { + free(array->data); + array->total = 0; + array->data = NULL; + } + + return EINA_TRUE; + } + + eina_error_set(0); + tmp = malloc(sizeof (void *) * array->total); + if (!tmp) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + + memcpy(tmp, array->data, limit * sizeof(void *)); + total = limit; + + if (i < array->count) + { + tmp[total] = data; + total++; + ++i; + } + + for (; i < array->count; ++i) + { + data = eina_array_data_get(array, i); + + if (keep(data, gdata)) + { + tmp[total] = data; + total++; + } + } + + free(array->data); + + /* If we do not keep any object in the array, we should have exited + earlier in test (i == array->count). */ + assert(total != 0); + + array->data = tmp; + array->count = total; + return EINA_TRUE; +} + +EAPI Eina_Iterator * +eina_array_iterator_new(const Eina_Array *array) +{ + Eina_Iterator_Array *it; + + EINA_SAFETY_ON_NULL_RETURN_VAL(array, NULL); + EINA_MAGIC_CHECK_ARRAY(array); + + eina_error_set(0); + it = calloc(1, sizeof (Eina_Iterator_Array)); + if (!it) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + EINA_MAGIC_SET(it, EINA_MAGIC_ARRAY_ITERATOR); + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->array = array; + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(eina_array_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER( + eina_array_iterator_get_container); + it->iterator.free = FUNC_ITERATOR_FREE(eina_array_iterator_free); + + return &it->iterator; +} + +EAPI Eina_Accessor * +eina_array_accessor_new(const Eina_Array *array) +{ + Eina_Accessor_Array *ac; + + EINA_SAFETY_ON_NULL_RETURN_VAL(array, NULL); + EINA_MAGIC_CHECK_ARRAY(array); + + eina_error_set(0); + ac = calloc(1, sizeof (Eina_Accessor_Array)); + if (!ac) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + EINA_MAGIC_SET(ac, EINA_MAGIC_ARRAY_ACCESSOR); + EINA_MAGIC_SET(&ac->accessor, EINA_MAGIC_ACCESSOR); + + ac->array = array; + + ac->accessor.version = EINA_ACCESSOR_VERSION; + ac->accessor.get_at = FUNC_ACCESSOR_GET_AT(eina_array_accessor_get_at); + ac->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER( + eina_array_accessor_get_container); + ac->accessor.free = FUNC_ACCESSOR_FREE(eina_array_accessor_free); + + return &ac->accessor; +} diff --git a/libraries/eina/src/lib/eina_benchmark.c b/libraries/eina/src/lib/eina_benchmark.c new file mode 100644 index 0000000..1ba2a00 --- /dev/null +++ b/libraries/eina/src/lib/eina_benchmark.c @@ -0,0 +1,372 @@ +/* EINA - EFL data type library + * Copyright (C) 2008 Cedric Bail + * + * 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 +#include + +#ifdef HAVE_EVIL +# include +#endif + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_log.h" +#include "eina_benchmark.h" +#include "eina_inlist.h" +#include "eina_list.h" +#include "eina_counter.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +#define EINA_BENCHMARK_FILENAME_MASK "bench_%s_%s.gnuplot" +#define EINA_BENCHMARK_DATA_MASK "bench_%s_%s.%s.data" + +typedef struct _Eina_Run Eina_Run; +struct _Eina_Run +{ + EINA_INLIST; + + Eina_Benchmark_Specimens cb; + const char *name; + int start; + int end; + int step; +}; + +struct _Eina_Benchmark +{ + const char *name; + const char *run; + + Eina_Inlist *runs; + Eina_List *names; +}; + +static int _eina_benchmark_log_dom = -1; + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_eina_benchmark_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_benchmark_log_dom, __VA_ARGS__) + +/** + * @endcond + */ + +/*============================================================================* +* Global * +*============================================================================*/ + +/** + * @internal + * @brief Initialize the benchmark module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the benchmark module of Eina. It is called by + * eina_init(). + * + * @see eina_init() + */ +Eina_Bool +eina_benchmark_init(void) +{ + _eina_benchmark_log_dom = eina_log_domain_register("eina_benchmark", + EINA_LOG_COLOR_DEFAULT); + if (_eina_benchmark_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_benchmark"); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +/** + * @internal + * @brief Shut down the benchmark module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the benchmark module set up by + * eina_benchmark_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_benchmark_shutdown(void) +{ + eina_log_domain_unregister(_eina_benchmark_log_dom); + _eina_benchmark_log_dom = -1; + return EINA_TRUE; +} + +/*============================================================================* +* API * +*============================================================================*/ + +EAPI Eina_Benchmark * +eina_benchmark_new(const char *name, const char *run) +{ + Eina_Benchmark *new; + + eina_error_set(0); + new = calloc(1, sizeof (Eina_Benchmark)); + if (!new) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + new->name = name; + new->run = run; + + return new; +} + +EAPI void +eina_benchmark_free(Eina_Benchmark *bench) +{ + Eina_Array *names; + + if (!bench) + return; + + while (bench->runs) + { + Eina_Run *run = (Eina_Run *)bench->runs; + + bench->runs = eina_inlist_remove(bench->runs, bench->runs); + free(run); + } + + EINA_LIST_FREE(bench->names, names) + { + Eina_Array_Iterator it; + char *tmp; + unsigned int i; + + EINA_ARRAY_ITER_NEXT(names, i, tmp, it) + free(tmp); + + eina_array_free(names); + } + + free(bench); +} + +EAPI Eina_Bool +eina_benchmark_register(Eina_Benchmark *bench, + const char *name, + Eina_Benchmark_Specimens bench_cb, + int count_start, + int count_end, + int count_step) +{ + Eina_Run *run; + + if (!bench) + return EINA_FALSE; + + if (count_step == 0) + return EINA_FALSE; + + eina_error_set(0); + run = calloc(1, sizeof (Eina_Run)); + if (!run) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + + run->cb = bench_cb; + run->name = name; + run->start = count_start; + run->end = count_end; + run->step = count_step; + + bench->runs = eina_inlist_append(bench->runs, EINA_INLIST_GET(run)); + + return EINA_TRUE; +} + +EAPI Eina_Array * +eina_benchmark_run(Eina_Benchmark *bench) +{ + FILE *main_script; + FILE *current_data; + Eina_Array *ea; + Eina_Run *run; + char *buffer; + Eina_Bool first = EINA_FALSE; + size_t length; + + if (!bench) + return NULL; + + length = strlen(EINA_BENCHMARK_FILENAME_MASK) + strlen(bench->name) + strlen( + bench->run); + + buffer = alloca(sizeof (char) * length); + if (!buffer) + return NULL; + + snprintf(buffer, + length, + EINA_BENCHMARK_FILENAME_MASK, + bench->name, + bench->run); + + main_script = fopen(buffer, "w"); + if (!main_script) + return NULL; + + ea = eina_array_new(16); + if (!ea) + { + fclose(main_script); + return NULL; + } + + eina_array_push(ea, strdup(buffer)); + + fprintf( + main_script, + "set autoscale # scale axes automatically\n" + "unset log # remove any log-scaling\n" + "unset label # remove any previous labels\n" + "set xtic auto # set xtics automatically\n" + "set ytic auto # set ytics automatically\n" +/* "set logscale y\n" */ + "set terminal png size 1024,768\n" + "set output \"output_%s_%s.png\"\n" + "set title \"%s %s\n" + "set xlabel \"tests\"\n" + "set ylabel \"time\"\n" + "plot ", + bench->name, + bench->run, + bench->name, + bench->run); + + EINA_INLIST_FOREACH(bench->runs, run) + { + Eina_Counter *counter; + char *result; + size_t tmp; + int i; + + tmp = strlen(EINA_BENCHMARK_DATA_MASK) + strlen(bench->name) + strlen( + bench->run) + strlen(run->name); + if (tmp > length) + { + buffer = alloca(sizeof (char) * tmp); + length = tmp; + } + + snprintf(buffer, + length, + EINA_BENCHMARK_DATA_MASK, + bench->name, + bench->run, + run->name); + + current_data = fopen(buffer, "w"); + if (!current_data) + continue; + + eina_array_push(ea, strdup(buffer)); + + counter = eina_counter_new(run->name); + + for (i = run->start; i < run->end; i += run->step) + { + fprintf(stderr, "Run %s: %i\n", run->name, i); + eina_counter_start(counter); + + run->cb(i); + + eina_counter_stop(counter, i); + } + + result = eina_counter_dump(counter); + if (result) + { + fprintf(current_data, "%s", result); + free(result); + } + + eina_counter_free(counter); + + fclose(current_data); + + if (first == EINA_FALSE) + first = EINA_TRUE; + else + fprintf(main_script, ", \\\n"); + + fprintf(main_script, + "\"%s\" using 1:2 title \'%s\' with line", + buffer, run->name); + } + + fprintf(main_script, "\n"); + + fclose(main_script); + + bench->names = eina_list_append(bench->names, ea); + + return ea; +} + +/** + * @} + */ diff --git a/libraries/eina/src/lib/eina_binbuf.c b/libraries/eina/src/lib/eina_binbuf.c new file mode 100644 index 0000000..3cbebd1 --- /dev/null +++ b/libraries/eina/src/lib/eina_binbuf.c @@ -0,0 +1,62 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#ifdef HAVE_EVIL +# include +#endif + +#include "eina_private.h" +#include "eina_strbuf_common.h" +#include "eina_binbuf.h" + +/*============================================================================* + * Local * + *============================================================================*/ + +/** + * @cond LOCAL + */ + +#ifdef _STRBUF_DATA_TYPE +# undef _STRBUF_DATA_TYPE +#endif + +#ifdef _STRBUF_CSIZE +# undef _STRBUF_CSIZE +#endif + +#ifdef _STRBUF_STRUCT_NAME +# undef _STRBUF_STRUCT_NAME +#endif + +#ifdef _STRBUF_MAGIC +# undef _STRBUF_MAGIC +#endif + +#ifdef _STRBUF_MAGIC_STR +# undef _STRBUF_MAGIC_STR +#endif + +#ifdef _FUNC_EXPAND +# undef _FUNC_EXPAND +#endif + + +#define _STRBUF_DATA_TYPE unsigned char +#define _STRBUF_CSIZE sizeof(_STRBUF_DATA_TYPE) +#define _STRBUF_STRUCT_NAME Eina_Binbuf +#define _STRBUF_MAGIC EINA_MAGIC_BINBUF +#define _STRBUF_MAGIC_STR __BINBUF_MAGIC_STR +static const char __BINBUF_MAGIC_STR[] = "Eina Binbuf"; + +#define _FUNC_EXPAND(y) eina_binbuf_ ## y + +#include "eina_binbuf_template_c.x" + +/** + * @endcond + */ diff --git a/libraries/eina/src/lib/eina_binbuf_template_c.x b/libraries/eina/src/lib/eina_binbuf_template_c.x new file mode 100644 index 0000000..613a715 --- /dev/null +++ b/libraries/eina/src/lib/eina_binbuf_template_c.x @@ -0,0 +1,144 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +/* This file should be included from files implementing binbuf. + * The including file should define the following macros: + * _STRBUF_DATA_TYPE + * _STRBUF_CSIZE + * _STRBUF_STRUCT_NAME + * _STRBUF_MAGIC + * _STRBUF_MAGIC_STR + * _FUNC_EXPAND + * See how it's done in eina_ustrbuf.c and eina_strbuf.c. This just makes things + * a lot easier since those are essentially the same just with different sizes. + */ + +/*============================================================================* + * Global * + *============================================================================*/ + +/** + * @internal + * @brief Initialize the strbuf module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the strbuf module of Eina. It is called by + * eina_init(). + * + * @see eina_init() + */ +Eina_Bool +_FUNC_EXPAND(init)(void) +{ + eina_magic_string_static_set(_STRBUF_MAGIC, _STRBUF_MAGIC_STR); + return eina_strbuf_common_init(); +} + +/** + * @internal + * @brief Shut down the strbuf module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the strbuf module set up by + * eina_ustrbuf_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +_FUNC_EXPAND(shutdown)(void) +{ + return eina_strbuf_common_shutdown(); +} + +/*============================================================================* + * API * + *============================================================================*/ + +EAPI _STRBUF_STRUCT_NAME * +_FUNC_EXPAND(new)(void) +{ + _STRBUF_STRUCT_NAME *buf = eina_strbuf_common_new(_STRBUF_CSIZE); + EINA_MAGIC_SET(buf, _STRBUF_MAGIC); + return buf; +} + +EAPI void +_FUNC_EXPAND(free)(_STRBUF_STRUCT_NAME *buf) +{ + EINA_MAGIC_CHECK_STRBUF(buf); + EINA_MAGIC_SET(buf, EINA_MAGIC_NONE); + eina_strbuf_common_free(buf); +} + +EAPI void +_FUNC_EXPAND(reset)(_STRBUF_STRUCT_NAME *buf) +{ + EINA_MAGIC_CHECK_STRBUF(buf); + eina_strbuf_common_reset(_STRBUF_CSIZE, buf); +} + +EAPI Eina_Bool +_FUNC_EXPAND(append_length)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t length) +{ + EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE); + return eina_strbuf_common_append_length(_STRBUF_CSIZE, buf, (const void *) str, length); +} + +EAPI Eina_Bool +_FUNC_EXPAND(insert_length)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t length, size_t pos) +{ + EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE); + return eina_strbuf_common_insert_length(_STRBUF_CSIZE, buf, (const void *) str, length, pos); +} + +EAPI Eina_Bool +_FUNC_EXPAND(append_char)(_STRBUF_STRUCT_NAME *buf, _STRBUF_DATA_TYPE c) +{ + EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE); + return eina_strbuf_common_append_char(_STRBUF_CSIZE, buf, (const void *) &c); +} + +EAPI Eina_Bool +_FUNC_EXPAND(insert_char)(_STRBUF_STRUCT_NAME *buf, _STRBUF_DATA_TYPE c, size_t pos) +{ + EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE); + return eina_strbuf_common_insert_char(_STRBUF_CSIZE, buf, (const void *) &c, pos); +} + +EAPI Eina_Bool +_FUNC_EXPAND(remove)(_STRBUF_STRUCT_NAME *buf, size_t start, size_t end) +{ + EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE); + return eina_strbuf_common_remove(_STRBUF_CSIZE, buf, start, end); +} + +EAPI const _STRBUF_DATA_TYPE * +_FUNC_EXPAND(string_get)(const _STRBUF_STRUCT_NAME *buf) +{ + EINA_MAGIC_CHECK_STRBUF(buf, NULL); + return (const _STRBUF_DATA_TYPE *) eina_strbuf_common_string_get(buf); +} + +EAPI _STRBUF_DATA_TYPE * +_FUNC_EXPAND(string_steal)(_STRBUF_STRUCT_NAME *buf) +{ + EINA_MAGIC_CHECK_STRBUF(buf, NULL); + return (_STRBUF_DATA_TYPE *) eina_strbuf_common_string_steal(_STRBUF_CSIZE, buf); +} + +EAPI void +_FUNC_EXPAND(string_free)(_STRBUF_STRUCT_NAME *buf) +{ + EINA_MAGIC_CHECK_STRBUF(buf); + eina_strbuf_common_string_free(_STRBUF_CSIZE, buf); +} + +EAPI size_t +_FUNC_EXPAND(length_get)(const _STRBUF_STRUCT_NAME *buf) +{ + EINA_MAGIC_CHECK_STRBUF(buf, 0); + return eina_strbuf_common_length_get(buf); +} diff --git a/libraries/eina/src/lib/eina_binshare.c b/libraries/eina/src/lib/eina_binshare.c new file mode 100644 index 0000000..68a82fc --- /dev/null +++ b/libraries/eina/src/lib/eina_binshare.c @@ -0,0 +1,127 @@ +/* EINA - EFL data type library + * Copyright (C) 2002-2008 Carsten Haitzler, + * Jorge Luis Zapata Muga, + * Cedric Bail, + * Gustavo Sverzut Barbieri + * Tom Hacohen + * + * 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 . + + */ + +#include "eina_share_common.h" +#include "eina_unicode.h" +#include "eina_private.h" +#include "eina_binshare.h" + +/*============================================================================* + * Local * + *============================================================================*/ + +/** + * @cond LOCAL + */ + +/* The actual share */ +static Eina_Share *binshare_share; +static const char EINA_MAGIC_BINSHARE_NODE_STR[] = "Eina Binshare Node"; + +/** + * @endcond + */ + + +/*============================================================================* +* Global * +*============================================================================*/ + +/** + * @internal + * @brief Initialize the share_common module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the share_common module of Eina. It is called by + * eina_init(). + * + * @see eina_init() + */ +EAPI Eina_Bool +eina_binshare_init(void) +{ + return eina_share_common_init(&binshare_share, + EINA_MAGIC_BINSHARE_NODE, + EINA_MAGIC_BINSHARE_NODE_STR); +} + +/** + * @internal + * @brief Shut down the share_common module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the share_common module set up by + * eina_share_common_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +EAPI Eina_Bool +eina_binshare_shutdown(void) +{ + Eina_Bool ret; + ret = eina_share_common_shutdown(&binshare_share); + return ret; +} + + +/*============================================================================* + * API * + *============================================================================*/ + +EAPI void +eina_binshare_del(const void *obj) +{ + if (!obj) + return; + + eina_share_common_del(binshare_share, obj); +} + +EAPI const void * +eina_binshare_add_length(const void *obj, unsigned int olen) +{ + return eina_share_common_add_length(binshare_share, + obj, + (olen) * sizeof(char), + 0); +} + +EAPI const void * +eina_binshare_ref(const void *obj) +{ + return eina_share_common_ref(binshare_share, obj); +} + +EAPI int +eina_binshare_length(const void *obj) +{ + return eina_share_common_length(binshare_share, obj); +} + +EAPI void +eina_binshare_dump(void) +{ + eina_share_common_dump(binshare_share, NULL, 0); +} diff --git a/libraries/eina/src/lib/eina_convert.c b/libraries/eina/src/lib/eina_convert.c new file mode 100644 index 0000000..63b6654 --- /dev/null +++ b/libraries/eina/src/lib/eina_convert.c @@ -0,0 +1,483 @@ +/* EINA - EFL data type library + * Copyright (C) 2008 Cedric BAIL, 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 + +#include +#include +#include +#include + +#ifdef HAVE_EVIL +# include +#endif + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_log.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_convert.h" +#include "eina_fp.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +static const char look_up_table[] = {'0', '1', '2', '3', '4', + '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f'}; +static int _eina_convert_log_dom = -1; + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_eina_convert_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_convert_log_dom, __VA_ARGS__) + +#define HEXA_TO_INT(Hexa) (Hexa >= 'a') ? Hexa - 'a' + 10 : Hexa - '0' + +static inline void reverse(char s[], int length) +{ + int i, j; + char c; + + for (i = 0, j = length - 1; i < j; i++, j--) + { + c = s[i]; + s[i] = s[j]; + s[j] = c; + } +} + +/** + * @endcond + */ + +/*============================================================================* +* Global * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +EAPI Eina_Error EINA_ERROR_CONVERT_P_NOT_FOUND = 0; +EAPI Eina_Error EINA_ERROR_CONVERT_0X_NOT_FOUND = 0; +EAPI Eina_Error EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH = 0; + +static const char EINA_ERROR_CONVERT_0X_NOT_FOUND_STR[] = + "Error during string conversion to float, First '0x' was not found."; +static const char EINA_ERROR_CONVERT_P_NOT_FOUND_STR[] = + "Error during string conversion to float, First 'p' was not found."; +static const char EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH_STR[] = + "Error outrun string limit during conversion string conversion to float."; + +/** + * @endcond + */ + +/** + * @internal + * @brief Initialize the convert module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the convert module of Eina. It is called by + * eina_init(). + * + * This function sets up the error module of Eina and registers the + * errors #EINA_ERROR_CONVERT_0X_NOT_FOUND, + * #EINA_ERROR_CONVERT_P_NOT_FOUND and + * #EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH. + * + * @see eina_init() + */ +Eina_Bool +eina_convert_init(void) +{ + _eina_convert_log_dom = eina_log_domain_register("eina_convert", + EINA_LOG_COLOR_DEFAULT); + if (_eina_convert_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_convert"); + return EINA_FALSE; + } + +#define EEMR(n) n = eina_error_msg_static_register(n ## _STR) + EEMR(EINA_ERROR_CONVERT_0X_NOT_FOUND); + EEMR(EINA_ERROR_CONVERT_P_NOT_FOUND); + EEMR(EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH); +#undef EEMR + + return EINA_TRUE; +} + +/** + * @internal + * @brief Shut down the convert module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the convert module set up by + * eina_convert_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_convert_shutdown(void) +{ + eina_log_domain_unregister(_eina_convert_log_dom); + _eina_convert_log_dom = -1; + return EINA_TRUE; +} + +/*============================================================================* +* API * +*============================================================================*/ + +/* + * Come from the second edition of The C Programming Language ("K&R2") on page 64 + */ + +EAPI int +eina_convert_itoa(int n, char *s) +{ + int i = 0; + int r = 0; + + EINA_SAFETY_ON_NULL_RETURN_VAL(s, 0); + + if (n < 0) + { + n = -n; + *s++ = '-'; + r = 1; + } + + do { + s[i++] = n % 10 + '0'; + } while ((n /= 10) > 0); + + s[i] = '\0'; + + reverse(s, i); + + return i + r; +} + +EAPI int +eina_convert_xtoa(unsigned int n, char *s) +{ + int i; + + EINA_SAFETY_ON_NULL_RETURN_VAL(s, 0); + + i = 0; + do { + s[i++] = look_up_table[n & 0xF]; + } while ((n >>= 4) > 0); + + s[i] = '\0'; + + reverse(s, i); + + return i; +} + +EAPI Eina_Bool +eina_convert_atod(const char *src, int length, long long *m, long *e) +{ + const char *str = src; + long long mantisse; + long exponent; + int nbr_decimals = 0; + int sign = 1; + + EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE); + + if (length <= 0) + goto on_length_error; + + /* Compute the mantisse. */ + if (*str == '-') + { + sign = -1; + str++; + length--; + } + + if (length <= 2) + goto on_length_error; + + if (strncmp(str, "0x", 2)) + { + eina_error_set(EINA_ERROR_CONVERT_0X_NOT_FOUND); + DBG("'0x' not found in '%s'", src); + return EINA_FALSE; + } + + str += 2; + length -= 2; + + mantisse = HEXA_TO_INT(*str); + + str++; + length--; if (length <= 0) + goto on_length_error; + + if (*str == '.') + for (str++, length--; + length > 0 && *str != 'p'; + ++str, --length, ++nbr_decimals) + { + mantisse <<= 4; + mantisse += HEXA_TO_INT(*str); + } + + if (sign < 0) + mantisse = -mantisse; + + /* Compute the exponent. */ + if (*str != 'p') + { + eina_error_set(EINA_ERROR_CONVERT_P_NOT_FOUND); + DBG("'p' not found in '%s'", src); + return EINA_FALSE; + } + + sign = +1; + + str++; + length--; if (length <= 0) + goto on_length_error; + + if (strchr("-+", *str)) + { + sign = (*str == '-') ? -1 : +1; + + str++; length--; + } + + for (exponent = 0; length > 0 && *str != '\0'; ++str, --length) + { + exponent *= 10; + exponent += *str - '0'; + } + + if (length < 0) + goto on_length_error; + + if (sign < 0) + exponent = -exponent; + + *m = mantisse; + *e = exponent - (nbr_decimals << 2); + + return EINA_TRUE; + +on_length_error: + eina_error_set(EINA_ERROR_CONVERT_OUTRUN_STRING_LENGTH); + return EINA_FALSE; +} + +EAPI int +eina_convert_dtoa(double d, char *des) +{ + int length = 0; + int p; + int i; + + EINA_SAFETY_ON_NULL_RETURN_VAL(des, EINA_FALSE); + + if (d < 0.0) + { + *(des++) = '-'; + d = -d; + length++; + } + + d = frexp(d, &p); + + if (p) + { + d *= 2; + p -= 1; + } + + *(des++) = '0'; + *(des++) = 'x'; + *(des++) = look_up_table[(size_t)d]; + *(des++) = '.'; + length += 4; + + for (i = 0; i < 16; i++, length++) + { + d -= floor(d); + d *= 16; + *(des++) = look_up_table[(size_t)d]; + } + + while (*(des - 1) == '0') + { + des--; + length--; + } + + if (*(des - 1) == '.') + { + des--; + length--; + } + + *(des++) = 'p'; + if (p < 0) + { + *(des++) = '-'; + p = -p; + } + else + *(des++) = '+'; + + length += 2; + + return length + eina_convert_itoa(p, des); +} + +EAPI int +eina_convert_fptoa(Eina_F32p32 fp, char *des) +{ + int length = 0; + int p = 0; + int i; + + EINA_SAFETY_ON_NULL_RETURN_VAL(des, EINA_FALSE); + + if (fp == 0) + { + memcpy(des, "0x0p+0", 7); + return 7; + } + + if (fp < 0) + { + *(des++) = '-'; + fp = -fp; + length++; + } + + /* fp >= 1 */ + if (fp >= 0x0000000100000000LL) + while (fp >= 0x0000000100000000LL) + { + p++; + /* fp /= 2 */ + fp >>= 1; + } /* fp < 0.5 */ + else if (fp < 0x80000000) + while (fp < 0x80000000) + { + p--; + /* fp *= 2 */ + fp <<= 1; + } + + if (p) + { + p--; + /* fp *= 2 */ + fp <<= 1; + } + + *(des++) = '0'; + *(des++) = 'x'; + *(des++) = look_up_table[fp >> 32]; + *(des++) = '.'; + length += 4; + + for (i = 0; i < 16; i++, length++) + { + fp &= 0x00000000ffffffffLL; + fp <<= 4; /* fp *= 16 */ + *(des++) = look_up_table[fp >> 32]; + } + + while (*(des - 1) == '0') + { + des--; + length--; + } + + if (*(des - 1) == '.') + { + des--; + length--; + } + + *(des++) = 'p'; + if (p < 0) + { + *(des++) = '-'; + p = -p; + } + else + *(des++) = '+'; + + length += 2; + + return length + eina_convert_itoa(p, des); +} + +EAPI Eina_Bool +eina_convert_atofp(const char *src, int length, Eina_F32p32 *fp) +{ + long long m; + long e; + + if (!eina_convert_atod(src, length, &m, &e)) + return EINA_FALSE; + + if (!fp) + return EINA_TRUE; + + e += 32; + + if (e > 0) + *fp = m << e; + else + *fp = m >> -e; + + return EINA_TRUE; +} + +/** + * @} + */ diff --git a/libraries/eina/src/lib/eina_counter.c b/libraries/eina/src/lib/eina_counter.c new file mode 100644 index 0000000..6ca9417 --- /dev/null +++ b/libraries/eina/src/lib/eina_counter.c @@ -0,0 +1,362 @@ +/* EINA - EFL data type library + * Copyright (C) 2008 Cedric Bail, 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 + +#include +#include +#include +#include +#ifndef _WIN32 +# include +# include +#else +# define WIN32_LEAN_AND_MEAN +# include +# undef WIN32_LEAN_AND_MEAN +#endif /* _WIN2 */ + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_inlist.h" +#include "eina_error.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_counter.h" + +#ifdef HAVE_ESCAPE +# include +#endif + +/*============================================================================* + * Local * + *============================================================================*/ + +/** + * @cond LOCAL + */ + +#ifndef _WIN32 +typedef struct timespec Eina_Nano_Time; +#else +typedef LARGE_INTEGER Eina_Nano_Time; +#endif + +typedef struct _Eina_Clock Eina_Clock; + +struct _Eina_Counter +{ + EINA_INLIST; + + Eina_Inlist *clocks; + const char *name; +}; + +struct _Eina_Clock +{ + EINA_INLIST; + + Eina_Nano_Time start; + Eina_Nano_Time end; + int specimen; + + Eina_Bool valid; +}; + +#ifndef _WIN32 +static inline int +_eina_counter_time_get(Eina_Nano_Time *tp) +{ +# if defined(CLOCK_PROCESS_CPUTIME_ID) + return clock_gettime(CLOCK_PROCESS_CPUTIME_ID, tp); +# elif defined(CLOCK_PROF) + return clock_gettime(CLOCK_PROF, tp); +# elif defined(CLOCK_REALTIME) + return clock_gettime(CLOCK_REALTIME, tp); +# else + struct timeval tv; + + if (gettimeofday(&tv, NULL)) + return -1; + + tp->tv_sec = tv.tv_sec; + tp->tv_nsec = tv.tv_usec * 1000L; + + return 0; +# endif +} +#else +static const char EINA_ERROR_COUNTER_WINDOWS_STR[] = + "Change your OS, you moron !"; +static int EINA_ERROR_COUNTER_WINDOWS = 0; +static LARGE_INTEGER _eina_counter_frequency; + +static inline int +_eina_counter_time_get(Eina_Nano_Time *tp) +{ + return QueryPerformanceCounter(tp); +} +#endif /* _WIN2 */ + +static char * +_eina_counter_asiprintf(char *base, int *position, const char *format, ...) +{ + char *tmp, *result; + int size = 32; + int n; + va_list ap; + + tmp = realloc(base, sizeof (char) * (*position + size)); + if (!tmp) + return base; + + result = tmp; + + while (1) + { + va_start(ap, format); + n = vsnprintf(result + *position, size, format, ap); + va_end(ap); + + if (n > -1 && n < size) + { + /* If we always have glibc > 2.2, we could just return *position += n. */ + *position += strlen(result + *position); + return result; + } + + if (n > -1) + size = n + 1; + else + size <<= 1; + + tmp = realloc(result, sizeof (char) * (*position + size)); + if (!tmp) + return result; + + result = tmp; + } +} + +/** + * @endcond + */ + +/*============================================================================* + * Global * + *============================================================================*/ + +/** + * @internal + * @brief Initialize the eina counter internal structure. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the counter module set up by + * eina_counter_init(). It is called by eina_init(). + * + * This function sets up the error module of Eina and only on Windows, + * it initializes the high precision timer. It also registers, only on + * Windows, the error #EINA_ERROR_COUNTER_WINDOWS. It is also called + * by eina_init(). It returns 0 on failure, otherwise it returns the + * number of times it has already been called. + * + * @see eina_init() + */ +Eina_Bool +eina_counter_init(void) +{ +#ifdef _WIN32 + EINA_ERROR_COUNTER_WINDOWS = eina_error_msg_static_register( + EINA_ERROR_COUNTER_WINDOWS_STR); + if (!QueryPerformanceFrequency(&_eina_counter_frequency)) + { + eina_error_set(EINA_ERROR_COUNTER_WINDOWS); + return EINA_FALSE; + } + +#endif /* _WIN2 */ + return EINA_TRUE; +} + +/** + * @internal + * @brief Shut down the counter module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the counter module set up by + * eina_counter_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_counter_shutdown(void) +{ + return EINA_TRUE; +} + +/*============================================================================* + * API * + *============================================================================*/ + +EAPI Eina_Counter * +eina_counter_new(const char *name) +{ + Eina_Counter *counter; + size_t length; + + EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL); + + length = strlen(name) + 1; + + eina_error_set(0); + counter = calloc(1, sizeof (Eina_Counter) + length); + if (!counter) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + counter->name = (char *)(counter + 1); + memcpy((char *)counter->name, name, length); + + return counter; +} + +EAPI void +eina_counter_free(Eina_Counter *counter) +{ + EINA_SAFETY_ON_NULL_RETURN(counter); + + while (counter->clocks) + { + Eina_Clock *clk = (Eina_Clock *)counter->clocks; + + counter->clocks = eina_inlist_remove(counter->clocks, counter->clocks); + free(clk); + } + + free(counter); +} + +EAPI void +eina_counter_start(Eina_Counter *counter) +{ + Eina_Clock *clk; + Eina_Nano_Time tp; + + EINA_SAFETY_ON_NULL_RETURN(counter); + if (_eina_counter_time_get(&tp) != 0) + return; + + eina_error_set(0); + clk = calloc(1, sizeof (Eina_Clock)); + if (!clk) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return; + } + + counter->clocks = eina_inlist_prepend(counter->clocks, EINA_INLIST_GET(clk)); + + clk->valid = EINA_FALSE; + clk->start = tp; +} + +EAPI void +eina_counter_stop(Eina_Counter *counter, int specimen) +{ + Eina_Clock *clk; + Eina_Nano_Time tp; + + EINA_SAFETY_ON_NULL_RETURN(counter); + if (_eina_counter_time_get(&tp) != 0) + return; + + clk = (Eina_Clock *)counter->clocks; + + if (!clk || clk->valid == EINA_TRUE) + return; + + clk->end = tp; + clk->specimen = specimen; + clk->valid = EINA_TRUE; +} + +EAPI char * +eina_counter_dump(Eina_Counter *counter) +{ + Eina_Clock *clk; + char *result = NULL; + int position = 0; + + EINA_SAFETY_ON_NULL_RETURN_VAL(counter, NULL); + + result = _eina_counter_asiprintf( + result, + &position, + "# specimen\texperiment time\tstarting time\tending time\n"); + if (!result) + return NULL; + + EINA_INLIST_REVERSE_FOREACH(counter->clocks, clk) + { + long int start; + long int end; + long int diff; + + if (clk->valid == EINA_FALSE) + continue; + +#ifndef _WIN32 + start = clk->start.tv_sec * 1000000000 + clk->start.tv_nsec; + end = clk->end.tv_sec * 1000000000 + clk->end.tv_nsec; + diff = + (clk->end.tv_sec - + clk->start.tv_sec) * 1000000000 + clk->end.tv_nsec - + clk->start.tv_nsec; +#else + start = + (long int)(((long long int)clk->start.QuadPart * + 1000000000ll) / + (long long int)_eina_counter_frequency.QuadPart); + end = + (long int)(((long long int)clk->end.QuadPart * + 1000000000LL) / + (long long int)_eina_counter_frequency.QuadPart); + diff = + (long int)(((long long int)(clk->end.QuadPart - + clk->start.QuadPart) * + 1000000000LL) / + (long long int)_eina_counter_frequency.QuadPart); +#endif /* _WIN2 */ + + result = _eina_counter_asiprintf(result, &position, + "%i\t%li\t%li\t%li\n", + clk->specimen, + diff, + start, + end); + } + + return result; +} diff --git a/libraries/eina/src/lib/eina_cpu.c b/libraries/eina/src/lib/eina_cpu.c new file mode 100644 index 0000000..8af550d --- /dev/null +++ b/libraries/eina/src/lib/eina_cpu.c @@ -0,0 +1,207 @@ +/* EINA - EFL data type library + * Copyright (C) 2007-2008 Jorge Luis Zapata Muga + * + * 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 EFL_HAVE_THREADS +# ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# include +# elif defined (__SUNPRO_C) || defined(__GNU__) +# include +# elif defined (__FreeBSD__) || defined (__OpenBSD__) || \ + defined (__NetBSD__) || defined (__DragonFly__) || defined (__MacOSX__) || \ + (defined (__MACH__) && defined (__APPLE__)) +# include +# include +# include +# elif defined (__linux__) || defined(__GLIBC__) +# include +# endif +# ifdef EFL_HAVE_POSIX_THREADS +# include +# endif + +# define TH_MAX 8 +#endif + +#include +#include +#include + +#include "eina_cpu.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/* FIXME this ifdefs should be replaced */ +#if defined(__i386__) || defined(__x86_64__) +/* We save ebx and restore it to be PIC compatible */ +static inline void _x86_cpuid(int op, int *a, int *b, int *c, int *d) +{ + asm volatile ( +#if defined(__x86_64__) + "pushq %%rbx \n\t" /* save %ebx */ +#else + "pushl %%ebx \n\t" /* save %ebx */ +#endif + "cpuid \n\t" + "movl %%ebx, %1 \n\t" /* save what cpuid just put in %ebx */ +#if defined(__x86_64__) + "popq %%rbx \n\t" /* restore the old %ebx */ +#else + "popl %%ebx \n\t" /* restore the old %ebx */ +#endif + : "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d) + : "a" (op) + : "cc"); +} + +static +void _x86_simd(Eina_Cpu_Features *features) +{ + int a, b, c, d; + + _x86_cpuid(1, &a, &b, &c, &d); + /* + * edx + * 18 = PN (Processor Number) + * 19 = CLFlush (Cache Line Flush) + * 23 = MMX + * 25 = SSE + * 26 = SSE2 + * 28 = HTT (Hyper Threading) + * ecx + * 0 = SSE3 + */ + if ((d >> 23) & 1) + *features |= EINA_CPU_MMX; + + if ((d >> 25) & 1) + *features |= EINA_CPU_SSE; + + if ((d >> 26) & 1) + *features |= EINA_CPU_SSE2; + + if (c & 1) + *features |= EINA_CPU_SSE3; +} +#endif + +/*============================================================================* +* Global * +*============================================================================*/ + +/*============================================================================* +* API * +*============================================================================*/ + +/* FIXME the features checks should be called when this function is called? + * or make it static by doing eina_cpu_init() and return a local var + */ +/** + * + * @return + */ +EAPI Eina_Cpu_Features eina_cpu_features_get(void) +{ + Eina_Cpu_Features ecf = 0; +#if defined(__i386__) || defined(__x86_64__) + _x86_simd(&ecf); +#endif + return ecf; +} + +EAPI int eina_cpu_count(void) +{ +#ifdef EFL_HAVE_THREADS + +# if defined (_WIN32) + SYSTEM_INFO sysinfo; + + GetSystemInfo(&sysinfo); + return sysinfo.dwNumberOfProcessors; + +# elif defined (__SUNPRO_C) || defined(__GNU__) + /* + * _SC_NPROCESSORS_ONLN: number of processors that are online, that + is available when sysconf is called. The number + of cpu can change by admins. + * _SC_NPROCESSORS_CONF: maximum number of processors that are available + to the current OS instance. That number can be + change after a reboot. + * _SC_NPROCESSORS_MAX : maximum number of processors that are on the + motherboard. + */ + return sysconf(_SC_NPROCESSORS_ONLN); + +# elif defined (__FreeBSD__) || defined (__OpenBSD__) || \ + defined (__NetBSD__) || defined (__DragonFly__) || defined (__MacOSX__) || \ + (defined (__MACH__) && defined (__APPLE__)) + + int mib[4]; + int cpus; + size_t len = sizeof(cpus); + + mib[0] = CTL_HW; +#ifdef HW_AVAILCPU + mib[1] = HW_AVAILCPU; +#else + mib[1] = HW_NCPU; +#endif + sysctl(mib, 2, &cpus, &len, NULL, 0); + if (cpus < 1) + cpus = 1; + + return cpus; + +# elif defined (__linux__) || defined(__GLIBC__) + cpu_set_t cpu; + int i; + static int cpus = 0; + + if (cpus != 0) + return cpus; + + CPU_ZERO(&cpu); + if (sched_getaffinity(0, sizeof(cpu), &cpu) != 0) + { + fprintf(stderr, "[Eina] could not get cpu affinity: %s\n", + strerror(errno)); + return 1; + } + + for (i = 0; i < TH_MAX; i++) + { + if (CPU_ISSET(i, &cpu)) + cpus = i + 1; + else + break; + } + return cpus; + +# else +# error "eina_cpu_count() error: Platform not supported" +# endif +#else + return 1; +#endif +} diff --git a/libraries/eina/src/lib/eina_error.c b/libraries/eina/src/lib/eina_error.c new file mode 100644 index 0000000..428c414 --- /dev/null +++ b/libraries/eina/src/lib/eina_error.c @@ -0,0 +1,279 @@ +/* EINA - EFL data type library + * Copyright (C) 2007-2008 Jorge Luis Zapata Muga, Cedric Bail + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_EVIL +# include +#endif + +#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_error.h" +#include "eina_stringshare.h" + +/* TODO + * + add a wrapper for assert? + * + add common error numbers, messages + * + add a calltrace of errors, not only store the last error but a list of them + * and also store the function that set it + */ + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +typedef struct _Eina_Error_Message Eina_Error_Message; +struct _Eina_Error_Message +{ + Eina_Bool string_allocated; + const char *string; +}; + +static Eina_Error_Message *_eina_errors = NULL; +static size_t _eina_errors_count = 0; +static size_t _eina_errors_allocated = 0; +static Eina_Error _eina_last_error; + +static Eina_Error_Message * +_eina_error_msg_alloc(void) +{ + size_t idx; + + if (_eina_errors_count == _eina_errors_allocated) + { + void *tmp; + size_t size; + + if (EINA_UNLIKELY(_eina_errors_allocated == 0)) + size = 24; + else + size = _eina_errors_allocated + 8; + + tmp = realloc(_eina_errors, sizeof(Eina_Error_Message) * size); + if (!tmp) + return NULL; + + _eina_errors = tmp; + _eina_errors_allocated = size; + } + + idx = _eina_errors_count; + _eina_errors_count++; + return _eina_errors + idx; +} + +/** + * @endcond + */ + + +/*============================================================================* +* Global * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +EAPI Eina_Error EINA_ERROR_OUT_OF_MEMORY = 0; + +static const char EINA_ERROR_OUT_OF_MEMORY_STR[] = "Out of memory"; + +/** + * @endcond + */ + +/** + * @internal + * @brief Initialize the error module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the error module of Eina. It is called by + * eina_init(). + * + * This function registers the error #EINA_ERROR_OUT_OF_MEMORY. + * + * @see eina_init() + */ +Eina_Bool +eina_error_init(void) +{ + /* TODO register the eina's basic errors */ + EINA_ERROR_OUT_OF_MEMORY = eina_error_msg_static_register( + EINA_ERROR_OUT_OF_MEMORY_STR); + return EINA_TRUE; +} + +/** + * @internal + * @brief Shut down the error module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the error module set up by + * eina_error_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_error_shutdown(void) +{ + Eina_Error_Message *eem, *eem_end; + + eem = _eina_errors; + eem_end = eem + _eina_errors_count; + + for (; eem < eem_end; eem++) + if (eem->string_allocated) + eina_stringshare_del(eem->string); + + free(_eina_errors); + _eina_errors = NULL; + _eina_errors_count = 0; + _eina_errors_allocated = 0; + + return EINA_TRUE; +} + +/*============================================================================* +* API * +*============================================================================*/ + +EAPI Eina_Error +eina_error_msg_register(const char *msg) +{ + Eina_Error_Message *eem; + + EINA_SAFETY_ON_NULL_RETURN_VAL(msg, 0); + + eem = _eina_error_msg_alloc(); + if (!eem) + return 0; + + eem->string_allocated = EINA_TRUE; + eem->string = eina_stringshare_add(msg); + if (!eem->string) + { + _eina_errors_count--; + return 0; + } + + return _eina_errors_count; /* identifier = index + 1 (== _count). */ +} + +EAPI Eina_Error +eina_error_msg_static_register(const char *msg) +{ + Eina_Error_Message *eem; + + EINA_SAFETY_ON_NULL_RETURN_VAL(msg, 0); + + eem = _eina_error_msg_alloc(); + if (!eem) + return 0; + + eem->string_allocated = EINA_FALSE; + eem->string = msg; + return _eina_errors_count; /* identifier = index + 1 (== _count). */ +} + +EAPI Eina_Bool +eina_error_msg_modify(Eina_Error error, const char *msg) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(msg, EINA_FALSE); + if (error < 1) + return EINA_FALSE; + + if ((size_t)error > _eina_errors_count) + return EINA_FALSE; + + if (_eina_errors[error - 1].string_allocated) + { + const char *tmp; + + if (!(tmp = eina_stringshare_add(msg))) + return EINA_FALSE; + + eina_stringshare_del(_eina_errors[error - 1].string); + _eina_errors[error - 1].string = tmp; + return EINA_TRUE; + } + + _eina_errors[error - 1].string = msg; + return EINA_TRUE; +} + +EAPI const char * +eina_error_msg_get(Eina_Error error) +{ + if (error < 1) + return NULL; + + if ((size_t)error > _eina_errors_count) + return NULL; + + return _eina_errors[error - 1].string; +} + +EAPI Eina_Error +eina_error_get(void) +{ + return _eina_last_error; +} + +EAPI void +eina_error_set(Eina_Error err) +{ + _eina_last_error = err; +} + +EAPI Eina_Error +eina_error_find(const char *msg) +{ + size_t i; + + EINA_SAFETY_ON_NULL_RETURN_VAL(msg, 0); + + for (i = 0; i < _eina_errors_count; i++) + { + if (_eina_errors[i].string_allocated) + { + if (_eina_errors[i].string == msg) + return i + 1; + } + if (!strcmp(_eina_errors[i].string, msg)) + return i + 1; + } + return 0; +} diff --git a/libraries/eina/src/lib/eina_file.c b/libraries/eina/src/lib/eina_file.c new file mode 100644 index 0000000..84b9e78 --- /dev/null +++ b/libraries/eina/src/lib/eina_file.c @@ -0,0 +1,1187 @@ +/* EINA - EFL data type library + * Copyright (C) 2007-2008 Jorge Luis Zapata Muga, Vincent Torri + * Copyright (C) 2010-2011 Cedric Bail + * + * 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 +#include +#include +#include +#include +#include +#include + +#define PATH_DELIM '/' + +#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_mmap.h" + +#ifdef HAVE_ESCAPE_H +# include +#endif + +/*============================================================================* + * 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__) + +#define EINA_SMALL_PAGE 4096 +# define EINA_HUGE_PAGE 16 * 1024 * 1024 + +typedef struct _Eina_File_Iterator Eina_File_Iterator; +typedef struct _Eina_File_Map Eina_File_Map; + +struct _Eina_File_Iterator +{ + Eina_Iterator iterator; + + DIR *dirp; + int length; + + char dir[1]; +}; + +struct _Eina_File +{ + const char *filename; + + Eina_Hash *map; + Eina_Hash *rmap; + void *global_map; + + Eina_Lock lock; + + unsigned long long length; + time_t mtime; + ino_t inode; +#ifdef _STAT_VER_LINUX + unsigned long int mtime_nsec; +#endif + + int refcount; + int global_refcount; + + int fd; + + 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; + + Eina_Bool hugetlb : 1; +}; + +static Eina_Hash *_eina_file_cache = NULL; +static Eina_Lock _eina_file_lock_cache; + +static int _eina_file_log_dom = -1; + +/* + * This complex piece of code is needed due to possible race condition. + * The code and description of the issue can be found at : + * http://womble.decadent.org.uk/readdir_r-advisory.html + */ +static long +_eina_name_max(DIR *dirp) +{ + long name_max; + +#if defined(HAVE_FPATHCONF) && defined(HAVE_DIRFD) && defined(_PC_NAME_MAX) + name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX); + + if (name_max == -1) + { +# if defined(NAME_MAX) + name_max = (NAME_MAX > 255) ? NAME_MAX : 255; +# else + name_max = PATH_MAX; +# endif + } +#else +# if defined(NAME_MAX) + name_max = (NAME_MAX > 255) ? NAME_MAX : 255; +# else +# ifdef _PC_NAME_MAX +# warning "buffer size for readdir_r cannot be determined safely, best effort, but racy" + name_max = pathconf(dirp, _PC_NAME_MAX); +# else +# error "buffer size for readdir_r cannot be determined safely" +# endif +# endif +#endif + + return name_max; +} + +static size_t +_eina_dirent_buffer_size(DIR *dirp) +{ + long name_max = _eina_name_max(dirp); + size_t name_end; + + name_end = (size_t) offsetof(struct dirent, d_name) + name_max + 1; + + return (name_end > sizeof (struct dirent) ? name_end : sizeof (struct dirent)); +} + +static Eina_Bool +_eina_file_ls_iterator_next(Eina_File_Iterator *it, void **data) +{ + struct dirent *dp; + char *name; + size_t length; + + dp = alloca(_eina_dirent_buffer_size(it->dirp)); + + do + { + if (readdir_r(it->dirp, dp, &dp)) + return EINA_FALSE; + if (dp == NULL) + return EINA_FALSE; + } + while ((dp->d_name[0] == '.') && + ((dp->d_name[1] == '\0') || + ((dp->d_name[1] == '.') && (dp->d_name[2] == '\0')))); + +#ifdef _DIRENT_HAVE_D_NAMLEN + length = dp->d_namlen; +#else + length = strlen(dp->d_name); +#endif + name = alloca(length + 2 + it->length); + + memcpy(name, it->dir, it->length); + memcpy(name + it->length, "/", 1); + memcpy(name + it->length + 1, dp->d_name, length + 1); + + *data = (char *)eina_stringshare_add(name); + return EINA_TRUE; +} + +static DIR * +_eina_file_ls_iterator_container(Eina_File_Iterator *it) +{ + return it->dirp; +} + +static void +_eina_file_ls_iterator_free(Eina_File_Iterator *it) +{ + closedir(it->dirp); + + EINA_MAGIC_SET(&it->iterator, 0); + free(it); +} + +typedef struct _Eina_File_Direct_Iterator Eina_File_Direct_Iterator; +struct _Eina_File_Direct_Iterator +{ + Eina_Iterator iterator; + + DIR *dirp; + int length; + + Eina_File_Direct_Info info; + + char dir[1]; +}; + +static Eina_Bool +_eina_file_direct_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data) +{ + struct dirent *dp; + size_t length; + + dp = alloca(_eina_dirent_buffer_size(it->dirp)); + + do + { + if (readdir_r(it->dirp, dp, &dp)) + return EINA_FALSE; + if (!dp) + return EINA_FALSE; + +#ifdef _DIRENT_HAVE_D_NAMLEN + length = dp->d_namlen; +#else + length = strlen(dp->d_name); +#endif + if (it->info.name_start + length + 1 >= EINA_PATH_MAX) + continue; + } + while ((dp->d_name[0] == '.') && + ((dp->d_name[1] == '\0') || + ((dp->d_name[1] == '.') && (dp->d_name[2] == '\0')))); + + memcpy(it->info.path + it->info.name_start, dp->d_name, length); + it->info.name_length = length; + it->info.path_length = it->info.name_start + length; + it->info.path[it->info.path_length] = '\0'; + +#ifdef _DIRENT_HAVE_D_TYPE + switch (dp->d_type) + { + case DT_FIFO: + it->info.type = EINA_FILE_FIFO; + break; + case DT_CHR: + it->info.type = EINA_FILE_CHR; + break; + case DT_DIR: + it->info.type = EINA_FILE_DIR; + break; + case DT_BLK: + it->info.type = EINA_FILE_BLK; + break; + case DT_REG: + it->info.type = EINA_FILE_REG; + break; + case DT_LNK: + it->info.type = EINA_FILE_LNK; + break; + case DT_SOCK: + it->info.type = EINA_FILE_SOCK; + break; + case DT_WHT: + it->info.type = EINA_FILE_WHT; + break; + default: + it->info.type = EINA_FILE_UNKNOWN; + break; + } +#else + it->info.type = EINA_FILE_UNKNOWN; +#endif + + *data = &it->info; + return EINA_TRUE; +} + +static DIR * +_eina_file_direct_ls_iterator_container(Eina_File_Direct_Iterator *it) +{ + return it->dirp; +} + +static void +_eina_file_direct_ls_iterator_free(Eina_File_Direct_Iterator *it) +{ + closedir(it->dirp); + + EINA_MAGIC_SET(&it->iterator, 0); + free(it); +} + +static Eina_Bool +_eina_file_stat_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data) +{ + struct 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 + 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; +} + +static void +_eina_file_real_close(Eina_File *file) +{ + if (file->refcount != 0) return; + + eina_hash_free(file->rmap); + eina_hash_free(file->map); + + if (file->global_map != MAP_FAILED) + munmap(file->global_map, file->length); + + close(file->fd); + + free(file); +} + +static void +_eina_file_map_close(Eina_File_Map *map) +{ + munmap(map->map, map->length); + 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)); +} + +#ifndef MAP_POPULATE +static unsigned int +_eina_file_map_populate(char *map, unsigned int size, Eina_Bool hugetlb) +{ + unsigned int r = 0xDEADBEEF; + unsigned int i; + unsigned int s; + + s = hugetlb ? EINA_HUGE_PAGE : EINA_SMALL_PAGE; + + for (i = 0; i < size; i += s) + r ^= map[i]; + + r ^= map[size]; + + return r; +} +#endif + +static int +_eina_file_map_rule_apply(Eina_File_Populate rule, void *addr, unsigned long int size, Eina_Bool hugetlb) +{ + int tmp = 42; + int flag = MADV_RANDOM; + + switch (rule) + { + case EINA_FILE_RANDOM: flag = MADV_RANDOM; break; + case EINA_FILE_SEQUENTIAL: flag = MADV_SEQUENTIAL; break; + case EINA_FILE_POPULATE: flag = MADV_WILLNEED; break; + case EINA_FILE_WILLNEED: flag = MADV_WILLNEED; break; + } + + madvise(addr, size, flag); + +#ifndef MAP_POPULATE + if (rule == EINA_FILE_POPULATE) + tmp ^= _eina_file_map_populate(addr, size, hugetlb); +#else + (void) hugetlb; +#endif + + return tmp; +} + +static Eina_Bool +_eina_file_timestamp_compare(Eina_File *f, struct stat *st) +{ + if (f->mtime != st->st_mtime) return EINA_FALSE; + if (f->length != (unsigned long long) st->st_size) return EINA_FALSE; + if (f->inode != st->st_ino) return EINA_FALSE; +#ifdef _STAT_VER_LINUX +# if (defined __USE_MISC && defined st_mtime) + if (f->mtime_nsec != (unsigned long int)st->st_mtim.tv_nsec) + return EINA_FALSE; +# else + if (f->mtime_nsec != (unsigned long int)st->st_mtimensec) + return EINA_FALSE; +# endif +#endif + return EINA_TRUE; +} + +static void +slprintf(char *str, size_t size, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + + vsnprintf(str, size, format, ap); + str[size - 1] = 0; + + va_end(ap); +} + +static char* +_eina_file_escape(const char* path, int* length) +{ + char *result = strdup(path ? path : ""); + char *p = result; + char *q = result; + int 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; +} + +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; +} + +/** + * @endcond + */ + +/*============================================================================* + * Global * + *============================================================================*/ + +/*============================================================================* + * API * + *============================================================================*/ + +EAPI char * +eina_file_path_sanitize(const char *path) +{ + char *result = NULL; + int len; + + if (!path) return NULL; + + len = strlen(path); + + if (*path != '/') + { + char cwd[PATH_MAX]; + char *tmp = NULL; + + tmp = getcwd(cwd, PATH_MAX); + if (!tmp) return NULL; + + len += strlen(cwd) + 2; + tmp = alloca(sizeof (char) * len); + + slprintf(tmp, len, "%s/%s", cwd, path); + + result = tmp; + } + + return _eina_file_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) +{ + Eina_File_Direct_Info *info; + Eina_Iterator *it; + + 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); + + it = eina_file_stat_ls(dir); + if (!it) + return EINA_FALSE; + + EINA_ITERATOR_FOREACH(it, info) + { + cb(info->path + info->name_start, dir, data); + + if (recursive == EINA_TRUE && info->type == EINA_FILE_DIR) + { + eina_file_dir_list(info->path, recursive, cb, data); + } + } + + eina_iterator_free(it); + + 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, PATH_DELIM); + current; + path = current + 1, current = strchr(path, PATH_DELIM)) + { + 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; + size_t length; + + EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL); + + length = strlen(dir); + if (length < 1) + return NULL; + + it = calloc(1, sizeof (Eina_File_Iterator) + length); + if (!it) + return NULL; + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->dirp = opendir(dir); + if (!it->dirp) + { + free(it); + return NULL; + } + + memcpy(it->dir, dir, length + 1); + if (dir[length - 1] != '/') + it->length = length; + else + it->length = length - 1; + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_ls_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER( + _eina_file_ls_iterator_container); + it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_ls_iterator_free); + + return &it->iterator; +} + +EAPI Eina_Iterator * +eina_file_direct_ls(const char *dir) +{ + Eina_File_Direct_Iterator *it; + size_t length; + + EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL); + + length = strlen(dir); + if (length < 1) + return NULL; + + it = calloc(1, sizeof(Eina_File_Direct_Iterator) + length); + if (!it) + return NULL; + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->dirp = opendir(dir); + if (!it->dirp) + { + free(it); + return NULL; + } + + if (length + _eina_name_max(it->dirp) + 2 >= EINA_PATH_MAX) + { + _eina_file_direct_ls_iterator_free(it); + return NULL; + } + + memcpy(it->dir, dir, length + 1); + it->length = length; + + 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; + } + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_direct_ls_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER( + _eina_file_direct_ls_iterator_container); + it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_direct_ls_iterator_free); + + return &it->iterator; +} + +EAPI Eina_Iterator * +eina_file_stat_ls(const char *dir) +{ + Eina_File_Direct_Iterator *it; + size_t length; + + EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL); + + length = strlen(dir); + if (length < 1) + return NULL; + + it = calloc(1, sizeof(Eina_File_Direct_Iterator) + length); + if (!it) + return NULL; + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->dirp = opendir(dir); + if (!it->dirp) + { + free(it); + return NULL; + } + + if (length + _eina_name_max(it->dirp) + 2 >= EINA_PATH_MAX) + { + _eina_file_direct_ls_iterator_free(it); + return NULL; + } + + memcpy(it->dir, dir, length + 1); + it->length = length; + + 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; + } + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_stat_ls_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER( + _eina_file_direct_ls_iterator_container); + it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_direct_ls_iterator_free); + + return &it->iterator; +} + +EAPI Eina_File * +eina_file_open(const char *path, Eina_Bool shared) +{ + Eina_File *file; + Eina_File *n; + char *filename; + struct stat file_stat; + int fd = -1; + int flags; + + EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL); + + filename = eina_file_path_sanitize(path); + if (!filename) return NULL; + + if (shared) +#ifdef HAVE_SHMOPEN + fd = shm_open(filename, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO); +#else + goto on_error; +#endif + else + fd = open(filename, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO); + + if (fd < 0) goto on_error; + +#ifdef HAVE_EXECVP + flags = fcntl(fd, F_GETFD); + if (flags == -1) + goto on_error; + + flags |= FD_CLOEXEC; + if (fcntl(fd, F_SETFD, flags) == -1) + goto on_error; +#endif + + if (fstat(fd, &file_stat)) + goto on_error; + + eina_lock_take(&_eina_file_lock_cache); + + file = eina_hash_find(_eina_file_cache, filename); + if ((file) && _eina_file_timestamp_compare(file, &file_stat)) + { + 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 on_error; + } + + 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 = file_stat.st_size; + n->mtime = file_stat.st_mtime; +#ifdef _STAT_VER_LINUX +# if (defined __USE_MISC && defined st_mtime) + n->mtime_nsec = (unsigned long int)file_stat.st_mtim.tv_nsec; +# else + n->mtime_nsec = (unsigned long int)file_stat.st_mtimensec; +# endif +#endif + n->inode = file_stat.st_ino; + n->refcount = 0; + n->fd = fd; + n->shared = shared; + n->delete_me = EINA_FALSE; + eina_lock_new(&n->lock); + eina_hash_direct_add(_eina_file_cache, n->filename, n); + } + else + { + close(fd); + 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; + + on_error: + free(filename); + if (fd >= 0) close(fd); + 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 void * +eina_file_map_all(Eina_File *file, Eina_File_Populate rule) +{ + int flags = MAP_SHARED; + void *ret = NULL; + + EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); + +// bsd people will lack this feature +#ifdef MAP_POPULATE + if (rule == EINA_FILE_POPULATE) flags |= MAP_POPULATE; +#endif +#ifdef MAP_HUGETLB + if (file->length > EINA_HUGE_PAGE) flags |= MAP_HUGETLB; +#endif + + eina_mmap_safety_enabled_set(EINA_TRUE); + eina_lock_take(&file->lock); + if (file->global_map == MAP_FAILED) + file->global_map = mmap(NULL, file->length, PROT_READ, flags, file->fd, 0); +#ifdef MAP_HUGETLB + if ((file->global_map == MAP_FAILED) && (flags & MAP_HUGETLB)) + { + flags &= ~MAP_HUGETLB; + file->global_map = mmap(NULL, file->length, PROT_READ, flags, file->fd, 0); + } +#endif + + if (file->global_map != MAP_FAILED) + { + Eina_Bool hugetlb = EINA_FALSE; + +#ifdef MAP_HUGETLB + hugetlb = !!(flags & MAP_HUGETLB); +#endif + _eina_file_map_rule_apply(rule, file->global_map, file->length, hugetlb); + file->global_refcount++; + ret = file->global_map; + } + + eina_lock_release(&file->lock); + return ret; +} + +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_mmap_safety_enabled_set(EINA_TRUE); + eina_lock_take(&file->lock); + + map = eina_hash_find(file->map, &key); + if (!map) + { + int flags = MAP_SHARED; + +// bsd people will lack this feature +#ifdef MAP_POPULATE + if (rule == EINA_FILE_POPULATE) flags |= MAP_POPULATE; +#endif +#ifdef MAP_HUGETLB + if (length > EINA_HUGE_PAGE) flags |= MAP_HUGETLB; +#endif + + map = malloc(sizeof (Eina_File_Map)); + if (!map) goto on_error; + + map->map = mmap(NULL, length, PROT_READ, flags, file->fd, offset); +#ifdef MAP_HUGETLB + if (map->map == MAP_FAILED && (flags & MAP_HUGETLB)) + { + flags &= ~MAP_HUGETLB; + map->map = mmap(NULL, length, PROT_READ, flags, file->fd, offset); + } + + map->hugetlb = !!(flags & MAP_HUGETLB); +#else + map->hugetlb = EINA_FALSE; +#endif + map->offset = offset; + map->length = length; + map->refcount = 0; + + if (map->map == MAP_FAILED) goto on_error; + + eina_hash_add(file->map, &key, map); + eina_hash_direct_add(file->rmap, map->map, map); + } + + map->refcount++; + + _eina_file_map_rule_apply(rule, map->map, length, map->hugetlb); + + eina_lock_release(&file->lock); + + return map->map; + + on_error: + free(map); + eina_lock_release(&file->lock); + + return NULL; +} + +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; + + munmap(file->global_map, file->length); + 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) 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); +} + + diff --git a/libraries/eina/src/lib/eina_file_win32.c b/libraries/eina/src/lib/eina_file_win32.c new file mode 100644 index 0000000..1cd8665 --- /dev/null +++ b/libraries/eina/src/lib/eina_file_win32.c @@ -0,0 +1,1021 @@ +/* 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); + } +} diff --git a/libraries/eina/src/lib/eina_fp.c b/libraries/eina/src/lib/eina_fp.c new file mode 100644 index 0000000..8984b49 --- /dev/null +++ b/libraries/eina/src/lib/eina_fp.c @@ -0,0 +1,532 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "eina_types.h" +#include "eina_fp.h" + +#define MAX_PREC 1025 +static const Eina_F32p32 eina_trigo[MAX_PREC] = +{ + 0x0000000100000000, 0x00000000ffffec43, 0x00000000ffffb10b, + 0x00000000ffff4e5a, 0x00000000fffec42e, 0x00000000fffe1287, + 0x00000000fffd3967, 0x00000000fffc38cd, 0x00000000fffb10b9, + 0x00000000fff9c12c, + 0x00000000fff84a25, 0x00000000fff6aba5, 0x00000000fff4e5ac, + 0x00000000fff2f83b, 0x00000000fff0e351, 0x00000000ffeea6ef, + 0x00000000ffec4316, 0x00000000ffe9b7c5, 0x00000000ffe704fe, + 0x00000000ffe42ac0, + 0x00000000ffe1290b, 0x00000000ffddffe2, 0x00000000ffdaaf43, + 0x00000000ffd7372f, 0x00000000ffd397a8, 0x00000000ffcfd0ad, + 0x00000000ffcbe23f, 0x00000000ffc7cc5f, 0x00000000ffc38f0d, + 0x00000000ffbf2a4b, + 0x00000000ffba9e17, 0x00000000ffb5ea75, 0x00000000ffb10f63, + 0x00000000ffac0ce3, 0x00000000ffa6e2f6, 0x00000000ffa1919c, + 0x00000000ff9c18d6, 0x00000000ff9678a6, 0x00000000ff90b10b, + 0x00000000ff8ac208, + 0x00000000ff84ab9c, 0x00000000ff7e6dc8, 0x00000000ff78088f, + 0x00000000ff717bf0, 0x00000000ff6ac7ec, 0x00000000ff63ec85, + 0x00000000ff5ce9bc, 0x00000000ff55bf92, 0x00000000ff4e6e08, + 0x00000000ff46f51f, + 0x00000000ff3f54d8, 0x00000000ff378d34, 0x00000000ff2f9e35, + 0x00000000ff2787dc, 0x00000000ff1f4a2a, 0x00000000ff16e520, + 0x00000000ff0e58c0, 0x00000000ff05a50a, 0x00000000fefcca01, + 0x00000000fef3c7a6, + 0x00000000feea9df9, 0x00000000fee14cfe, 0x00000000fed7d4b3, + 0x00000000fece351d, 0x00000000fec46e3b, 0x00000000feba800f, + 0x00000000feb06a9c, 0x00000000fea62de1, 0x00000000fe9bc9e2, + 0x00000000fe913e9f, + 0x00000000fe868c1b, 0x00000000fe7bb256, 0x00000000fe70b153, + 0x00000000fe658913, 0x00000000fe5a3998, 0x00000000fe4ec2e4, + 0x00000000fe4324f9, 0x00000000fe375fd7, 0x00000000fe2b7382, + 0x00000000fe1f5ffa, + 0x00000000fe132543, 0x00000000fe06c35d, 0x00000000fdfa3a4b, + 0x00000000fded8a0e, 0x00000000fde0b2a8, 0x00000000fdd3b41c, + 0x00000000fdc68e6c, 0x00000000fdb94199, 0x00000000fdabcda5, + 0x00000000fd9e3294, + 0x00000000fd907065, 0x00000000fd82871d, 0x00000000fd7476bd, + 0x00000000fd663f46, 0x00000000fd57e0bd, 0x00000000fd495b21, + 0x00000000fd3aae77, 0x00000000fd2bdabf, 0x00000000fd1cdffd, + 0x00000000fd0dbe32, + 0x00000000fcfe7562, 0x00000000fcef058e, 0x00000000fcdf6eb8, + 0x00000000fccfb0e4, 0x00000000fcbfcc13, 0x00000000fcafc048, + 0x00000000fc9f8d86, 0x00000000fc8f33ce, 0x00000000fc7eb325, + 0x00000000fc6e0b8b, + 0x00000000fc5d3d03, 0x00000000fc4c4791, 0x00000000fc3b2b37, + 0x00000000fc29e7f7, 0x00000000fc187dd5, 0x00000000fc06ecd2, + 0x00000000fbf534f2, 0x00000000fbe35637, 0x00000000fbd150a3, + 0x00000000fbbf243b, + 0x00000000fbacd100, 0x00000000fb9a56f6, 0x00000000fb87b61f, + 0x00000000fb74ee7e, 0x00000000fb620016, 0x00000000fb4eeaea, + 0x00000000fb3baefd, 0x00000000fb284c52, 0x00000000fb14c2eb, + 0x00000000fb0112cd, + 0x00000000faed3bf9, 0x00000000fad93e73, 0x00000000fac51a3f, + 0x00000000fab0cf5e, 0x00000000fa9c5dd5, 0x00000000fa87c5a6, + 0x00000000fa7306d5, 0x00000000fa5e2164, 0x00000000fa491558, + 0x00000000fa33e2b3, + 0x00000000fa1e8978, 0x00000000fa0909ab, 0x00000000f9f36350, + 0x00000000f9dd9668, 0x00000000f9c7a2f9, 0x00000000f9b18905, + 0x00000000f99b488f, 0x00000000f984e19c, 0x00000000f96e542e, + 0x00000000f957a049, + 0x00000000f940c5f1, 0x00000000f929c528, 0x00000000f9129df3, + 0x00000000f8fb5056, 0x00000000f8e3dc53, 0x00000000f8cc41ee, + 0x00000000f8b4812b, 0x00000000f89c9a0e, 0x00000000f8848c9b, + 0x00000000f86c58d4, + 0x00000000f853febe, 0x00000000f83b7e5d, 0x00000000f822d7b4, + 0x00000000f80a0ac7, 0x00000000f7f1179a, 0x00000000f7d7fe31, + 0x00000000f7bebe90, 0x00000000f7a558ba, 0x00000000f78bccb3, + 0x00000000f7721a80, + 0x00000000f7584225, 0x00000000f73e43a5, 0x00000000f7241f04, + 0x00000000f709d446, 0x00000000f6ef6370, 0x00000000f6d4cc85, + 0x00000000f6ba0f8a, 0x00000000f69f2c83, 0x00000000f6842374, + 0x00000000f668f461, + 0x00000000f64d9f4e, 0x00000000f632243f, 0x00000000f616833a, + 0x00000000f5fabc41, 0x00000000f5decf59, 0x00000000f5c2bc87, + 0x00000000f5a683cf, 0x00000000f58a2535, 0x00000000f56da0be, + 0x00000000f550f66e, + 0x00000000f5342649, 0x00000000f5173054, 0x00000000f4fa1494, + 0x00000000f4dcd30c, 0x00000000f4bf6bc2, 0x00000000f4a1deb9, + 0x00000000f4842bf7, 0x00000000f4665380, 0x00000000f4485559, + 0x00000000f42a3186, + 0x00000000f40be80c, 0x00000000f3ed78ef, 0x00000000f3cee434, + 0x00000000f3b029e1, 0x00000000f39149f9, 0x00000000f3724482, + 0x00000000f3531980, 0x00000000f333c8f8, 0x00000000f31452ef, + 0x00000000f2f4b76a, + 0x00000000f2d4f66d, 0x00000000f2b50ffe, 0x00000000f2950421, + 0x00000000f274d2dc, 0x00000000f2547c33, 0x00000000f234002b, + 0x00000000f2135eca, 0x00000000f1f29814, 0x00000000f1d1ac0e, + 0x00000000f1b09abe, + 0x00000000f18f6429, 0x00000000f16e0853, 0x00000000f14c8742, + 0x00000000f12ae0fb, 0x00000000f1091583, 0x00000000f0e724e0, + 0x00000000f0c50f17, 0x00000000f0a2d42c, 0x00000000f0807426, + 0x00000000f05def09, + 0x00000000f03b44db, 0x00000000f01875a1, 0x00000000eff58161, + 0x00000000efd2681f, 0x00000000efaf29e2, 0x00000000ef8bc6af, + 0x00000000ef683e8b, 0x00000000ef44917b, 0x00000000ef20bf86, + 0x00000000eefcc8b1, + 0x00000000eed8ad01, 0x00000000eeb46c7b, 0x00000000ee900727, + 0x00000000ee6b7d08, 0x00000000ee46ce25, 0x00000000ee21fa83, + 0x00000000edfd0228, 0x00000000edd7e51a, 0x00000000edb2a35f, + 0x00000000ed8d3cfc, + 0x00000000ed67b1f6, 0x00000000ed420255, 0x00000000ed1c2e1d, + 0x00000000ecf63554, 0x00000000ecd01801, 0x00000000eca9d628, + 0x00000000ec836fd1, 0x00000000ec5ce501, 0x00000000ec3635bd, + 0x00000000ec0f620d, + 0x00000000ebe869f5, 0x00000000ebc14d7d, 0x00000000eb9a0ca9, + 0x00000000eb72a780, 0x00000000eb4b1e08, 0x00000000eb237047, + 0x00000000eafb9e43, 0x00000000ead3a803, 0x00000000eaab8d8d, + 0x00000000ea834ee6, + 0x00000000ea5aec15, 0x00000000ea326520, 0x00000000ea09ba0d, + 0x00000000e9e0eae4, 0x00000000e9b7f7a9, 0x00000000e98ee063, + 0x00000000e965a51a, 0x00000000e93c45d2, 0x00000000e912c292, + 0x00000000e8e91b61, + 0x00000000e8bf5046, 0x00000000e8956146, 0x00000000e86b4e68, + 0x00000000e84117b3, 0x00000000e816bd2d, 0x00000000e7ec3edc, + 0x00000000e7c19cc8, 0x00000000e796d6f6, 0x00000000e76bed6e, + 0x00000000e740e036, + 0x00000000e715af54, 0x00000000e6ea5ad0, 0x00000000e6bee2af, + 0x00000000e69346f9, 0x00000000e66787b5, 0x00000000e63ba4e9, + 0x00000000e60f9e9b, 0x00000000e5e374d4, 0x00000000e5b72798, + 0x00000000e58ab6f1, + 0x00000000e55e22e3, 0x00000000e5316b76, 0x00000000e50490b1, + 0x00000000e4d7929c, 0x00000000e4aa713c, 0x00000000e47d2c98, + 0x00000000e44fc4b9, 0x00000000e42239a4, 0x00000000e3f48b61, + 0x00000000e3c6b9f7, + 0x00000000e398c56c, 0x00000000e36aadc9, 0x00000000e33c7314, + 0x00000000e30e1554, 0x00000000e2df9490, 0x00000000e2b0f0d0, + 0x00000000e2822a1a, 0x00000000e2534077, 0x00000000e22433ec, + 0x00000000e1f50482, + 0x00000000e1c5b240, 0x00000000e1963d2d, 0x00000000e166a550, + 0x00000000e136eab0, 0x00000000e1070d56, 0x00000000e0d70d48, + 0x00000000e0a6ea8e, 0x00000000e076a52f, 0x00000000e0463d33, + 0x00000000e015b2a1, + 0x00000000dfe50580, 0x00000000dfb435d9, 0x00000000df8343b2, + 0x00000000df522f13, 0x00000000df20f804, 0x00000000deef9e8d, + 0x00000000debe22b5, 0x00000000de8c8483, 0x00000000de5ac3ff, + 0x00000000de28e131, + 0x00000000ddf6dc21, 0x00000000ddc4b4d6, 0x00000000dd926b59, + 0x00000000dd5fffb0, 0x00000000dd2d71e3, 0x00000000dcfac1fb, + 0x00000000dcc7f000, 0x00000000dc94fbf8, 0x00000000dc61e5ec, + 0x00000000dc2eade4, + 0x00000000dbfb53e8, 0x00000000dbc7d7ff, 0x00000000db943a31, + 0x00000000db607a88, 0x00000000db2c9909, 0x00000000daf895bf, + 0x00000000dac470af, 0x00000000da9029e3, 0x00000000da5bc163, + 0x00000000da273737, + 0x00000000d9f28b66, 0x00000000d9bdbdf9, 0x00000000d988cef8, + 0x00000000d953be6b, 0x00000000d91e8c5b, 0x00000000d8e938d0, + 0x00000000d8b3c3d1, 0x00000000d87e2d67, 0x00000000d848759b, + 0x00000000d8129c74, + 0x00000000d7dca1fb, 0x00000000d7a68638, 0x00000000d7704934, + 0x00000000d739eaf7, 0x00000000d7036b89, 0x00000000d6cccaf3, + 0x00000000d696093d, 0x00000000d65f266f, 0x00000000d6282293, + 0x00000000d5f0fdb0, + 0x00000000d5b9b7d0, 0x00000000d58250fa, 0x00000000d54ac937, + 0x00000000d513208f, 0x00000000d4db570c, 0x00000000d4a36cb6, + 0x00000000d46b6195, 0x00000000d43335b3, 0x00000000d3fae917, + 0x00000000d3c27bcb, + 0x00000000d389edd7, 0x00000000d3513f43, 0x00000000d318701a, + 0x00000000d2df8063, 0x00000000d2a67027, 0x00000000d26d3f6f, + 0x00000000d233ee43, 0x00000000d1fa7cae, 0x00000000d1c0eab7, + 0x00000000d1873867, + 0x00000000d14d65c8, 0x00000000d11372e1, 0x00000000d0d95fbd, + 0x00000000d09f2c64, 0x00000000d064d8df, 0x00000000d02a6537, + 0x00000000cfefd176, 0x00000000cfb51da3, 0x00000000cf7a49c8, + 0x00000000cf3f55ef, + 0x00000000cf044220, 0x00000000cec90e64, 0x00000000ce8dbac5, + 0x00000000ce52474c, 0x00000000ce16b401, 0x00000000cddb00ef, + 0x00000000cd9f2e1e, 0x00000000cd633b97, 0x00000000cd272964, + 0x00000000cceaf78e, + 0x00000000ccaea61e, 0x00000000cc72351e, 0x00000000cc35a497, + 0x00000000cbf8f492, 0x00000000cbbc2519, 0x00000000cb7f3634, + 0x00000000cb4227ee, 0x00000000cb04fa50, 0x00000000cac7ad63, + 0x00000000ca8a4131, + 0x00000000ca4cb5c3, 0x00000000ca0f0b22, 0x00000000c9d14159, + 0x00000000c9935870, 0x00000000c9555072, 0x00000000c9172967, + 0x00000000c8d8e35a, 0x00000000c89a7e53, 0x00000000c85bfa5e, + 0x00000000c81d5782, + 0x00000000c7de95cb, 0x00000000c79fb541, 0x00000000c760b5ee, + 0x00000000c72197dc, 0x00000000c6e25b15, 0x00000000c6a2ffa3, + 0x00000000c663858f, 0x00000000c623ece2, 0x00000000c5e435a8, + 0x00000000c5a45fe9, + 0x00000000c5646bb0, 0x00000000c5245906, 0x00000000c4e427f6, + 0x00000000c4a3d888, 0x00000000c4636ac8, 0x00000000c422debf, + 0x00000000c3e23476, 0x00000000c3a16bf9, 0x00000000c3608550, + 0x00000000c31f8087, + 0x00000000c2de5da6, 0x00000000c29d1cb8, 0x00000000c25bbdc8, + 0x00000000c21a40de, 0x00000000c1d8a606, 0x00000000c196ed49, + 0x00000000c15516b2, 0x00000000c113224a, 0x00000000c0d1101d, + 0x00000000c08ee033, + 0x00000000c04c9297, 0x00000000c00a2754, 0x00000000bfc79e73, + 0x00000000bf84f800, 0x00000000bf423404, 0x00000000beff5289, + 0x00000000bebc539a, 0x00000000be793741, 0x00000000be35fd89, + 0x00000000bdf2a67b, + 0x00000000bdaf3223, 0x00000000bd6ba08b, 0x00000000bd27f1bc, + 0x00000000bce425c2, 0x00000000bca03ca7, 0x00000000bc5c3676, + 0x00000000bc181338, 0x00000000bbd3d2f9, 0x00000000bb8f75c3, + 0x00000000bb4afba1, + 0x00000000bb06649c, 0x00000000bac1b0c0, 0x00000000ba7ce018, + 0x00000000ba37f2ad, 0x00000000b9f2e88b, 0x00000000b9adc1bc, + 0x00000000b9687e4a, 0x00000000b9231e41, 0x00000000b8dda1ac, + 0x00000000b8980894, + 0x00000000b8525305, 0x00000000b80c8109, 0x00000000b7c692ac, + 0x00000000b78087f7, 0x00000000b73a60f6, 0x00000000b6f41db4, + 0x00000000b6adbe3a, 0x00000000b6674296, 0x00000000b620aad0, + 0x00000000b5d9f6f4, + 0x00000000b593270e, 0x00000000b54c3b27, 0x00000000b505334a, + 0x00000000b4be0f84, 0x00000000b476cfde, 0x00000000b42f7464, + 0x00000000b3e7fd20, 0x00000000b3a06a1e, 0x00000000b358bb69, + 0x00000000b310f10c, + 0x00000000b2c90b11, 0x00000000b2810985, 0x00000000b238ec71, + 0x00000000b1f0b3e2, 0x00000000b1a85fe2, 0x00000000b15ff07c, + 0x00000000b11765bc, 0x00000000b0cebfad, 0x00000000b085fe5a, + 0x00000000b03d21ce, + 0x00000000aff42a15, 0x00000000afab1739, 0x00000000af61e946, + 0x00000000af18a048, 0x00000000aecf3c49, 0x00000000ae85bd55, + 0x00000000ae3c2377, 0x00000000adf26ebb, 0x00000000ada89f2c, + 0x00000000ad5eb4d5, + 0x00000000ad14afc2, 0x00000000acca8ffd, 0x00000000ac805594, + 0x00000000ac360090, 0x00000000abeb90fe, 0x00000000aba106e9, + 0x00000000ab56625d, 0x00000000ab0ba364, 0x00000000aac0ca0b, + 0x00000000aa75d65d, + 0x00000000aa2ac865, 0x00000000a9dfa030, 0x00000000a9945dc9, + 0x00000000a949013a, 0x00000000a8fd8a91, 0x00000000a8b1f9d8, + 0x00000000a8664f1c, 0x00000000a81a8a68, 0x00000000a7ceabc7, + 0x00000000a782b345, + 0x00000000a736a0ef, 0x00000000a6ea74cf, 0x00000000a69e2ef2, + 0x00000000a651cf63, 0x00000000a605562f, 0x00000000a5b8c360, + 0x00000000a56c1702, 0x00000000a51f5123, 0x00000000a4d271cc, + 0x00000000a485790b, + 0x00000000a43866eb, 0x00000000a3eb3b77, 0x00000000a39df6bd, + 0x00000000a35098c7, 0x00000000a30321a2, 0x00000000a2b5915a, + 0x00000000a267e7fa, 0x00000000a21a258e, 0x00000000a1cc4a24, + 0x00000000a17e55c5, + 0x00000000a1304880, 0x00000000a0e2225f, 0x00000000a093e36f, + 0x00000000a0458bbb, 0x000000009ff71b50, 0x000000009fa8923a, + 0x000000009f59f086, 0x000000009f0b363e, 0x000000009ebc6370, + 0x000000009e6d7827, + 0x000000009e1e746f, 0x000000009dcf5856, 0x000000009d8023e6, + 0x000000009d30d72d, 0x000000009ce17236, 0x000000009c91f50e, + 0x000000009c425fc1, 0x000000009bf2b25b, 0x000000009ba2ece8, + 0x000000009b530f76, + 0x000000009b031a0f, 0x000000009ab30cc1, 0x000000009a62e797, + 0x000000009a12aa9f, 0x0000000099c255e5, 0x000000009971e974, + 0x000000009921655a, 0x0000000098d0c9a2, 0x0000000098801659, + 0x00000000982f4b8d, + 0x0000000097de6948, 0x00000000978d6f97, 0x00000000973c5e88, + 0x0000000096eb3626, 0x000000009699f67f, 0x0000000096489f9e, + 0x0000000095f73190, 0x0000000095a5ac61, 0x000000009554101f, + 0x0000000095025cd6, + 0x0000000094b09292, 0x00000000945eb161, 0x00000000940cb94e, + 0x0000000093baaa66, 0x00000000936884b6, 0x000000009316484b, + 0x0000000092c3f531, 0x0000000092718b75, 0x00000000921f0b24, + 0x0000000091cc744b, + 0x000000009179c6f5, 0x0000000091270331, 0x0000000090d4290a, + 0x000000009081388e, 0x00000000902e31c8, 0x000000008fdb14c7, + 0x000000008f87e197, 0x000000008f349845, 0x000000008ee138dd, + 0x000000008e8dc36c, + 0x000000008e3a3800, 0x000000008de696a5, 0x000000008d92df68, + 0x000000008d3f1256, 0x000000008ceb2f7c, 0x000000008c9736e7, + 0x000000008c4328a3, 0x000000008bef04bf, 0x000000008b9acb46, + 0x000000008b467c45, + 0x000000008af217cb, 0x000000008a9d9de3, 0x000000008a490e9b, + 0x0000000089f469ff, 0x00000000899fb01e, 0x00000000894ae103, + 0x0000000088f5fcbc, 0x0000000088a10357, 0x00000000884bf4df, + 0x0000000087f6d163, + 0x0000000087a198f0, 0x00000000874c4b92, 0x0000000086f6e956, + 0x0000000086a1724b, 0x00000000864be67c, 0x0000000085f645f8, + 0x0000000085a090cc, 0x00000000854ac704, 0x0000000084f4e8ad, + 0x00000000849ef5d7, + 0x000000008448ee8c, 0x0000000083f2d2db, 0x00000000839ca2d1, + 0x0000000083465e7c, 0x0000000082f005e8, 0x0000000082999922, + 0x0000000082431839, 0x0000000081ec833a, 0x000000008195da31, + 0x00000000813f1d2d, + 0x0000000080e84c3a, 0x0000000080916766, 0x00000000803a6ebf, + 0x000000007fe36251, 0x000000007f8c422b, 0x000000007f350e59, + 0x000000007eddc6ea, 0x000000007e866bea, 0x000000007e2efd67, + 0x000000007dd77b6f, + 0x000000007d7fe60f, 0x000000007d283d54, 0x000000007cd0814c, + 0x000000007c78b205, 0x000000007c20cf8c, 0x000000007bc8d9ef, + 0x000000007b70d13b, 0x000000007b18b57e, 0x000000007ac086c5, + 0x000000007a68451f, + 0x000000007a0ff098, 0x0000000079b7893e, 0x00000000795f0f1f, + 0x0000000079068248, 0x0000000078ade2c8, 0x00000000785530ab, + 0x0000000077fc6c01, 0x0000000077a394d5, 0x00000000774aab36, + 0x0000000076f1af32, + 0x000000007698a0d6, 0x00000000763f8030, 0x0000000075e64d4e, + 0x00000000758d083e, 0x000000007533b10d, 0x0000000074da47c9, + 0x000000007480cc80, 0x0000000074273f3f, 0x0000000073cda016, + 0x000000007373ef10, + 0x00000000731a2c3d, 0x0000000072c057aa, 0x0000000072667164, + 0x00000000720c797a, 0x0000000071b26ffa, 0x00000000715854f2, + 0x0000000070fe286e, 0x0000000070a3ea7e, 0x0000000070499b30, + 0x000000006fef3a90, + 0x000000006f94c8ae, 0x000000006f3a4596, 0x000000006edfb157, + 0x000000006e850c00, 0x000000006e2a559d, 0x000000006dcf8e3d, + 0x000000006d74b5ee, 0x000000006d19ccbe, 0x000000006cbed2bb, + 0x000000006c63c7f3, + 0x000000006c08ac74, 0x000000006bad804c, 0x000000006b524389, + 0x000000006af6f639, 0x000000006a9b986b, 0x000000006a402a2c, + 0x0000000069e4ab8a, 0x0000000069891c94, 0x00000000692d7d57, + 0x0000000068d1cde3, + 0x0000000068760e44, 0x00000000681a3e89, 0x0000000067be5ec1, + 0x0000000067626ef9, 0x0000000067066f40, 0x0000000066aa5fa3, + 0x00000000664e4032, 0x0000000065f210f9, 0x000000006595d209, + 0x000000006539836d, + 0x0000000064dd2536, 0x000000006480b770, 0x0000000064243a2b, + 0x0000000063c7ad75, 0x00000000636b115c, 0x00000000630e65ed, + 0x0000000062b1ab39, 0x000000006254e14c, 0x0000000061f80835, + 0x00000000619b2002, + 0x00000000613e28c2, 0x0000000060e12283, 0x0000000060840d54, + 0x000000006026e943, 0x000000005fc9b65d, 0x000000005f6c74b2, + 0x000000005f0f2450, 0x000000005eb1c545, 0x000000005e5457a0, + 0x000000005df6db6f, + 0x000000005d9950c0, 0x000000005d3bb7a3, 0x000000005cde1024, + 0x000000005c805a54, 0x000000005c22963f, 0x000000005bc4c3f6, + 0x000000005b66e385, 0x000000005b08f4fd, 0x000000005aaaf86a, + 0x000000005a4ceddc, + 0x0000000059eed561, 0x000000005990af08, 0x0000000059327adf, + 0x0000000058d438f4, 0x000000005875e957, 0x0000000058178c16, + 0x0000000057b9213f, 0x00000000575aa8e0, 0x0000000056fc230a, + 0x00000000569d8fc9, + 0x00000000563eef2d, 0x0000000055e04144, 0x000000005581861d, + 0x000000005522bdc6, 0x0000000054c3e84e, 0x00000000546505c4, + 0x0000000054061636, 0x0000000053a719b3, 0x000000005348104a, + 0x0000000052e8fa09, + 0x000000005289d6ff, 0x00000000522aa73a, 0x0000000051cb6aca, + 0x00000000516c21bc, 0x00000000510ccc20, 0x0000000050ad6a05, + 0x00000000504dfb78, 0x000000004fee808a, 0x000000004f8ef947, + 0x000000004f2f65c0, + 0x000000004ecfc603, 0x000000004e701a1f, 0x000000004e106222, + 0x000000004db09e1b, 0x000000004d50ce19, 0x000000004cf0f22b, + 0x000000004c910a5f, 0x000000004c3116c5, 0x000000004bd1176b, + 0x000000004b710c5f, + 0x000000004b10f5b2, 0x000000004ab0d371, 0x000000004a50a5ab, + 0x0000000049f06c70, 0x00000000499027cd, 0x00000000492fd7d3, + 0x0000000048cf7c8f, 0x00000000486f1611, 0x00000000480ea467, + 0x0000000047ae27a1, + 0x00000000474d9fcd, 0x0000000046ed0cfa, 0x00000000468c6f37, + 0x00000000462bc693, 0x0000000045cb131c, 0x00000000456a54e3, + 0x0000000045098bf5, 0x0000000044a8b861, 0x000000004447da37, + 0x0000000043e6f186, + 0x000000004385fe5c, 0x00000000432500c8, 0x0000000042c3f8d9, + 0x000000004262e69f, 0x000000004201ca28, 0x0000000041a0a383, + 0x00000000413f72bf, 0x0000000040de37eb, 0x00000000407cf317, + 0x00000000401ba450, + 0x000000003fba4ba7, 0x000000003f58e92a, 0x000000003ef77ce8, + 0x000000003e9606f1, 0x000000003e348752, 0x000000003dd2fe1c, + 0x000000003d716b5e, 0x000000003d0fcf25, 0x000000003cae2982, + 0x000000003c4c7a83, + 0x000000003beac238, 0x000000003b8900b0, 0x000000003b2735f9, + 0x000000003ac56223, 0x000000003a63853d, 0x000000003a019f56, + 0x00000000399fb07d, 0x00000000393db8c1, 0x0000000038dbb831, + 0x000000003879aedd, + 0x0000000038179cd3, 0x0000000037b58222, 0x0000000037535edb, + 0x0000000036f1330b, 0x00000000368efec2, 0x00000000362cc20f, + 0x0000000035ca7d02, 0x0000000035682fa9, 0x000000003505da14, + 0x0000000034a37c51, + 0x0000000034411671, 0x0000000033dea881, 0x00000000337c3292, + 0x000000003319b4b3, 0x0000000032b72ef2, 0x000000003254a15e, + 0x0000000031f20c08, 0x00000000318f6efe, 0x00000000312cca50, + 0x0000000030ca1e0c, + 0x0000000030676a43, 0x000000003004af02, 0x000000002fa1ec5a, + 0x000000002f3f2259, 0x000000002edc510f, 0x000000002e79788b, + 0x000000002e1698dc, 0x000000002db3b212, 0x000000002d50c43c, + 0x000000002cedcf68, + 0x000000002c8ad3a7, 0x000000002c27d108, 0x000000002bc4c799, + 0x000000002b61b76b, 0x000000002afea08c, 0x000000002a9b830b, + 0x000000002a385ef9, 0x0000000029d53464, 0x000000002972035b, + 0x00000000290ecbee, + 0x0000000028ab8e2c, 0x0000000028484a25, 0x0000000027e4ffe7, + 0x000000002781af83, 0x00000000271e5906, 0x0000000026bafc82, + 0x0000000026579a04, 0x0000000025f4319d, 0x000000002590c35c, + 0x00000000252d4f4f, + 0x0000000024c9d587, 0x0000000024665613, 0x000000002402d101, + 0x00000000239f4662, 0x00000000233bb644, 0x0000000022d820b8, + 0x00000000227485cc, 0x000000002210e590, 0x0000000021ad4013, + 0x0000000021499565, + 0x0000000020e5e594, 0x00000000208230b1, 0x00000000201e76ca, + 0x000000001fbab7ef, 0x000000001f56f430, 0x000000001ef32b9b, + 0x000000001e8f5e41, 0x000000001e2b8c30, 0x000000001dc7b578, + 0x000000001d63da29, + 0x000000001cfffa51, 0x000000001c9c1600, 0x000000001c382d46, + 0x000000001bd44032, 0x000000001b704ed3, 0x000000001b0c5939, + 0x000000001aa85f74, 0x000000001a446191, 0x0000000019e05fa2, + 0x00000000197c59b5, + 0x0000000019184fdb, 0x0000000018b44221, 0x0000000018503098, + 0x0000000017ec1b50, 0x0000000017880257, 0x000000001723e5bd, + 0x0000000016bfc591, 0x00000000165ba1e4, 0x0000000015f77ac3, + 0x0000000015935040, + 0x00000000152f2269, 0x0000000014caf14d, 0x000000001466bcfd, + 0x0000000014028587, 0x00000000139e4afb, 0x00000000133a0d69, + 0x0000000012d5cce0, 0x000000001271896f, 0x00000000120d4326, + 0x0000000011a8fa15, + 0x000000001144ae4a, 0x0000000010e05fd6, 0x00000000107c0ec7, + 0x000000001017bb2d, 0x000000000fb36519, 0x000000000f4f0c98, + 0x000000000eeab1bb, 0x000000000e865491, 0x000000000e21f52a, + 0x000000000dbd9395, + 0x000000000d592fe1, 0x000000000cf4ca1f, 0x000000000c90625c, + 0x000000000c2bf8aa, 0x000000000bc78d18, 0x000000000b631fb4, + 0x000000000afeb08f, 0x000000000a9a3fb8, 0x000000000a35cd3e, + 0x0000000009d15931, + 0x00000000096ce3a1, 0x0000000009086c9c, 0x0000000008a3f433, + 0x00000000083f7a75, 0x0000000007daff71, 0x0000000007768337, + 0x00000000071205d6, 0x0000000006ad875f, 0x00000000064907df, + 0x0000000005e48768, + 0x0000000005800608, 0x00000000051b83cf, 0x0000000004b700cc, + 0x0000000004527d0f, 0x0000000003edf8a7, 0x00000000038973a4, + 0x000000000324ee16, 0x0000000002c0680b, 0x00000000025be194, + 0x0000000001f75ac0, + 0x000000000192d39e, 0x00000000012e4c3e, 0x0000000000c9c4af, + 0x0000000000653d02, 0x0000000000000000 +}; + +EAPI Eina_F32p32 +eina_f32p32_cos(Eina_F32p32 a) +{ + Eina_F32p32 F32P32_2PI; + Eina_F32p32 F32P32_PI2; + Eina_F32p32 F32P32_3PI2; + Eina_F32p32 remainder_2PI; + Eina_F32p32 remainder_PI; + Eina_F32p32 interpol; + Eina_F32p32 result; + int idx; + int index2; + + F32P32_2PI = EINA_F32P32_PI << 1; + F32P32_PI2 = EINA_F32P32_PI >> 1; + F32P32_3PI2 = EINA_F32P32_PI + F32P32_PI2; + + /* Take advantage of cosinus symetrie. */ + a = eina_fp32p32_llabs(a); + + /* Find table entry in 0 to PI / 2 */ + remainder_PI = a - (a / EINA_F32P32_PI) * EINA_F32P32_PI; + + /* Find which case from 0 to 2 * PI */ + remainder_2PI = a - (a / F32P32_2PI) * F32P32_2PI; + + interpol = eina_f32p32_div(eina_f32p32_scale(remainder_PI, MAX_PREC * 2), + EINA_F32P32_PI); + idx = eina_f32p32_int_to(interpol); + if (idx >= MAX_PREC) + idx = 2 * MAX_PREC - (idx + 1); + + index2 = idx + 1; + if (index2 == MAX_PREC) + index2 = idx - 1; + + result = eina_f32p32_add(eina_trigo[idx], + eina_f32p32_mul(eina_f32p32_sub(eina_trigo[idx], + eina_trigo[index2]), + (Eina_F32p32)eina_f32p32_fracc_get( + interpol))); + + if (0 <= remainder_2PI && remainder_2PI < F32P32_PI2) + return result; + else if (F32P32_PI2 <= remainder_2PI && remainder_2PI < EINA_F32P32_PI) + return -result; + else if (EINA_F32P32_PI <= remainder_2PI && remainder_2PI < F32P32_3PI2) + return -result; + else /* if (F32P32_3PI2 <= remainder_2PI) */ + return result; +} + +EAPI Eina_F32p32 +eina_f32p32_sin(Eina_F32p32 a) +{ + Eina_F32p32 F32P32_2PI; + Eina_F32p32 F32P32_PI2; + Eina_F32p32 F32P32_3PI2; + Eina_F32p32 remainder_2PI; + Eina_F32p32 remainder_PI; + Eina_F32p32 interpol; + Eina_F32p32 result; + int idx; + int index2; + + F32P32_2PI = EINA_F32P32_PI << 1; + F32P32_PI2 = EINA_F32P32_PI >> 1; + F32P32_3PI2 = EINA_F32P32_PI + F32P32_PI2; + + /* We only have a table for cosinus, but sin(a) = cos(pi / 2 - a) */ + a = eina_f32p32_sub(F32P32_PI2, a); + + /* Take advantage of cosinus symetrie. */ + a = eina_fp32p32_llabs(a); + + /* Find table entry in 0 to PI / 2 */ + remainder_PI = a - (a / EINA_F32P32_PI) * EINA_F32P32_PI; + + /* Find which case from 0 to 2 * PI */ + remainder_2PI = a - (a / F32P32_2PI) * F32P32_2PI; + + interpol = eina_f32p32_div(eina_f32p32_scale(remainder_PI, MAX_PREC * 2), + EINA_F32P32_PI); + idx = eina_f32p32_int_to(interpol); + if (idx >= MAX_PREC) + idx = 2 * MAX_PREC - (idx + 1); + + index2 = idx + 1; + if (index2 == MAX_PREC) + index2 = idx - 1; + + result = eina_f32p32_add(eina_trigo[idx], + eina_f32p32_mul(eina_f32p32_sub(eina_trigo[idx], + eina_trigo[index2]), + (Eina_F32p32)eina_f32p32_fracc_get( + interpol))); + + if (0 <= remainder_2PI && remainder_2PI < F32P32_PI2) + return result; + else if (F32P32_PI2 <= remainder_2PI && remainder_2PI < EINA_F32P32_PI) + return -result; + else if (EINA_F32P32_PI <= remainder_2PI && remainder_2PI < F32P32_3PI2) + return -result; + else /* if (F32P32_3PI2 <= remainder_2PI) */ + return result; +} + diff --git a/libraries/eina/src/lib/eina_hamster.c b/libraries/eina/src/lib/eina_hamster.c new file mode 100644 index 0000000..cebc10b --- /dev/null +++ b/libraries/eina/src/lib/eina_hamster.c @@ -0,0 +1,113 @@ +/* EINA - EFL data type library + * Copyright (C) 2008 Cedric Bail + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "eina_config.h" +#include "eina_types.h" +#include "eina_hamster.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +const char *_eina_hamster_time = __TIME__; +const char *_eina_hamster_date = __DATE__; +static int _eina_hamsters = -1; + +/** + * @endcond + */ + +/*============================================================================* +* Global * +*============================================================================*/ + +/*============================================================================* +* API * +*============================================================================*/ + +EAPI int +eina_hamster_count(void) +{ + if (_eina_hamsters < 0) + { + int hrs = 0, min = 0, sec = 0; + char mon[8] = ""; + int monnum = 0, day = 0, year = 0; + int fields; + + fields = sscanf(_eina_hamster_time, "%02d:%02d:%02d", &hrs, &min, &sec); + if (fields == 3) + { + _eina_hamsters = (hrs * 60) + min; + fields = sscanf(_eina_hamster_date, "%s %d %d", mon, &day, &year); + if (fields == 3) + { + int i; + const char *mons[] = + { + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" + }; + + for (i = 0; i < 12; i++) + { + if (!strcmp(mon, mons[i])) + { + monnum = i + 1; + break; + } + } + // alloc 60 for mins, 24 for hrs + // alloc 1-31 (32) for days, 1-12 (13) for months + // use year as-is, for 31 bits (signed) this gives us up to + // 3584 years, which is good enough imho. - 1500 years from + // now or so. :) + _eina_hamsters += + (day + (monnum * 32) + (13 * 32 * year)) * (24 * 60); + } + } + } + + // format: [rest - year][0-12 - month][0-31 - day][0-23 - hrs][0-59 - sec] + return _eina_hamsters; +} + +/** + * @} + */ diff --git a/libraries/eina/src/lib/eina_hash.c b/libraries/eina/src/lib/eina_hash.c new file mode 100644 index 0000000..5df20aa --- /dev/null +++ b/libraries/eina/src/lib/eina_hash.c @@ -0,0 +1,1375 @@ +/* EINA - EFL data type library + * Copyright (C) 2002-2008 Carsten Haitzler, Gustavo Sverzut Barbieri, + * Vincent Torri, Jorge Luis Zapata Muga, Cedric Bail + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_STDINT_H +# include +#endif + +#ifdef _MSC_VER +# include +#endif + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_rbtree.h" +#include "eina_error.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_hash.h" + +/*============================================================================* + * Local * + *============================================================================*/ + +/** + * @cond LOCAL + */ + +#define EINA_MAGIC_CHECK_HASH(d) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_HASH)) { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_HASH); } \ + } while(0) + +#define EINA_MAGIC_CHECK_HASH_ITERATOR(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_HASH_ITERATOR)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_HASH_ITERATOR); \ + return __VA_ARGS__; \ + } \ + } while(0) + +#define EINA_HASH_BUCKET_SIZE 8 +#define EINA_HASH_SMALL_BUCKET_SIZE 5 + +#define EINA_HASH_RBTREE_MASK 0xFFF + +typedef struct _Eina_Hash_Head Eina_Hash_Head; +typedef struct _Eina_Hash_Element Eina_Hash_Element; +typedef struct _Eina_Hash_Foreach_Data Eina_Hash_Foreach_Data; +typedef struct _Eina_Iterator_Hash Eina_Iterator_Hash; +typedef struct _Eina_Hash_Each Eina_Hash_Each; + +struct _Eina_Hash +{ + Eina_Key_Length key_length_cb; + Eina_Key_Cmp key_cmp_cb; + Eina_Key_Hash key_hash_cb; + Eina_Free_Cb data_free_cb; + + Eina_Rbtree **buckets; + int size; + int mask; + + int population; + + EINA_MAGIC +}; + +struct _Eina_Hash_Head +{ + EINA_RBTREE; + int hash; + + Eina_Rbtree *head; +}; + +struct _Eina_Hash_Element +{ + EINA_RBTREE; + Eina_Hash_Tuple tuple; + Eina_Bool begin : 1; +}; + +struct _Eina_Hash_Foreach_Data +{ + Eina_Hash_Foreach cb; + const void *fdata; +}; + +typedef void *(*Eina_Iterator_Get_Content_Callback)(Eina_Iterator_Hash *it); +#define FUNC_ITERATOR_GET_CONTENT(Function) \ + ((Eina_Iterator_Get_Content_Callback)Function) + +struct _Eina_Iterator_Hash +{ + Eina_Iterator iterator; + + Eina_Iterator_Get_Content_Callback get_content; + const Eina_Hash *hash; + + Eina_Iterator *current; + Eina_Iterator *list; + Eina_Hash_Head *hash_head; + Eina_Hash_Element *hash_element; + int bucket; + + int index; + + EINA_MAGIC +}; + +struct _Eina_Hash_Each +{ + Eina_Hash_Head *hash_head; + const Eina_Hash_Element *hash_element; + const void *data; +}; + +#undef get16bits +#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ + || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) +# define get16bits(d) (*((const uint16_t *)(d))) +#endif + +#if !defined (get16bits) +# define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ + + (uint32_t)(((const uint8_t *)(d))[0])) +#endif + +static inline int +_eina_hash_hash_rbtree_cmp_hash(const Eina_Hash_Head *hash_head, + const int *hash, + __UNUSED__ int key_length, + __UNUSED__ void *data) +{ + return hash_head->hash - *hash; +} + +static Eina_Rbtree_Direction +_eina_hash_hash_rbtree_cmp_node(const Eina_Hash_Head *left, + const Eina_Hash_Head *right, + __UNUSED__ void *data) +{ + if (left->hash - right->hash < 0) + return EINA_RBTREE_LEFT; + + return EINA_RBTREE_RIGHT; +} + +static inline int +_eina_hash_key_rbtree_cmp_key_data(const Eina_Hash_Element *hash_element, + const Eina_Hash_Tuple *tuple, + __UNUSED__ unsigned int key_length, + Eina_Key_Cmp cmp) +{ + int result; + + result = cmp(hash_element->tuple.key, + hash_element->tuple.key_length, + tuple->key, + tuple->key_length); + + if (result == 0 && tuple->data && tuple->data != hash_element->tuple.data) + return 1; + + return result; +} + +static Eina_Rbtree_Direction +_eina_hash_key_rbtree_cmp_node(const Eina_Hash_Element *left, + const Eina_Hash_Element *right, + Eina_Key_Cmp cmp) +{ + int result; + + result = cmp(left->tuple.key, left->tuple.key_length, + right->tuple.key, right->tuple.key_length); + + if (result < 0) + return EINA_RBTREE_LEFT; + + return EINA_RBTREE_RIGHT; +} + +static inline Eina_Bool +eina_hash_add_alloc_by_hash(Eina_Hash *hash, + const void *key, int key_length, int alloc_length, + int key_hash, + const void *data) +{ + Eina_Hash_Element *new_hash_element = NULL; + Eina_Hash_Head *hash_head; + Eina_Error error = 0; + int hash_num; + + EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE); + EINA_MAGIC_CHECK_HASH(hash); + + error = EINA_ERROR_OUT_OF_MEMORY; + + /* Apply eina mask to hash. */ + hash_num = key_hash & hash->mask; + key_hash &= EINA_HASH_RBTREE_MASK; + + if (!hash->buckets) + { + hash->buckets = calloc(sizeof (Eina_Rbtree *), hash->size); + if (!hash->buckets) goto on_error; + + hash_head = NULL; + } + else + /* Look up for head node. */ + hash_head = (Eina_Hash_Head *) + eina_rbtree_inline_lookup(hash->buckets[hash_num], + &key_hash, 0, + EINA_RBTREE_CMP_KEY_CB( + _eina_hash_hash_rbtree_cmp_hash), + NULL); + + if (!hash_head) + { + /* If not found allocate it and an element. */ + hash_head = malloc(sizeof(Eina_Hash_Head) + sizeof(Eina_Hash_Element) + + alloc_length); + if (!hash_head) + goto on_error; + + hash_head->hash = key_hash; + hash_head->head = NULL; + + hash->buckets[hash_num] = + eina_rbtree_inline_insert(hash->buckets[hash_num], + EINA_RBTREE_GET(hash_head), + EINA_RBTREE_CMP_NODE_CB( + _eina_hash_hash_rbtree_cmp_node), + NULL); + + new_hash_element = (Eina_Hash_Element *)(hash_head + 1); + new_hash_element->begin = EINA_TRUE; + } + + if (!new_hash_element) + { + /* + Alloc a new element + (No more lookup as we expect to support more than one item for one key). + */ + new_hash_element = malloc(sizeof (Eina_Hash_Element) + alloc_length); + if (!new_hash_element) + goto on_error; + + new_hash_element->begin = EINA_FALSE; + } + + /* Setup the element */ + new_hash_element->tuple.key_length = key_length; + new_hash_element->tuple.data = (void *)data; + if (alloc_length > 0) + { + new_hash_element->tuple.key = (char *)(new_hash_element + 1); + memcpy((char *)new_hash_element->tuple.key, key, alloc_length); + } + else + new_hash_element->tuple.key = key; + + /* add the new element to the hash. */ + hash_head->head = eina_rbtree_inline_insert(hash_head->head, + EINA_RBTREE_GET(new_hash_element), + EINA_RBTREE_CMP_NODE_CB( + _eina_hash_key_rbtree_cmp_node), + (const void *)hash->key_cmp_cb); + hash->population++; + return EINA_TRUE; + +on_error: + eina_error_set(error); + return EINA_FALSE; +} + +static Eina_Bool +_eina_hash_rbtree_each(__UNUSED__ const Eina_Rbtree *container, + const Eina_Hash_Head *hash_head, + Eina_Hash_Each *data) +{ + Eina_Iterator *it; + Eina_Hash_Element *hash_element; + Eina_Bool found = EINA_TRUE; + + it = eina_rbtree_iterator_prefix(hash_head->head); + EINA_ITERATOR_FOREACH(it, hash_element) + { + if (hash_element->tuple.data == data->data) + { + data->hash_element = hash_element; + data->hash_head = (Eina_Hash_Head *)hash_head; + found = EINA_FALSE; + break; + } + } + + eina_iterator_free(it); + return found; +} + +static inline Eina_Hash_Element * +_eina_hash_find_by_hash(const Eina_Hash *hash, + Eina_Hash_Tuple *tuple, + int key_hash, + Eina_Hash_Head **hash_head) +{ + Eina_Hash_Element *hash_element; + int rb_hash = key_hash & EINA_HASH_RBTREE_MASK; + + key_hash &= hash->mask; + + if (!hash->buckets) + return NULL; + + *hash_head = (Eina_Hash_Head *) + eina_rbtree_inline_lookup(hash->buckets[key_hash], + &rb_hash, 0, + EINA_RBTREE_CMP_KEY_CB( + _eina_hash_hash_rbtree_cmp_hash), + NULL); + if (!*hash_head) + return NULL; + + hash_element = (Eina_Hash_Element *) + eina_rbtree_inline_lookup((*hash_head)->head, + tuple, 0, + EINA_RBTREE_CMP_KEY_CB( + _eina_hash_key_rbtree_cmp_key_data), + (const void *)hash->key_cmp_cb); + + return hash_element; +} + +static inline Eina_Hash_Element * +_eina_hash_find_by_data(const Eina_Hash *hash, + const void *data, + int *key_hash, + Eina_Hash_Head **hash_head) +{ + Eina_Hash_Each each; + Eina_Iterator *it; + int hash_num; + + if (!hash->buckets) + return NULL; + + each.hash_element = NULL; + each.data = data; + + for (hash_num = 0; hash_num < hash->size; hash_num++) + { + if (!hash->buckets[hash_num]) + continue; + + it = eina_rbtree_iterator_prefix(hash->buckets[hash_num]); + eina_iterator_foreach(it, EINA_EACH_CB(_eina_hash_rbtree_each), &each); + eina_iterator_free(it); + + if (each.hash_element) + { + *key_hash = hash_num; + *hash_head = each.hash_head; + return (Eina_Hash_Element *)each.hash_element; + } + } + + return NULL; +} + +static void +_eina_hash_el_free(Eina_Hash_Element *hash_element, Eina_Hash *hash) +{ + if (hash->data_free_cb) + hash->data_free_cb(hash_element->tuple.data); + + if (hash_element->begin == EINA_FALSE) + free(hash_element); +} + +static void +_eina_hash_head_free(Eina_Hash_Head *hash_head, Eina_Hash *hash) +{ + eina_rbtree_delete(hash_head->head, EINA_RBTREE_FREE_CB(_eina_hash_el_free), hash); + free(hash_head); +} + +static Eina_Bool +_eina_hash_del_by_hash_el(Eina_Hash *hash, + Eina_Hash_Element *hash_element, + Eina_Hash_Head *hash_head, + int key_hash) +{ + hash_head->head = eina_rbtree_inline_remove(hash_head->head, EINA_RBTREE_GET( + hash_element), EINA_RBTREE_CMP_NODE_CB( + _eina_hash_key_rbtree_cmp_node), + (const void *)hash->key_cmp_cb); + _eina_hash_el_free(hash_element, hash); + + if (!hash_head->head) + { + key_hash &= hash->mask; + + hash->buckets[key_hash] = + eina_rbtree_inline_remove(hash->buckets[key_hash], EINA_RBTREE_GET( + hash_head), + EINA_RBTREE_CMP_NODE_CB( + _eina_hash_hash_rbtree_cmp_node), NULL); + free(hash_head); + } + + hash->population--; + if (hash->population == 0) + { + free(hash->buckets); + hash->buckets = NULL; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_hash_del_by_key_hash(Eina_Hash *hash, + const void *key, + int key_length, + int key_hash, + const void *data) +{ + Eina_Hash_Element *hash_element; + Eina_Hash_Head *hash_head; + Eina_Hash_Tuple tuple; + + EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE); + EINA_MAGIC_CHECK_HASH(hash); + + if (!hash->buckets) + return EINA_FALSE; + + tuple.key = (void *)key; + tuple.key_length = key_length; + tuple.data = (void *)data; + + hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head); + if (!hash_element) + return EINA_FALSE; + + return _eina_hash_del_by_hash_el(hash, hash_element, hash_head, key_hash); +} + +static Eina_Bool +_eina_hash_del_by_key(Eina_Hash *hash, const void *key, const void *data) +{ + int key_length, key_hash; + + EINA_MAGIC_CHECK_HASH(hash); + if (!hash) + return EINA_FALSE; + + if (!key) + return EINA_FALSE; + + if (!hash->buckets) + return EINA_FALSE; + + key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0; + key_hash = hash->key_hash_cb(key, key_length); + return _eina_hash_del_by_key_hash(hash, key, key_length, key_hash, data); +} + +static unsigned int +_eina_string_key_length(const char *key) +{ + if (!key) + return 0; + + return (int)strlen(key) + 1; +} + +static int +_eina_string_key_cmp(const char *key1, __UNUSED__ int key1_length, + const char *key2, __UNUSED__ int key2_length) +{ + return strcmp(key1, key2); +} + +static int +_eina_stringshared_key_cmp(const char *key1, __UNUSED__ int key1_length, + const char *key2, __UNUSED__ int key2_length) +{ + return key1 - key2; +} + +static unsigned int +_eina_int32_key_length(__UNUSED__ const uint32_t *key) +{ + return 4; +} + +static int +_eina_int32_key_cmp(const uint32_t *key1, __UNUSED__ int key1_length, + const uint32_t *key2, __UNUSED__ int key2_length) +{ + return *key1 - *key2; +} + +static unsigned int +_eina_int64_key_length(__UNUSED__ const uint32_t *key) +{ + return 8; +} + +static int +_eina_int64_key_cmp(const uint64_t *key1, __UNUSED__ int key1_length, + const uint64_t *key2, __UNUSED__ int key2_length) +{ + return *key1 - *key2; +} + +static Eina_Bool +_eina_foreach_cb(const Eina_Hash *hash, + Eina_Hash_Tuple *data, + Eina_Hash_Foreach_Data *fdata) +{ + return fdata->cb((Eina_Hash *)hash, + data->key, + data->data, + (void *)fdata->fdata); +} + +static void * +_eina_hash_iterator_data_get_content(Eina_Iterator_Hash *it) +{ + Eina_Hash_Element *stuff; + + EINA_MAGIC_CHECK_HASH_ITERATOR(it, NULL); + + stuff = it->hash_element; + + if (!stuff) + return NULL; + + return stuff->tuple.data; +} + +static void * +_eina_hash_iterator_key_get_content(Eina_Iterator_Hash *it) +{ + Eina_Hash_Element *stuff; + + EINA_MAGIC_CHECK_HASH_ITERATOR(it, NULL); + + stuff = it->hash_element; + + if (!stuff) + return NULL; + + return (void *)stuff->tuple.key; +} + +static Eina_Hash_Tuple * +_eina_hash_iterator_tuple_get_content(Eina_Iterator_Hash *it) +{ + Eina_Hash_Element *stuff; + + EINA_MAGIC_CHECK_HASH_ITERATOR(it, NULL); + + stuff = it->hash_element; + + if (!stuff) + return NULL; + + return &stuff->tuple; +} + +static Eina_Bool +_eina_hash_iterator_next(Eina_Iterator_Hash *it, void **data) +{ + Eina_Bool ok; + int bucket; + + if (!(it->index < it->hash->population)) + return EINA_FALSE; + + if (!it->current) + { + ok = EINA_FALSE; + bucket = 0; + it->index = -1; + } + else + { + ok = eina_iterator_next(it->list, (void **)(void*)&it->hash_element); + if (!ok) + { + eina_iterator_free(it->list); + it->list = NULL; + + ok = eina_iterator_next(it->current, (void **)(void*)&it->hash_head); + if (!ok) + { + eina_iterator_free(it->current); + it->current = NULL; + it->bucket++; + } + else + { + it->list = eina_rbtree_iterator_prefix(it->hash_head->head); + ok = eina_iterator_next(it->list, (void **)(void*)&it->hash_element); + } + } + + bucket = it->bucket; + } + + if (ok == EINA_FALSE) + { + while (bucket < it->hash->size) + { + if (it->hash->buckets[bucket]) + { + it->current = + eina_rbtree_iterator_prefix(it->hash->buckets[bucket]); + ok = eina_iterator_next(it->current, (void **)(void*)&it->hash_head); + if (ok) + break; + + eina_iterator_free(it->current); + it->current = NULL; + } + + ++bucket; + } + if (it->list) + eina_iterator_free(it->list); + + it->list = eina_rbtree_iterator_prefix(it->hash_head->head); + ok = eina_iterator_next(it->list, (void **)(void*)&it->hash_element); + if (bucket == it->hash->size) + ok = EINA_FALSE; + } + + it->index++; + it->bucket = bucket; + + if (ok) + *data = it->get_content(it); + + return ok; +} + +static void * +_eina_hash_iterator_get_container(Eina_Iterator_Hash *it) +{ + EINA_MAGIC_CHECK_HASH_ITERATOR(it, NULL); + return (void *)it->hash; +} + +static void +_eina_hash_iterator_free(Eina_Iterator_Hash *it) +{ + EINA_MAGIC_CHECK_HASH_ITERATOR(it); + if (it->current) + eina_iterator_free(it->current); + + if (it->list) + eina_iterator_free(it->list); + + free(it); +} + +/** + * @endcond + */ + +/*============================================================================* + * Global * + *============================================================================*/ + +/*============================================================================* + * API * + *============================================================================*/ + +EAPI void +eina_hash_free_cb_set(Eina_Hash *hash, Eina_Free_Cb data_free_cb) +{ + EINA_MAGIC_CHECK_HASH(hash); + EINA_SAFETY_ON_NULL_RETURN(hash); + + hash->data_free_cb = data_free_cb; +} + +EAPI Eina_Hash * +eina_hash_new(Eina_Key_Length key_length_cb, + Eina_Key_Cmp key_cmp_cb, + Eina_Key_Hash key_hash_cb, + Eina_Free_Cb data_free_cb, + int buckets_power_size) +{ + /* FIXME: Use mempool. */ + Eina_Hash *new; + + eina_error_set(0); + EINA_SAFETY_ON_NULL_RETURN_VAL(key_cmp_cb, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(key_hash_cb, NULL); + EINA_SAFETY_ON_TRUE_RETURN_VAL(buckets_power_size <= 2, NULL); + EINA_SAFETY_ON_TRUE_RETURN_VAL(buckets_power_size >= 17, NULL); + + new = malloc(sizeof (Eina_Hash)); + if (!new) + goto on_error; + + EINA_MAGIC_SET(new, EINA_MAGIC_HASH); + + new->key_length_cb = key_length_cb; + new->key_cmp_cb = key_cmp_cb; + new->key_hash_cb = key_hash_cb; + new->data_free_cb = data_free_cb; + new->buckets = NULL; + new->population = 0; + + new->size = 1 << buckets_power_size; + new->mask = new->size - 1; + + return new; + +on_error: + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; +} + +EAPI Eina_Hash * +eina_hash_string_djb2_new(Eina_Free_Cb data_free_cb) +{ + return eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length), + EINA_KEY_CMP(_eina_string_key_cmp), + EINA_KEY_HASH(eina_hash_djb2), + data_free_cb, + EINA_HASH_BUCKET_SIZE); +} + +EAPI Eina_Hash * +eina_hash_string_superfast_new(Eina_Free_Cb data_free_cb) +{ + return eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length), + EINA_KEY_CMP(_eina_string_key_cmp), + EINA_KEY_HASH(eina_hash_superfast), + data_free_cb, + EINA_HASH_BUCKET_SIZE); +} + +EAPI Eina_Hash * +eina_hash_string_small_new(Eina_Free_Cb data_free_cb) +{ + return eina_hash_new(EINA_KEY_LENGTH(_eina_string_key_length), + EINA_KEY_CMP(_eina_string_key_cmp), + EINA_KEY_HASH(eina_hash_superfast), + data_free_cb, + EINA_HASH_SMALL_BUCKET_SIZE); +} + +EAPI Eina_Hash * +eina_hash_int32_new(Eina_Free_Cb data_free_cb) +{ + return eina_hash_new(EINA_KEY_LENGTH(_eina_int32_key_length), + EINA_KEY_CMP(_eina_int32_key_cmp), + EINA_KEY_HASH(eina_hash_int32), + data_free_cb, + EINA_HASH_BUCKET_SIZE); +} + +EAPI Eina_Hash * +eina_hash_int64_new(Eina_Free_Cb data_free_cb) +{ + return eina_hash_new(EINA_KEY_LENGTH(_eina_int64_key_length), + EINA_KEY_CMP(_eina_int64_key_cmp), + EINA_KEY_HASH(eina_hash_int64), + data_free_cb, + EINA_HASH_BUCKET_SIZE); +} + +EAPI Eina_Hash * +eina_hash_pointer_new(Eina_Free_Cb data_free_cb) +{ +#ifdef __LP64__ + return eina_hash_new(EINA_KEY_LENGTH(_eina_int64_key_length), + EINA_KEY_CMP(_eina_int64_key_cmp), + EINA_KEY_HASH(eina_hash_int64), + data_free_cb, + EINA_HASH_BUCKET_SIZE); +#else + return eina_hash_new(EINA_KEY_LENGTH(_eina_int32_key_length), + EINA_KEY_CMP(_eina_int32_key_cmp), + EINA_KEY_HASH(eina_hash_int32), + data_free_cb, + EINA_HASH_BUCKET_SIZE); +#endif +} + +EAPI Eina_Hash * +eina_hash_stringshared_new(Eina_Free_Cb data_free_cb) +{ + return eina_hash_new(NULL, + EINA_KEY_CMP(_eina_stringshared_key_cmp), + EINA_KEY_HASH(eina_hash_superfast), + data_free_cb, + EINA_HASH_BUCKET_SIZE); +} + +EAPI int +eina_hash_population(const Eina_Hash *hash) +{ + if (!hash) + return 0; + + EINA_MAGIC_CHECK_HASH(hash); + return hash->population; +} + +EAPI void +eina_hash_free(Eina_Hash *hash) +{ + int i; + + EINA_MAGIC_CHECK_HASH(hash); + EINA_SAFETY_ON_NULL_RETURN(hash); + + if (hash->buckets) + { + for (i = 0; i < hash->size; i++) + eina_rbtree_delete(hash->buckets[i], EINA_RBTREE_FREE_CB(_eina_hash_head_free), hash); + free(hash->buckets); + } + free(hash); +} + +EAPI void +eina_hash_free_buckets(Eina_Hash *hash) +{ + int i; + + EINA_MAGIC_CHECK_HASH(hash); + EINA_SAFETY_ON_NULL_RETURN(hash); + + if (hash->buckets) + { + for (i = 0; i < hash->size; i++) + eina_rbtree_delete(hash->buckets[i], + EINA_RBTREE_FREE_CB(_eina_hash_head_free), hash); + free(hash->buckets); + hash->buckets = NULL; + hash->population = 0; + } +} + +EAPI Eina_Bool +eina_hash_add_by_hash(Eina_Hash *hash, + const void *key, + int key_length, + int key_hash, + const void *data) +{ + return eina_hash_add_alloc_by_hash(hash, + key, + key_length, + key_length, + key_hash, + data); +} + +EAPI Eina_Bool +eina_hash_direct_add_by_hash(Eina_Hash *hash, + const void *key, + int key_length, + int key_hash, + const void *data) +{ + return eina_hash_add_alloc_by_hash(hash, key, key_length, 0, key_hash, data); +} + +EAPI Eina_Bool +eina_hash_add(Eina_Hash *hash, const void *key, const void *data) +{ + unsigned int key_length; + int key_hash; + + EINA_MAGIC_CHECK_HASH(hash); + EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE); + + key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0; + key_hash = hash->key_hash_cb(key, key_length); + + return eina_hash_add_alloc_by_hash(hash, key, key_length, key_length, key_hash, data); +} + +EAPI Eina_Bool +eina_hash_direct_add(Eina_Hash *hash, const void *key, const void *data) +{ + int key_length; + int key_hash; + + EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE); + EINA_MAGIC_CHECK_HASH(hash); + + key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0; + key_hash = hash->key_hash_cb(key, key_length); + + return eina_hash_add_alloc_by_hash(hash, key, key_length, 0, key_hash, data); +} + +EAPI Eina_Bool +eina_hash_del_by_key_hash(Eina_Hash *hash, + const void *key, + int key_length, + int key_hash) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE); + + return _eina_hash_del_by_key_hash(hash, key, key_length, key_hash, NULL); +} + +EAPI Eina_Bool +eina_hash_del_by_key(Eina_Hash *hash, const void *key) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE); + + return _eina_hash_del_by_key(hash, key, NULL); +} + +EAPI Eina_Bool +eina_hash_del_by_data(Eina_Hash *hash, const void *data) +{ + Eina_Hash_Element *hash_element; + Eina_Hash_Head *hash_head; + int key_hash; + + EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE); + EINA_MAGIC_CHECK_HASH(hash); + + hash_element = _eina_hash_find_by_data(hash, data, &key_hash, &hash_head); + if (!hash_element) + goto error; + + if (hash_element->tuple.data != data) + goto error; + + return _eina_hash_del_by_hash_el(hash, hash_element, hash_head, key_hash); + +error: + return EINA_FALSE; +} + +EAPI Eina_Bool +eina_hash_del_by_hash(Eina_Hash *hash, + const void *key, + int key_length, + int key_hash, + const void *data) +{ + Eina_Bool ret; + + EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE); + EINA_MAGIC_CHECK_HASH(hash); + + if (key) + ret = _eina_hash_del_by_key_hash(hash, key, key_length, key_hash, data); + else + ret = eina_hash_del_by_data(hash, data); + + return ret; +} + +EAPI Eina_Bool +eina_hash_del(Eina_Hash *hash, const void *key, const void *data) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE); + EINA_MAGIC_CHECK_HASH(hash); + + if (!key) + return eina_hash_del_by_data(hash, data); + + return _eina_hash_del_by_key(hash, key, data); +} + +EAPI void * +eina_hash_find_by_hash(const Eina_Hash *hash, + const void *key, + int key_length, + int key_hash) +{ + Eina_Hash_Head *hash_head; + Eina_Hash_Element *hash_element; + Eina_Hash_Tuple tuple; + + if (!hash) + return NULL; + + EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL); + EINA_MAGIC_CHECK_HASH(hash); + + tuple.key = key; + tuple.key_length = key_length; + tuple.data = NULL; + + hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head); + if (hash_element) + return hash_element->tuple.data; + + return NULL; +} + +EAPI void * +eina_hash_find(const Eina_Hash *hash, const void *key) +{ + int key_length; + int hash_num; + + if (!hash) + return NULL; + + EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL); + EINA_MAGIC_CHECK_HASH(hash); + + key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0; + hash_num = hash->key_hash_cb(key, key_length); + + return eina_hash_find_by_hash(hash, key, key_length, hash_num); +} + +EAPI void * +eina_hash_modify_by_hash(Eina_Hash *hash, + const void *key, + int key_length, + int key_hash, + const void *data) +{ + Eina_Hash_Head *hash_head; + Eina_Hash_Element *hash_element; + void *old_data = NULL; + Eina_Hash_Tuple tuple; + + EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL); + EINA_MAGIC_CHECK_HASH(hash); + + tuple.key = key; + tuple.key_length = key_length; + tuple.data = NULL; + + hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head); + if (hash_element) + { + old_data = hash_element->tuple.data; + hash_element->tuple.data = (void *)data; + } + + return old_data; +} + +EAPI void * +eina_hash_set(Eina_Hash *hash, const void *key, const void *data) +{ + Eina_Hash_Tuple tuple; + Eina_Hash_Head *hash_head; + Eina_Hash_Element *hash_element; + int key_length; + int key_hash; + + EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL); + EINA_MAGIC_CHECK_HASH(hash); + + key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0; + key_hash = hash->key_hash_cb(key, key_length); + + tuple.key = key; + tuple.key_length = key_length; + tuple.data = NULL; + + hash_element = _eina_hash_find_by_hash(hash, &tuple, key_hash, &hash_head); + if (hash_element) + { + void *old_data = NULL; + + old_data = hash_element->tuple.data; + + if (data) + { + hash_element->tuple.data = (void *)data; + } + else + { + _eina_hash_del_by_hash_el(hash, hash_element, hash_head, key_hash); + } + + return old_data; + } + + if (!data) return NULL; + + eina_hash_add_alloc_by_hash(hash, + key, + key_length, + key_length, + key_hash, + data); + return NULL; +} +EAPI void * +eina_hash_modify(Eina_Hash *hash, const void *key, const void *data) +{ + int key_length; + int hash_num; + + EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL); + EINA_MAGIC_CHECK_HASH(hash); + + key_length = hash->key_length_cb ? hash->key_length_cb(key) : 0; + hash_num = hash->key_hash_cb(key, key_length); + + return eina_hash_modify_by_hash(hash, key, key_length, hash_num, data); +} + +EAPI Eina_Bool +eina_hash_move(Eina_Hash *hash, const void *old_key, const void *new_key) +{ + Eina_Free_Cb hash_free_cb; + const void *data; + Eina_Bool result = EINA_FALSE; + + EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(hash->key_hash_cb, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(old_key, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(new_key, EINA_FALSE); + EINA_MAGIC_CHECK_HASH(hash); + + data = eina_hash_find(hash, old_key); + if (!data) goto error; + + hash_free_cb = hash->data_free_cb; + hash->data_free_cb = NULL; + + eina_hash_del(hash, old_key, data); + result = eina_hash_add(hash, new_key, data); + + hash->data_free_cb = hash_free_cb; + +error: + return result; +} + +/*============================================================================* +* Iterator * +*============================================================================*/ + +EAPI void +eina_hash_foreach(const Eina_Hash *hash, + Eina_Hash_Foreach func, + const void *fdata) +{ + Eina_Iterator *it; + Eina_Hash_Foreach_Data foreach; + + EINA_MAGIC_CHECK_HASH(hash); + EINA_SAFETY_ON_NULL_RETURN(hash); + EINA_SAFETY_ON_NULL_RETURN(func); + + foreach.cb = func; + foreach.fdata = fdata; + + it = eina_hash_iterator_tuple_new(hash); + if (!it) + return; + eina_iterator_foreach(it, EINA_EACH_CB(_eina_foreach_cb), &foreach); + + eina_iterator_free(it); +} + +EAPI Eina_Iterator * +eina_hash_iterator_data_new(const Eina_Hash *hash) +{ + Eina_Iterator_Hash *it; + + EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL); + EINA_MAGIC_CHECK_HASH(hash); + + eina_error_set(0); + it = calloc(1, sizeof (Eina_Iterator_Hash)); + if (!it) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + it->hash = hash; + it->get_content = FUNC_ITERATOR_GET_CONTENT(_eina_hash_iterator_data_get_content); + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_eina_hash_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER( + _eina_hash_iterator_get_container); + it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free); + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + EINA_MAGIC_SET(it, EINA_MAGIC_HASH_ITERATOR); + + return &it->iterator; +} + +EAPI Eina_Iterator * +eina_hash_iterator_key_new(const Eina_Hash *hash) +{ + Eina_Iterator_Hash *it; + + EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL); + EINA_MAGIC_CHECK_HASH(hash); + + eina_error_set(0); + it = calloc(1, sizeof (Eina_Iterator_Hash)); + if (!it) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + it->hash = hash; + it->get_content = FUNC_ITERATOR_GET_CONTENT( + _eina_hash_iterator_key_get_content); + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_eina_hash_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER( + _eina_hash_iterator_get_container); + it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free); + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + EINA_MAGIC_SET(it, EINA_MAGIC_HASH_ITERATOR); + + return &it->iterator; +} + +EAPI Eina_Iterator * +eina_hash_iterator_tuple_new(const Eina_Hash *hash) +{ + Eina_Iterator_Hash *it; + + EINA_SAFETY_ON_NULL_RETURN_VAL(hash, NULL); + EINA_MAGIC_CHECK_HASH(hash); + + eina_error_set(0); + it = calloc(1, sizeof (Eina_Iterator_Hash)); + if (!it) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + it->hash = hash; + it->get_content = FUNC_ITERATOR_GET_CONTENT( + _eina_hash_iterator_tuple_get_content); + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_eina_hash_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER( + _eina_hash_iterator_get_container); + it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free); + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + EINA_MAGIC_SET(it, EINA_MAGIC_HASH_ITERATOR); + + return &it->iterator; +} + +/* Common hash functions */ + +/* Paul Hsieh (http://www.azillionmonkeys.com/qed/hash.html) + used by WebCore (http://webkit.org/blog/8/hashtables-part-2/) */ +EAPI int +eina_hash_superfast(const char *key, int len) +{ + int hash = len, tmp; + int rem; + + rem = len & 3; + len >>= 2; + + /* Main loop */ + for (; len > 0; len--) + { + hash += get16bits(key); + tmp = (get16bits(key + 2) << 11) ^ hash; + hash = (hash << 16) ^ tmp; + key += 2 * sizeof (uint16_t); + hash += hash >> 11; + } + + /* Handle end cases */ + switch (rem) + { + case 3: + hash += get16bits(key); + hash ^= hash << 16; + hash ^= key[sizeof (uint16_t)] << 18; + hash += hash >> 11; + break; + + case 2: + hash += get16bits(key); + hash ^= hash << 11; + hash += hash >> 17; + break; + + case 1: + hash += *key; + hash ^= hash << 10; + hash += hash >> 1; + } + + /* Force "avalanching" of final 127 bits */ + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + + return hash; +} diff --git a/libraries/eina/src/lib/eina_inlist.c b/libraries/eina/src/lib/eina_inlist.c new file mode 100644 index 0000000..75a2cc1 --- /dev/null +++ b/libraries/eina/src/lib/eina_inlist.c @@ -0,0 +1,909 @@ +/* EINA - EFL data type library + * Copyright (C) 2002-2008 Carsten Haitzler, 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 + +#include +#include + +#include + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_error.h" +#include "eina_log.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_inlist.h" + +/* FIXME: TODO please, refactor this :) */ + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +#define EINA_INLIST_SORT_STACK_SIZE 32 + +typedef struct _Eina_Iterator_Inlist Eina_Iterator_Inlist; +typedef struct _Eina_Accessor_Inlist Eina_Accessor_Inlist; + +struct _Eina_Iterator_Inlist +{ + Eina_Iterator iterator; + const Eina_Inlist *head; + const Eina_Inlist *current; +}; + +struct _Eina_Accessor_Inlist +{ + Eina_Accessor accessor; + + const Eina_Inlist *head; + const Eina_Inlist *current; + + unsigned int index; +}; + +struct _Eina_Inlist_Sorted_State +{ + Eina_Inlist *jump_table[EINA_INLIST_JUMP_SIZE]; + + unsigned short jump_limit; + int jump_div; + + int inserted; +}; + +static Eina_Bool +eina_inlist_iterator_next(Eina_Iterator_Inlist *it, void **data) { + if (!it->current) + return EINA_FALSE; + + if (data) + *data = (void *)it->current; + + it->current = it->current->next; + + return EINA_TRUE; +} + +static Eina_Inlist * +eina_inlist_iterator_get_container(Eina_Iterator_Inlist *it) { + return (Eina_Inlist *)it->head; +} + +static void +eina_inlist_iterator_free(Eina_Iterator_Inlist *it) { + free(it); +} + +static Eina_Bool +eina_inlist_accessor_get_at(Eina_Accessor_Inlist *it, + unsigned int idx, + void **data) { + const Eina_Inlist *over; + unsigned int middle; + unsigned int i; + + if (it->index == idx) + over = it->current; + else if (idx > it->index) + /* Looking after current. */ + for (i = it->index, over = it->current; + i < idx && over; + ++i, over = over->next) + ; + else + { + middle = it->index >> 1; + + if (idx > middle) + /* Looking backward from current. */ + for (i = it->index, over = it->current; + i > idx && over; + --i, over = over->prev) + ; + else + /* Looking from the start. */ + for (i = 0, over = it->head; + i < idx && over; + ++i, over = over->next) + ; + } + + if (!over) + return EINA_FALSE; + + it->current = over; + it->index = idx; + + if (data) + *data = (void *)over; + + return EINA_TRUE; +} + +static Eina_Inlist * +eina_inlist_accessor_get_container(Eina_Accessor_Inlist *it) { + return (Eina_Inlist *)it->head; +} + +static void +eina_inlist_accessor_free(Eina_Accessor_Inlist *it) { + free(it); +} + +static Eina_Inlist * +eina_inlist_sort_merge(Eina_Inlist *a, Eina_Inlist *b, Eina_Compare_Cb func) +{ + Eina_Inlist *first, *last; + + if (func(a, b) < 0) + a = (last = first = a)->next; + else + b = (last = first = b)->next; + + while (a && b) + if (func(a, b) < 0) + a = (last = last->next = a)->next; + else + b = (last = last->next = b)->next; + + last->next = a ? a : b; + + return first; +} + +static Eina_Inlist * +eina_inlist_sort_rebuild_prev(Eina_Inlist *list) +{ + Eina_Inlist *prev = NULL; + + for (; list; list = list->next) + { + list->prev = prev; + prev = list; + } + + return prev; +} + +static void +_eina_inlist_sorted_state_compact(Eina_Inlist_Sorted_State *state) +{ + unsigned short i, j; + + /* compress the jump table */ + state->jump_div *= 2; + state->jump_limit /= 2; + + for (i = 2, j = 1; + i < EINA_INLIST_JUMP_SIZE; + i += 2, j++) + state->jump_table[j] = state->jump_table[i]; +} + +/** + * @endcond + */ + + +/*============================================================================* +* Global * +*============================================================================*/ + +/*============================================================================* +* API * +*============================================================================*/ + +EAPI Eina_Inlist * +eina_inlist_append(Eina_Inlist *list, Eina_Inlist *new_l) +{ + Eina_Inlist *l; + + EINA_SAFETY_ON_NULL_RETURN_VAL(new_l, list); + + new_l->next = NULL; + if (!list) + { + new_l->prev = NULL; + new_l->last = new_l; + return new_l; + } + + if (list->last) + l = list->last; + else + for (l = list; (l) && (l->next); l = l->next) + ; + + l->next = new_l; + new_l->prev = l; + list->last = new_l; + return list; +} + +EAPI Eina_Inlist * +eina_inlist_prepend(Eina_Inlist *list, Eina_Inlist *new_l) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(new_l, list); + + new_l->prev = NULL; + if (!list) + { + new_l->next = NULL; + new_l->last = new_l; + return new_l; + } + + new_l->next = list; + list->prev = new_l; + new_l->last = list->last; + list->last = NULL; + return new_l; +} + +EAPI Eina_Inlist * +eina_inlist_append_relative(Eina_Inlist *list, + Eina_Inlist *new_l, + Eina_Inlist *relative) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(new_l, list); + + if (relative) + { + if (relative->next) + { + new_l->next = relative->next; + relative->next->prev = new_l; + } + else + new_l->next = NULL; + + relative->next = new_l; + new_l->prev = relative; + if (!new_l->next) + list->last = new_l; + + return list; + } + + return eina_inlist_append(list, new_l); +} + +EAPI Eina_Inlist * +eina_inlist_prepend_relative(Eina_Inlist *list, + Eina_Inlist *new_l, + Eina_Inlist *relative) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(new_l, list); + + if (relative) + { + new_l->prev = relative->prev; + new_l->next = relative; + relative->prev = new_l; + if (new_l->prev) + { + new_l->prev->next = new_l; + /* new_l->next could not be NULL, as it was set to 'relative' */ + assert(new_l->next); + return list; + } + else + { + /* new_l->next could not be NULL, as it was set to 'relative' */ + assert(new_l->next); + + new_l->last = list->last; + list->last = NULL; + return new_l; + } + } + + return eina_inlist_prepend(list, new_l); +} + +EAPI Eina_Inlist * +eina_inlist_remove(Eina_Inlist *list, Eina_Inlist *item) +{ + Eina_Inlist *return_l; + + /* checkme */ + EINA_SAFETY_ON_NULL_RETURN_VAL(list, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(item, list); + if (EINA_UNLIKELY((item != list) && (!item->prev) && (!item->next))) + { + eina_error_set(EINA_ERROR_SAFETY_FAILED); + EINA_LOG_ERR("safety check failed: item %p does not appear to be part of an inlist!", item); + return list; + } + + if (item->next) + item->next->prev = item->prev; + + if (item->prev) + { + item->prev->next = item->next; + return_l = list; + } + else + { + return_l = item->next; + if (return_l) + return_l->last = list->last; + } + + if (item == list->last) + list->last = item->prev; + + item->next = NULL; + item->prev = NULL; + return return_l; +} + +EAPI Eina_Inlist * +eina_inlist_promote(Eina_Inlist *list, Eina_Inlist *item) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(list, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(item, list); + + if (item == list) + return list; + + if (item->next) + item->next->prev = item->prev; + + item->prev->next = item->next; + + if (list->last == item) + list->last = item->prev; + + item->next = list; + item->prev = NULL; + item->last = list->last; + + list->prev = item; + list->last = NULL; + + return item; +} + +EAPI Eina_Inlist * +eina_inlist_demote(Eina_Inlist *list, Eina_Inlist *item) +{ + Eina_Inlist *l; + + EINA_SAFETY_ON_NULL_RETURN_VAL(list, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(item, list); + + if (list->last == item) + return list; + + if (!list->last) + { + for (l = list; l->next; l = l->next) + ; + list->last = l; + } + + l = list; + if (item->prev) + item->prev->next = item->next; + else + l = item->next; + + item->next->prev = item->prev; + + list->last->next = item; + item->prev = list->last; + item->next = NULL; + + l->last = item; + return l; +} + +EAPI Eina_Inlist * +eina_inlist_find(Eina_Inlist *list, Eina_Inlist *item) +{ + Eina_Inlist *l; + + for (l = list; l; l = l->next) { + if (l == item) + return item; + } + return NULL; +} + +EAPI unsigned int +eina_inlist_count(const Eina_Inlist *list) +{ + const Eina_Inlist *l; + unsigned int i = 0; + + for (l = list; l; l = l->next) + i++; + + return i; +} + +EAPI int +eina_inlist_sorted_state_init(Eina_Inlist_Sorted_State *state, Eina_Inlist *list) +{ + Eina_Inlist *ct = NULL; + int count = 0; + int jump_count = 1; + + /* + * prepare a jump table to avoid doing unnecessary rewalk + * of the inlist as much as possible. + */ + for (ct = list; ct; ct = ct->next, jump_count++, count++) + { + if (jump_count == state->jump_div) + { + if (state->jump_limit == EINA_INLIST_JUMP_SIZE) + { + _eina_inlist_sorted_state_compact(state); + } + + state->jump_table[state->jump_limit] = ct; + state->jump_limit++; + jump_count = 0; + } + } + + state->inserted = count; + return count; +} + +EAPI Eina_Inlist_Sorted_State * +eina_inlist_sorted_state_new(void) +{ + Eina_Inlist_Sorted_State *r; + + r = calloc(1, sizeof (Eina_Inlist_Sorted_State)); + if (!r) return NULL; + + r->jump_div = 1; + + return r; +} + +EAPI void +eina_inlist_sorted_state_free(Eina_Inlist_Sorted_State *state) +{ + free(state); +} + +static void +_eina_inlist_sorted_state_insert(Eina_Inlist_Sorted_State *state, + unsigned short idx, + int offset) +{ + Eina_Inlist *last; + int jump_count; + int start; + + state->inserted++; + + if (offset != 0) idx++; + for (; idx < state->jump_limit; idx++) + { + state->jump_table[idx] = state->jump_table[idx]->prev; + } + + start = state->jump_limit - 3; + if (start < 0) + start = 0; + + last = state->jump_table[start]; + start++; + + /* Correctly rebuild end of list */ + for (jump_count = 0; last->next != NULL; last = last->next, jump_count++) + { + if (jump_count == state->jump_div) + { + if (state->jump_limit == start) + { + if (state->jump_limit == EINA_INLIST_JUMP_SIZE) + { + _eina_inlist_sorted_state_compact(state); + start = state->jump_limit - 1; + continue ; + } + else + { + state->jump_limit++; + } + } + + state->jump_table[start++] = last; + jump_count = 0; + } + } +} + +EAPI Eina_Inlist * +eina_inlist_sorted_insert(Eina_Inlist *list, + Eina_Inlist *item, + Eina_Compare_Cb func) +{ + Eina_Inlist *ct = NULL; + Eina_Inlist_Sorted_State state; + int cmp = 0; + int inf, sup; + int cur = 0; + int count; + + if (!list) return eina_inlist_append(NULL, item); + + if (!list->next) + { + cmp = func(list, item); + + if (cmp < 0) + return eina_inlist_append(list, item); + return eina_inlist_prepend(list, item); + } + + state.jump_div = 1; + state.jump_limit = 0; + count = eina_inlist_sorted_state_init(&state, list); + + /* + * now do a dychotomic search directly inside the jump_table. + */ + inf = 0; + sup = state.jump_limit - 1; + cur = 0; + ct = state.jump_table[cur]; + cmp = func(ct, item); + + while (inf <= sup) + { + cur = inf + ((sup - inf) >> 1); + ct = state.jump_table[cur]; + + cmp = func(ct, item); + if (cmp == 0) + break ; + else if (cmp < 0) + inf = cur + 1; + else if (cmp > 0) + { + if (cur > 0) + sup = cur - 1; + else + break; + } + else + break; + } + + /* If at the beginning of the table and cmp < 0, + * insert just after the head */ + if (cur == 0 && cmp > 0) + return eina_inlist_prepend_relative(list, item, ct); + + /* If at the end of the table and cmp >= 0, + * just append the item to the list */ + if (cmp < 0 && ct == list->last) + return eina_inlist_append(list, item); + + /* + * Now do a dychotomic search between two entries inside the jump_table + */ + cur *= state.jump_div; + inf = cur - state.jump_div - 1; + sup = cur + state.jump_div + 1; + + if (sup > count - 1) sup = count - 1; + if (inf < 0) inf = 0; + + while (inf <= sup) + { + int tmp = cur; + + cur = inf + ((sup - inf) >> 1); + if (tmp < cur) + for (; tmp != cur; tmp++, ct = ct->next); + else if (tmp > cur) + for (; tmp != cur; tmp--, ct = ct->prev); + + cmp = func(ct, item); + if (cmp == 0) + break ; + else if (cmp < 0) + inf = cur + 1; + else if (cmp > 0) + { + if (cur > 0) + sup = cur - 1; + else + break; + } + else + break; + } + + if (cmp <= 0) + return eina_inlist_append_relative(list, item, ct); + return eina_inlist_prepend_relative(list, item, ct); +} + +EAPI Eina_Inlist * +eina_inlist_sorted_state_insert(Eina_Inlist *list, + Eina_Inlist *item, + Eina_Compare_Cb func, + Eina_Inlist_Sorted_State *state) +{ + Eina_Inlist *ct = NULL; + int cmp = 0; + int inf, sup; + int cur = 0; + int count; + unsigned short head; + unsigned int offset; + + if (!list) + { + state->inserted = 1; + state->jump_limit = 1; + state->jump_table[0] = item; + return eina_inlist_append(NULL, item); + } + + if (!list->next) + { + cmp = func(list, item); + + state->jump_limit = 2; + state->inserted = 2; + + if (cmp < 0) + { + state->jump_table[1] = item; + return eina_inlist_append(list, item); + } + state->jump_table[1] = state->jump_table[0]; + state->jump_table[0] = item; + return eina_inlist_prepend(list, item); + } + + count = state->inserted; + + /* + * now do a dychotomic search directly inside the jump_table. + */ + inf = 0; + sup = state->jump_limit - 1; + cur = 0; + ct = state->jump_table[cur]; + cmp = func(ct, item); + + while (inf <= sup) + { + cur = inf + ((sup - inf) >> 1); + ct = state->jump_table[cur]; + + cmp = func(ct, item); + if (cmp == 0) + break ; + else if (cmp < 0) + inf = cur + 1; + else if (cmp > 0) + { + if (cur > 0) + sup = cur - 1; + else + break; + } + else + break; + } + + /* If at the beginning of the table and cmp < 0, + * insert just after the head */ + if (cur == 0 && cmp > 0) + { + ct = eina_inlist_prepend_relative(list, item, ct); + _eina_inlist_sorted_state_insert(state, 0, 0); + return ct; + } + + /* If at the end of the table and cmp >= 0, + * just append the item to the list */ + if (cmp < 0 && ct == list->last) + { + ct = eina_inlist_append(list, item); + _eina_inlist_sorted_state_insert(state, state->jump_limit - 1, 1); + return ct; + } + + /* + * Now do a dychotomic search between two entries inside the jump_table + */ + cur *= state->jump_div; + inf = cur - state->jump_div - 1; + sup = cur + state->jump_div + 1; + + if (sup > count - 1) sup = count - 1; + if (inf < 0) inf = 0; + + while (inf <= sup) + { + int tmp = cur; + + cur = inf + ((sup - inf) >> 1); + if (tmp < cur) + for (; tmp != cur; tmp++, ct = ct->next); + else if (tmp > cur) + for (; tmp != cur; tmp--, ct = ct->prev); + + cmp = func(ct, item); + if (cmp == 0) + break ; + else if (cmp < 0) + inf = cur + 1; + else if (cmp > 0) + { + if (cur > 0) + sup = cur - 1; + else + break; + } + else + break; + } + + if (cmp <= 0) + { + cur++; + + ct = eina_inlist_append_relative(list, item, ct); + } + else + { + ct = eina_inlist_prepend_relative(list, item, ct); + } + + head = cur / state->jump_div; + offset = cur % state->jump_div; + + _eina_inlist_sorted_state_insert(state, head, offset); + return ct; +} + +EAPI Eina_Inlist * +eina_inlist_sort(Eina_Inlist *head, Eina_Compare_Cb func) +{ + unsigned int i = 0; + unsigned int n = 0; + Eina_Inlist *tail = head; + Eina_Inlist *unsort = NULL; + Eina_Inlist *stack[EINA_INLIST_SORT_STACK_SIZE]; + + EINA_SAFETY_ON_NULL_RETURN_VAL(head, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(func, head); + + while (tail) + { + unsigned int idx, tmp; + + Eina_Inlist *a = tail; + Eina_Inlist *b = tail->next; + + if (!b) + { + stack[i++] = a; + break; + } + + tail = b->next; + + if (func(a, b) < 0) + ((stack[i++] = a)->next = b)->next = 0; + else + ((stack[i++] = b)->next = a)->next = 0; + + tmp = n++; + for (idx = n ^ tmp; idx &= idx - 1; i--) + stack[i - 2] = eina_inlist_sort_merge(stack[i - 2], stack[i - 1], func); + } + + while (i-- > 1) + stack[i - 1] = eina_inlist_sort_merge(stack[i - 1], stack[i], func); + + head = stack[0]; + tail = eina_inlist_sort_rebuild_prev(head); + + if (unsort) + { + tail->next = unsort; + unsort->prev = tail; + } + + head->last = tail; + + return head; + +} + +EAPI Eina_Iterator * +eina_inlist_iterator_new(const Eina_Inlist *list) +{ + Eina_Iterator_Inlist *it; + + eina_error_set(0); + it = calloc(1, sizeof (Eina_Iterator_Inlist)); + if (!it) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + it->head = list; + it->current = list; + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(eina_inlist_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER( + eina_inlist_iterator_get_container); + it->iterator.free = FUNC_ITERATOR_FREE(eina_inlist_iterator_free); + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + return &it->iterator; +} + +EAPI Eina_Accessor * +eina_inlist_accessor_new(const Eina_Inlist *list) +{ + Eina_Accessor_Inlist *ac; + + eina_error_set(0); + ac = calloc(1, sizeof (Eina_Accessor_Inlist)); + if (!ac) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + ac->head = list; + ac->current = list; + ac->index = 0; + + ac->accessor.version = EINA_ACCESSOR_VERSION; + ac->accessor.get_at = FUNC_ACCESSOR_GET_AT(eina_inlist_accessor_get_at); + ac->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER( + eina_inlist_accessor_get_container); + ac->accessor.free = FUNC_ACCESSOR_FREE(eina_inlist_accessor_free); + + EINA_MAGIC_SET(&ac->accessor, EINA_MAGIC_ACCESSOR); + + return &ac->accessor; +} diff --git a/libraries/eina/src/lib/eina_iterator.c b/libraries/eina/src/lib/eina_iterator.c new file mode 100644 index 0000000..0721066 --- /dev/null +++ b/libraries/eina/src/lib/eina_iterator.c @@ -0,0 +1,172 @@ +/* EINA - EFL data type library + * Copyright (C) 2002-2008 Cedric Bail + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "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_iterator.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +static const char EINA_MAGIC_ITERATOR_STR[] = "Eina Iterator"; + +#define EINA_MAGIC_CHECK_ITERATOR(d) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_ITERATOR)) { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_ITERATOR); } \ + } while(0) + +/** + * @endcond + */ + + +/*============================================================================* +* Global * +*============================================================================*/ + +/** + * @internal + * @brief Initialize the iterator module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the iterator module of Eina. It is called by + * eina_init(). + * + * @see eina_init() + */ +Eina_Bool +eina_iterator_init(void) +{ + return eina_magic_string_set(EINA_MAGIC_ITERATOR, EINA_MAGIC_ITERATOR_STR); +} + +/** + * @internal + * @brief Shut down the iterator module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the iterator module set up by + * eina_iterator_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_iterator_shutdown(void) +{ + return EINA_TRUE; +} + +/*============================================================================* +* API * +*============================================================================*/ + +EAPI void +eina_iterator_free(Eina_Iterator *iterator) +{ + EINA_MAGIC_CHECK_ITERATOR(iterator); + EINA_SAFETY_ON_NULL_RETURN(iterator); + EINA_SAFETY_ON_NULL_RETURN(iterator->free); + iterator->free(iterator); +} + +EAPI void * +eina_iterator_container_get(Eina_Iterator *iterator) +{ + EINA_MAGIC_CHECK_ITERATOR(iterator); + EINA_SAFETY_ON_NULL_RETURN_VAL(iterator, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(iterator->get_container, NULL); + return iterator->get_container(iterator); +} + +EAPI Eina_Bool +eina_iterator_next(Eina_Iterator *iterator, void **data) +{ + if (!iterator) + return EINA_FALSE; + + EINA_MAGIC_CHECK_ITERATOR(iterator); + EINA_SAFETY_ON_NULL_RETURN_VAL(iterator, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(iterator->next, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE); + return iterator->next(iterator, data); +} + +EAPI void +eina_iterator_foreach(Eina_Iterator *iterator, + Eina_Each_Cb cb, + const void *fdata) +{ + const void *container; + void *data; + + EINA_MAGIC_CHECK_ITERATOR(iterator); + EINA_SAFETY_ON_NULL_RETURN(iterator); + EINA_SAFETY_ON_NULL_RETURN(iterator->get_container); + EINA_SAFETY_ON_NULL_RETURN(iterator->next); + EINA_SAFETY_ON_NULL_RETURN(cb); + + if (!eina_iterator_lock(iterator)) return ; + + container = iterator->get_container(iterator); + while (iterator->next(iterator, &data) == EINA_TRUE) { + if (cb(container, data, (void *)fdata) != EINA_TRUE) + goto on_exit; + } + + on_exit: + (void) eina_iterator_unlock(iterator); +} + +EAPI Eina_Bool +eina_iterator_lock(Eina_Iterator *iterator) +{ + EINA_MAGIC_CHECK_ITERATOR(iterator); + EINA_SAFETY_ON_NULL_RETURN_VAL(iterator, EINA_FALSE); + + if (iterator->lock) + return iterator->lock(iterator); + return EINA_TRUE; +} + +EAPI Eina_Bool +eina_iterator_unlock(Eina_Iterator *iterator) +{ + EINA_MAGIC_CHECK_ITERATOR(iterator); + EINA_SAFETY_ON_NULL_RETURN_VAL(iterator, EINA_FALSE); + + if (iterator->unlock) + return iterator->unlock(iterator); + return EINA_TRUE; +} diff --git a/libraries/eina/src/lib/eina_lalloc.c b/libraries/eina/src/lib/eina_lalloc.c new file mode 100644 index 0000000..b1e62b7 --- /dev/null +++ b/libraries/eina/src/lib/eina_lalloc.c @@ -0,0 +1,158 @@ +/* EINA - EFL data type library + * Copyright (C) 2007-2008 Jorge Luis Zapata Muga + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "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_lalloc.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +struct _Eina_Lalloc +{ + void *data; + int num_allocated; + int num_elements; + int acc; + Eina_Lalloc_Alloc alloc_cb; + Eina_Lalloc_Free free_cb; +}; + +/** + * @endcond + */ + +/*============================================================================* +* Global * +*============================================================================*/ + +/*============================================================================* +* API * +*============================================================================*/ + +/** + * @addtogroup Eina_Lalloc_Group Lazy allocator + * + * @{ + */ + +EAPI Eina_Lalloc *eina_lalloc_new(void *data, + Eina_Lalloc_Alloc alloc_cb, + Eina_Lalloc_Free free_cb, + int num_init) +{ + Eina_Lalloc *a; + + EINA_SAFETY_ON_NULL_RETURN_VAL(alloc_cb, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(free_cb, NULL); + + a = calloc(1, sizeof(Eina_Lalloc)); + a->data = data; + a->alloc_cb = alloc_cb; + a->free_cb = free_cb; + if (num_init > 0) + { + a->num_allocated = num_init; + a->alloc_cb(a->data, a->num_allocated); + } + + return a; +} + +EAPI void eina_lalloc_free(Eina_Lalloc *a) +{ + EINA_SAFETY_ON_NULL_RETURN(a); + EINA_SAFETY_ON_NULL_RETURN(a->free_cb); + a->free_cb(a->data); + free(a); +} + +EAPI Eina_Bool eina_lalloc_element_add(Eina_Lalloc *a) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(a, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(a->alloc_cb, EINA_FALSE); + + if (a->num_elements == a->num_allocated) + { + if (a->alloc_cb(a->data, (1 << a->acc)) == EINA_TRUE) + { + a->num_allocated = (1 << a->acc); + a->acc++; + } + else + return EINA_FALSE; + } + + a->num_elements++; + + return EINA_TRUE; +} + +EAPI Eina_Bool eina_lalloc_elements_add(Eina_Lalloc *a, int num) +{ + int tmp; + + EINA_SAFETY_ON_NULL_RETURN_VAL(a, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(a->alloc_cb, EINA_FALSE); + + tmp = a->num_elements + num; + if (tmp > a->num_allocated) + { + int allocated; + int acc; + + allocated = a->num_allocated; + acc = a->acc; + + while (tmp > allocated) + { + allocated = (1 << acc); + acc++; + } + + if (a->alloc_cb(a->data, allocated) == EINA_TRUE) + { + a->num_allocated = allocated; + a->acc = acc; + } + else + return EINA_FALSE; + } + + a->num_elements += num; + + return EINA_TRUE; +} + +/** + * @} + */ diff --git a/libraries/eina/src/lib/eina_list.c b/libraries/eina/src/lib/eina_list.c new file mode 100644 index 0000000..d45cffd --- /dev/null +++ b/libraries/eina/src/lib/eina_list.c @@ -0,0 +1,1490 @@ +/* EINA - EFL data type library + * Copyright (C) 2002-2008 Carsten Haitzler, Gustavo Sverzut Barbieri, Tilman Sauerbeck, + * Vincent Torri, Cedric Bail, Jorge Luis Zapata Muga, + * Corey Donohoe, Arnaud de Turckheim, Alexandre Becoulet + * + * 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 . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright (C) 2004 ncn + * Copyright (C) 2006 Sebastian Dransfeld + * Copyright (C) 2007 Christopher Michael + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies of the Software and its Copyright notices. In addition publicly + * documented acknowledgment must be given that this software has been used if no + * source code of this software is made available publicly. This includes + * acknowledgments in either Copyright notices, Manuals, Publicity and Marketing + * documents or any documentation provided with any product containing this + * software. This License does not apply to any software that links to the + * libraries provided by this software (statically or dynamically), but only to + * the software provided. + + * Please see the OLD-COPYING.PLAIN for a plain-english explanation of this notice + * and it's intent. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_EVIL +# include +#endif + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_error.h" +#include "eina_log.h" +#include "eina_mempool.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_list.h" + + +/*============================================================================* + * Local * + *============================================================================*/ + +/** + * @cond LOCAL + */ + +static const char EINA_MAGIC_LIST_STR[] = "Eina List"; +static const char EINA_MAGIC_LIST_ITERATOR_STR[] = "Eina List Iterator"; +static const char EINA_MAGIC_LIST_ACCESSOR_STR[] = "Eina List Accessor"; +static const char EINA_MAGIC_LIST_ACCOUNTING_STR[] = "Eina List Accounting"; + + +#define EINA_MAGIC_CHECK_LIST(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST); \ + return __VA_ARGS__; \ + } \ + } while(0) + +#define EINA_MAGIC_CHECK_LIST_ITERATOR(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST_ITERATOR)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST_ITERATOR); \ + return __VA_ARGS__; \ + } \ + } while(0) + +#define EINA_MAGIC_CHECK_LIST_ACCESSOR(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST_ACCESSOR)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST_ACCESSOR); \ + return __VA_ARGS__; \ + } \ + } while(0) + +#define EINA_MAGIC_CHECK_LIST_ACCOUNTING(d) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST_ACCOUNTING)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST_ACCOUNTING); \ + return; \ + } \ + } while(0) + +#define EINA_LIST_SORT_STACK_SIZE 32 + +typedef struct _Eina_Iterator_List Eina_Iterator_List; +typedef struct _Eina_Accessor_List Eina_Accessor_List; + +struct _Eina_Iterator_List +{ + Eina_Iterator iterator; + + const Eina_List *head; + const Eina_List *current; + + EINA_MAGIC +}; + +struct _Eina_Accessor_List +{ + Eina_Accessor accessor; + + const Eina_List *head; + const Eina_List *current; + + unsigned int index; + + EINA_MAGIC +}; + +static Eina_Mempool *_eina_list_mp = NULL; +static Eina_Mempool *_eina_list_accounting_mp = NULL; +static int _eina_list_log_dom = -1; + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_eina_list_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_list_log_dom, __VA_ARGS__) + +static inline Eina_List_Accounting * +_eina_list_mempool_accounting_new(__UNUSED__ Eina_List *list) +{ + Eina_List_Accounting *tmp; + + tmp = + eina_mempool_malloc(_eina_list_accounting_mp, + sizeof (Eina_List_Accounting)); + if (!tmp) + return NULL; + + EINA_MAGIC_SET(tmp, EINA_MAGIC_LIST_ACCOUNTING); + + return tmp; +} +static inline void +_eina_list_mempool_accounting_free(Eina_List_Accounting *accounting) +{ + EINA_MAGIC_CHECK_LIST_ACCOUNTING(accounting); + + EINA_MAGIC_SET(accounting, EINA_MAGIC_NONE); + eina_mempool_free(_eina_list_accounting_mp, accounting); +} + +static inline Eina_List * +_eina_list_mempool_list_new(__UNUSED__ Eina_List *list) +{ + Eina_List *tmp; + + tmp = eina_mempool_malloc(_eina_list_mp, sizeof (Eina_List)); + if (!tmp) + return NULL; + + EINA_MAGIC_SET(tmp, EINA_MAGIC_LIST); + + return tmp; +} +static inline void +_eina_list_mempool_list_free(Eina_List *list) +{ + EINA_MAGIC_CHECK_LIST(list); + + list->accounting->count--; + if (list->accounting->count == 0) + _eina_list_mempool_accounting_free(list->accounting); + + EINA_MAGIC_SET(list, EINA_MAGIC_NONE); + eina_mempool_free(_eina_list_mp, list); +} + +static Eina_List * +_eina_list_setup_accounting(Eina_List *list) +{ + EINA_MAGIC_CHECK_LIST(list, NULL); + + list->accounting = _eina_list_mempool_accounting_new(list); + if (!list->accounting) + goto on_error; + + list->accounting->last = list; + list->accounting->count = 1; + + return list; + +on_error: + _eina_list_mempool_list_free(list); + return NULL; +} + +static inline void +_eina_list_update_accounting(Eina_List *list, Eina_List *new_list) +{ + EINA_MAGIC_CHECK_LIST(list); + EINA_MAGIC_CHECK_LIST(new_list); + + list->accounting->count++; + new_list->accounting = list->accounting; +} + +#if 0 +static Eina_Mempool2 _eina_list_mempool = +{ + sizeof(Eina_List), + 320, + 0, NULL, NULL +}; +static Eina_Mempool2 _eina_list_accounting_mempool = +{ + sizeof(Eina_List_Accounting), + 80, + 0, NULL, NULL +}; +#endif + +static Eina_Bool +eina_list_iterator_next(Eina_Iterator_List *it, void **data) +{ + EINA_MAGIC_CHECK_LIST_ITERATOR(it, EINA_FALSE); + + if (!it->current) + return EINA_FALSE; + + *data = eina_list_data_get(it->current); + + it->current = eina_list_next(it->current); + + return EINA_TRUE; +} + +static Eina_Bool +eina_list_iterator_prev(Eina_Iterator_List *it, void **data) +{ + EINA_MAGIC_CHECK_LIST_ITERATOR(it, EINA_FALSE); + + if (!it->current) + return EINA_FALSE; + + *data = eina_list_data_get(it->current); + + it->current = eina_list_prev(it->current); + + return EINA_TRUE; +} + +static Eina_List * +eina_list_iterator_get_container(Eina_Iterator_List *it) +{ + EINA_MAGIC_CHECK_LIST_ITERATOR(it, NULL); + + return (Eina_List *)it->head; +} + +static void +eina_list_iterator_free(Eina_Iterator_List *it) +{ + EINA_MAGIC_CHECK_LIST_ITERATOR(it); + + MAGIC_FREE(it); +} + +static Eina_Bool +eina_list_accessor_get_at(Eina_Accessor_List *it, unsigned int idx, void **data) +{ + const Eina_List *over; + unsigned int middle; + unsigned int i; + + EINA_MAGIC_CHECK_LIST_ACCESSOR(it, EINA_FALSE); + + if (idx >= eina_list_count(it->head)) + return EINA_FALSE; + + if (it->index == idx) + over = it->current; + else if (idx > it->index) + { + /* After current position. */ + middle = ((eina_list_count(it->head) - it->index) >> 1) + it->index; + + if (idx > middle) + /* Go backward from the end. */ + for (i = eina_list_count(it->head) - 1, + over = eina_list_last(it->head); + i > idx && over; + --i, over = eina_list_prev(over)) + ; + else + /* Go forward from current. */ + for (i = it->index, over = it->current; + i < idx && over; + ++i, over = eina_list_next(over)) + ; + } + else + { + /* Before current position. */ + middle = it->index >> 1; + + if (idx > middle) + /* Go backward from current. */ + for (i = it->index, over = it->current; + i > idx && over; + --i, over = eina_list_prev(over)) + ; + else + /* Go forward from start. */ + for (i = 0, over = it->head; + i < idx && over; + ++i, over = eina_list_next(over)) + ; + } + + if (!over) + return EINA_FALSE; + + it->current = over; + it->index = idx; + + *data = eina_list_data_get(it->current); + return EINA_TRUE; +} + +static Eina_List * +eina_list_accessor_get_container(Eina_Accessor_List *it) +{ + EINA_MAGIC_CHECK_LIST_ACCESSOR(it, NULL); + + return (Eina_List *)it->head; +} + +static void +eina_list_accessor_free(Eina_Accessor_List *it) +{ + EINA_MAGIC_CHECK_LIST_ACCESSOR(it); + + MAGIC_FREE(it); +} + +static Eina_List * +eina_list_sort_rebuild_prev(Eina_List *list) +{ + Eina_List *prev = NULL; + + EINA_MAGIC_CHECK_LIST(list, NULL); + + for (; list; list = list->next) + { + list->prev = prev; + prev = list; + } + + return prev; +} + +static Eina_List * +eina_list_sort_merge(Eina_List *a, Eina_List *b, Eina_Compare_Cb func) +{ + Eina_List *first, *last; + + if (func(a->data, b->data) < 0) + a = (last = first = a)->next; + else + b = (last = first = b)->next; + + while (a && b) + if (func(a->data, b->data) < 0) + a = (last = last->next = a)->next; + else + b = (last = last->next = b)->next; + + last->next = a ? a : b; + + return first; +} + +/** + * @endcond + */ + +/*============================================================================* + * Global * + *============================================================================*/ + +/** + * @internal + * @brief Initialize the list module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the list module of Eina. It is called by + * eina_init(). + * + * This function creates mempool to speed up list node and accounting + * management, using EINA_MEMPOOL environment variable if it is set to + * choose the memory pool type to use. + * + * @see eina_init() + */ +Eina_Bool +eina_list_init(void) +{ + const char *choice, *tmp; + + _eina_list_log_dom = eina_log_domain_register("eina_list", + EINA_LOG_COLOR_DEFAULT); + if (_eina_list_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_list"); + return EINA_FALSE; + } + +#ifdef EINA_DEFAULT_MEMPOOL + choice = "pass_through"; +#else + choice = "chained_mempool"; +#endif + tmp = getenv("EINA_MEMPOOL"); + if (tmp && tmp[0]) + choice = tmp; + + _eina_list_mp = eina_mempool_add + (choice, "list", NULL, sizeof(Eina_List), 320); + if (!_eina_list_mp) + { + ERR("ERROR: Mempool for list cannot be allocated in list init."); + goto on_init_fail; + } + + _eina_list_accounting_mp = eina_mempool_add + (choice, "list_accounting", NULL, sizeof(Eina_List_Accounting), 80); + if (!_eina_list_accounting_mp) + { + ERR( + "ERROR: Mempool for list accounting cannot be allocated in list init."); + eina_mempool_del(_eina_list_mp); + goto on_init_fail; + } + +#define EMS(n) eina_magic_string_static_set(n, n ## _STR) + EMS(EINA_MAGIC_LIST); + EMS(EINA_MAGIC_LIST_ITERATOR); + EMS(EINA_MAGIC_LIST_ACCESSOR); + EMS(EINA_MAGIC_LIST_ACCOUNTING); +#undef EMS + + return EINA_TRUE; + +on_init_fail: + eina_log_domain_unregister(_eina_list_log_dom); + _eina_list_log_dom = -1; + return EINA_FALSE; +} + +/** + * @internal + * @brief Shut down the list module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the list module set up by + * eina_list_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_list_shutdown(void) +{ + eina_mempool_del(_eina_list_accounting_mp); + eina_mempool_del(_eina_list_mp); + + eina_log_domain_unregister(_eina_list_log_dom); + _eina_list_log_dom = -1; + return EINA_TRUE; +} + +/*============================================================================* + * API * + *============================================================================*/ + +EAPI Eina_List * +eina_list_append(Eina_List *list, const void *data) +{ + Eina_List *l, *new_l; + + eina_error_set(0); + new_l = _eina_list_mempool_list_new(list); + if (!new_l) + return list; + + new_l->next = NULL; + new_l->data = (void *)data; + if (!list) + { + new_l->prev = NULL; + return _eina_list_setup_accounting(new_l); + } + + EINA_MAGIC_CHECK_LIST(list, NULL); + + l = list->accounting->last; + list->accounting->last = new_l; + + l->next = new_l; + new_l->prev = l; + + _eina_list_update_accounting(list, new_l); + return list; +} + +EAPI Eina_List * +eina_list_prepend(Eina_List *list, const void *data) +{ + Eina_List *new_l; + + eina_error_set(0); + new_l = _eina_list_mempool_list_new(list); + if (!new_l) + return list; + + new_l->prev = NULL; + new_l->next = list; + new_l->data = (void *)data; + + if (!list) + return _eina_list_setup_accounting(new_l); + + EINA_MAGIC_CHECK_LIST(list, NULL); + + list->prev = new_l; + + _eina_list_update_accounting(list, new_l); + + return new_l; +} + +EAPI Eina_List * +eina_list_append_relative(Eina_List *list, + const void *data, + const void *relative) +{ + Eina_List *l; + void *list_data; + + if (list) + EINA_MAGIC_CHECK_LIST(list, NULL); + + EINA_LIST_FOREACH(list, l, list_data) + { + if (list_data == relative) + return eina_list_append_relative_list(list, data, l); + } + + return eina_list_append(list, data); +} + +EAPI Eina_List * +eina_list_append_relative_list(Eina_List *list, + const void *data, + Eina_List *relative) +{ + Eina_List *new_l; + + if ((!list) || (!relative)) + return eina_list_append(list, data); + + eina_error_set(0); + new_l = _eina_list_mempool_list_new(list); + if (!new_l) + return list; + + EINA_MAGIC_CHECK_LIST(relative, NULL); + new_l->next = relative->next; + new_l->data = (void *)data; + + if (relative->next) + relative->next->prev = new_l; + + relative->next = new_l; + new_l->prev = relative; + + _eina_list_update_accounting(list, new_l); + + if (!new_l->next) + new_l->accounting->last = new_l; + + return list; +} + +EAPI Eina_List * +eina_list_prepend_relative(Eina_List *list, + const void *data, + const void *relative) +{ + Eina_List *l; + void *list_data; + + if (list) + EINA_MAGIC_CHECK_LIST(list, NULL); + + EINA_LIST_FOREACH(list, l, list_data) + { + if (list_data == relative) + return eina_list_prepend_relative_list(list, data, l); + } + return eina_list_prepend(list, data); +} + +EAPI Eina_List * +eina_list_prepend_relative_list(Eina_List *list, + const void *data, + Eina_List *relative) +{ + Eina_List *new_l; + + if ((!list) || (!relative)) + return eina_list_prepend(list, data); + + eina_error_set(0); + new_l = _eina_list_mempool_list_new(list); + if (!new_l) + return list; + + EINA_MAGIC_CHECK_LIST(relative, NULL); + + new_l->prev = relative->prev; + new_l->next = relative; + new_l->data = (void *)data; + + if (relative->prev) + relative->prev->next = new_l; + + relative->prev = new_l; + + _eina_list_update_accounting(list, new_l); + + if (new_l->prev) + return list; + + return new_l; +} + +EAPI Eina_List * +eina_list_sorted_insert(Eina_List *list, Eina_Compare_Cb func, const void *data) +{ + Eina_List *lnear; + int cmp; + + if (!list) + return eina_list_append(NULL, data); + + lnear = eina_list_search_sorted_near_list(list, func, data, &cmp); + if (cmp < 0) + return eina_list_append_relative_list(list, data, lnear); + else + return eina_list_prepend_relative_list(list, data, lnear); +} + +EAPI Eina_List * +eina_list_remove(Eina_List *list, const void *data) +{ + Eina_List *l; + + if (list) + EINA_MAGIC_CHECK_LIST(list, NULL); + + l = eina_list_data_find_list(list, data); + return eina_list_remove_list(list, l); +} + +EAPI Eina_List * +eina_list_remove_list(Eina_List *list, Eina_List *remove_list) +{ + Eina_List *return_l; + + if (!list) + return NULL; + + if (!remove_list) + return list; + + EINA_MAGIC_CHECK_LIST(remove_list, NULL); + + if (remove_list->next) + remove_list->next->prev = remove_list->prev; + + if (remove_list->prev) + { + remove_list->prev->next = remove_list->next; + return_l = list; + } + else + return_l = remove_list->next; + + if (remove_list == remove_list->accounting->last) + { + EINA_MAGIC_CHECK_LIST(list, NULL); + list->accounting->last = remove_list->prev; + } + + _eina_list_mempool_list_free(remove_list); + return return_l; +} + +EAPI Eina_List * +eina_list_free(Eina_List *list) +{ + Eina_List *l, *free_l; + + if (!list) + return NULL; + + EINA_MAGIC_CHECK_LIST(list, NULL); + + for (l = list; l; ) + { + free_l = l; + l = l->next; + + _eina_list_mempool_list_free(free_l); + } + + return NULL; +} + +EAPI Eina_List * +eina_list_promote_list(Eina_List *list, Eina_List *move_list) +{ + if (!list) + return NULL; + + if (!move_list) + { + return list; /* Promoting head to be head. */ + + } + + if (move_list == list) + return list; + + if (move_list->next == list) + return move_list; + + EINA_MAGIC_CHECK_LIST(list, NULL); + EINA_MAGIC_CHECK_LIST(move_list, NULL); + + /* Remove the promoted item from the list. */ + if (!move_list->prev) + move_list->next->prev = NULL; + else + { + move_list->prev->next = move_list->next; + if (move_list == list->accounting->last) + list->accounting->last = move_list->prev; + else + move_list->next->prev = move_list->prev; + } + + /* Add the promoted item in the list. */ + move_list->next = list; + move_list->prev = list->prev; + list->prev = move_list; + if (move_list->prev) + move_list->prev->next = move_list; + + return move_list; +} + +EAPI Eina_List * +eina_list_demote_list(Eina_List *list, Eina_List *move_list) +{ + if (!list) + return NULL; + + if (!move_list) + { + return list; /* Demoting tail to be tail. */ + + } + + if (move_list == list->accounting->last) + return list; + + EINA_MAGIC_CHECK_LIST(list, NULL); + EINA_MAGIC_CHECK_LIST(move_list, NULL); + + /* Update pointer list if necessary. */ + if (list == move_list) + { + list = move_list->next; /* Remove the demoted item from the list. */ + + } + + if (move_list->prev) + move_list->prev->next = move_list->next; + + move_list->next->prev = move_list->prev; + /* Add the demoted item in the list. */ + move_list->prev = list->accounting->last; + move_list->prev->next = move_list; + move_list->next = NULL; + list->accounting->last = move_list; + + return list; +} + +EAPI void * +eina_list_data_find(const Eina_List *list, const void *data) +{ + if (eina_list_data_find_list(list, data)) + return (void *)data; + + return NULL; +} + +EAPI Eina_Bool +eina_list_move(Eina_List **to, Eina_List **from, void *data) +{ + Eina_List *l; + + EINA_SAFETY_ON_NULL_RETURN_VAL(to, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(from, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE); + + if (*to) EINA_MAGIC_CHECK_LIST(*to, EINA_FALSE); + EINA_MAGIC_CHECK_LIST(*from, EINA_FALSE); + + l = eina_list_data_find_list(*from, data); + EINA_SAFETY_ON_NULL_RETURN_VAL(l, EINA_FALSE); + + *to = eina_list_append(*to, data); + *from = eina_list_remove_list(*from, l); + return EINA_TRUE; +} + +EAPI Eina_Bool +eina_list_move_list(Eina_List **to, Eina_List **from, Eina_List *data) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(to, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(from, EINA_FALSE); + + if (*to) EINA_MAGIC_CHECK_LIST(*to, EINA_FALSE); + EINA_MAGIC_CHECK_LIST(*from, EINA_FALSE); + EINA_MAGIC_CHECK_LIST(data, EINA_FALSE); + + *to = eina_list_append(*to, data->data); + *from = eina_list_remove_list(*from, data); + return EINA_TRUE; +} + +EAPI Eina_List * +eina_list_data_find_list(const Eina_List *list, const void *data) +{ + const Eina_List *l; + void *list_data; + + if (list) + EINA_MAGIC_CHECK_LIST(list, NULL); + + EINA_LIST_FOREACH(list, l, list_data) + { + if (list_data == data) + return (Eina_List *)l; + } + + return NULL; +} + +EAPI void * +eina_list_nth(const Eina_List *list, unsigned int n) +{ + Eina_List *l; + + l = eina_list_nth_list(list, n); + return l ? l->data : NULL; +} + +EAPI Eina_List * +eina_list_nth_list(const Eina_List *list, unsigned int n) +{ + const Eina_List *l; + unsigned int i; + + if (list) + EINA_MAGIC_CHECK_LIST(list, NULL); + + /* check for non-existing nodes */ + if ((!list) || (n > (list->accounting->count - 1))) + return NULL; + + /* if the node is in the 2nd half of the list, search from the end + * else, search from the beginning. + */ + if (n > (list->accounting->count / 2)) + for (i = list->accounting->count - 1, + l = list->accounting->last; + l; + l = l->prev, i--) + { + if (i == n) + return (Eina_List *)l; + } + else + for (i = 0, l = list; l; l = l->next, i++) + { + if (i == n) + return (Eina_List *)l; + } + + abort(); +} + +EAPI Eina_List * +eina_list_reverse(Eina_List *list) +{ + Eina_List *l1, *l2; + + if (!list) + return NULL; + + EINA_MAGIC_CHECK_LIST(list, NULL); + + l1 = list; + l2 = list->accounting->last; + while (l1 != l2) + { + void *data; + + data = l1->data; + l1->data = l2->data; + l2->data = data; + l1 = l1->next; + if (l1 == l2) + break; + + l2 = l2->prev; + } + + return list; +} + +EAPI Eina_List * +eina_list_reverse_clone(const Eina_List *list) +{ + const Eina_List *l; + Eina_List *lclone; + void *data; + + if (!list) + return NULL; + + EINA_MAGIC_CHECK_LIST(list, NULL); + + lclone = NULL; + EINA_LIST_FOREACH(list, l, data) + lclone = eina_list_prepend(lclone, data); + + return lclone; +} + +EAPI Eina_List * +eina_list_clone(const Eina_List *list) +{ + const Eina_List *l; + Eina_List *lclone; + void *data; + + if (!list) + return NULL; + + EINA_MAGIC_CHECK_LIST(list, NULL); + + lclone = NULL; + EINA_LIST_FOREACH(list, l, data) + lclone = eina_list_append(lclone, data); + + return lclone; +} + +EAPI Eina_List * +eina_list_sort(Eina_List *list, unsigned int size, Eina_Compare_Cb func) +{ + unsigned int i = 0; + unsigned int n = 0; + Eina_List *tail = list; + Eina_List *unsort = NULL; + Eina_List *stack[EINA_LIST_SORT_STACK_SIZE]; + + EINA_SAFETY_ON_NULL_RETURN_VAL(func, list); + if (!list) + return NULL; + + 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 (size != list->accounting->count) + { + unsort = eina_list_nth_list(list, size); + if (unsort) + unsort->prev->next = NULL; + } + + while (tail) + { + unsigned int idx, tmp; + + Eina_List *a = tail; + Eina_List *b = tail->next; + + if (!b) + { + stack[i++] = a; + break; + } + + tail = b->next; + + if (func(a->data, b->data) < 0) + ((stack[i++] = a)->next = b)->next = 0; + else + ((stack[i++] = b)->next = a)->next = 0; + + tmp = n++; + for (idx = n ^ tmp; idx &= idx - 1; i--) + stack[i - 2] = eina_list_sort_merge(stack[i - 2], stack[i - 1], func); + } + + while (i-- > 1) + stack[i - 1] = eina_list_sort_merge(stack[i - 1], stack[i], func); + + list = stack[0]; + tail = eina_list_sort_rebuild_prev(list); + + if (unsort) + { + tail->next = unsort; + unsort->prev = tail; + } + else + list->accounting->last = tail; + + return list; +} + +EAPI Eina_List * +eina_list_merge(Eina_List *left, Eina_List *right) +{ + unsigned int n_left, n_right; + + if (!left) + return right; + + if (!right) + return left; + + left->accounting->last->next = right; + right->prev = left->accounting->last; + + n_left = left->accounting->count; + n_right = right->accounting->count; + + if (n_left >= n_right) + { + Eina_List *itr = right; + left->accounting->last = right->accounting->last; + left->accounting->count += n_right; + + _eina_list_mempool_accounting_free(right->accounting); + + do + { + itr->accounting = left->accounting; + itr = itr->next; + } + while (itr); + } + else + { + Eina_List *itr = left->accounting->last; + right->accounting->count += n_left; + + _eina_list_mempool_accounting_free(left->accounting); + + do + { + itr->accounting = right->accounting; + itr = itr->prev; + } + while (itr); + } + + return left; +} + + +EAPI Eina_List * +eina_list_split_list(Eina_List *list, Eina_List *relative, Eina_List **right) +{ + Eina_List *next; + Eina_List *itr; + + if(!right) + return list; + + *right = NULL; + + if (!list) + return NULL; + + if (!relative) + { + *right = list; + return NULL; + } + + if (relative == eina_list_last(list)) + return list; + + next = eina_list_next(relative); + next->prev = NULL; + next->accounting = _eina_list_mempool_accounting_new(next); + next->accounting->last = list->accounting->last; + *right = next; + + itr = next; + do + { + itr->accounting = next->accounting; + next->accounting->count++; + itr = itr->next; + } + while (itr); + + relative->next = NULL; + list->accounting->last = relative; + list->accounting->count = list->accounting->count - next->accounting->count; + + return list; +} + +EAPI Eina_List * +eina_list_sorted_merge(Eina_List *left, Eina_List *right, Eina_Compare_Cb func) +{ + Eina_List *ret; + Eina_List *current; + + EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL); + + if (!left) + return right; + + if (!right) + return left; + + if (func(left->data, right->data) < 0) + { + ret = left; + current = left; + left = left->next; + ret->accounting->count += right->accounting->count; + + _eina_list_mempool_accounting_free(right->accounting); + } + else + { + ret = right; + current = right; + right = right->next; + ret->accounting->count += left->accounting->count; + + _eina_list_mempool_accounting_free(left->accounting); + } + + while (left && right) + { + if (func(left->data, right->data) < 0) + { + current->next = left; + left->prev = current; + left = left->next; + } + else + { + current->next = right; + right->prev = current; + right = right->next; + } + + current = current->next; + current->accounting = ret->accounting; + } + + if (left) + { + current->next = left; + left->prev = current; + current->accounting = ret->accounting; + } + + if (right) + { + current->next = right; + right->prev = current; + current->accounting = ret->accounting; + } + + while (current->next) + { + current = current->next; + current->accounting = ret->accounting; + } + + ret->accounting->last = current; + + return ret; +} + +EAPI Eina_List * +eina_list_search_sorted_near_list(const Eina_List *list, + Eina_Compare_Cb func, + const void *data, + int *result_cmp) +{ + const Eina_List *ct; + unsigned int inf, sup, cur; + int cmp; + + if (!list) + { + if (result_cmp) + *result_cmp = 0; + + return NULL; + } + + if (list->accounting->count == 1) + { + if (result_cmp) + *result_cmp = func(list->data, data); + + return (Eina_List *)list; + } + + /* list walk is expensive, do quick check: tail */ + ct = list->accounting->last; + cmp = func(ct->data, data); + if (cmp <= 0) + goto end; + + /* list walk is expensive, do quick check: head */ + ct = list; + cmp = func(ct->data, data); + if (cmp >= 0) + goto end; + + /* inclusive bounds */ + inf = 1; + sup = list->accounting->count - 2; + cur = 1; + ct = list->next; + + /* no loop, just compare if comparison value is important to caller */ + if (inf > sup) + { + if (result_cmp) + cmp = func(ct->data, data); + + goto end; + } + + while (inf <= sup) + { + unsigned int tmp = cur; + cur = inf + ((sup - inf) >> 1); + if (tmp < cur) + for (; tmp != cur; tmp++, ct = ct->next) ; + else if (tmp > cur) + for (; tmp != cur; tmp--, ct = ct->prev) ; + + cmp = func(ct->data, data); + if (cmp == 0) + break; + else if (cmp < 0) + inf = cur + 1; + else if (cmp > 0) + { + if (cur > 0) + sup = cur - 1; + else + break; + } + else + break; + } + +end: + if (result_cmp) + *result_cmp = cmp; + + return (Eina_List *)ct; +} + +EAPI Eina_List * +eina_list_search_sorted_list(const Eina_List *list, + Eina_Compare_Cb func, + const void *data) +{ + Eina_List *lnear; + int cmp; + + lnear = eina_list_search_sorted_near_list(list, func, data, &cmp); + if (!lnear) + return NULL; + + if (cmp == 0) + return lnear; + + return NULL; +} + + +EAPI void * +eina_list_search_sorted(const Eina_List *list, + Eina_Compare_Cb func, + const void *data) +{ + return eina_list_data_get(eina_list_search_sorted_list(list, func, data)); +} + +EAPI Eina_List * +eina_list_search_unsorted_list(const Eina_List *list, + Eina_Compare_Cb func, + const void *data) +{ + const Eina_List *l; + void *d; + + EINA_LIST_FOREACH(list, l, d) + { + if (!func(d, data)) + return (Eina_List *)l; + } + return NULL; +} + +EAPI void * +eina_list_search_unsorted(const Eina_List *list, + Eina_Compare_Cb func, + const void *data) +{ + return eina_list_data_get(eina_list_search_unsorted_list(list, func, data)); +} + + +EAPI Eina_Iterator * +eina_list_iterator_new(const Eina_List *list) +{ + Eina_Iterator_List *it; + + eina_error_set(0); + it = calloc(1, sizeof (Eina_Iterator_List)); + if (!it) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + EINA_MAGIC_SET(it, EINA_MAGIC_LIST_ITERATOR); + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->head = list; + it->current = list; + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(eina_list_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER( + eina_list_iterator_get_container); + it->iterator.free = FUNC_ITERATOR_FREE(eina_list_iterator_free); + + return &it->iterator; +} + +EAPI Eina_Iterator * +eina_list_iterator_reversed_new(const Eina_List *list) +{ + Eina_Iterator_List *it; + + eina_error_set(0); + it = calloc(1, sizeof (Eina_Iterator_List)); + if (!it) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + EINA_MAGIC_SET(it, EINA_MAGIC_LIST_ITERATOR); + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->head = eina_list_last(list); + it->current = it->head; + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(eina_list_iterator_prev); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER( + eina_list_iterator_get_container); + it->iterator.free = FUNC_ITERATOR_FREE(eina_list_iterator_free); + + return &it->iterator; +} + +EAPI Eina_Accessor * +eina_list_accessor_new(const Eina_List *list) +{ + Eina_Accessor_List *ac; + + eina_error_set(0); + ac = calloc(1, sizeof (Eina_Accessor_List)); + if (!ac) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + EINA_MAGIC_SET(ac, EINA_MAGIC_LIST_ACCESSOR); + EINA_MAGIC_SET(&ac->accessor, EINA_MAGIC_ACCESSOR); + + ac->head = list; + ac->current = list; + ac->index = 0; + + ac->accessor.version = EINA_ACCESSOR_VERSION; + ac->accessor.get_at = FUNC_ACCESSOR_GET_AT(eina_list_accessor_get_at); + ac->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER( + eina_list_accessor_get_container); + ac->accessor.free = FUNC_ACCESSOR_FREE(eina_list_accessor_free); + + return &ac->accessor; +} diff --git a/libraries/eina/src/lib/eina_log.c b/libraries/eina/src/lib/eina_log.c new file mode 100644 index 0000000..dd772d2 --- /dev/null +++ b/libraries/eina/src/lib/eina_log.c @@ -0,0 +1,1852 @@ +/* EINA - EFL data type library + * Copyright (C) 2007-2009 Jorge Luis Zapata Muga, Cedric Bail, Andre Dieb + * Martins + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef EFL_HAVE_POSIX_THREADS +# include +#endif + +#ifdef HAVE_EVIL +# include +#endif + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_inlist.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_log.h" + +/* TODO + * + printing logs to stdout or stderr can be implemented + * using a queue, useful for multiple threads printing + * + add a wrapper for assert? + */ + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +#define EINA_LOG_ENV_ABORT "EINA_LOG_ABORT" +#define EINA_LOG_ENV_ABORT_LEVEL "EINA_LOG_ABORT_LEVEL" +#define EINA_LOG_ENV_LEVEL "EINA_LOG_LEVEL" +#define EINA_LOG_ENV_LEVELS "EINA_LOG_LEVELS" +#define EINA_LOG_ENV_LEVELS_GLOB "EINA_LOG_LEVELS_GLOB" +#define EINA_LOG_ENV_COLOR_DISABLE "EINA_LOG_COLOR_DISABLE" +#define EINA_LOG_ENV_FILE_DISABLE "EINA_LOG_FILE_DISABLE" +#define EINA_LOG_ENV_FUNCTION_DISABLE "EINA_LOG_FUNCTION_DISABLE" + + +// Structure for storing domain level settings passed from the command line +// that will be matched with application-defined domains. +typedef struct _Eina_Log_Domain_Level_Pending Eina_Log_Domain_Level_Pending; +struct _Eina_Log_Domain_Level_Pending +{ + EINA_INLIST; + unsigned int level; + size_t namelen; + char name[]; +}; + +/* + * List of levels for domains set by the user before the domains are registered, + * updates the domain levels on the first log and clears itself. + */ +static Eina_Inlist *_pending_list = NULL; +static Eina_Inlist *_glob_list = NULL; + +// Disable color flag (can be changed through the env var +// EINA_LOG_ENV_COLOR_DISABLE). +static Eina_Bool _disable_color = EINA_FALSE; +static Eina_Bool _disable_file = EINA_FALSE; +static Eina_Bool _disable_function = EINA_FALSE; +static Eina_Bool _abort_on_critical = EINA_FALSE; +static int _abort_level_on_critical = EINA_LOG_LEVEL_CRITICAL; + +#ifdef EFL_HAVE_THREADS + +static Eina_Bool _threads_enabled = EINA_FALSE; +static Eina_Bool _threads_inited = EINA_FALSE; + +# ifdef EFL_HAVE_POSIX_THREADS + +typedef pthread_t Thread; + +static pthread_t _main_thread; + +# define SELF() pthread_self() +# define IS_MAIN(t) pthread_equal(t, _main_thread) +# define IS_OTHER(t) EINA_UNLIKELY(!IS_MAIN(t)) +# define CHECK_MAIN(...) \ + do { \ + if (!IS_MAIN(pthread_self())) { \ + fprintf(stderr, \ + "ERR: not main thread! current=%lu, main=%lu\n", \ + (unsigned long)pthread_self(), \ + (unsigned long)_main_thread); \ + return __VA_ARGS__; \ + } \ + } while (0) + +# ifdef EFL_HAVE_POSIX_THREADS_SPINLOCK + +static pthread_spinlock_t _log_lock; + +static Eina_Bool _eina_log_spinlock_init(void) +{ + if (pthread_spin_init(&_log_lock, PTHREAD_PROCESS_PRIVATE) == 0) + return EINA_TRUE; + + fprintf(stderr, + "ERROR: pthread_spin_init(%p, PTHREAD_PROCESS_PRIVATE): %s\n", + &_log_lock, strerror(errno)); + return EINA_FALSE; +} + +# define LOG_LOCK() \ + if (_threads_enabled) \ + do { \ + if (0) { \ + fprintf(stderr, "+++LOG LOG_LOCKED! [%s, %lu]\n", \ + __FUNCTION__, (unsigned long)pthread_self()); } \ + if (EINA_UNLIKELY(_threads_enabled)) { \ + pthread_spin_lock(&_log_lock); } \ + } while (0) +# define LOG_UNLOCK() \ + if (_threads_enabled) \ + do { \ + if (EINA_UNLIKELY(_threads_enabled)) { \ + pthread_spin_unlock(&_log_lock); } \ + if (0) { \ + fprintf(stderr, \ + "---LOG LOG_UNLOCKED! [%s, %lu]\n", \ + __FUNCTION__, (unsigned long)pthread_self()); } \ + } while (0) +# define INIT() _eina_log_spinlock_init() +# define SHUTDOWN() pthread_spin_destroy(&_log_lock) + +# else /* ! EFL_HAVE_POSIX_THREADS_SPINLOCK */ + +static pthread_mutex_t _log_mutex = PTHREAD_MUTEX_INITIALIZER; +# define LOG_LOCK() if(_threads_enabled) {pthread_mutex_lock(&_log_mutex); } +# define LOG_UNLOCK() if(_threads_enabled) {pthread_mutex_unlock(&_log_mutex); } +# define INIT() (1) +# define SHUTDOWN() do {} while (0) + +# endif /* ! EFL_HAVE_POSIX_THREADS_SPINLOCK */ + +# else /* EFL_HAVE_WIN32_THREADS */ + +typedef DWORD Thread; + +static DWORD _main_thread; + +# define SELF() GetCurrentThreadId() +# define IS_MAIN(t) (t == _main_thread) +# define IS_OTHER(t) EINA_UNLIKELY(!IS_MAIN(t)) +# define CHECK_MAIN(...) \ + do { \ + if (!IS_MAIN(GetCurrentThreadId())) { \ + fprintf(stderr, \ + "ERR: not main thread! current=%lu, main=%lu\n", \ + GetCurrentThreadId(), _main_thread); \ + return __VA_ARGS__; \ + } \ + } while (0) + +static HANDLE _log_mutex = NULL; + +# define LOG_LOCK() if(_threads_enabled) WaitForSingleObject(_log_mutex, INFINITE) +# define LOG_UNLOCK() if(_threads_enabled) ReleaseMutex(_log_mutex) +# define INIT() ((_log_mutex = CreateMutex(NULL, FALSE, NULL)) ? 1 : 0) +# define SHUTDOWN() if (_log_mutex) CloseHandle(_log_mutex) + +# endif /* EFL_HAVE_WIN32_THREADS */ + +#else /* ! EFL_HAVE_THREADS */ + +# define LOG_LOCK() do {} while (0) +# define LOG_UNLOCK() do {} while (0) +# define IS_MAIN(t) (1) +# define IS_OTHER(t) (0) +# define CHECK_MAIN(...) do {} while (0) +# define INIT() (1) +# define SHUTDOWN() do {} while (0) + +#endif /* ! EFL_HAVE_THREADS */ + + +// List of domains registered +static Eina_Log_Domain *_log_domains = NULL; +static unsigned int _log_domains_count = 0; +static size_t _log_domains_allocated = 0; + +// Default function for printing on domains +static Eina_Log_Print_Cb _print_cb = eina_log_print_cb_stderr; +static void *_print_cb_data = NULL; + +#ifdef DEBUG +static Eina_Log_Level _log_level = EINA_LOG_LEVEL_DBG; +#elif DEBUG_CRITICAL +static Eina_Log_Level _log_level = EINA_LOG_LEVEL_CRITICAL; +#else +static Eina_Log_Level _log_level = EINA_LOG_LEVEL_ERR; +#endif + +/* NOTE: if you change this, also change: + * eina_log_print_level_name_get() + * eina_log_print_level_name_color_get() + */ +static const char *_names[] = { + "CRI", + "ERR", + "WRN", + "INF", + "DBG", +}; + +#ifdef _WIN32 +static int +eina_log_win32_color_get(const char *domain_str) +{ + char *str; + char *tmp; + char *tmp2; + int code = -1; + int lighted = 0; + int ret = 0; + + str = strdup(domain_str); + if (!str) + return 0; + + /* this should not append */ + if (str[0] != '\033') + { + free(str); + return 0; + } + + /* we skip the first char and the [ */ + tmp = tmp2 = str + 2; + while (*tmp != 'm') + { + if (*tmp == ';') + { + *tmp = '\0'; + code = atol(tmp2); + tmp++; + tmp2 = tmp; + } + + tmp++; + } + *tmp = '\0'; + if (code < 0) + code = atol(tmp2); + else + lighted = atol(tmp2); + + free(str); + + if (code < lighted) + { + int c; + + c = code; + code = lighted; + lighted = c; + } + + if (lighted) + ret = FOREGROUND_INTENSITY; + + if (code == 31) + ret |= FOREGROUND_RED; + else if (code == 32) + ret |= FOREGROUND_GREEN; + else if (code == 33) + ret |= FOREGROUND_RED | FOREGROUND_GREEN; + else if (code == 34) + ret |= FOREGROUND_BLUE; + else if (code == 36) + ret |= FOREGROUND_GREEN | FOREGROUND_BLUE; + else if (code == 37) + ret |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + + return ret; +} +#endif + +static inline unsigned int +eina_log_pid_get(void) +{ + return (unsigned int)getpid(); +} + +static inline void +eina_log_print_level_name_get(int level, const char **p_name) +{ + static char buf[4]; + /* NOTE: if you change this, also change + * eina_log_print_level_name_color_get() + * eina_log_level_name_get() (at eina_inline_log.x) + */ + if (EINA_UNLIKELY(level < 0)) + { + snprintf(buf, sizeof(buf), "%03d", level); + *p_name = buf; + } + else if (EINA_UNLIKELY(level >= EINA_LOG_LEVELS)) + { + snprintf(buf, sizeof(buf), "%03d", level); + *p_name = buf; + } + else + *p_name = _names[level]; +} + +#ifdef _WIN32 +static inline void +eina_log_print_level_name_color_get(int level, + const char **p_name, + int *p_color) +{ + static char buf[4]; + /* NOTE: if you change this, also change: + * eina_log_print_level_name_get() + */ + if (EINA_UNLIKELY(level < 0)) + { + snprintf(buf, sizeof(buf), "%03d", level); + *p_name = buf; + } + else if (EINA_UNLIKELY(level >= EINA_LOG_LEVELS)) + { + snprintf(buf, sizeof(buf), "%03d", level); + *p_name = buf; + } + else + *p_name = _names[level]; + + *p_color = eina_log_win32_color_get(eina_log_level_color_get(level)); +} +#else +static inline void +eina_log_print_level_name_color_get(int level, + const char **p_name, + const char **p_color) +{ + static char buf[4]; + /* NOTE: if you change this, also change: + * eina_log_print_level_name_get() + */ + if (EINA_UNLIKELY(level < 0)) + { + snprintf(buf, sizeof(buf), "%03d", level); + *p_name = buf; + } + else if (EINA_UNLIKELY(level >= EINA_LOG_LEVELS)) + { + snprintf(buf, sizeof(buf), "%03d", level); + *p_name = buf; + } + else + *p_name = _names[level]; + + *p_color = eina_log_level_color_get(level); +} +#endif + +#define DECLARE_LEVEL_NAME(level) const char *name; \ + eina_log_print_level_name_get(level, &name) +#ifdef _WIN32 +# define DECLARE_LEVEL_NAME_COLOR(level) const char *name; int color; \ + eina_log_print_level_name_color_get(level, &name, &color) +#else +# define DECLARE_LEVEL_NAME_COLOR(level) const char *name, *color; \ + eina_log_print_level_name_color_get(level, &name, &color) +#endif + +/** No threads, No color */ +static void +eina_log_print_prefix_NOthreads_NOcolor_file_func(FILE *fp, + const Eina_Log_Domain *d, + Eina_Log_Level level, + const char *file, + const char *fnc, + int line) +{ + DECLARE_LEVEL_NAME(level); + fprintf(fp, "%s<%u>:%s %s:%d %s() ", name, eina_log_pid_get(), + d->domain_str, file, line, fnc); +} + +static void +eina_log_print_prefix_NOthreads_NOcolor_NOfile_func(FILE *fp, + const Eina_Log_Domain *d, + Eina_Log_Level level, + const char *file __UNUSED__, + const char *fnc, + int line __UNUSED__) +{ + DECLARE_LEVEL_NAME(level); + fprintf(fp, "%s<%u>:%s %s() ", name, eina_log_pid_get(), d->domain_str, + fnc); +} + +static void +eina_log_print_prefix_NOthreads_NOcolor_file_NOfunc(FILE *fp, + const Eina_Log_Domain *d, + Eina_Log_Level level, + const char *file, + const char *fnc __UNUSED__, + int line) +{ + DECLARE_LEVEL_NAME(level); + fprintf(fp, "%s<%u>:%s %s:%d ", name, eina_log_pid_get(), d->domain_str, + file, line); +} + +/* No threads, color */ +static void +eina_log_print_prefix_NOthreads_color_file_func(FILE *fp, + const Eina_Log_Domain *d, + Eina_Log_Level level, + const char *file, + const char *fnc, + int line) +{ + DECLARE_LEVEL_NAME_COLOR(level); +#ifdef _WIN32_WCE + fprintf(fp, "%s<%u>:%s %s:%d %s() ", name, eina_log_pid_get(), + d->domain_str, file, line, fnc); +#elif _WIN32 + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + color); + fprintf(fp, "%s", name); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + fprintf(fp, ":"); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + eina_log_win32_color_get(d->domain_str)); + fprintf(fp, "%s", d->name); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + fprintf(fp, " %s:%d ", file, line); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + FOREGROUND_INTENSITY | FOREGROUND_RED | + FOREGROUND_GREEN | FOREGROUND_BLUE); + fprintf(fp, "%s()", fnc); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + fprintf(fp, " "); +#else + fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s %s:%d " + EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ", + color, name, eina_log_pid_get(), d->domain_str, file, line, fnc); +#endif +} + +static void +eina_log_print_prefix_NOthreads_color_NOfile_func(FILE *fp, + const Eina_Log_Domain *d, + Eina_Log_Level level, + const char *file __UNUSED__, + const char *fnc, + int line __UNUSED__) +{ + DECLARE_LEVEL_NAME_COLOR(level); +#ifdef _WIN32_WCE + fprintf(fp, "%s<%u>:%s %s() ", name, eina_log_pid_get(), d->domain_str, + fnc); +#elif _WIN32 + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + color); + fprintf(fp, "%s", name); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + fprintf(fp, ":"); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + eina_log_win32_color_get(d->domain_str)); + fprintf(fp, "%s", d->name); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + FOREGROUND_INTENSITY | FOREGROUND_RED | + FOREGROUND_GREEN | FOREGROUND_BLUE); + fprintf(fp, "%s()", fnc); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + fprintf(fp, " "); +#else + fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s " + EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ", + color, name, eina_log_pid_get(), d->domain_str, fnc); +#endif +} + +static void +eina_log_print_prefix_NOthreads_color_file_NOfunc(FILE *fp, + const Eina_Log_Domain *d, + Eina_Log_Level level, + const char *file, + const char *fnc __UNUSED__, + int line) +{ + DECLARE_LEVEL_NAME_COLOR(level); +#ifdef _WIN32_WCE + fprintf(fp, "%s<%u>:%s %s:%d ", name, eina_log_pid_get(), d->domain_str, + file, line); +#elif _WIN32 + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + color); + fprintf(fp, "%s", name); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + fprintf(fp, ":"); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + eina_log_win32_color_get(d->domain_str)); + fprintf(fp, "%s", d->name); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + fprintf(fp, " %s:%d ", file, line); +#else + fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s %s:%d ", + color, name, eina_log_pid_get(), d->domain_str, file, line); +#endif +} + +/** threads, No color */ +#ifdef EFL_HAVE_THREADS +static void +eina_log_print_prefix_threads_NOcolor_file_func(FILE *fp, + const Eina_Log_Domain *d, + Eina_Log_Level level, + const char *file, + const char *fnc, + int line) +{ + Thread cur; + + DECLARE_LEVEL_NAME(level); + cur = SELF(); + if (IS_OTHER(cur)) + { + fprintf(fp, "%s<%u>:%s[T:%lu] %s:%d %s() ", + name, eina_log_pid_get(), d->domain_str, + (unsigned long)cur, file, line, fnc); + return; + } + fprintf(fp, "%s<%u>:%s %s:%d %s() ", + name, eina_log_pid_get(), d->domain_str, file, line, fnc); +} + +static void +eina_log_print_prefix_threads_NOcolor_NOfile_func(FILE *fp, + const Eina_Log_Domain *d, + Eina_Log_Level level, + const char *file __UNUSED__, + const char *fnc, + int line __UNUSED__) +{ + Thread cur; + + DECLARE_LEVEL_NAME(level); + cur = SELF(); + if (IS_OTHER(cur)) + { + fprintf(fp, "%s<%u>:%s[T:%lu] %s() ", + name, eina_log_pid_get(), d->domain_str, + (unsigned long)cur, fnc); + return; + } + fprintf(fp, "%s<%u>:%s %s() ", + name, eina_log_pid_get(), d->domain_str, fnc); +} + +static void +eina_log_print_prefix_threads_NOcolor_file_NOfunc(FILE *fp, + const Eina_Log_Domain *d, + Eina_Log_Level level, + const char *file, + const char *fnc __UNUSED__, + int line) +{ + Thread cur; + + DECLARE_LEVEL_NAME(level); + cur = SELF(); + if (IS_OTHER(cur)) + { + fprintf(fp, "%s<%u>:%s[T:%lu] %s:%d ", + name, eina_log_pid_get(), d->domain_str, (unsigned long)cur, + file, line); + return; + } + + fprintf(fp, "%s<%u>:%s %s:%d ", + name, eina_log_pid_get(), d->domain_str, file, line); +} + +/* threads, color */ +static void +eina_log_print_prefix_threads_color_file_func(FILE *fp, + const Eina_Log_Domain *d, + Eina_Log_Level level, + const char *file, + const char *fnc, + int line) +{ + Thread cur; + + DECLARE_LEVEL_NAME_COLOR(level); + cur = SELF(); + if (IS_OTHER(cur)) + { +# ifdef _WIN32 + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + color); + fprintf(fp, "%s", name); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_BLUE); + fprintf(fp, ":"); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + eina_log_win32_color_get(d->domain_str)); + fprintf(fp, "%s[T:", d->name); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_BLUE); + fprintf(fp, "[T:"); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + FOREGROUND_GREEN | FOREGROUND_BLUE); + fprintf(fp, "%lu", (unsigned long)cur); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_BLUE); + fprintf(fp, "] %s:%d ", file, line); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + FOREGROUND_INTENSITY | FOREGROUND_RED | + FOREGROUND_GREEN | FOREGROUND_BLUE); + fprintf(fp, "%s()", fnc); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_BLUE); + fprintf(fp, " "); +# else + fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s[T:" + EINA_COLOR_ORANGE "%lu" EINA_COLOR_RESET "] %s:%d " + EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ", + color, name, eina_log_pid_get() ,d->domain_str, + (unsigned long)cur, file, line, fnc); +# endif + return; + } + +# ifdef _WIN32 + eina_log_print_prefix_NOthreads_color_file_func(fp, + d, + level, + file, + fnc, + line); +# else + fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s %s:%d " + EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ", + color, name, eina_log_pid_get(), d->domain_str, file, line, fnc); +# endif +} + +static void +eina_log_print_prefix_threads_color_NOfile_func(FILE *fp, + const Eina_Log_Domain *d, + Eina_Log_Level level, + const char *file __UNUSED__, + const char *fnc, + int line __UNUSED__) +{ + Thread cur; + + DECLARE_LEVEL_NAME_COLOR(level); + cur = SELF(); + if (IS_OTHER(cur)) + { +# ifdef _WIN32 + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + color); + fprintf(fp, "%s", name); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_BLUE); + fprintf(fp, ":"); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + eina_log_win32_color_get(d->domain_str)); + fprintf(fp, "%s[T:", d->name); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_BLUE); + fprintf(fp, "[T:"); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + FOREGROUND_GREEN | FOREGROUND_BLUE); + fprintf(fp, "%lu", (unsigned long)cur); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + FOREGROUND_INTENSITY | FOREGROUND_RED | + FOREGROUND_GREEN | FOREGROUND_BLUE); + fprintf(fp, "%s()", fnc); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_BLUE); + fprintf(fp, " "); +# else + fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s[T:" + EINA_COLOR_ORANGE "%lu" EINA_COLOR_RESET "] " + EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ", + color, name, eina_log_pid_get(), d->domain_str, + (unsigned long)cur, fnc); +# endif + return; + } + +# ifdef _WIN32 + eina_log_print_prefix_NOthreads_color_NOfile_func(fp, + d, + level, + file, + fnc, + line); +# else + fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s " + EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ", + color, name, eina_log_pid_get(), d->domain_str, fnc); +# endif +} + +static void +eina_log_print_prefix_threads_color_file_NOfunc(FILE *fp, + const Eina_Log_Domain *d, + Eina_Log_Level level, + const char *file, + const char *fnc __UNUSED__, + int line) +{ + Thread cur; + + DECLARE_LEVEL_NAME_COLOR(level); + cur = SELF(); + if (IS_OTHER(cur)) + { +# ifdef _WIN32 + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + color); + fprintf(fp, "%s", name); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_BLUE); + fprintf(fp, ":"); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + eina_log_win32_color_get(d->domain_str)); + fprintf(fp, "%s[T:", d->name); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_BLUE); + fprintf(fp, "[T:"); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + FOREGROUND_GREEN | FOREGROUND_BLUE); + fprintf(fp, "%lu", (unsigned long)cur); + SetConsoleTextAttribute(GetStdHandle( + STD_OUTPUT_HANDLE), + FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_BLUE); + fprintf(fp, "] %s:%d ", file, line); +# else + fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s[T:" + EINA_COLOR_ORANGE "%lu" EINA_COLOR_RESET "] %s:%d ", + color, name, eina_log_pid_get(), d->domain_str, + (unsigned long)cur, file, line); +# endif + return; + } + +# ifdef _WIN32 + eina_log_print_prefix_NOthreads_color_file_NOfunc(fp, + d, + level, + file, + fnc, + line); +# else + fprintf(fp, "%s%s" EINA_COLOR_RESET ":%s %s:%d ", + color, name, d->domain_str, file, line); +# endif +} +#endif /* EFL_HAVE_THREADS */ + +static void (*_eina_log_print_prefix)(FILE *fp, const Eina_Log_Domain *d, + Eina_Log_Level level, const char *file, + const char *fnc, + int line) = + eina_log_print_prefix_NOthreads_color_file_func; + +static inline void +eina_log_print_prefix_update(void) +{ + if (_disable_file && _disable_function) + { + fprintf(stderr, "ERROR: cannot have " EINA_LOG_ENV_FILE_DISABLE " and " + EINA_LOG_ENV_FUNCTION_DISABLE " set at the same time, will " + "just disable function.\n"); + _disable_file = 0; + } + +#define S(NOthread, NOcolor, NOfile, NOfunc) \ + _eina_log_print_prefix = \ + eina_log_print_prefix_ ## NOthread ## threads_ ## NOcolor ## color_ ## \ + NOfile \ + ## file_ ## NOfunc ## func + +#ifdef EFL_HAVE_THREADS + if (_threads_enabled) + { + if (_disable_color) + { + if (_disable_file) + S(,NO,NO,); + else if (_disable_function) + S(,NO,,NO); + else + S(,NO,,); + } + else + { + if (_disable_file) + S(,,NO,); + else if (_disable_function) + S(,,,NO); + else + S(,,,); + } + + return; + } + +#endif + + if (_disable_color) + { + if (_disable_file) + S(NO,NO,NO,); + else if (_disable_function) + S(NO,NO,,NO); + else + S(NO,NO,,); + } + else + { + if (_disable_file) + S(NO,,NO,); + else if (_disable_function) + S(NO,,,NO); + else + S(NO,,,); + } + +#undef S +} + +/* + * Creates a colored domain name string. + */ +static const char * +eina_log_domain_str_get(const char *name, const char *color) +{ + const char *d; + + if (color) + { + size_t name_len; + size_t color_len; + + name_len = strlen(name); + color_len = strlen(color); + d = + malloc(sizeof(char) * + (color_len + name_len + strlen(EINA_COLOR_RESET) + 1)); + if (!d) + return NULL; + + memcpy((char *)d, color, color_len); + memcpy((char *)(d + color_len), name, name_len); + memcpy((char *)(d + color_len + name_len), EINA_COLOR_RESET, + strlen(EINA_COLOR_RESET)); + ((char *)d)[color_len + name_len + strlen(EINA_COLOR_RESET)] = '\0'; + } + else + d = strdup(name); + + return d; +} + +/* + * Setups a new logging domain to the name and color specified. Note that this + * constructor acts upon an pre-allocated object. + */ +static Eina_Log_Domain * +eina_log_domain_new(Eina_Log_Domain *d, const char *name, const char *color) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL); + + d->level = EINA_LOG_LEVEL_UNKNOWN; + d->deleted = EINA_FALSE; + + if ((color) && (!_disable_color)) + d->domain_str = eina_log_domain_str_get(name, color); + else + d->domain_str = eina_log_domain_str_get(name, NULL); + + d->name = strdup(name); + d->namelen = strlen(name); + + return d; +} + +/* + * Frees internal strings of a log domain, keeping the log domain itself as a + * slot for next domain registers. + */ +static void +eina_log_domain_free(Eina_Log_Domain *d) +{ + EINA_SAFETY_ON_NULL_RETURN(d); + + if (d->domain_str) + free((char *)d->domain_str); + + if (d->name) + free((char *)d->name); +} + +/* + * Parses domain levels passed through the env var. + */ +static void +eina_log_domain_parse_pendings(void) +{ + const char *start; + + if (!(start = getenv(EINA_LOG_ENV_LEVELS))) + return; + + // name1:level1,name2:level2,name3:level3,... + while (1) + { + Eina_Log_Domain_Level_Pending *p; + char *end = NULL; + char *tmp = NULL; + long int level; + + end = strchr(start, ':'); + if (!end) + break; + + // Parse level, keep going if failed + level = strtol((char *)(end + 1), &tmp, 10); + if (tmp == (end + 1)) + goto parse_end; + + // Parse name + p = malloc(sizeof(Eina_Log_Domain_Level_Pending) + end - start + 1); + if (!p) + break; + + p->namelen = end - start; + memcpy((char *)p->name, start, end - start); + ((char *)p->name)[end - start] = '\0'; + p->level = level; + + _pending_list = eina_inlist_append(_pending_list, EINA_INLIST_GET(p)); + +parse_end: + start = strchr(tmp, ','); + if (start) + start++; + else + break; + } +} + +static void +eina_log_domain_parse_pending_globs(void) +{ + const char *start; + + if (!(start = getenv(EINA_LOG_ENV_LEVELS_GLOB))) + return; + + // name1:level1,name2:level2,name3:level3,... + while (1) + { + Eina_Log_Domain_Level_Pending *p; + char *end = NULL; + char *tmp = NULL; + long int level; + + end = strchr(start, ':'); + if (!end) + break; + + // Parse level, keep going if failed + level = strtol((char *)(end + 1), &tmp, 10); + if (tmp == (end + 1)) + goto parse_end; + + // Parse name + p = malloc(sizeof(Eina_Log_Domain_Level_Pending) + end - start + 1); + if (!p) + break; + + p->namelen = 0; /* not that useful */ + memcpy((char *)p->name, start, end - start); + ((char *)p->name)[end - start] = '\0'; + p->level = level; + + _glob_list = eina_inlist_append(_glob_list, EINA_INLIST_GET(p)); + +parse_end: + start = strchr(tmp, ','); + if (start) + start++; + else + break; + } +} + +static inline int +eina_log_domain_register_unlocked(const char *name, const char *color) +{ + Eina_Log_Domain_Level_Pending *pending = NULL; + size_t namelen; + unsigned int i; + + for (i = 0; i < _log_domains_count; i++) + { + if (_log_domains[i].deleted) + { + // Found a flagged slot, free domain_str and replace slot + eina_log_domain_new(&_log_domains[i], name, color); + goto finish_register; + } + } + + if (_log_domains_count >= _log_domains_allocated) + { + Eina_Log_Domain *tmp; + size_t size; + + if (!_log_domains) + // special case for init, eina itself will allocate a dozen of domains + size = 24; + else + // grow 8 buckets to minimize reallocs + size = _log_domains_allocated + 8; + + tmp = realloc(_log_domains, sizeof(Eina_Log_Domain) * size); + + if (tmp) + { + // Success! + _log_domains = tmp; + _log_domains_allocated = size; + } + else + return -1; + } + + // Use an allocated slot + eina_log_domain_new(&_log_domains[i], name, color); + _log_domains_count++; + +finish_register: + namelen = _log_domains[i].namelen; + + EINA_INLIST_FOREACH(_pending_list, pending) + { + if ((namelen == pending->namelen) && (strcmp(pending->name, name) == 0)) + { + _log_domains[i].level = pending->level; + _pending_list = + eina_inlist_remove(_pending_list, EINA_INLIST_GET(pending)); + free(pending); + break; + } + } + + if (_log_domains[i].level == EINA_LOG_LEVEL_UNKNOWN) + { + EINA_INLIST_FOREACH(_glob_list, pending) + { + if (!fnmatch(pending->name, name, 0)) + { + _log_domains[i].level = pending->level; + break; + } + } + } + + // Check if level is still UNKNOWN, set it to global + if (_log_domains[i].level == EINA_LOG_LEVEL_UNKNOWN) + _log_domains[i].level = _log_level; + + return i; +} + +static inline Eina_Bool +eina_log_term_color_supported(const char *term) +{ + const char *tail; + + if (!term) + return EINA_FALSE; + + tail = term + 1; + switch (term[0]) + { + /* list of known to support color terminals, + * take from gentoo's portage. + */ + + case 'x': /* xterm and xterm-color */ + return ((strncmp(tail, "term", sizeof("term") - 1) == 0) && + ((tail[sizeof("term") - 1] == '\0') || + (strcmp(tail + sizeof("term") - 1, "-color") == 0))); + + case 'E': /* Eterm */ + case 'a': /* aterm */ + case 'k': /* kterm */ + return (strcmp(tail, "term") == 0); + + case 'r': /* xrvt or rxvt-unicode */ + return ((strncmp(tail, "xvt", sizeof("xvt") - 1) == 0) && + ((tail[sizeof("xvt") - 1] == '\0') || + (strcmp(tail + sizeof("xvt") - 1, "-unicode") == 0))); + + case 's': /* screen */ + return (strcmp(tail, "creen") == 0); + + case 'g': /* gnome */ + return (strcmp(tail, "nome") == 0); + + case 'i': /* interix */ + return (strcmp(tail, "nterix") == 0); + + default: + return EINA_FALSE; + } +} + +static inline void +eina_log_domain_unregister_unlocked(int domain) +{ + Eina_Log_Domain *d; + + if ((unsigned int)domain >= _log_domains_count) + return; + + d = &_log_domains[domain]; + eina_log_domain_free(d); + d->deleted = 1; +} + +static inline void +eina_log_print_unlocked(int domain, + Eina_Log_Level level, + const char *file, + const char *fnc, + int line, + const char *fmt, + va_list args) +{ + Eina_Log_Domain *d; + +#ifdef EINA_SAFETY_CHECKS + if (EINA_UNLIKELY((unsigned int)domain >= _log_domains_count) || + EINA_UNLIKELY(domain < 0)) + { + if (file && fnc && fmt) + fprintf( + stderr, + "CRI: %s:%d %s() eina_log_print() unknown domain %d, original message format '%s'\n", + file, + line, + fnc, + domain, + fmt); + else + fprintf( + stderr, + "CRI: eina_log_print() unknown domain %d, original message format '%s'\n", + domain, + fmt ? fmt : ""); + + if (_abort_on_critical) + abort(); + + return; + } + +#endif + d = _log_domains + domain; +#ifdef EINA_SAFETY_CHECKS + if (EINA_UNLIKELY(d->deleted)) + { + fprintf(stderr, + "ERR: eina_log_print() domain %d is deleted\n", + domain); + return; + } + +#endif + + if (level > d->level) + return; + +#ifdef _WIN32 + { + char *wfmt; + char *tmp; + + wfmt = strdup(fmt); + if (!wfmt) + { + fprintf(stderr, "ERR: %s: can not allocate memory\n", __FUNCTION__); + return; + } + + tmp = wfmt; + while (strchr(tmp, '%')) + { + tmp++; + if (*tmp == 'z') + *tmp = 'I'; + } + _print_cb(d, level, file, fnc, line, wfmt, _print_cb_data, args); + free(wfmt); + } +#else + _print_cb(d, level, file, fnc, line, fmt, _print_cb_data, args); +#endif + + if (EINA_UNLIKELY(_abort_on_critical) && + EINA_UNLIKELY(level <= _abort_level_on_critical)) + abort(); +} + +/** + * @endcond + */ + + +/*============================================================================* +* Global * +*============================================================================*/ + +/** + * @internal + * @brief Initialize the log module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the log module of Eina. It is called by + * eina_init(). + * + * @see eina_init() + * + * @warning Not-MT: just call this function from main thread! The + * place where this function was called the first time is + * considered the main thread. + */ +Eina_Bool +eina_log_init(void) +{ + const char *level, *tmp; + int color_disable; + + assert((sizeof(_names) / sizeof(_names[0])) == EINA_LOG_LEVELS); + + if ((tmp = getenv(EINA_LOG_ENV_COLOR_DISABLE))) + color_disable = atoi(tmp); + else + color_disable = -1; + + /* Check if color is explicitly disabled */ + if (color_disable == 1) + _disable_color = EINA_TRUE; + +#ifndef _WIN32 + /* color was not explicitly disabled or enabled, guess it */ + else if (color_disable == -1) + { + if (!eina_log_term_color_supported(getenv("TERM"))) + _disable_color = EINA_TRUE; + else + { + /* if not a terminal, but redirected to a file, disable color */ + int fd; + + if (_print_cb == eina_log_print_cb_stderr) + fd = STDERR_FILENO; + else if (_print_cb == eina_log_print_cb_stdout) + fd = STDOUT_FILENO; + else + fd = -1; + + if ((fd >= 0) && (!isatty(fd))) + _disable_color = EINA_TRUE; + } + } +#endif + + if ((tmp = getenv(EINA_LOG_ENV_FILE_DISABLE)) && (atoi(tmp) == 1)) + _disable_file = EINA_TRUE; + + if ((tmp = getenv(EINA_LOG_ENV_FUNCTION_DISABLE)) && (atoi(tmp) == 1)) + _disable_function = EINA_TRUE; + + if ((tmp = getenv(EINA_LOG_ENV_ABORT)) && (atoi(tmp) == 1)) + _abort_on_critical = EINA_TRUE; + + if ((tmp = getenv(EINA_LOG_ENV_ABORT_LEVEL))) + _abort_level_on_critical = atoi(tmp); + + eina_log_print_prefix_update(); + + // Global log level + if ((level = getenv(EINA_LOG_ENV_LEVEL))) + _log_level = atoi(level); + + // Register UNKNOWN domain, the default logger + EINA_LOG_DOMAIN_GLOBAL = eina_log_domain_register("", NULL); + + if (EINA_LOG_DOMAIN_GLOBAL < 0) + { + fprintf(stderr, "Failed to create global logging domain.\n"); + return EINA_FALSE; + } + + // Parse pending domains passed through EINA_LOG_LEVELS_GLOB + eina_log_domain_parse_pending_globs(); + + // Parse pending domains passed through EINA_LOG_LEVELS + eina_log_domain_parse_pendings(); + + return EINA_TRUE; +} + +/** + * @internal + * @brief Shut down the log module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the log module set up by + * eina_log_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + * + * @warning Not-MT: just call this function from main thread! The + * place where eina_log_init() (eina_init()) was called the + * first time is considered the main thread. + */ +Eina_Bool +eina_log_shutdown(void) +{ + Eina_Inlist *tmp; + + while (_log_domains_count--) + { + if (_log_domains[_log_domains_count].deleted) + continue; + + eina_log_domain_free(&_log_domains[_log_domains_count]); + } + + free(_log_domains); + + _log_domains = NULL; + _log_domains_count = 0; + _log_domains_allocated = 0; + + while (_glob_list) + { + tmp = _glob_list; + _glob_list = _glob_list->next; + free(tmp); + } + + while (_pending_list) + { + tmp = _pending_list; + _pending_list = _pending_list->next; + free(tmp); + } + + return EINA_TRUE; +} + +#ifdef EFL_HAVE_THREADS + +/** + * @internal + * @brief Activate the log mutex. + * + * This function activate the mutex in the eina log module. It is called by + * eina_threads_init(). + * + * @see eina_threads_init() + */ +void +eina_log_threads_init(void) +{ + if (_threads_inited) return; + _main_thread = SELF(); + if (!INIT()) return; + _threads_inited = EINA_TRUE; +} + +/** + * @internal + * @brief Shut down the log mutex. + * + * This function shuts down the mutex in the log module. + * It is called by eina_threads_shutdown(). + * + * @see eina_threads_shutdown() + */ +void +eina_log_threads_shutdown(void) +{ + if (!_threads_inited) return; + CHECK_MAIN(); + SHUTDOWN(); + _threads_enabled = EINA_FALSE; + _threads_inited = EINA_FALSE; +} + +#endif + +/*============================================================================* +* API * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +EAPI int EINA_LOG_DOMAIN_GLOBAL = 0; + +/** + * @endcond + */ + +EAPI void +eina_log_threads_enable(void) +{ +#ifdef EFL_HAVE_THREADS + if (_threads_enabled) return; + if (!_threads_inited) eina_log_threads_init(); + _threads_enabled = EINA_TRUE; + eina_log_print_prefix_update(); +#endif +} + +EAPI void +eina_log_print_cb_set(Eina_Log_Print_Cb cb, void *data) +{ + LOG_LOCK(); + _print_cb = cb; + _print_cb_data = data; + eina_log_print_prefix_update(); + LOG_UNLOCK(); +} + +EAPI void +eina_log_level_set(int level) +{ + _log_level = level; + if (EINA_LIKELY((EINA_LOG_DOMAIN_GLOBAL >= 0) && + ((unsigned int)EINA_LOG_DOMAIN_GLOBAL < _log_domains_count))) + _log_domains[EINA_LOG_DOMAIN_GLOBAL].level = level; +} + +EAPI int +eina_log_level_get(void) +{ + return _log_level; +} + +EAPI Eina_Bool +eina_log_main_thread_check(void) +{ +#ifdef EFL_HAVE_THREADS + return ((!_threads_enabled) || IS_MAIN(SELF())); +#else + return EINA_TRUE; +#endif +} + +EAPI void +eina_log_color_disable_set(Eina_Bool disabled) +{ + _disable_color = disabled; +} + +EAPI Eina_Bool +eina_log_color_disable_get(void) +{ + return _disable_color; +} + +EAPI void +eina_log_file_disable_set(Eina_Bool disabled) +{ + _disable_file = disabled; +} + +EAPI Eina_Bool +eina_log_file_disable_get(void) +{ + return _disable_file; +} + +EAPI void +eina_log_function_disable_set(Eina_Bool disabled) +{ + _disable_function = disabled; +} + +EAPI Eina_Bool +eina_log_function_disable_get(void) +{ + return _disable_function; +} + +EAPI void +eina_log_abort_on_critical_set(Eina_Bool abort_on_critical) +{ + _abort_on_critical = abort_on_critical; +} + +EAPI Eina_Bool +eina_log_abort_on_critical_get(void) +{ + return _abort_on_critical; +} + +EAPI void +eina_log_abort_on_critical_level_set(int critical_level) +{ + _abort_level_on_critical = critical_level; +} + +EAPI int +eina_log_abort_on_critical_level_get(void) +{ + return _abort_level_on_critical; +} + +EAPI int +eina_log_domain_register(const char *name, const char *color) +{ + int r; + + EINA_SAFETY_ON_NULL_RETURN_VAL(name, -1); + + LOG_LOCK(); + r = eina_log_domain_register_unlocked(name, color); + LOG_UNLOCK(); + return r; +} + +EAPI void +eina_log_domain_unregister(int domain) +{ + EINA_SAFETY_ON_FALSE_RETURN(domain >= 0); + LOG_LOCK(); + eina_log_domain_unregister_unlocked(domain); + LOG_UNLOCK(); +} + +EAPI void +eina_log_domain_level_set(const char *domain_name, int level) +{ + Eina_Log_Domain_Level_Pending *pending; + size_t namelen; + unsigned int i; + + EINA_SAFETY_ON_NULL_RETURN(domain_name); + + namelen = strlen(domain_name); + + for (i = 0; i < _log_domains_count; i++) + { + if (_log_domains[i].deleted) + continue; + + if ((namelen != _log_domains[i].namelen) || + (strcmp(_log_domains[i].name, domain_name) != 0)) + continue; + + _log_domains[i].level = level; + return; + } + + EINA_INLIST_FOREACH(_pending_list, pending) + { + if ((namelen == pending->namelen) && + (strcmp(pending->name, domain_name) == 0)) + { + pending->level = level; + return; + } + } + + pending = malloc(sizeof(Eina_Log_Domain_Level_Pending) + namelen + 1); + if (!pending) + return; + + pending->level = level; + pending->namelen = namelen; + memcpy(pending->name, domain_name, namelen + 1); + + _pending_list = eina_inlist_append(_pending_list, EINA_INLIST_GET(pending)); +} + +EAPI int +eina_log_domain_level_get(const char *domain_name) +{ + Eina_Log_Domain_Level_Pending *pending; + size_t namelen; + unsigned int i; + + EINA_SAFETY_ON_NULL_RETURN_VAL(domain_name, EINA_LOG_LEVEL_UNKNOWN); + + namelen = strlen(domain_name); + + for (i = 0; i < _log_domains_count; i++) + { + if (_log_domains[i].deleted) + continue; + + if ((namelen != _log_domains[i].namelen) || + (strcmp(_log_domains[i].name, domain_name) != 0)) + continue; + + return _log_domains[i].level; + } + + EINA_INLIST_FOREACH(_pending_list, pending) + { + if ((namelen == pending->namelen) && + (strcmp(pending->name, domain_name) == 0)) + return pending->level; + } + + EINA_INLIST_FOREACH(_glob_list, pending) + { + if (!fnmatch(pending->name, domain_name, 0)) + return pending->level; + } + + return _log_level; +} + +EAPI int +eina_log_domain_registered_level_get(int domain) +{ + EINA_SAFETY_ON_FALSE_RETURN_VAL(domain >= 0, EINA_LOG_LEVEL_UNKNOWN); + EINA_SAFETY_ON_FALSE_RETURN_VAL((unsigned int)domain < _log_domains_count, + EINA_LOG_LEVEL_UNKNOWN); + EINA_SAFETY_ON_TRUE_RETURN_VAL(_log_domains[domain].deleted, + EINA_LOG_LEVEL_UNKNOWN); + return _log_domains[domain].level; +} + +EAPI void +eina_log_print_cb_stderr(const Eina_Log_Domain *d, + Eina_Log_Level level, + const char *file, + const char *fnc, + int line, + const char *fmt, + __UNUSED__ void *data, + va_list args) +{ + _eina_log_print_prefix(stderr, d, level, file, fnc, line); + vfprintf(stderr, fmt, args); + putc('\n', stderr); +} + +EAPI void +eina_log_print_cb_stdout(const Eina_Log_Domain *d, + Eina_Log_Level level, + const char *file, + const char *fnc, + int line, + const char *fmt, + __UNUSED__ void *data, + va_list args) +{ + _eina_log_print_prefix(stdout, d, level, file, fnc, line); + vprintf(fmt, args); + putchar('\n'); +} + +EAPI void +eina_log_print_cb_file(const Eina_Log_Domain *d, + __UNUSED__ Eina_Log_Level level, + const char *file, + const char *fnc, + int line, + const char *fmt, + void *data, + va_list args) +{ + FILE *f = data; +#ifdef EFL_HAVE_THREADS + if (_threads_enabled) + { + Thread cur; + + cur = SELF(); + if (IS_OTHER(cur)) + { + fprintf(f, "%s[T:%lu] %s:%d %s() ", d->name, (unsigned long)cur, + file, line, fnc); + goto end; + } + } + +#endif + fprintf(f, "%s<%u> %s:%d %s() ", d->name, eina_log_pid_get(), + file, line, fnc); +#ifdef EFL_HAVE_THREADS +end: +#endif + vfprintf(f, fmt, args); + putc('\n', f); +} + +EAPI void +eina_log_print(int domain, Eina_Log_Level level, const char *file, + const char *fnc, int line, const char *fmt, ...) +{ + va_list args; + +#ifdef EINA_SAFETY_CHECKS + if (EINA_UNLIKELY(!file)) + { + fputs("ERR: eina_log_print() file == NULL\n", stderr); + return; + } + + if (EINA_UNLIKELY(!fnc)) + { + fputs("ERR: eina_log_print() fnc == NULL\n", stderr); + return; + } + + if (EINA_UNLIKELY(!fmt)) + { + fputs("ERR: eina_log_print() fmt == NULL\n", stderr); + return; + } + +#endif + va_start(args, fmt); + LOG_LOCK(); + eina_log_print_unlocked(domain, level, file, fnc, line, fmt, args); + LOG_UNLOCK(); + va_end(args); +} + +EAPI void +eina_log_vprint(int domain, Eina_Log_Level level, const char *file, + const char *fnc, int line, const char *fmt, va_list args) +{ +#ifdef EINA_SAFETY_CHECKS + if (EINA_UNLIKELY(!file)) + { + fputs("ERR: eina_log_print() file == NULL\n", stderr); + return; + } + + if (EINA_UNLIKELY(!fnc)) + { + fputs("ERR: eina_log_print() fnc == NULL\n", stderr); + return; + } + + if (EINA_UNLIKELY(!fmt)) + { + fputs("ERR: eina_log_print() fmt == NULL\n", stderr); + return; + } + +#endif + LOG_LOCK(); + eina_log_print_unlocked(domain, level, file, fnc, line, fmt, args); + LOG_UNLOCK(); +} diff --git a/libraries/eina/src/lib/eina_magic.c b/libraries/eina/src/lib/eina_magic.c new file mode 100644 index 0000000..1adde92 --- /dev/null +++ b/libraries/eina/src/lib/eina_magic.c @@ -0,0 +1,320 @@ +/* EINA - EFL data type library + * Copyright (C) 2008 Cedric Bail + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#ifdef HAVE_EVIL +# include +#endif + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_error.h" +#include "eina_log.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_magic.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +typedef struct _Eina_Magic_String Eina_Magic_String; +struct _Eina_Magic_String +{ + Eina_Magic magic; + Eina_Bool string_allocated; + const char *string; +}; + +static int _eina_magic_string_log_dom = -1; + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_eina_magic_string_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_magic_string_log_dom, __VA_ARGS__) + +static Eina_Magic_String *_eina_magic_strings = NULL; +static size_t _eina_magic_strings_count = 0; +static size_t _eina_magic_strings_allocated = 0; +static Eina_Bool _eina_magic_strings_dirty = 0; + +static int +_eina_magic_strings_sort_cmp(const void *p1, const void *p2) +{ + const Eina_Magic_String *a = p1, *b = p2; + return a->magic - b->magic; +} + +static int +_eina_magic_strings_find_cmp(const void *p1, const void *p2) +{ + Eina_Magic a = (Eina_Magic)p1; + const Eina_Magic_String *b = p2; + return a - b->magic; +} + +static Eina_Magic_String * +_eina_magic_strings_alloc(void) +{ + size_t idx; + + if (_eina_magic_strings_count == _eina_magic_strings_allocated) + { + void *tmp; + size_t size; + + if (EINA_UNLIKELY(_eina_magic_strings_allocated == 0)) + size = 48; + else + size = _eina_magic_strings_allocated + 16; + + 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; + } + + _eina_magic_strings = tmp; + _eina_magic_strings_allocated = size; + } + + idx = _eina_magic_strings_count; + _eina_magic_strings_count++; + return _eina_magic_strings + idx; +} + +/** + * @endcond + */ + +/*============================================================================* +* Global * +*============================================================================*/ + +/** + * @internal + * @brief Initialize the magic string module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the magic string module of Eina. It is called by + * eina_init(). + * + * @see eina_init() + */ +Eina_Bool +eina_magic_string_init(void) +{ + _eina_magic_string_log_dom = eina_log_domain_register + ("eina_magic_string", EINA_LOG_COLOR_DEFAULT); + if (_eina_magic_string_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_magic_string"); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +/** + * @internal + * @brief Shut down the magic string module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the magic string module set up by + * eina_magic string_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_magic_string_shutdown(void) +{ + Eina_Magic_String *ems, *ems_end; + + ems = _eina_magic_strings; + ems_end = ems + _eina_magic_strings_count; + + for (; ems < ems_end; ems++) + if (ems->string_allocated) + free((char *)ems->string); + + free(_eina_magic_strings); + _eina_magic_strings = NULL; + _eina_magic_strings_count = 0; + _eina_magic_strings_allocated = 0; + + eina_log_domain_unregister(_eina_magic_string_log_dom); + _eina_magic_string_log_dom = -1; + + return EINA_TRUE; +} + +/*============================================================================* +* API * +*============================================================================*/ +EAPI const char * +eina_magic_string_get(Eina_Magic magic) +{ + Eina_Magic_String *ems; + + if (!_eina_magic_strings) + return "(none)"; + + if (_eina_magic_strings_dirty) + { + qsort(_eina_magic_strings, _eina_magic_strings_count, + sizeof(Eina_Magic_String), _eina_magic_strings_sort_cmp); + _eina_magic_strings_dirty = 0; + } + + ems = bsearch((void *)magic, _eina_magic_strings, + _eina_magic_strings_count, sizeof(Eina_Magic_String), + _eina_magic_strings_find_cmp); + if (ems) + return ems->string ? ems->string : "(undefined)"; + + return "(unknown)"; +} + +EAPI Eina_Bool +eina_magic_string_set(Eina_Magic magic, const char *magic_name) +{ + Eina_Magic_String *ems; + + EINA_SAFETY_ON_NULL_RETURN_VAL(magic_name, EINA_FALSE); + + ems = _eina_magic_strings_alloc(); + if (!ems) + return EINA_FALSE; + + ems->magic = magic; + ems->string_allocated = EINA_TRUE; + ems->string = strdup(magic_name); + if (!ems->string) + { + ERR("could not allocate string '%s'", magic_name); + _eina_magic_strings_count--; + return EINA_FALSE; + } + + _eina_magic_strings_dirty = 1; + return EINA_TRUE; +} + +EAPI Eina_Bool +eina_magic_string_static_set(Eina_Magic magic, const char *magic_name) +{ + Eina_Magic_String *ems; + + EINA_SAFETY_ON_NULL_RETURN_VAL(magic_name, EINA_FALSE); + + ems = _eina_magic_strings_alloc(); + if (!ems) + return EINA_FALSE; + + ems->magic = magic; + ems->string_allocated = EINA_FALSE; + ems->string = magic_name; + + _eina_magic_strings_dirty = 1; + return EINA_TRUE; +} + +#ifdef eina_magic_fail +# undef eina_magic_fail +#endif + +EAPI void +eina_magic_fail(void *d, + Eina_Magic m, + Eina_Magic req_m, + const char *file, + const char *fnc, + int line) +{ + if (!d) + eina_log_print(EINA_LOG_DOMAIN_GLOBAL, EINA_LOG_LEVEL_CRITICAL, + file, fnc, line, + "*** Eina Magic Check Failed !!!\n" + " Input handle pointer is NULL !\n" + "*** NAUGHTY PROGRAMMER!!!\n" + "*** SPANK SPANK SPANK!!!\n" + "*** Now go fix your code. Tut tut tut!\n" + "\n"); + else + if (m == EINA_MAGIC_NONE) + eina_log_print(EINA_LOG_DOMAIN_GLOBAL, EINA_LOG_LEVEL_CRITICAL, + file, fnc, line, + "*** Eina Magic Check Failed !!!\n" + " Input handle has already been freed!\n" + "*** NAUGHTY PROGRAMMER!!!\n" + "*** SPANK SPANK SPANK!!!\n" + "*** Now go fix your code. Tut tut tut!\n" + "\n"); + else + if (m != req_m) + eina_log_print(EINA_LOG_DOMAIN_GLOBAL, EINA_LOG_LEVEL_CRITICAL, + file, fnc, line, + "*** Eina Magic Check Failed !!!\n" + " Input handle is wrong type\n" + " Expected: %08x - %s\n" + " Supplied: %08x - %s\n" + "*** NAUGHTY PROGRAMMER!!!\n" + "*** SPANK SPANK SPANK!!!\n" + "*** Now go fix your code. Tut tut tut!\n" + "\n", + req_m, eina_magic_string_get(req_m), + m, eina_magic_string_get(m)); + else + eina_log_print(EINA_LOG_DOMAIN_GLOBAL, EINA_LOG_LEVEL_CRITICAL, + file, fnc, line, + "*** Eina Magic Check Failed !!!\n" + " Why did you call me !\n" + "*** NAUGHTY PROGRAMMER!!!\n" + "*** SPANK SPANK SPANK!!!\n" + "*** Now go fix your code. Tut tut tut!\n" + "\n"); +} + +/** + * @} + */ diff --git a/libraries/eina/src/lib/eina_main.c b/libraries/eina/src/lib/eina_main.c new file mode 100644 index 0000000..8727f83 --- /dev/null +++ b/libraries/eina/src/lib/eina_main.c @@ -0,0 +1,431 @@ +/* EINA - EFL data type library + * Copyright (C) 2008 Cedric Bail + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#ifdef EFL_HAVE_WIN32_THREADS +# define WIN32_LEAN_AND_MEAN +# include +# undef WIN32_LEAN_AND_MEAN +#endif + +#ifdef EFL_HAVE_THREADS +# ifdef HAVE_SYS_TYPES_H +# include +# endif +# ifdef HAVE_UNISTD_H +# include +# endif +#endif + +#ifdef HAVE_MCHECK +# ifdef HAVE_MTRACE +# define MT 1 +# endif +#endif + +#ifdef MT +#include +#endif + +#include "eina_lock.h" +#include "eina_config.h" +#include "eina_private.h" +#include "eina_types.h" +#include "eina_main.h" +#include "eina_error.h" +#include "eina_log.h" +#include "eina_hash.h" +#include "eina_binshare.h" +#include "eina_stringshare.h" +#include "eina_ustringshare.h" +#include "eina_list.h" +#include "eina_matrixsparse.h" +#include "eina_array.h" +#include "eina_counter.h" +#include "eina_benchmark.h" +#include "eina_magic.h" +#include "eina_rectangle.h" +#include "eina_safety_checks.h" +#include "eina_inlist.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +static Eina_Version _version = { VMAJ, VMIN, VMIC, VREV }; + +static int _eina_main_count = 0; +#ifdef EFL_HAVE_THREADS +static int _eina_main_thread_count = 0; +#endif +static int _eina_log_dom = -1; + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_eina_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_log_dom, __VA_ARGS__) + +EAPI Eina_Bool _eina_threads_activated = EINA_FALSE; +EAPI Eina_Error EINA_ERROR_NOT_MAIN_LOOP = 0; + +static const char EINA_ERROR_NOT_MAIN_LOOP_STR[] = "Main loop thread check failed."; + +#ifdef EFL_HAVE_THREADS +# ifdef _WIN32 +EAPI DWORD _eina_main_loop; +# else +EAPI pthread_t _eina_main_loop; +# endif +static pid_t _eina_pid; +#endif + +#ifdef MT +static int _mt_enabled = 0; +#endif + +#ifdef EFL_HAVE_THREADS +EAPI int _eina_threads_debug = 0; +# if !defined(_WIN32_WCE) && !defined(_WIN32) +EAPI pthread_mutex_t _eina_tracking_lock; +EAPI Eina_Inlist *_eina_tracking = NULL; +# endif +#endif + +/* place module init/shutdown functions here to avoid other modules + * calling them by mistake. + */ +#define S(x) extern Eina_Bool eina_ ## x ## _init(void); \ + extern Eina_Bool eina_ ## x ## _shutdown(void) + S(log); + S(error); + S(safety_checks); + S(magic_string); + S(iterator); + S(accessor); + S(array); + S(module); + S(mempool); + S(list); + S(binshare); + S(stringshare); + S(ustringshare); + S(matrixsparse); + S(convert); + S(counter); + S(benchmark); + S(rectangle); + S(strbuf); + S(ustrbuf); + S(quadtree); + S(simple_xml); + S(file); + S(prefix); +#undef S + +struct eina_desc_setup +{ + const char *name; + Eina_Bool (*init)(void); + Eina_Bool (*shutdown)(void); +}; + +static const struct eina_desc_setup _eina_desc_setup[] = { +#define S(x) {# x, eina_ ## x ## _init, eina_ ## x ## _shutdown} + /* log is a special case as it needs printf */ + S(error), + S(safety_checks), + S(magic_string), + S(iterator), + S(accessor), + S(array), + S(module), + S(mempool), + S(list), + S(binshare), + S(stringshare), + S(ustringshare), + S(matrixsparse), + S(convert), + S(counter), + S(benchmark), + S(rectangle), + S(strbuf), + S(ustrbuf), + S(quadtree), + S(simple_xml), + S(file), + S(prefix) +#undef S +}; +static const size_t _eina_desc_setup_len = sizeof(_eina_desc_setup) / + sizeof(_eina_desc_setup[0]); + +static void +_eina_shutdown_from_desc(const struct eina_desc_setup *itr) +{ + for (itr--; itr >= _eina_desc_setup; itr--) + { + if (!itr->shutdown()) + ERR("Problems shutting down eina module '%s', ignored.", itr->name); + } + + eina_log_domain_unregister(_eina_log_dom); + _eina_log_dom = -1; + eina_log_shutdown(); +} + +/** + * @endcond + */ + +/*============================================================================* +* Global * +*============================================================================*/ + + +/*============================================================================* +* API * +*============================================================================*/ + +/** + * @var eina_version + * @brief Eina version (defined at configuration time) + */ +EAPI Eina_Version *eina_version = &_version; + +EAPI int +eina_init(void) +{ + const struct eina_desc_setup *itr, *itr_end; + + if (EINA_LIKELY(_eina_main_count > 0)) + return ++_eina_main_count; + +#ifdef MT + if ((getenv("EINA_MTRACE")) && (getenv("MALLOC_TRACE"))) + { + _mt_enabled = 1; + mtrace(); + } +#endif + + if (!eina_log_init()) + { + fprintf(stderr, "Could not initialize eina logging system.\n"); + return 0; + } + + _eina_log_dom = eina_log_domain_register("eina", EINA_LOG_COLOR_DEFAULT); + if (_eina_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina"); + eina_log_shutdown(); + return 0; + } + + EINA_ERROR_NOT_MAIN_LOOP = eina_error_msg_static_register( + EINA_ERROR_NOT_MAIN_LOOP_STR); + +#ifdef EFL_HAVE_THREADS +# ifdef _WIN32 + _eina_main_loop = GetCurrentThreadId(); +# else + _eina_main_loop = pthread_self(); +# endif + _eina_pid = getpid(); +#endif + +#ifdef EINA_HAVE_DEBUG_THREADS + pthread_mutex_init(&_eina_tracking_lock, NULL); + + if (getenv("EINA_DEBUG_THREADS")) + _eina_threads_debug = atoi(getenv("EINA_DEBUG_THREADS")); +#endif + + itr = _eina_desc_setup; + itr_end = itr + _eina_desc_setup_len; + for (; itr < itr_end; itr++) + { + if (!itr->init()) + { + ERR("Could not initialize eina module '%s'.", itr->name); + _eina_shutdown_from_desc(itr); + return 0; + } + } + + _eina_main_count = 1; + return 1; +} + +EAPI int +eina_shutdown(void) +{ + _eina_main_count--; + if (EINA_UNLIKELY(_eina_main_count == 0)) + { + _eina_shutdown_from_desc(_eina_desc_setup + _eina_desc_setup_len); + +#ifdef EINA_HAVE_DEBUG_THREADS + pthread_mutex_destroy(&_eina_tracking_lock); +#endif +#ifdef MT + if (_mt_enabled) + { + muntrace(); + _mt_enabled = 0; + } +#endif + } + + return _eina_main_count; +} + + +EAPI int +eina_threads_init(void) +{ +#ifdef EFL_HAVE_THREADS + int ret; + +#ifdef EINA_HAVE_DEBUG_THREADS + assert(pthread_equal(_eina_main_loop, pthread_self())); +#endif + + ++_eina_main_thread_count; + ret = _eina_main_thread_count; + + if(_eina_main_thread_count > 1) + return ret; + + eina_share_common_threads_init(); + eina_log_threads_init(); + _eina_threads_activated = EINA_TRUE; + + return ret; +#else + return 0; +#endif +} + +EAPI int +eina_threads_shutdown(void) +{ +#ifdef EFL_HAVE_THREADS + int ret; + +#ifdef EINA_HAVE_DEBUG_THREADS + const Eina_Lock *lk; + + assert(pthread_equal(_eina_main_loop, pthread_self())); + assert(_eina_main_thread_count > 0); +#endif + + ret = --_eina_main_thread_count; + if(_eina_main_thread_count > 0) + return ret; + +#ifdef EINA_HAVE_DEBUG_THREADS + pthread_mutex_lock(&_eina_tracking_lock); + if (_eina_tracking) + { + fprintf(stderr, "*************************\n"); + fprintf(stderr, "* The IMPOSSIBLE HAPPEN *\n"); + fprintf(stderr, "* LOCK STILL TAKEN : *\n"); + fprintf(stderr, "*************************\n"); + EINA_INLIST_FOREACH(_eina_tracking, lk) + eina_lock_debug(lk); + fprintf(stderr, "*************************\n"); + abort(); + } + pthread_mutex_unlock(&_eina_tracking_lock); +#endif + + eina_share_common_threads_shutdown(); + eina_log_threads_shutdown(); + + _eina_threads_activated = EINA_FALSE; + + return ret; +#else + return 0; +#endif +} + +EAPI Eina_Bool +eina_main_loop_is(void) +{ +#ifdef EFL_HAVE_THREADS + pid_t pid = getpid(); + +# ifdef _WIN32 + if (pid != _eina_pid) + { + _eina_pid = pid; + _eina_main_loop = GetCurrentThreadId(); + return EINA_TRUE; + } + if (_eina_main_loop == GetCurrentThreadId()) + return EINA_TRUE; +# else + if (pid != _eina_pid) + { + /* This is in case of a fork, but don't like the solution */ + _eina_pid = pid; + _eina_main_loop = pthread_self(); + return EINA_TRUE; + } + + if (pthread_equal(_eina_main_loop, pthread_self())) + return EINA_TRUE; +# endif +#endif + return EINA_FALSE; +} + +/** The purpose of this API should not be documented, it is used only by the one who know what they are doing. */ +EAPI void +eina_main_loop_define(void) +{ +#ifdef EFL_HAVE_THREADS + _eina_pid = getpid(); +# ifdef _WIN32 + _eina_main_loop = GetCurrentThreadId(); +# else + _eina_main_loop = pthread_self(); +# endif +#endif +} + +/** + * @} + */ diff --git a/libraries/eina/src/lib/eina_matrixsparse.c b/libraries/eina/src/lib/eina_matrixsparse.c new file mode 100644 index 0000000..3ac0439 --- /dev/null +++ b/libraries/eina/src/lib/eina_matrixsparse.c @@ -0,0 +1,1421 @@ +/* EINA - EFL data type library + * Copyright (C) 2009 Gustavo Sverzut Barbieri + * + * 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 . + */ + + +/** + * @page tutorial_matrixsparse_page Sparse Matrix Tutorial + * + * to be written... + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#ifdef HAVE_EVIL +# include +#endif + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_error.h" +#include "eina_log.h" +#include "eina_magic.h" +#include "eina_mempool.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_matrixsparse.h" + + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +static const char EINA_MAGIC_MATRIXSPARSE_STR[] = "Eina Matrixsparse"; +static const char EINA_MAGIC_MATRIXSPARSE_ROW_STR[] = "Eina Matrixsparse Row"; +static const char EINA_MAGIC_MATRIXSPARSE_CELL_STR[] = "Eina Matrixsparse Cell"; +static const char EINA_MAGIC_MATRIXSPARSE_ITERATOR_STR[] = + "Eina Matrixsparse Iterator"; +static const char EINA_MAGIC_MATRIXSPARSE_ROW_ACCESSOR_STR[] = + "Eina Matrixsparse Row Accessor"; +static const char EINA_MAGIC_MATRIXSPARSE_ROW_ITERATOR_STR[] = + "Eina Matrixsparse Row Iterator"; +static const char EINA_MAGIC_MATRIXSPARSE_CELL_ACCESSOR_STR[] = + "Eina Matrixsparse Cell Accessor"; +static const char EINA_MAGIC_MATRIXSPARSE_CELL_ITERATOR_STR[] = + "Eina Matrixsparse Cell Iterator"; + + +#define EINA_MAGIC_CHECK_MATRIXSPARSE(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_MATRIXSPARSE)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_MATRIXSPARSE); \ + return __VA_ARGS__; \ + } \ + } while(0) + +#define EINA_MAGIC_CHECK_MATRIXSPARSE_ROW(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_MATRIXSPARSE_ROW)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_MATRIXSPARSE_ROW); \ + return __VA_ARGS__; \ + } \ + } while(0) + +#define EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_MATRIXSPARSE_CELL)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_MATRIXSPARSE_CELL); \ + return __VA_ARGS__; \ + } \ + } while(0) + +#define EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_MATRIXSPARSE_ITERATOR)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_MATRIXSPARSE_ITERATOR); \ + return __VA_ARGS__; \ + } \ + } while(0) + +struct _Eina_Matrixsparse_Cell +{ + Eina_Matrixsparse_Cell *next; + Eina_Matrixsparse_Cell *prev; + + void *data; + unsigned long col; + + Eina_Matrixsparse_Row *parent; + + EINA_MAGIC +}; + +struct _Eina_Matrixsparse_Row +{ + Eina_Matrixsparse_Row *next; + Eina_Matrixsparse_Row *prev; + + Eina_Matrixsparse_Cell *cols; + Eina_Matrixsparse_Cell *last_col; + Eina_Matrixsparse_Cell *last_used; /* fast sequential access */ + unsigned long row; + + Eina_Matrixsparse *parent; + + EINA_MAGIC +}; + +struct _Eina_Matrixsparse +{ + Eina_Matrixsparse_Row *rows; + Eina_Matrixsparse_Row *last_row; + Eina_Matrixsparse_Row *last_used; /* fast sequential access */ + + struct + { + unsigned long rows; + unsigned long cols; + } size; + + struct + { + void (*func)(void *user_data, void *cell_data); + void *user_data; + } free; + + EINA_MAGIC +}; + +typedef struct _Eina_Matrixsparse_Iterator Eina_Matrixsparse_Iterator; +typedef struct _Eina_Matrixsparse_Iterator_Complete +Eina_Matrixsparse_Iterator_Complete; + +struct _Eina_Matrixsparse_Iterator +{ + Eina_Iterator iterator; + + const Eina_Matrixsparse *m; + struct + { + const Eina_Matrixsparse_Row *row; + const Eina_Matrixsparse_Cell *col; + } ref; + + EINA_MAGIC +}; + +struct _Eina_Matrixsparse_Iterator_Complete +{ + Eina_Iterator iterator; + + const Eina_Matrixsparse *m; + struct + { + const Eina_Matrixsparse_Row *row; + const Eina_Matrixsparse_Cell *col; + } ref; + + struct + { + unsigned long row, col; + } idx; + + struct + { + Eina_Matrixsparse_Row row; + Eina_Matrixsparse_Cell col; + } dummy; + + EINA_MAGIC +}; + +/** + * @todo Eina_Matrixsparse_Row_Iterator: iterator over rows in matrix + * @todo Eina_Matrixsparse_Row_Accessor: accessor over rows in matrix + * @todo Eina_Matrixsparse_Cell_Iterator: iterator over cells in row + * @todo Eina_Matrixsparse_Cell_Accessor: accessor over cells in row + */ + +static int _eina_matrixsparse_log_dom = -1; + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_eina_matrixsparse_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_matrixsparse_log_dom, __VA_ARGS__) + +static Eina_Mempool *_eina_matrixsparse_cell_mp = NULL; +static Eina_Mempool *_eina_matrixsparse_row_mp = NULL; + +static inline void +_eina_matrixsparse_cell_free(Eina_Matrixsparse_Cell *c, void (*free_func)( + void *, + void *), void *user_data) +{ + if (free_func) + free_func(user_data, c->data); + + EINA_MAGIC_SET(c, EINA_MAGIC_NONE); + eina_mempool_free(_eina_matrixsparse_cell_mp, c); +} + +static inline void +_eina_matrixsparse_cell_unlink(Eina_Matrixsparse_Cell *c) +{ + Eina_Matrixsparse_Row *r = c->parent; + + if (r->last_used == c) + { + if (c->next) + r->last_used = c->next; + else + r->last_used = c->prev; + } + + if (r->last_col == c) + r->last_col = c->prev; + + if (r->cols == c) + r->cols = c->next; + + if (c->next && c->prev) + { + c->next->prev = c->prev; + c->prev->next = c->next; + } + else if (c->next) + c->next->prev = NULL; + else if (c->prev) + c->prev->next = NULL; +} + +static inline void +_eina_matrixsparse_row_cells_free(Eina_Matrixsparse_Row *r, void (*free_func)( + void *, + void *), void *user_data) +{ + Eina_Matrixsparse_Cell *c = r->cols; + while (c) + { + Eina_Matrixsparse_Cell *c_aux = c; + c = c->next; + _eina_matrixsparse_cell_free(c_aux, free_func, user_data); + } +} + +static inline void +_eina_matrixsparse_row_free(Eina_Matrixsparse_Row *r, void (*free_func)(void *, + void *), + void *user_data) +{ + _eina_matrixsparse_row_cells_free(r, free_func, user_data); + EINA_MAGIC_SET(r, EINA_MAGIC_NONE); + eina_mempool_free(_eina_matrixsparse_row_mp, r); +} + +static inline void +_eina_matrixsparse_row_unlink(Eina_Matrixsparse_Row *r) +{ + Eina_Matrixsparse *m = r->parent; + + if (m->last_used == r) + { + if (r->next) + m->last_used = r->next; + else + m->last_used = r->prev; + } + + if (m->last_row == r) + m->last_row = r->prev; + + if (m->rows == r) + m->rows = r->next; + + if (r->next && r->prev) + { + r->next->prev = r->prev; + r->prev->next = r->next; + } + else if (r->next) + r->next->prev = NULL; + else if (r->prev) + r->prev->next = NULL; +} + +static inline void +_eina_matrixsparse_row_find_parms_get(const Eina_Matrixsparse *m, + unsigned long row, + Eina_Matrixsparse_Row **p_r, + int *p_dir) +{ + Eina_Matrixsparse_Row *r; + unsigned long dist; + int dir; + + dist = row - m->rows->row; + r = m->rows; + dir = 1; + if (dist > m->last_row->row - row) + { + dist = m->last_row->row - row; + r = m->last_row; + dir = -1; + } + + if (m->last_used) + { + if (m->last_used->row < row) + { + if (dist > row - m->last_used->row) + { +/* dist = row = m->last_used->row; */ + r = m->last_used; + dir = 1; + } + } + else if (dist > m->last_used->row - row) + { +/* dist = m->last_used->row - row; */ + r = m->last_used; + dir = -1; + } + } + + *p_r = r; + *p_dir = dir; +} + +static inline void +_eina_matrixsparse_row_cell_find_parms_get(const Eina_Matrixsparse_Row *r, + unsigned long col, + Eina_Matrixsparse_Cell **p_c, + int *p_dir) +{ + Eina_Matrixsparse_Cell *c; + unsigned long dist; + int dir; + + dist = col - r->cols->col; + c = r->cols; + dir = 1; + if (dist > r->last_col->col - col) + { + dist = r->last_col->col - col; + c = r->last_col; + dir = -1; + } + + if (r->last_used) + { + if (r->last_used->col < col) + { + if (dist > col - r->last_used->col) + { +/* dist = col = r->last_used->col; */ + c = r->last_used; + dir = 1; + } + } + else if (dist > r->last_used->col - col) + { +/* dist = r->last_used->col - col; */ + c = r->last_used; + dir = -1; + } + } + + *p_c = c; + *p_dir = dir; +} + +static inline Eina_Matrixsparse_Row * +_eina_matrixsparse_row_idx_get(const Eina_Matrixsparse *m, unsigned long row) +{ + Eina_Matrixsparse_Row *r; + int dir; + + if (!m->rows) + return NULL; + + if (m->rows->row == row) + return m->rows; + else if (m->rows->row > row) + return NULL; + + if (m->last_row->row == row) + return m->last_row; + else if (m->last_row->row < row) + return NULL; + + if ((m->last_used) && (m->last_used->row == row)) + return m->last_used; + + _eina_matrixsparse_row_find_parms_get(m, row, &r, &dir); + assert(dir != 0); + if (dir > 0) + { + for (; r; r = r->next) + if (r->row == row) + { + ((Eina_Matrixsparse *)m)->last_used = r; + return r; + } + else if (r->row > row) + return NULL; + + } + else if (dir < 0) + { + for (; r; r = r->prev) + if (r->row == row) + { + ((Eina_Matrixsparse *)m)->last_used = r; + return r; + } + else if (r->row < row) + return NULL; + } + + return NULL; +} + +static inline Eina_Matrixsparse_Cell * +_eina_matrixsparse_row_cell_idx_get(const Eina_Matrixsparse_Row *r, + unsigned long col) +{ + Eina_Matrixsparse_Cell *c; + int dir; + + if (!r->cols) + return NULL; + + if (r->cols->col == col) + return r->cols; + else if (r->cols->col > col) + return NULL; + + if (r->last_col->col == col) + return r->last_col; + else if (r->last_col->col < col) + return NULL; + + if ((r->last_used) && (r->last_used->col == col)) + return r->last_used; + + _eina_matrixsparse_row_cell_find_parms_get(r, col, &c, &dir); + assert(dir != 0); + if (dir > 0) + { + for (; r; c = c->next) + if (c->col == col) + { + ((Eina_Matrixsparse_Row *)r)->last_used = c; + return c; + } + else if (c->col > col) + return NULL; + + } + else if (dir < 0) + { + for (; r; c = c->prev) + if (c->col == col) + { + ((Eina_Matrixsparse_Row *)r)->last_used = c; + return c; + } + else if (c->col < col) + return NULL; + } + + return NULL; +} + +static inline Eina_Matrixsparse_Cell * +_eina_matrixsparse_cell_idx_get(const Eina_Matrixsparse *m, + unsigned long row, + unsigned long col) +{ + Eina_Matrixsparse_Row *r = _eina_matrixsparse_row_idx_get(m, row); + if (!r) + return NULL; + + return _eina_matrixsparse_row_cell_idx_get(r, col); +} + +static inline void +_eina_matrixsparse_row_idx_siblings_find(const Eina_Matrixsparse *m, + unsigned long row, + Eina_Matrixsparse_Row **p_prev, + Eina_Matrixsparse_Row **p_next) +{ + Eina_Matrixsparse_Row *r; + int dir; + + _eina_matrixsparse_row_find_parms_get(m, row, &r, &dir); + assert(dir != 0); + if (dir > 0) + { + for (; r; r = r->next) + if (r->row > row) + break; + + assert(r != NULL); + *p_prev = r->prev; + *p_next = r; + } + else if (dir < 0) + { + for (; r; r = r->prev) + if (r->row < row) + break; + + assert(r != NULL); + *p_prev = r; + *p_next = r->next; + } +} + +static inline void +_eina_matrixsparse_row_cell_idx_siblings_find(const Eina_Matrixsparse_Row *r, + unsigned long col, + Eina_Matrixsparse_Cell **p_prev, + Eina_Matrixsparse_Cell **p_next) +{ + Eina_Matrixsparse_Cell *c; + int dir; + + _eina_matrixsparse_row_cell_find_parms_get(r, col, &c, &dir); + assert(dir != 0); + if (dir > 0) + { + for (; c; c = c->next) + if (c->col > col) + break; + + assert(c != NULL); + *p_prev = c->prev; + *p_next = c; + } + else if (dir < 0) + { + for (; c; c = c->prev) + if (c->col < col) + break; + + assert(c != NULL); + *p_prev = c; + *p_next = c->next; + } +} + +static inline Eina_Matrixsparse_Row * +_eina_matrixsparse_row_idx_add(Eina_Matrixsparse *m, unsigned long row) +{ + Eina_Matrixsparse_Row *r = eina_mempool_malloc + (_eina_matrixsparse_row_mp, sizeof(Eina_Matrixsparse_Row)); + if (!r) + return NULL; + + if (!m->rows) + { + r->prev = NULL; + r->next = NULL; + m->rows = r; + m->last_row = r; + } + else if (row < m->rows->row) + { + r->prev = NULL; + r->next = m->rows; + m->rows->prev = r; + m->rows = r; + } + else if (row > m->last_row->row) + { + r->prev = m->last_row; + m->last_row->next = r; + r->next = NULL; + m->last_row = r; + } + else + { + Eina_Matrixsparse_Row *prev = NULL, *next = NULL; + _eina_matrixsparse_row_idx_siblings_find(m, row, &prev, &next); + assert(prev != NULL); + assert(next != NULL); + r->prev = prev; + r->next = next; + prev->next = r; + next->prev = r; + } + + r->cols = NULL; + r->last_col = NULL; + r->last_used = NULL; + r->row = row; + r->parent = m; + EINA_MAGIC_SET(r, EINA_MAGIC_MATRIXSPARSE_ROW); + m->last_used = r; + return r; +} + +static inline Eina_Matrixsparse_Cell * +_eina_matrixsparse_row_cell_idx_add(Eina_Matrixsparse_Row *r, + unsigned long col, + const void *data) +{ + Eina_Matrixsparse_Cell *c = eina_mempool_malloc + (_eina_matrixsparse_cell_mp, sizeof(Eina_Matrixsparse_Cell)); + if (!c) + return NULL; + + if (!r->cols) + { + c->prev = NULL; + c->next = NULL; + r->cols = c; + r->last_col = c; + } + else if (col < r->cols->col) + { + c->prev = NULL; + c->next = r->cols; + r->cols->prev = c; + r->cols = c; + } + else if (col > r->last_col->col) + { + c->prev = r->last_col; + r->last_col->next = c; + c->next = NULL; + r->last_col = c; + } + else + { + Eina_Matrixsparse_Cell *prev = NULL, *next = NULL; + _eina_matrixsparse_row_cell_idx_siblings_find(r, col, &prev, &next); + assert(prev != NULL); + assert(next != NULL); + c->prev = prev; + c->next = next; + prev->next = c; + next->prev = c; + } + + c->data = (void *)data; + c->col = col; + c->parent = r; + EINA_MAGIC_SET(c, EINA_MAGIC_MATRIXSPARSE_CELL); + r->last_used = c; + return c; +} + +static inline Eina_Bool +_eina_matrixsparse_cell_idx_add(Eina_Matrixsparse *m, + unsigned long row, + unsigned long col, + const void *data) +{ + Eina_Matrixsparse_Row *r = _eina_matrixsparse_row_idx_get(m, row); + if (!r) + r = _eina_matrixsparse_row_idx_add(m, row); + + if (!r) + return 0; + + if (_eina_matrixsparse_row_cell_idx_add(r, col, data)) + return 1; + + if (r->cols) + return 0; + + _eina_matrixsparse_row_unlink(r); + _eina_matrixsparse_row_free(r, m->free.func, m->free.user_data); + return 0; +} + +/*============================================================================* +* Iterators * +*============================================================================*/ +static Eina_Bool +_eina_matrixsparse_iterator_next(Eina_Matrixsparse_Iterator *it, void **data) +{ + EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it, EINA_FALSE); + + /* do not touch it->idx */ + + if (!it->ref.col) + return 0; + + *data = (Eina_Matrixsparse_Cell *)it->ref.col; + + it->ref.col = it->ref.col->next; + if (!it->ref.col) + { + it->ref.row = it->ref.row->next; + if (it->ref.row) + it->ref.col = it->ref.row->cols; + } + + return 1; +} + +static Eina_Matrixsparse * +_eina_matrixsparse_iterator_get_container(Eina_Matrixsparse_Iterator *it) +{ + EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it, NULL); + return (Eina_Matrixsparse *)it->m; +} + +static void +_eina_matrixsparse_iterator_free(Eina_Matrixsparse_Iterator *it) +{ + EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it); + EINA_MAGIC_SET(it, EINA_MAGIC_NONE); + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_NONE); + free(it); +} + +static Eina_Bool +_eina_matrixsparse_iterator_complete_next( + Eina_Matrixsparse_Iterator_Complete *it, + void **data) +{ + EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it, EINA_FALSE); + + if (it->idx.row >= it->m->size.rows) + return 0; + + if (it->dummy.col.data) + ERR("Last iterator call changed dummy cell!"); + + if ((it->ref.col) && + (it->ref.col->col == it->idx.col) && + (it->ref.row->row == it->idx.row)) + { + *data = (Eina_Matrixsparse_Cell *)it->ref.col; + it->ref.col = it->ref.col->next; + if (!it->ref.col) + { + it->ref.row = it->ref.row->next; + if (it->ref.row) + it->ref.col = it->ref.row->cols; + } + } + else + { + it->dummy.col.data = NULL; + it->dummy.col.col = it->idx.col; + it->dummy.row.row = it->idx.row; + *data = &it->dummy.col; + } + + it->idx.col++; + if (it->idx.col == it->m->size.cols) + { + it->idx.col = 0; + it->idx.row++; + } + + return 1; +} + +static Eina_Matrixsparse * +_eina_matrixsparse_iterator_complete_get_container( + Eina_Matrixsparse_Iterator_Complete *it) +{ + EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it, NULL); + return (Eina_Matrixsparse *)it->m; +} + +static void +_eina_matrixsparse_iterator_complete_free( + Eina_Matrixsparse_Iterator_Complete *it) +{ + EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it); + + if (it->dummy.col.data) + ERR("Last iterator call changed dummy cell!"); + + EINA_MAGIC_SET(it, EINA_MAGIC_NONE); + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_NONE); + free(it); +} + + +/** + * @endcond + */ + +/*============================================================================* +* Global * +*============================================================================*/ + +/** + * @internal + * @brief Initialize the matrixsparse module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the matrixsparse module of Eina. It is called by + * eina_init(). + * + * This function creates mempool to speed up matrix rows and cells + * management, using EINA_MEMPOOL environment variable if it is set to + * choose the memory pool type to use. + * + * @see eina_init() + */ +Eina_Bool +eina_matrixsparse_init(void) +{ + const char *choice, *tmp; + + _eina_matrixsparse_log_dom = eina_log_domain_register("eina_matrixsparse", + EINA_LOG_COLOR_DEFAULT); + if (_eina_matrixsparse_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_matrixsparse"); + return EINA_FALSE; + } + +#ifdef EINA_DEFAULT_MEMPOOL + choice = "pass_through"; +#else + choice = "chained_mempool"; +#endif + tmp = getenv("EINA_MEMPOOL"); + if (tmp && tmp[0]) + choice = tmp; + + _eina_matrixsparse_cell_mp = eina_mempool_add + (choice, + "matrixsparse_cell", + NULL, + sizeof (Eina_Matrixsparse_Cell), + 120); + if (!_eina_matrixsparse_cell_mp) + { + ERR( + "Mempool for matrixsparse_cell cannot be allocated in matrixsparse init."); + goto on_init_fail; + } + + _eina_matrixsparse_row_mp = eina_mempool_add + (choice, "matrixsparse_row", NULL, sizeof (Eina_Matrixsparse_Row), 120); + if (!_eina_matrixsparse_row_mp) + { + ERR( + "Mempool for matrixsparse_row cannot be allocated in matrixsparse init."); + goto on_init_fail; + } + +#define EMS(n) eina_magic_string_static_set(n, n ## _STR) + EMS(EINA_MAGIC_MATRIXSPARSE); + EMS(EINA_MAGIC_MATRIXSPARSE_ROW); + EMS(EINA_MAGIC_MATRIXSPARSE_CELL); + EMS(EINA_MAGIC_MATRIXSPARSE_ITERATOR); + EMS(EINA_MAGIC_MATRIXSPARSE_ROW_ACCESSOR); + EMS(EINA_MAGIC_MATRIXSPARSE_ROW_ITERATOR); + EMS(EINA_MAGIC_MATRIXSPARSE_CELL_ACCESSOR); + EMS(EINA_MAGIC_MATRIXSPARSE_CELL_ITERATOR); +#undef EMS + + return EINA_TRUE; + +on_init_fail: + eina_log_domain_unregister(_eina_matrixsparse_log_dom); + _eina_matrixsparse_log_dom = -1; + return EINA_FALSE; +} + +/** + * @internal + * @brief Shut down the matrixsparse module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the matrixsparse module set up by + * eina_matrixsparse_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_matrixsparse_shutdown(void) +{ + eina_mempool_del(_eina_matrixsparse_row_mp); + eina_mempool_del(_eina_matrixsparse_cell_mp); + + eina_log_domain_unregister(_eina_matrixsparse_log_dom); + _eina_matrixsparse_log_dom = -1; + return EINA_TRUE; +} + +/*============================================================================* +* API * +*============================================================================*/ + +EAPI Eina_Matrixsparse * +eina_matrixsparse_new(unsigned long rows, unsigned long cols, void (*free_func)( + void *user_data, + void *cell_data), const void *user_data) +{ + Eina_Matrixsparse *m; + + EINA_SAFETY_ON_FALSE_RETURN_VAL(rows > 0, NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL(cols > 0, NULL); + + m = malloc(sizeof(Eina_Matrixsparse)); + if (!m) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + EINA_MAGIC_SET(m, EINA_MAGIC_MATRIXSPARSE); + + m->rows = NULL; + m->last_row = NULL; + m->last_used = NULL; + + m->size.rows = rows; + m->size.cols = cols; + m->free.func = free_func; + m->free.user_data = (void *)user_data; + + eina_error_set(0); + return m; +} + +EAPI void +eina_matrixsparse_free(Eina_Matrixsparse *m) +{ + void (*free_func)(void *, void *); + void *user_data; + + Eina_Matrixsparse_Row *r; + EINA_MAGIC_CHECK_MATRIXSPARSE(m); + + free_func = m->free.func; + user_data = m->free.user_data; + + r = m->rows; + while (r) + { + Eina_Matrixsparse_Row *r_aux = r; + r = r->next; + _eina_matrixsparse_row_free(r_aux, free_func, user_data); + } + + EINA_MAGIC_SET(m, EINA_MAGIC_NONE); + free(m); +} + +EAPI void +eina_matrixsparse_size_get(const Eina_Matrixsparse *m, + unsigned long *rows, + unsigned long *cols) +{ + if (rows) + *rows = 0; + + if (cols) + *cols = 0; + + EINA_MAGIC_CHECK_MATRIXSPARSE(m); + if (rows) + *rows = m->size.rows; + + if (cols) + *cols = m->size.cols; +} + +EAPI Eina_Bool +eina_matrixsparse_size_set(Eina_Matrixsparse *m, + unsigned long rows, + unsigned long cols) +{ + Eina_Bool update_last_used_row; + Eina_Matrixsparse_Row *r; + void (*free_func)(void *, void *); + void *user_data; + + EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0); + EINA_SAFETY_ON_FALSE_RETURN_VAL(rows > 0, 0); + EINA_SAFETY_ON_FALSE_RETURN_VAL(cols > 0, 0); + + if ((rows == m->size.rows) && (cols == m->size.cols)) + return 1; + + update_last_used_row = ((m->last_used) && (m->last_used->row >= rows)); + free_func = m->free.func; + user_data = m->free.user_data; + + r = m->last_row; + while (r && r->row >= rows) + { + Eina_Matrixsparse_Row *r_aux = r; + r = r->prev; + _eina_matrixsparse_row_free(r_aux, free_func, user_data); + } + if (!r) + { + m->last_row = NULL; + m->rows = NULL; + } + else if (r != m->last_row) + { + r->next = NULL; + m->last_row = r; + } + + if (update_last_used_row) + m->last_used = m->last_row; + + r = m->rows; + while (r) + { + Eina_Matrixsparse_Cell *c = r->last_col; + Eina_Bool update_last_used_col; + update_last_used_col = ((r->last_used) && (r->last_used->col >= cols)); + while (c && c->col >= cols) + { + Eina_Matrixsparse_Cell *c_aux = c; + c = c->prev; + _eina_matrixsparse_cell_free(c_aux, free_func, user_data); + } + if (!c) + { + Eina_Matrixsparse_Row *r_aux = r; + r->cols = NULL; + r->last_col = NULL; + if (r->next) + r->next->prev = r->prev; + else + m->last_row = r->prev; + + if (r->prev) + r->prev->next = r->next; + else + m->rows = r->next; + + r = r->next; + _eina_matrixsparse_row_free(r_aux, free_func, user_data); + } + else + { + if (c != r->last_col) + { + c->next = NULL; + r->last_col = c; + } + + if (update_last_used_col) + r->last_used = r->last_col; + + r = r->next; + } + } + + update_last_used_row = 0; + if (m->last_used) + { + if (m->last_row) + update_last_used_row = m->last_used->row > m->last_row->row; + else + update_last_used_row = 1; + } + + if (update_last_used_row) + m->last_used = m->last_row; + + m->size.rows = rows; + m->size.cols = cols; + return 1; +} + +EAPI Eina_Bool +eina_matrixsparse_cell_idx_get(const Eina_Matrixsparse *m, + unsigned long row, + unsigned long col, + Eina_Matrixsparse_Cell **cell) +{ + EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0); + EINA_SAFETY_ON_NULL_RETURN_VAL(cell, 0); + *cell = NULL; + EINA_SAFETY_ON_FALSE_RETURN_VAL(row < m->size.rows, 0); + EINA_SAFETY_ON_FALSE_RETURN_VAL(col < m->size.cols, 0); + *cell = _eina_matrixsparse_cell_idx_get(m, row, col); + return 1; +} + +EAPI void * +eina_matrixsparse_cell_data_get(const Eina_Matrixsparse_Cell *cell) +{ + EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(cell, NULL); + return cell->data; +} + +EAPI void * +eina_matrixsparse_data_idx_get(const Eina_Matrixsparse *m, + unsigned long row, + unsigned long col) +{ + Eina_Matrixsparse_Cell *c; + EINA_MAGIC_CHECK_MATRIXSPARSE(m, NULL); + c = _eina_matrixsparse_cell_idx_get(m, row, col); + if (c) + return c->data; + else + return NULL; +} + +EAPI Eina_Bool +eina_matrixsparse_cell_position_get(const Eina_Matrixsparse_Cell *cell, + unsigned long *row, + unsigned long *col) +{ + if (row) + *row = 0; + + if (col) + *col = 0; + + EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(cell, 0); + EINA_MAGIC_CHECK_MATRIXSPARSE_ROW(cell->parent, 0); + if (row) + *row = cell->parent->row; + + if (col) + *col = cell->col; + + return 1; +} + +EAPI Eina_Bool +eina_matrixsparse_cell_data_replace(Eina_Matrixsparse_Cell *cell, + const void *data, + void **p_old) +{ + if (p_old) + *p_old = NULL; + + EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(cell, 0); + + if (p_old) + *p_old = cell->data; + + cell->data = (void *)data; + return 1; +} + +EAPI Eina_Bool +eina_matrixsparse_cell_data_set(Eina_Matrixsparse_Cell *cell, const void *data) +{ + Eina_Matrixsparse *m; + + EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(cell, 0); + EINA_MAGIC_CHECK_MATRIXSPARSE_ROW(cell->parent, 0); + EINA_MAGIC_CHECK_MATRIXSPARSE(cell->parent->parent, 0); + + m = cell->parent->parent; + + if (m->free.func) + m->free.func(m->free.user_data, cell->data); + + cell->data = (void *)data; + return 1; +} + +EAPI Eina_Bool +eina_matrixsparse_data_idx_replace(Eina_Matrixsparse *m, + unsigned long row, + unsigned long col, + const void *data, + void **p_old) +{ + Eina_Matrixsparse_Cell *cell; + + if (p_old) + *p_old = NULL; + + EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0); + EINA_SAFETY_ON_FALSE_RETURN_VAL(row < m->size.rows, 0); + EINA_SAFETY_ON_FALSE_RETURN_VAL(col < m->size.cols, 0); + + cell = _eina_matrixsparse_cell_idx_get(m, row, col); + if (cell) + { + if (p_old) + *p_old = cell->data; + + cell->data = (void *)data; + return 1; + } + + return _eina_matrixsparse_cell_idx_add(m, row, col, data); +} + +EAPI Eina_Bool +eina_matrixsparse_data_idx_set(Eina_Matrixsparse *m, + unsigned long row, + unsigned long col, + const void *data) +{ + Eina_Matrixsparse_Cell *cell; + + EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0); + EINA_SAFETY_ON_FALSE_RETURN_VAL(row < m->size.rows, 0); + EINA_SAFETY_ON_FALSE_RETURN_VAL(col < m->size.cols, 0); + + cell = _eina_matrixsparse_cell_idx_get(m, row, col); + if (cell) + { + if (m->free.func) + m->free.func(m->free.user_data, cell->data); + + cell->data = (void *)data; + return 1; + } + + return _eina_matrixsparse_cell_idx_add(m, row, col, data); +} + +EAPI Eina_Bool +eina_matrixsparse_row_idx_clear(Eina_Matrixsparse *m, unsigned long row) +{ + Eina_Matrixsparse_Row *r; + + EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0); + EINA_SAFETY_ON_FALSE_RETURN_VAL(row < m->size.rows, 0); + + r = _eina_matrixsparse_row_idx_get(m, row); + if (!r) + return 1; + + _eina_matrixsparse_row_unlink(r); + _eina_matrixsparse_row_free(r, m->free.func, m->free.user_data); + + return 1; +} + +EAPI Eina_Bool +eina_matrixsparse_column_idx_clear(Eina_Matrixsparse *m, unsigned long col) +{ + Eina_Matrixsparse_Row *r; + void (*free_func)(void *, void *); + void *user_data; + + EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0); + EINA_SAFETY_ON_FALSE_RETURN_VAL(col < m->size.cols, 0); + + free_func = m->free.func; + user_data = m->free.user_data; + + for (r = m->rows; r; ) + { + Eina_Matrixsparse_Row *r_aux = r; + Eina_Matrixsparse_Cell *c; + + c = _eina_matrixsparse_row_cell_idx_get(r, col); + r = r->next; + + if (!c) + continue; + + if ((r_aux->cols != c) || (r_aux->last_col != c)) + { + _eina_matrixsparse_cell_unlink(c); + _eina_matrixsparse_cell_free(c, free_func, user_data); + } + else + { + _eina_matrixsparse_row_unlink(r_aux); + _eina_matrixsparse_row_free(r_aux, free_func, user_data); + } + } + + return 1; +} + +EAPI Eina_Bool +eina_matrixsparse_cell_idx_clear(Eina_Matrixsparse *m, + unsigned long row, + unsigned long col) +{ + Eina_Matrixsparse_Cell *c; + + EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0); + EINA_SAFETY_ON_FALSE_RETURN_VAL(row < m->size.rows, 0); + EINA_SAFETY_ON_FALSE_RETURN_VAL(col < m->size.cols, 0); + + c = _eina_matrixsparse_cell_idx_get(m, row, col); + if (!c) + return 1; + + _eina_matrixsparse_cell_unlink(c); + _eina_matrixsparse_cell_free(c, m->free.func, m->free.user_data); + + return 1; +} + +EAPI Eina_Bool +eina_matrixsparse_cell_clear(Eina_Matrixsparse_Cell *cell) +{ + Eina_Matrixsparse *m; + + EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(cell, 0); + EINA_MAGIC_CHECK_MATRIXSPARSE_ROW(cell->parent, 0); + EINA_MAGIC_CHECK_MATRIXSPARSE(cell->parent->parent, 0); + + m = cell->parent->parent; + + _eina_matrixsparse_cell_unlink(cell); + _eina_matrixsparse_cell_free(cell, m->free.func, m->free.user_data); + return 1; +} + +EAPI Eina_Iterator * +eina_matrixsparse_iterator_new(const Eina_Matrixsparse *m) +{ + Eina_Matrixsparse_Iterator *it; + + it = calloc(1, sizeof(*it)); + if (!it) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + EINA_MAGIC_SET(it, EINA_MAGIC_MATRIXSPARSE_ITERATOR); + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->m = m; + it->ref.row = m->rows; + it->ref.col = m->rows ? m->rows->cols : NULL; + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_eina_matrixsparse_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER( + _eina_matrixsparse_iterator_get_container); + it->iterator.free = FUNC_ITERATOR_FREE(_eina_matrixsparse_iterator_free); + return &it->iterator; +} + +EAPI Eina_Iterator * +eina_matrixsparse_iterator_complete_new(const Eina_Matrixsparse *m) +{ + Eina_Matrixsparse_Iterator_Complete *it; + + it = calloc(1, sizeof(*it)); + if (!it) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + EINA_MAGIC_SET(it, EINA_MAGIC_MATRIXSPARSE_ITERATOR); + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->m = m; + it->idx.row = 0; + it->idx.col = 0; + it->ref.row = m->rows; + it->ref.col = m->rows ? m->rows->cols : NULL; + + it->dummy.row.next = it->dummy.row.prev = NULL; + it->dummy.row.cols = it->dummy.row.last_col = it->dummy.row.last_used = NULL; + it->dummy.row.parent = (Eina_Matrixsparse *)m; + EINA_MAGIC_SET(&it->dummy.row, EINA_MAGIC_MATRIXSPARSE_ROW); + + it->dummy.col.next = it->dummy.col.prev = NULL; + it->dummy.col.data = NULL; + it->dummy.col.parent = &it->dummy.row; + EINA_MAGIC_SET(&it->dummy.col, EINA_MAGIC_MATRIXSPARSE_CELL); + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT( + _eina_matrixsparse_iterator_complete_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER( + _eina_matrixsparse_iterator_complete_get_container); + it->iterator.free = FUNC_ITERATOR_FREE( + _eina_matrixsparse_iterator_complete_free); + return &it->iterator; +} diff --git a/libraries/eina/src/lib/eina_mempool.c b/libraries/eina/src/lib/eina_mempool.c new file mode 100644 index 0000000..065532e --- /dev/null +++ b/libraries/eina/src/lib/eina_mempool.c @@ -0,0 +1,387 @@ +/* EINA - EFL data type library + * Copyright (C) 2007-2008 Jorge Luis Zapata Muga + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_hash.h" +#include "eina_module.h" +#include "eina_log.h" +#include "eina_main.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_mempool.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +static Eina_Hash *_backends; +static Eina_Array *_modules; +static int _eina_mempool_log_dom = -1; + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_eina_mempool_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_mempool_log_dom, __VA_ARGS__) + + +static Eina_Mempool * +_new_va(const char *name, + const char *context, + const char *options, + va_list args) +{ + Eina_Mempool_Backend *be; + Eina_Mempool *mp; + + Eina_Error err = EINA_ERROR_NOT_MEMPOOL_MODULE; + + eina_error_set(0); + be = eina_hash_find(_backends, name); + if ((!be) || (!be->init)) + goto on_error; + + err = EINA_ERROR_OUT_OF_MEMORY; + mp = calloc(1, sizeof(Eina_Mempool)); + if (!mp) + goto on_error; + + /* Work around ABI incompability introduced in Eina 1.1 */ +#define SBP(Property) mp->backend.Property = be->Property; + SBP(name); + SBP(init); + SBP(free); + SBP(alloc); + SBP(realloc); + SBP(garbage_collect); + SBP(statistics); + SBP(shutdown); +#undef SBP + + if (be->repack) + { + mp->backend2 = calloc(1, sizeof (Eina_Mempool_Backend_ABI2)); + if (mp->backend2) + mp->backend2->repack = be->repack; + } + + mp->backend_data = mp->backend.init(context, options, args); + + return mp; + +on_error: + eina_error_set(err); + return NULL; +} + +/* Built-in backend's prototypes */ + +#ifdef EINA_STATIC_BUILD_BUDDY +Eina_Bool buddy_init(void); +void buddy_shutdown(void); +#endif + +#ifdef EINA_STATIC_BUILD_CHAINED_POOL +Eina_Bool chained_init(void); +void chained_shutdown(void); +#endif + +#ifdef EINA_STATIC_BUILD_EMEMOA_FIXED +Eina_Bool ememoa_fixed_init(void); +void ememoa_fixed_shutdown(void); +#endif + +#ifdef EINA_STATIC_BUILD_EMEMOA_UNKNOWN +Eina_Bool ememoa_unknown_init(void); +void ememoa_unknown_shutdown(void); +#endif + +#ifdef EINA_STATIC_BUILD_FIXED_BITMAP +Eina_Bool fixed_bitmap_init(void); +void fixed_bitmap_shutdown(void); +#endif + +#ifdef EINA_STATIC_BUILD_ONE_BIG +Eina_Bool one_big_init(void); +void one_big_shutdown(void); +#endif + +#ifdef EINA_STATIC_BUILD_PASS_THROUGH +Eina_Bool pass_through_init(void); +void pass_through_shutdown(void); +#endif + +/** + * @endcond + */ + +/*============================================================================* +* Global * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +EAPI Eina_Error EINA_ERROR_NOT_MEMPOOL_MODULE = 0; + +static const char EINA_ERROR_NOT_MEMPOOL_MODULE_STR[] = + "Not a memory pool module."; + +/** + * @endcond + */ + +EAPI Eina_Bool +eina_mempool_register(Eina_Mempool_Backend *be) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(be, 0); + DBG("be=%p, name=%p", be, be->name); + return eina_hash_add(_backends, be->name, be); +} + +EAPI void +eina_mempool_unregister(Eina_Mempool_Backend *be) +{ + EINA_SAFETY_ON_NULL_RETURN(be); + DBG("be=%p, name=%p", be, be->name); + eina_hash_del(_backends, be->name, be); +} + +Eina_Bool +eina_mempool_init(void) +{ + char *path; + + _eina_mempool_log_dom = eina_log_domain_register("eina_mempool", + EINA_LOG_COLOR_DEFAULT); + if (_eina_mempool_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_mempool"); + return 0; + } + + EINA_ERROR_NOT_MEMPOOL_MODULE = eina_error_msg_static_register( + EINA_ERROR_NOT_MEMPOOL_MODULE_STR); + _backends = eina_hash_string_superfast_new(NULL); + + /* dynamic backends */ + _modules = eina_module_arch_list_get(NULL, + PACKAGE_LIB_DIR "/eina/modules/mp", + MODULE_ARCH); + + path = eina_module_environment_path_get("HOME", "/.eina/mp/modules/mp"); + _modules = eina_module_arch_list_get(_modules, path, MODULE_ARCH); + if (path) + free(path); + + path = eina_module_environment_path_get("EINA_MODULES_MEMPOOL_DIR", + "/eina/modules/mp"); + _modules = eina_module_arch_list_get(_modules, path, MODULE_ARCH); + if (path) + free(path); + + path = eina_module_symbol_path_get((const void *)eina_init, + "/eina/modules/mp"); + _modules = eina_module_arch_list_get(_modules, path, MODULE_ARCH); + if (path) + free(path); + + if (!_modules) + { + ERR("no mempool modules able to be loaded."); + eina_hash_free(_backends); + goto mempool_init_error; + } + + eina_module_list_load(_modules); + + /* builtin backends */ +#ifdef EINA_STATIC_BUILD_BUDDY + buddy_init(); +#endif +#ifdef EINA_STATIC_BUILD_CHAINED_POOL + chained_init(); +#endif +#ifdef EINA_STATIC_BUILD_EMEMOA_FIXED + ememoa_fixed_init(); +#endif +#ifdef EINA_STATIC_BUILD_EMEMOA_UNKNOWN + ememoa_unknown_init(); +#endif +#ifdef EINA_STATIC_BUILD_FIXED_BITMAP + fixed_bitmap_init(); +#endif +#ifdef EINA_STATIC_BUILD_ONE_BIG + one_big_init(); +#endif +#ifdef EINA_STATIC_BUILD_PASS_THROUGH + pass_through_init(); +#endif + + return EINA_TRUE; + +mempool_init_error: + eina_log_domain_unregister(_eina_mempool_log_dom); + _eina_mempool_log_dom = -1; + + return EINA_FALSE; +} + +Eina_Bool +eina_mempool_shutdown(void) +{ + /* builtin backends */ +#ifdef EINA_STATIC_BUILD_BUDDY + buddy_shutdown(); +#endif +#ifdef EINA_STATIC_BUILD_CHAINED_POOL + chained_shutdown(); +#endif +#ifdef EINA_STATIC_BUILD_EMEMOA_FIXED + ememoa_fixed_shutdown(); +#endif +#ifdef EINA_STATIC_BUILD_EMEMOA_UNKNOWN + ememoa_unknown_shutdown(); +#endif +#ifdef EINA_STATIC_BUILD_FIXED_BITMAP + fixed_bitmap_shutdown(); +#endif +#ifdef EINA_STATIC_BUILD_ONE_BIG + one_big_shutdown(); +#endif +#ifdef EINA_STATIC_BUILD_PASS_THROUGH + pass_through_shutdown(); +#endif + /* dynamic backends */ + eina_module_list_free(_modules); + if (_modules) + eina_array_free(_modules); + + if (_backends) + eina_hash_free(_backends); + + eina_log_domain_unregister(_eina_mempool_log_dom); + _eina_mempool_log_dom = -1; + + return EINA_TRUE; +} + +/*============================================================================* +* API * +*============================================================================*/ + +EAPI Eina_Mempool * +eina_mempool_add(const char *name, + const char *context, + const char *options, + ...) +{ + Eina_Mempool *mp; + va_list args; + + EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL); + DBG("name=%s, context=%s, options=%s", + name, context ? context : "", options ? options : ""); + + va_start(args, options); + mp = _new_va(name, context, options, args); + va_end(args); + + DBG("name=%s, context=%s, options=%s, mp=%p", + name, context ? context : "", options ? options : "", mp); + + return mp; +} + +EAPI void eina_mempool_del(Eina_Mempool *mp) +{ + EINA_SAFETY_ON_NULL_RETURN(mp); + EINA_SAFETY_ON_NULL_RETURN(mp->backend.shutdown); + DBG("mp=%p", mp); + mp->backend.shutdown(mp->backend_data); + free(mp->backend2); + free(mp); +} + +EAPI void eina_mempool_repack(Eina_Mempool *mp, Eina_Mempool_Repack_Cb cb, void *data) +{ + EINA_SAFETY_ON_NULL_RETURN(mp); + EINA_SAFETY_ON_NULL_RETURN(mp->backend2); + EINA_SAFETY_ON_NULL_RETURN(mp->backend2->repack); + DBG("mp=%p", mp); + mp->backend2->repack(mp->backend_data, cb, data); +} + +EAPI void eina_mempool_gc(Eina_Mempool *mp) +{ + EINA_SAFETY_ON_NULL_RETURN(mp); + EINA_SAFETY_ON_NULL_RETURN(mp->backend.garbage_collect); + DBG("mp=%p", mp); + mp->backend.garbage_collect(mp->backend_data); +} + +EAPI void eina_mempool_statistics(Eina_Mempool *mp) +{ + EINA_SAFETY_ON_NULL_RETURN(mp); + EINA_SAFETY_ON_NULL_RETURN(mp->backend.statistics); + DBG("mp=%p", mp); + mp->backend.statistics(mp->backend_data); +} + +EAPI unsigned int +eina_mempool_alignof(unsigned int size) +{ + int align; + + if (size <= 2) + align = 2; + else if (size < 8) + align = 4; + else +#if __WORDSIZE == 32 + align = 8; + +#else + if (size < 16) + align = 8; + else + align = 16; +#endif + + return ((size / align) + 1) * align; +} diff --git a/libraries/eina/src/lib/eina_mmap.c b/libraries/eina/src/lib/eina_mmap.c new file mode 100644 index 0000000..fb27bd7 --- /dev/null +++ b/libraries/eina/src/lib/eina_mmap.c @@ -0,0 +1,185 @@ +/* EINA - EFL data type library + * Copyright (C) 2011 Carsten Haitzler + * + * 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_SIGINFO_T + +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_SIGINFO_H +# include +#endif + +#endif + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_log.h" +#include "eina_mmap.h" + +/*============================================================================* + * Local * + *============================================================================*/ + +static Eina_Bool mmap_safe = EINA_FALSE; +#ifdef HAVE_SIGINFO_T + +static int _eina_mmap_log_dom = -1; +static int _eina_mmap_zero_fd = -1; +static long _eina_mmap_pagesize = -1; + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_eina_mmap_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_mmap_log_dom, __VA_ARGS__) + +static void +_eina_mmap_safe_sigbus(int sig __UNUSED__, + siginfo_t *siginfo, + void *ptr __UNUSED__) +{ + unsigned char *addr = (unsigned char *)(siginfo->si_addr); + int perrno; + + /* save previous errno */ + perrno = errno; + /* if problems was an unaligned access - complain accordingly and abort */ + if (siginfo->si_code == BUS_ADRALN) + { + ERR("Unaligned memory access. SIGBUS!!!"); + errno = perrno; + abort(); + } + /* send this to stderr - not eina_log. Specifically want this on stderr */ + fprintf(stderr, + "EINA: Data at address 0x%lx is invalid. Replacing with zero page.\n", + (unsigned long)addr); + /* align address to the lower page boundary */ + addr = (unsigned char *)((long)addr & (~(_eina_mmap_pagesize - 1))); + /* mmap a pzge of zero's from /dev/zero in there */ + if (mmap(addr, _eina_mmap_pagesize, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_FIXED, + _eina_mmap_zero_fd, 0) == MAP_FAILED) + { + /* mmap of /dev/zero failed :( */ + perror("mmap"); + ERR("Failed to mmap() /dev/zero in place of page. SIGBUS!!!"); + errno = perrno; + abort(); + } + /* restore previous errno */ + errno = perrno; +} +#endif + +/*============================================================================* + * API * + *============================================================================*/ + +EAPI Eina_Bool +eina_mmap_safety_enabled_set(Eina_Bool enabled) +{ +#ifndef HAVE_SIGINFO_T + (void) enabled; + return EINA_FALSE; +#else + if (_eina_mmap_log_dom < 0) + { + _eina_mmap_log_dom = eina_log_domain_register("eina_mmap", + EINA_LOG_COLOR_DEFAULT); + if (_eina_mmap_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_mmap"); + return EINA_FALSE; + } + } + + enabled = !!enabled; + + if (mmap_safe == enabled) return mmap_safe; + if (enabled) + { + struct sigaction sa; + + /* find out system page size the cleanest way we can */ +#ifdef _SC_PAGESIZE + _eina_mmap_pagesize = sysconf(_SC_PAGESIZE); + if (_eina_mmap_pagesize <= 0) return EINA_FALSE; +#else + _eina_mmap_pagesize = 4096; +#endif + /* no zero page device - open it */ + if (_eina_mmap_zero_fd < 0) + { + _eina_mmap_zero_fd = open("/dev/zero", O_RDWR); + /* if we don;'t have one - fail to set up mmap safety */ + if (_eina_mmap_zero_fd < 0) return EINA_FALSE; + } + /* set up signal handler for SIGBUS */ + sa.sa_sigaction = _eina_mmap_safe_sigbus; + sa.sa_flags = SA_RESTART | SA_SIGINFO; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGBUS, &sa, NULL) == 0) return EINA_FALSE; + /* setup of SIGBUS handler failed, lets close zero page dev and fail */ + close(_eina_mmap_zero_fd); + _eina_mmap_zero_fd = -1; + return EINA_FALSE; + } + else + { + /* reset signal handler to default for SIGBUS */ + signal(SIGBUS, SIG_DFL); + } + mmap_safe = enabled; + return mmap_safe; +#endif +} + +EAPI Eina_Bool +eina_mmap_safety_enabled_get(void) +{ + return mmap_safe; +} diff --git a/libraries/eina/src/lib/eina_module.c b/libraries/eina/src/lib/eina_module.c new file mode 100644 index 0000000..0dd19a6 --- /dev/null +++ b/libraries/eina/src/lib/eina_module.c @@ -0,0 +1,599 @@ +/* EINA - EFL data type library + * Copyright (C) 2007-2008 Jorge Luis Zapata Muga, Cedric BAIL + * + * 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 +#include + +#ifdef HAVE_LIBGEN_H +# include +#endif + +#ifdef HAVE_DLOPEN +# include +#endif + +#ifdef HAVE_EVIL +# include +#endif + +#ifdef HAVE_ESCAPE +# include +#endif + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_error.h" +#include "eina_file.h" +#include "eina_log.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_module.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +static int EINA_MODULE_LOG_DOM = -1; +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(EINA_MODULE_LOG_DOM, __VA_ARGS__) + +#ifdef WRN +#undef WRN +#endif +#define WRN(...) EINA_LOG_DOM_WARN(EINA_MODULE_LOG_DOM, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(EINA_MODULE_LOG_DOM, __VA_ARGS__) + +#ifdef _WIN32 +# define SEP_C '\\' +# define SEP_S "\\" +#else +# define SEP_C '/' +# define SEP_S "/" +#endif + +#define EINA_MODULE_SYMBOL_INIT "__eina_module_init" +#define EINA_MODULE_SYMBOL_SHUTDOWN "__eina_module_shutdown" + +struct _Eina_Module +{ + void *handle; + int ref; + const char file[]; +}; + +typedef struct _Dir_List_Get_Cb_Data +{ + Eina_Module_Cb cb; + void *data; + Eina_Array *array; +} Dir_List_Get_Cb_Data; + +typedef struct _Dir_List_Cb_Data +{ + Eina_Module_Cb cb; + void *data; +} Dir_List_Cb_Data; + +static Eina_Bool _dir_list_get_cb(Eina_Module *m, void *data) +{ + Dir_List_Get_Cb_Data *cb_data = data; + Eina_Bool ret = EINA_TRUE; + + if (cb_data->cb) + ret = cb_data->cb(m, cb_data->data); + + if (ret) + eina_array_push(cb_data->array, m); + + return ret; +} + +static void _dir_list_cb(const char *name, const char *path, void *data) +{ + Dir_List_Cb_Data *cb_data = data; + size_t length; + + length = strlen(name); + if (length < sizeof(SHARED_LIB_SUFFIX)) /* x.so */ + return; + + if (!strcmp(name + length - sizeof(SHARED_LIB_SUFFIX) + 1, + SHARED_LIB_SUFFIX)) + { + char *file; + Eina_Module *m; + + length = strlen(path) + strlen(name) + 2; + + file = alloca(sizeof (char) * length); + + snprintf(file, length, "%s" SEP_S "%s", path, name); + m = eina_module_new(file); + if (!m) + { + return; /* call the user provided cb on this module */ + + } + + if (!cb_data->cb(m, cb_data->data)) + eina_module_free(m); + } +} + +static void _dir_arch_list_cb(const char *name, const char *path, void *data) +{ + Dir_List_Get_Cb_Data *cb_data = data; + Eina_Module *m; + char *file = NULL; + size_t length; + + length = strlen(path) + 1 + strlen(name) + 1 + + strlen((char *)(cb_data->data)) + 1 + sizeof("module") + + sizeof(SHARED_LIB_SUFFIX) + 1; + + file = alloca(length); + snprintf(file, length, "%s" SEP_S "%s" SEP_S "%s" SEP_S "module" SHARED_LIB_SUFFIX, + path, name, (char *)(cb_data->data)); + m = eina_module_new(file); + if (!m) + return; + + eina_array_push(cb_data->array, m); +} + +/** + * @endcond + */ + + +/*============================================================================* +* Global * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +static const char EINA_ERROR_WRONG_MODULE_STR[] = + "Wrong file format or no file module found"; +static const char EINA_ERROR_MODULE_INIT_FAILED_STR[] = + "Module initialisation function failed"; + +EAPI Eina_Error EINA_ERROR_WRONG_MODULE = 0; +EAPI Eina_Error EINA_ERROR_MODULE_INIT_FAILED = 0; + +/** + * @endcond + */ + +/** + * @internal + * @brief Initialize the module loader module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the module loader module of Eina. It is + * called by eina_init(). + * + * This function sets up the module module of Eina. It also registers + * the errors #EINA_ERROR_WRONG_MODULE and + * #EINA_ERROR_MODULE_INIT_FAILED. + * + * @see eina_init() + */ +Eina_Bool +eina_module_init(void) +{ + EINA_MODULE_LOG_DOM = eina_log_domain_register + ("eina_module", EINA_LOG_COLOR_DEFAULT); + if (EINA_MODULE_LOG_DOM < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_module"); + return EINA_FALSE; + } + +#define EEMR(n) n = eina_error_msg_static_register(n ## _STR) + EEMR(EINA_ERROR_WRONG_MODULE); + EEMR(EINA_ERROR_MODULE_INIT_FAILED); +#undef EEMR + + return EINA_TRUE; +} + +/** + * @internal + * @brief Shut down the module loader module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the module loader module set up by + * eina_module_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_module_shutdown(void) +{ + /* TODO should we store every module when "new" is called and + * delete the list of modules here + */ + + eina_log_domain_unregister(EINA_MODULE_LOG_DOM); + EINA_MODULE_LOG_DOM = -1; + return EINA_TRUE; +} + +/*============================================================================* +* API * +*============================================================================*/ + +EAPI Eina_Module *eina_module_new(const char *file) +{ + Eina_Module *m; + size_t len; + + EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); + /* TODO check that the file exists. Update doc too */ + + len = strlen(file); + EINA_SAFETY_ON_FALSE_RETURN_VAL(len > 0, NULL); + + m = malloc(sizeof(Eina_Module) + len + 1); + if (!m) + { + ERR("could not malloc(%lu)", + (unsigned long)(sizeof(Eina_Module) + len + 1)); + return NULL; + } + + memcpy((char *)m->file, file, len + 1); + m->ref = 0; + m->handle = NULL; + DBG("m=%p, file=%s", m, file); + + return m; +} + +EAPI Eina_Bool eina_module_free(Eina_Module *m) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE); + + DBG("m=%p, handle=%p, file=%s, refs=%d", m, m->handle, m->file, m->ref); + + if (m->handle) + if (eina_module_unload(m) == EINA_FALSE) + return EINA_FALSE; + + free(m); + return EINA_TRUE; +} + +EAPI Eina_Bool eina_module_load(Eina_Module *m) +{ +#ifdef HAVE_DLOPEN + void *dl_handle; + Eina_Module_Init *initcall; + + EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE); + + DBG("m=%p, handle=%p, file=%s, refs=%d", m, m->handle, m->file, m->ref); + + if (m->handle) + goto loaded; + + dl_handle = dlopen(m->file, RTLD_NOW); + if (!dl_handle) + { + WRN("could not dlopen(\"%s\", RTLD_NOW): %s", m->file, dlerror()); + eina_error_set(EINA_ERROR_WRONG_MODULE); + return EINA_FALSE; + } + + initcall = dlsym(dl_handle, EINA_MODULE_SYMBOL_INIT); + if ((!initcall) || (!(*initcall))) + goto ok; + + if ((*initcall)() == EINA_TRUE) + goto ok; + + WRN("could not find eina's entry symbol %s inside module %s", + EINA_MODULE_SYMBOL_INIT, m->file); + eina_error_set(EINA_ERROR_MODULE_INIT_FAILED); + dlclose(dl_handle); + return EINA_FALSE; +ok: + DBG("successfully loaded %s", m->file); + m->handle = dl_handle; +loaded: + m->ref++; + DBG("ref %d", m->ref); + + eina_error_set(0); + return EINA_TRUE; +#else + (void) m; + return EINA_FALSE; +#endif +} + +EAPI Eina_Bool eina_module_unload(Eina_Module *m) +{ +#ifdef HAVE_DLOPEN + Eina_Module_Shutdown *shut; + EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE); + + DBG("m=%p, handle=%p, file=%s, refs=%d", m, m->handle, m->file, m->ref); + + m->ref--; + if (!m->ref) + { + shut = dlsym(m->handle, EINA_MODULE_SYMBOL_SHUTDOWN); + if ((shut) && (*shut)) + (*shut)(); + + dlclose(m->handle); + m->handle = NULL; + DBG("unloaded module %s", m->file); + return EINA_TRUE; + } + + return EINA_FALSE; +#else + (void) m; + return EINA_FALSE; +#endif +} + +EAPI void *eina_module_symbol_get(const Eina_Module *m, const char *symbol) +{ +#ifdef HAVE_DLOPEN + EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(m->handle, NULL); + return dlsym(m->handle, symbol); +#else + (void) m; + (void) symbol; + return NULL; +#endif +} + +EAPI const char *eina_module_file_get(const Eina_Module *m) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL); + return m->file; +} + +EAPI char *eina_module_symbol_path_get(const void *symbol, const char *sub_dir) +{ +#ifdef HAVE_DLADDR + Dl_info eina_dl; + + EINA_SAFETY_ON_NULL_RETURN_VAL(symbol, NULL); + + if (dladdr(symbol, &eina_dl)) + { + char *pos = strrchr(eina_dl.dli_fname, SEP_C); + if (pos) + { + char *path; + int l0; + int l1; + int l2 = 0; + + l0 = strlen(eina_dl.dli_fname); + l1 = strlen(pos); + if (sub_dir && (*sub_dir != '\0')) + l2 = strlen(sub_dir); + + path = malloc(l0 - l1 + l2 + 1); + if (path) + { + memcpy(path, eina_dl.dli_fname, l0 - l1); + if (sub_dir && (*sub_dir != '\0')) + memcpy(path + l0 - l1, sub_dir, l2); + + path[l0 - l1 + l2] = '\0'; + return path; + } + } + } +#else + (void) symbol; + (void) sub_dir; +#endif /* ! HAVE_DLADDR */ + + return NULL; +} + +EAPI char *eina_module_environment_path_get(const char *env, + const char *sub_dir) +{ + const char *env_dir; + + EINA_SAFETY_ON_NULL_RETURN_VAL(env, NULL); + + env_dir = getenv(env); + if (env_dir) + { + char *path; + size_t l1; + size_t l2 = 0; + + l1 = strlen(env_dir); + if (sub_dir && (*sub_dir != '\0')) + l2 = strlen(sub_dir); + + path = (char *)malloc(l1 + l2 + 1); + if (path) + { + memcpy(path, env_dir, l1); + if (sub_dir && (*sub_dir != '\0')) + memcpy(path + l1, sub_dir, l2); + + path[l1 + l2] = '\0'; + + return path; + } + } + + return NULL; +} + +EAPI Eina_Array *eina_module_arch_list_get(Eina_Array *array, + const char *path, + const char *arch) +{ + Dir_List_Get_Cb_Data list_get_cb_data; + + if ((!path) || (!arch)) + return array; + + list_get_cb_data.array = array ? array : eina_array_new(4); + list_get_cb_data.cb = NULL; + list_get_cb_data.data = (void *)arch; + + eina_file_dir_list(path, 0, &_dir_arch_list_cb, &list_get_cb_data); + + return list_get_cb_data.array; +} + +EAPI Eina_Array *eina_module_list_get(Eina_Array *array, + const char *path, + Eina_Bool recursive, + Eina_Module_Cb cb, + void *data) +{ + Dir_List_Get_Cb_Data list_get_cb_data; + Dir_List_Cb_Data list_cb_data; + + if (!path) + return array; + + list_get_cb_data.array = array ? array : eina_array_new(4); + list_get_cb_data.cb = cb; + list_get_cb_data.data = data; + + list_cb_data.cb = &_dir_list_get_cb; + list_cb_data.data = &list_get_cb_data; + + eina_file_dir_list(path, recursive, &_dir_list_cb, &list_cb_data); + + return list_get_cb_data.array; +} + +EAPI Eina_Module * +eina_module_find(const Eina_Array *array, const char *module) +{ + unsigned int i; + Eina_Array_Iterator iterator; + Eina_Module *m; + + EINA_ARRAY_ITER_NEXT(array, i, m, iterator) + { + char *file_m; + char *tmp; + ssize_t len; + + /* basename() can modify its argument, so we first get a copie */ + /* do not use strdupa, as opensolaris does not have it */ + len = strlen(eina_module_file_get(m)); + tmp = alloca(len + 1); + memcpy(tmp, eina_module_file_get(m), len + 1); + file_m = basename(tmp); + len = strlen(file_m); + len -= sizeof(SHARED_LIB_SUFFIX) - 1; + if (len <= 0) + continue; + + if (!strncmp(module, file_m, len)) + return m;; + } + + return NULL; +} + +EAPI void eina_module_list_load(Eina_Array *array) +{ + Eina_Array_Iterator iterator; + Eina_Module *m; + unsigned int i; + + EINA_SAFETY_ON_NULL_RETURN(array); + DBG("array %p, count %u", array, array->count); + EINA_ARRAY_ITER_NEXT(array, i, m, iterator) + eina_module_load(m); +} + +EAPI void eina_module_list_unload(Eina_Array *array) +{ + Eina_Array_Iterator iterator; + Eina_Module *m; + unsigned int i; + + EINA_SAFETY_ON_NULL_RETURN(array); + DBG("array %p, count %u", array, array->count); + EINA_ARRAY_ITER_NEXT(array, i, m, iterator) + eina_module_unload(m); +} + +EAPI void eina_module_list_free(Eina_Array *array) +{ + Eina_Array_Iterator iterator; + Eina_Module *m; + unsigned int i; + + EINA_SAFETY_ON_NULL_RETURN(array); + DBG("array %p, count %u", array, array->count); + EINA_ARRAY_ITER_NEXT(array, i, m, iterator) + eina_module_free(m); + + eina_array_flush(array); +} diff --git a/libraries/eina/src/lib/eina_prefix.c b/libraries/eina/src/lib/eina_prefix.c new file mode 100644 index 0000000..9445222 --- /dev/null +++ b/libraries/eina/src/lib/eina_prefix.c @@ -0,0 +1,727 @@ +/* EINA - EFL data type library + * Copyright (C) 2011 Carsten Haitzler + * + * 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 STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#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 +# ifdef __cplusplus +extern "C" +# endif +void *alloca (size_t); +# endif +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef HAVE_DLADDR +# include +#endif + +#ifdef HAVE_EVIL +# include +#endif + +#ifdef HAVE_ESCAPE +# include +#endif + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_log.h" +#include "eina_prefix.h" + +#ifdef _WIN32 +# define PSEP_C ';' +# define DSEP_C '\\' +# define DSEP_S "\\" +#else +# define PSEP_C ':' +# define DSEP_C '/' +# define DSEP_S "/" +#endif /* _WIN32 */ + +/*============================================================================* + * Local * + *============================================================================*/ + +/** + * @cond LOCAL + */ + +struct _Eina_Prefix +{ + char *exe_path; + + char *prefix_path; + char *prefix_path_bin; + char *prefix_path_data; + char *prefix_path_lib; + char *prefix_path_locale; + + unsigned char fallback : 1; + unsigned char no_common_prefix : 1; + unsigned char env_used : 1; +}; + +#define STRDUP_REP(x, y) do { if (x) free(x); x = strdup(y); } while (0) +#define IF_FREE_NULL(p) do { if (p) { free(p); p = NULL; } } while (0) + +#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_prefix_log_dom, __VA_ARGS__) + +#ifdef WRN +#undef WRN +#endif +#define WRN(...) EINA_LOG_DOM_WARN(_eina_prefix_log_dom, __VA_ARGS__) + +#ifdef INF +#undef INF +#endif +#define INF(...) EINA_LOG_DOM_INFO(_eina_prefix_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_prefix_log_dom, __VA_ARGS__) + +static int _eina_prefix_log_dom = -1; + +static int +_fallback(Eina_Prefix *pfx, const char *pkg_bin, const char *pkg_lib, + const char *pkg_data, const char *pkg_locale, const char *envprefix) +{ + char *p; + + STRDUP_REP(pfx->prefix_path, pkg_bin); + if (!pfx->prefix_path) return 0; + p = strrchr(pfx->prefix_path, DSEP_C); + if (p) *p = 0; + STRDUP_REP(pfx->prefix_path_bin, pkg_bin); + STRDUP_REP(pfx->prefix_path_lib, pkg_lib); + STRDUP_REP(pfx->prefix_path_data, pkg_data); + STRDUP_REP(pfx->prefix_path_locale, pkg_locale); + fprintf(stderr, + "WARNING: Could not determine its installed prefix for '%s'\n" + " so am falling back on the compiled in default:\n" + " %s\n" + " implied by the following:\n" + " bindir = %s\n" + " libdir = %s\n" + " datadir = %s\n" + " localedir = %s\n" + " Try setting the following environment variables:\n" + " %s_PREFIX - points to the base prefix of install\n" + " or the next 4 variables\n" + " %s_BIN_DIR - provide a specific binary directory\n" + " %s_LIB_DIR - provide a specific library directory\n" + " %s_DATA_DIR - provide a specific data directory\n" + " %s_LOCALE_DIR - provide a specific locale directory\n" + , envprefix, + pfx->prefix_path, pkg_bin, pkg_lib, pkg_data, pkg_locale, + envprefix, envprefix, envprefix, envprefix, envprefix); + pfx->fallback = 1; + return 1; +} + +#ifndef _WIN32 +static int +_try_proc(Eina_Prefix *pfx, void *symbol) +{ + FILE *f; + char buf[4096]; + + DBG("Try /proc/self/maps"); + f = fopen("/proc/self/maps", "rb"); + if (!f) return 0; + DBG("Exists /proc/self/maps"); + while (fgets(buf, sizeof(buf), f)) + { + int len; + char *p, mode[5] = ""; + unsigned long ptr1 = 0, ptr2 = 0; + + len = strlen(buf); + if (buf[len - 1] == '\n') + { + buf[len - 1] = 0; + len--; + } + if (sscanf(buf, "%lx-%lx %4s", &ptr1, &ptr2, mode) == 3) + { + if (!strcmp(mode, "r-xp")) + { + if (((void *)ptr1 <= symbol) && (symbol < (void *)ptr2)) + { + DBG("Found in /proc/self/maps: %s", buf); + p = strchr(buf, '/'); + if (p) + { + DBG("Found in /proc/self/maps: found last /"); + if (len > 10) + { + if (!strcmp(buf + len - 10, " (deleted)")) + buf[len - 10] = 0; + } + STRDUP_REP(pfx->exe_path, p); + INF("Found in /proc/self/maps: guess exe path is %s", pfx->exe_path); + fclose(f); + return 1; + } + else break; + } + } + } + } + fclose(f); + WRN("Failed in /proc/self/maps"); + return 0; +} +#endif + +static int +_try_argv(Eina_Prefix *pfx, const char *argv0) +{ + char *path, *p, *cp, *s; + int len, lenexe; + char buf[PATH_MAX], buf2[PATH_MAX], buf3[PATH_MAX]; + + DBG("Try argv0 = %s", argv0); + /* 1. is argv0 abs path? */ +#ifdef _WIN32 + if (argv0[0] && (argv0[1] == ':')) +#else + if (argv0[0] == DSEP_C) +#endif + { + DBG("Match arvg0 is full path: %s", argv0); + STRDUP_REP(pfx->exe_path, argv0); + if (access(pfx->exe_path, X_OK) == 0) + { + INF("Executable argv0 = %s", argv0); + return 1; + } + IF_FREE_NULL(pfx->exe_path); + DBG("Non existent argv0: %s", argv0); + return 0; + } + /* 2. relative path */ + if (strchr(argv0, DSEP_C)) + { + DBG("Relative path argv0: %s", argv0); + if (getcwd(buf3, sizeof(buf3))) + { + snprintf(buf2, sizeof(buf2), "%s" DSEP_S "%s", buf3, argv0); + DBG("Relative to CWD: %s", buf2); + if (realpath(buf2, buf)) + { + DBG("Realpath is: %s", buf); + STRDUP_REP(pfx->exe_path, buf); + if (access(pfx->exe_path, X_OK) == 0) + { + INF("Path %s is executable", pfx->exe_path); + return 1; + } + DBG("Fail check for executable: %s", pfx->exe_path); + IF_FREE_NULL(pfx->exe_path); + } + } + } + /* 3. argv0 no path - look in PATH */ + DBG("Look for argv0=%s in $PATH", argv0); + path = getenv("PATH"); + if (!path) return 0; + p = path; + cp = p; + lenexe = strlen(argv0); + while ((p = strchr(cp, PSEP_C))) + { + len = p - cp; + s = malloc(len + 1 + lenexe + 1); + if (s) + { + strncpy(s, cp, len); + s[len] = DSEP_C; + strcpy(s + len + 1, argv0); + DBG("Try path: %s", s); + if (realpath(s, buf)) + { + DBG("Realpath is: %s", buf); + if (access(buf, X_OK) == 0) + { + STRDUP_REP(pfx->exe_path, buf); + INF("Path %s is executable", pfx->exe_path); + free(s); + return 1; + } + } + free(s); + } + cp = p + 1; + } + /* 4. big problems. arg[0] != executable - weird execution */ + return 0; +} + +static int +_get_env_var(char **var, const char *env, const char *prefix, const char *dir) +{ + char buf[PATH_MAX]; + const char *s = getenv(env); + + DBG("Try env var %s", env); + if (s) + { + INF("Have env %s = %s", env, s); + STRDUP_REP(*var, s); + return 1; + } + else if (prefix) + { + snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", prefix, dir); + INF("Have prefix %s = %s", prefix, buf); + STRDUP_REP(*var, buf); + return 1; + } + return 0; +} + +static int +_get_env_vars(Eina_Prefix *pfx, + const char *envprefix, + const char *bindir, + const char *libdir, + const char *datadir, + const char *localedir) +{ + char env[1024]; + const char *s; + int ret = 0; + + snprintf(env, sizeof(env), "%s_PREFIX", envprefix); + if ((s = getenv(env))) STRDUP_REP(pfx->prefix_path, s); + snprintf(env, sizeof(env), "%s_BIN_DIR", envprefix); + ret += _get_env_var(&pfx->prefix_path_bin, env, s, bindir); + snprintf(env, sizeof(env), "%s_LIB_DIR", envprefix); + ret += _get_env_var(&pfx->prefix_path_lib, env, s, libdir); + snprintf(env, sizeof(env), "%s_DATA_DIR", envprefix); + ret += _get_env_var(&pfx->prefix_path_data, env, s, datadir); + snprintf(env, sizeof(env), "%s_LOCALE_DIR", envprefix); + ret += _get_env_var(&pfx->prefix_path_locale, env, s, localedir); + return ret; +} + +/** + * @endcond + */ + + +/*============================================================================* + * Global * + *============================================================================*/ + + +/*============================================================================* + * API * + *============================================================================*/ + + +EAPI Eina_Prefix * +eina_prefix_new(const char *argv0, void *symbol, const char *envprefix, + const char *sharedir, const char *magicsharefile, + const char *pkg_bin, const char *pkg_lib, + const char *pkg_data, const char *pkg_locale) +{ + Eina_Prefix *pfx; + char *p, buf[4096], *tmp, *magic = NULL; + struct stat st; + const char *p1, *p2; + const char *pkg_bin_p = NULL; + const char *pkg_lib_p = NULL; + const char *pkg_data_p = NULL; + const char *pkg_locale_p = NULL; + const char *bindir = "bin"; + const char *libdir = "lib"; + const char *datadir = "share"; + const char *localedir = "share"; + + DBG("EINA PREFIX: argv0=%s, symbol=%p, magicsharefile=%s, envprefix=%s", + argv0, symbol, magicsharefile, envprefix); + pfx = calloc(1, sizeof(Eina_Prefix)); + if (!pfx) return NULL; + + /* if provided with a share dir use datadir/sharedir as the share dir */ + if (sharedir) + { + int len; + + len = snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", datadir, sharedir); + if (len > 0) + { +#ifdef _WIN32 + /* on win32 convert / to \ for path here */ + for (p = buf + strlen(datadir) + strlen(DSEP_S); *p; p++) + { + if (*p == '/') *p = DSEP_C; + } +#endif + tmp = alloca(len + 1); + strcpy(tmp, buf); + datadir = tmp; + } + } + if (magicsharefile) + { + magic = alloca(strlen(magicsharefile)); + strcpy(magic, magicsharefile); +#ifdef _WIN32 + /* on win32 convert / to \ for path here */ + for (p = magic; *p; p++) + { + if (*p == '/') *p = DSEP_C; + } +#endif + } + + /* look at compile-time package bin/lib/datadir etc. and figure out the + * bin, lib and data dirs from these, if possible. i.e. + * bin = /usr/local/bin + * lib = /usr/local/lib + * data = /usr/local/share/enlightenment + * thus they all have a common prefix string of /usr/local/ and + * bindir = bin + * libdir = lib + * datadir = share/enlightenment + * this addresses things like libdir is lib64 or lib32 or other such + * junk distributions like to do so then: + * bin = /usr/local/bin + * lib = /usr/local/lib64 + * data = /usr/local/share/enlightenment + * then + * bindir = bin + * libdir = lib64 + * datadir = share/enlightennment + * in theory this should also work with debians new multiarch style like + * bindir = bin + * libdir = lib/i386-linux-gnu + * or + * libdir = lib/x86_64-linux-gnu + * all with a common prefix that can be relocated + */ + /* 1. check last common char in bin and lib strings */ + for (p1 = pkg_bin, p2 = pkg_lib; *p1 && *p2; p1++, p2++) + { + if (*p1 != *p2) + { + pkg_bin_p = p1; + pkg_lib_p = p2; + break; + } + } + /* 1. check last common char in bin and data strings */ + for (p1 = pkg_bin, p2 = pkg_data; *p1 && *p2; p1++, p2++) + { + if (*p1 != *p2) + { + pkg_data_p = p2; + break; + } + } + /* 1. check last common char in bin and locale strings */ + for (p1 = pkg_bin, p2 = pkg_locale; *p1 && *p2; p1++, p2++) + { + if (*p1 != *p2) + { + pkg_locale_p = p2; + break; + } + } + /* 2. if all the common string offsets match we compiled with a common prefix */ + if (((pkg_bin_p - pkg_bin) == (pkg_lib_p - pkg_lib)) + && ((pkg_bin_p - pkg_bin) == (pkg_data_p - pkg_data)) + && ((pkg_bin_p - pkg_bin) == (pkg_locale_p - pkg_locale)) + ) + { + bindir = pkg_bin_p; + libdir = pkg_lib_p; + datadir = pkg_data_p; + localedir = pkg_locale_p; + DBG("Prefix relative bindir = %s", bindir); + DBG("Prefix relative libdir = %s", libdir); + DBG("Prefix relative datadir = %s", datadir); + DBG("Prefix relative localedir = %s", localedir); + } + /* 3. some galoot thought it awesome not to give us a common prefix at compile time + * so fall back to the compile time directories. we are no longer relocatable */ + else + { + STRDUP_REP(pfx->prefix_path_bin, pkg_bin); + STRDUP_REP(pfx->prefix_path_lib, pkg_lib); + STRDUP_REP(pfx->prefix_path_data, pkg_data); + STRDUP_REP(pfx->prefix_path_locale, pkg_locale); + pfx->no_common_prefix = 1; + DBG("Can't work out a common prefix - compiled in fallback"); + } + + /* if user provides env vars - then use that or also more specific sub + * dirs for bin, lib, data and locale */ + if ((envprefix) && + (_get_env_vars(pfx, envprefix, bindir, libdir, datadir, localedir) > 0)) + { + pfx->env_used = 1; + return pfx; + } + +#ifdef HAVE_DLADDR + DBG("Try dladdr on %p", symbol); + if (symbol) + { + Dl_info info_dl; + + if (dladdr(symbol, &info_dl)) + { + DBG("Dlinfo worked"); + if (info_dl.dli_fname) + { + DBG("Dlinfo dli_fname = %s", info_dl.dli_fname); +# ifdef _WIN32 + if (info_dl.dli_fname[0] && (info_dl.dli_fname[1] == ':')) +# else + if (info_dl.dli_fname[0] == DSEP_C) +# endif + { + INF("Dlsym gave full path = %s", info_dl.dli_fname); + STRDUP_REP(pfx->exe_path, info_dl.dli_fname); + } + } + } + } +#endif + /* no env var - examine process and possible argv0 */ + if ((argv0) && (!pfx->exe_path) && (symbol)) + { +#ifndef _WIN32 + if (!_try_proc(pfx, symbol)) + { +#endif + if (!_try_argv(pfx, argv0)) + { + _fallback(pfx, pkg_bin, pkg_lib, pkg_data, pkg_locale, + envprefix); + return pfx; + } +#ifndef _WIN32 + } +#endif + } + if (!pfx->exe_path) + { + WRN("Fallback - nothing found"); + _fallback(pfx, pkg_bin, pkg_lib, pkg_data, pkg_locale, envprefix); + return pfx; + } + /* _exe_path is now a full absolute path TO this exe - figure out rest */ + /* if + * exe = /blah/whatever/bin/exe + * or + * exe = /blah/whatever/lib/libexe.so + * then + * prefix = /blah/whatever + * bin_dir = /blah/whatever/bin + * data_dir = /blah/whatever/share/enlightenment + * lib_dir = /blah/whatever/lib + */ + DBG("From exe %s figure out the rest", pfx->exe_path); + p = strrchr(pfx->exe_path, DSEP_C); + if (p) + { + p--; + while (p >= pfx->exe_path) + { + if (*p == DSEP_C) + { + pfx->prefix_path = malloc(p - pfx->exe_path + 1); + if (pfx->prefix_path) + { + strncpy(pfx->prefix_path, pfx->exe_path, + p - pfx->exe_path); + pfx->prefix_path[p - pfx->exe_path] = 0; + DBG("Have prefix = %s", pfx->prefix_path); + + /* bin */ + snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", + pfx->prefix_path, bindir); + STRDUP_REP(pfx->prefix_path_bin, buf); + DBG("Have bin = %s", pfx->prefix_path_bin); + /* lib */ + snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", + pfx->prefix_path, libdir); + STRDUP_REP(pfx->prefix_path_lib, buf); + DBG("Have lib = %s", pfx->prefix_path_lib); + /* locale */ + snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", + pfx->prefix_path, localedir); + STRDUP_REP(pfx->prefix_path_locale, buf); + DBG("Have locale = %s", pfx->prefix_path_locale); + /* check if magic file is there - then our guess is right */ + if (magic) + { + DBG("Magic = %s", magic); + snprintf(buf, sizeof(buf), + "%s" DSEP_S "%s" DSEP_S "%s", + pfx->prefix_path, datadir, magic); + DBG("Check in %s", buf); + } + if ((!magic) || (stat(buf, &st) == 0)) + { + if (buf[0]) + DBG("Magic path %s stat passed", buf); + else + DBG("No magic file"); + snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", + pfx->prefix_path, datadir); + STRDUP_REP(pfx->prefix_path_data, buf); + } + /* magic file not there. time to start hunting! */ + else + { + WRN("Magic failed"); + _fallback(pfx, pkg_bin, pkg_lib, pkg_data, + pkg_locale, envprefix); + } + } + else + { + WRN("No Prefix path (alloc fail)"); + _fallback(pfx, pkg_bin, pkg_lib, pkg_data, pkg_locale, + envprefix); + } + return pfx; + } + p--; + } + } + WRN("Final fallback"); + _fallback(pfx, pkg_bin, pkg_lib, pkg_data, pkg_locale, envprefix); + return pfx; +} + +EAPI void +eina_prefix_free(Eina_Prefix *pfx) +{ + if (!pfx) return; + + IF_FREE_NULL(pfx->exe_path); + IF_FREE_NULL(pfx->prefix_path); + IF_FREE_NULL(pfx->prefix_path_bin); + IF_FREE_NULL(pfx->prefix_path_data); + IF_FREE_NULL(pfx->prefix_path_lib); + IF_FREE_NULL(pfx->prefix_path_locale); + free(pfx); +} + +EAPI const char * +eina_prefix_get(Eina_Prefix *pfx) +{ + if (!pfx) return ""; + return pfx->prefix_path; +} + +EAPI const char * +eina_prefix_bin_get(Eina_Prefix *pfx) +{ + if (!pfx) return ""; + return pfx->prefix_path_bin; +} + +EAPI const char * +eina_prefix_lib_get(Eina_Prefix *pfx) +{ + if (!pfx) return ""; + return pfx->prefix_path_lib; +} + +EAPI const char * +eina_prefix_data_get(Eina_Prefix *pfx) +{ + if (!pfx) return ""; + return pfx->prefix_path_data; +} + +EAPI const char * +eina_prefix_locale_get(Eina_Prefix *pfx) +{ + if (!pfx) return ""; + return pfx->prefix_path_locale; +} + +Eina_Bool +eina_prefix_init(void) +{ + _eina_prefix_log_dom = eina_log_domain_register("eina_prefix", + EINA_LOG_COLOR_DEFAULT); + if (_eina_prefix_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_prefix"); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +Eina_Bool +eina_prefix_shutdown(void) +{ + eina_log_domain_unregister(_eina_prefix_log_dom); + _eina_prefix_log_dom = -1; + return EINA_TRUE; +} diff --git a/libraries/eina/src/lib/eina_private.h b/libraries/eina/src/lib/eina_private.h new file mode 100644 index 0000000..d390397 --- /dev/null +++ b/libraries/eina/src/lib/eina_private.h @@ -0,0 +1,140 @@ +/* EINA - EFL data type library + * Copyright (C) 2008 Carsten Haitzler, Vincent Torri, Jorge Luis Zapata Muga + * + * 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 . + */ + +#ifndef EINA_PRIVATE_H_ +#define EINA_PRIVATE_H_ + +#include + +#include "eina_magic.h" +#include "eina_iterator.h" +#include "eina_accessor.h" + +#ifndef MIN +# define MIN(x, y) (((x) > (y)) ? (y) : (x)) +#endif + +#ifndef MAX +# define MAX(x, y) (((x) > (y)) ? (x) : (y)) +#endif + +#ifndef ABS +# define ABS(x) ((x) < 0 ? -(x) : (x)) +#endif + +#ifndef CLAMP +# define CLAMP(x, min, \ + max) (((x) > (max)) ? (max) : (((x) < (min)) ? (min) : (x))) +#endif + +#define EINA_INLIST_JUMP_SIZE 256 + +#define READBUFSIZ 65536 + +#define EINA_LOG_COLOR_DEFAULT "\033[36m" + +/* eina magic types */ +#define EINA_MAGIC_SHARE 0x98761234 +#define EINA_MAGIC_SHARE_HEAD 0x98761235 +#define EINA_MAGIC_STRINGSHARE_NODE 0x98761254 +#define EINA_MAGIC_USTRINGSHARE_NODE 0x98761255 +#define EINA_MAGIC_BINSHARE_NODE 0x98761256 + +#define EINA_MAGIC_LIST 0x98761237 +#define EINA_MAGIC_LIST_ITERATOR 0x98761238 +#define EINA_MAGIC_LIST_ACCESSOR 0x98761239 +#define EINA_MAGIC_LIST_ACCOUNTING 0x9876123a + +#define EINA_MAGIC_ARRAY 0x9876123b +#define EINA_MAGIC_ARRAY_ITERATOR 0x9876123c +#define EINA_MAGIC_ARRAY_ACCESSOR 0x9876123d + +#define EINA_MAGIC_HASH 0x9876123e +#define EINA_MAGIC_HASH_ITERATOR 0x9876123f + +#define EINA_MAGIC_TILER 0x98761240 +#define EINA_MAGIC_TILER_ITERATOR 0x98761241 + +#define EINA_MAGIC_MATRIXSPARSE 0x98761242 +#define EINA_MAGIC_MATRIXSPARSE_ROW 0x98761243 +#define EINA_MAGIC_MATRIXSPARSE_CELL 0x98761244 +#define EINA_MAGIC_MATRIXSPARSE_ITERATOR 0x98761245 +#define EINA_MAGIC_MATRIXSPARSE_ROW_ITERATOR 0x98761246 +#define EINA_MAGIC_MATRIXSPARSE_ROW_ACCESSOR 0x98761247 +#define EINA_MAGIC_MATRIXSPARSE_CELL_ITERATOR 0x98761248 +#define EINA_MAGIC_MATRIXSPARSE_CELL_ACCESSOR 0x98761249 + +#define EINA_MAGIC_STRBUF 0x98761250 +#define EINA_MAGIC_USTRBUF 0x98761257 +#define EINA_MAGIC_BINBUF 0x98761258 + +#define EINA_MAGIC_QUADTREE 0x98761251 +#define EINA_MAGIC_QUADTREE_ROOT 0x98761252 +#define EINA_MAGIC_QUADTREE_ITEM 0x98761253 + +#define EINA_MAGIC_SIMPLE_XML_TAG 0x98761260 +#define EINA_MAGIC_SIMPLE_XML_DATA 0x98761261 +#define EINA_MAGIC_SIMPLE_XML_ATTRIBUTE 0x98761262 + +#define EINA_MAGIC_CLASS 0x9877CB30 + +/* undef the following, we want out version */ +#undef FREE +#define FREE(ptr) \ + do { \ + free(ptr); \ + ptr = NULL; \ + } while(0); + +#undef IF_FREE +#define IF_FREE(ptr) \ + do { \ + if (ptr) { \ + free(ptr); \ + ptr = NULL; \ + } \ + } while(0); + +#undef IF_FN_DEL +#define IF_FN_DEL(_fn, ptr) \ + do { \ + if (ptr) { \ + _fn(ptr); \ + ptr = NULL; \ + } \ + } while(0); + +#define MAGIC_FREE(ptr) \ + do { \ + if (ptr) { \ + EINA_MAGIC_SET(ptr, EINA_MAGIC_NONE); \ + FREE(ptr); \ + } \ + } while(0); + +#ifdef EFL_HAVE_THREADS +extern Eina_Bool _threads_activated; + +void eina_share_common_threads_init(void); +void eina_share_common_threads_shutdown(void); +void eina_log_threads_init(void); +void eina_log_threads_shutdown(void); +#endif + +#endif /* EINA_PRIVATE_H_ */ + diff --git a/libraries/eina/src/lib/eina_quadtree.c b/libraries/eina/src/lib/eina_quadtree.c new file mode 100644 index 0000000..daf03d0 --- /dev/null +++ b/libraries/eina/src/lib/eina_quadtree.c @@ -0,0 +1,935 @@ +/* EINA - EFL data type library + * Copyright (C) 2010 Cedric Bail + * + * 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 . + */ + +/** + * @page tutorial_quadtree_page QuadTree Tutorial + * + * to be written... + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#ifdef HAVE_EVIL +# include +#endif + +#include "eina_quadtree.h" +#include "eina_magic.h" +#include "eina_mempool.h" +#include "eina_list.h" +#include "eina_inlist.h" +#include "eina_trash.h" +#include "eina_log.h" +#include "eina_rectangle.h" + +#include "eina_private.h" + +typedef struct _Eina_QuadTree_Root Eina_QuadTree_Root; + +static const char EINA_MAGIC_QUADTREE_STR[] = "Eina QuadTree"; +static const char EINA_MAGIC_QUADTREE_ROOT_STR[] = "Eina QuadTree Root"; +static const char EINA_MAGIC_QUADTREE_ITEM_STR[] = "Eina QuadTree Item"; + +#define EINA_MAGIC_CHECK_QUADTREE(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_QUADTREE)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_QUADTREE); \ + return __VA_ARGS__; \ + } \ + } while(0); + +#define EINA_MAGIC_CHECK_QUADTREE_ROOT(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_QUADTREE_ROOT)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_QUADTREE_ROOT); \ + return __VA_ARGS__; \ + } \ + } while(0); + +#define EINA_MAGIC_CHECK_QUADTREE_ITEM(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_QUADTREE_ITEM)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_QUADTREE_ITEM); \ + return __VA_ARGS__; \ + } \ + } while(0); + +struct _Eina_QuadTree +{ + Eina_QuadTree_Root *root; + + Eina_List *hidden; + + size_t root_count; + size_t items_count; + + Eina_Trash *items_trash; + Eina_Trash *root_trash; + + Eina_Inlist *change; + Eina_Inlist *cached; + Eina_Rectangle target; + + size_t index; + + struct + { + Eina_Quad_Callback v; + Eina_Quad_Callback h; + } func; + + struct + { + size_t w; + size_t h; + } geom; + + Eina_Bool resize : 1; + Eina_Bool lost : 1; + + EINA_MAGIC +}; + +struct _Eina_QuadTree_Root +{ + Eina_QuadTree_Root *parent; + Eina_QuadTree_Root *left; + Eina_QuadTree_Root *right; + + Eina_List *both; + + Eina_Bool sorted : 1; + + EINA_MAGIC +}; + +struct _Eina_QuadTree_Item +{ + EINA_INLIST; + + Eina_QuadTree *quad; + Eina_QuadTree_Root *root; + + const void *object; + + size_t index; + + Eina_Bool change : 1; + Eina_Bool delete_me : 1; + Eina_Bool visible : 1; + Eina_Bool hidden : 1; + + EINA_MAGIC +}; + +static int _eina_quadtree_log_dom = -1; +static Eina_Mempool *eina_quadtree_root_mp = NULL; +static Eina_Mempool *_eina_quadtree_items_mp = NULL; + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_eina_quadtree_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_quadtree_log_dom, __VA_ARGS__) + + +static int +_eina_quadtree_item_cmp(const void *a, const void *b) +{ + const Eina_QuadTree_Item *i = a; + const Eina_QuadTree_Item *j = b; + + return i->index - j->index; +} + +static Eina_QuadTree_Root * +eina_quadtree_root_free(Eina_QuadTree *q, Eina_QuadTree_Root *root) +{ + Eina_QuadTree_Item *item; + + if (!root) + return NULL; + + EINA_MAGIC_CHECK_QUADTREE_ROOT(root, NULL); + + EINA_LIST_FREE(root->both, item) + eina_mempool_free(_eina_quadtree_items_mp, item); + + root->left = eina_quadtree_root_free(q, root->left); + root->right = eina_quadtree_root_free(q, root->right); + + EINA_MAGIC_SET(root, 0); + eina_mempool_free(eina_quadtree_root_mp, root); + + return NULL; +} + +static Eina_QuadTree_Root * +eina_quadtree_root_rebuild_pre(Eina_QuadTree *q, + Eina_Inlist **change, + Eina_QuadTree_Root *root) +{ + Eina_QuadTree_Item *item; + + if (!root) + return NULL; + + EINA_LIST_FREE(root->both, item) + { + if (item->visible) + *change = eina_inlist_append(*change, EINA_INLIST_GET(item)); + else if (!item->hidden) + { + q->hidden = eina_list_append(q->hidden, item); + item->hidden = EINA_TRUE; + item->root = NULL; + } + } + + root->left = eina_quadtree_root_rebuild_pre(q, change, root->left); + root->right = eina_quadtree_root_rebuild_pre(q, change, root->right); + + EINA_MAGIC_SET(root, 0); + if (q->root_count > 50) + eina_mempool_free(eina_quadtree_root_mp, root); + else + { + eina_trash_push(&q->root_trash, root); + q->root_count++; + } + + return NULL; +} + +static size_t +_eina_quadtree_split(Eina_Inlist *objects, + Eina_QuadTree_Root *root, + Eina_Inlist **left, + Eina_Inlist **right, + Eina_Quad_Callback func, + int border, + int middle) +{ + Eina_QuadTree_Item *object; + + middle /= 2; + + if (middle <= 4) + while (objects) + { + object = EINA_INLIST_CONTAINER_GET(objects, Eina_QuadTree_Item); + objects = objects->next; + + object->change = EINA_FALSE; + if (!object->visible) + { + if (!object->hidden) + { + object->hidden = EINA_TRUE; + object->quad->hidden = eina_list_append( + object->quad->hidden, + object); + } + + continue; + } + + if (object->hidden) + { + object->hidden = EINA_FALSE; + object->quad->hidden = eina_list_remove(object->quad->hidden, + object); + } + + if (!object->delete_me) + { + if (root->sorted) + root->both = eina_list_sorted_insert(root->both, + _eina_quadtree_item_cmp, + object); + else + root->both = eina_list_append(root->both, object); + + object->root = root; + } + else + eina_quadtree_del(object); + } + else + while (objects) + { + object = EINA_INLIST_CONTAINER_GET(objects, Eina_QuadTree_Item); + objects = objects->next; + + object->change = EINA_FALSE; + if (!object->visible) + { + if (!object->hidden) + { + object->hidden = EINA_TRUE; + object->quad->hidden = eina_list_append( + object->quad->hidden, + object); + } + + continue; + } + + if (object->hidden) + { + object->hidden = EINA_FALSE; + object->quad->hidden = eina_list_remove(object->quad->hidden, + object); + } + + if (!object->delete_me) + { + switch (func(object->object, border + middle)) + { + case EINA_QUAD_LEFT: + *left = eina_inlist_append(*left, EINA_INLIST_GET(object)); + break; + + case EINA_QUAD_RIGHT: + *right = + eina_inlist_append(*right, EINA_INLIST_GET(object)); + break; + + case EINA_QUAD_BOTH: + root->both = eina_list_append(root->both, object); + object->root = root; + break; + + default: + abort(); + } + } + else + eina_quadtree_del(object); + } + + return middle; +} + + +static Eina_QuadTree_Root * +_eina_quadtree_update(Eina_QuadTree *q, Eina_QuadTree_Root *parent, + Eina_QuadTree_Root *root, Eina_Inlist *objects, + Eina_Bool direction, Eina_Rectangle *size) +{ + Eina_Inlist *right = NULL; + Eina_Inlist *left = NULL; + size_t w2; + size_t h2; + + if (!objects) + return root; + + if (!root) + { + root = eina_trash_pop(&q->root_trash); + if (!root) + root = eina_mempool_malloc(eina_quadtree_root_mp, sizeof (Eina_QuadTree_Root)); + else + q->root_count--; + + if (!root) + /* FIXME: NOT GOOD TIMING, WE ARE GOING TO LEAK MORE MEMORY */ + return NULL; + + root->parent = parent; + root->both = NULL; + root->left = NULL; + root->right = NULL; + root->sorted = EINA_TRUE; + + EINA_MAGIC_SET(root, EINA_MAGIC_QUADTREE_ROOT); + } + + w2 = 0; + h2 = 0; + + if (direction) + w2 = _eina_quadtree_split(objects, root, + &left, &right, + q->func.h, size->x, size->w); + else + h2 = _eina_quadtree_split(objects, root, + &left, &right, + q->func.v, size->y, size->h); + + size->w -= w2; size->h -= h2; + root->left = _eina_quadtree_update(q, root, + root->left, left, + !direction, size); + size->x += w2; size->y += h2; + root->right = _eina_quadtree_update(q, root, + root->right, right, + !direction, size); + size->x -= w2; size->y -= h2; + size->w += w2; size->h += h2; + + return root; +} + +static Eina_Inlist * +_eina_quadtree_merge(Eina_Inlist *result, + Eina_List *both) +{ + Eina_QuadTree_Item *item; + Eina_QuadTree_Item *b; + Eina_Inlist *moving; + + if (!both) + return result; + + if (!result) + { + Eina_List *l; + + EINA_LIST_FOREACH(both, l, item) + if (item->visible) + result = eina_inlist_append(result, EINA_INLIST_GET(item)); + + return result; + } + + moving = result; + + item = EINA_INLIST_CONTAINER_GET(moving, Eina_QuadTree_Item); + b = eina_list_data_get(both); + + while (both && moving) + { + if (!b->visible) + { + both = eina_list_next(both); + b = eina_list_data_get(both); + continue; + } + + if (_eina_quadtree_item_cmp(item, b) < 0) + { + /* moving is still lower than item, so we can continue to the next one. */ + moving = moving->next; + item = EINA_INLIST_CONTAINER_GET(moving, Eina_QuadTree_Item); + } + else + { + /* we just get above the limit of both, so insert it */ + result = eina_inlist_prepend_relative(result, + EINA_INLIST_GET(b), + moving); + both = eina_list_next(both); + b = eina_list_data_get(both); + } + } + + item = EINA_INLIST_CONTAINER_GET(result->last, Eina_QuadTree_Item); + + while (both) + { + b = eina_list_data_get(both); + if (b->visible) + { + if (_eina_quadtree_item_cmp(item, b) < 0) + break; + + result = eina_inlist_prepend_relative(result, + EINA_INLIST_GET(b), + result->last); + } + + both = eina_list_next(both); + } + + while (both) + { + b = eina_list_data_get(both); + if (b->visible) + result = eina_inlist_append(result, EINA_INLIST_GET(b)); + + both = eina_list_next(both); + } + + return result; +} + +static Eina_Inlist * +_eina_quadtree_collide(Eina_Inlist *result, + Eina_QuadTree_Root *root, + Eina_Bool direction, Eina_Rectangle *size, + Eina_Rectangle *target) +{ + if (!root) + return result; + + if (!root->sorted) + { + root->both = eina_list_sort(root->both, -1, _eina_quadtree_item_cmp); + root->sorted = EINA_TRUE; + } + + result = _eina_quadtree_merge(result, root->both); + DBG("%p: %i in both for (%i, %i - %i, %i)", + root, eina_list_count(root->both), + size->x, size->y, size->w, size->h); + + if (direction) + { + int middle = size->w / 2; + + size->w -= middle; + if (eina_spans_intersect(size->x, size->w, target->x, target->w)) + result = _eina_quadtree_collide(result, root->left, + !direction, size, + target); + + size->x += middle; + if (eina_spans_intersect(size->x, size->w, target->x, target->w)) + result = _eina_quadtree_collide(result, root->right, + !direction, size, + target); + + size->x -= middle; + size->w += middle; + } + else + { + int middle = size->h / 2; + + size->h -= middle; + if (eina_spans_intersect(size->y, size->h, target->y, target->h)) + result = _eina_quadtree_collide(result, root->left, + !direction, size, + target); + + size->y += middle; + if (eina_spans_intersect(size->y, size->h, target->y, target->h)) + result = _eina_quadtree_collide(result, root->right, + !direction, size, + target); + + size->y -= middle; + size->h += middle; + } + + return result; +} + +static void +_eina_quadtree_remove(Eina_QuadTree_Item *object) +{ + if (!object->root) + return; + + object->root->both = eina_list_remove(object->root->both, object); + if (object->root->both) + goto end; + + if (object->root->left) + goto end; + + if (object->root->right) + goto end; + + /* The root is not useful anymore... */ + if (object->root->parent) + { + if (object->root->parent->left == object->root) + object->root->parent->left = NULL; + else + object->root->parent->right = NULL; + + object->root->parent = NULL; + } + else + object->quad->root = NULL; + + if (object->quad->root_count > 50) + eina_mempool_free(eina_quadtree_root_mp, object->root); + else + { + eina_trash_push(&object->quad->root_trash, object->root); + object->quad->root_count++; + } + +end: + object->root = NULL; +} + +EAPI Eina_QuadTree * +eina_quadtree_new(size_t w, size_t h, + Eina_Quad_Callback vertical, Eina_Quad_Callback horizontal) +{ + Eina_QuadTree *result; + + if (!vertical || !horizontal || h == 0 || w == 0) + return NULL; + + result = calloc(1, sizeof (Eina_QuadTree)); + if (!result) + return NULL; + + result->func.v = vertical; + result->func.h = horizontal; + + result->geom.w = w; + result->geom.h = h; + + result->change = NULL; + + result->lost = EINA_TRUE; + + EINA_MAGIC_SET(result, EINA_MAGIC_QUADTREE); + + return result; +} + +EAPI void +eina_quadtree_free(Eina_QuadTree *q) +{ + Eina_QuadTree_Item *item; + + if (!q) + return; + + EINA_MAGIC_CHECK_QUADTREE(q); + + while (q->change) + { + item = EINA_INLIST_CONTAINER_GET(q->change, Eina_QuadTree_Item); + q->change = q->change->next; + if (!item->hidden) + eina_mempool_free(_eina_quadtree_items_mp, item); + } + + EINA_LIST_FREE(q->hidden, item) + eina_mempool_free(_eina_quadtree_items_mp, item); + + eina_quadtree_root_free(q, q->root); + + while (q->items_trash) + { + item = eina_trash_pop(&q->items_trash); + eina_mempool_free(_eina_quadtree_items_mp, item); + } + + while (q->root_trash) + { + Eina_QuadTree_Root *root; + + root = eina_trash_pop(&q->root_trash); + eina_mempool_free(eina_quadtree_root_mp, root); + } + + EINA_MAGIC_SET(q, 0); + free(q); +} + +EAPI Eina_QuadTree_Item * +eina_quadtree_add(Eina_QuadTree *q, const void *object) +{ + Eina_QuadTree_Item *result; + + EINA_MAGIC_CHECK_QUADTREE(q, NULL); + + if (!object) + return NULL; + + result = eina_trash_pop(&q->items_trash); + if (!result) + result = eina_mempool_malloc(_eina_quadtree_items_mp, sizeof (Eina_QuadTree_Item)); + else + q->items_count--; + + if (!result) + return NULL; + + result->quad = q; + result->root = NULL; + result->object = object; + + result->index = q->index++; + + result->change = EINA_TRUE; + result->delete_me = EINA_FALSE; + result->visible = EINA_TRUE; + result->hidden = EINA_FALSE; + + EINA_MAGIC_SET(result, EINA_MAGIC_QUADTREE_ITEM); + + /* Insertion is delayed until we really need to use it */ + q->change = eina_inlist_append(q->change, EINA_INLIST_GET(result)); + + return result; +} + +EAPI Eina_Bool +eina_quadtree_del(Eina_QuadTree_Item *object) +{ + if (!object) + return EINA_FALSE; + + EINA_MAGIC_CHECK_QUADTREE_ITEM(object, EINA_FALSE); + + _eina_quadtree_remove(object); + + if (object->change) + { + /* This object is still in the update array, delaying it's removal !*/ + object->delete_me = EINA_TRUE; + object->visible = EINA_TRUE; + return EINA_TRUE; + } + + if (object->hidden) + { + object->quad->hidden = eina_list_remove(object->quad->hidden, object); + object->hidden = EINA_TRUE; + } + + /* This object is not anymore inside the tree, we can remove it now !*/ + EINA_MAGIC_SET(object, 0); + if (object->quad->items_count > 256) + eina_mempool_free(_eina_quadtree_items_mp, object); + else + { + object->quad->items_count++; + eina_trash_push(&object->quad->items_trash, object); + } + + return EINA_TRUE; +} + +EAPI Eina_Bool +eina_quadtree_change(Eina_QuadTree_Item *object) +{ + EINA_MAGIC_CHECK_QUADTREE_ITEM(object, EINA_FALSE); + + if (object->delete_me || !object->visible) + return EINA_FALSE; + + if (object->quad->resize) + return EINA_TRUE; + + /* Delaying change until needed */ + if (!object->change) + object->quad->change = eina_inlist_append(object->quad->change, + EINA_INLIST_GET(object)); + + object->change = EINA_TRUE; + + _eina_quadtree_remove(object); + + return EINA_TRUE; +} + +EAPI Eina_Bool +eina_quadtree_hide(Eina_QuadTree_Item *object) +{ + EINA_MAGIC_CHECK_QUADTREE_ITEM(object, EINA_FALSE); + + object->visible = EINA_FALSE; + + return EINA_TRUE; +} + +EAPI Eina_Bool +eina_quadtree_show(Eina_QuadTree_Item *object) +{ + EINA_MAGIC_CHECK_QUADTREE_ITEM(object, EINA_FALSE); + + object->quad->lost = EINA_TRUE; + + if (object->visible) + return EINA_TRUE; + + object->visible = EINA_TRUE; + if (!object->change) + return eina_quadtree_change(object); + + return EINA_TRUE; +} + +EAPI Eina_Inlist * +eina_quadtree_collide(Eina_QuadTree *q, int x, int y, int w, int h) +{ + Eina_Rectangle canvas; + + EINA_MAGIC_CHECK_QUADTREE(q, NULL); + + /* Now we need the tree to be up to date, so it's time */ + if (q->resize) /* Full rebuild needed ! */ + { + DBG("resizing quadtree"); + q->root = eina_quadtree_root_rebuild_pre(q, &q->change, q->root); + q->resize = EINA_FALSE; + } + + EINA_RECTANGLE_SET(&canvas, 0, 0, q->geom.w, q->geom.h); + + if (q->change) + { + DBG("updating quadtree content"); + q->root = _eina_quadtree_update(q, NULL, q->root, q->change, + EINA_FALSE, &canvas); + q->change = NULL; + q->lost = EINA_TRUE; + } + + if (q->target.x != x + || q->target.y != y + || q->target.w != w + || q->target.h != h) + { + DBG("new target"); + EINA_RECTANGLE_SET(&q->target, x, y, w, h); + q->lost = EINA_TRUE; + } + + if (q->lost) + { + DBG("computing collide"); + q->cached = _eina_quadtree_collide(NULL, q->root, + EINA_FALSE, &canvas, + &q->target); + q->lost = EINA_FALSE; + } + + return q->cached; +} + +EAPI void * +eina_quadtree_object(Eina_Inlist *item) +{ + Eina_QuadTree_Item *qi; + + if (!item) + return NULL; + + qi = EINA_INLIST_CONTAINER_GET(item, Eina_QuadTree_Item); + if (!qi) + return NULL; + + EINA_MAGIC_CHECK_QUADTREE_ITEM(qi, NULL); + + if (!qi->visible) + return NULL; + + return (void *)qi->object; +} + +EAPI void +eina_quadtree_resize(Eina_QuadTree *q, size_t w, size_t h) +{ + EINA_MAGIC_CHECK_QUADTREE(q); + + if (q->geom.w == w + && q->geom.h == h) + return; + + q->resize = EINA_TRUE; + q->geom.w = w; + q->geom.h = h; +} + +EAPI void +eina_quadtree_cycle(Eina_QuadTree *q) +{ + EINA_MAGIC_CHECK_QUADTREE(q); + + q->index = 0; +} + +EAPI void +eina_quadtree_increase(Eina_QuadTree_Item *object) +{ + size_t tmp; + + tmp = object->quad->index++; + if (object->index == tmp) + return; + + object->index = tmp; + if (object->root) + object->root->sorted = EINA_FALSE; +} + +Eina_Bool +eina_quadtree_init(void) +{ + const char *choice, *tmp; + + _eina_quadtree_log_dom = eina_log_domain_register("eina_quadtree", + EINA_LOG_COLOR_DEFAULT); + if (_eina_quadtree_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_quadtree"); + return EINA_FALSE; + } + +#define EMS(n) eina_magic_string_static_set(n, n ## _STR) + EMS(EINA_MAGIC_QUADTREE); + EMS(EINA_MAGIC_QUADTREE_ROOT); + EMS(EINA_MAGIC_QUADTREE_ITEM); +#undef EMS + +#ifdef EINA_DEFAULT_MEMPOOL + choice = "pass_through"; +#else + choice = "chained_mempool"; +#endif + tmp = getenv("EINA_MEMPOOL"); + if (tmp && tmp[0]) + choice = tmp; + + _eina_quadtree_items_mp = eina_mempool_add(choice, "QuadTree Item", NULL, + sizeof (Eina_QuadTree_Item), 320); + eina_quadtree_root_mp = eina_mempool_add(choice, "QuadTree Root", NULL, + sizeof (Eina_QuadTree_Root), 32); + + return EINA_TRUE; +} + +Eina_Bool +eina_quadtree_shutdown(void) +{ + eina_mempool_del(eina_quadtree_root_mp); + eina_mempool_del(_eina_quadtree_items_mp); + + eina_log_domain_unregister(_eina_quadtree_log_dom); + _eina_quadtree_log_dom = -1; + return EINA_TRUE; +} + + + diff --git a/libraries/eina/src/lib/eina_rbtree.c b/libraries/eina/src/lib/eina_rbtree.c new file mode 100644 index 0000000..c0c9f9e --- /dev/null +++ b/libraries/eina/src/lib/eina_rbtree.c @@ -0,0 +1,518 @@ +/* EINA - EFL data type library + * Copyright (C) 2008 Cedric Bail + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_array.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_rbtree.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +#define EINA_RBTREE_ITERATOR_PREFIX_MASK 0x1 +#define EINA_RBTREE_ITERATOR_INFIX_MASK 0x2 +#define EINA_RBTREE_ITERATOR_POSTFIX_MASK 0x4 + +typedef struct _Eina_Iterator_Rbtree Eina_Iterator_Rbtree; +typedef struct _Eina_Iterator_Rbtree_List Eina_Iterator_Rbtree_List; + +struct _Eina_Iterator_Rbtree +{ + Eina_Iterator iterator; + + Eina_Array *stack; + + unsigned char mask; +}; + +struct _Eina_Iterator_Rbtree_List +{ + Eina_Rbtree *tree; + + Eina_Rbtree_Direction dir : 1; + Eina_Bool up : 1; +}; + +static Eina_Iterator_Rbtree_List * +_eina_rbtree_iterator_list_new(const Eina_Rbtree *tree) +{ + Eina_Iterator_Rbtree_List *new; + + eina_error_set(0); + new = malloc(sizeof (Eina_Iterator_Rbtree_List)); + if (!new) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + new->tree = (Eina_Rbtree *)tree; + new->dir = EINA_RBTREE_RIGHT; + new->up = EINA_FALSE; + + return new; +} + +static Eina_Rbtree * +_eina_rbtree_iterator_get_content(Eina_Iterator_Rbtree *it) +{ + if (eina_array_count_get(it->stack) <= 0) + return NULL; + + return eina_array_data_get(it->stack, 0); +} + +static void +_eina_rbtree_iterator_free(Eina_Iterator_Rbtree *it) +{ + Eina_Iterator_Rbtree_List *item; + Eina_Array_Iterator et; + unsigned int i; + + EINA_ARRAY_ITER_NEXT(it->stack, i, item, et) + free(item); + + eina_array_free(it->stack); + free(it); +} + +static Eina_Bool +_eina_rbtree_iterator_next(Eina_Iterator_Rbtree *it, void **data) +{ + Eina_Iterator_Rbtree_List *last; + Eina_Iterator_Rbtree_List *new; + Eina_Rbtree *tree; + + if (eina_array_count_get(it->stack) <= 0) + return EINA_FALSE; + + last = eina_array_data_get(it->stack, eina_array_count_get(it->stack) - 1); + tree = last->tree; + + if (!last->tree || last->up == EINA_TRUE) + { + last = eina_array_pop(it->stack); + while (last->dir == EINA_RBTREE_LEFT + || !last->tree) + { + if (tree) + if ((it->mask & EINA_RBTREE_ITERATOR_POSTFIX_MASK) == + EINA_RBTREE_ITERATOR_POSTFIX_MASK) + { + free(last); + + if (eina_array_count_get(it->stack) > 0) + { + last = eina_array_data_get(it->stack, + eina_array_count_get( + it-> + stack) + - 1); + last->up = EINA_TRUE; + } + + goto onfix; + } + + free(last); + + last = eina_array_pop(it->stack); + if (!last) + return EINA_FALSE; + + tree = last->tree; + } + + last->dir = EINA_RBTREE_LEFT; + last->up = EINA_FALSE; + + eina_array_push(it->stack, last); + + if ((it->mask & EINA_RBTREE_ITERATOR_INFIX_MASK) == + EINA_RBTREE_ITERATOR_INFIX_MASK) + goto onfix; + } + + new = _eina_rbtree_iterator_list_new(last->tree->son[last->dir]); + if (!new) + return EINA_FALSE; + + eina_array_push(it->stack, new); + + if (last->dir == EINA_RBTREE_RIGHT) + if ((it->mask & EINA_RBTREE_ITERATOR_PREFIX_MASK) == + EINA_RBTREE_ITERATOR_PREFIX_MASK) + goto onfix; + + return _eina_rbtree_iterator_next(it, data); + +onfix: + *data = tree; + return EINA_TRUE; +} + +static Eina_Iterator * +_eina_rbtree_iterator_build(const Eina_Rbtree *root, unsigned char mask) +{ + Eina_Iterator_Rbtree_List *first; + Eina_Iterator_Rbtree *it; + + eina_error_set(0); + it = calloc(1, sizeof (Eina_Iterator_Rbtree)); + if (!it) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + it->stack = eina_array_new(8); + if (!it->stack) + goto on_error2; + + first = _eina_rbtree_iterator_list_new(root); + if (!first) + goto on_error; + + eina_array_push(it->stack, first); + + it->mask = mask; + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_eina_rbtree_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER( + _eina_rbtree_iterator_get_content); + it->iterator.free = FUNC_ITERATOR_FREE(_eina_rbtree_iterator_free); + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + return &it->iterator; + +on_error: + eina_array_free(it->stack); +on_error2: + free(it); + + return NULL; +} + +static void +_eina_rbtree_node_init(Eina_Rbtree *node) +{ + if (!node) + return; + + node->son[0] = NULL; + node->son[1] = NULL; + + node->color = EINA_RBTREE_RED; +} + +static inline Eina_Bool +_eina_rbtree_is_red(Eina_Rbtree *node) +{ + return !!node && node->color == EINA_RBTREE_RED; +} + +static inline Eina_Rbtree * +_eina_rbtree_inline_single_rotation(Eina_Rbtree *node, + Eina_Rbtree_Direction dir) +{ + Eina_Rbtree *save = node->son[!dir]; + + node->son[!dir] = save->son[dir]; + save->son[dir] = node; + + node->color = EINA_RBTREE_RED; + save->color = EINA_RBTREE_BLACK; + + return save; +} + +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); + return _eina_rbtree_inline_single_rotation(node, dir); +} + +/*============================================================================* +* Global * +*============================================================================*/ + +/*============================================================================* +* API * +*============================================================================*/ + +EAPI Eina_Rbtree * +eina_rbtree_inline_insert(Eina_Rbtree *root, + Eina_Rbtree *node, + 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_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; + + dir2 = (t->son[1] == g) ? EINA_RBTREE_RIGHT : EINA_RBTREE_LEFT; + + 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); + + /* Update helpers */ + if ( g ) + t = g; + + g = p, p = q; + q = q->son[dir]; + } + + root = head.son[1]; + +end_add: + /* Make root black */ + root->color = EINA_RBTREE_BLACK; + + return root; +} + +EAPI Eina_Rbtree * +eina_rbtree_inline_remove(Eina_Rbtree *root, + Eina_Rbtree *node, + Eina_Rbtree_Cmp_Node_Cb cmp, + const void *data) +{ + Eina_Rbtree head; + Eina_Rbtree *q, *p; + Eina_Rbtree *f = NULL; + Eina_Rbtree_Direction dir; + + 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; + + /* 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; + } + + root = head.son[1]; + if (root) + root->color = EINA_RBTREE_BLACK; + + return root; +} + +EAPI Eina_Iterator * +eina_rbtree_iterator_prefix(const Eina_Rbtree *root) +{ + return _eina_rbtree_iterator_build(root, EINA_RBTREE_ITERATOR_PREFIX_MASK); +} + +EAPI Eina_Iterator * +eina_rbtree_iterator_infix(const Eina_Rbtree *root) +{ + return _eina_rbtree_iterator_build(root, EINA_RBTREE_ITERATOR_INFIX_MASK); +} + +EAPI Eina_Iterator * +eina_rbtree_iterator_postfix(const Eina_Rbtree *root) +{ + return _eina_rbtree_iterator_build(root, EINA_RBTREE_ITERATOR_POSTFIX_MASK); +} + +EAPI void +eina_rbtree_delete(Eina_Rbtree *root, Eina_Rbtree_Free_Cb func, void *data) +{ + if (!root) + return; + + EINA_SAFETY_ON_NULL_RETURN(func); + + eina_rbtree_delete(root->son[0], func, data); + eina_rbtree_delete(root->son[1], func, data); + func(root, data); +} diff --git a/libraries/eina/src/lib/eina_rectangle.c b/libraries/eina/src/lib/eina_rectangle.c new file mode 100644 index 0000000..7f0a619 --- /dev/null +++ b/libraries/eina/src/lib/eina_rectangle.c @@ -0,0 +1,568 @@ +/* EINA - EFL data type library + * Copyright (C) 2007-2008 Cedric BAIL, Carsten Haitzler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#ifdef HAVE_EVIL +# include +#endif + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_magic.h" +#include "eina_inlist.h" +#include "eina_mempool.h" +#include "eina_list.h" +#include "eina_trash.h" +#include "eina_log.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_rectangle.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +#define EINA_RECTANGLE_POOL_MAGIC 0x1578FCB0 +#define EINA_RECTANGLE_ALLOC_MAGIC 0x1578FCB1 + +#define BUCKET_THRESHOLD 110 + +typedef struct _Eina_Rectangle_Alloc Eina_Rectangle_Alloc; + +struct _Eina_Rectangle_Pool +{ + Eina_Inlist *head; + Eina_List *empty; + void *data; + + Eina_Trash *bucket; + unsigned int bucket_count; + + unsigned int references; + int w; + int h; + + Eina_Bool sorted; + EINA_MAGIC +}; + +struct _Eina_Rectangle_Alloc +{ + EINA_INLIST; + Eina_Rectangle_Pool *pool; + EINA_MAGIC +}; + +#define EINA_MAGIC_CHECK_RECTANGLE_POOL(d) \ + do { \ + if (!EINA_MAGIC_CHECK((d), EINA_RECTANGLE_POOL_MAGIC)) { \ + EINA_MAGIC_FAIL((d), EINA_RECTANGLE_POOL_MAGIC); } \ + } while (0) + +#define EINA_MAGIC_CHECK_RECTANGLE_ALLOC(d) \ + do { \ + if (!EINA_MAGIC_CHECK((d), EINA_RECTANGLE_ALLOC_MAGIC)) { \ + EINA_MAGIC_FAIL((d), EINA_RECTANGLE_ALLOC_MAGIC); } \ + } while (0) + +static Eina_Mempool *_eina_rectangle_alloc_mp = NULL; +static Eina_Mempool *_eina_rectangle_mp = NULL; + +static Eina_Trash *_eina_rectangles = NULL; +static unsigned int _eina_rectangles_count = 0; +static int _eina_rectangle_log_dom = -1; + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_eina_rectangle_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_rectangle_log_dom, __VA_ARGS__) + +static int +_eina_rectangle_cmp(const Eina_Rectangle *r1, const Eina_Rectangle *r2) +{ + return (r2->w * r2->h) - (r1->w * r1->h); +} + +static Eina_List * +_eina_rectangle_merge_list(Eina_List *empty, Eina_Rectangle *r) +{ + Eina_Rectangle *match; + Eina_List *l; + int xw; + int yh; + + if (r->w == 0 || r->h == 0) + { + eina_rectangle_free(r); + return empty; + } + +start_again: + xw = r->x + r->w; + yh = r->y + r->h; + + EINA_LIST_FOREACH(empty, l, match) + { + if (match->x == r->x && match->w == r->w + && (match->y == yh || r->y == match->y + match->h)) + { + if (match->y > r->y) + match->y = r->y; + + match->h += r->h; + + eina_rectangle_free(r); + + empty = eina_list_remove_list(empty, l); + + r = match; + + goto start_again; + } + else if (match->y == r->y && match->h == r->h + && (match->x == xw || r->x == match->x + match->w)) + { + if (match->x > r->x) + match->x = r->x; + + match->w += r->w; + + eina_rectangle_free(r); + + empty = eina_list_remove_list(empty, l); + + r = match; + + goto start_again; + } + } + + return eina_list_append(empty, r); +} + +static Eina_List * +_eina_rectangle_empty_space_find(Eina_List *empty, int w, int h, int *x, int *y) +{ + Eina_Rectangle *r; + Eina_List *l; + + EINA_LIST_FOREACH(empty, l, r) + { + if (r->w >= w && r->h >= h) + { + /* Remove l from empty */ + empty = eina_list_remove_list(empty, l); + /* Remember x and y */ + *x = r->x; + *y = r->y; + /* Split r in 2 rectangle if needed (only the empty one) and insert them */ + if (r->w == w) + { + r->y += h; + r->h -= h; + } + else if (r->h == h) + { + r->x += w; + r->w -= w; + } + else + { + int rx1, ry1, rw1, rh1; + int x2, y2, w2, h2; + + rx1 = r->x + w; + ry1 = r->y; + rw1 = r->w - w; + /* h1 could be h or r->h */ + x2 = r->x; + y2 = r->y + h; + /* w2 could be w or r->w */ + h2 = r->h - h; + + if (rw1 * r->h > h2 * r->w) + { + rh1 = r->h; + w2 = w; + } + else + { + rh1 = h; + w2 = r->w; + } + + EINA_RECTANGLE_SET(r, rx1, ry1, rw1, rh1); + empty = _eina_rectangle_merge_list(empty, r); + + r = eina_rectangle_new(x2, y2, w2, h2); + } + + if (r) + { + empty = _eina_rectangle_merge_list(empty, r); /* Return empty */ + + } + + return empty; + } + } + + *x = -1; + *y = -1; + return empty; +} + +/** + * @endcond + */ + +/*============================================================================* +* Global * +*============================================================================*/ + +Eina_Bool +eina_rectangle_init(void) +{ + const char *choice, *tmp; + + _eina_rectangle_log_dom = eina_log_domain_register("eina_rectangle", + EINA_LOG_COLOR_DEFAULT); + if (_eina_rectangle_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_rectangle"); + return EINA_FALSE; + } + +#ifdef EINA_DEFAULT_MEMPOOL + choice = "pass_through"; +#else + choice = "chained_mempool"; +#endif + tmp = getenv("EINA_MEMPOOL"); + if (tmp && tmp[0]) + choice = tmp; + + _eina_rectangle_alloc_mp = eina_mempool_add + (choice, "rectangle-alloc", NULL, + sizeof(Eina_Rectangle_Alloc) + sizeof(Eina_Rectangle), 1024); + if (!_eina_rectangle_alloc_mp) + { + ERR("Mempool for rectangle cannot be allocated in rectangle init."); + goto init_error; + } + + _eina_rectangle_mp = eina_mempool_add + (choice, "rectangle", NULL, sizeof(Eina_Rectangle), 256); + if (!_eina_rectangle_mp) + { + ERR("Mempool for rectangle cannot be allocated in rectangle init."); + goto init_error; + } + + return EINA_TRUE; + +init_error: + eina_log_domain_unregister(_eina_rectangle_log_dom); + _eina_rectangle_log_dom = -1; + + return EINA_FALSE; +} + +Eina_Bool +eina_rectangle_shutdown(void) +{ + Eina_Rectangle *del; + + while ((del = eina_trash_pop(&_eina_rectangles))) + eina_mempool_free(_eina_rectangle_mp, del); + _eina_rectangles_count = 0; + + eina_mempool_del(_eina_rectangle_alloc_mp); + eina_mempool_del(_eina_rectangle_mp); + + eina_log_domain_unregister(_eina_rectangle_log_dom); + _eina_rectangle_log_dom = -1; + + return EINA_TRUE; +} + +/*============================================================================* +* API * +*============================================================================*/ + +EAPI Eina_Rectangle * +eina_rectangle_new(int x, int y, int w, int h) +{ + Eina_Rectangle *rect; + + if (_eina_rectangles) + { + rect = eina_trash_pop(&_eina_rectangles); + _eina_rectangles_count--; + } + else + rect = eina_mempool_malloc(_eina_rectangle_mp, sizeof (Eina_Rectangle)); + + if (!rect) + return NULL; + + EINA_RECTANGLE_SET(rect, x, y, w, h); + + return rect; +} + +EAPI void +eina_rectangle_free(Eina_Rectangle *rect) +{ + EINA_SAFETY_ON_NULL_RETURN(rect); + + if (_eina_rectangles_count > BUCKET_THRESHOLD) + eina_mempool_free(_eina_rectangle_mp, rect); + else + { + eina_trash_push(&_eina_rectangles, rect); + _eina_rectangles_count++; + } +} + +EAPI Eina_Rectangle_Pool * +eina_rectangle_pool_new(int w, int h) +{ + Eina_Rectangle_Pool *new; + + new = malloc(sizeof (Eina_Rectangle_Pool)); + if (!new) + return NULL; + + new->head = NULL; + new->empty = eina_list_append(NULL, eina_rectangle_new(0, 0, w, h)); + new->references = 0; + new->sorted = EINA_FALSE; + new->w = w; + new->h = h; + new->bucket = NULL; + new->bucket_count = 0; + + EINA_MAGIC_SET(new, EINA_RECTANGLE_POOL_MAGIC); + DBG("pool=%p, size=(%d, %d)", new, w, h); + + return new; +} + +EAPI void +eina_rectangle_pool_free(Eina_Rectangle_Pool *pool) +{ + Eina_Rectangle_Alloc *del; + + EINA_SAFETY_ON_NULL_RETURN(pool); + DBG("pool=%p, size=(%d, %d), references=%u", + pool, pool->w, pool->h, pool->references); + while (pool->head) + { + del = (Eina_Rectangle_Alloc *)pool->head; + + pool->head = (EINA_INLIST_GET(del))->next; + + EINA_MAGIC_SET(del, EINA_MAGIC_NONE); + eina_mempool_free(_eina_rectangle_alloc_mp, del); + } + + while (pool->bucket) + { + del = eina_trash_pop(&pool->bucket); + eina_mempool_free(_eina_rectangle_alloc_mp, del); + } + + MAGIC_FREE(pool); +} + +EAPI int +eina_rectangle_pool_count(Eina_Rectangle_Pool *pool) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(pool, 0); + return pool->references; +} + +EAPI Eina_Rectangle * +eina_rectangle_pool_request(Eina_Rectangle_Pool *pool, int w, int h) +{ + Eina_Rectangle_Alloc *new; + Eina_Rectangle *rect; + int x; + int y; + + EINA_SAFETY_ON_NULL_RETURN_VAL(pool, NULL); + + DBG("pool=%p, size=(%d, %d), references=%u", + pool, pool->w, pool->h, pool->references); + + if (w <= 0 || h <= 0) + return NULL; + + if (w > pool->w || h > pool->h) + return NULL; + + /* Sort empty if dirty */ + if (pool->sorted) + { + pool->empty = + eina_list_sort(pool->empty, 0, EINA_COMPARE_CB(_eina_rectangle_cmp)); + pool->sorted = EINA_TRUE; + } + + pool->empty = _eina_rectangle_empty_space_find(pool->empty, w, h, &x, &y); + if (x == -1) + return NULL; + + pool->sorted = EINA_FALSE; + + if (pool->bucket_count > 0) + { + new = eina_trash_pop(&pool->bucket); + pool->bucket_count--; + } + else + new = eina_mempool_malloc(_eina_rectangle_alloc_mp, + sizeof (Eina_Rectangle_Alloc) + + sizeof (Eina_Rectangle)); + + if (!new) + return NULL; + + rect = (Eina_Rectangle *)(new + 1); + eina_rectangle_coords_from(rect, x, y, w, h); + + pool->head = eina_inlist_prepend(pool->head, EINA_INLIST_GET(new)); + pool->references++; + + new->pool = pool; + + EINA_MAGIC_SET(new, EINA_RECTANGLE_ALLOC_MAGIC); + DBG("rect=%p pool=%p, size=(%d, %d), references=%u", + rect, pool, pool->w, pool->h, pool->references); + + return rect; +} + +EAPI void +eina_rectangle_pool_release(Eina_Rectangle *rect) +{ + Eina_Rectangle_Alloc *era = ((Eina_Rectangle_Alloc *)rect) - 1; + Eina_Rectangle *r; + + EINA_SAFETY_ON_NULL_RETURN(rect); + + EINA_MAGIC_CHECK_RECTANGLE_ALLOC(era); + EINA_MAGIC_CHECK_RECTANGLE_POOL(era->pool); + + DBG("rect=%p pool=%p, size=(%d, %d), references=%u", + rect, era->pool, era->pool->w, era->pool->h, era->pool->references); + + era->pool->references--; + era->pool->head = eina_inlist_remove(era->pool->head, EINA_INLIST_GET(era)); + + r = eina_rectangle_new(rect->x, rect->y, rect->w, rect->h); + if (r) + { + era->pool->empty = _eina_rectangle_merge_list(era->pool->empty, r); + era->pool->sorted = EINA_FALSE; + } + + if (era->pool->bucket_count < BUCKET_THRESHOLD) + { + Eina_Rectangle_Pool *pool; + + pool = era->pool; + + pool->bucket_count++; + eina_trash_push(&pool->bucket, era); + } + else + { + EINA_MAGIC_SET(era, EINA_MAGIC_NONE); + eina_mempool_free(_eina_rectangle_alloc_mp, era); + } +} + +EAPI Eina_Rectangle_Pool * +eina_rectangle_pool_get(Eina_Rectangle *rect) +{ + Eina_Rectangle_Alloc *era = ((Eina_Rectangle_Alloc *)rect) - 1; + + EINA_SAFETY_ON_NULL_RETURN_VAL(rect, NULL); + + EINA_MAGIC_CHECK_RECTANGLE_ALLOC(era); + EINA_MAGIC_CHECK_RECTANGLE_POOL(era->pool); + + return era->pool; +} + +EAPI void +eina_rectangle_pool_data_set(Eina_Rectangle_Pool *pool, const void *data) +{ + EINA_MAGIC_CHECK_RECTANGLE_POOL(pool); + EINA_SAFETY_ON_NULL_RETURN(pool); + + DBG("data=%p pool=%p, size=(%d, %d), references=%u", + data, pool, pool->w, pool->h, pool->references); + + pool->data = (void *)data; +} + +EAPI void * +eina_rectangle_pool_data_get(Eina_Rectangle_Pool *pool) +{ + EINA_MAGIC_CHECK_RECTANGLE_POOL(pool); + EINA_SAFETY_ON_NULL_RETURN_VAL(pool, NULL); + + return pool->data; +} + +EAPI Eina_Bool +eina_rectangle_pool_geometry_get(Eina_Rectangle_Pool *pool, int *w, int *h) +{ + if (!pool) + return EINA_FALSE; + + EINA_MAGIC_CHECK_RECTANGLE_POOL(pool); + EINA_SAFETY_ON_NULL_RETURN_VAL(pool, EINA_FALSE); + + if (w) + *w = pool->w; + + if (h) + *h = pool->h; + + return EINA_TRUE; +} diff --git a/libraries/eina/src/lib/eina_safety_checks.c b/libraries/eina/src/lib/eina_safety_checks.c new file mode 100644 index 0000000..eed7c59 --- /dev/null +++ b/libraries/eina/src/lib/eina_safety_checks.c @@ -0,0 +1,90 @@ +/* EINA - EFL data type library + * Copyright (C) 2008 Gustavo Sverzut Barbieri + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "eina_private.h" +#include "eina_error.h" +#include "eina_log.h" +#include "eina_safety_checks.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/*============================================================================* +* Global * +*============================================================================*/ + +/** + * @internal + * @brief Shut down the safety checks module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the error module set up by + * eina_safety_checks_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_safety_checks_shutdown(void) +{ + return EINA_TRUE; +} + +/*============================================================================* +* API * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +EAPI Eina_Error EINA_ERROR_SAFETY_FAILED = 0; + +static const char EINA_ERROR_SAFETY_FAILED_STR[] = "Safety check failed."; + +/** + * @endcond + */ + +/** + * @internal + * @brief Initialize the safety checks module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the safety checks module of Eina. It is + * called by eina_init(). + * + * @see eina_init() + */ +Eina_Bool +eina_safety_checks_init(void) +{ + EINA_ERROR_SAFETY_FAILED = eina_error_msg_static_register( + EINA_ERROR_SAFETY_FAILED_STR); + return EINA_TRUE; +} + +/** + * @} + */ diff --git a/libraries/eina/src/lib/eina_sched.c b/libraries/eina/src/lib/eina_sched.c new file mode 100644 index 0000000..8c7f7fe --- /dev/null +++ b/libraries/eina/src/lib/eina_sched.c @@ -0,0 +1,94 @@ +/* EINA - EFL data type library + * Copyright (C) 2010 ProFUSION embedded systems + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef EFL_HAVE_POSIX_THREADS +# include +# ifdef __linux__ +# include +# include +# include +# include +# endif +#endif + +#ifdef EFL_HAVE_WIN32_THREADS +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# undef WIN32_LEAN_AND_MEAN +#endif + +#include "eina_sched.h" +#include "eina_log.h" + +#define RTNICENESS 5 +#define NICENESS 5 + +EAPI void +eina_sched_prio_drop(void) +{ +#ifdef EFL_HAVE_POSIX_THREADS + struct sched_param param; + int pol, prio, ret; + pthread_t pthread_id; + + pthread_id = pthread_self(); + ret = pthread_getschedparam(pthread_id, &pol, ¶m); + if (ret) + { + EINA_LOG_ERR("Unable to query sched parameters"); + return; + } + + 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; + + pthread_setschedparam(pthread_id, pol, ¶m); + } +# ifdef __linux__ + else + { + errno = 0; + prio = getpriority(PRIO_PROCESS, 0); + if (errno == 0) + { + prio += NICENESS; + if (prio > 19) + prio = 19; + + setpriority(PRIO_PROCESS, 0, prio); + } + } +# endif +#elif defined EFL_HAVE_WIN32_THREADS + if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL)) + EINA_LOG_ERR("Can not set thread priority"); +#else + EINA_LOG_ERR("Eina does not have support for threads enabled" + "or it doesn't support setting scheduler priorities"); +#endif +} diff --git a/libraries/eina/src/lib/eina_share_common.c b/libraries/eina/src/lib/eina_share_common.c new file mode 100644 index 0000000..90e1868 --- /dev/null +++ b/libraries/eina/src/lib/eina_share_common.c @@ -0,0 +1,977 @@ +/* EINA - EFL data type library + * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2010 + * Carsten Haitzler, + * Jorge Luis Zapata Muga, + * Cedric Bail, + * Gustavo Sverzut Barbieri + * Tom Hacohen + * Brett Nash + * + * 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 . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright (C) 2008 Peter Wehrfritz + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies of the Software and its Copyright notices. In addition publicly + * documented acknowledgment must be given that this software has been used if no + * source code of this software is made available publicly. This includes + * acknowledgments in either Copyright notices, Manuals, Publicity and Marketing + * documents or any documentation provided with any product containing this + * software. This License does not apply to any software that links to the + * libraries provided by this software (statically or dynamically), but only to + * the software provided. + * + * Please see the OLD-COPYING.PLAIN for a plain-english explanation of this notice + * and it's intent. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#ifdef EFL_HAVE_POSIX_THREADS +# include +#endif + +#ifdef HAVE_EVIL +# include +#endif + +#include "eina_config.h" +#include "eina_private.h" +#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! */ +#include "eina_safety_checks.h" +#include "eina_share_common.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +#define EINA_SHARE_COMMON_BUCKETS 256 +#define EINA_SHARE_COMMON_MASK 0xFF + +static const char EINA_MAGIC_SHARE_STR[] = "Eina Share"; +static const char EINA_MAGIC_SHARE_HEAD_STR[] = "Eina Share Head"; + +static int _eina_share_common_count = 0; + +#define EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(d, unlock, ...) \ + do { \ + if (!EINA_MAGIC_CHECK((d), EINA_MAGIC_SHARE_HEAD)) \ + { \ + EINA_MAGIC_FAIL((d), EINA_MAGIC_SHARE_HEAD); \ + unlock; \ + return __VA_ARGS__; \ + } \ + } while (0) + +#define EINA_MAGIC_CHECK_SHARE_COMMON_NODE(d, _node_magic, unlock) \ + do { \ + if (!EINA_MAGIC_CHECK((d), _node_magic)) \ + { \ + EINA_MAGIC_FAIL((d), _node_magic); \ + unlock; \ + } \ + } while (0) + +#ifdef EINA_SHARE_USAGE +typedef struct _Eina_Share_Common_Population Eina_Share_Common_Population; +#endif + +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; + Eina_Magic node_magic; +#ifdef EINA_SHARE_COMMON_USAGE + Eina_Share_Common_Population population; + int max_node_population; +#endif +}; + +struct _Eina_Share_Common +{ + Eina_Share_Common_Head *buckets[EINA_SHARE_COMMON_BUCKETS]; + + EINA_MAGIC +}; + +struct _Eina_Share_Common_Node +{ + Eina_Share_Common_Node *next; + + EINA_MAGIC + + unsigned int length; + unsigned int references; + char str[]; +}; + +struct _Eina_Share_Common_Head +{ + EINA_RBTREE; + EINA_MAGIC + + int hash; + +#ifdef EINA_SHARE_COMMON_USAGE + int population; +#endif + + Eina_Share_Common_Node *head; + Eina_Share_Common_Node builtin_node; +}; + +Eina_Bool _share_common_threads_activated = EINA_FALSE; + +static Eina_Lock _mutex_big; + +#ifdef EINA_SHARE_COMMON_USAGE +struct _Eina_Share_Common_Population +{ + int count; + int max; +}; + +static Eina_Share_Common_Population population = { 0, 0 }; + +static Eina_Share_Common_Population population_group[4] = +{ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 } +}; + +static void +_eina_share_common_population_init(Eina_Share *share) +{ + unsigned int i; + + for (i = 0; + i < sizeof (share->population_group) / + sizeof (share->population_group[0]); + ++i) + { + share->population_group[i].count = 0; + share->population_group[i].max = 0; + } +} + +static void +_eina_share_common_population_shutdown(Eina_Share *share) +{ + unsigned int i; + + share->max_node_population = 0; + share->population.count = 0; + share->population.max = 0; + + for (i = 0; + i < sizeof (share->population_group) / + sizeof (share->population_group[0]); + ++i) + { + share->population_group[i].count = 0; + share->population_group[i].max = 0; + } +} + +static void +_eina_share_common_population_stats(Eina_Share *share) +{ + unsigned int i; + + fprintf(stderr, "eina share_common statistic:\n"); + fprintf(stderr, + " * maximum shared strings : %i\n", + share->population.max); + fprintf(stderr, + " * maximum shared strings per node : %i\n", + share->max_node_population); + + for (i = 0; + i < sizeof (share->population_group) / + sizeof (share->population_group[0]); + ++i) + fprintf(stderr, + "DDD: %i strings of length %i, max strings: %i\n", + share->population_group[i].count, + i, + share->population_group[i].max); +} + +void +eina_share_common_population_add(Eina_Share *share, int slen) +{ + eina_lock_take(&_mutex_big); + + share->population.count++; + if (share->population.count > share->population.max) + share->population.max = share->population.count; + + if (slen < 4) + { + share->population_group[slen].count++; + if (share->population_group[slen].count > + share->population_group[slen].max) + share->population_group[slen].max = + share->population_group[slen].count; + } + + eina_lock_release(&_mutex_big); +} + +void +eina_share_common_population_del(Eina_Share *share, int slen) +{ + eina_lock_take(&_mutex_big); + + share->population.count--; + if (slen < 4) + share->population_group[slen].count--; + + eina_lock_release(&_mutex_big); +} + +static void +_eina_share_common_population_head_init(Eina_Share *share, + Eina_Share_Common_Head *head) +{ + head->population = 1; +} + +static void +_eina_share_common_population_head_add(Eina_Share *share, + Eina_Share_Common_Head *head) +{ + head->population++; + if (head->population > share->max_node_population) + share->max_node_population = head->population; +} + +static void +_eina_share_common_population_head_del(Eina_Share *share, + Eina_Share_Common_Head *head) +{ + head->population--; +} + +#else /* EINA_SHARE_COMMON_USAGE undefined */ + +static void _eina_share_common_population_init(__UNUSED__ Eina_Share *share) { +} +static void _eina_share_common_population_shutdown(__UNUSED__ Eina_Share *share) +{ +} +static void _eina_share_common_population_stats(__UNUSED__ Eina_Share *share) { +} +void eina_share_common_population_add(__UNUSED__ Eina_Share *share, + __UNUSED__ int slen) { +} +void eina_share_common_population_del(__UNUSED__ Eina_Share *share, + __UNUSED__ int slen) { +} +static void _eina_share_common_population_head_init( + __UNUSED__ Eina_Share *share, + __UNUSED__ Eina_Share_Common_Head *head) { +} +static void _eina_share_common_population_head_add( + __UNUSED__ Eina_Share *share, + __UNUSED__ + Eina_Share_Common_Head *head) { +} +static void _eina_share_common_population_head_del( + __UNUSED__ Eina_Share *share, + __UNUSED__ + Eina_Share_Common_Head *head) { +} +#endif + +static int +_eina_share_common_cmp(const Eina_Share_Common_Head *ed, + const int *hash, + __UNUSED__ int length, + __UNUSED__ void *data) +{ + EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, , 0); + + return ed->hash - *hash; +} + +static Eina_Rbtree_Direction +_eina_share_common_node(const Eina_Share_Common_Head *left, + const Eina_Share_Common_Head *right, + __UNUSED__ void *data) +{ + EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(left, , 0); + EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(right, , 0); + + if (left->hash - right->hash < 0) + return EINA_RBTREE_LEFT; + + return EINA_RBTREE_RIGHT; +} + +static void +_eina_share_common_head_free(Eina_Share_Common_Head *ed, __UNUSED__ void *data) +{ + EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, ); + + while (ed->head) + { + Eina_Share_Common_Node *el = ed->head; + + ed->head = ed->head->next; + if (el != &ed->builtin_node) + MAGIC_FREE(el); + } + MAGIC_FREE(ed); +} + +static void +_eina_share_common_node_init(Eina_Share_Common_Node *node, + const char *str, + int slen, + unsigned int null_size, + Eina_Magic node_magic) +{ + EINA_MAGIC_SET(node, node_magic); + node->references = 1; + node->length = slen; + memcpy(node->str, str, slen); + memset(node->str + slen, 0, null_size); /* Nullify the null */ + + (void) node_magic; /* When magic are disable, node_magic is unused, this remove a warning. */ +} + +static Eina_Share_Common_Head * +_eina_share_common_head_alloc(int slen) +{ + Eina_Share_Common_Head *head; + const size_t head_size = offsetof(Eina_Share_Common_Head, builtin_node.str); + + head = malloc(head_size + slen); + if (!head) + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + + return head; +} + +static const char * +_eina_share_common_add_head(Eina_Share *share, + Eina_Share_Common_Head **p_bucket, + int hash, + const char *str, + unsigned int slen, + unsigned int null_size) +{ + Eina_Rbtree **p_tree = (Eina_Rbtree **)p_bucket; + Eina_Share_Common_Head *head; + + head = _eina_share_common_head_alloc(slen + null_size); + if (!head) + return NULL; + + EINA_MAGIC_SET(head, EINA_MAGIC_SHARE_HEAD); + head->hash = hash; + head->head = &head->builtin_node; + _eina_share_common_node_init(head->head, + str, + slen, + null_size, + share->node_magic); + head->head->next = NULL; + + _eina_share_common_population_head_init(share, head); + + *p_tree = eina_rbtree_inline_insert + (*p_tree, EINA_RBTREE_GET(head), + EINA_RBTREE_CMP_NODE_CB(_eina_share_common_node), NULL); + + return head->head->str; +} + +static void +_eina_share_common_del_head(Eina_Share_Common_Head **p_bucket, + Eina_Share_Common_Head *head) +{ + Eina_Rbtree **p_tree = (Eina_Rbtree **)p_bucket; + + *p_tree = eina_rbtree_inline_remove + (*p_tree, EINA_RBTREE_GET(head), + EINA_RBTREE_CMP_NODE_CB(_eina_share_common_node), NULL); + + MAGIC_FREE(head); +} + + +static inline Eina_Bool +_eina_share_common_node_eq(const Eina_Share_Common_Node *node, + const char *str, + unsigned int slen) +{ + return ((node->length == slen) && + (memcmp(node->str, str, slen) == 0)); +} + +static Eina_Share_Common_Node * +_eina_share_common_head_find(Eina_Share_Common_Head *head, + const char *str, + unsigned int slen) +{ + Eina_Share_Common_Node *node, *prev; + + node = head->head; + if (_eina_share_common_node_eq(node, str, slen)) + return node; + + prev = node; + node = node->next; + for (; node; prev = node, node = node->next) + if (_eina_share_common_node_eq(node, str, slen)) + { + /* promote node, make hot items be at the beginning */ + prev->next = node->next; + node->next = head->head; + head->head = node; + return node; + } + + return NULL; +} + +static Eina_Bool +_eina_share_common_head_remove_node(Eina_Share_Common_Head *head, + const Eina_Share_Common_Node *node) +{ + Eina_Share_Common_Node *cur, *prev; + + if (head->head == node) + { + head->head = node->next; + return 1; + } + + prev = head->head; + cur = head->head->next; + for (; cur; prev = cur, cur = cur->next) + if (cur == node) + { + prev->next = cur->next; + return 1; + } + + return 0; +} + +static Eina_Share_Common_Head * +_eina_share_common_find_hash(Eina_Share_Common_Head *bucket, int hash) +{ + return (Eina_Share_Common_Head *)eina_rbtree_inline_lookup + (EINA_RBTREE_GET(bucket), &hash, 0, + EINA_RBTREE_CMP_KEY_CB(_eina_share_common_cmp), NULL); +} + +static Eina_Share_Common_Node * +_eina_share_common_node_alloc(unsigned int slen, unsigned int null_size) +{ + Eina_Share_Common_Node *node; + const size_t node_size = offsetof(Eina_Share_Common_Node, str); + + node = malloc(node_size + slen + null_size); + if (!node) + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + + return node; +} + +static Eina_Share_Common_Node * +_eina_share_common_node_from_str(const char *str, Eina_Magic node_magic) +{ + Eina_Share_Common_Node *node; + const size_t offset = offsetof(Eina_Share_Common_Node, str); + + node = (Eina_Share_Common_Node *)(str - offset); + EINA_MAGIC_CHECK_SHARE_COMMON_NODE(node, node_magic, node = NULL); + return node; + + (void) node_magic; /* When magic are disable, node_magic is unused, this remove a warning. */ +} + +static Eina_Bool +eina_iterator_array_check(const Eina_Rbtree *rbtree __UNUSED__, + Eina_Share_Common_Head *head, + struct dumpinfo *fdata) +{ + Eina_Share_Common_Node *node; + + fdata->used += sizeof(Eina_Share_Common_Head); + for (node = head->head; node; node = node->next) + { + printf("DDD: %5i %5i ", node->length, node->references); + printf("'%.*s'\n", node->length, ((char *)node) + sizeof(Eina_Share_Common_Node)); + fdata->used += sizeof(Eina_Share_Common_Node); + fdata->used += node->length; + fdata->saved += (node->references - 1) * node->length; + fdata->dups += node->references - 1; + fdata->unique++; + } + + return EINA_TRUE; +} + +/** + * @endcond + */ + + +/*============================================================================* +* Global * +*============================================================================*/ + +/** + * @internal + * @brief Initialize the share_common module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the share_common module of Eina. It is called by + * eina_init(). + * + * @see eina_init() + */ +Eina_Bool +eina_share_common_init(Eina_Share **_share, + Eina_Magic node_magic, + const char *node_magic_STR) +{ + 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; + } + + share->node_magic = node_magic; +#define EMS(n) eina_magic_string_static_set(n, n ## _STR) + EMS(EINA_MAGIC_SHARE); + EMS(EINA_MAGIC_SHARE_HEAD); + EMS(node_magic); +#undef EMS + EINA_MAGIC_SET(share->share, EINA_MAGIC_SHARE); + + _eina_share_common_population_init(share); + + /* below is the common part among other all eina_share_common user */ + if (_eina_share_common_count++ != 0) + return EINA_TRUE; + + eina_lock_new(&_mutex_big); + return EINA_TRUE; + + on_error: + _eina_share_common_count--; + return EINA_FALSE; +} + +/** + * @internal + * @brief Shut down the share_common module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the share_common module set up by + * eina_share_common_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_share_common_shutdown(Eina_Share **_share) +{ + unsigned int i; + Eina_Share *share = *_share; + + eina_lock_take(&_mutex_big); + + _eina_share_common_population_stats(share); + + /* remove any string still in the table */ + for (i = 0; i < EINA_SHARE_COMMON_BUCKETS; i++) + { + eina_rbtree_delete(EINA_RBTREE_GET( + share->share->buckets[i]), + EINA_RBTREE_FREE_CB( + _eina_share_common_head_free), NULL); + share->share->buckets[i] = NULL; + } + 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); + + free(*_share); + *_share = NULL; + + /* below is the common part among other all eina_share_common user */ + if (--_eina_share_common_count != 0) + return EINA_TRUE; + + eina_lock_free(&_mutex_big); + + return EINA_TRUE; +} + +#ifdef EFL_HAVE_THREADS + +/** + * @internal + * @brief Activate the share_common mutexes. + * + * This function activate the mutexes in the eina share_common module. It is called by + * eina_threads_init(). + * + * @see eina_threads_init() + */ +void +eina_share_common_threads_init(void) +{ + _share_common_threads_activated = EINA_TRUE; +} + +/** + * @internal + * @brief Shut down the share_common mutexes. + * + * This function shuts down the mutexes in the share_common module. + * It is called by eina_threads_shutdown(). + * + * @see eina_threads_shutdown() + */ +void +eina_share_common_threads_shutdown(void) +{ + _share_common_threads_activated = EINA_FALSE; +} + +#endif + +/*============================================================================* +* API * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +const char * +eina_share_common_add_length(Eina_Share *share, + const char *str, + unsigned int slen, + unsigned int null_size) +{ + Eina_Share_Common_Head **p_bucket, *ed; + Eina_Share_Common_Node *el; + int hash_num, hash; + + if (!str) + return NULL; + + eina_share_common_population_add(share, slen); + + if (slen <= 0) + return NULL; + + hash = eina_hash_superfast(str, slen); + hash_num = hash & 0xFF; + hash = (hash >> 8) & EINA_SHARE_COMMON_MASK; + + eina_lock_take(&_mutex_big); + p_bucket = share->share->buckets + hash_num; + + ed = _eina_share_common_find_hash(*p_bucket, hash); + if (!ed) + { + const char *s = _eina_share_common_add_head(share, + p_bucket, + hash, + str, + slen, + null_size); + eina_lock_release(&_mutex_big); + return s; + } + + EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, eina_lock_release(&_mutex_big), NULL); + + el = _eina_share_common_head_find(ed, str, slen); + if (el) + { + EINA_MAGIC_CHECK_SHARE_COMMON_NODE(el, + share->node_magic, + eina_lock_release(&_mutex_big)); + el->references++; + eina_lock_release(&_mutex_big); + return el->str; + } + + el = _eina_share_common_node_alloc(slen, null_size); + if (!el) + { + eina_lock_release(&_mutex_big); + return NULL; + } + + _eina_share_common_node_init(el, str, slen, null_size, share->node_magic); + el->next = ed->head; + ed->head = el; + _eina_share_common_population_head_add(share, ed); + + eina_lock_release(&_mutex_big); + + return el->str; +} + +const char * +eina_share_common_ref(Eina_Share *share, const char *str) +{ + Eina_Share_Common_Node *node; + + if (!str) + return NULL; + + eina_lock_take(&_mutex_big); + node = _eina_share_common_node_from_str(str, share->node_magic); + if (!node) + { + eina_lock_release(&_mutex_big); + return str; + } + node->references++; + + eina_lock_release(&_mutex_big); + + eina_share_common_population_add(share, node->length); + + return str; +} + + +void +eina_share_common_del(Eina_Share *share, const char *str) +{ + unsigned int slen; + Eina_Share_Common_Head *ed; + Eina_Share_Common_Head **p_bucket; + Eina_Share_Common_Node *node; + int hash_num, hash; + + if (!str) + return; + + eina_lock_take(&_mutex_big); + + node = _eina_share_common_node_from_str(str, share->node_magic); + if (!node) + goto on_error; + + slen = node->length; + eina_share_common_population_del(share, slen); + if (node->references > 1) + { + node->references--; + eina_lock_release(&_mutex_big); + return; + } + + node->references = 0; + + hash = eina_hash_superfast(str, slen); + hash_num = hash & 0xFF; + hash = (hash >> 8) & EINA_SHARE_COMMON_MASK; + + p_bucket = share->share->buckets + hash_num; + ed = _eina_share_common_find_hash(*p_bucket, hash); + if (!ed) + goto on_error; + + EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, eina_lock_release(&_mutex_big)); + + if (!_eina_share_common_head_remove_node(ed, node)) + goto on_error; + + if (node != &ed->builtin_node) + MAGIC_FREE(node); + + if (!ed->head) + _eina_share_common_del_head(p_bucket, ed); + else + _eina_share_common_population_head_del(share, ed); + + eina_lock_release(&_mutex_big); + + return; + +on_error: + eina_lock_release(&_mutex_big); + /* possible segfault happened before here, but... */ + CRITICAL("EEEK trying to del non-shared share_common \"%s\"", str); +} + +int +eina_share_common_length(__UNUSED__ Eina_Share *share, const char *str) +{ + const Eina_Share_Common_Node *node; + + if (!str) + return -1; + + node = _eina_share_common_node_from_str(str, share->node_magic); + if (!node) return 0; + return node->length; +} + +void +eina_share_common_dump(Eina_Share *share, void (*additional_dump)( + struct dumpinfo *), int used) +{ + Eina_Iterator *it; + unsigned int i; + struct dumpinfo di; + + if (!share) + return; + + di.used = used; + di.saved = 0; + di.dups = 0; + di.unique = 0; + printf("DDD: len ref string\n"); + printf("DDD:-------------------\n"); + + eina_lock_take(&_mutex_big); + for (i = 0; i < EINA_SHARE_COMMON_BUCKETS; i++) + { + if (!share->share->buckets[i]) + { + continue; // printf("DDD: BUCKET # %i (HEAD=%i, NODE=%i)\n", i, + + } + +// sizeof(Eina_Share_Common_Head), sizeof(Eina_Share_Common_Node)); + it = eina_rbtree_iterator_prefix( + (Eina_Rbtree *)share->share->buckets[i]); + eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_array_check), &di); + eina_iterator_free(it); + } + if (additional_dump) + additional_dump(&di); + +#ifdef EINA_SHARE_COMMON_USAGE + /* One character strings are not counted in the hash. */ + di.saved += share->population_group[0].count * sizeof(char); + di.saved += share->population_group[1].count * sizeof(char) * 2; +#endif + printf("DDD:-------------------\n"); + printf("DDD: usage (bytes) = %i, saved = %i (%3.0f%%)\n", + di.used, di.saved, di.used ? (di.saved * 100.0 / di.used) : 0.0); + printf("DDD: unique: %d, duplicates: %d (%3.0f%%)\n", + di.unique, di.dups, di.unique ? (di.dups * 100.0 / di.unique) : 0.0); + +#ifdef EINA_SHARE_COMMON_USAGE + printf("DDD: Allocated strings: %i\n", share->population.count); + printf("DDD: Max allocated strings: %i\n", share->population.max); + + for (i = 0; + i < sizeof (share->population_group) / + sizeof (share->population_group[0]); + ++i) + fprintf(stderr, + "DDD: %i strings of length %i, max strings: %i\n", + share->population_group[i].count, + i, + share->population_group[i].max); +#endif + + eina_lock_release(&_mutex_big); +} + +/** + * @endcond + */ diff --git a/libraries/eina/src/lib/eina_share_common.h b/libraries/eina/src/lib/eina_share_common.h new file mode 100644 index 0000000..002c652 --- /dev/null +++ b/libraries/eina/src/lib/eina_share_common.h @@ -0,0 +1,103 @@ +/* EINA - EFL data type library + * Copyright (C) 2002-2008 Carsten Haitzler, Jorge Luis Zapata Muga, Cedric Bail + * + * 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 . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright (C) 2008 Peter Wehrfritz + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies of the Software and its Copyright notices. In addition publicly + * documented acknowledgment must be given that this software has been used if no + * source code of this software is made available publicly. This includes + * acknowledgments in either Copyright notices, Manuals, Publicity and Marketing + * documents or any documentation provided with any product containing this + * software. This License does not apply to any software that links to the + * libraries provided by this software (statically or dynamically), but only to + * the software provided. + * + * Please see the OLD-COPYING.PLAIN for a plain-english explanation of this notice + * and it's intent. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef EINA_SHARE_COMMON_H_ +#define EINA_SHARE_COMMON_H_ + +#include "eina_types.h" +#include "eina_magic.h" + +typedef struct _Eina_Share Eina_Share; + +struct dumpinfo +{ + int used, saved, dups, unique; +}; + +Eina_Bool eina_share_common_init(Eina_Share **share, + Eina_Magic node_magic, + const char *node_magic_STR); +Eina_Bool eina_share_common_shutdown(Eina_Share **share); +const char *eina_share_common_add_length(Eina_Share *share, + const char *str, + unsigned int slen, + 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); +int eina_share_common_length(Eina_Share *share, + const char *str) EINA_CONST +EINA_WARN_UNUSED_RESULT; +void eina_share_common_dump(Eina_Share *share, void (*additional_dump)( + struct dumpinfo *), int used); + + +/* Population functions */ +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_ */ diff --git a/libraries/eina/src/lib/eina_simple_xml_parser.c b/libraries/eina/src/lib/eina_simple_xml_parser.c new file mode 100644 index 0000000..08a8259 --- /dev/null +++ b/libraries/eina/src/lib/eina_simple_xml_parser.c @@ -0,0 +1,1070 @@ +/* EINA - EFL data type library + * Copyright (C) 2011 Gustavo Sverzut Barbieri + * Cedric Bail + * + * 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 +#include + +#ifdef HAVE_EVIL +# include +#endif + +#include "eina_private.h" +#include "eina_log.h" +#include "eina_mempool.h" +#include "eina_stringshare.h" +#include "eina_strbuf.h" +#include "eina_simple_xml_parser.h" + +/*============================================================================* + * Local * + *============================================================================*/ + +/** + * @cond LOCAL + */ + +static Eina_Mempool *_eina_simple_xml_tag_mp = NULL; +static Eina_Mempool *_eina_simple_xml_attribute_mp = NULL; +static int _eina_simple_xml_log_dom = -1; + +static const char EINA_MAGIC_SIMPLE_XML_TAG_STR[] = "Eina Simple XML Tag"; +static const char EINA_MAGIC_SIMPLE_XML_DATA_STR[] = "Eina Simple XML Data"; +static const char EINA_MAGIC_SIMPLE_XML_ATTRIBUTE_STR[] = "Eina Simple XML Attribute"; + +#define EINA_MAGIC_CHECK_TAG(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_SIMPLE_XML_TAG)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_SIMPLE_XML_TAG); \ + return __VA_ARGS__; \ + } \ + } while(0) + +#define EINA_MAGIC_CHECK_DATA(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_SIMPLE_XML_DATA)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_SIMPLE_XML_DATA); \ + return __VA_ARGS__; \ + } \ + } while(0) + +#define EINA_MAGIC_CHECK_ATTRIBUTE(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_SIMPLE_XML_ATTRIBUTE)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_SIMPLE_XML_ATTRIBUTE); \ + return __VA_ARGS__; \ + } \ + } while(0) + + +#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_simple_xml_log_dom, __VA_ARGS__) + +#ifdef WRN +#undef WRN +#endif +#define WRN(...) EINA_LOG_DOM_WARN(_eina_simple_xml_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_simple_xml_log_dom, __VA_ARGS__) + + +static inline const char * +_eina_simple_xml_whitespace_find(const char *itr, const char *itr_end) +{ + for (; itr < itr_end; itr++) + if (isspace(*itr)) break; + return itr; +} + +static inline const char * +_eina_simple_xml_whitespace_skip(const char *itr, const char *itr_end) +{ + for (; itr < itr_end; itr++) + if (!isspace(*itr)) break; + return itr; +} + +static inline const char * +_eina_simple_xml_whitespace_unskip(const char *itr, const char *itr_start) +{ + for (itr--; itr > itr_start; itr--) + if (!isspace(*itr)) break; + return itr + 1; +} + +static inline const char * +_eina_simple_xml_tag_start_find(const char *itr, const char *itr_end) +{ + return memchr(itr, '<', itr_end - itr); +} + +static inline const char * +_eina_simple_xml_tag_end_find(const char *itr, const char *itr_end) +{ + for (; itr < itr_end; itr++) + if ((*itr == '>') || (*itr == '<')) /* consider < also ends a tag */ + return itr; + return NULL; +} + +/** + * @endcond + */ + +/*============================================================================* + * Global * + *============================================================================*/ + + +/** + * @internal + * @brief Initialize the simple xml parser module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the simple xml parser module of Eina. It is called by + * eina_init(). + * + * @see eina_init() + */ +Eina_Bool +eina_simple_xml_init(void) +{ + const char *choice, *tmp; + + _eina_simple_xml_log_dom = eina_log_domain_register("eina_simple_xml", + EINA_LOG_COLOR_DEFAULT); + if (_eina_simple_xml_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_simple_xml"); + return EINA_FALSE; + } + +#ifdef EINA_DEFAULT_MEMPOOL + choice = "pass_through"; +#else + choice = "chained_mempool"; +#endif + tmp = getenv("EINA_MEMPOOL"); + if (tmp && tmp[0]) + choice = tmp; + + _eina_simple_xml_tag_mp = eina_mempool_add + (choice, "simple_xml_tag", NULL, + sizeof(Eina_Simple_XML_Node_Tag), 320); + if (!_eina_simple_xml_tag_mp) + { + ERR("Mempool for simple_xml_tag cannot be allocated in init."); + goto on_init_fail; + } + + _eina_simple_xml_attribute_mp = eina_mempool_add + (choice, "simple_xml_attribute", NULL, + sizeof(Eina_Simple_XML_Attribute), 80); + if (!_eina_simple_xml_attribute_mp) + { + ERR("Mempool for simple_xml_attribute cannot be allocated in init."); + eina_mempool_del(_eina_simple_xml_tag_mp); + goto on_init_fail; + } + +#define EMS(n) eina_magic_string_static_set(n, n ## _STR) + EMS(EINA_MAGIC_SIMPLE_XML_TAG); + EMS(EINA_MAGIC_SIMPLE_XML_DATA); + EMS(EINA_MAGIC_SIMPLE_XML_ATTRIBUTE); +#undef EMS + + return EINA_TRUE; + +on_init_fail: + eina_log_domain_unregister(_eina_simple_xml_log_dom); + _eina_simple_xml_log_dom = -1; + return EINA_FALSE; +} + +/** + * @internal + * @brief Shut down the simple xml parser module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the simple xml parser module set + * up by eina_simple_xml_init(). It is called by + * eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_simple_xml_shutdown(void) +{ + eina_mempool_del(_eina_simple_xml_attribute_mp); + eina_mempool_del(_eina_simple_xml_tag_mp); + + eina_log_domain_unregister(_eina_simple_xml_log_dom); + _eina_simple_xml_log_dom = -1; + return EINA_TRUE; +} + + +/*============================================================================* + * API * + *============================================================================*/ + + +EAPI Eina_Bool +eina_simple_xml_parse(const char *buf, unsigned buflen, Eina_Bool strip, Eina_Simple_XML_Cb func, const void *data) +{ + const char *itr = buf, *itr_end = buf + buflen; + + if (!buf) return EINA_FALSE; + if (!func) return EINA_FALSE; + +#define CB(type, start, end) \ + do \ + { \ + size_t _sz = end - start; \ + Eina_Bool _ret; \ + _ret = func((void*)data, type, start, start - buf, _sz); \ + if (!_ret) return EINA_FALSE; \ + } \ + while (0) + + while (itr < itr_end) + { + if (itr[0] == '<') + { + if (itr + 1 >= itr_end) + { + CB(EINA_SIMPLE_XML_ERROR, itr, itr_end); + return EINA_FALSE; + } + else + { + Eina_Simple_XML_Type type; + size_t toff; + const char *p; + + if (itr[1] == '/') + { + type = EINA_SIMPLE_XML_CLOSE; + toff = 1; + } + else if (itr[1] == '?') + { + type = EINA_SIMPLE_XML_PROCESSING; + toff = 1; + } + else if (itr[1] == '!') + { + if ((itr + sizeof("") - 1 < itr_end) && + (!memcmp(itr + 2, "DOCTYPE", + sizeof("DOCTYPE") - 1)) && + ((itr[2 + sizeof("DOCTYPE") - 1] == '>') || + (isspace(itr[2 + sizeof("DOCTYPE") - 1])))) + { + type = EINA_SIMPLE_XML_DOCTYPE; + toff = sizeof("!DOCTYPE") - 1; + } + else if ((itr + sizeof("") - 1 < itr_end) && + (!memcmp(itr + 2, "--", sizeof("--") - 1))) + { + type = EINA_SIMPLE_XML_COMMENT; + toff = sizeof("!--") - 1; + } + else if ((itr + sizeof("") - 1 < itr_end) && + (!memcmp(itr + 2, "[CDATA[", + sizeof("[CDATA[") - 1))) + { + type = EINA_SIMPLE_XML_CDATA; + toff = sizeof("![CDATA[") - 1; + } + else + { + type = EINA_SIMPLE_XML_OPEN; + toff = 0; + } + } + else + { + type = EINA_SIMPLE_XML_OPEN; + toff = 0; + } + + p = _eina_simple_xml_tag_end_find(itr + 1 + toff, itr_end); + if (p) + { + if (type == EINA_SIMPLE_XML_CDATA) + { + /* must end with ]]> */ + while ((p) && (memcmp(p - 2, "]]>", 3))) + p = _eina_simple_xml_tag_end_find(p + 1, itr_end); + } + + if ((p) && (*p == '<')) + { + type = EINA_SIMPLE_XML_ERROR; + toff = 0; + } + } + + if (p) + { + const char *start, *end; + + start = itr + 1 + toff; + end = p; + + switch (type) + { + case EINA_SIMPLE_XML_OPEN: + if (p[-1] == '/') + { + type = EINA_SIMPLE_XML_OPEN_EMPTY; + end--; + } + break; + case EINA_SIMPLE_XML_CDATA: + if (!memcmp(p - 2, "]]", 2)) end -= 2; + break; + case EINA_SIMPLE_XML_PROCESSING: + if (p[-1] == '?') end--; + break; + case EINA_SIMPLE_XML_COMMENT: + if (!memcmp(p - 2, "--", 2)) end -= 2; + break; + case EINA_SIMPLE_XML_OPEN_EMPTY: + case EINA_SIMPLE_XML_CLOSE: + case EINA_SIMPLE_XML_DATA: + case EINA_SIMPLE_XML_ERROR: + case EINA_SIMPLE_XML_DOCTYPE: + case EINA_SIMPLE_XML_IGNORED: + break; + } + + if ((strip) && (type != EINA_SIMPLE_XML_ERROR)) + { + start = _eina_simple_xml_whitespace_skip + (start, end); + end = _eina_simple_xml_whitespace_unskip + (end, start + 1); + } + + CB(type, start, end); + + if (type != EINA_SIMPLE_XML_ERROR) + itr = p + 1; + else + itr = p; + } + else + { + CB(EINA_SIMPLE_XML_ERROR, itr, itr_end); + return EINA_FALSE; + } + } + } + else + { + const char *p, *end; + + if (strip) + { + p = _eina_simple_xml_whitespace_skip(itr, itr_end); + if (p) + { + CB(EINA_SIMPLE_XML_IGNORED, itr, p); + itr = p; + } + } + + p = _eina_simple_xml_tag_start_find(itr, itr_end); + if (!p) p = itr_end; + + end = p; + if (strip) + end = _eina_simple_xml_whitespace_unskip(end, itr); + + if (itr != end) + CB(EINA_SIMPLE_XML_DATA, itr, end); + + if ((strip) && (end < p)) + CB(EINA_SIMPLE_XML_IGNORED, end, p); + + itr = p; + } + } + +#undef CB + + return EINA_TRUE; +} + +EAPI const char * +eina_simple_xml_tag_attributes_find(const char *buf, unsigned buflen) +{ + const char *itr = buf, *itr_end = buf + buflen; + + for (; itr < itr_end; itr++) + { + if (!isspace(*itr)) + { + /* user skip tagname and already gave it the attributes */ + if (*itr == '=') + return buf; + } + else + { + itr = _eina_simple_xml_whitespace_skip(itr + 1, itr_end); + if (itr == itr_end) + return NULL; + return itr; + } + } + + return NULL; +} + +EAPI Eina_Bool +eina_simple_xml_attributes_parse(const char *buf, unsigned buflen, Eina_Simple_XML_Attribute_Cb func, const void *data) +{ + const char *itr = buf, *itr_end = buf + buflen; + char *tmpbuf = alloca(buflen + 1); + + if (!buf) return EINA_FALSE; + if (!func) return EINA_FALSE; + + while (itr < itr_end) + { + const char *p = _eina_simple_xml_whitespace_skip(itr, itr_end); + const char *key, *key_end, *value, *value_end; + char *tval; + + if (p == itr_end) return EINA_TRUE; + + key = p; + for (key_end = key; key_end < itr_end; key_end++) + if ((*key_end == '=') || (isspace(*key_end))) break; + if (key_end == itr_end) return EINA_FALSE; + if (key_end == key) continue; + + if (*key_end == '=') value = key_end + 1; + else + { + value = memchr(key_end, '=', itr_end - key_end); + if (!value) return EINA_FALSE; + value++; + } + for (; value < itr_end; value++) + if (!isspace(*value)) break; + if (value == itr_end) return EINA_FALSE; + + if ((*value == '"') || (*value == '\'')) + { + value_end = memchr(value + 1, *value, itr_end - value); + if (!value_end) return EINA_FALSE; + value++; + } + else + { + value_end = _eina_simple_xml_whitespace_find(value, itr_end); + } + + memcpy(tmpbuf, key, key_end - key); + tmpbuf[key_end - key] = '\0'; + + tval = tmpbuf + (key_end - key) + 1; + memcpy(tval, value, value_end - value); + tval[value_end - value] = '\0'; + + if (!func((void*)data, tmpbuf, tval)) + return EINA_FALSE; + + itr = value_end + 1; + } + return EINA_TRUE; +} + +/* Node loader *************************************************************/ + +EAPI Eina_Simple_XML_Attribute * +eina_simple_xml_attribute_new(Eina_Simple_XML_Node_Tag *parent, const char *key, const char *value) +{ + Eina_Simple_XML_Attribute *attr; + + if (!key) return NULL; + + attr = eina_mempool_malloc(_eina_simple_xml_attribute_mp, sizeof(*attr)); + if (!attr) + { + ERR("could not allocate memory for attribute from mempool"); + return NULL; + } + + EINA_MAGIC_SET(attr, EINA_MAGIC_SIMPLE_XML_ATTRIBUTE); + attr->parent = parent; + attr->key = eina_stringshare_add(key); + attr->value = eina_stringshare_add(value ? value : ""); + + if (parent) + parent->attributes = eina_inlist_append + (parent->attributes, EINA_INLIST_GET(attr)); + + return attr; +} + +EAPI void +eina_simple_xml_attribute_free(Eina_Simple_XML_Attribute *attr) +{ + EINA_MAGIC_CHECK_ATTRIBUTE(attr); + + if (attr->parent) + attr->parent->attributes = eina_inlist_remove + (attr->parent->attributes, EINA_INLIST_GET(attr)); + + eina_stringshare_del(attr->key); + eina_stringshare_del(attr->value); + EINA_MAGIC_SET(attr, EINA_MAGIC_NONE); + eina_mempool_free(_eina_simple_xml_attribute_mp, attr); +} + +static void +_eina_simple_xml_node_data_free(Eina_Simple_XML_Node_Data *node) +{ + if (node->base.parent) + node->base.parent->children = eina_inlist_remove + (node->base.parent->children, EINA_INLIST_GET(&node->base)); + + EINA_MAGIC_SET(&node->base, EINA_MAGIC_NONE); + free(node); +} + +EAPI Eina_Simple_XML_Node_Tag * +eina_simple_xml_node_tag_new(Eina_Simple_XML_Node_Tag *parent, const char *name) +{ + Eina_Simple_XML_Node_Tag *n; + + if (!name) return NULL; + + n = eina_mempool_malloc(_eina_simple_xml_tag_mp, sizeof(*n)); + if (!n) + { + ERR("could not allocate memory for node from mempool"); + return NULL; + } + + memset(n, 0, sizeof(*n)); + + EINA_MAGIC_SET(&n->base, EINA_MAGIC_SIMPLE_XML_TAG); + + n->base.type = EINA_SIMPLE_XML_NODE_TAG; + n->base.parent = parent; + n->name = eina_stringshare_add(name); + + if (parent) + parent->children = eina_inlist_append + (parent->children, EINA_INLIST_GET(&n->base)); + + return n; +} + +void +_eina_simple_xml_node_tag_free(Eina_Simple_XML_Node_Tag *tag) +{ + while (tag->children) + { + Eina_Simple_XML_Node *n = EINA_INLIST_CONTAINER_GET + (tag->children, Eina_Simple_XML_Node); + if (n->type == EINA_SIMPLE_XML_NODE_TAG) + _eina_simple_xml_node_tag_free((Eina_Simple_XML_Node_Tag *)n); + else + _eina_simple_xml_node_data_free((Eina_Simple_XML_Node_Data *)n); + } + + while (tag->attributes) + { + Eina_Simple_XML_Attribute *a = EINA_INLIST_CONTAINER_GET + (tag->attributes, Eina_Simple_XML_Attribute); + eina_simple_xml_attribute_free(a); + } + + if (tag->base.parent) + tag->base.parent->children = eina_inlist_remove + (tag->base.parent->children, EINA_INLIST_GET(&tag->base)); + + eina_stringshare_del(tag->name); + EINA_MAGIC_SET(&tag->base, EINA_MAGIC_NONE); + eina_mempool_free(_eina_simple_xml_tag_mp, tag); +} + +EAPI void +eina_simple_xml_node_tag_free(Eina_Simple_XML_Node_Tag *tag) +{ + EINA_MAGIC_CHECK_TAG(&tag->base); + if (tag->base.type != EINA_SIMPLE_XML_NODE_TAG) + { + ERR("expected tag node!"); + return; + } + _eina_simple_xml_node_tag_free(tag); +} + +static Eina_Simple_XML_Node_Data * +_eina_simple_xml_node_data_new(Eina_Simple_XML_Node_Tag *parent, Eina_Simple_XML_Node_Type type, const char *content, unsigned length) +{ + Eina_Simple_XML_Node_Data *n = malloc(sizeof(*n) + length + 1); + + if (!content) return NULL; + + if (!n) + { + ERR("could not allocate memory for node"); + return NULL; + } + + EINA_MAGIC_SET(&n->base, EINA_MAGIC_SIMPLE_XML_DATA); + n->base.type = type; + n->base.parent = parent; + + n->length = length; + memcpy(n->data, content, length); + n->data[length] = '\0'; + + if (parent) + parent->children = eina_inlist_append + (parent->children, EINA_INLIST_GET(&n->base)); + + return n; +} + +EAPI Eina_Simple_XML_Node_Data * +eina_simple_xml_node_data_new(Eina_Simple_XML_Node_Tag *parent, const char *contents, size_t length) +{ + return _eina_simple_xml_node_data_new + (parent, EINA_SIMPLE_XML_NODE_DATA, contents, length); +} + +EAPI void +eina_simple_xml_node_data_free(Eina_Simple_XML_Node_Data *node) +{ + EINA_MAGIC_CHECK_DATA(&node->base); + if (node->base.type != EINA_SIMPLE_XML_NODE_DATA) + { + ERR("expected node of type: data!"); + return; + } + _eina_simple_xml_node_data_free(node); +} + +EAPI Eina_Simple_XML_Node_CData * +eina_simple_xml_node_cdata_new(Eina_Simple_XML_Node_Tag *parent, const char *contents, size_t length) +{ + return _eina_simple_xml_node_data_new + (parent, EINA_SIMPLE_XML_NODE_CDATA, contents, length); +} + +EAPI void +eina_simple_xml_node_cdata_free(Eina_Simple_XML_Node_Data *node) +{ + EINA_MAGIC_CHECK_DATA(&node->base); + if (node->base.type != EINA_SIMPLE_XML_NODE_CDATA) + { + ERR("expected node of type: cdata!"); + return; + } + _eina_simple_xml_node_data_free(node); +} + +EAPI Eina_Simple_XML_Node_Processing * +eina_simple_xml_node_processing_new(Eina_Simple_XML_Node_Tag *parent, const char *contents, size_t length) +{ + return _eina_simple_xml_node_data_new + (parent, EINA_SIMPLE_XML_NODE_PROCESSING, contents, length); +} + +EAPI void +eina_simple_xml_node_processing_free(Eina_Simple_XML_Node_Data *node) +{ + EINA_MAGIC_CHECK_DATA(&node->base); + if (node->base.type != EINA_SIMPLE_XML_NODE_PROCESSING) + { + ERR("expected node of type: processing!"); + return; + } + _eina_simple_xml_node_data_free(node); +} + +EAPI Eina_Simple_XML_Node_Doctype * +eina_simple_xml_node_doctype_new(Eina_Simple_XML_Node_Tag *parent, const char *contents, size_t length) +{ + return _eina_simple_xml_node_data_new + (parent, EINA_SIMPLE_XML_NODE_DOCTYPE, contents, length); +} + +EAPI void +eina_simple_xml_node_doctype_free(Eina_Simple_XML_Node_Data *node) +{ + EINA_MAGIC_CHECK_DATA(&node->base); + if (node->base.type != EINA_SIMPLE_XML_NODE_DOCTYPE) + { + ERR("expected node of type: doctype!"); + return; + } + _eina_simple_xml_node_data_free(node); +} + +EAPI Eina_Simple_XML_Node_Comment * +eina_simple_xml_node_comment_new(Eina_Simple_XML_Node_Tag *parent, const char *contents, size_t length) +{ + return _eina_simple_xml_node_data_new + (parent, EINA_SIMPLE_XML_NODE_COMMENT, contents, length); +} + +EAPI void +eina_simple_xml_node_comment_free(Eina_Simple_XML_Node_Data *node) +{ + EINA_MAGIC_CHECK_DATA(&node->base); + if (node->base.type != EINA_SIMPLE_XML_NODE_COMMENT) + { + ERR("expected node of type: comment!"); + return; + } + _eina_simple_xml_node_data_free(node); +} + +struct eina_simple_xml_node_load_ctxt +{ + Eina_Simple_XML_Node_Root *root; + Eina_Simple_XML_Node_Tag *current; +}; + +static Eina_Bool +_eina_simple_xml_attrs_parse(void *data, const char *key, const char *value) +{ + Eina_Simple_XML_Node_Tag *n = data; + Eina_Simple_XML_Attribute *attr; + + attr = eina_simple_xml_attribute_new(n, key, value); + return !!attr; +} + +static Eina_Bool +_eina_simple_xml_node_parse(void *data, Eina_Simple_XML_Type type, const char *content, unsigned offset, unsigned length) +{ + struct eina_simple_xml_node_load_ctxt *ctx = data; + + switch (type) + { + case EINA_SIMPLE_XML_OPEN: + case EINA_SIMPLE_XML_OPEN_EMPTY: + { + Eina_Simple_XML_Node_Tag *n; + const char *name, *name_end, *attrs; + + attrs = eina_simple_xml_tag_attributes_find(content, length); + if (!attrs) + name_end = content + length; + else + name_end = attrs; + + name_end = _eina_simple_xml_whitespace_unskip(name_end, content); + + name = eina_stringshare_add_length(content, name_end - content); + n = eina_simple_xml_node_tag_new(ctx->current, name); + eina_stringshare_del(name); + if (!n) return EINA_FALSE; + + if (attrs) + eina_simple_xml_attributes_parse + (attrs, length - (attrs - content), + _eina_simple_xml_attrs_parse, n); + + if (type == EINA_SIMPLE_XML_OPEN) + ctx->current = n; + } + break; + + case EINA_SIMPLE_XML_CLOSE: + if (ctx->current->base.parent) + { + const char *end = _eina_simple_xml_whitespace_unskip + (content + length, content); + int len; + len = end - content; + if ((len == 0) /* closes the tag for us. */ || + ((eina_stringshare_strlen(ctx->current->name) == len) && + (memcmp(ctx->current->name, content, len) == 0))) + ctx->current = ctx->current->base.parent; + else + WRN("closed incorrect tag: '%.*s', '%s' was expected!", + len, content, ctx->current->name); + } + else + WRN("closed tag '%.*s' but already at document root!", + length, content); + break; + + case EINA_SIMPLE_XML_DATA: + return !!eina_simple_xml_node_data_new + (ctx->current, content, length); + case EINA_SIMPLE_XML_CDATA: + return !!eina_simple_xml_node_cdata_new + (ctx->current, content, length); + case EINA_SIMPLE_XML_PROCESSING: + return !!eina_simple_xml_node_processing_new + (ctx->current, content, length); + case EINA_SIMPLE_XML_DOCTYPE: + return !!eina_simple_xml_node_doctype_new + (ctx->current, content, length); + case EINA_SIMPLE_XML_COMMENT: + return !!eina_simple_xml_node_comment_new + (ctx->current, content, length); + + case EINA_SIMPLE_XML_ERROR: + ERR("parser error at offset %u-%u: %.*s", + offset, length, length, content); + break; + case EINA_SIMPLE_XML_IGNORED: + DBG("ignored contents at offset %u-%u: %.*s", + offset, length, length, content); + break; + } + + return EINA_TRUE; +} + +EAPI Eina_Simple_XML_Node_Root * +eina_simple_xml_node_load(const char *buf, unsigned buflen, Eina_Bool strip) +{ + Eina_Simple_XML_Node_Root *root; + struct eina_simple_xml_node_load_ctxt ctx; + + if (!buf) return NULL; + + root = eina_mempool_malloc(_eina_simple_xml_tag_mp, sizeof(*root)); + if (!root) return NULL; + + memset(root, 0, sizeof(*root)); + EINA_MAGIC_SET(&root->base, EINA_MAGIC_SIMPLE_XML_TAG); + root->base.type = EINA_SIMPLE_XML_NODE_ROOT; + + ctx.root = root; + ctx.current = root; + eina_simple_xml_parse(buf, buflen, strip, _eina_simple_xml_node_parse, &ctx); + + return root; +} + +EAPI void +eina_simple_xml_node_root_free(Eina_Simple_XML_Node_Root *root) +{ + if (!root) return; + EINA_MAGIC_CHECK_TAG(&root->base); + if (root->base.type != EINA_SIMPLE_XML_NODE_ROOT) + { + ERR("expected root node!"); + return; + } + _eina_simple_xml_node_tag_free(root); +} + +static inline void +_eina_simple_xml_node_dump_indent(Eina_Strbuf *buf, const char *indent, unsigned level) +{ + unsigned i, indent_len = strlen(indent); + for (i = 0; i < level; i++) + eina_strbuf_append_length(buf, indent, indent_len); +} + +static void +_eina_simple_xml_node_tag_attributes_append(Eina_Strbuf *buf, Eina_Simple_XML_Node_Tag *tag) +{ + Eina_Simple_XML_Attribute *a; + + EINA_INLIST_FOREACH(tag->attributes, a) + eina_strbuf_append_printf(buf, " %s=\"%s\"", a->key, a->value); +} + +static void _eina_simple_xml_node_dump(Eina_Strbuf *buf, Eina_Simple_XML_Node *node, const char *indent, unsigned level); + +static void +_eina_simple_xml_node_children_dump(Eina_Strbuf *buf, Eina_Simple_XML_Node_Tag *tag, const char *indent, unsigned level) +{ + Eina_Simple_XML_Node *node; + + EINA_INLIST_FOREACH(tag->children, node) + _eina_simple_xml_node_dump(buf, node, indent, level); +} + +static void +_eina_simple_xml_node_dump(Eina_Strbuf *buf, Eina_Simple_XML_Node *node, const char *indent, unsigned level) +{ + switch (node->type) + { + case EINA_SIMPLE_XML_NODE_ROOT: + _eina_simple_xml_node_children_dump + (buf, (Eina_Simple_XML_Node_Tag *)node, indent, level); + break; + + case EINA_SIMPLE_XML_NODE_TAG: + { + Eina_Simple_XML_Node_Tag *n = (Eina_Simple_XML_Node_Tag *)node; + + if (indent) _eina_simple_xml_node_dump_indent(buf, indent, level); + + eina_strbuf_append_char(buf, '<'); + eina_strbuf_append_length + (buf, n->name, eina_stringshare_strlen(n->name)); + + if (n->attributes) + _eina_simple_xml_node_tag_attributes_append(buf, n); + + if (n->children) + eina_strbuf_append_char(buf, '>'); + else + eina_strbuf_append_length(buf, "/>", sizeof("/>") - 1); + + if (indent) eina_strbuf_append_char(buf, '\n'); + + if (n->children) + { + _eina_simple_xml_node_children_dump(buf, n, indent, level + 1); + + if (indent) + _eina_simple_xml_node_dump_indent(buf, indent, level); + + eina_strbuf_append_length(buf, "name, eina_stringshare_strlen(n->name)); + eina_strbuf_append_char(buf, '>'); + + if (indent) eina_strbuf_append_char(buf, '\n'); + } + } + break; + case EINA_SIMPLE_XML_NODE_DATA: + { + Eina_Simple_XML_Node_Data *n = (Eina_Simple_XML_Node_Data *)node; + + if (indent) _eina_simple_xml_node_dump_indent(buf, indent, level); + eina_strbuf_append_length(buf, n->data, n->length); + if (indent) eina_strbuf_append_char(buf, '\n'); + } + break; + + case EINA_SIMPLE_XML_NODE_CDATA: + { + Eina_Simple_XML_Node_Data *n = (Eina_Simple_XML_Node_Data *)node; + + if (indent) _eina_simple_xml_node_dump_indent(buf, indent, level); + eina_strbuf_append_length(buf, "data, n->length); + eina_strbuf_append_length(buf, "]]>", sizeof("]]>") - 1); + if (indent) eina_strbuf_append_char(buf, '\n'); + } + break; + + case EINA_SIMPLE_XML_NODE_PROCESSING: + { + Eina_Simple_XML_Node_Data *n = (Eina_Simple_XML_Node_Data *)node; + + if (indent) _eina_simple_xml_node_dump_indent(buf, indent, level); + eina_strbuf_append_length(buf, "data, n->length); + eina_strbuf_append_length(buf, " ?>", sizeof(" ?>") - 1); + if (indent) eina_strbuf_append_char(buf, '\n'); + } + break; + + case EINA_SIMPLE_XML_NODE_DOCTYPE: + { + Eina_Simple_XML_Node_Data *n = (Eina_Simple_XML_Node_Data *)node; + + if (indent) _eina_simple_xml_node_dump_indent(buf, indent, level); + eina_strbuf_append_length + (buf, "data, n->length); + eina_strbuf_append_char(buf, '>'); + if (indent) eina_strbuf_append_char(buf, '\n'); + } + break; + + case EINA_SIMPLE_XML_NODE_COMMENT: + { + Eina_Simple_XML_Node_Data *n = (Eina_Simple_XML_Node_Data *)node; + + if (indent) _eina_simple_xml_node_dump_indent(buf, indent, level); + eina_strbuf_append_length(buf, "", sizeof(" -->") - 1); + if (indent) eina_strbuf_append_char(buf, '\n'); + } + break; + } +} + +EAPI char * +eina_simple_xml_node_dump(Eina_Simple_XML_Node *node, const char *indent) +{ + Eina_Strbuf *buf; + char *ret; + + if (!node) return NULL; + + buf = eina_strbuf_new(); + if (!buf) return NULL; + + _eina_simple_xml_node_dump(buf, node, indent, 0); + + ret = eina_strbuf_string_steal(buf); + eina_strbuf_free(buf); + return ret; +} diff --git a/libraries/eina/src/lib/eina_str.c b/libraries/eina/src/lib/eina_str.c new file mode 100644 index 0000000..8d27c65 --- /dev/null +++ b/libraries/eina/src/lib/eina_str.c @@ -0,0 +1,462 @@ +/* Leave the OpenBSD version below so we can track upstream fixes */ +/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include + +#ifdef HAVE_ICONV +# include +# include +#endif + +#include "eina_private.h" +#include "eina_str.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +/* + * Internal helper function used by eina_str_has_suffix() and + * eina_str_has_extension() + */ +static inline Eina_Bool +eina_str_has_suffix_helper(const char *str, + const char *suffix, + int (*cmp)(const char *, const char *)) +{ + size_t str_len; + size_t suffix_len; + + if ((!str) || (!suffix)) return EINA_FALSE; + str_len = strlen(str); + suffix_len = eina_strlen_bounded(suffix, str_len); + if (suffix_len == (size_t)-1) + return EINA_FALSE; + + return cmp(str + str_len - suffix_len, suffix) == 0; +} + +static inline char ** +eina_str_split_full_helper(const char *str, + const char *delim, + int max_tokens, + unsigned int *elements) +{ + char *s, **str_array; + const char *src; + size_t len, dlen; + unsigned int tokens; + + dlen = strlen(delim); + if (dlen == 0) + { + if (elements) + *elements = 0; + + return NULL; + } + + tokens = 0; + src = str; + /* count tokens and check strlen(str) */ + while (*src != '\0') + { + const char *d = delim, *d_end = d + dlen; + const char *tmp = src; + for (; (d < d_end) && (*tmp != '\0'); d++, tmp++) + { + if (EINA_LIKELY(*d != *tmp)) + break; + } + if (EINA_UNLIKELY(d == d_end)) + { + src = tmp; + tokens++; + } + else + src++; + } + len = src - str; + + if ((max_tokens > 0) && (tokens > (unsigned int)max_tokens)) + tokens = max_tokens; + + str_array = malloc(sizeof(char *) * (tokens + 2)); + if (!str_array) + { + if (elements) + *elements = 0; + + return NULL; + } + + s = malloc(len + 1); + if (!s) + { + free(str_array); + if (elements) + *elements = 0; + + return NULL; + } + + /* copy tokens and string */ + tokens = 0; + str_array[0] = s; + src = str; + while (*src != '\0') + { + const char *d = delim, *d_end = d + dlen; + const char *tmp = src; + for (; (d < d_end) && (*tmp != '\0'); d++, tmp++) + { + if (EINA_LIKELY(*d != *tmp)) + break; + } + if (EINA_UNLIKELY(d == d_end)) + { + src = tmp; + *s = '\0'; + s += dlen; + tokens++; + str_array[tokens] = s; + } + else + { + *s = *src; + s++; + src++; + } + } + *s = '\0'; + str_array[tokens + 1] = NULL; + if (elements) + *elements = (tokens + 1); + + return str_array; +} + +/** + * @endcond + */ + +/*============================================================================* +* Global * +*============================================================================*/ + +/*============================================================================* +* API * +*============================================================================*/ + +EAPI size_t +eina_strlcpy(char *dst, const char *src, size_t siz) +{ +#ifdef HAVE_STRLCPY + return strlcpy(dst, src, siz); +#else + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0) + while (--n != 0) + { + if ((*d++ = *s++) == '\0') + break; + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) + { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +#endif +} + +EAPI size_t +eina_strlcat(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + + while (*s != '\0') { + if (n != 1) + { + *d++ = *s; + n--; + } + + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} + +EAPI Eina_Bool +eina_str_has_prefix(const char *str, const char *prefix) +{ + size_t str_len; + size_t prefix_len; + + str_len = strlen(str); + prefix_len = eina_strlen_bounded(prefix, str_len); + if (prefix_len == (size_t)-1) + return EINA_FALSE; + + return (strncmp(str, prefix, prefix_len) == 0); +} + +EAPI Eina_Bool +eina_str_has_suffix(const char *str, const char *suffix) +{ + return eina_str_has_suffix_helper(str, suffix, strcmp); +} + +EAPI Eina_Bool +eina_str_has_extension(const char *str, const char *ext) +{ + return eina_str_has_suffix_helper(str, ext, strcasecmp); +} + +EAPI char ** +eina_str_split_full(const char *str, + const char *delim, + int max_tokens, + unsigned int *elements) +{ + return eina_str_split_full_helper(str, delim, max_tokens, elements); +} + + +EAPI char ** +eina_str_split(const char *str, const char *delim, int max_tokens) +{ + return eina_str_split_full_helper(str, delim, max_tokens, NULL); +} + +EAPI size_t +eina_str_join_len(char *dst, + size_t size, + char sep, + const char *a, + size_t a_len, + const char *b, + size_t b_len) +{ + size_t ret = a_len + b_len + 1; + size_t off; + + if (size < 1) + return ret; + + if (size <= a_len) + { + memcpy(dst, a, size - 1); + dst[size - 1] = '\0'; + return ret; + } + + memcpy(dst, a, a_len); + off = a_len; + + if (size <= off + 1) + { + dst[size - 1] = '\0'; + return ret; + } + + dst[off] = sep; + off++; + + if (size <= off + b_len + 1) + { + memcpy(dst + off, b, size - off - 1); + dst[size - 1] = '\0'; + return ret; + } + + memcpy(dst + off, b, b_len); + dst[off + b_len] = '\0'; + return ret; +} + +#ifdef HAVE_ICONV +EAPI char * +eina_str_convert(const char *enc_from, const char *enc_to, const char *text) +{ + iconv_t ic; + char *new_txt, *inp, *outp; + size_t inb, outb, outlen, tob, outalloc; + + if (!text) + return NULL; + + ic = iconv_open(enc_to, enc_from); + if (ic == (iconv_t)(-1)) + return NULL; + + new_txt = malloc(64); + inb = strlen(text); + outb = 64; + inp = (char *)text; + outp = new_txt; + outalloc = 64; + outlen = 0; + + for (;; ) + { + size_t count; + + tob = outb; + count = iconv(ic, &inp, &inb, &outp, &outb); + outlen += tob - outb; + if (count == (size_t)(-1)) + { + if (errno == E2BIG) + { + new_txt = realloc(new_txt, outalloc + 64); + outp = new_txt + outlen; + outalloc += 64; + outb += 64; + } + else if (errno == EILSEQ) + { + if (new_txt) + free(new_txt); + + new_txt = NULL; + break; + } + else if (errno == EINVAL) + { + if (new_txt) + free(new_txt); + + new_txt = NULL; + break; + } + else + { + if (new_txt) + free(new_txt); + + new_txt = NULL; + break; + } + } + + if (inb == 0) + { + if (outalloc == outlen) + new_txt = realloc(new_txt, outalloc + 1); + + new_txt[outlen] = 0; + break; + } + } + iconv_close(ic); + return new_txt; +} +#else +EAPI char * +eina_str_convert(const char *enc_from __UNUSED__, + const char *enc_to __UNUSED__, + const char *text __UNUSED__) +{ + return NULL; +} +#endif + +EAPI char * +eina_str_escape(const char *str) +{ + char *s2, *d; + const char *s; + + s2 = malloc((strlen(str) * 2) + 1); + if (!s2) + return NULL; + + for (s = str, d = s2; *s != 0; s++, d++) + { + if ((*s == ' ') || (*s == '\\') || (*s == '\'')) + { + *d = '\\'; + d++; + } + + *d = *s; + } + *d = 0; + return s2; +} + +EAPI void +eina_str_tolower(char **str) +{ + char *p; + if ((!str) || (!(*str))) + return; + + for (p = *str; (*p); p++) + *p = tolower((unsigned char )(*p)); +} + +EAPI void +eina_str_toupper(char **str) +{ + char *p; + if ((!str) || (!(*str))) + return; + + for (p = *str; (*p); p++) + *p = toupper((unsigned char)(*p)); +} diff --git a/libraries/eina/src/lib/eina_strbuf.c b/libraries/eina/src/lib/eina_strbuf.c new file mode 100644 index 0000000..74b1eb9 --- /dev/null +++ b/libraries/eina/src/lib/eina_strbuf.c @@ -0,0 +1,202 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_EVIL +# include +#endif + +#include "eina_private.h" +#include "eina_str.h" +#include "eina_strbuf_common.h" +#include "eina_unicode.h" + +/*============================================================================* + * Local * + *============================================================================*/ + +/** + * @cond LOCAL + */ + +#ifdef _STRBUF_DATA_TYPE +# undef _STRBUF_DATA_TYPE +#endif + +#ifdef _STRBUF_CSIZE +# undef _STRBUF_CSIZE +#endif + +#ifdef _STRBUF_STRUCT_NAME +# undef _STRBUF_STRUCT_NAME +#endif + +#ifdef _STRBUF_STRLEN_FUNC +# undef _STRBUF_STRLEN_FUNC +#endif + +#ifdef _STRBUF_STRESCAPE_FUNC +# undef _STRBUF_STRESCAPE_FUNC +#endif + +#ifdef _STRBUF_MAGIC +# undef _STRBUF_MAGIC +#endif + +#ifdef _STRBUF_MAGIC_STR +# undef _STRBUF_MAGIC_STR +#endif + +#ifdef _FUNC_EXPAND +# undef _FUNC_EXPAND +#endif + + +#define _STRBUF_DATA_TYPE char +#define _STRBUF_CSIZE sizeof(_STRBUF_DATA_TYPE) +#define _STRBUF_STRUCT_NAME Eina_Strbuf +#define _STRBUF_STRLEN_FUNC(x) strlen(x) +#define _STRBUF_STRESCAPE_FUNC(x) eina_str_escape(x) +#define _STRBUF_MAGIC EINA_MAGIC_STRBUF +#define _STRBUF_MAGIC_STR __STRBUF_MAGIC_STR +static const char __STRBUF_MAGIC_STR[] = "Eina Strbuf"; + +#define _FUNC_EXPAND(y) eina_strbuf_ ## y + +/** + * @endcond + */ + + +/*============================================================================* + * Global * + *============================================================================*/ + + +/*============================================================================* + * API * + *============================================================================*/ + + +EAPI Eina_Bool +eina_strbuf_append_printf(Eina_Strbuf *buf, const char *fmt, ...) +{ + va_list args; + char *str; + size_t len; + Eina_Bool ret; + + va_start(args, fmt); + len = vasprintf(&str, fmt, args); + va_end(args); + + if (len <= 0 || !str) + return EINA_FALSE; + + ret = eina_strbuf_append_length(buf, str, len); + free(str); + return ret; +} + +EAPI Eina_Bool +eina_strbuf_append_vprintf(Eina_Strbuf *buf, const char *fmt, va_list args) +{ + char *str; + size_t len; + Eina_Bool ret; + + len = vasprintf(&str, fmt, args); + + if (len <= 0 || !str) + return EINA_FALSE; + + ret = eina_strbuf_append_length(buf, str, len); + free(str); + return ret; +} + +EAPI Eina_Bool +eina_strbuf_insert_printf(Eina_Strbuf *buf, const char *fmt, size_t pos, ...) +{ + va_list args; + char *str; + size_t len; + Eina_Bool ret; + + va_start(args, pos); + len = vasprintf(&str, fmt, args); + va_end(args); + + if (len <= 0 || !str) + return EINA_FALSE; + + ret = eina_strbuf_insert(buf, str, pos); + free(str); + return ret; +} + +EAPI Eina_Bool +eina_strbuf_insert_vprintf(Eina_Strbuf *buf, + const char *fmt, + size_t pos, + va_list args) +{ + char *str; + size_t len; + Eina_Bool ret; + + len = vasprintf(&str, fmt, args); + + if (len <= 0 || !str) + return EINA_FALSE; + + ret = eina_strbuf_insert(buf, str, pos); + free(str); + return ret; +} + +EAPI void +eina_strbuf_trim(Eina_Strbuf *buf) +{ + char *c = buf->buf; + + while (buf->len > 0 && isspace(((unsigned char*)(buf->buf))[buf->len - 1])) + buf->len--; + while (buf->len > 0 && isspace(*c)) + { + c++; + buf->len--; + } + memmove(buf->buf, c, buf->len); + ((unsigned char *)buf->buf)[buf->len] = '\0'; +} + +EAPI void +eina_strbuf_ltrim(Eina_Strbuf *buf) +{ + char *c = buf->buf; + + while (buf->len > 0 && isspace(*c)) + { + c++; + buf->len--; + } + memmove(buf->buf, c, buf->len); + ((unsigned char *)buf->buf)[buf->len] = '\0'; +} + +EAPI void +eina_strbuf_rtrim(Eina_Strbuf *buf) +{ + while (buf->len > 0 && isspace(((unsigned char*)(buf->buf))[buf->len - 1])) + buf->len--; + ((unsigned char *)buf->buf)[buf->len] = '\0'; +} + +/* Unicode */ + +#include "eina_strbuf_template_c.x" diff --git a/libraries/eina/src/lib/eina_strbuf_common.c b/libraries/eina/src/lib/eina_strbuf_common.c new file mode 100644 index 0000000..46067cd --- /dev/null +++ b/libraries/eina/src/lib/eina_strbuf_common.c @@ -0,0 +1,874 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef _WIN32 +# include +#endif + +#include "eina_private.h" +#include "eina_str.h" +#include "eina_magic.h" +#include "eina_error.h" +#include "eina_safety_checks.h" +#include "eina_strbuf.h" +#include "eina_strbuf_common.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +#define EINA_STRBUF_INIT_SIZE 32 +#define EINA_STRBUF_INIT_STEP 32 +#define EINA_STRBUF_MAX_STEP 4096 + +/** + * @endcond + */ + +/*============================================================================* +* Global * +*============================================================================*/ + +/** + * @internal + * @brief Initialize the strbuf module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the strbuf module of Eina. It is called by + * eina_init(). + * + * @see eina_init() + */ +Eina_Bool +eina_strbuf_common_init(void) +{ + return EINA_TRUE; +} + +/** + * @internal + * @brief Shut down the strbuf module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the strbuf module set up by + * eina_strbuf_common_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_strbuf_common_shutdown(void) +{ + return EINA_TRUE; +} + +/** + * @internal + * + * init the buffer + * @param csize the character size + * @param buf the buffer to init + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + */ +static Eina_Bool +_eina_strbuf_common_init(size_t csize, Eina_Strbuf *buf) +{ + buf->len = 0; + buf->size = EINA_STRBUF_INIT_SIZE; + buf->step = EINA_STRBUF_INIT_STEP; + + eina_error_set(0); + buf->buf = calloc(csize, buf->size); + if (EINA_UNLIKELY(!buf->buf)) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +/** + * @internal + * + * init the buffer without allocating the actual string (for managed) + * @param csize the character size + * @param buf the buffer to init + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + */ +static Eina_Bool +_eina_strbuf_common_manage_init(size_t csize __UNUSED__, + Eina_Strbuf *buf, + void *str, + size_t len) +{ + buf->len = len; + buf->size = len + 1; + buf->step = EINA_STRBUF_INIT_STEP; + buf->buf = str; + + return EINA_TRUE; +} + + +/** + * @internal + * + * resize the buffer + * @param csize the character size + * @param buf the buffer to resize + * @param size the minimum size of the buffer + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + */ +static inline Eina_Bool +_eina_strbuf_common_resize(size_t csize, Eina_Strbuf *buf, size_t size) +{ + size_t new_size, new_step, delta; + void *buffer; + + size += 1; // Add extra space for '\0' + + /* nothing to do */ + if (size == buf->size) return EINA_TRUE; + else if (size > buf->size) delta = size - buf->size; + else delta = buf->size - size; + + /* check if should keep the same step (just used while growing) */ + if ((delta <= buf->step) && (size > buf->size)) new_step = buf->step; + else + { + new_step = (((delta / EINA_STRBUF_INIT_STEP) + 1) + * EINA_STRBUF_INIT_STEP); + if (new_step > EINA_STRBUF_MAX_STEP) new_step = EINA_STRBUF_MAX_STEP; + } + + new_size = (((size / new_step) + 1) * new_step); + + /* reallocate the buffer to the new size */ + buffer = realloc(buf->buf, new_size * csize); + if (EINA_UNLIKELY(!buffer)) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + + buf->buf = buffer; + buf->size = new_size; + buf->step = new_step; + eina_error_set(0); + return EINA_TRUE; +} + +/** + * @internal + * + * If required, enlarge the buffer to fit the new size. + * + * @param csize the character size + * @param buf the buffer to resize + * @param size the minimum size of the buffer + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + */ +Eina_Bool +_eina_strbuf_common_grow(size_t csize, Eina_Strbuf *buf, size_t size) +{ + if ((size + 1) < buf->size) return EINA_TRUE; + return _eina_strbuf_common_resize(csize, buf, size); +} + +/** + * @internal + * + * insert string of known length at random within existing strbuf limits. + * + * @param csize the character size + * @param buf the buffer to resize, must be valid. + * @param str the string to copy, must be valid (!NULL and smaller than @a len) + * @param len the amount of bytes in @a str to copy, must be valid. + * @param pos the position inside buffer to insert, must be valid (smaller + * than eina_strbuf_common_length_get()) + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + */ +static inline Eina_Bool +_eina_strbuf_common_insert_length(size_t csize, + Eina_Strbuf *buf, + const void *str, + size_t len, + size_t pos) +{ + if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + len))) + return EINA_FALSE; + + /* move the existing text */ + memmove(((unsigned char *)(buf->buf)) + ((len + pos) * csize), + ((unsigned char *)(buf->buf)) + (pos * csize), + (buf->len - pos) * csize); + + /* and now insert the given string */ + memcpy((unsigned char *)buf->buf + (pos * csize), str, len * csize); + + buf->len += len; + memset(((unsigned char *)(buf->buf)) + (buf->len * csize), 0, csize); + return EINA_TRUE; +} + +/*============================================================================* +* API * +*============================================================================*/ + +/** + * @internal + * @brief Create a new string buffer. + * + * @param csize the character size + * @return Newly allocated string buffer instance. + * + * This function creates a new string buffer. On error, @c NULL is + * returned and Eina error is set to #EINA_ERROR_OUT_OF_MEMORY. To + * free the resources, use eina_strbuf_common_free(). + * + * @see eina_strbuf_common_free() + * @see eina_strbuf_common_append() + * @see eina_strbuf_common_string_get() + */ +Eina_Strbuf * +eina_strbuf_common_new(size_t csize) +{ + Eina_Strbuf *buf; + + eina_error_set(0); + buf = malloc(sizeof(Eina_Strbuf)); + if (EINA_UNLIKELY(!buf)) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + if (EINA_UNLIKELY(!_eina_strbuf_common_init(csize, buf))) + { + eina_strbuf_common_free(buf); + return NULL; + } + return buf; +} + +/** + * @internal + * @brief Create a new string buffer managing str. + * + * @param csize the character size + * @param str the string to manage + * @param len the length of the string to manage + * @return Newly allocated string buffer instance. + * + * This function creates a new string buffer. On error, @c NULL is + * returned and Eina error is set to #EINA_ERROR_OUT_OF_MEMORY. To + * free the resources, use eina_strbuf_common_free(). + * + * @see eina_strbuf_common_free() + * @see eina_strbuf_common_append() + * @see eina_strbuf_common_string_get() + * @since 1.1.0 + */ +Eina_Strbuf * +eina_strbuf_common_manage_new(size_t csize, + void *str, + size_t len) +{ + Eina_Strbuf *buf; + + eina_error_set(0); + buf = malloc(sizeof(Eina_Strbuf)); + if (EINA_UNLIKELY(!buf)) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + if (EINA_UNLIKELY(!_eina_strbuf_common_manage_init(csize, buf, str, len))) + { + eina_strbuf_common_free(buf); + return NULL; + } + return buf; +} + +/** + * @internal + * @brief Free a string buffer. + * + * @param buf The string buffer to free. + * + * This function frees the memory of @p buf. @p buf must have been + * created by eina_strbuf_common_new(). + */ +void +eina_strbuf_common_free(Eina_Strbuf *buf) +{ + free(buf->buf); + free(buf); +} + +/** + * @internal + * @brief Reset a string buffer. + * + * @param csize the character size + * @param buf The string buffer to reset. + * + * This function reset @p buf: the buffer len is set to 0, and the + * string is set to '\\0'. No memory is free'd. + */ +void +eina_strbuf_common_reset(size_t csize, Eina_Strbuf *buf) +{ + buf->len = 0; + buf->step = EINA_STRBUF_INIT_STEP; + memset(buf->buf, 0, csize); +} + +/** + * @internal + * @brief Append a string to a buffer, reallocating as necessary. + * + * @param csize the character size + * @param buf The string buffer to append to. + * @param str The string to append. + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function appends @p str to @p buf. It computes the length of + * @p str, so is slightly slower than eina_strbuf_common_append_length(). If + * the length is known beforehand, consider using that variant. If + * @p buf can't append it, #EINA_FALSE is returned, otherwise + * #EINA_TRUE is returned. + * + * @see eina_strbuf_common_append() + * @see eina_strbuf_common_append_length() + */ +Eina_Bool +eina_strbuf_common_append(size_t csize, + Eina_Strbuf *buf, + const void *str, + size_t len) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE); + + if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + len))) + return EINA_FALSE; + memcpy(((unsigned char *)(buf->buf)) + (buf->len * csize), str, + (len + 1) * csize); + buf->len += len; + return EINA_TRUE; +} + +/** + * @internal + * @brief Append a string to a buffer, reallocating as necessary, + * limited by the given length. + * + * @param csize the character size + * @param buf The string buffer to append to. + * @param str The string to append. + * @param maxlen The maximum number of characters to append. + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function appends at most @p maxlen characters of @p str to + * @p buf. It can't appends more than the length of @p str. It + * computes the length of @p str, so is slightly slower than + * eina_strbuf_common_append_length(). If the length is known beforehand, + * consider using that variant (@p maxlen should then be checked so + * that it is greater than the size of @p str). If @p str can not be + * appended, #EINA_FALSE is returned, otherwise, #EINA_TRUE is + * returned. + * + * @see eina_strbuf_common_append() + * @see eina_strbuf_common_append_length() + */ +Eina_Bool +eina_strbuf_common_append_n(size_t csize, + Eina_Strbuf *buf, + const void *str, + size_t len, + size_t maxlen) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE); + + if (len > maxlen) len = maxlen; + if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + len))) + return EINA_FALSE; + memcpy(((unsigned char *)(buf->buf)) + (buf->len * csize), str, + len * csize); + buf->len += len; + memset(((unsigned char *)(buf->buf)) + (buf->len * csize), 0, csize); + return EINA_TRUE; +} + +/** + * @internal + * @brief Append a string of exact length to a buffer, reallocating as necessary. + * + * @param csize the character size + * @param buf The string buffer to append to. + * @param str The string to append. + * @param length The exact length to use. + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function appends @p str to @p buf. @p str must be of size at + * most @p length. It is slightly faster than eina_strbuf_common_append() as + * it does not compute the size of @p str. It is useful when dealing + * with strings of known size, such as eina_strngshare. If @p buf + * can't append it, #EINA_FALSE is returned, otherwise #EINA_TRUE is + * returned. + * + * @see eina_stringshare_length() + * @see eina_strbuf_common_append() + * @see eina_strbuf_common_append_n() + */ +Eina_Bool +eina_strbuf_common_append_length(size_t csize, + Eina_Strbuf *buf, + const void *str, + size_t length) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE); + + if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + length))) + return EINA_FALSE; + memcpy(((unsigned char *)(buf->buf)) + (buf->len * csize), str, + length * csize); + buf->len += length; + memset(((unsigned char *)(buf->buf)) + (buf->len * csize), 0, csize); + return EINA_TRUE; +} + +/** + * @internal + * @brief Insert a string to a buffer, reallocating as necessary. + * + * @param csize the character size + * @param buf The string buffer to insert. + * @param str The string to insert. + * @param pos The position to insert the string. + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function inserts @p str to @p buf at position @p pos. It + * computes the length of @p str, so is slightly slower than + * eina_strbuf_common_insert_length(). If the length is known beforehand, + * consider using that variant. If @p buf can't insert it, #EINA_FALSE + * is returned, otherwise #EINA_TRUE is returned. + */ +Eina_Bool +eina_strbuf_common_insert(size_t csize, + Eina_Strbuf *buf, + const void *str, + size_t len, + size_t pos) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE); + + if (pos >= buf->len) return eina_strbuf_common_append(csize, buf, str, len); + return _eina_strbuf_common_insert_length(csize, buf, str, len, pos); +} + +/** + * @internal + * @brief Insert a string to a buffer, reallocating as necessary. Limited by maxlen. + * + * @param csize the character size + * @param buf The string buffer to insert to. + * @param str The string to insert. + * @param maxlen The maximum number of chars to insert. + * @param pos The position to insert the string. + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function inserts @p str ot @p buf at position @p pos, with at + * most @p maxlen bytes. The number of inserted characters can not be + * greater than the length of @p str. It computes the length of + * @p str, so is slightly slower than eina_strbuf_common_insert_length(). If the + * length is known beforehand, consider using that variant (@p maxlen + * should then be checked so that it is greater than the size of + * @p str). If @p str can not be inserted, #EINA_FALSE is returned, + * otherwise, #EINA_TRUE is returned. + */ +Eina_Bool +eina_strbuf_common_insert_n(size_t csize, + Eina_Strbuf *buf, + const void *str, + size_t len, + size_t maxlen, + size_t pos) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE); + + if (pos >= buf->len) + return eina_strbuf_common_append_n(csize, buf, str, len, maxlen); + if (len > maxlen) len = maxlen; + return _eina_strbuf_common_insert_length(csize, buf, str, len, pos); +} + +/** + * @internal + * @brief Insert a string of exact length to a buffer, reallocating as necessary. + * + * @param csize the character size + * @param buf The string buffer to insert to. + * @param str The string to insert. + * @param length The exact length to use. + * @param pos The position to insert the string. + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function inserts @p str to @p buf. @p str must be of size at + * most @p length. It is slightly faster than eina_strbuf_common_insert() as + * it does not compute the size of @p str. It is useful when dealing + * with strings of known size, such as eina_strngshare. If @p buf + * can't insert it, #EINA_FALSE is returned, otherwise #EINA_TRUE is + * returned. + * + * @see eina_stringshare_length() + * @see eina_strbuf_common_insert() + * @see eina_strbuf_common_insert_n() + */ +Eina_Bool +eina_strbuf_common_insert_length(size_t csize, + Eina_Strbuf *buf, + const void *str, + size_t length, + size_t pos) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE); + + if (pos >= buf->len) + return eina_strbuf_common_append_length(csize, buf, str, length); + return _eina_strbuf_common_insert_length(csize, buf, str, length, pos); +} + +/** + * @internal + * @brief Append a character to a string buffer, reallocating as + * necessary. + * + * @param csize the character size + * @param buf The string buffer to append to. + * @param c The char to append. + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function inserts @p c to @p buf. If it can not insert it, + * #EINA_FALSE is returned, otherwise #EINA_TRUE is returned. + */ +Eina_Bool +eina_strbuf_common_append_char(size_t csize, Eina_Strbuf *buf, const void *c) +{ + if (EINA_UNLIKELY(!_eina_strbuf_common_grow(csize, buf, buf->len + 1))) + return EINA_FALSE; + + memcpy(((unsigned char *)(buf->buf)) + ((buf->len)++ *csize), c, csize); + memset(((unsigned char *)(buf->buf)) + (buf->len * csize), 0, csize); + return EINA_TRUE; +} + +/** + * @internal + * @brief Insert a character to a string buffer, reallocating as + * necessary. + * + * @param csize the character size + * @param buf The string buffer to insert to. + * @param c The char to insert. + * @param pos The position to insert the char. + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function inserts @p c to @p buf at position @p pos. If @p buf + * can't append it, #EINA_FALSE is returned, otherwise #EINA_TRUE is + * returned. + */ +Eina_Bool +eina_strbuf_common_insert_char(size_t csize, + Eina_Strbuf *buf, + const void *c, + size_t pos) +{ + if (pos >= buf->len) + return eina_strbuf_common_append_char(csize, buf, c); + return _eina_strbuf_common_insert_length(csize, buf, c, 1, pos); +} + +/** + * @internal + * @brief Remove a slice of the given string buffer. + * + * @param csize the character size + * @param buf The string buffer to remove a slice. + * @param start The initial (inclusive) slice position to start + * removing, in bytes. + * @param end The final (non-inclusive) slice position to finish + * removing, in bytes. + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function removes a slice of @p buf, starting at @p start + * (inclusive) and ending at @p end (non-inclusive). Both values are + * in bytes. It returns #EINA_FALSE on failure, #EINA_TRUE otherwise. + */ +Eina_Bool +eina_strbuf_common_remove(size_t csize, + Eina_Strbuf *buf, + size_t start, + size_t end) +{ + size_t remove_len, tail_len; + + if (end >= buf->len) end = buf->len; + if (end <= start) return EINA_TRUE; + + remove_len = end - start; + if (remove_len == buf->len) + { + free(buf->buf); + return _eina_strbuf_common_init(csize, buf); + } + + tail_len = buf->len - end + 1; /* includes '\0' */ + memmove(((unsigned char *)(buf->buf)) + (start * csize), + ((unsigned char *)(buf->buf)) + (end * csize), + tail_len * csize); + buf->len -= remove_len; + return _eina_strbuf_common_resize(csize, buf, buf->len); +} + +/** + * @internal + * @brief Retrieve a pointer to the contents of a string buffer + * + * @param buf The string buffer. + * @return The current string in the string buffer. + * + * This function returns the string contained in @p buf. The returned + * value must not be modified and will no longer be valid if @p buf is + * modified. In other words, any eina_strbuf_common_append() or similar will + * make that pointer invalid. + * + * @see eina_strbuf_common_string_steal() + */ +const void * +eina_strbuf_common_string_get(const Eina_Strbuf *buf) +{ + return buf->buf; +} + +/** + * @internal + * @brief Steal the contents of a string buffer. + * + * @param csize the character size + * @param buf The string buffer to steal. + * @return The current string in the string buffer. + * + * This function returns the string contained in @p buf. @p buf is + * then initialized and does not own the returned string anymore. The + * caller must release the memory of the returned string by calling + * free(). + * + * @see eina_strbuf_common_string_get() + */ +void * +eina_strbuf_common_string_steal(size_t csize, Eina_Strbuf *buf) +{ + void *ret; + + ret = buf->buf; + // TODO: Check return value and do something clever + _eina_strbuf_common_init(csize, buf); + return ret; +} + +/** + * @internal + * @brief Free the contents of a string buffer but not the buffer. + * + * @param csize the character size + * @param buf The string buffer to free the string of. + * + * This function frees the string contained in @p buf without freeing + * @p buf. + */ +void +eina_strbuf_common_string_free(size_t csize, Eina_Strbuf *buf) +{ + free(buf->buf); + _eina_strbuf_common_init(csize, buf); +} + +/** + * @internal + * @brief Retrieve the length of the string buffer content. + * + * @param buf The string buffer. + * @return The current length of the string, in bytes. + * + * This function returns the length of @p buf. + */ +size_t +eina_strbuf_common_length_get(const Eina_Strbuf *buf) +{ + return buf->len; +} + +/** + * @cond LOCAL + */ + +/*FIXME: Implementing them here is a hack! */ + +#ifdef _STRBUF_CSIZE +# undef _STRBUF_CSIZE +#endif + +#ifdef _STRBUF_MAGIC +# undef _STRBUF_MAGIC +#endif + +#ifdef _STRBUF_MAGIC_STR +# undef _STRBUF_MAGIC_STR +#endif + +#define _STRBUF_CSIZE 1 +#define _STRBUF_MAGIC EINA_MAGIC_STRBUF +#define _STRBUF_MAGIC_STR __STRBUF_STR_MAGIC_STR +static const char __STRBUF_STR_MAGIC_STR[] = "Eina Strbuf"; + + +/** + * @endcond + */ + + +EAPI Eina_Bool +eina_strbuf_replace(Eina_Strbuf *buf, + const char *str, + const char *with, + unsigned int n) +{ + size_t len1, len2; + char *spos; + size_t pos; + + EINA_SAFETY_ON_NULL_RETURN_VAL( str, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(with, EINA_FALSE); + EINA_MAGIC_CHECK_STRBUF(buf, 0); + if (n == 0) return EINA_FALSE; + + spos = buf->buf; + while (n--) + { + spos = strstr(spos, str); + if (!spos || *spos == '\0') return EINA_FALSE; + if (n) spos++; + } + + pos = spos - (const char *)buf->buf; + len1 = strlen(str); + len2 = strlen(with); + if (len1 != len2) + { + /* resize the buffer if necessary */ + if (EINA_UNLIKELY(!_eina_strbuf_common_grow(_STRBUF_CSIZE, buf, + buf->len - len1 + len2))) + return EINA_FALSE; /* move the existing text */ + memmove(((unsigned char *)(buf->buf)) + pos + len2, + ((unsigned char *)(buf->buf)) + pos + len1, + buf->len - pos - len1); + } + /* and now insert the given string */ + memcpy(((unsigned char *)(buf->buf)) + pos, with, len2); + buf->len += len2 - len1; + memset(((unsigned char *)(buf->buf)) + buf->len, 0, 1); + return EINA_TRUE; +} + +EAPI int +eina_strbuf_replace_all(Eina_Strbuf *buf, const char *str, const char *with) +{ + size_t len1, len2, len; + char *tmp_buf = NULL; + char *spos; + size_t pos, start; + size_t pos_tmp, start_tmp; + int n = 0; + + EINA_SAFETY_ON_NULL_RETURN_VAL( str, 0); + EINA_SAFETY_ON_NULL_RETURN_VAL(with, 0); + EINA_MAGIC_CHECK_STRBUF(buf, 0); + + spos = strstr(buf->buf, str); + if (!spos || *spos == '\0') return 0; + len1 = strlen(str); + len2 = strlen(with); + /* if the size of the two string is equal, it is fairly easy to replace them + * we don't need to resize the buffer or doing other calculations */ + if (len1 == len2) + { + while (spos) + { + memcpy(spos, with, len2); + spos = strstr(spos + len2, str); + n++; + } + return n; + } + pos = pos_tmp = spos - (const char *)buf->buf; + tmp_buf = buf->buf; + buf->buf = malloc(buf->size); + if (EINA_UNLIKELY(!buf->buf)) + { + buf->buf = tmp_buf; + return 0; + } + start = start_tmp = 0; + len = buf->len; + while (spos) + { + n++; + len = (len + len2) - len1; + /* resize the buffer if necessary */ + if (EINA_UNLIKELY(!_eina_strbuf_common_grow(_STRBUF_CSIZE, buf, len))) + { + /* we have to stop replacing here, because we haven't enough + * memory to go on */ + len = (len + len1) - len2; + break; + } + /* copy the untouched text */ + memcpy(((unsigned char *)(buf->buf)) + start, tmp_buf + start_tmp, + pos - start); + /* copy the new string */ + memcpy(((unsigned char *)(buf->buf)) + pos, with, len2); + /* calculate the next positions */ + start_tmp = pos_tmp + len1; + start = pos + len2; + spos = strstr(tmp_buf + start_tmp, str); + /* this calculations don't make sense if spos == NULL, but the + * calculated values won't be used, because the loop will stop + * then */ + pos_tmp = spos - tmp_buf; + pos = start + pos_tmp - start_tmp; + } + /* and now copy the rest of the text */ + memcpy(((unsigned char *)(buf->buf)) + start, tmp_buf + start_tmp, + len - start); + buf->len = len; + memset(((unsigned char *)(buf->buf)) + buf->len, 0, 1); + free(tmp_buf); + return n; +} diff --git a/libraries/eina/src/lib/eina_strbuf_common.h b/libraries/eina/src/lib/eina_strbuf_common.h new file mode 100644 index 0000000..06a1353 --- /dev/null +++ b/libraries/eina/src/lib/eina_strbuf_common.h @@ -0,0 +1,120 @@ +#ifndef EINA_STRBUF_COMMON_H +#define EINA_STRBUF_COMMON_H + +#include + +#include "eina_private.h" +#include "eina_magic.h" +#include "eina_strbuf.h" + +/** + * @struct _Eina_Strbuf + * String buffer to facilitate string operations. + */ +struct _Eina_Strbuf +{ + void *buf; + size_t len; + size_t size; + size_t step; + + EINA_MAGIC +}; + +#define EINA_MAGIC_CHECK_STRBUF(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK((d), _STRBUF_MAGIC)) \ + { \ + EINA_MAGIC_FAIL((d), _STRBUF_MAGIC); \ + return __VA_ARGS__; \ + } \ + } while (0) + +Eina_Bool +eina_strbuf_common_init(void); + +Eina_Bool +eina_strbuf_common_shutdown(void); +Eina_Strbuf * +eina_strbuf_common_new(size_t csize); +Eina_Strbuf * +eina_strbuf_common_manage_new(size_t csize, + void *str, + size_t len); +void +eina_strbuf_common_free(Eina_Strbuf *buf); +void +eina_strbuf_common_reset(size_t csize, Eina_Strbuf *buf); +Eina_Bool +eina_strbuf_common_append(size_t csize, + Eina_Strbuf *buf, + const void *str, + size_t len); +Eina_Bool +eina_strbuf_common_append_escaped(size_t csize, + Eina_Strbuf *buf, + const void *str); +Eina_Bool +eina_strbuf_common_append_n(size_t csize, + Eina_Strbuf *buf, + const void *str, + size_t len, + size_t maxlen); +Eina_Bool +eina_strbuf_common_append_length(size_t csize, + Eina_Strbuf *buf, + const void *str, + size_t length); +Eina_Bool +eina_strbuf_common_insert(size_t csize, + Eina_Strbuf *buf, + const void *str, + size_t len, + size_t pos); +Eina_Bool +eina_strbuf_common_insert_escaped(size_t csize, + Eina_Strbuf *buf, + const void *str, + size_t len, + size_t pos); +Eina_Bool +eina_strbuf_common_insert_n(size_t csize, + Eina_Strbuf *buf, + const void *str, + size_t len, + size_t maxlen, + size_t pos); +Eina_Bool +eina_strbuf_common_insert_length(size_t csize, + Eina_Strbuf *buf, + const void *str, + size_t length, + size_t pos); +Eina_Bool +eina_strbuf_common_append_char(size_t csize, Eina_Strbuf *buf, const void *c); +Eina_Bool +eina_strbuf_common_insert_char(size_t csize, + Eina_Strbuf *buf, + const void *c, + size_t pos); +Eina_Bool +eina_strbuf_common_remove(size_t csize, + Eina_Strbuf *buf, + size_t start, + size_t end); +const void * +eina_strbuf_common_string_get(const Eina_Strbuf *buf); +void * +eina_strbuf_common_string_steal(size_t csize, Eina_Strbuf *buf); +void +eina_strbuf_common_string_free(size_t csize, Eina_Strbuf *buf); +size_t +eina_strbuf_common_length_get(const Eina_Strbuf *buf); + +Eina_Bool +_eina_strbuf_common_grow(size_t csize, Eina_Strbuf *buf, size_t size); +/** + * @} + */ + +#endif diff --git a/libraries/eina/src/lib/eina_strbuf_template_c.x b/libraries/eina/src/lib/eina_strbuf_template_c.x new file mode 100644 index 0000000..e8c3b61 --- /dev/null +++ b/libraries/eina/src/lib/eina_strbuf_template_c.x @@ -0,0 +1,97 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +/* This file should be included from files implementing strbuf. + The including file should define the following macros: + * _STRBUF_DATA_TYPE + * _STRBUF_CSIZE + * _STRBUF_STRUCT_NAME + * _STRBUF_STRLEN_FUNC(x) + * _STRBUF_STRESCAPE_FUNC(x) + * _STRBUF_STRSTR_FUNC(x, y) + * _STRBUF_MAGIC + * _STRBUF_MAGIC_STR + * See how it's done in eina_ustrbuf.c and eina_strbuf.c. This just makes things + * a lot easier since those are essentially the same just with different sizes. + */ + +#include "eina_binbuf_template_c.x" + +/*============================================================================* + * API * + *============================================================================*/ + +EAPI _STRBUF_STRUCT_NAME * +_FUNC_EXPAND(manage_new)(_STRBUF_DATA_TYPE *str) +{ + _STRBUF_STRUCT_NAME *buf = eina_strbuf_common_manage_new(_STRBUF_CSIZE, + (void *) str, _STRBUF_STRLEN_FUNC(str)); + EINA_MAGIC_SET(buf, _STRBUF_MAGIC); + return buf; +} + +EAPI Eina_Bool +_FUNC_EXPAND(append)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str) +{ + EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE); + return eina_strbuf_common_append(_STRBUF_CSIZE, buf, (const void *) str, _STRBUF_STRLEN_FUNC(str)); +} + +EAPI Eina_Bool +_FUNC_EXPAND(append_escaped)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str) +{ + _STRBUF_DATA_TYPE *esc; + Eina_Bool ret; + + EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE); + esc = _STRBUF_STRESCAPE_FUNC(str); + if (!esc) { + return _FUNC_EXPAND(append)(buf, str); + } + ret = _FUNC_EXPAND(append)(buf, esc); + if (esc) + free(esc); + + return ret; +} + +EAPI Eina_Bool +_FUNC_EXPAND(append_n)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t maxlen) +{ + EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE); + return eina_strbuf_common_append_n(_STRBUF_CSIZE, buf, (const void *) str, _STRBUF_STRLEN_FUNC(str), maxlen); +} + +EAPI Eina_Bool +_FUNC_EXPAND(insert)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t pos) +{ + EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE); + return eina_strbuf_common_insert(_STRBUF_CSIZE, buf, (const void *) str, _STRBUF_STRLEN_FUNC(str), pos); +} + +EAPI Eina_Bool +_FUNC_EXPAND(insert_escaped)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t pos) +{ + _STRBUF_DATA_TYPE *esc; + Eina_Bool ret; + EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE); + + esc = _STRBUF_STRESCAPE_FUNC(str); + if (!esc) { + return _FUNC_EXPAND(insert)(buf, str, pos); + } + ret = _FUNC_EXPAND(insert)(buf, esc, pos); + if (esc) + free(esc); + + return ret; +} + +EAPI Eina_Bool +_FUNC_EXPAND(insert_n)(_STRBUF_STRUCT_NAME *buf, const _STRBUF_DATA_TYPE *str, size_t maxlen, size_t pos) +{ + EINA_MAGIC_CHECK_STRBUF(buf, EINA_FALSE); + return eina_strbuf_common_insert_n(_STRBUF_CSIZE, buf, (const void *) str, _STRBUF_STRLEN_FUNC(str), maxlen, pos); +} + diff --git a/libraries/eina/src/lib/eina_stringshare.c b/libraries/eina/src/lib/eina_stringshare.c new file mode 100644 index 0000000..478b300 --- /dev/null +++ b/libraries/eina/src/lib/eina_stringshare.c @@ -0,0 +1,751 @@ +/* EINA - EFL data type library + * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2010 + * Carsten Haitzler, + * Jorge Luis Zapata Muga, + * Cedric Bail, + * Gustavo Sverzut Barbieri + * Tom Hacohen + * Brett Nash + * + * 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 +#include + +#ifdef HAVE_EVIL +# include +#endif + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_error.h" +#include "eina_log.h" +#include "eina_stringshare.h" +#include "eina_lock.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_share_common.h" + +/* The actual share */ +static Eina_Share *stringshare_share; +static const char EINA_MAGIC_STRINGSHARE_NODE_STR[] = "Eina Stringshare Node"; + +extern Eina_Bool _share_common_threads_activated; +static Eina_Lock _mutex_small; + +/* Stringshare optimizations */ +static const unsigned char _eina_stringshare_single[512] = { + 0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,10,0,11,0,12,0,13,0,14,0,15,0, + 16,0,17,0,18,0,19,0,20,0,21,0,22,0,23,0,24,0,25,0,26,0,27,0,28,0,29,0,30,0, + 31,0,32,0,33,0,34,0,35,0,36,0,37,0,38,0,39,0,40,0,41,0,42,0,43,0,44,0,45,0, + 46,0,47,0,48,0,49,0,50,0,51,0,52,0,53,0,54,0,55,0,56,0,57,0,58,0,59,0,60,0, + 61,0,62,0,63,0,64,0,65,0,66,0,67,0,68,0,69,0,70,0,71,0,72,0,73,0,74,0,75,0, + 76,0,77,0,78,0,79,0,80,0,81,0,82,0,83,0,84,0,85,0,86,0,87,0,88,0,89,0,90,0, + 91,0,92,0,93,0,94,0,95,0,96,0,97,0,98,0,99,0,100,0,101,0,102,0,103,0,104,0, + 105,0, + 106,0,107,0,108,0,109,0,110,0,111,0,112,0,113,0,114,0,115,0,116,0,117,0,118, + 0,119,0,120,0, + 121,0,122,0,123,0,124,0,125,0,126,0,127,0,128,0,129,0,130,0,131,0,132,0,133, + 0,134,0,135,0, + 136,0,137,0,138,0,139,0,140,0,141,0,142,0,143,0,144,0,145,0,146,0,147,0,148, + 0,149,0,150,0, + 151,0,152,0,153,0,154,0,155,0,156,0,157,0,158,0,159,0,160,0,161,0,162,0,163, + 0,164,0,165,0, + 166,0,167,0,168,0,169,0,170,0,171,0,172,0,173,0,174,0,175,0,176,0,177,0,178, + 0,179,0,180,0, + 181,0,182,0,183,0,184,0,185,0,186,0,187,0,188,0,189,0,190,0,191,0,192,0,193, + 0,194,0,195,0, + 196,0,197,0,198,0,199,0,200,0,201,0,202,0,203,0,204,0,205,0,206,0,207,0,208, + 0,209,0,210,0, + 211,0,212,0,213,0,214,0,215,0,216,0,217,0,218,0,219,0,220,0,221,0,222,0,223, + 0,224,0,225,0, + 226,0,227,0,228,0,229,0,230,0,231,0,232,0,233,0,234,0,235,0,236,0,237,0,238, + 0,239,0,240,0, + 241,0,242,0,243,0,244,0,245,0,246,0,247,0,248,0,249,0,250,0,251,0,252,0,253, + 0,254,0,255,0 +}; + +typedef struct _Eina_Stringshare_Small Eina_Stringshare_Small; +typedef struct _Eina_Stringshare_Small_Bucket Eina_Stringshare_Small_Bucket; + +struct _Eina_Stringshare_Small_Bucket +{ + /* separate arrays for faster lookups */ + const char **strings; + unsigned char *lengths; + unsigned short *references; + int count; + int size; +}; + +struct _Eina_Stringshare_Small +{ + Eina_Stringshare_Small_Bucket *buckets[256]; +}; + +#define EINA_STRINGSHARE_SMALL_BUCKET_STEP 8 +static Eina_Stringshare_Small _eina_small_share; + +static inline int +_eina_stringshare_small_cmp(const Eina_Stringshare_Small_Bucket *bucket, + int i, + const char *pstr, + unsigned char plength) +{ + /* pstr and plength are from second char and on, since the first is + * always the same. + * + * First string being always the same, size being between 2 and 3 + * characters (there is a check for special case length==1 and then + * small stringshare is applied to strings < 4), we just need to + * compare 2 characters of both strings. + */ + const unsigned char cur_plength = bucket->lengths[i] - 1; + const char *cur_pstr; + + if (cur_plength > plength) + return 1; + else if (cur_plength < plength) + return -1; + + cur_pstr = bucket->strings[i] + 1; + + if (cur_pstr[0] > pstr[0]) + return 1; + else if (cur_pstr[0] < pstr[0]) + return -1; + + if (plength == 1) + return 0; + + if (cur_pstr[1] > pstr[1]) + return 1; + else if (cur_pstr[1] < pstr[1]) + return -1; + + return 0; +} + +static const char * +_eina_stringshare_small_bucket_find(const Eina_Stringshare_Small_Bucket *bucket, + const char *str, + unsigned char length, + int *idx) +{ + const char *pstr = str + 1; /* skip first letter, it's always the same */ + unsigned char plength = length - 1; + int i, low, high; + + if (bucket->count == 0) + { + *idx = 0; + return NULL; + } + + low = 0; + high = bucket->count; + + while (low < high) + { + int r; + + i = (low + high - 1) / 2; + + r = _eina_stringshare_small_cmp(bucket, i, pstr, plength); + if (r > 0) + high = i; + else if (r < 0) + low = i + 1; + else + { + *idx = i; + return bucket->strings[i]; + } + } + + *idx = low; + return NULL; +} + +static Eina_Bool +_eina_stringshare_small_bucket_resize(Eina_Stringshare_Small_Bucket *bucket, + int size) +{ + void *tmp; + + tmp = realloc((void *)bucket->strings, size * sizeof(bucket->strings[0])); + if (!tmp) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return 0; + } + + bucket->strings = tmp; + + tmp = realloc(bucket->lengths, size * sizeof(bucket->lengths[0])); + if (!tmp) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return 0; + } + + bucket->lengths = tmp; + + tmp = realloc(bucket->references, size * sizeof(bucket->references[0])); + if (!tmp) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return 0; + } + + bucket->references = tmp; + + bucket->size = size; + return 1; +} + +static const char * +_eina_stringshare_small_bucket_insert_at( + Eina_Stringshare_Small_Bucket **p_bucket, + const char *str, + unsigned char length, + int idx) +{ + Eina_Stringshare_Small_Bucket *bucket = *p_bucket; + int todo, off; + char *snew; + + if (!bucket) + { + *p_bucket = bucket = calloc(1, sizeof(*bucket)); + if (!bucket) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + } + + if (bucket->count + 1 >= bucket->size) + { + int size = bucket->size + EINA_STRINGSHARE_SMALL_BUCKET_STEP; + if (!_eina_stringshare_small_bucket_resize(bucket, size)) + return NULL; + } + + snew = malloc(length + 1); + if (!snew) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + memcpy(snew, str, length); + snew[length] = '\0'; + + off = idx + 1; + todo = bucket->count - idx; + if (todo > 0) + { + memmove((void *)(bucket->strings + off), bucket->strings + idx, + todo * sizeof(bucket->strings[0])); + memmove(bucket->lengths + off, bucket->lengths + idx, + todo * sizeof(bucket->lengths[0])); + memmove(bucket->references + off, bucket->references + idx, + todo * sizeof(bucket->references[0])); + } + + bucket->strings[idx] = snew; + bucket->lengths[idx] = length; + bucket->references[idx] = 1; + bucket->count++; + + return snew; +} + +static void +_eina_stringshare_small_bucket_remove_at( + Eina_Stringshare_Small_Bucket **p_bucket, + int idx) +{ + Eina_Stringshare_Small_Bucket *bucket = *p_bucket; + int todo, off; + + if (bucket->references[idx] > 1) + { + bucket->references[idx]--; + return; + } + + free((char *)bucket->strings[idx]); + + if (bucket->count == 1) + { + free((void *)bucket->strings); + free(bucket->lengths); + free(bucket->references); + free(bucket); + *p_bucket = NULL; + return; + } + + bucket->count--; + if (idx == bucket->count) + goto end; + + off = idx + 1; + todo = bucket->count - idx; + + memmove((void *)(bucket->strings + idx), bucket->strings + off, + todo * sizeof(bucket->strings[0])); + memmove(bucket->lengths + idx, bucket->lengths + off, + todo * sizeof(bucket->lengths[0])); + memmove(bucket->references + idx, bucket->references + off, + todo * sizeof(bucket->references[0])); + +end: + if (bucket->count + EINA_STRINGSHARE_SMALL_BUCKET_STEP < bucket->size) + { + int size = bucket->size - EINA_STRINGSHARE_SMALL_BUCKET_STEP; + _eina_stringshare_small_bucket_resize(bucket, size); + } +} + +static const char * +_eina_stringshare_small_add(const char *str, unsigned char length) +{ + Eina_Stringshare_Small_Bucket **bucket; + int i; + + bucket = _eina_small_share.buckets + (unsigned char)str[0]; + if (!*bucket) + i = 0; + else + { + const char *ret; + ret = _eina_stringshare_small_bucket_find(*bucket, str, length, &i); + if (ret) + { + (*bucket)->references[i]++; + return ret; + } + } + + return _eina_stringshare_small_bucket_insert_at(bucket, str, length, i); +} + +static void +_eina_stringshare_small_del(const char *str, unsigned char length) +{ + Eina_Stringshare_Small_Bucket **bucket; + const char *ret; + int i; + + bucket = _eina_small_share.buckets + (unsigned char)str[0]; + if (!*bucket) + goto error; + + ret = _eina_stringshare_small_bucket_find(*bucket, str, length, &i); + if (!ret) + goto error; + + _eina_stringshare_small_bucket_remove_at(bucket, i); + return; + +error: + CRITICAL("EEEK trying to del non-shared stringshare \"%s\"", str); +} + +static void +_eina_stringshare_small_init(void) +{ + eina_lock_new(&_mutex_small); + memset(&_eina_small_share, 0, sizeof(_eina_small_share)); +} + +static void +_eina_stringshare_small_shutdown(void) +{ + Eina_Stringshare_Small_Bucket **p_bucket, **p_bucket_end; + + p_bucket = _eina_small_share.buckets; + p_bucket_end = p_bucket + 256; + + for (; p_bucket < p_bucket_end; p_bucket++) + { + Eina_Stringshare_Small_Bucket *bucket = *p_bucket; + char **s, **s_end; + + if (!bucket) + continue; + + s = (char **)bucket->strings; + s_end = s + bucket->count; + for (; s < s_end; s++) + free(*s); + + free((void *)bucket->strings); + free(bucket->lengths); + free(bucket->references); + free(bucket); + *p_bucket = NULL; + } + + eina_lock_free(&_mutex_small); +} + +static void +_eina_stringshare_small_bucket_dump(Eina_Stringshare_Small_Bucket *bucket, + struct dumpinfo *di) +{ + const char **s = bucket->strings; + unsigned char *l = bucket->lengths; + unsigned short *r = bucket->references; + int i; + + di->used += sizeof(*bucket); + di->used += bucket->count * sizeof(*s); + di->used += bucket->count * sizeof(*l); + di->used += bucket->count * sizeof(*r); + di->unique += bucket->count; + + 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); + + di->used += *l; + di->saved += *l * dups; + di->dups += dups; + } +} + +static void +_eina_stringshare_small_dump(struct dumpinfo *di) +{ + Eina_Stringshare_Small_Bucket **p_bucket, **p_bucket_end; + + p_bucket = _eina_small_share.buckets; + p_bucket_end = p_bucket + 256; + + for (; p_bucket < p_bucket_end; p_bucket++) + { + Eina_Stringshare_Small_Bucket *bucket = *p_bucket; + + if (!bucket) + continue; + + _eina_stringshare_small_bucket_dump(bucket, di); + } +} + + +/*============================================================================* +* Global * +*============================================================================*/ + +/** + * @internal + * @brief Initialize the share_common module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the share_common module of Eina. It is called by + * eina_init(). + * + * @see eina_init() + */ +Eina_Bool +eina_stringshare_init(void) +{ + Eina_Bool ret; + ret = eina_share_common_init(&stringshare_share, + EINA_MAGIC_STRINGSHARE_NODE, + EINA_MAGIC_STRINGSHARE_NODE_STR); + if (ret) + _eina_stringshare_small_init(); + + return ret; +} + +/** + * @internal + * @brief Shut down the share_common module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the share_common module set up by + * eina_share_common_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_stringshare_shutdown(void) +{ + Eina_Bool ret; + _eina_stringshare_small_shutdown(); + ret = eina_share_common_shutdown(&stringshare_share); + return ret; +} + +/*============================================================================* +* API * +*============================================================================*/ + +EAPI void +eina_stringshare_del(const char *str) +{ + int slen; + + if (!str) + return; + + /* special cases */ + if (str[0] == '\0') + slen = 0; + else if (str[1] == '\0') + slen = 1; + else if (str[2] == '\0') + slen = 2; + else if (str[3] == '\0') + slen = 3; + else + slen = 4; /* handled later */ + + if (slen < 2) + return; + else if (slen < 4) + { + eina_share_common_population_del(stringshare_share, slen); + eina_lock_take(&_mutex_small); + _eina_stringshare_small_del(str, slen); + eina_lock_release(&_mutex_small); + return; + } + + eina_share_common_del(stringshare_share, str); +} + +EAPI const char * +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); + else if (slen < 4) + { + const char *s; + + eina_lock_take(&_mutex_small); + s = _eina_stringshare_small_add(str, slen); + eina_lock_release(&_mutex_small); + return s; + } + + return eina_share_common_add_length(stringshare_share, str, slen * + sizeof(char), sizeof(char)); +} + +EAPI const char * +eina_stringshare_add(const char *str) +{ + int slen; + if (!str) + return NULL; + + if (str[0] == '\0') + slen = 0; + else if (str[1] == '\0') + slen = 1; + else if (str[2] == '\0') + slen = 2; + else if (str[3] == '\0') + slen = 3; + else + slen = 3 + (int)strlen(str + 3); + + return eina_stringshare_add_length(str, slen); +} + +EAPI const char * +eina_stringshare_printf(const char *fmt, ...) +{ + va_list args; + char *tmp; + const char *ret; + int len; + + if (!fmt) + return NULL; + + va_start(args, fmt); + len = vasprintf(&tmp, fmt, args); + va_end(args); + + if (len < 1) + return NULL; + + ret = eina_stringshare_add_length(tmp, len); + free(tmp); + + return ret; +} + +EAPI const char * +eina_stringshare_vprintf(const char *fmt, va_list args) +{ + char *tmp; + const char *ret; + int len; + + if (!fmt) + return NULL; + + len = vasprintf(&tmp, fmt, args); + + if (len < 1) + return NULL; + + ret = eina_stringshare_add_length(tmp, len); + free(tmp); + + return ret; +} + +EAPI const char * +eina_stringshare_nprintf(unsigned int len, const char *fmt, ...) +{ + va_list args; + char *tmp; + int size; + + if (!fmt) + return NULL; + + if (len < 1) + return NULL; + + tmp = alloca(sizeof(char) * len + 1); + + va_start(args, fmt); + size = vsnprintf(tmp, len, fmt, args); + va_end(args); + + if (size < 1) + return NULL; + + return eina_stringshare_add_length(tmp, len); +} + +EAPI const char * +eina_stringshare_ref(const char *str) +{ + int slen; + + if (!str) + return eina_share_common_ref(stringshare_share, str); + + /* special cases */ + if (str[0] == '\0') + slen = 0; + else if (str[1] == '\0') + slen = 1; + else if (str[2] == '\0') + slen = 2; + else if (str[3] == '\0') + slen = 3; + else + slen = 3 + (int)strlen(str + 3); + + if (slen < 2) + { + eina_share_common_population_add(stringshare_share, slen); + + return str; + } + else if (slen < 4) + { + const char *s; + eina_share_common_population_add(stringshare_share, slen); + + eina_lock_take(&_mutex_small); + s = _eina_stringshare_small_add(str, slen); + eina_lock_release(&_mutex_small); + + return s; + } + + return eina_share_common_ref(stringshare_share, str); +} + +EAPI int +eina_stringshare_strlen(const char *str) +{ + int len; + /* special cases */ + if (str[0] == '\0') + return 0; + + if (str[1] == '\0') + return 1; + + if (str[2] == '\0') + return 2; + + if (str[3] == '\0') + return 3; + + len = eina_share_common_length(stringshare_share, (const char *)str); + len = (len > 0) ? len / (int)sizeof(char) : -1; + return len; +} + +EAPI void +eina_stringshare_dump(void) +{ + eina_share_common_dump(stringshare_share, + _eina_stringshare_small_dump, + sizeof(_eina_stringshare_single)); +} diff --git a/libraries/eina/src/lib/eina_tiler.c b/libraries/eina/src/lib/eina_tiler.c new file mode 100644 index 0000000..69b944e --- /dev/null +++ b/libraries/eina/src/lib/eina_tiler.c @@ -0,0 +1,1276 @@ +/* EINA - EFL data type library + * Copyright (C) 2007-2008 Gustavo Sverzut Barbieri, Jorge Luis Zapata Muga + * + * 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 . + */ + +/* TODO + * it is possible to have more than one tiler algorithm, but for now the + * version Gustavo did is hardcoded here + * http://blog.gustavobarbieri.com.br/2007/06/03/evas-now-using-rectangle-split-and-merge/ + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_tiler.h" +#include "eina_error.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/* The splitter data types */ +typedef struct list_node list_node_t; +typedef struct list list_t; +typedef struct rect rect_t; +typedef struct rect_node rect_node_t; + +struct list_node +{ + struct list_node *next; +}; + +struct list +{ + struct list_node *head; + struct list_node *tail; +}; + +struct rect +{ + short right; + short bottom; + short left; + short top; + short width; + short height; + int area; +}; + +struct rect_node +{ + struct list_node _lst; + struct rect rect; +}; + +typedef struct splitter +{ + Eina_Bool need_merge; + list_t rects; +} splitter_t; + +typedef struct list_node_pool +{ + list_node_t *node; + int len; + int max; +} list_node_pool_t; + + +static const list_node_t list_node_zeroed = { NULL }; +static const list_t list_zeroed = { NULL, NULL }; +static list_node_pool_t list_node_pool = { NULL, 0, 1024 }; + + +typedef struct _Eina_Iterator_Tiler +{ + Eina_Iterator iterator; + const Eina_Tiler *tiler; + list_node_t *curr; + Eina_Rectangle r; + EINA_MAGIC +} Eina_Iterator_Tiler; + +struct _Eina_Tiler +{ + struct + { + int w, h; + } tile; + Eina_Rectangle area; + EINA_MAGIC + splitter_t splitter; +}; + +#define EINA_MAGIC_CHECK_TILER(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_TILER)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_TILER); \ + return __VA_ARGS__; \ + } \ + } while(0) + + +#define EINA_MAGIC_CHECK_TILER_ITERATOR(d, ...) \ + do { \ + if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_TILER_ITERATOR)) \ + { \ + EINA_MAGIC_FAIL(d, EINA_MAGIC_TILER_ITERATOR); \ + return __VA_ARGS__; \ + } \ + } while(0) + +/* The Splitter algorithm */ +static inline void rect_init(rect_t *r, int x, int y, int w, int h) +{ + r->area = w * h; + + r->left = x; + r->top = y; + + r->right = x + w; + r->bottom = y + h; + + r->width = w; + r->height = h; +} + +static inline list_node_t * +rect_list_node_pool_get(void) +{ + if (list_node_pool.node) + { + list_node_t *node; + + node = list_node_pool.node; + list_node_pool.node = node->next; + list_node_pool.len--; + + return node; + } + else + return malloc(sizeof(rect_node_t)); +} + + +static inline void rect_list_concat(list_t *rects, list_t *other) +{ + if (!other->head) + return; + + if (rects->tail) + { + rects->tail->next = other->head; + rects->tail = other->tail; + } + else + { + rects->head = other->head; + rects->tail = other->tail; + } + + *other = list_zeroed; +} + +static inline void rect_list_append_node(list_t *rects, list_node_t *node) +{ + if (rects->tail) + { + rects->tail->next = node; + rects->tail = node; + } + else + { + rects->head = node; + rects->tail = node; + } +} + +static inline void rect_list_append(list_t *rects, const rect_t r) +{ + rect_node_t *rect_node; + + rect_node = (rect_node_t *)rect_list_node_pool_get(); + rect_node->rect = r; + rect_node->_lst = list_node_zeroed; + + rect_list_append_node(rects, (list_node_t *)rect_node); +} + +static inline void rect_list_append_xywh(list_t *rects, + int x, + int y, + int w, + int h) +{ + rect_t r; + + rect_init(&r, x, y, w, h); + rect_list_append(rects, r); +} + +static inline void _calc_intra_rect_area(const rect_t a, const rect_t b, + int *width, int *height) +{ + int max_left, min_right, max_top, min_bottom; + + if (a.left < b.left) + max_left = b.left; + else + max_left = a.left; + + if (a.right < b.right) + min_right = a.right; + else + min_right = b.right; + + *width = min_right - max_left; + + if (a.top < b.top) + max_top = b.top; + else + max_top = a.top; + + if (a.bottom < b.bottom) + min_bottom = a.bottom; + else + min_bottom = b.bottom; + + *height = min_bottom - max_top; +} + +static inline void _split_strict(list_t *dirty, const rect_t current, rect_t r) +{ + int h_1, h_2, w_1, w_2; + + h_1 = current.top - r.top; + h_2 = r.bottom - current.bottom; + w_1 = current.left - r.left; + w_2 = r.right - current.right; + + if (h_1 > 0) + { + /* .--.r (b) .---.r2 + * | | | | + * .-------.cur (a) .---.r '---' + * | | | | -> | | + + * | `--' | `---' + * `-------' + */ + rect_list_append_xywh(dirty, r.left, r.top, r.width, h_1); + r.height -= h_1; + r.top = current.top; + } + + if (h_2 > 0) + { + /* .-------.cur (a) + * | .---. | .---.r + * | | | | -> | | + * `-------' `---' + .---.r2 + * | | | | + * `---'r (b) `---' + */ + rect_list_append_xywh(dirty, r.left, current.bottom, r.width, + h_2); + r.height -= h_2; + } + + if (w_1 > 0) + /* (b) r .----.cur (a) + * .--|-. | .--.r2 .-.r + * | | | | -> | | + | | + * `--|-' | `--' `-' + * `----' + */ + rect_list_append_xywh(dirty, r.left, r.top, w_1, r.height); /* not necessary to keep these, r (b) will be destroyed */ + + /* r.width -= w_1; */ + /* r.left = current.left; */ + + if (w_2 > 0) + /* .----.cur (a) + * | | + * | .-|--.r (b) .-.r .--.r2 + * | | | | -> | | + | | + * | `-|--' `-' `--' + * `----' + */ + rect_list_append_xywh(dirty, current.right, r.top, w_2, + r.height); /* not necessary to keep this, r (b) will be destroyed */ + + /* r.width -= w_2; */ +} + +static inline void _calc_intra_outer_rect_area(const rect_t a, const rect_t b, + rect_t *intra, rect_t *outer) +{ + int min_left, max_left, min_right, max_right; + int min_top, max_top, min_bottom, max_bottom; + + if (a.left < b.left) + { + max_left = b.left; + min_left = a.left; + } + else + { + max_left = a.left; + min_left = b.left; + } + + if (a.right < b.right) + { + min_right = a.right; + max_right = b.right; + } + else + { + min_right = b.right; + max_right = a.right; + } + + intra->left = max_left; + intra->right = min_right; + intra->width = min_right - max_left; + + outer->left = min_left; + outer->right = max_right; + outer->width = max_right - min_left; + + if (a.top < b.top) + { + max_top = b.top; + min_top = a.top; + } + else + { + max_top = a.top; + min_top = b.top; + } + + if (a.bottom < b.bottom) + { + min_bottom = a.bottom; + max_bottom = b.bottom; + } + else + { + min_bottom = b.bottom; + max_bottom = a.bottom; + } + + intra->top = max_top; + intra->bottom = min_bottom; + intra->height = min_bottom - max_top; + if ((intra->width > 0) && (intra->height > 0)) + intra->area = intra->width * intra->height; + else + intra->area = 0; + + outer->top = min_top; + outer->bottom = max_bottom; + outer->height = max_bottom - min_top; + outer->area = outer->width * outer->height; +} + +enum +{ + SPLIT_FUZZY_ACTION_NONE, + SPLIT_FUZZY_ACTION_SPLIT, + SPLIT_FUZZY_ACTION_MERGE +}; + +static inline int _split_fuzzy(list_t *dirty, const rect_t a, rect_t *b) +{ + int h_1, h_2, w_1, w_2, action; + + h_1 = a.top - b->top; + h_2 = b->bottom - a.bottom; + w_1 = a.left - b->left; + w_2 = b->right - a.right; + + action = SPLIT_FUZZY_ACTION_NONE; + + if (h_1 > 0) + { + /* .--.r (b) .---.r2 + * | | | | + * .-------.cur (a) .---.r '---' + * | | | | -> | | + + * | `--' | `---' + * `-------' + */ + rect_list_append_xywh(dirty, b->left, b->top, b->width, h_1); + b->height -= h_1; + b->top = a.top; + action = SPLIT_FUZZY_ACTION_SPLIT; + } + + if (h_2 > 0) + { + /* .-------.cur (a) + * | .---. | .---.r + * | | | | -> | | + * `-------' `---' + .---.r2 + * | | | | + * `---'r (b) `---' + */ + rect_list_append_xywh(dirty, b->left, a.bottom, b->width, h_2); + b->height -= h_2; + action = SPLIT_FUZZY_ACTION_SPLIT; + } + + if (((w_1 > 0) || (w_2 > 0)) && (a.height == b->height)) + return SPLIT_FUZZY_ACTION_MERGE; + + if (w_1 > 0) + { + /* (b) r .----.cur (a) + * .--|-. | .--.r2 .-.r + * | | | | -> | | + | | + * `--|-' | `--' `-' + * `----' + */ + rect_list_append_xywh(dirty, b->left, b->top, w_1, b->height); + /* not necessary to keep these, r (b) will be destroyed */ + /* b->width -= w_1; */ + /* b->left = a.left; */ + action = SPLIT_FUZZY_ACTION_SPLIT; + } + + if (w_2 > 0) + { + /* .----.cur (a) + * | | + * | .-|--.r (b) .-.r .--.r2 + * | | | | -> | | + | | + * | `-|--' `-' `--' + * `----' + */ + rect_list_append_xywh(dirty, a.right, b->top, w_2, b->height); + /* not necessary to keep these, r (b) will be destroyed */ + /* b->width -= w_2; */ + action = SPLIT_FUZZY_ACTION_SPLIT; + } + + return action; +} + +#if 0 +static void rect_list_node_pool_set_max(int max) +{ + int diff; + + diff = list_node_pool.len - max; + for (; diff > 0 && list_node_pool.node != NULL; diff--) + { + list_node_t *node; + + node = list_node_pool.node; + list_node_pool.node = node->next; + list_node_pool.len--; + + free(node); + } + + list_node_pool.max = max; +} +#endif + +static void rect_list_node_pool_flush(void) +{ + while (list_node_pool.node) + { + list_node_t *node; + + node = list_node_pool.node; + list_node_pool.node = node->next; + list_node_pool.len--; + + free(node); + } +} + + + +static inline void rect_list_node_pool_put(list_node_t *node) +{ + if (list_node_pool.len < list_node_pool.max) + { + node->next = list_node_pool.node; + list_node_pool.node = node; + list_node_pool.len++; + } + else + free(node); +} + +#if 0 +static void rect_print(const rect_t r) +{ + printf("", r.left, r.top, r.width, r.height); +} + +static void rect_list_print(const list_t rects) +{ + list_node_t *node; + int len; + + len = 0; + for (node = rects.head; node != NULL; node = node->next) + len++; + + printf("["); + for (node = rects.head; node != NULL; node = node->next) + { + rect_print(((rect_node_t *)node)->rect); + if (node->next) + { + putchar(','); + if (len < 4) + putchar(' '); + else + { + putchar('\n'); + putchar(' '); + } + } + } + printf("]\n"); +} +#endif + +static inline list_node_t * +rect_list_unlink_next(list_t *rects, list_node_t *parent_node) +{ + list_node_t *node; + + if (parent_node) + { + node = parent_node->next; + parent_node->next = node->next; + } + else + { + node = rects->head; + rects->head = node->next; + } + + if (rects->tail == node) + rects->tail = parent_node; + + *node = list_node_zeroed; + return node; +} + +static inline void rect_list_del_next(list_t *rects, list_node_t *parent_node) +{ + list_node_t *node; + + node = rect_list_unlink_next(rects, parent_node); + rect_list_node_pool_put(node); +} + +static void rect_list_clear(list_t *rects) +{ + list_node_t *node; + + node = rects->head; + while (node) + { + list_node_t *aux; + + aux = node->next; + rect_list_node_pool_put(node); + node = aux; + } + *rects = list_zeroed; +} + +static void rect_list_del_split_strict(list_t *rects, const rect_t del_r) +{ + list_t modified = list_zeroed; + list_node_t *cur_node, *prev_node; + + prev_node = NULL; + cur_node = rects->head; + while (cur_node) + { + int intra_width, intra_height; + rect_t current; + + current = ((rect_node_t *)cur_node)->rect; + + _calc_intra_rect_area(del_r, current, &intra_width, + &intra_height); + if ((intra_width <= 0) || (intra_height <= 0)) + { + /* .---.current .---.del_r + * | | | | + * `---+---.del_r `---+---.current + * | | | | + * `---' `---' + * no intersection, nothing to do + */ + prev_node = cur_node; + cur_node = cur_node->next; + } + else if ((intra_width == current.width) && (intra_height + == current.height)) + { + /* .-------.del_r + * | .---. | + * | | | | + * | `---'current + * `-------' + * current is contained, remove from rects + */ + cur_node = cur_node->next; + rect_list_del_next(rects, prev_node); + } + else + { + _split_strict(&modified, del_r, current); + cur_node = cur_node->next; + rect_list_del_next(rects, prev_node); + } + } + + rect_list_concat(rects, &modified); +} + +#if 0 +static void rect_list_add_split_strict(list_t *rects, list_node_t *node) +{ + list_t dirty = list_zeroed; + list_t new_dirty = list_zeroed; + list_node_t *cur_node; + + if (!rects->head) + { + rect_list_append_node(rects, node); + return; + } + + rect_list_append_node(&dirty, node); + + cur_node = rects->head; + while (dirty.head) + { + rect_t current; + + if (!cur_node) + { + rect_list_concat(rects, &dirty); + break; + } + + current = ((rect_node_t *)cur_node)->rect; + + while (dirty.head) + { + int intra_width, intra_height; + rect_t r; + + r = ((rect_node_t *)dirty.head)->rect; + _calc_intra_rect_area(r, current, &intra_width, + &intra_height); + if ((intra_width == r.width) && (intra_height + == r.height)) + /* .-------.cur + * | .---.r| + * | | | | + * | `---' | + * `-------' + */ + rect_list_del_next(&dirty, NULL); + else if ((intra_width <= 0) || (intra_height <= 0)) + { + /* .---.cur .---.r + * | | | | + * `---+---.r `---+---.cur + * | | | | + * `---' `---' + */ + list_node_t *tmp; + tmp = rect_list_unlink_next(&dirty, NULL); + rect_list_append_node(&new_dirty, tmp); + } + else + { + _split_strict(&new_dirty, current, r); + rect_list_del_next(&dirty, NULL); + } + } + dirty = new_dirty; + new_dirty = list_zeroed; + + cur_node = cur_node->next; + } +} +#endif + +static list_node_t * +rect_list_add_split_fuzzy(list_t *rects, list_node_t *node, int accepted_error) +{ + list_t dirty = list_zeroed; + list_node_t *old_last; + + old_last = rects->tail; + + if (!rects->head) + { + rect_list_append_node(rects, node); + return old_last; + } + + rect_list_append_node(&dirty, node); + while (dirty.head) + { + list_node_t *d_node, *cur_node, *prev_cur_node; + int keep_dirty; + rect_t r; + + d_node = rect_list_unlink_next(&dirty, NULL); + r = ((rect_node_t *)d_node)->rect; + + prev_cur_node = NULL; + cur_node = rects->head; + keep_dirty = 1; + while (cur_node) + { + int area, action; + rect_t current, intra, outer; + + current = ((rect_node_t *)cur_node)->rect; + + _calc_intra_outer_rect_area(r, current, &intra, &outer); + area = current.area + r.area - intra.area; + + if ((intra.width == r.width) && (intra.height + == r.height)) + { + /* .-------.cur + * | .---.r| + * | | | | + * | `---' | + * `-------' + */ + keep_dirty = 0; + break; + } + else if ((intra.width == current.width) + && (intra.height == current.height)) + { + /* .-------.r + * | .---.cur + * | | | | + * | `---' | + * `-------' + */ + if (old_last == cur_node) + old_last = prev_cur_node; + + cur_node = cur_node->next; + rect_list_del_next(rects, prev_cur_node); + } + else if ((outer.area - area) <= accepted_error) + { + /* .-----------. bounding box (outer) + * |.---. .---.| + * ||cur| |r || + * || | | || + * |`---' `---'| + * `-----------' + * merge them, remove both and add merged + */ + rect_node_t *n; + + if (old_last == cur_node) + old_last = prev_cur_node; + + n = (rect_node_t *)rect_list_unlink_next( + rects, prev_cur_node); + n->rect = outer; + rect_list_append_node(&dirty, (list_node_t *)n); + + keep_dirty = 0; + break; + } + else if (intra.area <= accepted_error) + { + /* .---.cur .---.r + * | | | | + * `---+---.r `---+---.cur + * | | | | + * `---' `---' + * no split, no merge + */ + prev_cur_node = cur_node; + cur_node = cur_node->next; + } + else + { + /* split is required */ + action = _split_fuzzy(&dirty, current, &r); + if (action == SPLIT_FUZZY_ACTION_MERGE) + { +/* horizontal merge is possible: remove both, add merged */ + rect_node_t *n; + + if (old_last == cur_node) + old_last = prev_cur_node; + + n + = (rect_node_t *)rect_list_unlink_next( + rects, + prev_cur_node); + + n->rect.left = outer.left; + n->rect.width = outer.width; + n->rect.right = outer.right; + n->rect.area = outer.width * r.height; + rect_list_append_node(&dirty, + (list_node_t *)n); + } + else if (action == SPLIT_FUZZY_ACTION_NONE) + { +/* + * this rect check was totally useless, + * should never happen + */ +/* prev_cur_node = cur_node; */ +/* cur_node = cur_node->next; */ + printf("Should not get here!\n"); + abort(); + } + + keep_dirty = 0; + break; + } + } + if (EINA_UNLIKELY(keep_dirty)) + rect_list_append_node(rects, d_node); + else + rect_list_node_pool_put(d_node); + } + + return old_last; +} + +static inline void _calc_outer_rect_area(const rect_t a, const rect_t b, + rect_t *outer) +{ + int min_left, max_right; + int min_top, max_bottom; + + if (a.left < b.left) + min_left = a.left; + else + min_left = b.left; + + if (a.right < b.right) + max_right = b.right; + else + max_right = a.right; + + outer->left = min_left; + outer->right = max_right; + outer->width = max_right - min_left; + + if (a.top < b.top) + min_top = a.top; + else + min_top = b.top; + + if (a.bottom < b.bottom) + max_bottom = b.bottom; + else + max_bottom = a.bottom; + + outer->top = min_top; + outer->bottom = max_bottom; + outer->height = max_bottom - min_top; + + outer->area = outer->width * outer->height; +} + +static void rect_list_merge_rects(list_t *rects, + list_t *to_merge, + int accepted_error) +{ + while (to_merge->head) + { + list_node_t *node, *parent_node; + rect_t r1; + int merged; + + r1 = ((rect_node_t *)to_merge->head)->rect; + + merged = 0; + parent_node = NULL; + node = rects->head; + while (node) + { + rect_t r2, outer; + int area; + + r2 = ((rect_node_t *)node)->rect; + + _calc_outer_rect_area(r1, r2, &outer); + area = r1.area + r2.area; /* intra area is taken as 0 */ + if (outer.area - area <= accepted_error) + { + /* + * remove both r1 and r2, create r3 + * actually r3 uses r2 instance, saves memory + */ + rect_node_t *n; + + n = (rect_node_t *)rect_list_unlink_next( + rects, parent_node); + n->rect = outer; + rect_list_append_node(to_merge, + (list_node_t *)n); + merged = 1; + break; + } + + parent_node = node; + node = node->next; + } + + if (!merged) + { + list_node_t *n; + n = rect_list_unlink_next(to_merge, NULL); + rect_list_append_node(rects, n); + } + else + rect_list_del_next(to_merge, NULL); + } +} + +static void rect_list_add_split_fuzzy_and_merge(list_t *rects, + list_node_t *node, + int split_accepted_error, + int merge_accepted_error) +{ + list_node_t *n; + + n = rect_list_add_split_fuzzy(rects, node, split_accepted_error); + if (n && n->next) + { + list_t to_merge; + + /* split list into 2 segments, already merged and to merge */ + to_merge.head = n->next; + to_merge.tail = rects->tail; + rects->tail = n; + n->next = NULL; + + rect_list_merge_rects(rects, &to_merge, merge_accepted_error); + } +} + +static inline void _splitter_new(Eina_Tiler *t) +{ + t->splitter.rects = list_zeroed; + t->splitter.need_merge = EINA_FALSE; +} + +static inline void _splitter_del(Eina_Tiler *t) +{ + rect_list_clear(&t->splitter.rects); + rect_list_node_pool_flush(); +} + +static inline void _splitter_tile_size_set(Eina_Tiler *t, + int w __UNUSED__, + int h __UNUSED__) +{ + /* TODO are w and h used for something? */ + t->splitter.rects = list_zeroed; +} + +static inline Eina_Bool _splitter_rect_add(Eina_Tiler *t, Eina_Rectangle *rect) +{ + rect_node_t *rn; + + //printf("ACCOUNTING[1]: add_redraw: %4d,%4d %3dx%3d\n", x, y, w, h); + rect->x >>= 1; + rect->y >>= 1; + rect->w += 2; + rect->w >>= 1; + rect->h += 2; + rect->h >>= 1; + + rn = (rect_node_t *)rect_list_node_pool_get(); + rn->_lst = list_node_zeroed; + rect_init(&rn->rect, rect->x, rect->y, rect->w, rect->h); + //printf("ACCOUNTING[2]: add_redraw: %4d,%4d %3dx%3d\n", x, y, w, h); + //testing on my core2 duo desktop - fuzz of 32 or 48 is best. +#define FUZZ 32 + rect_list_add_split_fuzzy_and_merge(&t->splitter.rects, + (list_node_t *)rn, + FUZZ * FUZZ, + FUZZ * FUZZ); + return EINA_TRUE; +} + +static inline void _splitter_rect_del(Eina_Tiler *t, Eina_Rectangle *rect) +{ + rect_t r; + + if (!t->splitter.rects.head) + return; + + rect->x += 1; + rect->y += 1; + rect->x >>= 1; + rect->y >>= 1; + rect->w -= 1; + rect->w >>= 1; + rect->h -= 1; + rect->h >>= 1; + + if ((rect->w <= 0) || (rect->h <= 0)) + return; + + rect_init(&r, rect->x, rect->y, rect->w, rect->h); + //fprintf(stderr, "ACCOUNTING: del_redraw: %4d,%4d %3dx%3d\n", x, y, w, h); + + rect_list_del_split_strict(&t->splitter.rects, r); + t->splitter.need_merge = EINA_TRUE; + return; +} + +static inline void _splitter_clear(Eina_Tiler *t) +{ + rect_list_clear(&t->splitter.rects); + t->splitter.need_merge = EINA_FALSE; +} +/* end of splitter algorithm */ + +static Eina_Bool _iterator_next(Eina_Iterator_Tiler *it, void **data) +{ + list_node_t *n; + + for (n = it->curr; n; n = n->next) + { + rect_t cur; + + cur = ((rect_node_t *)n)->rect; + + it->r.x = cur.left << 1; + it->r.y = cur.top << 1; + it->r.w = cur.width << 1; + it->r.h = cur.height << 1; + + if (eina_rectangle_intersection(&it->r, &it->tiler->area) == EINA_FALSE) + continue; + + if ((it->r.w <= 0) || (it->r.h <= 0)) + continue; + + it->curr = n->next; + *(Eina_Rectangle **)data = &it->r; + return EINA_TRUE; + } + return EINA_FALSE; +} + +static void *_iterator_get_container(Eina_Iterator_Tiler *it) +{ + EINA_MAGIC_CHECK_TILER_ITERATOR(it, NULL); + return (void *)it->tiler; +} + +static void _iterator_free(Eina_Iterator_Tiler *it) +{ + EINA_MAGIC_CHECK_TILER_ITERATOR(it); + free(it); +} + +/*============================================================================* +* Global * +*============================================================================*/ + +/*============================================================================* +* API * +*============================================================================*/ + +EAPI Eina_Tiler *eina_tiler_new(int w, int h) +{ + Eina_Tiler *t; + + t = calloc(1, sizeof(Eina_Tiler)); + t->area.w = w; + t->area.h = h; + t->tile.w = w; + t->tile.h = h; + EINA_MAGIC_SET(t, EINA_MAGIC_TILER); + _splitter_new(t); + return t; +} + +EAPI void eina_tiler_free(Eina_Tiler *t) +{ + EINA_MAGIC_CHECK_TILER(t); + _splitter_del(t); + free(t); +} + +EAPI void eina_tiler_tile_size_set(Eina_Tiler *t, int w, int h) +{ + EINA_MAGIC_CHECK_TILER(t); + if ((w <= 0) || (h <= 0)) + return; + + t->tile.w = w; + t->tile.h = h; + _splitter_tile_size_set(t, w, h); +} + +EAPI Eina_Bool eina_tiler_rect_add(Eina_Tiler *t, const Eina_Rectangle *r) +{ + Eina_Rectangle tmp; + + EINA_MAGIC_CHECK_TILER(t, EINA_FALSE); + if ((r->w <= 0) || (r->h <= 0)) + return EINA_FALSE; + + tmp = *r; + if (eina_rectangle_intersection(&tmp, &t->area) == EINA_FALSE) + return EINA_FALSE; + + if ((tmp.w <= 0) || (tmp.h <= 0)) + return EINA_FALSE; + + return _splitter_rect_add(t, &tmp); +} + +EAPI void eina_tiler_rect_del(Eina_Tiler *t, const Eina_Rectangle *r) +{ + Eina_Rectangle tmp; + + EINA_MAGIC_CHECK_TILER(t); + if ((r->w <= 0) || (r->h <= 0)) + return; + + tmp = *r; + if (eina_rectangle_intersection(&tmp, &t->area) == EINA_FALSE) + return; + + if ((tmp.w <= 0) || (tmp.h <= 0)) + return; + + _splitter_rect_del(t, &tmp); +} + +EAPI void eina_tiler_clear(Eina_Tiler *t) +{ + EINA_MAGIC_CHECK_TILER(t); + _splitter_clear(t); +} + + +EAPI Eina_Iterator *eina_tiler_iterator_new(const Eina_Tiler *t) +{ + Eina_Iterator_Tiler *it; + + EINA_MAGIC_CHECK_TILER(t, NULL); + + it = calloc(1, sizeof (Eina_Iterator_Tiler)); + if (!it) + return NULL; + + it->tiler = t; + + if (t->splitter.need_merge == EINA_TRUE) + { + list_t to_merge; + splitter_t *sp; + + sp = (splitter_t *)&(t->splitter); + to_merge = t->splitter.rects; + sp->rects = list_zeroed; + rect_list_merge_rects(&sp->rects, &to_merge, FUZZ * FUZZ); + sp->need_merge = 0; + } + + it->curr = it->tiler->splitter.rects.head; + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER( + _iterator_get_container); + it->iterator.free = FUNC_ITERATOR_FREE(_iterator_free); + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + EINA_MAGIC_SET(it, EINA_MAGIC_TILER_ITERATOR); + + return &it->iterator; +} + +struct _Eina_Tile_Grid_Slicer_Iterator +{ + Eina_Iterator iterator; + Eina_Tile_Grid_Slicer priv; +}; + +typedef struct _Eina_Tile_Grid_Slicer_Iterator Eina_Tile_Grid_Slicer_Iterator; + +static void +eina_tile_grid_slicer_iterator_free(Eina_Tile_Grid_Slicer_Iterator *it) +{ + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_NONE); + free(it); +} + +static Eina_Bool +eina_tile_grid_slicer_iterator_next(Eina_Tile_Grid_Slicer_Iterator *it, + void **data) +{ + return eina_tile_grid_slicer_next + (&it->priv, (const Eina_Tile_Grid_Info **)data); +} + +EAPI Eina_Iterator * +eina_tile_grid_slicer_iterator_new(int x, + int y, + int w, + int h, + int tile_w, + int tile_h) +{ + Eina_Tile_Grid_Slicer_Iterator *it; + + it = calloc(1, sizeof(*it)); + if (!it) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(eina_tile_grid_slicer_iterator_next); + it->iterator.free = FUNC_ITERATOR_FREE(eina_tile_grid_slicer_iterator_free); + + eina_tile_grid_slicer_setup(&it->priv, x, y, w, h, tile_w, tile_h); + + return &it->iterator; +} diff --git a/libraries/eina/src/lib/eina_unicode.c b/libraries/eina/src/lib/eina_unicode.c new file mode 100644 index 0000000..342e3cb --- /dev/null +++ b/libraries/eina/src/lib/eina_unicode.c @@ -0,0 +1,405 @@ +/* EINA - EFL data type library + * Copyright (C) 2010 Tom Hacohen, + * Brett Nash + * + * 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 . + + */ + +#include +#include "eina_unicode.h" + +/* FIXME: check if sizeof(wchar_t) == sizeof(Eina_Unicode) if so, + * probably better to use the standard functions */ + +/* Maybe I'm too tired, but this is the only thing that actually worked. */ +const Eina_Unicode _EINA_UNICODE_EMPTY_STRING[1] = {0}; +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) +{ + for (; *a && *a == *b; a++, b++) + ; + if (*a == *b) + return 0; + else if (*a < *b) + return -1; + else + return 1; +} + +EAPI Eina_Unicode * +eina_unicode_strcpy(Eina_Unicode *dest, const Eina_Unicode *source) +{ + Eina_Unicode *ret = dest; + + while (*source) + *dest++ = *source++; + *dest = 0; + return ret; +} + +EAPI Eina_Unicode * +eina_unicode_strncpy(Eina_Unicode *dest, const Eina_Unicode *source, size_t n) +{ + Eina_Unicode *ret = dest; + + for ( ; n && *source ; n--) + *dest++ = *source++; + for (; n; n--) + *dest++ = 0; + return ret; +} + +EAPI size_t +eina_unicode_strlen(const Eina_Unicode *ustr) +{ + const Eina_Unicode *end; + for (end = ustr; *end; end++) + ; + return end - ustr; +} + +EAPI size_t +eina_unicode_strnlen(const Eina_Unicode *ustr, int n) +{ + const Eina_Unicode *end; + const Eina_Unicode *last = ustr + n; /* technically not portable ;-) */ + for (end = ustr; end < last && *end; end++) + ; + return end - ustr; +} + + + + +EAPI Eina_Unicode * +eina_unicode_strndup(const Eina_Unicode *text, size_t n) +{ + Eina_Unicode *ustr; + + ustr = (Eina_Unicode *) malloc((n + 1) * sizeof(Eina_Unicode)); + memcpy(ustr, text, n * sizeof(Eina_Unicode)); + ustr[n] = 0; + return ustr; +} + +EAPI Eina_Unicode * +eina_unicode_strdup(const Eina_Unicode *text) +{ + size_t len; + + len = eina_unicode_strlen(text); + return eina_unicode_strndup(text, len); +} + +EAPI Eina_Unicode * +eina_unicode_strstr(const Eina_Unicode *haystack, const Eina_Unicode *needle) +{ + const Eina_Unicode *i, *j; + + for (i = haystack; *i; i++) + { + haystack = i; /* set this location as the base position */ + for (j = needle; *j && *i && *j == *i; j++, i++) + ; + + if (!*j) /*if we got to the end of j this means we got a full match */ + { + return (Eina_Unicode *)haystack; /* return the new base position */ + } + } + + return NULL; +} + +EAPI Eina_Unicode * +eina_unicode_escape(const Eina_Unicode *str) +{ + Eina_Unicode *s2, *d; + const Eina_Unicode *s; + + s2 = malloc((eina_unicode_strlen(str) * 2) + 1); + if (!s2) + return NULL; + + for (s = str, d = s2; *s != 0; s++, d++) + { + if ((*s == ' ') || (*s == '\\') || (*s == '\'')) + { + *d = '\\'; + d++; + } + + *d = *s; + } + *d = 0; + return s2; +} + +/* UTF-8 Handling */ + +#define EINA_UNICODE_UTF8_BYTES_PER_CHAR 6 +/* The replacement range that will be used for bad utf8 chars. */ +#define ERROR_REPLACEMENT_BASE 0xDC80 +#define ERROR_REPLACEMENT_END 0xDCFF +#define IS_INVALID_BYTE(x) ((x == 192) || (x == 193) || (x >= 245)) +#define IS_CONTINUATION_BYTE(x) ((x & 0xC0) == 0x80) + +EAPI Eina_Unicode +eina_unicode_utf8_get_next(const char *buf, int *iindex) +{ + int ind = *iindex; + Eina_Unicode r; + unsigned char d; + + /* if this char is the null terminator, exit */ + if ((d = buf[ind++]) == 0) return 0; + + if ((d & 0x80) == 0) + { // 1 byte (7bit) - 0xxxxxxx + *iindex = ind; + return d; + } + if ((d & 0xe0) == 0xc0) + { // 2 byte (11bit) - 110xxxxx 10xxxxxx + r = (d & 0x1f) << 6; + if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) || + !IS_CONTINUATION_BYTE(d)) goto error; + r |= (d & 0x3f); + if (r <= 0x7F) goto error; + *iindex = ind; + return r; + } + if ((d & 0xf0) == 0xe0) + { // 3 byte (16bit) - 1110xxxx 10xxxxxx 10xxxxxx + r = (d & 0x0f) << 12; + if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) || + !IS_CONTINUATION_BYTE(d)) goto error; + r |= (d & 0x3f) << 6; + if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) || + !IS_CONTINUATION_BYTE(d)) goto error; + r |= (d & 0x3f); + if (r <= 0x7FF) goto error; + *iindex = ind; + return r; + } + if ((d & 0xf8) == 0xf0) + { // 4 byte (21bit) - 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + r = (d & 0x07) << 18; + if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) || + !IS_CONTINUATION_BYTE(d)) goto error; + r |= (d & 0x3f) << 12; + if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) || + !IS_CONTINUATION_BYTE(d)) goto error; + r |= (d & 0x3f) << 6; + if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) || + !IS_CONTINUATION_BYTE(d)) goto error; + r |= (d & 0x3f); + if (r <= 0xFFFF) goto error; + *iindex = ind; + return r; + } + if ((d & 0xfc) == 0xf8) + { // 5 byte (26bit) - 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + r = (d & 0x03) << 24; + if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) || + !IS_CONTINUATION_BYTE(d)) goto error; + r |= (d & 0x3f) << 18; + if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) || + !IS_CONTINUATION_BYTE(d)) goto error; + r |= (d & 0x3f) << 12; + if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) || + !IS_CONTINUATION_BYTE(d)) goto error; + r |= (d & 0x3f) << 6; + if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) || + !IS_CONTINUATION_BYTE(d)) goto error; + r |= (d & 0x3f); + if (r <= 0x1FFFFF) goto error; + *iindex = ind; + return r; + } + if ((d & 0xfe) == 0xfc) + { // 6 byte (31bit) - 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + r = (d & 0x01) << 30; + if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) || + !IS_CONTINUATION_BYTE(d)) goto error; + r |= (d & 0x3f) << 24; + if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) || + !IS_CONTINUATION_BYTE(d)) goto error; + r |= (d & 0x3f) << 18; + if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) || + !IS_CONTINUATION_BYTE(d)) goto error; + r |= (d & 0x3f) << 12; + if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) || + !IS_CONTINUATION_BYTE(d)) goto error; + r |= (d & 0x3f) << 6; + if (((d = buf[ind++]) == 0) || IS_INVALID_BYTE(d) || + !IS_CONTINUATION_BYTE(d)) goto error; + r |= (d & 0x3f); + if (r <= 0x3FFFFFF) goto error; + *iindex = ind; + return r; + } + +/* Gets here where there was an error and we want to replace the char + * we just use the invalid unicode codepoints 8 lower bits represent + * the original char */ +error: + d = buf[*iindex]; + (*iindex)++; + return ERROR_REPLACEMENT_BASE | d; +} + +EAPI Eina_Unicode +eina_unicode_utf8_get_prev(const char *buf, int *iindex) +{ + int r; + int ind = *iindex; + /* First obtain the codepoint at iindex */ + r = eina_unicode_utf8_get_next(buf, &ind); + + /* although when ind == 0 there's no previous char, we still want to get + * the current char */ + if (*iindex <= 0) + return r; + + /* Next advance iindex to previous codepoint */ + ind = *iindex; + ind--; + while ((ind > 0) && ((buf[ind] & 0xc0) == 0x80)) + ind--; + + *iindex = ind; + return r; +} + +EAPI int +eina_unicode_utf8_get_len(const char *buf) +{ + /* returns the number of utf8 characters (not bytes) in the string */ + int i = 0, len = 0; + + while (eina_unicode_utf8_get_next(buf, &i)) + len++; + + return len; +} + +EAPI Eina_Unicode * +eina_unicode_utf8_to_unicode(const char *utf, int *_len) +{ + /* FIXME: Should optimize! */ + int len, i; + int ind; + Eina_Unicode *buf, *uind; + + len = eina_unicode_utf8_get_len(utf); + if (_len) + *_len = len; + buf = (Eina_Unicode *) calloc(sizeof(Eina_Unicode), (len + 1)); + if (!buf) return buf; + + for (i = 0, ind = 0, uind = buf ; i < len ; i++, uind++) + { + *uind = eina_unicode_utf8_get_next(utf, &ind); + } + + return buf; +} + +EAPI char * +eina_unicode_unicode_to_utf8(const Eina_Unicode *uni, int *_len) +{ + char *buf; + const Eina_Unicode *uind; + char *ind; + int ulen, len; + + ulen = eina_unicode_strlen(uni); + buf = (char *) calloc(ulen + 1, EINA_UNICODE_UTF8_BYTES_PER_CHAR); + + len = 0; + for (uind = uni, ind = buf ; *uind ; uind++) + { + if (*uind <= 0x7F) /* 1 byte char */ + { + *ind++ = *uind; + len += 1; + } + else if (*uind <= 0x7FF) /* 2 byte char */ + { + *ind++ = 0xC0 | (unsigned char) (*uind >> 6); + *ind++ = 0x80 | (unsigned char) (*uind & 0x3F); + len += 2; + } + else if (*uind <= 0xFFFF) /* 3 byte char */ + { + /* If it's a special replacement codepoint */ + if (*uind >= ERROR_REPLACEMENT_BASE && + *uind <= ERROR_REPLACEMENT_END) + { + *ind++ = *uind & 0xFF; + len += 1; + } + else + { + *ind++ = 0xE0 | (unsigned char) (*uind >> 12); + *ind++ = 0x80 | (unsigned char) ((*uind >> 6) & 0x3F); + *ind++ = 0x80 | (unsigned char) (*uind & 0x3F); + len += 3; + } + } + else if (*uind <= 0x1FFFFF) /* 4 byte char */ + { + *ind++ = 0xF0 | (unsigned char) ((*uind >> 18) & 0x07); + *ind++ = 0x80 | (unsigned char) ((*uind >> 12) & 0x3F); + *ind++ = 0x80 | (unsigned char) ((*uind >> 6) & 0x3F); + *ind++ = 0x80 | (unsigned char) (*uind & 0x3F); + len += 4; + } + else if (*uind <= 0x3FFFFFF) /* 5 byte char */ + { + *ind++ = 0xF8 | (unsigned char) ((*uind >> 24) & 0x03); + *ind++ = 0x80 | (unsigned char) ((*uind >> 18) & 0x3F); + *ind++ = 0x80 | (unsigned char) ((*uind >> 12) & 0x3F); + *ind++ = 0x80 | (unsigned char) ((*uind >> 6) & 0x3F); + *ind++ = 0x80 | (unsigned char) (*uind & 0x3F); + len += 5; + } + else if (*uind <= 0x7FFFFFFF) /* 6 byte char */ + { + *ind++ = 0xFC | (unsigned char) ((*uind >> 30) & 0x01); + *ind++ = 0x80 | (unsigned char) ((*uind >> 24) & 0x3F); + *ind++ = 0x80 | (unsigned char) ((*uind >> 18) & 0x3F); + *ind++ = 0x80 | (unsigned char) ((*uind >> 12) & 0x3F); + *ind++ = 0x80 | (unsigned char) ((*uind >> 6) & 0x3F); + *ind++ = 0x80 | (unsigned char) (*uind & 0x3F); + len += 6; + } + else /* error */ + { + /* Do something */ + } + } + buf = realloc(buf, len + 1); + buf[len] = '\0'; + if (_len) + *_len = len; + return buf; +} + + + diff --git a/libraries/eina/src/lib/eina_ustrbuf.c b/libraries/eina/src/lib/eina_ustrbuf.c new file mode 100644 index 0000000..7c1c2db --- /dev/null +++ b/libraries/eina/src/lib/eina_ustrbuf.c @@ -0,0 +1,74 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "eina_strbuf_common.h" +#include "eina_unicode.h" +#include "eina_ustrbuf.h" + +/*============================================================================* + * Local * + *============================================================================*/ + +/** + * @cond LOCAL + */ + +#ifdef _STRBUF_DATA_TYPE +# undef _STRBUF_DATA_TYPE +#endif + +#ifdef _STRBUF_CSIZE +# undef _STRBUF_CSIZE +#endif + +#ifdef _STRBUF_STRUCT_NAME +# undef _STRBUF_STRUCT_NAME +#endif + +#ifdef _STRBUF_STRLEN_FUNC +# undef _STRBUF_STRLEN_FUNC +#endif + +#ifdef _STRBUF_STRESCAPE_FUNC +# undef _STRBUF_STRESCAPE_FUNC +#endif + +#ifdef _STRBUF_MAGIC +# undef _STRBUF_MAGIC +#endif + +#ifdef _STRBUF_MAGIC_STR +# undef _STRBUF_MAGIC_STR +#endif + +#ifdef _FUNC_EXPAND +# undef _FUNC_EXPAND +#endif + +#define _STRBUF_DATA_TYPE Eina_Unicode +#define _STRBUF_CSIZE sizeof(_STRBUF_DATA_TYPE) +#define _STRBUF_STRUCT_NAME Eina_UStrbuf +#define _STRBUF_STRLEN_FUNC(x) eina_unicode_strlen(x) +#define _STRBUF_STRESCAPE_FUNC(x) eina_unicode_escape(x) +#define _STRBUF_MAGIC EINA_MAGIC_USTRBUF +#define _STRBUF_MAGIC_STR __USTRBUF_MAGIC_STR +static const char __USTRBUF_MAGIC_STR[] = "Eina UStrbuf"; + +#define _FUNC_EXPAND(y) eina_ustrbuf_ ## y + +/** + * @endcond + */ + + +/*============================================================================* + * Global * + *============================================================================*/ + + +/*============================================================================* + * API * + *============================================================================*/ + +#include "eina_strbuf_template_c.x" diff --git a/libraries/eina/src/lib/eina_ustringshare.c b/libraries/eina/src/lib/eina_ustringshare.c new file mode 100644 index 0000000..3992dc6 --- /dev/null +++ b/libraries/eina/src/lib/eina_ustringshare.c @@ -0,0 +1,132 @@ +/* EINA - EFL data type library + * Copyright (C) 2002-2008 Carsten Haitzler, + * Jorge Luis Zapata Muga, + * Cedric Bail, + * Gustavo Sverzut Barbieri + * Tom Hacohen + * + * 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 . + + */ +/** + * @page tutorial_ustringshare_page UStringshare Tutorial + * + * to be written... + * + */ + +#include "eina_share_common.h" +#include "eina_unicode.h" +#include "eina_private.h" +#include "eina_ustringshare.h" + +/* The actual share */ +static Eina_Share *ustringshare_share; +static const char EINA_MAGIC_USTRINGSHARE_NODE_STR[] = "Eina UStringshare Node"; + +/*============================================================================* +* Global * +*============================================================================*/ + +/** + * @internal + * @brief Initialize the share_common module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the share_common module of Eina. It is called by + * eina_init(). + * + * @see eina_init() + */ +Eina_Bool +eina_ustringshare_init(void) +{ + return eina_share_common_init(&ustringshare_share, + EINA_MAGIC_USTRINGSHARE_NODE, + EINA_MAGIC_USTRINGSHARE_NODE_STR); +} + +/** + * @internal + * @brief Shut down the share_common module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the share_common module set up by + * eina_share_common_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_ustringshare_shutdown(void) +{ + Eina_Bool ret; + ret = eina_share_common_shutdown(&ustringshare_share); + return ret; +} + +/*============================================================================* +* API * +*============================================================================*/ + +EAPI void +eina_ustringshare_del(const Eina_Unicode *str) +{ + if (!str) + return; + + eina_share_common_del(ustringshare_share,(const char *)str); +} + +EAPI const Eina_Unicode * +eina_ustringshare_add_length(const Eina_Unicode *str, unsigned int slen) +{ + return (const Eina_Unicode *)eina_share_common_add_length(ustringshare_share, + (const char *)str, + slen * + sizeof( + Eina_Unicode), + sizeof( + Eina_Unicode)); +} + +EAPI const Eina_Unicode * +eina_ustringshare_add(const Eina_Unicode *str) +{ + int slen = (str) ? (int)eina_unicode_strlen(str) : -1; + return eina_ustringshare_add_length(str, slen); +} + +EAPI const Eina_Unicode * +eina_ustringshare_ref(const Eina_Unicode *str) +{ + return (const Eina_Unicode *)eina_share_common_ref(ustringshare_share, + (const char *)str); +} + +EAPI int +eina_ustringshare_strlen(const Eina_Unicode *str) +{ + int len = eina_share_common_length(ustringshare_share, (const char *)str); + len = (len > 0) ? len / (int)sizeof(Eina_Unicode) : -1; + return len; +} + +EAPI void +eina_ustringshare_dump(void) +{ + eina_share_common_dump(ustringshare_share, NULL, 0); +} diff --git a/libraries/eina/src/lib/eina_value.c b/libraries/eina/src/lib/eina_value.c new file mode 100644 index 0000000..554f907 --- /dev/null +++ b/libraries/eina/src/lib/eina_value.c @@ -0,0 +1,47 @@ +/* eina_value.c + + Copyright (C) 2001 Christopher Rosendahl + Nathan Ingersoll + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies of the Software and its documentation and acknowledgment shall be + given in the documentation and software packages that this Software was + used. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "eina_config.h" +#include "eina_private.h" + +/*============================================================================* +* Global * +*============================================================================*/ + +/*============================================================================* +* API * +*============================================================================*/ + +EAPI const unsigned int eina_prime_table[] = +{ + 17, 31, 61, 127, 257, 509, 1021, + 2053, 4093, 8191, 16381, 32771, 65537, 131071, 262147, 524287, 1048573, + 2097143, 4194301, 8388617, 16777213 +}; diff --git a/libraries/eina/src/lib/eina_xattr.c b/libraries/eina/src/lib/eina_xattr.c new file mode 100644 index 0000000..bd5b98e --- /dev/null +++ b/libraries/eina/src/lib/eina_xattr.c @@ -0,0 +1,292 @@ +/* EINA - EFL data type library + * Copyright (C) 2011 Cedric Bail + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_XATTR +# include +#endif + +#include "eina_config.h" +#include "eina_private.h" + +#include "eina_safety_checks.h" +#include "eina_xattr.h" +#include "eina_convert.h" + +/*============================================================================* + * Local * + *============================================================================*/ + +/** + * @cond LOCAL + */ + +typedef struct _Eina_Xattr_Iterator Eina_Xattr_Iterator; + +struct _Eina_Xattr_Iterator +{ + Eina_Iterator iterator; + + ssize_t length; + ssize_t offset; + + char xattr[1]; +}; + +#ifdef HAVE_XATTR +static Eina_Bool +_eina_xattr_ls_iterator_next(Eina_Xattr_Iterator *it, void **data) +{ + if (it->offset >= it->length) + return EINA_FALSE; + + *data = it->xattr + it->offset; + it->offset += strlen(it->xattr + it->offset) + 1; + + return EINA_TRUE; +} + +static void * +_eina_xattr_ls_iterator_container(Eina_Xattr_Iterator *it __UNUSED__) +{ + return NULL; +} + +static void +_eina_xattr_ls_iterator_free(Eina_Xattr_Iterator *it) +{ + EINA_MAGIC_SET(&it->iterator, 0); + free(it); +} +#endif + +/** + * @endcond + */ + + +/*============================================================================* + * Global * + *============================================================================*/ + + +/*============================================================================* + * API * + *============================================================================*/ + + +EAPI Eina_Iterator * +eina_xattr_ls(const char *file) +{ +#ifdef HAVE_XATTR + Eina_Xattr_Iterator *it; + ssize_t length; + + EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); + + length = listxattr(file, NULL, 0); + if (length <= 0) return NULL; + + it = calloc(1, sizeof (Eina_Xattr_Iterator) + length - 1); + if (!it) return NULL; + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->length = listxattr(file, it->xattr, length); + if (it->length != length) + { + free(it); + return NULL; + } + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_eina_xattr_ls_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_xattr_ls_iterator_container); + it->iterator.free = FUNC_ITERATOR_FREE(_eina_xattr_ls_iterator_free); + + return &it->iterator; +#else + return NULL; + (void)file; +#endif +} + +EAPI void * +eina_xattr_get(const char *file, const char *attribute, ssize_t *size) +{ +#ifdef HAVE_XATTR + void *ret = NULL; + ssize_t tmp; + + EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(attribute, NULL); + EINA_SAFETY_ON_TRUE_RETURN_VAL(!size, NULL); + + *size = getxattr(file, attribute, NULL, 0); + /* Size should be less than 2MB (already huge in my opinion) */ + if (!(*size > 0 && *size < 2 * 1024 * 1024)) + goto on_error; + + ret = malloc(*size); + if (!ret) return NULL; + + tmp = getxattr(file, attribute, ret, *size); + if (tmp != *size) + goto on_error; + + return ret; + + on_error: + free(ret); + *size = 0; + return NULL; +#else + EINA_SAFETY_ON_TRUE_RETURN_VAL(!size, NULL); + *size = 0; + return NULL; + (void)file; + (void)attribute; +#endif +} + +EAPI Eina_Bool +eina_xattr_set(const char *file, const char *attribute, const void *data, ssize_t length, Eina_Xattr_Flags flags) +{ +#ifdef HAVE_XATTR + int iflags; + + EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(attribute, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE); + EINA_SAFETY_ON_TRUE_RETURN_VAL(!(length > 0 && length < 2 * 1024 * 1024), EINA_FALSE); + + switch (flags) + { + case EINA_XATTR_INSERT: iflags = 0; break; + case EINA_XATTR_REPLACE: iflags = XATTR_REPLACE; break; + case EINA_XATTR_CREATED: iflags = XATTR_CREATE; break; + default: + return EINA_FALSE; + } + + if (setxattr(file, attribute, data, length, iflags)) + return EINA_FALSE; + return EINA_TRUE; +#else + return EINA_FALSE; + (void)file; + (void)attribute; + (void)data; + (void)length; + (void)flags; +#endif +} + +EAPI Eina_Bool +eina_xattr_string_set(const char *file, const char *attribute, const char *data, Eina_Xattr_Flags flags) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE); + + return eina_xattr_set(file, attribute, data, strlen(data) + 1, flags); +} + +EAPI char * +eina_xattr_string_get(const char *file, const char *attribute) +{ + char *tmp; + ssize_t size; + + tmp = eina_xattr_get(file, attribute, &size); + if (!tmp) return NULL; + + if (tmp[size - 1] != '\0') + { + free(tmp); + return NULL; + } + + return tmp; +} + +EAPI Eina_Bool +eina_xattr_double_set(const char *file, const char *attribute, double value, Eina_Xattr_Flags flags) +{ + char buffer[128]; + + eina_convert_dtoa(value, buffer); + return eina_xattr_string_set(file, attribute, buffer, flags); +} + +EAPI Eina_Bool +eina_xattr_double_get(const char *file, const char *attribute, double *value) +{ + char *tmp; + long long int m = 0; + long int e = 0; + + EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE); + + tmp = eina_xattr_string_get(file, attribute); + if (!tmp) return EINA_FALSE; + + if (!eina_convert_atod(tmp, strlen(tmp), &m, &e)) + { + free(tmp); + return EINA_FALSE; + } + + *value = ldexp((double)m, e); + free(tmp); + + return EINA_TRUE; +} + +EAPI Eina_Bool +eina_xattr_int_set(const char *file, const char *attribute, int value, Eina_Xattr_Flags flags) +{ + char buffer[10]; + + eina_convert_itoa(value, buffer); + return eina_xattr_string_set(file, attribute, buffer, flags); +} + +EAPI Eina_Bool +eina_xattr_int_get(const char *file, const char *attribute, int *value) +{ + char *tmp; + char *eos; + Eina_Bool result; + + EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE); + + tmp = eina_xattr_string_get(file, attribute); + if (!tmp) return EINA_FALSE; + + *value = (int) strtol(tmp, &eos, 10); + result = (*eos == '\0'); + free(tmp); + + return result; +} -- cgit v1.1