diff options
Diffstat (limited to 'src/lib')
53 files changed, 0 insertions, 39383 deletions
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am deleted file mode 100644 index 0e017c3..0000000 --- a/src/lib/Makefile.am +++ /dev/null @@ -1,180 +0,0 @@ -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)\" \ -@EFL_EINA_BUILD@ \ -@EFL_PTHREAD_CFLAGS@ \ -@EINA_CFLAGS@ \ -@VALGRIND_CFLAGS@ - -base_sources = \ -eina_accessor.c \ -eina_array.c \ -eina_benchmark.c \ -eina_binbuf.c \ -eina_binshare.c \ -eina_convert.c \ -eina_counter.c \ -eina_cpu.c \ -eina_error.c \ -eina_fp.c \ -eina_hamster.c \ -eina_hash.c \ -eina_inarray.c \ -eina_inlist.c \ -eina_iterator.c \ -eina_lalloc.c \ -eina_list.c \ -eina_log.c \ -eina_magic.c \ -eina_main.c \ -eina_matrixsparse.c \ -eina_mempool.c \ -eina_mmap.c \ -eina_module.c \ -eina_prefix.c \ -eina_quadtree.c \ -eina_rbtree.c \ -eina_rectangle.c \ -eina_safety_checks.c \ -eina_sched.c \ -eina_share_common.c \ -eina_simple_xml_parser.c \ -eina_str.c \ -eina_strbuf.c \ -eina_strbuf_common.c \ -eina_stringshare.c \ -eina_tiler.c \ -eina_thread.c \ -eina_unicode.c \ -eina_ustrbuf.c \ -eina_ustringshare.c \ -eina_value.c \ -eina_xattr.c - -# Will be back for developper after 1.2 -# eina_model.c \ -# 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 <alloca.h>" >> 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 <malloc.h>" >> eina_amalgamation.c - @echo "# define alloca _alloca" >> eina_amalgamation.c - @echo "#else" >> eina_amalgamation.c - @echo "# include <stddef.h>" >> 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 <stdio.h>" >> eina_amalgamation.c - @echo "#include <stdlib.h>" >> eina_amalgamation.c - @echo "#include <string.h>" >> eina_amalgamation.c - @echo "#ifdef HAVE_DLOPEN" >> eina_amalgamation.c - @echo "# include <dlfcn.h>" >> eina_amalgamation.c - @echo "#endif" >> eina_amalgamation.c - @echo "#include <sys/types.h>" >> eina_amalgamation.c - @echo "#ifdef HAVE_DIRENT_H" >> eina_amalgamation.c - @echo "# include <dirent.h>" >> eina_amalgamation.c - @echo "#endif" >> eina_amalgamation.c - @echo "#include <assert.h>" >> eina_amalgamation.c - @echo "#include <errno.h>" >> eina_amalgamation.c - @echo "#include <fnmatch.h>" >> eina_amalgamation.c - @echo "#include <fcntl.h>" >> eina_amalgamation.c - - @echo "#ifdef HAVE_EVIL" >> eina_amalgamation.c - @echo "# include <Evil.h>" >> 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 = @EINA_LIBS@ -lm -libeina_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@ @EFL_PTHREAD_LIBS@ - -clean-local: - rm -rf *.gcno eina_amalgamation.c diff --git a/src/lib/eina_accessor.c b/src/lib/eina_accessor.c deleted file mode 100644 index 994704d..0000000 --- a/src/lib/eina_accessor.c +++ /dev/null @@ -1,179 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> - -#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) -{ - if (!accessor) - return; - - EINA_MAGIC_CHECK_ACCESSOR(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; - - if (!accessor) return ; - - EINA_MAGIC_CHECK_ACCESSOR(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/src/lib/eina_array.c b/src/lib/eina_array.c deleted file mode 100644 index 4bcab61..0000000 --- a/src/lib/eina_array.c +++ /dev/null @@ -1,491 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> - -#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(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(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/src/lib/eina_benchmark.c b/src/lib/eina_benchmark.c deleted file mode 100644 index 1ba2a00..0000000 --- a/src/lib/eina_benchmark.c +++ /dev/null @@ -1,372 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_ALLOCA_H -# include <alloca.h> -#elif defined __GNUC__ -# define alloca __builtin_alloca -#elif defined _AIX -# define alloca __alloca -#elif defined _MSC_VER -# include <malloc.h> -# define alloca _alloca -#else -# include <stddef.h> -# ifdef __cplusplus -extern "C" -# endif -void *alloca (size_t); -#endif - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#ifdef HAVE_EVIL -# include <Evil.h> -#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/src/lib/eina_binbuf.c b/src/lib/eina_binbuf.c deleted file mode 100644 index 3cbebd1..0000000 --- a/src/lib/eina_binbuf.c +++ /dev/null @@ -1,62 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdio.h> -#include <string.h> - -#ifdef HAVE_EVIL -# include <Evil.h> -#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/src/lib/eina_binbuf_template_c.x b/src/lib/eina_binbuf_template_c.x deleted file mode 100644 index 7e0c539..0000000 --- a/src/lib/eina_binbuf_template_c.x +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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 _STRBUF_STRUCT_NAME * -_FUNC_EXPAND(manage_new_length)(_STRBUF_DATA_TYPE *str, size_t length) -{ - _STRBUF_STRUCT_NAME *buf = - eina_strbuf_common_manage_new(_STRBUF_CSIZE, (void *) str, length); - EINA_MAGIC_SET(buf, _STRBUF_MAGIC); - return buf; -} - -EAPI void -_FUNC_EXPAND(free)(_STRBUF_STRUCT_NAME *buf) -{ - 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/src/lib/eina_binshare.c b/src/lib/eina_binshare.c deleted file mode 100644 index 01e8046..0000000 --- a/src/lib/eina_binshare.c +++ /dev/null @@ -1,182 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "eina_config.h" -#include "eina_private.h" -#include "eina_unicode.h" -#include "eina_log.h" -#include "eina_share_common.h" - -/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ -#include "eina_safety_checks.h" -#include "eina_binshare.h" - -/*============================================================================* - * Local * - *============================================================================*/ - -/** - * @cond LOCAL - */ - -#ifdef CRITICAL -#undef CRITICAL -#endif -#define CRITICAL(...) EINA_LOG_DOM_CRIT(_eina_share_binshare_log_dom, __VA_ARGS__) - -#ifdef ERR -#undef ERR -#endif -#define ERR(...) EINA_LOG_DOM_ERR(_eina_share_binshare_log_dom, __VA_ARGS__) - -#ifdef DBG -#undef DBG -#endif -#define DBG(...) EINA_LOG_DOM_DBG(_eina_share_binshare_log_dom, __VA_ARGS__) - -static int _eina_share_binshare_log_dom = -1; - -/* The actual share */ -static Eina_Share *binshare_share; -static const char EINA_MAGIC_BINSHARE_NODE_STR[] = "Eina Binshare Node"; - -/** - * @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) -{ - Eina_Bool ret; - - if (_eina_share_binshare_log_dom < 0) - { - _eina_share_binshare_log_dom = eina_log_domain_register - ("eina_binshare", EINA_LOG_COLOR_DEFAULT); - - if (_eina_share_binshare_log_dom < 0) - { - EINA_LOG_ERR("Could not register log domain: eina_binshare"); - return EINA_FALSE; - } - } - - ret = eina_share_common_init(&binshare_share, - EINA_MAGIC_BINSHARE_NODE, - EINA_MAGIC_BINSHARE_NODE_STR); - - if (!ret) - { - eina_log_domain_unregister(_eina_share_binshare_log_dom); - _eina_share_binshare_log_dom = -1; - } - - return ret; -} - -/** - * @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); - - if (_eina_share_binshare_log_dom > 0) - { - eina_log_domain_unregister(_eina_share_binshare_log_dom); - _eina_share_binshare_log_dom = -1; - } - - return ret; -} - - -/*============================================================================* - * API * - *============================================================================*/ - -EAPI void -eina_binshare_del(const void *obj) -{ - if (!obj) - return; - - if (!eina_share_common_del(binshare_share, obj)) - CRITICAL("EEEK trying to del non-shared binshare %p", 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/src/lib/eina_convert.c b/src/lib/eina_convert.c deleted file mode 100644 index 7e397e0..0000000 --- a/src/lib/eina_convert.c +++ /dev/null @@ -1,482 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <math.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> - -#ifdef HAVE_EVIL -# include <Evil.h> -#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_FALSE; - - e += 32; - - if (e > 0) - *fp = m << e; - else - *fp = m >> -e; - - return EINA_TRUE; -} - -/** - * @} - */ diff --git a/src/lib/eina_counter.c b/src/lib/eina_counter.c deleted file mode 100644 index 6ca9417..0000000 --- a/src/lib/eina_counter.c +++ /dev/null @@ -1,362 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#ifndef _WIN32 -# include <time.h> -# include <sys/time.h> -#else -# define WIN32_LEAN_AND_MEAN -# include <windows.h> -# 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 <Escape.h> -#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/src/lib/eina_cpu.c b/src/lib/eina_cpu.c deleted file mode 100644 index eb71002..0000000 --- a/src/lib/eina_cpu.c +++ /dev/null @@ -1,224 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef EFL_HAVE_THREADS -# ifdef _WIN32 -# define WIN32_LEAN_AND_MEAN -# include <windows.h> -# elif defined (__sun) || defined(__GNU__) || defined(__CYGWIN__) -# include <unistd.h> -# elif defined (__FreeBSD__) || defined (__OpenBSD__) || \ - defined (__NetBSD__) || defined (__DragonFly__) || defined (__MacOSX__) || \ - (defined (__MACH__) && defined (__APPLE__)) -# include <unistd.h> -# include <sys/param.h> -# include <sys/sysctl.h> -# elif defined (__linux__) || defined(__GLIBC__) -# include <sched.h> -# endif -# ifdef EFL_HAVE_POSIX_THREADS -# include <pthread.h> -# endif - -# define TH_MAX 8 -#endif - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#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; -} - -static int _cpu_count = -1; - -static int -_eina_cpu_count_internal(void) -{ -#ifdef EFL_HAVE_THREADS - -# if defined (_WIN32) - SYSTEM_INFO sysinfo; - - GetSystemInfo(&sysinfo); - return sysinfo.dwNumberOfProcessors; - -# elif defined (__sun) || defined(__GNU__) || defined(__CYGWIN__) - /* - * _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 -} - -EAPI int eina_cpu_count(void) -{ - return _cpu_count; -} - -void eina_cpu_count_internal(void) -{ - if (getenv("EINA_CPU_FAKE")) - _cpu_count = atoi(getenv("EINA_CPU_FAKE")); - else - _cpu_count = _eina_cpu_count_internal(); -} diff --git a/src/lib/eina_error.c b/src/lib/eina_error.c deleted file mode 100644 index 428c414..0000000 --- a/src/lib/eina_error.c +++ /dev/null @@ -1,279 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> - -#ifdef HAVE_EVIL -# include <Evil.h> -#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/src/lib/eina_file.c b/src/lib/eina_file.c deleted file mode 100644 index 85e19ec..0000000 --- a/src/lib/eina_file.c +++ /dev/null @@ -1,1512 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_ALLOCA_H -# include <alloca.h> -#elif defined __GNUC__ -# define alloca __builtin_alloca -#elif defined _AIX -# define alloca __alloca -#elif defined _MSC_VER -# include <malloc.h> -# define alloca _alloca -#else -# include <stddef.h> -# ifdef __cplusplus -extern "C" -# endif -void *alloca (size_t); -#endif - -#include <stdlib.h> -#include <string.h> -#include <stddef.h> -#include <stdint.h> -#ifdef HAVE_DIRENT_H -# include <dirent.h> -#endif -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#ifdef HAVE_SYS_MMAN_H -# include <sys/mman.h> -#endif -#include <fcntl.h> - -#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" -#include "eina_log.h" -#include "eina_xattr.h" - -#ifdef HAVE_ESCAPE -# include <Escape.h> -#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 - -#ifdef HAVE_DIRENT_H -typedef struct _Eina_File_Iterator Eina_File_Iterator; -struct _Eina_File_Iterator -{ - Eina_Iterator iterator; - - DIR *dirp; - int length; - - char dir[1]; -}; -#endif - -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; - Eina_Bool global_faulty : 1; -}; - -typedef struct _Eina_File_Map Eina_File_Map; -struct _Eina_File_Map -{ - void *map; - - unsigned long int offset; - unsigned long int length; - - int refcount; - - Eina_Bool hugetlb : 1; - Eina_Bool faulty : 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 - */ -#ifdef HAVE_DIRENT_H -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) -{ - Eina_Stat st; - - if (!_eina_file_direct_ls_iterator_next(it, data)) - return EINA_FALSE; - - if (it->info.type == EINA_FILE_UNKNOWN) - { - if (eina_file_statat(it->dirp, &it->info, &st) != 0) - it->info.type = EINA_FILE_UNKNOWN; - } - - return EINA_TRUE; -} -#endif - -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; - char *p; - char *q; - size_t len; - - result = strdup(path ? path : ""); - p = result; - q = result; - - 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 - if (p[1] == '.' - && p[2] == '/') - { - // remove '/./' - len -= 2; - memmove(p, p + 2, len - (p - result)); - result[len] = '\0'; - q = p; - ++p; - } - else - { - q = p; - ++p; - } - } - - if (length) - *length = len; - return result; -} - -/** - * @endcond - */ - -/*============================================================================* - * Global * - *============================================================================*/ - -Eina_Bool -eina_file_init(void) -{ - _eina_file_log_dom = eina_log_domain_register("eina_file", - EINA_LOG_COLOR_DEFAULT); - if (_eina_file_log_dom < 0) - { - EINA_LOG_ERR("Could not register log domain: eina_file"); - return EINA_FALSE; - } - - _eina_file_cache = eina_hash_string_djb2_new(NULL); - if (!_eina_file_cache) - { - ERR("Could not create cache."); - eina_log_domain_unregister(_eina_file_log_dom); - _eina_file_log_dom = -1; - return EINA_FALSE; - } - - eina_lock_new(&_eina_file_lock_cache); - - return EINA_TRUE; -} - -Eina_Bool -eina_file_shutdown(void) -{ - if (eina_hash_population(_eina_file_cache) > 0) - { - Eina_Iterator *it; - const char *key; - - it = eina_hash_iterator_key_new(_eina_file_cache); - EINA_ITERATOR_FOREACH(it, key) - ERR("File [%s] still open !", key); - eina_iterator_free(it); - } - - eina_hash_free(_eina_file_cache); - - eina_lock_free(&_eina_file_lock_cache); - - eina_log_domain_unregister(_eina_file_log_dom); - _eina_file_log_dom = -1; - return EINA_TRUE; -} - -void -eina_file_mmap_faulty(void *addr, long page_size) -{ - Eina_File_Map *m; - Eina_File *f; - Eina_Iterator *itf; - Eina_Iterator *itm; - - /* NOTE: I actually don't know if other thread are running, I will try to take the lock. - It may be possible that if other thread are not running and they were in the middle of - accessing an Eina_File this lock are still taken and we will result as a deadlock. */ - eina_lock_take(&_eina_file_lock_cache); - - itf = eina_hash_iterator_data_new(_eina_file_cache); - EINA_ITERATOR_FOREACH(itf, f) - { - Eina_Bool faulty = EINA_FALSE; - - eina_lock_take(&f->lock); - - if (f->global_map) - { - if ((unsigned char *) addr < (((unsigned char *)f->global_map) + f->length) && - (((unsigned char *) addr) + page_size) >= (unsigned char *) f->global_map) - { - f->global_faulty = EINA_TRUE; - faulty = EINA_TRUE; - } - } - - if (!faulty) - { - itm = eina_hash_iterator_data_new(f->map); - EINA_ITERATOR_FOREACH(itm, m) - { - if ((unsigned char *) addr < (((unsigned char *)m->map) + m->length) && - (((unsigned char *) addr) + page_size) >= (unsigned char *) m->map) - { - m->faulty = EINA_TRUE; - faulty = EINA_TRUE; - break; - } - } - eina_iterator_free(itm); - } - - eina_lock_release(&f->lock); - - if (faulty) break; - } - eina_iterator_free(itf); - - eina_lock_release(&_eina_file_lock_cache); -} - -/*============================================================================* - * 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) -{ -#ifdef HAVE_DIRENT_H - 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; -#else - (void) dir; - return NULL; -#endif -} - -EAPI Eina_Iterator * -eina_file_direct_ls(const char *dir) -{ -#ifdef HAVE_DIRENT_H - Eina_File_Direct_Iterator *it; - size_t length; - - 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; -#else - (void) dir; - return NULL; -#endif -} - -EAPI Eina_Iterator * -eina_file_stat_ls(const char *dir) -{ -#ifdef HAVE_DIRENT_H - Eina_File_Direct_Iterator *it; - size_t length; - - 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; -#else - (void) dir; - return NULL; -#endif -} - -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; -#ifdef HAVE_EXECVP - int flags; -#endif - - EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL); - - filename = eina_file_path_sanitize(path); - if (!filename) return NULL; - - if (shared) -#ifdef HAVE_SHM_OPEN - 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; - } - - memset(n, 0, sizeof(Eina_File)); - 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->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->fd = fd; - n->shared = shared; - 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; -} - -typedef struct _Eina_Lines_Iterator Eina_Lines_Iterator; -struct _Eina_Lines_Iterator -{ - Eina_Iterator iterator; - - Eina_File *fp; - const char *map; - const char *end; - - int boundary; - - Eina_File_Line current; -}; - -/* search '\r' and '\n' by preserving cache locality and page locality - in doing a search inside 4K boundary. - */ -static inline const char * -_eina_fine_eol(const char *start, int boundary, const char *end) -{ - const char *cr; - const char *lf; - unsigned long long chunk; - - while (start < end) - { - chunk = start + boundary < end ? boundary : end - start; - cr = memchr(start, '\r', chunk); - lf = memchr(start, '\n', chunk); - if (cr) - { - if (lf && lf < cr) - return lf + 1; - return cr + 1; - } - else if (lf) - return lf + 1; - - start += chunk; - boundary = 4096; - } - - return end; -} - -static Eina_Bool -_eina_file_map_lines_iterator_next(Eina_Lines_Iterator *it, void **data) -{ - const char *eol; - unsigned char match; - - if (it->current.end >= it->end) - return EINA_FALSE; - - match = *it->current.end; - while ((*it->current.end == '\n' || *it->current.end == '\r') - && it->current.end < it->end) - { - if (match == *it->current.end) - it->current.index++; - it->current.end++; - } - it->current.index++; - - if (it->current.end == it->end) - return EINA_FALSE; - - eol = _eina_fine_eol(it->current.end, - it->boundary, - it->end); - it->boundary = (uintptr_t) eol & 0x3FF; - if (it->boundary == 0) it->boundary = 4096; - - it->current.start = it->current.end; - - it->current.end = eol; - it->current.length = eol - it->current.start - 1; - - *data = &it->current; - return EINA_TRUE; -} - -static Eina_File * -_eina_file_map_lines_iterator_container(Eina_Lines_Iterator *it) -{ - return it->fp; -} - -static void -_eina_file_map_lines_iterator_free(Eina_Lines_Iterator *it) -{ - eina_file_map_free(it->fp, (void*) it->map); - eina_file_close(it->fp); - - EINA_MAGIC_SET(&it->iterator, 0); - free(it); -} - -EAPI Eina_Iterator * -eina_file_map_lines(Eina_File *file) -{ - Eina_Lines_Iterator *it; - - EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); - - if (file->length == 0) return NULL; - - it = calloc(1, sizeof (Eina_Lines_Iterator)); - if (!it) return NULL; - - EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); - - it->map = eina_file_map_all(file, EINA_FILE_SEQUENTIAL); - if (!it->map) - { - free(it); - return NULL; - } - - eina_lock_take(&file->lock); - file->refcount++; - eina_lock_release(&file->lock); - - it->fp = file; - it->boundary = 4096; - it->current.start = it->map; - it->current.end = it->current.start; - it->current.index = 0; - it->current.length = 0; - it->end = it->map + it->fp->length; - - it->iterator.version = EINA_ITERATOR_VERSION; - it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_map_lines_iterator_next); - it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_map_lines_iterator_container); - it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_map_lines_iterator_free); - - return &it->iterator; -} - -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) goto on_exit; - - em->refcount--; - - if (em->refcount > 0) goto on_exit; - - key[0] = em->offset; - key[1] = em->length; - - eina_hash_del(file->rmap, &map, em); - eina_hash_del(file->map, &key, em); - } - - on_exit: - eina_lock_release(&file->lock); -} - -EAPI Eina_Bool -eina_file_map_faulted(Eina_File *file, void *map) -{ - Eina_File_Map *em; - Eina_Bool r = EINA_FALSE; - - EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE); - - eina_lock_take(&file->lock); - - if (file->global_map == map) - { - r = file->global_faulty; - } - else - { - em = eina_hash_find(file->rmap, &map); - if (em) r = em->faulty; - } - - eina_lock_release(&file->lock); - - return r; -} - -EAPI Eina_Iterator * -eina_file_xattr_get(Eina_File *file) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); - - return eina_xattr_fd_ls(file->fd); -} - -EAPI Eina_Iterator * -eina_file_xattr_value_get(Eina_File *file) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); - - return eina_xattr_value_fd_ls(file->fd); -} - -EAPI int -eina_file_statat(void *container, Eina_File_Direct_Info *info, Eina_Stat *st) -{ - struct stat buf; -#if defined(HAVE_FSTATAT) && defined(HAVE_DIRFD) - int fd; -#endif - - EINA_SAFETY_ON_NULL_RETURN_VAL(info, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(st, -1); - -#if defined(HAVE_FSTATAT) && defined(HAVE_DIRFD) - fd = dirfd((DIR*) container); - if (fstatat(fd, info->path + info->name_start, &buf, 0)) -#else - (void)container; - if (stat(info->path, &buf)) -#endif - { - if (info->type != EINA_FILE_LNK) - info->type = EINA_FILE_UNKNOWN; - return -1; - } - - if (info->type == EINA_FILE_UNKNOWN) - { - if (S_ISREG(buf.st_mode)) - info->type = EINA_FILE_REG; - else if (S_ISDIR(buf.st_mode)) - info->type = EINA_FILE_DIR; - else if (S_ISCHR(buf.st_mode)) - info->type = EINA_FILE_CHR; - else if (S_ISBLK(buf.st_mode)) - info->type = EINA_FILE_BLK; - else if (S_ISFIFO(buf.st_mode)) - info->type = EINA_FILE_FIFO; - else if (S_ISLNK(buf.st_mode)) - info->type = EINA_FILE_LNK; - else if (S_ISSOCK(buf.st_mode)) - info->type = EINA_FILE_SOCK; - else - info->type = EINA_FILE_UNKNOWN; - } - - st->dev = buf.st_dev; - st->ino = buf.st_ino; - st->mode = buf.st_mode; - st->nlink = buf.st_nlink; - st->uid = buf.st_uid; - st->gid = buf.st_gid; - st->rdev = buf.st_rdev; - st->size = buf.st_size; - st->blksize = buf.st_blksize; - st->blocks = buf.st_blocks; - st->atime = buf.st_atime; - st->mtime = buf.st_mtime; - st->ctime = buf.st_ctime; -#ifdef _STAT_VER_LINUX -# if (defined __USE_MISC && defined st_mtime) - st->atimensec = buf.st_atim.tv_nsec; - st->mtimensec = buf.st_mtim.tv_nsec; - st->ctimensec = buf.st_ctim.tv_nsec; -# else - st->atimensec = buf.st_atimensec; - st->mtimensec = buf.st_mtimensec; - st->ctimensec = buf.st_ctimensec; -# endif -#else - st->atimensec = 0; - st->mtimensec = 0; - st->ctimensec = 0; -#endif - return 0; -} diff --git a/src/lib/eina_file_win32.c b/src/lib/eina_file_win32.c deleted file mode 100644 index 61bd0d1..0000000 --- a/src/lib/eina_file_win32.c +++ /dev/null @@ -1,1387 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_ALLOCA_H -# include <alloca.h> -#elif defined __GNUC__ -# define alloca __builtin_alloca -#elif defined _AIX -# define alloca __alloca -#elif defined _MSC_VER -# include <malloc.h> -# define alloca _alloca -#else -# include <stddef.h> -# ifdef __cplusplus -extern "C" -# endif -void *alloca (size_t); -#endif - -#include <sys/types.h> -#include <sys/stat.h> - -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#undef WIN32_LEAN_AND_MEAN - -#include <Evil.h> - -#include "eina_config.h" -#include "eina_private.h" - -/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ -#include "eina_safety_checks.h" -#include "eina_file.h" -#include "eina_stringshare.h" -#include "eina_hash.h" -#include "eina_list.h" -#include "eina_lock.h" -#include "eina_log.h" - -/*============================================================================* - * Local * - *============================================================================*/ - -/** - * @cond LOCAL - */ - -#ifndef EINA_LOG_COLOR_DEFAULT -#define EINA_LOG_COLOR_DEFAULT EINA_COLOR_CYAN -#endif - -#ifdef ERR -#undef ERR -#endif -#define ERR(...) EINA_LOG_DOM_ERR(_eina_file_log_dom, __VA_ARGS__) - -#ifdef WRN -#undef WRN -#endif -#define WRN(...) EINA_LOG_DOM_WARN(_eina_file_log_dom, __VA_ARGS__) - -#ifdef DBG -#undef DBG -#endif -#define DBG(...) EINA_LOG_DOM_DBG(_eina_file_log_dom, __VA_ARGS__) - -#ifdef MAP_FAILED -# undef MAP_FAILED -#endif -#define MAP_FAILED ((void *)-1) - -typedef struct _Eina_File_Iterator Eina_File_Iterator; -typedef struct _Eina_Lines_Iterator Eina_Lines_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_Lines_Iterator -{ - Eina_Iterator iterator; - - Eina_File *fp; - const char *map; - const char *end; - - int boundary; - - Eina_File_Line current; -}; - -struct _Eina_File_Direct_Iterator -{ - Eina_Iterator iterator; - - WIN32_FIND_DATA data; - HANDLE handle; - size_t length; - Eina_Bool is_last : 1; - - Eina_File_Direct_Info info; - - char dir[1]; -}; - -struct _Eina_File -{ - const char *filename; - - Eina_Hash *map; - Eina_Hash *rmap; - void *global_map; - - Eina_Lock lock; - - ULONGLONG length; - ULONGLONG mtime; - - int refcount; - int global_refcount; - - HANDLE handle; - HANDLE fm; - - Eina_Bool shared : 1; - Eina_Bool delete_me : 1; -}; - -struct _Eina_File_Map -{ - void *map; - - unsigned long int offset; - unsigned long int length; - - int refcount; -}; - -static Eina_Hash *_eina_file_cache = NULL; -static Eina_Lock _eina_file_lock_cache; - -static int _eina_file_log_dom = -1; - -static 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); - - 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_HIDDEN | - FILE_ATTRIBUTE_NORMAL | - FILE_ATTRIBUTE_SPARSE_FILE | - FILE_ATTRIBUTE_TEMPORARY)) - it->info.type = EINA_FILE_REG; - else - it->info.type = EINA_FILE_UNKNOWN; - - *data = &it->info; - -#ifdef UNICODE - free(cname); -#endif - - free(old_name); - - if (is_last) - res = EINA_FALSE; - - return res; -} - -static HANDLE -_eina_file_win32_direct_ls_iterator_container(Eina_File_Direct_Iterator *it) -{ - return it->handle; -} - -static void -_eina_file_win32_direct_ls_iterator_free(Eina_File_Direct_Iterator *it) -{ - if (it->handle != INVALID_HANDLE_VALUE) - FindClose(it->handle); - - EINA_MAGIC_SET(&it->iterator, 0); - free(it); -} - -static void -_eina_file_real_close(Eina_File *file) -{ - eina_hash_free(file->rmap); - eina_hash_free(file->map); - - if (file->global_map != MAP_FAILED) - UnmapViewOfFile(file->global_map); - - CloseHandle(file->fm); - CloseHandle(file->handle); - - free(file); -} - -static void -_eina_file_map_close(Eina_File_Map *map) -{ - if (map->map != MAP_FAILED) - UnmapViewOfFile(map->map); - free(map); -} - -static unsigned int -_eina_file_map_key_length(const void *key __UNUSED__) -{ - return sizeof (unsigned long int) * 2; -} - -static int -_eina_file_map_key_cmp(const unsigned long int *key1, int key1_length __UNUSED__, - const unsigned long int *key2, int key2_length __UNUSED__) -{ - if (key1[0] - key2[0] == 0) return key1[1] - key2[1]; - return key1[0] - key2[0]; -} - -static int -_eina_file_map_key_hash(const unsigned long int *key, int key_length __UNUSED__) -{ - return eina_hash_int64(&key[0], sizeof (unsigned long int)) - ^ eina_hash_int64(&key[1], sizeof (unsigned long int)); -} - -static char * -_eina_file_win32_escape(const char *path, size_t *length) -{ - char *result; - char *p; - char *q; - size_t len; - - result = strdup(path ? path : ""); - if (!result) - return NULL; - - p = result; - while (*p) - { - if (*p == '\\') *p = '/'; - p++; - } - p = result; - q = result; - - 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; -} - -/* search '\r' and '\n' by preserving cache locality and page locality - in doing a search inside 4K boundary. - */ -static inline const char * -_eina_fine_eol(const char *start, int boundary, const char *end) -{ - const char *cr; - const char *lf; - unsigned long long chunk; - - while (start < end) - { - chunk = start + boundary < end ? boundary : end - start; - cr = memchr(start, '\r', chunk); - lf = memchr(start, '\n', chunk); - if (cr) - { - if (lf && lf < cr) - return lf + 1; - return cr + 1; - } - else if (lf) - return lf + 1; - - start += chunk; - boundary = 4096; - } - - return end; -} - -static Eina_Bool -_eina_file_map_lines_iterator_next(Eina_Lines_Iterator *it, void **data) -{ - const char *eol; - unsigned char match; - - if (it->current.end >= it->end) - return EINA_FALSE; - - match = *it->current.end; - while ((*it->current.end == '\n' || *it->current.end == '\r') - && it->current.end < it->end) - { - if (match == *it->current.end) - it->current.index++; - it->current.end++; - } - it->current.index++; - - if (it->current.end == it->end) - return EINA_FALSE; - - eol = _eina_fine_eol(it->current.end, - it->boundary, - it->end); - it->boundary = (uintptr_t) eol & 0x3FF; - if (it->boundary == 0) it->boundary = 4096; - - it->current.start = it->current.end; - - it->current.end = eol; - it->current.length = eol - it->current.start - 1; - - *data = &it->current; - return EINA_TRUE; -} - -static Eina_File * -_eina_file_map_lines_iterator_container(Eina_Lines_Iterator *it) -{ - return it->fp; -} - -static void -_eina_file_map_lines_iterator_free(Eina_Lines_Iterator *it) -{ - eina_file_map_free(it->fp, (void*) it->map); - eina_file_close(it->fp); - - EINA_MAGIC_SET(&it->iterator, 0); - free(it); -} - - -/** - * @endcond - */ - -/*============================================================================* - * Global * - *============================================================================*/ - -Eina_Bool -eina_file_init(void) -{ - _eina_file_log_dom = eina_log_domain_register("eina_file", - EINA_LOG_COLOR_DEFAULT); - if (_eina_file_log_dom < 0) - { - EINA_LOG_ERR("Could not register log domain: eina_file"); - return EINA_FALSE; - } - - _eina_file_cache = eina_hash_string_djb2_new(NULL); - if (!_eina_file_cache) - { - ERR("Could not create cache."); - eina_log_domain_unregister(_eina_file_log_dom); - _eina_file_log_dom = -1; - return EINA_FALSE; - } - - eina_lock_new(&_eina_file_lock_cache); - - return EINA_TRUE; -} - -Eina_Bool -eina_file_shutdown(void) -{ - if (eina_hash_population(_eina_file_cache) > 0) - { - Eina_Iterator *it; - const char *key; - - it = eina_hash_iterator_key_new(_eina_file_cache); - EINA_ITERATOR_FOREACH(it, key) - ERR("File [%s] still open !", key); - eina_iterator_free(it); - } - - eina_hash_free(_eina_file_cache); - - eina_lock_free(&_eina_file_lock_cache); - - eina_log_domain_unregister(_eina_file_log_dom); - _eina_file_log_dom = -1; - return EINA_TRUE; -} - -/*============================================================================* - * API * - *============================================================================*/ - - -EAPI char * -eina_file_path_sanitize(const char *path) -{ - char *result = NULL; - size_t len; - - if (!path) return NULL; - - len = strlen(path); - - if (!evil_path_is_absolute(path)) - { - DWORD l; - - l = GetCurrentDirectory(0, NULL); - if (l > 0) - { - char *cwd; - char *tmp; - - cwd = alloca(sizeof(char) * (l + 1)); - GetCurrentDirectory(l + 1, cwd); - len += l + 2; - tmp = alloca(sizeof (char) * len); - snprintf(tmp, len, "%s\\%s", cwd, path); - tmp[len - 1] = '\0'; - result = tmp; - } - } - - return _eina_file_win32_escape(result ? result : path, &len); -} - -EAPI Eina_Bool -eina_file_dir_list(const char *dir, - Eina_Bool recursive, - Eina_File_Dir_List_Cb cb, - void *data) -{ - WIN32_FIND_DATA file; - HANDLE h; - char *new_dir; - - EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(dir, EINA_FALSE); - EINA_SAFETY_ON_TRUE_RETURN_VAL(dir[0] == '\0', EINA_FALSE); - - if (!_eina_file_win32_is_dir(dir)) - return EINA_FALSE; - - new_dir = _eina_file_win32_dir_new(dir); - if (!new_dir) - return EINA_FALSE; - - h = _eina_file_win32_first_file(new_dir, &file); - - if (h == INVALID_HANDLE_VALUE) - return EINA_FALSE; - - do - { - char *filename; - -# ifdef UNICODE - filename = evil_wchar_to_char(file.cFileName); -# else - filename = file.cFileName; -# endif /* ! UNICODE */ - if (!strcmp(filename, ".") || !strcmp(filename, "..")) - continue; - - cb(filename, dir, data); - - if (recursive == EINA_TRUE) - { - char *path; - - path = alloca(strlen(dir) + strlen(filename) + 2); - strcpy(path, dir); - strcat(path, "/"); - strcat(path, filename); - - if (!(file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) - continue; - - eina_file_dir_list(path, recursive, cb, data); - } - -# ifdef UNICODE - free(filename); -# endif /* UNICODE */ - - } while (FindNextFile(h, &file)); - FindClose(h); - - return EINA_TRUE; -} - -EAPI Eina_Array * -eina_file_split(char *path) -{ - Eina_Array *ea; - char *current; - size_t length; - - EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL); - - ea = eina_array_new(16); - - if (!ea) - return NULL; - - current = path; - while (*current) - { - if ((*current == '\\') || (*current == '/')) - { - if (((*current == '\\') && (current[1] == '\\')) || - ((*current == '/') && (current[1] == '/'))) - { - *current = '\0'; - goto next_char; - } - - length = current - path; - if (length <= 0) - goto next_char; - - eina_array_push(ea, path); - *current = '\0'; - path = current + 1; - } - next_char: - current++; - } - - if (*path != '\0') - eina_array_push(ea, path); - - return ea; -} - -EAPI Eina_Iterator * -eina_file_ls(const char *dir) -{ - Eina_File_Iterator *it; - char *new_dir; - size_t length; - - EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL); - - if (!dir || !*dir) - return NULL; - - if (!_eina_file_win32_is_dir(dir)) - return NULL; - - length = strlen(dir); - - it = calloc(1, sizeof (Eina_File_Iterator) + length); - if (!it) - return NULL; - - EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); - - new_dir = _eina_file_win32_dir_new(dir); - if (!new_dir) - goto free_it; - - it->handle = _eina_file_win32_first_file(new_dir, &it->data); - free(new_dir); - if (it->handle == INVALID_HANDLE_VALUE) - goto free_it; - - memcpy(it->dir, dir, length + 1); - if ((dir[length - 1] != '\\') && (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_win32_ls_iterator_next); - it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_win32_ls_iterator_container); - it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_win32_ls_iterator_free); - - return &it->iterator; - - free_it: - free(it); - - return NULL; -} - -EAPI Eina_Iterator * -eina_file_direct_ls(const char *dir) -{ - Eina_File_Direct_Iterator *it; - char *new_dir; - size_t length; - - EINA_SAFETY_ON_NULL_RETURN_VAL(dir, NULL); - - if (!dir || !*dir) - return NULL; - - length = strlen(dir); - - if (length + 12 + 2 >= MAX_PATH) - return NULL; - - it = calloc(1, sizeof(Eina_File_Direct_Iterator) + length); - if (!it) - return NULL; - - EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); - - new_dir = _eina_file_win32_dir_new(dir); - if (!new_dir) - goto free_it; - - it->handle = _eina_file_win32_first_file(new_dir, &it->data); - free(new_dir); - if (it->handle == INVALID_HANDLE_VALUE) - goto free_it; - - memcpy(it->dir, dir, length + 1); - it->length = length; - - memcpy(it->info.path, dir, length); - if ((dir[length - 1] == '\\') || (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_win32_direct_ls_iterator_next); - it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_win32_direct_ls_iterator_container); - it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_win32_direct_ls_iterator_free); - - return &it->iterator; - - free_it: - free(it); - - return NULL; -} - -EAPI Eina_Iterator * -eina_file_stat_ls(const char *dir) -{ - return eina_file_direct_ls(dir); -} - -EAPI Eina_File * -eina_file_open(const char *path, Eina_Bool shared) -{ - Eina_File *file; - Eina_File *n; - char *filename; - HANDLE handle; - HANDLE fm; - WIN32_FILE_ATTRIBUTE_DATA fad; - ULARGE_INTEGER length; - ULARGE_INTEGER mtime; - - EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL); - - filename = eina_file_path_sanitize(path); - if (!filename) return NULL; - - /* FIXME: how to emulate shm_open ? Just OpenFileMapping ? */ -#if 0 - if (shared) - handle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, - NULL); - else -#endif - handle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, - NULL); - - if (handle == INVALID_HANDLE_VALUE) - return NULL; - - fm = CreateFileMapping(handle, NULL, PAGE_READONLY, 0, 0, NULL); - if (!fm) - goto close_handle; - - if (!GetFileAttributesEx(filename, GetFileExInfoStandard, &fad)) - goto close_fm; - - length.u.LowPart = fad.nFileSizeLow; - length.u.HighPart = fad.nFileSizeHigh; - mtime.u.LowPart = fad.ftLastWriteTime.dwLowDateTime; - mtime.u.HighPart = fad.ftLastWriteTime.dwHighDateTime; - - eina_lock_take(&_eina_file_lock_cache); - - file = eina_hash_find(_eina_file_cache, filename); - if (file && - (file->mtime != mtime.QuadPart || file->length != length.QuadPart)) - { - file->delete_me = EINA_TRUE; - eina_hash_del(_eina_file_cache, file->filename, file); - _eina_file_real_close(file); - file = NULL; - } - - if (!file) - { - n = malloc(sizeof(Eina_File) + strlen(filename) + 1); - if (!n) - { - eina_lock_release(&_eina_file_lock_cache); - goto close_fm; - } - - memset(n, 0, sizeof(Eina_File)); - 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->length = length.QuadPart; - n->mtime = mtime.QuadPart; - n->handle = handle; - n->fm = fm; - n->shared = shared; - eina_lock_new(&n->lock); - eina_hash_direct_add(_eina_file_cache, n->filename, n); - } - else - { - CloseHandle(fm); - CloseHandle(handle); - - n = file; - } - eina_lock_take(&n->lock); - n->refcount++; - eina_lock_release(&n->lock); - - eina_lock_release(&_eina_file_lock_cache); - - free(filename); - - return n; - - close_fm: - CloseHandle(fm); - close_handle: - CloseHandle(handle); - - return NULL; -} - -EAPI void -eina_file_close(Eina_File *file) -{ - EINA_SAFETY_ON_NULL_RETURN(file); - - eina_lock_take(&file->lock); - file->refcount--; - eina_lock_release(&file->lock); - - if (file->refcount != 0) return ; - eina_lock_take(&_eina_file_lock_cache); - - eina_hash_del(_eina_file_cache, file->filename, file); - _eina_file_real_close(file); - - eina_lock_release(&_eina_file_lock_cache); -} - -EAPI size_t -eina_file_size_get(Eina_File *file) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0); - return file->length; -} - -EAPI time_t -eina_file_mtime_get(Eina_File *file) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(file, 0); - return file->mtime; -} - -EAPI const char * -eina_file_filename_get(Eina_File *file) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); - return file->filename; -} - -EAPI Eina_Iterator *eina_file_xattr_get(Eina_File *file __UNUSED__) -{ - return NULL; -} - -EAPI Eina_Iterator *eina_file_xattr_value_get(Eina_File *file __UNUSED__) -{ - return NULL; -} - -EAPI void * -eina_file_map_all(Eina_File *file, Eina_File_Populate rule __UNUSED__) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); - - eina_lock_take(&file->lock); - if (file->global_map == MAP_FAILED) - { - void *data; - - data = MapViewOfFile(file->fm, FILE_MAP_READ, - 0, 0, file->length); - if (!data) - file->global_map = MAP_FAILED; - else - file->global_map = data; - } - - if (file->global_map != MAP_FAILED) - { - file->global_refcount++; - return file->global_map; - } - - eina_lock_release(&file->lock); - return NULL; -} - -EAPI Eina_Iterator * -eina_file_map_lines(Eina_File *file) -{ - Eina_Lines_Iterator *it; - - EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); - - if (file->length == 0) return NULL; - - it = calloc(1, sizeof (Eina_Lines_Iterator)); - if (!it) return NULL; - - EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); - - it->map = eina_file_map_all(file, EINA_FILE_SEQUENTIAL); - if (!it->map) - { - free(it); - return NULL; - } - - eina_lock_take(&file->lock); - file->refcount++; - eina_lock_release(&file->lock); - - it->fp = file; - it->boundary = 4096; - it->current.start = it->map; - it->current.end = it->current.start; - it->current.index = 0; - it->current.length = 0; - it->end = it->map + it->fp->length; - - it->iterator.version = EINA_ITERATOR_VERSION; - it->iterator.next = FUNC_ITERATOR_NEXT(_eina_file_map_lines_iterator_next); - it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_file_map_lines_iterator_container); - it->iterator.free = FUNC_ITERATOR_FREE(_eina_file_map_lines_iterator_free); - - return &it->iterator; -} - -EAPI void * -eina_file_map_new(Eina_File *file, Eina_File_Populate rule, - unsigned long int offset, unsigned long int length) -{ - Eina_File_Map *map; - unsigned long int key[2]; - - EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); - - if (offset > file->length) - return NULL; - if (offset + length > file->length) - return NULL; - - if (offset == 0 && length == file->length) - return eina_file_map_all(file, rule); - - key[0] = offset; - key[1] = length; - - eina_lock_take(&file->lock); - - map = eina_hash_find(file->map, &key); - if (!map) - { - void *data; - - map = malloc(sizeof (Eina_File_Map)); - if (!map) - { - eina_lock_release(&file->lock); - return NULL; - } - - data = MapViewOfFile(file->fm, FILE_MAP_READ, - offset & 0xffff0000, - offset & 0x0000ffff, - length); - if (!data) - map->map = MAP_FAILED; - else - map->map = data; - - map->offset = offset; - map->length = length; - map->refcount = 0; - - if (map->map == MAP_FAILED) - { - free(map); - eina_lock_release(&file->lock); - return NULL; - } - - eina_hash_add(file->map, &key, map); - eina_hash_direct_add(file->rmap, map->map, map); - } - - map->refcount++; - - eina_lock_release(&file->lock); - - return map->map; -} - -EAPI void -eina_file_map_free(Eina_File *file, void *map) -{ - EINA_SAFETY_ON_NULL_RETURN(file); - - eina_lock_take(&file->lock); - - if (file->global_map == map) - { - file->global_refcount--; - - if (file->global_refcount > 0) goto on_exit; - - UnmapViewOfFile(file->global_map); - file->global_map = MAP_FAILED; - } - else - { - Eina_File_Map *em; - unsigned long int key[2]; - - em = eina_hash_find(file->rmap, &map); - if (!em) goto on_exit; - - em->refcount--; - - if (em->refcount > 0) goto on_exit; - - key[0] = em->offset; - key[1] = em->length; - - eina_hash_del(file->rmap, &map, em); - eina_hash_del(file->map, &key, em); - } - - on_exit: - eina_lock_release(&file->lock); -} - -EAPI Eina_Bool -eina_file_map_faulted(Eina_File *file, void *map) -{ - /* - * FIXME: - * vc++ : http://msdn.microsoft.com/en-us/library/windows/desktop/aa366801%28v=vs.85%29.aspx - * - * mingw-w64 : - * - 32 bits : there is a way to implement __try/__except/__final in C. - * see excpt.h header for 32-bits - * - 64 bits : some inline assembly required for it. See as example our - * startup-code in WinMainCRTStartup() in crtexe.c : -{ - int ret = 255; -#ifdef __SEH__ - asm ("\t.l_startw:\n" - "\t.seh_handler __C_specific_handler, @except\n" - "\t.seh_handlerdata\n" - "\t.long 1\n" - "\t.rva .l_startw, .l_endw, _gnu_exception_handler ,.l_endw\n" - "\t.text" - ); -#endif - mingw_app_type = 1; - __security_init_cookie (); - ret = __tmainCRTStartup (); -#ifdef __SEH__ - asm ("\tnop\n" - "\t.l_endw: nop\n"); -#endif - return ret; -} - */ - return EINA_FALSE; -} - -EAPI int -eina_file_statat(void *container __UNUSED__, Eina_File_Direct_Info *info, Eina_Stat *st) -{ - struct __stat64 buf; - - EINA_SAFETY_ON_NULL_RETURN_VAL(info, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(st, -1); - - if (stat64(info->path, &buf)) - { - if (info->type != EINA_FILE_LNK) - info->type = EINA_FILE_UNKNOWN; - return -1; - } - - if (info->type == EINA_FILE_UNKNOWN) - { - if (S_ISREG(buf.st_mode)) - info->type = EINA_FILE_REG; - else if (S_ISDIR(buf.st_mode)) - info->type = EINA_FILE_DIR; - else - info->type = EINA_FILE_UNKNOWN; - } - - st->dev = buf.st_dev; - st->ino = buf.st_ino; - st->mode = buf.st_mode; - st->nlink = buf.st_nlink; - st->uid = buf.st_uid; - st->gid = buf.st_gid; - st->rdev = buf.st_rdev; - st->size = buf.st_size; - st->blksize = 0; - st->blocks = 0; - st->atime = buf.st_atime; - st->mtime = buf.st_mtime; - st->ctime = buf.st_ctime; - st->atimensec = 0; - st->mtimensec = 0; - st->ctimensec = 0; - - return 0; -} diff --git a/src/lib/eina_fp.c b/src/lib/eina_fp.c deleted file mode 100644 index ea1775c..0000000 --- a/src/lib/eina_fp.c +++ /dev/null @@ -1,486 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdio.h> -#include <math.h> - -#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 - 1) * 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 (F32P32_PI2 < remainder_2PI && remainder_2PI < F32P32_3PI2) - result *= -1; - - return result; -} - -EAPI Eina_F32p32 -eina_f32p32_sin(Eina_F32p32 a) -{ - Eina_F32p32 F32P32_PI2; - - F32P32_PI2 = EINA_F32P32_PI >> 1; - - /* We only have a table for cosinus, but sin(a) = cos(pi / 2 - a) */ - a = eina_f32p32_sub(F32P32_PI2, a); - - return eina_f32p32_cos(a); -} - diff --git a/src/lib/eina_hamster.c b/src/lib/eina_hamster.c deleted file mode 100644 index cebc10b..0000000 --- a/src/lib/eina_hamster.c +++ /dev/null @@ -1,113 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdio.h> -#include <string.h> - -#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/src/lib/eina_hash.c b/src/lib/eina_hash.c deleted file mode 100644 index 821d225..0000000 --- a/src/lib/eina_hash.c +++ /dev/null @@ -1,1379 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#ifdef HAVE_STDINT_H -# include <stdint.h> -#endif - -#ifdef _MSC_VER -# include <Evil.h> -#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_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; - - 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; - - if (!hash) return; - - EINA_MAGIC_CHECK_HASH(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; - - if (!hash) return; - - EINA_MAGIC_CHECK_HASH(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_Free_Cb cb = hash->data_free_cb; - hash->data_free_cb = NULL; - _eina_hash_del_by_hash_el(hash, hash_element, hash_head, key_hash); - hash->data_free_cb = cb; - } - - 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/src/lib/eina_inarray.c b/src/lib/eina_inarray.c deleted file mode 100644 index 1a12757..0000000 --- a/src/lib/eina_inarray.c +++ /dev/null @@ -1,795 +0,0 @@ -/* EINA - EFL data type library - * Copyright (C) 2012 - ProFUSION embedded systems - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; - * if not, see <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> -#include <string.h> - -#include "eina_config.h" -#include "eina_private.h" -#include "eina_error.h" -#include "eina_log.h" - -/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ -#include "eina_safety_checks.h" -#include "eina_inarray.h" - -/*============================================================================* -* Local * -*============================================================================*/ - -/** - * @cond LOCAL - */ - -static const char EINA_MAGIC_INARRAY_STR[] = "Eina Inline Array"; -static const char EINA_MAGIC_INARRAY_ITERATOR_STR[] = "Eina Inline Array Iterator"; -static const char EINA_MAGIC_INARRAY_ACCESSOR_STR[] = "Eina Inline Array Accessor"; - -typedef struct _Eina_Iterator_Inarray Eina_Iterator_Inarray; -typedef struct _Eina_Accessor_Inarray Eina_Accessor_Inarray; - -struct _Eina_Iterator_Inarray -{ - Eina_Iterator iterator; - const Eina_Inarray *array; - unsigned int pos; - EINA_MAGIC -}; - -struct _Eina_Accessor_Inarray -{ - Eina_Accessor accessor; - const Eina_Inarray *array; - EINA_MAGIC -}; - -static int _eina_inarray_log_dom = -1; - -#ifdef ERR -#undef ERR -#endif -#define ERR(...) EINA_LOG_DOM_ERR(_eina_inarray_log_dom, __VA_ARGS__) - -#ifdef DBG -#undef DBG -#endif -#define DBG(...) EINA_LOG_DOM_DBG(_eina_inarray_log_dom, __VA_ARGS__) - -#define EINA_MAGIC_CHECK_INARRAY(d, ...) \ - do \ - { \ - if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_INARRAY)) \ - { \ - EINA_MAGIC_FAIL(d, EINA_MAGIC_INARRAY); \ - return __VA_ARGS__; \ - } \ - eina_error_set(0); \ - } \ - while(0) - -#define EINA_MAGIC_CHECK_INARRAY_ITERATOR(d, ...) \ - do \ - { \ - if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_INARRAY_ITERATOR)) \ - { \ - EINA_MAGIC_FAIL(d, EINA_MAGIC_INARRAY_ITERATOR); \ - return __VA_ARGS__; \ - } \ - eina_error_set(0); \ - } \ - while(0) - -#define EINA_MAGIC_CHECK_INARRAY_ACCESSOR(d, ...) \ - do \ - { \ - if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_INARRAY_ACCESSOR)) \ - { \ - EINA_MAGIC_FAIL(d, EINA_MAGIC_INARRAY_ACCESSOR); \ - return __VA_ARGS__; \ - } \ - eina_error_set(0); \ - } \ - while(0) - -static void -_eina_inarray_setup(Eina_Inarray *array, unsigned int member_size, unsigned int step) -{ - EINA_MAGIC_SET(array, EINA_MAGIC_INARRAY); - array->version = EINA_ARRAY_VERSION; - array->member_size = member_size; - array->len = 0; - array->max = 0; - array->step = (step > 0) ? step : 32; - array->members = NULL; -} - -static Eina_Bool -_eina_inarray_resize(Eina_Inarray *array, unsigned int new_size) -{ - unsigned int new_max; - void *tmp; - - if (new_size < array->max) /* don't change this behaviour as eina_inarray_pop rely on it */ - return EINA_TRUE; - - if (new_size % array->step == 0) - new_max = new_size; - else - new_max = ((new_size / array->step) + 1) * array->step; - - tmp = realloc(array->members, new_max * array->member_size); - if ((!tmp) && (new_max > 0)) - { - eina_error_set(EINA_ERROR_OUT_OF_MEMORY); - return EINA_FALSE; - } - - array->members = tmp; - array->max = new_max; - return EINA_TRUE; -} - -static inline void * -_eina_inarray_get(const Eina_Inarray *array, unsigned int position) -{ - unsigned int offset = position * array->member_size; - return (unsigned char *)array->members + offset; -} - -static int -_eina_inarray_search(const Eina_Inarray *array, const void *data, Eina_Compare_Cb compare) -{ - const unsigned char *start, *found; - start = array->members; - found = bsearch(data, start, array->len, array->member_size, compare); - if (!found) - return -1; - return (found - start) / array->member_size; -} - -static unsigned int -_eina_inarray_search_sorted_near(const Eina_Inarray *array, const void *data, Eina_Compare_Cb compare, int *cmp) -{ - unsigned int start, last, middle; - - if (array->len == 0) - { - *cmp = -1; - return 0; - } - else if (array->len == 1) - { - *cmp = compare(data, array->members); - return 0; - } - - start = 0; - last = array->len - 1; /* inclusive */ - do - { - void *p; - middle = start + (last - start) / 2; /* avoid overflow */ - p = _eina_inarray_get(array, middle); - *cmp = compare(data, p); - if (*cmp == 0) - return middle; - else if (*cmp > 0) - start = middle + 1; - else if (middle > 0) - last = middle - 1; - else - break; - } - while (start <= last); - return middle; -} - - -static Eina_Bool -_eina_inarray_iterator_next(Eina_Iterator_Inarray *it, void **data) -{ - EINA_MAGIC_CHECK_INARRAY_ITERATOR(it, EINA_FALSE); - - if (it->pos >= it->array->len) - return EINA_FALSE; - - *data = _eina_inarray_get(it->array, it->pos); - it->pos++; - - return EINA_TRUE; -} - -static Eina_Bool -_eina_inarray_iterator_prev(Eina_Iterator_Inarray *it, void **data) -{ - EINA_MAGIC_CHECK_INARRAY_ITERATOR(it, EINA_FALSE); - - if (it->pos == 0) - return EINA_FALSE; - - it->pos--; - *data = _eina_inarray_get(it->array, it->pos); - - return EINA_TRUE; -} - -static Eina_Inarray * -_eina_inarray_iterator_get_container(Eina_Iterator_Inarray *it) -{ - EINA_MAGIC_CHECK_INARRAY_ITERATOR(it, NULL); - return (Eina_Inarray *)it->array; -} - -static void -_eina_inarray_iterator_free(Eina_Iterator_Inarray *it) -{ - EINA_MAGIC_CHECK_INARRAY_ITERATOR(it); - MAGIC_FREE(it); -} - -static Eina_Bool -_eina_inarray_accessor_get_at(Eina_Accessor_Inarray *it, unsigned int pos, void **data) -{ - EINA_MAGIC_CHECK_INARRAY_ACCESSOR(it, EINA_FALSE); - - if (pos >= it->array->len) - return EINA_FALSE; - - *data = _eina_inarray_get(it->array, pos); - return EINA_TRUE; -} - -static Eina_Inarray * -_eina_inarray_accessor_get_container(Eina_Accessor_Inarray *it) -{ - EINA_MAGIC_CHECK_INARRAY_ACCESSOR(it, NULL); - return (Eina_Inarray *)it->array; -} - -static void -_eina_inarray_accessor_free(Eina_Accessor_Inarray *it) -{ - EINA_MAGIC_CHECK_INARRAY_ACCESSOR(it); - MAGIC_FREE(it); -} - -/** - * @endcond - */ - - -/*============================================================================* -* Global * -*============================================================================*/ - -/** - * @internal - * @brief Initialize the inline array module. - * - * @return #EINA_TRUE on success, #EINA_FALSE on failure. - * - * This function sets up the inline array module of Eina. It is called - * by eina_init(). - * - * @see eina_init() - */ -Eina_Bool -eina_inarray_init(void) -{ - _eina_inarray_log_dom = eina_log_domain_register("eina_inarray", - EINA_LOG_COLOR_DEFAULT); - if (_eina_inarray_log_dom < 0) - { - EINA_LOG_ERR("Could not register log domain: eina_inarray"); - return EINA_FALSE; - } - -#define EMS(n) eina_magic_string_static_set(n, n ## _STR) - EMS(EINA_MAGIC_INARRAY); - EMS(EINA_MAGIC_INARRAY_ITERATOR); - EMS(EINA_MAGIC_INARRAY_ACCESSOR); -#undef EMS - - return EINA_TRUE; -} - -/** - * @internal - * @brief Shut down the inline array module. - * - * @return #EINA_TRUE on success, #EINA_FALSE on failure. - * - * This function shuts down the inline array module set up by - * eina_inarray_init(). It is called by eina_shutdown(). - * - * @see eina_shutdown() - */ -Eina_Bool -eina_inarray_shutdown(void) -{ - eina_log_domain_unregister(_eina_inarray_log_dom); - _eina_inarray_log_dom = -1; - return EINA_TRUE; -} - -/*============================================================================* -* API * -*============================================================================*/ -EAPI Eina_Inarray * -eina_inarray_new(unsigned int member_size, unsigned int step) -{ - Eina_Inarray *ret; - - EINA_SAFETY_ON_TRUE_RETURN_VAL(member_size == 0, NULL); - - ret = malloc(sizeof(*ret)); - if (!ret) - { - eina_error_set(EINA_ERROR_OUT_OF_MEMORY); - return NULL; - } - eina_error_set(0); - _eina_inarray_setup(ret, member_size, step); - return ret; -} - -EAPI void -eina_inarray_free(Eina_Inarray *array) -{ - if (!array) - return; - - EINA_MAGIC_CHECK_INARRAY(array); - free(array->members); - free(array); -} - -EAPI void -eina_inarray_step_set(Eina_Inarray *array, - unsigned int sizeof_eina_inarray, - unsigned int member_size, - unsigned int step) -{ - EINA_SAFETY_ON_NULL_RETURN(array); - EINA_SAFETY_ON_TRUE_RETURN(member_size == 0); - - if (sizeof (Eina_Inarray) != sizeof_eina_inarray) - { - ERR("Unknow Eina_Inarray size ! Got %i, expected %i\n", - sizeof_eina_inarray, - (int) sizeof (Eina_Inarray)); - /* Force memory to zero to provide a small layer of security */ - memset(array, 0, sizeof_eina_inarray); - return ; - } - - _eina_inarray_setup(array, member_size, step); -} - -EAPI void -eina_inarray_flush(Eina_Inarray *array) -{ - EINA_MAGIC_CHECK_INARRAY(array); - free(array->members); - array->len = 0; - array->max = 0; - array->members = NULL; -} - -EAPI int -eina_inarray_push(Eina_Inarray *array, const void *data) -{ - void *p; - - EINA_MAGIC_CHECK_INARRAY(array, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1); - - if (!_eina_inarray_resize(array, array->len + 1)) - return -1; - - p = _eina_inarray_get(array, array->len); - memcpy(p, data, array->member_size); - - array->len++; - return array->len - 1; -} - -EAPI int -eina_inarray_insert(Eina_Inarray *array, const void *data, Eina_Compare_Cb compare) -{ - const unsigned char *itr, *itr_end; - unsigned int sz; - - EINA_MAGIC_CHECK_INARRAY(array, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(compare, -1); - - sz = array->member_size; - itr = array->members; - itr_end = itr + array->len * sz; - for (; itr < itr_end; itr += sz) - { - unsigned int offset, position; - int cmp = compare(itr, data); - if (cmp <= 0) - continue; - - offset = itr - (unsigned char *)array->members; - position = offset / sz; - if (!eina_inarray_insert_at(array, position, data)) - return -1; - return position; - } - return eina_inarray_push(array, data); -} - -EAPI int -eina_inarray_insert_sorted(Eina_Inarray *array, const void *data, Eina_Compare_Cb compare) -{ - unsigned int pos; - int cmp; - - EINA_MAGIC_CHECK_INARRAY(array, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(compare, -1); - - pos = _eina_inarray_search_sorted_near(array, data, compare, &cmp); - if (cmp > 0) - pos++; - - if (!eina_inarray_insert_at(array, pos, data)) - return -1; - return pos; -} - -EAPI int -eina_inarray_remove(Eina_Inarray *array, const void *data) -{ - const unsigned char *itr, *itr_end; - unsigned int position, sz; - - EINA_MAGIC_CHECK_INARRAY(array, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1); - - sz = array->member_size; - if ((data >= array->members) && - (data < _eina_inarray_get(array, array->len))) - { - unsigned int offset = ((unsigned char *)data - - (unsigned char *)array->members); - position = offset / sz; - goto found; - } - - itr = array->members; - itr_end = itr + array->len * sz; - for (; itr < itr_end; itr += sz) - { - if (memcmp(data, itr, sz) == 0) - { - unsigned int offset = itr - (unsigned char *)array->members; - position = offset / sz; - goto found; - } - } - return -1; - -found: - if (!eina_inarray_remove_at(array, position)) - return -1; - return position; -} - -EAPI void * -eina_inarray_pop(Eina_Inarray *array) -{ - EINA_MAGIC_CHECK_INARRAY(array, NULL); - EINA_SAFETY_ON_TRUE_RETURN_VAL(array->len == 0, NULL); - if (!_eina_inarray_resize(array, array->len - 1)) - return NULL; - array->len--; - return _eina_inarray_get(array, array->len + 1); -} - -EAPI void * -eina_inarray_nth(const Eina_Inarray *array, unsigned int position) -{ - EINA_MAGIC_CHECK_INARRAY(array, NULL); - EINA_SAFETY_ON_TRUE_RETURN_VAL(position >= array->len, NULL); - return _eina_inarray_get(array, position); -} - -EAPI Eina_Bool -eina_inarray_insert_at(Eina_Inarray *array, unsigned int position, const void *data) -{ - unsigned int sz; - unsigned char *p; - - EINA_MAGIC_CHECK_INARRAY(array, EINA_FALSE); - EINA_SAFETY_ON_TRUE_RETURN_VAL(position > array->len, EINA_FALSE); - - if (!_eina_inarray_resize(array, array->len + 1)) - return EINA_FALSE; - - p = _eina_inarray_get(array, position); - sz = array->member_size; - if (array->len > position) - memmove(p + sz, p, (array->len - position) * sz); - memcpy(p, data, sz); - - array->len++; - return EINA_TRUE; -} - -EAPI void * -eina_inarray_alloc_at(Eina_Inarray *array, unsigned int position, unsigned int member_count) -{ - unsigned int sz; - unsigned char *p; - - EINA_MAGIC_CHECK_INARRAY(array, NULL); - EINA_SAFETY_ON_TRUE_RETURN_VAL(position > array->len, NULL); - EINA_SAFETY_ON_TRUE_RETURN_VAL(member_count == 0, NULL); - - if (!_eina_inarray_resize(array, array->len + member_count)) - return NULL; - - p = _eina_inarray_get(array, position); - sz = array->member_size; - if (array->len > position) - memmove(p + member_count * sz, p, (array->len - position) * sz); - - array->len += member_count; - return p; -} - -EAPI Eina_Bool -eina_inarray_replace_at(Eina_Inarray *array, unsigned int position, const void *data) -{ - unsigned char *p; - - EINA_MAGIC_CHECK_INARRAY(array, EINA_FALSE); - EINA_SAFETY_ON_TRUE_RETURN_VAL(position >= array->len, EINA_FALSE); - - p = _eina_inarray_get(array, position); - memcpy(p, data, array->member_size); - - return EINA_TRUE; -} - -EAPI Eina_Bool -eina_inarray_remove_at(Eina_Inarray *array, unsigned int position) -{ - EINA_MAGIC_CHECK_INARRAY(array, EINA_FALSE); - EINA_SAFETY_ON_TRUE_RETURN_VAL(position >= array->len, EINA_FALSE); - - if (position + 1 < array->len) - { - unsigned int sz = array->member_size; - unsigned char *p = _eina_inarray_get(array, position); - memmove(p, p + sz, (array->len - position - 1) * sz); - } - - _eina_inarray_resize(array, array->len - 1); - array->len--; - return EINA_TRUE; -} - -EAPI void -eina_inarray_reverse(Eina_Inarray *array) -{ - size_t sz; - unsigned char *fwd, *rev, *fwd_end; - void *tmp; - - EINA_MAGIC_CHECK_INARRAY(array); - - if (array->len < 2) - return; - - sz = array->member_size; - - tmp = alloca(sz); - EINA_SAFETY_ON_NULL_RETURN(tmp); - - fwd = array->members; - fwd_end = fwd + (array->len / 2) * sz; - - rev = fwd + (array->len - 1) * sz; - - for (; fwd < fwd_end; fwd += sz, rev -= sz) - { - memcpy(tmp, fwd, sz); - memcpy(fwd, rev, sz); - memcpy(rev, tmp, sz); - } -} - -EAPI void -eina_inarray_sort(Eina_Inarray *array, Eina_Compare_Cb compare) -{ - EINA_MAGIC_CHECK_INARRAY(array); - EINA_SAFETY_ON_NULL_RETURN(compare); - qsort(array->members, array->len, array->member_size, compare); -} - -EAPI int -eina_inarray_search(const Eina_Inarray *array, const void *data, Eina_Compare_Cb compare) -{ - EINA_MAGIC_CHECK_INARRAY(array, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(compare, -1); - return _eina_inarray_search(array, data, compare); -} - -EAPI int -eina_inarray_search_sorted(const Eina_Inarray *array, const void *data, Eina_Compare_Cb compare) -{ - unsigned int pos; - int cmp; - - EINA_MAGIC_CHECK_INARRAY(array, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(compare, -1); - - pos = _eina_inarray_search_sorted_near(array, data, compare, &cmp); - if (cmp == 0) - return pos; - return -1; -} - -EAPI Eina_Bool -eina_inarray_foreach(const Eina_Inarray *array, Eina_Each_Cb function, const void *user_data) -{ - unsigned char *itr, *itr_end; - unsigned int sz; - Eina_Bool ret = EINA_TRUE; - - EINA_MAGIC_CHECK_INARRAY(array, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(function, EINA_FALSE); - - sz = array->member_size; - itr = array->members; - itr_end = itr + array->len * sz; - for (; (itr < itr_end) && (ret); itr += sz) - ret = function(array, itr, (void *)user_data); - return ret; -} - -EAPI int -eina_inarray_foreach_remove(Eina_Inarray *array, Eina_Each_Cb match, const void *user_data) -{ - unsigned int i = 0, count = 0; - - EINA_MAGIC_CHECK_INARRAY(array, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(match, -1); - - while (i < array->len) - { - void *p = _eina_inarray_get(array, i); - if (match(array, p, (void *)user_data) == EINA_FALSE) - { - i++; - continue; - } - - eina_inarray_remove_at(array, i); - count++; - } - - return count; -} - -EAPI unsigned int -eina_inarray_count(const Eina_Inarray *array) -{ - EINA_MAGIC_CHECK_INARRAY(array, 0); - return array->len; -} - -EAPI Eina_Iterator * -eina_inarray_iterator_new(const Eina_Inarray *array) -{ - Eina_Iterator_Inarray *it; - - EINA_MAGIC_CHECK_INARRAY(array, NULL); - - eina_error_set(0); - it = calloc(1, sizeof(Eina_Iterator_Inarray)); - if (!it) - { - eina_error_set(EINA_ERROR_OUT_OF_MEMORY); - return NULL; - } - - EINA_MAGIC_SET(it, EINA_MAGIC_INARRAY_ITERATOR); - EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); - - it->array = array; - - it->iterator.version = EINA_ITERATOR_VERSION; - it->iterator.next = FUNC_ITERATOR_NEXT(_eina_inarray_iterator_next); - it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER - (_eina_inarray_iterator_get_container); - it->iterator.free = FUNC_ITERATOR_FREE(_eina_inarray_iterator_free); - - return &it->iterator; -} - -EAPI Eina_Iterator * -eina_inarray_iterator_reversed_new(const Eina_Inarray *array) -{ - Eina_Iterator_Inarray *it; - - EINA_MAGIC_CHECK_INARRAY(array, NULL); - - eina_error_set(0); - it = calloc(1, sizeof(Eina_Iterator_Inarray)); - if (!it) - { - eina_error_set(EINA_ERROR_OUT_OF_MEMORY); - return NULL; - } - - EINA_MAGIC_SET(it, EINA_MAGIC_INARRAY_ITERATOR); - EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); - - it->array = array; - it->pos = array->len; - - it->iterator.version = EINA_ITERATOR_VERSION; - it->iterator.next = FUNC_ITERATOR_NEXT(_eina_inarray_iterator_prev); - it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER - (_eina_inarray_iterator_get_container); - it->iterator.free = FUNC_ITERATOR_FREE(_eina_inarray_iterator_free); - - return &it->iterator; -} - -EAPI Eina_Accessor * -eina_inarray_accessor_new(const Eina_Inarray *array) -{ - Eina_Accessor_Inarray *ac; - - EINA_MAGIC_CHECK_INARRAY(array, NULL); - - eina_error_set(0); - ac = calloc(1, sizeof(Eina_Accessor_Inarray)); - if (!ac) - { - eina_error_set(EINA_ERROR_OUT_OF_MEMORY); - return NULL; - } - - EINA_MAGIC_SET(ac, EINA_MAGIC_INARRAY_ACCESSOR); - EINA_MAGIC_SET(&ac->accessor, EINA_MAGIC_ACCESSOR); - - ac->array = array; - - ac->accessor.version = EINA_ACCESSOR_VERSION; - ac->accessor.get_at = FUNC_ACCESSOR_GET_AT(_eina_inarray_accessor_get_at); - ac->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER - (_eina_inarray_accessor_get_container); - ac->accessor.free = FUNC_ACCESSOR_FREE(_eina_inarray_accessor_free); - - return &ac->accessor; -} diff --git a/src/lib/eina_inlist.c b/src/lib/eina_inlist.c deleted file mode 100644 index c80f87b..0000000 --- a/src/lib/eina_inlist.c +++ /dev/null @@ -1,914 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> -#include <assert.h> - -#include <stdio.h> - -#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; - - EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL); - - 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; - - EINA_SAFETY_ON_NULL_RETURN_VAL(item, list); - EINA_SAFETY_ON_NULL_RETURN_VAL(func, list); - - if (!list) return eina_inlist_append(NULL, item); - - if (!list->next) - { - 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/src/lib/eina_iterator.c b/src/lib/eina_iterator.c deleted file mode 100644 index d035873..0000000 --- a/src/lib/eina_iterator.c +++ /dev/null @@ -1,176 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> - -#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) -{ - if (!iterator) - return; - - EINA_MAGIC_CHECK_ITERATOR(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->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; - - if (!iterator) - return; - - EINA_MAGIC_CHECK_ITERATOR(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/src/lib/eina_lalloc.c b/src/lib/eina_lalloc.c deleted file mode 100644 index b1e62b7..0000000 --- a/src/lib/eina_lalloc.c +++ /dev/null @@ -1,158 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> - -#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/src/lib/eina_list.c b/src/lib/eina_list.c deleted file mode 100644 index 7ef219d..0000000 --- a/src/lib/eina_list.c +++ /dev/null @@ -1,1493 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#ifdef HAVE_EVIL -# include <Evil.h> -#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), 128); - 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), 16); - 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 limit, 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 limit, sort the whole list */ - if ((limit == 0) || - (limit > list->accounting->count)) - limit = list->accounting->count; - - if (limit != list->accounting->count) - { - unsort = eina_list_nth_list(list, limit); - 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; - next->accounting->count = 0; - *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_SAFETY_ON_NULL_RETURN_VAL(list, NULL); - - 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/src/lib/eina_log.c b/src/lib/eina_log.c deleted file mode 100644 index f58163f..0000000 --- a/src/lib/eina_log.c +++ /dev/null @@ -1,2100 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <fnmatch.h> -#include <assert.h> -#include <errno.h> - -#if defined HAVE_EXECINFO_H && defined HAVE_BACKTRACE && defined HAVE_BACKTRACE_SYMBOLS -# include <execinfo.h> -# define EINA_LOG_BACKTRACE -#endif - -#ifdef HAVE_UNISTD_H -# include <unistd.h> -#endif - -#ifdef EFL_HAVE_POSIX_THREADS -# include <pthread.h> -#endif - -#ifdef HAVE_EVIL -# include <Evil.h> -#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" -#define EINA_LOG_ENV_BACKTRACE "EINA_LOG_BACKTRACE" - -#ifdef EINA_ENABLE_LOG - -// 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 EINA_LOG_BACKTRACE -static int _backtrace_level = -1; -#endif - -#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 -/* TODO: query win32_def_attr on eina_log_init() */ -static int win32_def_attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; - -/* NOTE: can't use eina_log from inside this function */ -static int -eina_log_win32_color_convert(const char *color, const char **endptr) -{ - const char *p; - int attr = 0; - - if (endptr) *endptr = color; - - if (color[0] != '\033') return 0; - if (color[1] != '[') return 0; - - p = color + 2; - while (1) - { - char *end; - int code = strtol(p, &end, 10); - - if (p == end) - { - //fputs("empty color string\n", stderr); - if (endptr) *endptr = end; - attr = 0; /* assume it was not color, must end with 'm' */ - break; - } - - if (code) - { - if (code == 0) attr = win32_def_attr; - else if (code == 1) attr |= FOREGROUND_INTENSITY; - else if (code == 4) attr |= COMMON_LVB_UNDERSCORE; - else if (code == 7) attr |= COMMON_LVB_REVERSE_VIDEO; - else if ((code >= 30) && (code <= 37)) - { - /* clear foreground */ - attr &= ~(FOREGROUND_RED | - FOREGROUND_GREEN | - FOREGROUND_BLUE); - - if (code == 31) - attr |= FOREGROUND_RED; - else if (code == 32) - attr |= FOREGROUND_GREEN; - else if (code == 33) - attr |= FOREGROUND_RED | FOREGROUND_GREEN; - else if (code == 34) - attr |= FOREGROUND_BLUE; - else if (code == 35) - attr |= FOREGROUND_RED | FOREGROUND_BLUE; - else if (code == 36) - attr |= FOREGROUND_GREEN | FOREGROUND_BLUE; - else if (code == 37) - attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; - } - else if ((code >= 40) && (code <= 47)) - { - /* clear background */ - attr &= ~(BACKGROUND_RED | - BACKGROUND_GREEN | - BACKGROUND_BLUE); - - if (code == 41) - attr |= BACKGROUND_RED; - else if (code == 42) - attr |= BACKGROUND_GREEN; - else if (code == 43) - attr |= BACKGROUND_RED | BACKGROUND_GREEN; - else if (code == 44) - attr |= BACKGROUND_BLUE; - else if (code == 45) - attr |= BACKGROUND_RED | BACKGROUND_BLUE; - else if (code == 46) - attr |= BACKGROUND_GREEN | BACKGROUND_BLUE; - else if (code == 47) - attr |= BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE; - } - } - - if (*end == 'm') - { - if (endptr) *endptr = end + 1; - break; - } - else if (*end == ';') - p = end + 1; - else - { - //fprintf(stderr, "unexpected char in color string: %s\n", end); - attr = 0; /* assume it was not color */ - if (endptr) *endptr = end; - break; - } - } - - return attr; -} - -static int -eina_log_win32_color_get(const char *color) -{ - return eina_log_win32_color_convert(color, NULL); -} -#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; - 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(); -} - -#endif - -/** - * @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) -{ -#ifdef EINA_ENABLE_LOG - const char *level, *tmp; - int color_disable; - - assert((sizeof(_names) / sizeof(_names[0])) == EINA_LOG_LEVELS); - -#ifdef EINA_LOG_BACKTRACE - if ((tmp = getenv(EINA_LOG_ENV_BACKTRACE))) - _backtrace_level = atoi(tmp); -#endif - - 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(); - -#endif - 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) -{ -#ifdef EINA_ENABLE_LOG - 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); - } - -#endif - 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) -{ -#ifdef EINA_ENABLE_LOG - if (_threads_inited) return; - _main_thread = SELF(); - if (!INIT()) return; - _threads_inited = EINA_TRUE; -#endif -} - -/** - * @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) -{ -#ifdef EINA_ENABLE_LOG - if (!_threads_inited) return; - CHECK_MAIN(); - SHUTDOWN(); - _threads_enabled = EINA_FALSE; - _threads_inited = EINA_FALSE; -#endif -} - -#endif - -/*============================================================================* -* API * -*============================================================================*/ - -/** - * @cond LOCAL - */ - -EAPI int EINA_LOG_DOMAIN_GLOBAL = 0; - -/** - * @endcond - */ - -EAPI void -eina_log_threads_enable(void) -{ -#if defined (EFL_HAVE_THREADS) && defined (EINA_ENABLE_LOG) - 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) -{ -#ifdef EINA_ENABLE_LOG - LOG_LOCK(); - _print_cb = cb; - _print_cb_data = data; - eina_log_print_prefix_update(); - LOG_UNLOCK(); -#else - (void) cb; - (void) data; -#endif -} - -EAPI void -eina_log_level_set(int level) -{ -#ifdef EINA_ENABLE_LOG - _log_level = level; - if (EINA_LIKELY((EINA_LOG_DOMAIN_GLOBAL >= 0) && - ((unsigned int)EINA_LOG_DOMAIN_GLOBAL < _log_domains_count))) - _log_domains[EINA_LOG_DOMAIN_GLOBAL].level = level; -#else - (void) level; -#endif -} - -EAPI int -eina_log_level_get(void) -{ -#ifdef EINA_ENABLE_LOG - return _log_level; -#else - return 0; -#endif -} - -EAPI Eina_Bool -eina_log_main_thread_check(void) -{ -#if defined (EFL_HAVE_THREADS) && defined (EINA_ENABLE_LOG) - return ((!_threads_enabled) || IS_MAIN(SELF())); -#else - return EINA_TRUE; -#endif -} - -EAPI void -eina_log_color_disable_set(Eina_Bool disabled) -{ -#ifdef EINA_ENABLE_LOG - _disable_color = disabled; -#else - (void) disabled; -#endif -} - -EAPI Eina_Bool -eina_log_color_disable_get(void) -{ -#ifdef EINA_ENABLE_LOG - return _disable_color; -#else - return EINA_TRUE; -#endif -} - -EAPI void -eina_log_file_disable_set(Eina_Bool disabled) -{ -#ifdef EINA_ENABLE_LOG - _disable_file = disabled; -#else - (void) disabled; -#endif -} - -EAPI Eina_Bool -eina_log_file_disable_get(void) -{ -#ifdef EINA_ENABLE_LOG - return _disable_file; -#else - return EINA_TRUE; -#endif -} - -EAPI void -eina_log_function_disable_set(Eina_Bool disabled) -{ -#ifdef EINA_ENABLE_LOG - _disable_function = disabled; -#else - (void) disabled; -#endif -} - -EAPI Eina_Bool -eina_log_function_disable_get(void) -{ -#ifdef EINA_ENABLE_LOG - return _disable_function; -#else - return EINA_TRUE; -#endif -} - -EAPI void -eina_log_abort_on_critical_set(Eina_Bool abort_on_critical) -{ -#ifdef EINA_ENABLE_LOG - _abort_on_critical = abort_on_critical; -#else - (void) abort_on_critical; -#endif -} - -EAPI Eina_Bool -eina_log_abort_on_critical_get(void) -{ -#ifdef EINA_ENABLE_LOG - return _abort_on_critical; -#else - return EINA_FALSE; -#endif -} - -EAPI void -eina_log_abort_on_critical_level_set(int critical_level) -{ -#ifdef EINA_ENABLE_LOG - _abort_level_on_critical = critical_level; -#else - (void) critical_level; -#endif -} - -EAPI int -eina_log_abort_on_critical_level_get(void) -{ -#ifdef EINA_ENABLE_LOG - return _abort_level_on_critical; -#else - return 0; -#endif -} - -EAPI int -eina_log_domain_register(const char *name, const char *color) -{ -#ifdef EINA_ENABLE_LOG - int r; - - EINA_SAFETY_ON_NULL_RETURN_VAL(name, -1); - - LOG_LOCK(); - r = eina_log_domain_register_unlocked(name, color); - LOG_UNLOCK(); - return r; -#else - (void) name; - (void) color; - return 0; -#endif -} - -EAPI void -eina_log_domain_unregister(int domain) -{ -#ifdef EINA_ENABLE_LOG - EINA_SAFETY_ON_FALSE_RETURN(domain >= 0); - LOG_LOCK(); - eina_log_domain_unregister_unlocked(domain); - LOG_UNLOCK(); -#else - (void) domain; -#endif -} - -EAPI void -eina_log_domain_level_set(const char *domain_name, int level) -{ -#ifdef EINA_ENABLE_LOG - Eina_Log_Domain_Level_Pending *pending; - size_t namelen; - unsigned int i; - - 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)); -#else - (void) domain_name; - (void) level; -#endif -} - -EAPI int -eina_log_domain_level_get(const char *domain_name) -{ -#ifdef EINA_ENABLE_LOG - Eina_Log_Domain_Level_Pending *pending; - size_t namelen; - unsigned int i; - - 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; -#else - (void) domain_name; - return 0; -#endif -} - -EAPI int -eina_log_domain_registered_level_get(int domain) -{ -#ifdef EINA_ENABLE_LOG - EINA_SAFETY_ON_FALSE_RETURN_VAL(domain >= 0, EINA_LOG_LEVEL_UNKNOWN); - EINA_SAFETY_ON_FALSE_RETURN_VAL((unsigned int)domain < _log_domains_count, - EINA_LOG_LEVEL_UNKNOWN); - EINA_SAFETY_ON_TRUE_RETURN_VAL(_log_domains[domain].deleted, - EINA_LOG_LEVEL_UNKNOWN); - return _log_domains[domain].level; -#else - (void) domain; - return 0; -#endif -} - -#ifdef EINA_LOG_BACKTRACE -# define DISPLAY_BACKTRACE(File, Level) \ - if (EINA_UNLIKELY(Level < _backtrace_level)) \ - { \ - void *bt[256]; \ - char **strings; \ - int btlen; \ - int i; \ - \ - btlen = backtrace((void **)bt, 256); \ - strings = backtrace_symbols((void **)bt, btlen); \ - fprintf(File, "*** Backtrace ***\n"); \ - for (i = 0; i < btlen; ++i) \ - fprintf(File, "%s\n", strings[i]); \ - free(strings); \ - } -#else -# define DISPLAY_BACKTRACE(File, Level) -#endif - -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) -{ -#ifdef EINA_ENABLE_LOG - _eina_log_print_prefix(stderr, d, level, file, fnc, line); - vfprintf(stderr, fmt, args); - putc('\n', stderr); - DISPLAY_BACKTRACE(stderr, level); -#else - (void) d; - (void) level; - (void) file; - (void) fnc; - (void) line; - (void) fmt; - (void) data; - (void) args; -#endif -} - -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) -{ -#ifdef EINA_ENABLE_LOG - _eina_log_print_prefix(stdout, d, level, file, fnc, line); - vprintf(fmt, args); - putchar('\n'); - DISPLAY_BACKTRACE(stdout, level); -#else - (void) d; - (void) level; - (void) file; - (void) fnc; - (void) line; - (void) fmt; - (void) data; - (void) args; -#endif -} - -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) -{ -#ifdef EINA_ENABLE_LOG - EINA_SAFETY_ON_NULL_RETURN(data); - 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); - DISPLAY_BACKTRACE(f, level); -#ifdef EFL_HAVE_THREADS -end: -#endif - vfprintf(f, fmt, args); - putc('\n', f); -#else - (void) d; - (void) file; - (void) fnc; - (void) line; - (void) fmt; - (void) data; - (void) args; -#endif -} - -EAPI void -eina_log_print(int domain, Eina_Log_Level level, const char *file, - const char *fnc, int line, const char *fmt, ...) -{ -#ifdef EINA_ENABLE_LOG - va_list args; - -#ifdef EINA_SAFETY_CHECKS - 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); -#else - (void) domain; - (void) level; - (void) file; - (void) fnc; - (void) line; - (void) fmt; -#endif -} - -EAPI void -eina_log_vprint(int domain, Eina_Log_Level level, const char *file, - const char *fnc, int line, const char *fmt, va_list args) -{ -#ifdef EINA_ENABLE_LOG - -#ifdef EINA_SAFETY_CHECKS - if (EINA_UNLIKELY(!file)) - { - 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(); -#else - (void) domain; - (void) level; - (void) file; - (void) fnc; - (void) line; - (void) fmt; - (void) args; -#endif -} - -EAPI void -eina_log_console_color_set(FILE *fp, const char *color) -{ -#ifdef EINA_ENABLE_LOG - - EINA_SAFETY_ON_NULL_RETURN(fp); - EINA_SAFETY_ON_NULL_RETURN(color); - if (_disable_color) return; - -#ifdef _WIN32 - int attr = eina_log_win32_color_convert(color, NULL); - HANDLE *handle; - - if (!attr) return; - - if (fp == stderr) - handle = GetStdHandle(STD_ERROR_HANDLE); - else if (fp == stdout) - handle = GetStdHandle(STD_OUTPUT_HANDLE); - else - { - /* Do we have a way to convert FILE* to HANDLE? - * Should we use it? - */ - return; - } - SetConsoleTextAttribute(handle, attr); -#else - fputs(color, fp); -#endif - -#else - (void)color; -#endif -} diff --git a/src/lib/eina_magic.c b/src/lib/eina_magic.c deleted file mode 100644 index a42db2d..0000000 --- a/src/lib/eina_magic.c +++ /dev/null @@ -1,322 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> -#include <string.h> - -#ifdef HAVE_EVIL -# include <Evil.h> -#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)(size_t)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) - { - ERR("could not realloc magic_strings from %zu to %zu buckets.", - _eina_magic_strings_allocated, size); - 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 * -*============================================================================*/ - -EAPI Eina_Error EINA_ERROR_MAGIC_FAILED = 0; - -static const char EINA_ERROR_MAGIC_FAILED_STR[] = "Magic check failed."; - -/** - * @internal - * @brief Initialize the magic string module. - * - * @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; - } - EINA_ERROR_MAGIC_FAILED = eina_error_msg_static_register( - EINA_ERROR_MAGIC_FAILED_STR); - - 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 *)(size_t)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) -{ - eina_error_set(EINA_ERROR_MAGIC_FAILED); - 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/src/lib/eina_main.c b/src/lib/eina_main.c deleted file mode 100644 index a4aea4e..0000000 --- a/src/lib/eina_main.c +++ /dev/null @@ -1,463 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdio.h> - -#ifdef EFL_HAVE_WIN32_THREADS -# define WIN32_LEAN_AND_MEAN -# include <windows.h> -# undef WIN32_LEAN_AND_MEAN -#endif - -#ifdef EFL_HAVE_THREADS -# ifdef HAVE_SYS_TYPES_H -# include <sys/types.h> -# endif -# ifdef HAVE_UNISTD_H -# include <unistd.h> -# endif -#endif - -#ifdef HAVE_MCHECK_H -# ifdef HAVE_MTRACE -# define MT 1 -# endif -#endif - -#ifdef MT -#include <mcheck.h> -#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" -#include "eina_inarray.h" -#include "eina_value.h" -/* no model for now -#include "eina_model.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(inarray); - 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); - S(value); - S(thread); -/* no model for now - S(model); - */ -#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(stringshare), - S(error), - S(safety_checks), - S(magic_string), - S(iterator), - S(accessor), - S(inarray), - S(array), - S(module), - S(mempool), - S(list), - S(binshare), - S(ustringshare), - S(matrixsparse), - S(convert), - S(counter), - S(benchmark), - S(rectangle), - S(strbuf), - S(ustrbuf), - S(quadtree), - S(simple_xml), - S(file), - S(prefix), - S(value), - S(thread) -/* no model for now - S(model) - */ -#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_cpu_count_internal(); - - _eina_main_count = 1; - return 1; -} - -EAPI int -eina_shutdown(void) -{ - if (_eina_main_count <= 0) - { - ERR("Init count not greater than 0 in shutdown."); - return 0; - } - _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) - { - fprintf(stderr, "=======\n"); - 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; - -# ifdef _WIN32 - if (_eina_main_loop == GetCurrentThreadId()) - return EINA_TRUE; -# else - if (pthread_equal(_eina_main_loop, pthread_self())) - return EINA_TRUE; -# endif - - pid = getpid(); -# ifdef _WIN32 - if (pid != _eina_pid) - { - _eina_pid = pid; - _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; - } -#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/src/lib/eina_matrixsparse.c b/src/lib/eina_matrixsparse.c deleted file mode 100644 index d287545..0000000 --- a/src/lib/eina_matrixsparse.c +++ /dev/null @@ -1,1427 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - - -/** - * @page tutorial_matrixsparse_page Sparse Matrix Tutorial - * - * to be written... - * - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> - -#ifdef HAVE_EVIL -# include <Evil.h> -#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), - 32); - 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), 32); - 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; - - if (!m) - return; - - 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); - if ((update_last_used_row) && (m->last_used == r_aux)) - m->last_used = r; - } - 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/src/lib/eina_mempool.c b/src/lib/eina_mempool.c deleted file mode 100644 index 385ea15..0000000 --- a/src/lib/eina_mempool.c +++ /dev/null @@ -1,391 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <assert.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#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 = NULL; - Eina_Mempool *mp; - - Eina_Error err = EINA_ERROR_NOT_MEMPOOL_MODULE; - - eina_error_set(0); - if (getenv("EINA_MEMPOOL_PASS")) - { - be = eina_hash_find(_backends, "pass_through"); - if (!be) be = eina_hash_find(_backends, name); - } - else 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/src/lib/eina_mmap.c b/src/lib/eina_mmap.c deleted file mode 100644 index 90809a2..0000000 --- a/src/lib/eina_mmap.c +++ /dev/null @@ -1,193 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_SIGINFO_T - -#ifdef STDC_HEADERS -# include <stdlib.h> -# include <stddef.h> -#else -# ifdef HAVE_STDLIB_H -# include <stdlib.h> -# endif -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <limits.h> -#include <signal.h> -#include <errno.h> -#include <fcntl.h> -#include <unistd.h> - -#if HAVE_SIGINFO_H -# include <siginfo.h> -#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(); - } - /* Look into mmaped Eina_File if it was one of them, just to remember for later request */ - eina_file_mmap_faulty(addr, _eina_mmap_pagesize); - /* restore previous errno */ - errno = perrno; -} -#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) goto done; - /* 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 */ - if (_eina_mmap_zero_fd >= 0) - { - close(_eina_mmap_zero_fd); - _eina_mmap_zero_fd = -1; - } - signal(SIGBUS, SIG_DFL); - } -done: - mmap_safe = enabled; - return mmap_safe; -#endif -} - -EAPI Eina_Bool -eina_mmap_safety_enabled_get(void) -{ - return mmap_safe; -} diff --git a/src/lib/eina_model.c b/src/lib/eina_model.c deleted file mode 100644 index 22ca718..0000000 --- a/src/lib/eina_model.c +++ /dev/null @@ -1,5551 +0,0 @@ -/* EINA - EFL data type library - * Copyright (C) 2012 ProFUSION embedded systems - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; - * if not, see <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_ALLOCA_H -# include <alloca.h> -#elif defined __GNUC__ -# define alloca __builtin_alloca -#elif defined _AIX -# define alloca __alloca -#elif defined _MSC_VER -# include <malloc.h> -# define alloca _alloca -#else -# include <stddef.h> -# ifdef __cplusplus -extern "C" -# endif -void *alloca (size_t); -#endif - -#ifdef HAVE_EXECINFO_H -#include <execinfo.h> -#endif - -#include "eina_config.h" -#include "eina_private.h" -#include "eina_error.h" -#include "eina_log.h" -#include "eina_mempool.h" -#include "eina_lock.h" -#include "eina_inlist.h" -#include "eina_strbuf.h" - -/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ -#include "eina_safety_checks.h" -#include "eina_value.h" /* eina-safety used in inline.x */ -#include "eina_model.h" - -/*============================================================================* - * Local * - *============================================================================*/ - -/** - * @cond LOCAL - */ - -static Eina_Mempool *_eina_model_mp = NULL; -static Eina_Hash *_eina_model_inner_mps = NULL; -static Eina_Lock _eina_model_inner_mps_lock; -static char *_eina_model_mp_choice = NULL; -static Eina_Hash *_eina_model_descriptions = NULL; -static Eina_Lock _eina_model_descriptions_lock; -static int _eina_model_log_dom = -1; -static enum { - EINA_MODEL_DEBUG_NONE = 0, - EINA_MODEL_DEBUG_CHECK = 1, - EINA_MODEL_DEBUG_BACKTRACE = 2, -} _eina_model_debug = EINA_MODEL_DEBUG_NONE; -static Eina_Lock _eina_model_debug_list_lock; -static Eina_List *_eina_model_debug_list = NULL; - -static const char _eina_model_str_deleted[] = "deleted"; -static const char _eina_model_str_freed[] = "freed"; -static const char _eina_model_str_property_set[] = "property,set"; -static const char _eina_model_str_property_del[] = "property,deleted"; -static const char _eina_model_str_children_changed[] = "children,changed"; -static const char _eina_model_str_child_inserted[] = "child,inserted"; -static const char _eina_model_str_child_set[] = "child,set"; -static const char _eina_model_str_child_del[] = "child,deleted"; -static const char _eina_model_str_loaded[] = "loaded"; -static const char _eina_model_str_unloaded[] = "unloaded"; -static const char _eina_model_str_properties_loaded[] = "properties,loaded"; -static const char _eina_model_str_properties_unloaded[] = "properties,unloaded"; -static const char _eina_model_str_children_loaded[] = "children,loaded"; -static const char _eina_model_str_children_unloaded[] = "children,unloaded"; - -#ifdef CRITICAL -#undef CRITICAL -#endif -#define CRITICAL(...) EINA_LOG_DOM_CRIT(_eina_model_log_dom, __VA_ARGS__) - -#ifdef ERR -#undef ERR -#endif -#define ERR(...) EINA_LOG_DOM_ERR(_eina_model_log_dom, __VA_ARGS__) - -#ifdef WRN -#undef WRN -#endif -#define WRN(...) EINA_LOG_DOM_WARN(_eina_model_log_dom, __VA_ARGS__) - -#ifdef INF -#undef INF -#endif -#define INF(...) EINA_LOG_DOM_INFO(_eina_model_log_dom, __VA_ARGS__) - -#ifdef DBG -#undef DBG -#endif -#define DBG(...) EINA_LOG_DOM_DBG(_eina_model_log_dom, __VA_ARGS__) - - -/* convenience sort array of Eina_Model* giving compare Eina_Model* instead of - * Eina_Model** - */ -static unsigned int -_eina_model_array_partition(Eina_Model **array, unsigned int start, unsigned int last, unsigned int pivot, Eina_Compare_Cb compare) -{ - Eina_Model **itr, **itr_end, *tmp, *pivot_value; - - pivot_value = tmp = array[pivot]; - array[pivot] = array[last]; - array[last] = tmp; - - pivot = start; - itr = array + start; - itr_end = array + last; - for (; itr < itr_end; itr++) - { - if (compare(*itr, pivot_value) < 0) - { - tmp = *itr; - *itr = array[pivot]; - array[pivot] = tmp; - pivot++; - } - } - - tmp = array[last]; - array[last] = array[pivot]; - array[pivot] = tmp; - - return pivot; -} - -static void -_eina_model_array_sort(Eina_Model **array, unsigned int start, unsigned int last, Eina_Compare_Cb compare) -{ - unsigned int pivot, new_pivot; - - if (last <= start) - return; - - pivot = start + (last - start) / 2; /* avoid overflow */ - new_pivot = _eina_model_array_partition(array, start, last, pivot, compare); - - if (start + 1 < new_pivot) - _eina_model_array_sort(array, start, new_pivot - 1, compare); - - if (new_pivot + 1 < last) - _eina_model_array_sort(array, new_pivot + 1, last, compare); -} - -/* - * Most of inner allocations are made with internal mempools, types - * and thus instace private data will repeat and it's good to use them. - * - * To save on the number of mempools, they are kept per size, not per - * type. - * - * This is done by means of _eina_model_inner_alloc() and - * _eina_model_inner_free(), both at thread safe. - * - */ -typedef struct _Eina_Model_Inner_Mp Eina_Model_Inner_Mp; -struct _Eina_Model_Inner_Mp -{ - Eina_Mempool *mempool; - int refcount; -}; - -static inline void -_eina_model_inner_mp_dispose(int size, Eina_Model_Inner_Mp *imp) -{ - EINA_SAFETY_ON_FALSE_RETURN(imp->refcount == 0); - - eina_hash_del_by_key(_eina_model_inner_mps, &size); - eina_mempool_del(imp->mempool); - free(imp); -} - -static inline Eina_Model_Inner_Mp * -_eina_model_inner_mp_get(int size) -{ - Eina_Model_Inner_Mp *imp = eina_hash_find(_eina_model_inner_mps, &size); - if (imp) return imp; - - imp = malloc(sizeof(Eina_Model_Inner_Mp)); - if (!imp) - return NULL; - - imp->refcount = 0; - - imp->mempool = eina_mempool_add(_eina_model_mp_choice, - "Eina_Model_Inner_Mp", NULL, size, 16); - if (!imp->mempool) - { - free(imp); - return NULL; - } - - if (!eina_hash_add(_eina_model_inner_mps, &size, imp)) - { - eina_mempool_del(imp->mempool); - free(imp); - return NULL; - } - - return imp; -} - -static inline void * -_eina_model_inner_alloc_internal(int size) -{ - Eina_Model_Inner_Mp *imp; - void *mem; - - imp = _eina_model_inner_mp_get(size); - if (!imp) return NULL; - - mem = eina_mempool_malloc(imp->mempool, size); - if (mem) imp->refcount++; - else if (imp->refcount == 0) _eina_model_inner_mp_dispose(size, imp); - - return mem; -} - -static inline void -_eina_model_inner_free_internal(int size, void *mem) -{ - Eina_Model_Inner_Mp *imp = eina_hash_find(_eina_model_inner_mps, &size); - EINA_SAFETY_ON_NULL_RETURN(imp); - - eina_mempool_free(imp->mempool, mem); - - imp->refcount--; - if (imp->refcount > 0) return; - _eina_model_inner_mp_dispose(size, imp); -} - -static void * -_eina_model_inner_alloc(size_t size) -{ - void *mem; - - if (size > 512) return malloc(size); - - eina_lock_take(&_eina_model_inner_mps_lock); - mem = _eina_model_inner_alloc_internal(size); - eina_lock_release(&_eina_model_inner_mps_lock); - - return mem; -} - -static void -_eina_model_inner_free(size_t size, void *mem) -{ - if (size > 512) - { - free(mem); - return; - } - - eina_lock_take(&_eina_model_inner_mps_lock); - _eina_model_inner_free_internal(size, mem); - eina_lock_release(&_eina_model_inner_mps_lock); -} - - -typedef union _Eina_Model_Provider Eina_Model_Provider; -union _Eina_Model_Provider -{ - const Eina_Model_Type *type; - const Eina_Model_Interface *iface; -}; - -/* store event name to aid searching */ -typedef struct _Eina_Model_Event_Description_Cache Eina_Model_Event_Description_Cache; -struct _Eina_Model_Event_Description_Cache -{ - const char *name; - const Eina_Model_Event_Description *desc; - Eina_Model_Provider provider; -}; - -/* description is an optimized structure for type. It's built at runtime - * to avoid user input errors and help declaration. - * - * lookups (ifaces, events) are sorted for binary search. - * - * recursion is avoided by expansion of every possible value in "cache" - * struct. - * - * the first usable operation is stopred for type at "ops" struct, - * avoiding usage of _eina_model_type_find_offset(). - * - * Get a model type description using _eina_model_description_get(), - * when it's not used anymore use - * _eina_model_description_dispose(). These operations are thread - * safe. - */ -typedef struct _Eina_Model_Description Eina_Model_Description; -struct _Eina_Model_Description -{ - struct { - const Eina_Model_Type **types; /* size = total.types */ - const Eina_Model_Interface **ifaces; /* sorted, size = total.ifaces */ - Eina_Model_Provider *privates; /* size = total.privates (types + ifaces) */ - Eina_Model_Event_Description_Cache *events; /* size = total.events */ - } cache; - struct { - /* ops are the topmost operation to use for type/interface */ - struct { - Eina_Bool (*setup)(Eina_Model *model); - Eina_Bool (*flush)(Eina_Model *model); - Eina_Bool (*constructor)(Eina_Model *model); - Eina_Bool (*destructor)(Eina_Model *model); - Eina_Bool (*copy)(const Eina_Model *src, Eina_Model *dst); - Eina_Bool (*deep_copy)(const Eina_Model *src, Eina_Model *dst); - Eina_Bool (*compare)(const Eina_Model *a, const Eina_Model *b, int *cmp); - Eina_Bool (*load)(Eina_Model *model); - Eina_Bool (*unload)(Eina_Model *model); - Eina_Bool (*property_get)(const Eina_Model *model, const char *name, Eina_Value *value); - Eina_Bool (*property_set)(Eina_Model *model, const char *name, const Eina_Value *value); - Eina_Bool (*property_del)(Eina_Model *model, const char *name); - Eina_List *(*properties_names_list_get)(const Eina_Model *model); - int (*child_count)(const Eina_Model *model); - Eina_Model *(*child_get)(const Eina_Model *model, unsigned int position); - Eina_Bool (*child_set)(Eina_Model *model, unsigned int position, Eina_Model *child); - Eina_Bool (*child_del)(Eina_Model *model, unsigned int position); - Eina_Bool (*child_insert_at)(Eina_Model *model, unsigned int position, Eina_Model *child); - int (*child_find)(const Eina_Model *model, unsigned int start_position, const Eina_Model *other); - int (*child_criteria_match)(const Eina_Model *model, unsigned int start_position, Eina_Each_Cb match, const void *data); - void (*child_sort)(Eina_Model *model, Eina_Compare_Cb compare); - Eina_Iterator *(*child_iterator_get)(Eina_Model *model, unsigned int start, unsigned int count); - Eina_Iterator *(*child_reversed_iterator_get)(Eina_Model *model, unsigned int start, unsigned int count); - Eina_Iterator *(*child_sorted_iterator_get)(Eina_Model *model, unsigned int start, unsigned int count, Eina_Compare_Cb compare); - Eina_Iterator *(*child_filtered_iterator_get)(Eina_Model *model, unsigned int start, unsigned int count, Eina_Each_Cb match, const void *data); - char *(*to_string)(const Eina_Model *model); /**< used to represent model as string, usually for debug purposes or user convenience */ - const void **extension; - } type; - } ops; - struct { - unsigned int types; - unsigned int ifaces; - unsigned int privates; - unsigned int size; /* sum of all private sizes */ - unsigned int events; - } total; - int refcount; -}; - -static Eina_Bool -_eina_model_description_type_fill(Eina_Model_Description *desc, const Eina_Model_Type *type) -{ - const Eina_Model_Type *itr, *last_itr = NULL; - unsigned int count, child_size = 0; - - for (count = 0, itr = type; itr != NULL; itr = itr->parent, count++) - { - if (itr->version != EINA_MODEL_TYPE_VERSION) - { - CRITICAL("Type %p version is %u, expected %u instead.", - itr, itr->version, EINA_MODEL_TYPE_VERSION); - return EINA_FALSE; - } - if (!itr->name) - { - CRITICAL("Type %p provides no name!", itr); - return EINA_FALSE; - } - if (itr->type_size < sizeof(Eina_Model_Type)) - { - CRITICAL("Type %p %s size must be >= sizeof(Eina_Model_Type)!", - itr, itr->name); - return EINA_FALSE; - } - if (child_size == 0) child_size = itr->type_size; - else if (child_size < itr->type_size) - { - CRITICAL("Type %p %s size is bigger than its child type %p %s!", - itr, itr->name, last_itr, last_itr->name); - return EINA_FALSE; - } - last_itr = itr; - -#define DEF_METH(meth) \ - if (!desc->ops.type.meth) desc->ops.type.meth = itr->meth - DEF_METH(setup); - DEF_METH(flush); - DEF_METH(constructor); - DEF_METH(destructor); - DEF_METH(copy); - DEF_METH(deep_copy); - DEF_METH(compare); - DEF_METH(load); - DEF_METH(unload); - DEF_METH(property_get); - DEF_METH(property_set); - DEF_METH(property_del); - DEF_METH(properties_names_list_get); - DEF_METH(child_count); - DEF_METH(child_get); - DEF_METH(child_set); - DEF_METH(child_del); - DEF_METH(child_insert_at); - DEF_METH(child_find); - DEF_METH(child_criteria_match); - DEF_METH(child_sort); - DEF_METH(child_iterator_get); - DEF_METH(child_reversed_iterator_get); - DEF_METH(child_sorted_iterator_get); - DEF_METH(child_filtered_iterator_get); - DEF_METH(to_string); -#undef DEF_METH - - if ((!itr->parent) && (itr != EINA_MODEL_TYPE_BASE)) - { - CRITICAL("Type %p (%s) does not inherit from EINA_MODEL_TYPE_BASE!", - type, type->name); - return EINA_FALSE; - } - } - -#define CK_METH(meth) \ - if (!desc->ops.type.meth) \ - { \ - CRITICAL("Mandatory method "#meth \ - "() was not provided by type %p (%s).", \ - type, type->name); \ - return EINA_FALSE; \ - } - CK_METH(setup); - CK_METH(flush); - CK_METH(constructor); - CK_METH(destructor); - CK_METH(property_get); -#undef CK_METH - - if (child_size <= sizeof(Eina_Model_Type)) - desc->ops.type.extension = NULL; - else - { - unsigned ext_size = child_size - sizeof(Eina_Model_Type); - unsigned ext_count = ext_size / sizeof(void *); - - if (ext_size % sizeof(void *) != 0) - { - CRITICAL("Extension size %u is not multiple of sizeof(void*)", - ext_size); - return EINA_FALSE; - } - - desc->ops.type.extension = calloc(ext_count, sizeof(void *)); - EINA_SAFETY_ON_NULL_RETURN_VAL(desc->ops.type.extension, EINA_FALSE); - - for (itr = type; itr != NULL; itr = itr->parent) - { - unsigned cur_size = itr->type_size - sizeof(Eina_Model_Type); - unsigned i, cur_count = cur_size / sizeof(void *); - const void * const *ptr = (const void **)((const char *)itr + sizeof(Eina_Model_Type)); - - if (cur_size == 0) break; - - for (i = 0; i < cur_count; i++) - { - if (desc->ops.type.extension[i]) continue; - desc->ops.type.extension[i] = ptr[i]; - } - } - } - - desc->cache.types = malloc(count * sizeof(Eina_Model_Type *)); - EINA_SAFETY_ON_NULL_GOTO(desc->cache.types, cache_types_failed); - desc->total.types = count; - - for (count = 0, itr = type; itr != NULL; itr = itr->parent, count++) - desc->cache.types[count] = itr; - - return EINA_TRUE; - - cache_types_failed: - free(desc->ops.type.extension); - return EINA_FALSE; -} - -static inline Eina_Bool -_eina_model_interface_implements(const Eina_Model_Interface *iface, const Eina_Model_Interface *query) -{ - const Eina_Model_Interface **itr; - - if (iface == query) - return EINA_TRUE; - - if (!iface->interfaces) - return EINA_FALSE; - - for (itr = iface->interfaces; *itr != NULL; itr++) - if (_eina_model_interface_implements(*itr, query)) - return EINA_TRUE; - - return EINA_FALSE; -} - -/* apply topological sort and remove duplicates */ -/* - * TODO: Topological sort will only work for linked interfaces, but - * will ignore original ordering provided by types. Consider the - * following: - * - * - A_Type -> X_Iface (name: "MyIface") - * - B_Type -> Y_Iface (name: "MyIface") - * - * Both X_Iface and Y_Iface are different implementations of the - * "MyIface". - * - * B_Type inherits from A_Type, then Y_Iface must be looked up - * first, even though there is no link between Y_Iface and - * X_Iface. - * - * However, the way the current topological sort behaves, the - * roots may come out in any order. We need a stable version - * that sorts roots before removing them from graph. - * - * Thanks to Tasn to report it :-) - */ -static Eina_Bool -_eina_model_description_ifaces_fix(Eina_Model_Description *desc) -{ - struct node { - const Eina_Model_Interface *iface; - unsigned int users; - Eina_List *deps; - } *nodes, **pending, **roots; - unsigned int n_nodes = desc->total.ifaces, n_pending = 0, n_roots = 0, i, j; - Eina_Bool ret = EINA_TRUE; - - nodes = alloca(n_nodes * sizeof(struct node)); - pending = alloca(n_nodes * sizeof(struct node *)); - roots = alloca(n_nodes * sizeof(struct node *)); - - /* populate */ - for (i = 0, j = 0; i < n_nodes; i++) - { - unsigned int k; - for (k = 0; k < j; k++) - { - if (nodes[k].iface == desc->cache.ifaces[i]) - break; - } - if (k < j) - continue; /* already exists */ - - nodes[j].iface = desc->cache.ifaces[i]; - nodes[j].users = 0; - nodes[j].deps = NULL; - j++; - } - n_nodes = j; - - for (i = 0; i < n_nodes; i++) - { - for (j = 0; j < n_nodes; j++) - { - if (i == j) continue; - if (!_eina_model_interface_implements(nodes[j].iface, - nodes[i].iface)) - continue; - - nodes[i].users++; - nodes[j].deps = eina_list_append(nodes[j].deps, nodes + i); - } - } - for (i = 0; i < n_nodes; i++) - { - if (nodes[i].users == 0) - { - roots[n_roots] = nodes + i; - n_roots++; - } - else - { - pending[n_pending] = nodes + i; - n_pending++; - } - } - - /* topological sort */ - desc->total.ifaces = 0; - while (n_roots > 0) - { - struct node *r, *d; - - /* TODO: sort roots using input order? Or at least study if - * it's enough to change roots append to prepend. - * - * See comments above. - */ - n_roots--; - r = roots[n_roots]; - - desc->cache.ifaces[desc->total.ifaces] = r->iface; - desc->total.ifaces++; - - EINA_LIST_FREE(r->deps, d) - { - d->users--; - if (d->users > 0) continue; - - roots[n_roots] = d; - n_roots++; - - /* remove node, it became a root */ - for (j = 0; j < n_pending; j++) - { - if (pending[j] == d) - { - n_pending--; - if (j < n_pending) - pending[j] = pending[n_pending]; - break; - } - } - } - } - - if (n_pending > 0) - { - ERR("Dependency loop found for interfaces!"); - for (i = 0; i < n_pending; i++) - ERR("%p (%s) is part of dependency loop!", - pending[i]->iface, pending[i]->iface->name); - CRITICAL("Cannot use type %p (%s) with broken interfaces!", - desc->cache.types[0], desc->cache.types[0]->name); - free(desc->cache.ifaces); - ret = EINA_FALSE; - } - - /* likely from still pending (dependency loops) */ - for (i = 0; i < n_nodes; i++) - eina_list_free(nodes[i].deps); - - return ret; -} - -static Eina_Bool -_eina_model_description_ifaces_validate_and_count(const Eina_Model_Interface *iface, unsigned int *count) -{ - if (iface->version != EINA_MODEL_INTERFACE_VERSION) - { - CRITICAL("Interface %p version is %u, expected %u instead.", - iface, iface->version, EINA_MODEL_INTERFACE_VERSION); - return EINA_FALSE; - } - - if (!iface->name) - { - CRITICAL("Interface %p provides no name!", iface); - return EINA_FALSE; - } - - if (iface->interfaces) - { - const Eina_Model_Interface **itr = iface->interfaces; - for (; *itr != NULL; itr++) - if (!_eina_model_description_ifaces_validate_and_count(*itr, count)) - return EINA_FALSE; - } - - (*count)++; - return EINA_TRUE; -} - -static void -_eina_model_description_ifaces_populate(Eina_Model_Description *desc, const Eina_Model_Interface *iface) -{ - desc->cache.ifaces[desc->total.ifaces] = iface; - desc->total.ifaces++; - - if (iface->interfaces) - { - const Eina_Model_Interface **itr = iface->interfaces; - for (; *itr != NULL; itr++) - _eina_model_description_ifaces_populate(desc, *itr); - } -} - -static Eina_Bool -_eina_model_description_ifaces_fill(Eina_Model_Description *desc) -{ - const Eina_Model_Type **titr, **titr_end; - unsigned int count; - - titr = desc->cache.types; - titr_end = titr + desc->total.types; - - /* naively count all interfaces, remove duplicates later */ - for (count = 0; titr < titr_end; titr++) - { - const Eina_Model_Type *type = *titr; - const Eina_Model_Interface **iitr = type->interfaces; - if (!type->interfaces) continue; - - for (; *iitr != NULL; iitr++) - if (!_eina_model_description_ifaces_validate_and_count(*iitr, &count)) - return EINA_FALSE; - } - if (count == 0) - { - desc->cache.ifaces = NULL; - desc->total.ifaces = 0; - return EINA_TRUE; - } - - desc->cache.ifaces = malloc(count * sizeof(Eina_Model_Interface *)); - EINA_SAFETY_ON_NULL_RETURN_VAL(desc->cache.ifaces, EINA_FALSE); - - titr = desc->cache.types; - desc->total.ifaces = 0; - for (; titr < titr_end; titr++) - { - const Eina_Model_Type *type = *titr; - const Eina_Model_Interface **iitr = type->interfaces; - - if (!type->interfaces) continue; - - for (; *iitr != NULL; iitr++) - _eina_model_description_ifaces_populate(desc, *iitr); - } - - return _eina_model_description_ifaces_fix(desc); -} - -static Eina_Bool -_eina_model_description_privates_fill(Eina_Model_Description *desc) -{ - unsigned int i; - - desc->total.privates = desc->total.types + desc->total.ifaces; - desc->cache.privates = malloc(desc->total.privates * - sizeof(Eina_Model_Provider)); - EINA_SAFETY_ON_NULL_RETURN_VAL(desc->cache.privates, EINA_FALSE); - - desc->total.size = 0; - - for (i = 0; i < desc->total.types; i++) - { - const Eina_Model_Type *type = desc->cache.types[i]; - desc->cache.privates[i].type = type; - if (type->private_size > 0) - { - unsigned int size = type->private_size; - if (size % sizeof(void *) != 0) - size += sizeof(void *) - (size % sizeof(void *)); - desc->total.size += size; - } - } - - for (i = 0; i < desc->total.ifaces; i++) - { - const Eina_Model_Interface *iface = desc->cache.ifaces[i]; - desc->cache.privates[desc->total.types + i].iface = iface; - if (iface->private_size > 0) - { - unsigned int size = iface->private_size; - if (size % sizeof(void *) != 0) - size += sizeof(void *) - (size % sizeof(void *)); - desc->total.size += size; - } - } - - return EINA_TRUE; -} - -static int -_eina_model_description_events_cmp(const void *pa, const void *pb) -{ - const Eina_Model_Event_Description_Cache *a = pa, *b = pb; - return strcmp(a->name, b->name); -} - -static int -_eina_model_description_events_find(const Eina_Model_Description *desc, const Eina_Model_Event_Description *query) -{ - unsigned int i; - for (i = 0; i < desc->total.events; i++) - { - const Eina_Model_Event_Description_Cache *itr = desc->cache.events + i; - if ((itr->name == query->name) || (strcmp(itr->name, query->name) == 0)) - return i; - } - - return -1; -} - -/* warn and remove duplicates, sort items to speed up lookups */ -static Eina_Bool -_eina_model_description_events_fill(Eina_Model_Description *desc) -{ - unsigned int i, count = 0, type_events; - - for (i = 0; i < desc->total.types; i++) - { - const Eina_Model_Event_Description *itr = desc->cache.types[i]->events; - if (!itr) continue; - for (; itr->name != NULL; itr++) - { - count++; - } - } - type_events = count; - - for (i = 0; i < desc->total.ifaces; i++) - { - const Eina_Model_Event_Description *itr = desc->cache.ifaces[i]->events; - if (!itr) continue; - for (; itr->name != NULL; itr++) - count++; - } - - if (count == 0) - { - desc->cache.events = NULL; - desc->total.events = 0; - return EINA_TRUE; - } - - desc->cache.events = malloc(count * - sizeof(Eina_Model_Event_Description_Cache)); - EINA_SAFETY_ON_NULL_RETURN_VAL(desc->cache.events, EINA_FALSE); - desc->total.events = 0; - - for (i = 0; i < desc->total.types; i++) - { - const Eina_Model_Type *mtype = desc->cache.types[i]; - const Eina_Model_Event_Description *itr = mtype->events; - if (!itr) continue; - for (; itr->name != NULL; itr++) - { - int j = _eina_model_description_events_find(desc, itr); - if (j >= 0) - { - const Eina_Model_Event_Description_Cache *o = desc->cache.events + j; - const Eina_Model_Type *omtype = o->provider.type; - WRN("Ignored duplicated event '%s' (type: '%s') from " - "model type %p (%s): already exists with type '%s' " - "from model type %p (%s)", - itr->name, - itr->type ? itr->type : "", - mtype, mtype->name, - o->desc->type ? o->desc->type : "", - omtype, omtype->name); - continue; - } - - desc->cache.events[desc->total.events].name = itr->name; - desc->cache.events[desc->total.events].desc = itr; - desc->cache.events[desc->total.events].provider.type = mtype; - desc->total.events++; - } - } - - for (i = 0; i < desc->total.ifaces; i++) - { - const Eina_Model_Interface *miface = desc->cache.ifaces[i]; - const Eina_Model_Event_Description *itr = desc->cache.ifaces[i]->events; - if (!itr) continue; - for (; itr->name != NULL; itr++) - { - int j = _eina_model_description_events_find(desc, itr); - if (j >= 0) - { - const Eina_Model_Event_Description_Cache *o = desc->cache.events + j; - if ((unsigned)j < type_events) - { - const Eina_Model_Type *omtype = o->provider.type; - WRN("Ignored duplicated event '%s' (type: '%s') from " - "model interface %p (%s): already exists with " - "type '%s' from model interface %p (%s)", - itr->name, - itr->type ? itr->type : "", - miface, miface->name, - o->desc->type ? o->desc->type : "", - omtype, omtype->name); - } - else - { - const Eina_Model_Interface *omiface = o->provider.iface; - WRN("Ignored duplicated event '%s' (iface: '%s') from " - "model interface %p (%s): already exists with " - "interface '%s' from model interface %p (%s)", - itr->name, - itr->type ? itr->type : "", - miface, miface->name, - o->desc->type ? o->desc->type : "", - omiface, omiface->name); - } - continue; - } - - desc->cache.events[desc->total.events].name = itr->name; - desc->cache.events[desc->total.events].desc = itr; - desc->cache.events[desc->total.events].provider.iface = miface; - desc->total.events++; - } - } - - qsort(desc->cache.events, desc->total.events, - sizeof(Eina_Model_Event_Description_Cache), - _eina_model_description_events_cmp); - - return EINA_TRUE; -} - -static const Eina_Model_Description * -_eina_model_description_get_internal(const Eina_Model_Type *type) -{ - Eina_Model_Description *desc; - - desc = eina_hash_find(_eina_model_descriptions, &type); - if (desc) - { - desc->refcount++; - return desc; - } - - desc = calloc(1, sizeof(Eina_Model_Description)); - EINA_SAFETY_ON_NULL_RETURN_VAL(desc, NULL); - - if (!_eina_model_description_type_fill(desc, type)) goto failed_type; - if (!_eina_model_description_ifaces_fill(desc)) goto failed_ifaces; - if (!_eina_model_description_privates_fill(desc)) goto failed_privates; - if (!_eina_model_description_events_fill(desc)) goto failed_events; - if (!eina_hash_add(_eina_model_descriptions, &type, desc)) goto failed_hash; - - desc->refcount = 1; - return desc; - - failed_hash: - free(desc->cache.events); - failed_events: - free(desc->cache.privates); - failed_privates: - free(desc->cache.ifaces); - failed_ifaces: - free(desc->cache.types); - free(desc->ops.type.extension); - failed_type: - free(desc); - return NULL; -} - -static void -_eina_model_description_dispose_internal(Eina_Model_Description *desc) -{ - const Eina_Model_Type *type; - - EINA_SAFETY_ON_FALSE_RETURN(desc->refcount > 0); - desc->refcount--; - if (desc->refcount > 0) return; - - type = desc->cache.types[0]; - if (!eina_hash_del_by_key(_eina_model_descriptions, &type)) - ERR("Cannot find type %p (%s) in descriptions hash!", - type, type->name); - - INF("Disposed model description for type %p (%s)", type, type->name); - - free(desc->ops.type.extension); - free(desc->cache.types); - free(desc->cache.ifaces); - free(desc->cache.privates); - free(desc->cache.events); - free(desc); -} - -static const Eina_Model_Description * -_eina_model_description_get(const Eina_Model_Type *type) -{ - const Eina_Model_Description *desc; - - eina_lock_take(&_eina_model_descriptions_lock); - desc = _eina_model_description_get_internal(type); - eina_lock_release(&_eina_model_descriptions_lock); - - return desc; -} - -static void -_eina_model_description_dispose(const Eina_Model_Description *desc) -{ - eina_lock_take(&_eina_model_descriptions_lock); - _eina_model_description_dispose_internal((Eina_Model_Description *)desc); - eina_lock_release(&_eina_model_descriptions_lock); -} - -static inline int -_eina_model_description_event_id_find(const Eina_Model_Description *desc, const char *event_name) -{ - const Eina_Model_Event_Description_Cache *cache; - Eina_Model_Event_Description_Cache criteria_match; - - criteria_match.name = event_name; - cache = bsearch(&criteria_match, desc->cache.events, desc->total.events, - sizeof(Eina_Model_Event_Description_Cache), - _eina_model_description_events_cmp); - if (!cache) - { - ERR("No event named %s for type %p (%s)", event_name, - desc->cache.types[0], desc->cache.types[0]->name); - return -1; - } - - return cache - desc->cache.events; -} - -/* - * Model management and book keeping - */ -typedef struct _Eina_Model_Event_Listener Eina_Model_Event_Listener; -struct _Eina_Model_Event_Listener -{ - EINA_INLIST; - Eina_Model_Event_Cb cb; - const void *data; - Eina_Bool deleted:1; -}; - -struct _Eina_Model -{ - const Eina_Model_Description *desc; /**< optimized model description */ - struct { - Eina_Inlist **entries; /**< connected/listeners for each event, array of lists of Eina_Model_Event_Listener */ - Eina_List **deleted; /**< deleted listeners while was walking. array of lists of Eina_Model_Event_Listener with deleted flag */ - int *freeze; /**< freeze count for each event */ - int walking; /**< increased while walking entries lists */ - } listeners; - void **privates; /**< private data per type and interface, each level gets its own stuff */ - Eina_Inlist *xrefs; /**< if EINA_MODEL_DEBUG and eina_model_xref() is used */ - int refcount; /**< number of users of this model instance */ - Eina_Bool deleted:1; /**< if deleted but still have references */ - EINA_MAGIC -}; - -static inline Eina_Bool -_eina_model_type_check(const Eina_Model_Type *type) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL(type->version == EINA_MODEL_TYPE_VERSION, - EINA_FALSE); - return EINA_TRUE; -} - -/* find in type hierarchy the first one that the given offset is not a null - * pointer. Use this to discover which method to call on a parent. - */ -static const void * -_eina_model_type_find_offset(const Eina_Model_Type *type, unsigned int offset) -{ - const unsigned char *ptr = (const unsigned char *)type; - const void **addr = (const void **)(ptr + offset); - - if (*addr) return *addr; - if (!type->parent) return NULL; - return _eina_model_type_find_offset(type->parent, offset); -} - -/* find in interface hierarchy the first one that the given offset is - * not a null pointer. Use this to discover which method to call on a - * parent. - * - * TODO: Keep Eina_Model_Interface_Description with topological sorted - * entries for each interface? - * I smell problems with the current code in more complex - * situations (k-s) - * - * iface1 - * ^ - * | - * .---------+---------. - * | | | - * iface2 iface3 iface4 - * ^ ^ ^ - * | | | - * `---------+---------' - * | - * iface5 - * - * It should look: iface5 -> iface2 -> iface3 -> iface4 -> iface1 - * Now it does: iface5 -> iface2 -> iface1 -> iface3 -> iface1 -> iface4 -> iface1 - * - * - * iface1 - * ^ - * | - * iface2 - * ^ - * | - * .---------+---------. - * | | - * iface3 iface4 - * ^ ^ - * | | - * `---------+---------' - * | - * iface5 - * - * It should look: iface5 -> iface3 -> iface4 -> iface2 -> iface1 - * Now it does: iface5 -> iface3 -> iface2 -> iface1 -> iface4 -> iface2 -> iface1 - * - * - * iface1 iface2 - * ^ ^ - * | | - * `---------+---------' - * | - * iface3 - * - * It should look: iface3 -> iface1 -> iface2 - * Now it does: iface3 -> iface1 -> iface2 - * - * For the common case it should work, let's see. - */ -static const void * -_eina_model_interface_find_offset(const Eina_Model_Interface *iface, unsigned int offset) -{ - const Eina_Model_Interface **itr; - const unsigned char *ptr = (const unsigned char *)iface; - const void **addr = (const void **)(ptr + offset); - - if (offset + sizeof(void *) > iface->interface_size) return NULL; - - if (*addr) return *addr; - if (!iface->interfaces) return NULL; - - for (itr = iface->interfaces; *itr != NULL; itr++) - { - const void *r = _eina_model_interface_find_offset(*itr, offset); - if (r) - return r; - } - - return NULL; -} - -static void -_eina_model_event_callback_free_deleted(Eina_Model *model) -{ - unsigned int i; - - for (i = 0; i < model->desc->total.events; i++) - { - Eina_Model_Event_Listener *el; - EINA_LIST_FREE(model->listeners.deleted[i], el) - { - model->listeners.entries[i] = eina_inlist_remove - (model->listeners.entries[i], EINA_INLIST_GET(el)); - _eina_model_inner_free(sizeof(Eina_Model_Event_Listener), el); - } - } - - _eina_model_inner_free(model->desc->total.events * sizeof(Eina_List *), - model->listeners.deleted); - model->listeners.deleted = NULL; -} - -static inline Eina_Bool -_eina_model_event_callback_call(Eina_Model *model, const char *name, const void *event_info) -{ - Eina_Inlist *lst; - Eina_Model_Event_Listener *el; - const Eina_Model_Event_Description *ev_desc; - int event_id = _eina_model_description_event_id_find(model->desc, name); - - if (event_id < 0) return EINA_FALSE; - if (!model->listeners.entries) return EINA_TRUE; - - if ((model->listeners.freeze) && (model->listeners.freeze[event_id])) - { - DBG("Ignored event callback '%s' of model %p (%s): frozen", - name, model, model->desc->cache.types[0]->name); - return EINA_TRUE; - } - - lst = model->listeners.entries[event_id]; - if (!lst) return EINA_TRUE; - - ev_desc = model->desc->cache.events[event_id].desc; - - model->listeners.walking++; - EINA_INLIST_FOREACH(lst, el) - { - if (el->deleted) continue; - el->cb((void *)el->data, model, ev_desc, (void *)event_info); - } - model->listeners.walking--; - - if ((model->listeners.walking == 0) && (model->listeners.deleted)) - _eina_model_event_callback_free_deleted(model); - - return EINA_FALSE; -} - -static const char EINA_ERROR_MODEL_FAILED_STR[] = "Model check failed."; -static const char EINA_ERROR_MODEL_METHOD_MISSING_STR[] = "Model method is missing."; -static const char EINA_MAGIC_MODEL_STR[] = "Eina Model"; - -static void _eina_model_unref(Eina_Model *model); - -/** - * @endcond - */ - -/* EINA_MODEL_TYPE_BASE: base of all other types **********************/ - -static Eina_Bool -_eina_model_type_base_setup(Eina_Model *model) -{ - DBG("base setup of %p", model); - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_type_base_flush(Eina_Model *model) -{ - DBG("base flush of %p", model); - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_type_base_constructor(Eina_Model *model) -{ - DBG("base constructor of %p", model); - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_type_base_destructor(Eina_Model *model) -{ - DBG("base destructor of %p", model); - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_type_base_properties_copy(const Eina_Model *model, Eina_Model *copy) -{ - Eina_List *l, *props = eina_model_properties_names_list_get(model); - const char *name; - EINA_LIST_FOREACH(props, l, name) - { - Eina_Value tmp; - if (!eina_model_property_get(model, name, &tmp)) - { - ERR("Could not get property %s from model %p (%s)", - name, model, model->desc->cache.types[0]->name); - eina_model_properties_names_list_free(props); - return EINA_FALSE; - } - if (!eina_model_property_set(copy, name, &tmp)) - { - ERR("Could not set property %s on model %p (%s)", - name, copy, copy->desc->cache.types[0]->name); - eina_value_flush(&tmp); - eina_model_properties_names_list_free(props); - return EINA_FALSE; - } - eina_value_flush(&tmp); - } - eina_model_properties_names_list_free(props); - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_type_base_children_copy(const Eina_Model *model, Eina_Model *copy) -{ - int i, count = eina_model_child_count(model); - - if (count < 0) - { - ERR("Could not get children count of model %p (%s)", - model, model->desc->cache.types[0]->name); - return EINA_FALSE; - } - - for (i = 0; i < count; i++) - { - Eina_Model *child = eina_model_child_get(model, i); - Eina_Bool ret; - - if (!child) - { - ERR("Could not get child #%d from model %p (%s)", - i, model, model->desc->cache.types[0]->name); - return EINA_FALSE; - } - - ret = eina_model_child_insert_at(copy, i, child); - _eina_model_unref(child); - - if (!ret) - { - ERR("Could not set child #%d on model %p (%s)", - i, copy, copy->desc->cache.types[0]->name); - return EINA_FALSE; - } - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_type_base_copy(const Eina_Model *model, Eina_Model *copy) -{ - DBG("base copy of %p to %p", model, copy); - - return _eina_model_type_base_properties_copy(model, copy) && - _eina_model_type_base_children_copy(model, copy); -} - -static Eina_Bool -_eina_model_type_base_children_deep_copy(const Eina_Model *model, Eina_Model *copy) -{ - int i, count = eina_model_child_count(model); - - if (count < 0) - { - ERR("Could not get children count of model %p (%s)", - model, model->desc->cache.types[0]->name); - return EINA_FALSE; - } - - for (i = 0; i < count; i++) - { - Eina_Model *child_copy, *child = eina_model_child_get(model, i); - Eina_Bool ret; - - if (!child) - { - ERR("Could not get child #%d from model %p (%s)", - i, model, model->desc->cache.types[0]->name); - return EINA_FALSE; - } - - child_copy = eina_model_deep_copy(child); - if (!child_copy) - { - ERR("Could not deep copy child #%d %p (%s) from model %p (%s)", i, - child, child->desc->cache.types[0]->name, - model, model->desc->cache.types[0]->name); - _eina_model_unref(child); - return EINA_FALSE; - } - _eina_model_unref(child); - - ret = eina_model_child_insert_at(copy, i, child_copy); - _eina_model_unref(child_copy); - - if (!ret) - { - ERR("Could not set child #%d on model %p (%s)", - i, copy, copy->desc->cache.types[0]->name); - return EINA_FALSE; - } - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_type_base_deep_copy(const Eina_Model *model, Eina_Model *copy) -{ - DBG("base deep copy of %p to %p", model, copy); - - return _eina_model_type_base_properties_copy(model, copy) && - _eina_model_type_base_children_deep_copy(model, copy); -} - -static Eina_Bool -_eina_model_type_base_properties_compare(const Eina_Model *a, const Eina_Model *b, int *cmp) -{ - Eina_List *al, *aprops = eina_model_properties_names_list_get(a); - Eina_List *bl, *bprops = eina_model_properties_names_list_get(b); - Eina_List *l, *props = NULL; - const char *aname, *bname, *name; - Eina_Bool ret = EINA_TRUE; - - EINA_LIST_FOREACH(aprops, al, aname) - { - EINA_LIST_FOREACH(bprops, bl, bname) - if (strcmp(aname, bname) == 0) - { - props = eina_list_append(props, aname); - break; - } - } - - *cmp = 0; - EINA_LIST_FOREACH(props, l, name) - { - Eina_Value atmp, btmp; - - if (!eina_model_property_get(a, name, &atmp)) - { - ERR("Could not get property %s from model %p (%s)", - name, a, a->desc->cache.types[0]->name); - ret = EINA_FALSE; - *cmp = -1; - break; - } - - if (!eina_model_property_get(b, name, &btmp)) - { - ERR("Could not get property %s from model %p (%s)", - name, b, b->desc->cache.types[0]->name); - ret = EINA_FALSE; - *cmp = -1; - eina_value_flush(&atmp); - break; - } - - *cmp = eina_value_compare(&atmp, &btmp); - if (eina_error_get() != 0) - { - char *astr = eina_value_to_string(&atmp); - char *bstr = eina_value_to_string(&btmp); - ERR("Could not compare property %s: %s=%s, %s=%s", name, - eina_value_type_name_get(eina_value_type_get(&atmp)), astr, - eina_value_type_name_get(eina_value_type_get(&btmp)), bstr); - free(astr); - free(bstr); - ret = EINA_FALSE; - *cmp = -1; - } - - eina_value_flush(&atmp); - eina_value_flush(&btmp); - - if ((!ret) || (*cmp != 0)) - break; - } - - if ((ret) && (*cmp == 0)) - { - int acount = eina_list_count(aprops); - int bcount = eina_list_count(bprops); - - if (acount < bcount) - *cmp = -1; - else if (acount > bcount) - *cmp = 1; - } - - eina_model_properties_names_list_free(aprops); - eina_model_properties_names_list_free(bprops); - eina_list_free(props); - return ret; -} - -static Eina_Bool -_eina_model_type_base_children_compare(const Eina_Model *a, const Eina_Model *b, int *cmp) -{ - int acount = eina_model_child_count(a); - int bcount = eina_model_child_count(b); - int i, count; - Eina_Bool ret = EINA_TRUE; - - if (acount < 0) - { - ERR("Could not get children count of model %p (%s)", - a, a->desc->cache.types[0]->name); - return EINA_FALSE; - } - if (bcount < 0) - { - ERR("Could not get children count of model %p (%s)", - b, b->desc->cache.types[0]->name); - return EINA_FALSE; - } - - if (acount < bcount) - count = acount; - else - count = bcount; - - for (i = 0; i < count; i++) - { - Eina_Model *achild, *bchild; - - achild = eina_model_child_get(a, i); - if (!achild) - { - ERR("Could not get child #%d from model %p (%s)", - i, a, a->desc->cache.types[0]->name); - *cmp = -1; - return EINA_FALSE; - } - - bchild = eina_model_child_get(b, i); - if (!bchild) - { - ERR("Could not get child #%d from model %p (%s)", - i, b, b->desc->cache.types[0]->name); - *cmp = -1; - _eina_model_unref(achild); - return EINA_FALSE; - } - - *cmp = eina_model_compare(achild, bchild); - if (eina_error_get()) - { - ERR("Could not compare children #%d %p (%s) and %p (%s) " - "from models %p (%s) and %p (%s)", i, - achild, - eina_model_type_name_get(eina_model_type_get(achild)), - bchild, - eina_model_type_name_get(eina_model_type_get(bchild)), - a, a->desc->cache.types[0]->name, - b, b->desc->cache.types[0]->name); - ret = EINA_FALSE; - } - _eina_model_unref(achild); - _eina_model_unref(bchild); - - if ((!ret) || (*cmp != 0)) - break; - } - - if ((ret) && (*cmp == 0)) - { - if (acount < bcount) - *cmp = -1; - else if (acount > bcount) - *cmp = 1; - } - - return ret; -} - -static Eina_Bool -_eina_model_type_base_compare(const Eina_Model *a, const Eina_Model *b, int *cmp) -{ - *cmp = 0; - DBG("base compare of %p and %p", a, b); - - if (!_eina_model_type_base_properties_compare(a, b, cmp)) - return EINA_FALSE; - - if (*cmp != 0) - return EINA_TRUE; - - return _eina_model_type_base_children_compare(a, b, cmp); -} - -static int -_eina_model_type_base_child_count(const Eina_Model *model) -{ - DBG("base child_count of %p", model); - return 0; -} - -static int -_eina_model_type_base_child_find(const Eina_Model *model, unsigned int start_position, const Eina_Model *other) -{ - int x = eina_model_child_count(model); - unsigned int i, count; - - DBG("base child_find of %p, %d children", model, x); - - if (x < 0) - return -1; - - count = x; - for (i = start_position; i < count; i++) - { - Eina_Model *current = eina_model_child_get(model, i); - if (current) - { - _eina_model_unref(current); /* we'll not use it's value anyway */ - if (current == other) - return i; - } - } - - return -1; -} - -static int -_eina_model_type_base_child_criteria_match(const Eina_Model *model, unsigned int start_position, Eina_Each_Cb match, const void *user_data) -{ - int x = eina_model_child_count(model); - unsigned int i, count; - - DBG("base child_criteria_match of %p, %d children", model, x); - - if (x < 0) - return -1; - - count = x; - for (i = start_position; i < count; i++) - { - Eina_Model *current = eina_model_child_get(model, i); - if (current) - { - Eina_Bool r = match(model, current, (void *)user_data); - _eina_model_unref(current); - if (r) - return i; - } - } - - return -1; -} - -typedef struct _Eina_Iterator_Model_Base Eina_Iterator_Model_Base; -struct _Eina_Iterator_Model_Base -{ - Eina_Iterator base; - Eina_Model *model; - unsigned int current; - unsigned int end; -}; - -static Eina_Bool -_eina_model_type_base_child_iterator_next(Eina_Iterator *base, void **data) -{ - Eina_Iterator_Model_Base *it; - - it = (Eina_Iterator_Model_Base *)base; - if (it->current >= it->end) - return EINA_FALSE; - - *data = eina_model_child_get(it->model, it->current); - if (!*data) - return EINA_FALSE; - - it->current++; - return EINA_TRUE; -} - -static void * -_eina_model_type_base_child_iterator_get_container(Eina_Iterator *base) -{ - Eina_Iterator_Model_Base *it; - it = (Eina_Iterator_Model_Base *)base; - return it->model; -} - -static void -_eina_model_type_base_child_iterator_free(Eina_Iterator *base) -{ - Eina_Iterator_Model_Base *it; - it = (Eina_Iterator_Model_Base *)base; - eina_model_xunref(it->model, it); - free(it); -} - -static Eina_Iterator * -_eina_model_type_base_child_iterator_get(Eina_Model *model, unsigned int start, unsigned int count) -{ - Eina_Iterator_Model_Base *it = calloc(1, sizeof(*it)); - EINA_SAFETY_ON_NULL_RETURN_VAL(it, NULL); - - EINA_MAGIC_SET(&it->base, EINA_MAGIC_ITERATOR); - it->base.version = EINA_ITERATOR_VERSION; - it->base.next = _eina_model_type_base_child_iterator_next; - it->base.get_container = _eina_model_type_base_child_iterator_get_container; - it->base.free = _eina_model_type_base_child_iterator_free; - - it->model = eina_model_xref(model, it, "eina_model_child_slice_iterator_get"); - it->current = start; - it->end = start + count; - - return &it->base; -} - -typedef struct _Eina_Iterator_Model_Base_Reversed Eina_Iterator_Model_Base_Reversed; -struct _Eina_Iterator_Model_Base_Reversed -{ - Eina_Iterator base; - Eina_Model *model; - unsigned int current; - unsigned int end; -}; - -static Eina_Bool -_eina_model_type_base_child_reversed_iterator_next(Eina_Iterator *base, void **data) -{ - Eina_Iterator_Model_Base_Reversed *it; - - it = (Eina_Iterator_Model_Base_Reversed *)base; - if (it->current == it->end) - return EINA_FALSE; - - it->current--; - *data = eina_model_child_get(it->model, it->current); - if (!*data) - return EINA_FALSE; - - return EINA_TRUE; -} - -static void * -_eina_model_type_base_child_reversed_iterator_get_container(Eina_Iterator *base) -{ - Eina_Iterator_Model_Base_Reversed *it; - it = (Eina_Iterator_Model_Base_Reversed *)base; - return it->model; -} - -static void -_eina_model_type_base_child_reversed_iterator_free(Eina_Iterator *base) -{ - Eina_Iterator_Model_Base_Reversed *it; - it = (Eina_Iterator_Model_Base_Reversed *)base; - eina_model_xunref(it->model, it); - free(it); -} - -static Eina_Iterator * -_eina_model_type_base_child_reversed_iterator_get(Eina_Model *model, unsigned int start, unsigned int count) -{ - Eina_Iterator_Model_Base_Reversed *it; - int children_count; - - children_count = eina_model_child_count(model); - if (children_count < 0) - return NULL; - - if (start + count > (unsigned int)children_count) - { - if (start >= (unsigned int)children_count) - count = 0; - else - count = children_count - start; - } - - it = calloc(1, sizeof(*it)); - EINA_SAFETY_ON_NULL_RETURN_VAL(it, NULL); - EINA_MAGIC_SET(&it->base, EINA_MAGIC_ITERATOR); - it->base.version = EINA_ITERATOR_VERSION; - it->base.next = _eina_model_type_base_child_reversed_iterator_next; - it->base.get_container = _eina_model_type_base_child_reversed_iterator_get_container; - it->base.free = _eina_model_type_base_child_reversed_iterator_free; - - it->model = eina_model_xref(model, it, "eina_model_child_slice_reversed_iterator_get"); - it->current = start + count; - it->end = start; - - return &it->base; -} - -typedef struct _Eina_Iterator_Model_Base_Sorted Eina_Iterator_Model_Base_Sorted; -struct _Eina_Iterator_Model_Base_Sorted -{ - Eina_Iterator base; - Eina_Model *model; - unsigned int current; - unsigned int count; - Eina_Model *elements[]; -}; - -static Eina_Bool -_eina_model_type_base_child_sorted_iterator_next(Eina_Iterator *base, void **data) -{ - Eina_Iterator_Model_Base_Sorted *it; - - it = (Eina_Iterator_Model_Base_Sorted *)base; - if (it->current == it->count) - return EINA_FALSE; - - *data = eina_model_ref(it->elements[it->current]); - it->current++; - return EINA_TRUE; -} - -static void * -_eina_model_type_base_child_sorted_iterator_get_container(Eina_Iterator *base) -{ - Eina_Iterator_Model_Base_Sorted *it; - it = (Eina_Iterator_Model_Base_Sorted *)base; - return it->model; -} - -static void -_eina_model_type_base_child_sorted_iterator_free(Eina_Iterator *base) -{ - Eina_Iterator_Model_Base_Sorted *it; - unsigned int i; - it = (Eina_Iterator_Model_Base_Sorted *)base; - eina_model_xunref(it->model, it); - - for (i = 0; i < it->count; i++) - _eina_model_unref(it->elements[i]); - - free(it); -} - -static Eina_Iterator * -_eina_model_type_base_child_sorted_iterator_get(Eina_Model *model, unsigned int start, unsigned int count, Eina_Compare_Cb compare) -{ - Eina_Iterator_Model_Base_Sorted *it; - int children_count; - unsigned int i; - - children_count = eina_model_child_count(model); - if (children_count < 0) - return NULL; - - if (start + count > (unsigned int)children_count) - { - if (start >= (unsigned int)children_count) - count = 0; - else - count = children_count - start; - } - - it = calloc(1, sizeof(*it) + count * sizeof(Eina_Model *)); - EINA_SAFETY_ON_NULL_RETURN_VAL(it, NULL); - EINA_MAGIC_SET(&it->base, EINA_MAGIC_ITERATOR); - it->base.version = EINA_ITERATOR_VERSION; - it->base.next = _eina_model_type_base_child_sorted_iterator_next; - it->base.get_container = _eina_model_type_base_child_sorted_iterator_get_container; - it->base.free = _eina_model_type_base_child_sorted_iterator_free; - - it->model = eina_model_xref(model, it, "eina_model_child_slice_sorted_iterator_get"); - it->current = 0; - it->count = count; - - for (i = 0; i < count; i++) - { - it->elements[i] = eina_model_child_get(model, i + start); - if (!it->elements[i]) - { - ERR("Failed to get child %u of model %p (%s)", - i + start, model, model->desc->cache.types[0]->name); - free(it); - return NULL; - } - } - - if (count > 1) - _eina_model_array_sort(it->elements, 0, count - 1, compare); - - return &it->base; -} - -typedef struct _Eina_Iterator_Model_Base_Filtered Eina_Iterator_Model_Base_Filtered; -struct _Eina_Iterator_Model_Base_Filtered -{ - Eina_Iterator base; - Eina_Model *model; - Eina_Each_Cb match; - const void *data; - unsigned int current; - unsigned int count; -}; - -static Eina_Bool -_eina_model_type_base_child_filtered_iterator_next(Eina_Iterator *base, void **data) -{ - Eina_Iterator_Model_Base_Filtered *it; - unsigned int *ret; - int i; - - it = (Eina_Iterator_Model_Base_Filtered *)base; - if (it->count == 0) return EINA_FALSE; - - i = eina_model_child_criteria_match(it->model, it->current, it->match, it->data); - if (i < 0) return EINA_FALSE; - - it->current = i + 1; - it->count--; - ret = (unsigned int *)data; - *ret = i; - return EINA_TRUE; -} - -static void * -_eina_model_type_base_child_filtered_iterator_get_container(Eina_Iterator *base) -{ - Eina_Iterator_Model_Base_Filtered *it; - it = (Eina_Iterator_Model_Base_Filtered *)base; - return it->model; -} - -static void -_eina_model_type_base_child_filtered_iterator_free(Eina_Iterator *base) -{ - Eina_Iterator_Model_Base_Filtered *it; - it = (Eina_Iterator_Model_Base_Filtered *)base; - eina_model_xunref(it->model, it); - free(it); -} - -static Eina_Iterator * -_eina_model_type_base_child_filtered_iterator_get(Eina_Model *model, unsigned int start, unsigned int count, Eina_Each_Cb match, const void *data) -{ - Eina_Iterator_Model_Base_Filtered *it = calloc(1, sizeof(*it)); - EINA_SAFETY_ON_NULL_RETURN_VAL(it, NULL); - - EINA_MAGIC_SET(&it->base, EINA_MAGIC_ITERATOR); - it->base.version = EINA_ITERATOR_VERSION; - it->base.next = _eina_model_type_base_child_filtered_iterator_next; - it->base.get_container = _eina_model_type_base_child_filtered_iterator_get_container; - it->base.free = _eina_model_type_base_child_filtered_iterator_free; - - it->model = eina_model_xref(model, it, "eina_model_child_slice_filtered_iterator_get"); - it->match = match; - it->data = data; - it->current = start; - it->count = count; - - return &it->base; -} - -static char * -_eina_model_type_base_to_string(const Eina_Model *model) -{ - Eina_List *l, *props; - const char *name; - Eina_Strbuf *str; - Eina_Bool first; - int i, count; - char *ret; - - str = eina_strbuf_new(); - EINA_SAFETY_ON_NULL_RETURN_VAL(str, NULL); - - eina_strbuf_append_printf(str, "%s({", model->desc->cache.types[0]->name); - - props = eina_model_properties_names_list_get(model); - props = eina_list_sort(props, 0, EINA_COMPARE_CB(strcmp)); - - first = EINA_TRUE; - EINA_LIST_FOREACH(props, l, name) - { - Eina_Value val; - - if (!first) - eina_strbuf_append_printf(str, ", %s: ", name); - else - { - eina_strbuf_append_printf(str, "%s: ", name); - first = EINA_FALSE; - } - - if (!eina_model_property_get(model, name, &val)) - eina_strbuf_append_char(str, '?'); - else - { - char *tmp = eina_value_to_string(&val); - eina_strbuf_append(str, tmp ? tmp : "?"); - free(tmp); - eina_value_flush(&val); - } - } - eina_list_free(props); - - eina_strbuf_append(str, "}, ["); - - count = eina_model_child_count(model); - first = EINA_TRUE; - for (i = 0; i < count; i++) - { - Eina_Model *c = eina_model_child_get(model, i); - if (!c) - { - if (!first) - eina_strbuf_append(str, ", ?"); - else - { - eina_strbuf_append_char(str, '?'); - first = EINA_FALSE; - } - } - else - { - char *tmp = eina_model_to_string(c); - if (!first) - eina_strbuf_append_printf(str, ", %s", tmp ? tmp : "?"); - else - { - eina_strbuf_append(str, tmp ? tmp : "?"); - first = EINA_FALSE; - } - free(tmp); - _eina_model_unref(c); - } - } - - eina_strbuf_append(str, "])"); - - ret = eina_strbuf_string_steal(str); - eina_strbuf_free(str); - - return ret; -} - -static const Eina_Model_Event_Description _eina_model_type_base_events[] = { - EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_deleted, "", "model was deleted"), - EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_freed, "", "model memory was released"), - EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_property_set, "s", "model data was set, data name given as event information."), - EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_property_del, "s", "model data was deleted, data name given as event information."), - EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_children_changed, "", "model children changed (deleted, inserted)."), - EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_child_inserted, "u", "model child was inserted, child position is given."), - EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_child_set, "u", "model child was set, child position is given."), - EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_child_del, "u", "model child was deleted, child position is given."), - EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_loaded, "", "model was loaded"), - EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_unloaded, "", "model was unloaded"), - EINA_MODEL_EVENT_DESCRIPTION_SENTINEL -}; - -static const Eina_Model_Type _EINA_MODEL_TYPE_BASE = { - EINA_MODEL_TYPE_VERSION, - 0, /* there is no private data */ - sizeof(Eina_Model_Type), - "Eina_Model_Type_Base", - NULL, /* should be the only type with NULL here! */ - NULL, /* no interfaces implemented */ - _eina_model_type_base_events, - _eina_model_type_base_setup, - _eina_model_type_base_flush, - _eina_model_type_base_constructor, - _eina_model_type_base_destructor, - _eina_model_type_base_copy, - _eina_model_type_base_deep_copy, - _eina_model_type_base_compare, - NULL, /* no load */ - NULL, /* no unload */ - NULL, /* no property value get */ - NULL, /* no property value set */ - NULL, /* no property del */ - NULL, /* no properties names list */ - _eina_model_type_base_child_count, - NULL, /* no child get */ - NULL, /* no child set */ - NULL, /* no child del */ - NULL, /* no child insert */ - _eina_model_type_base_child_find, - _eina_model_type_base_child_criteria_match, - NULL, /* no child sort */ - _eina_model_type_base_child_iterator_get, - _eina_model_type_base_child_reversed_iterator_get, - _eina_model_type_base_child_sorted_iterator_get, - _eina_model_type_base_child_filtered_iterator_get, - _eina_model_type_base_to_string, - NULL, /* extension pointer */ - NULL, /* extension pointer */ - NULL, /* extension pointer */ - NULL /* extension pointer */ -}; - -/* - * EINA_MODEL_TYPE_MIXIN: - * - * Mix-in is a type that uses 2 interfaces, one for properties, - * another for children. Users should inherit this model and implement - * at least onf of the interfaces to get an usable model without - * defining the methods. - */ - -static const char _EINA_MODEL_INTERFACE_NAME_PROPERTIES[] = "Eina_Model_Interface_Properties"; -static const char _EINA_MODEL_INTERFACE_NAME_CHILDREN[] = "Eina_Model_Interface_Children"; - -typedef struct _Eina_Model_Type_Mixin_Data Eina_Model_Type_Mixin_Data; -struct _Eina_Model_Type_Mixin_Data -{ - /* just keep interfaces to avoid lookups */ - const Eina_Model_Interface *if_properties; - const Eina_Model_Interface *if_children; -}; - -static Eina_Bool -_eina_model_type_mixin_setup(Eina_Model *model) -{ - DBG("mix-in setup of %p", model); - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_type_mixin_flush(Eina_Model *model) -{ - DBG("mix-in flush of %p", model); - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_type_mixin_constructor(Eina_Model *model) -{ - Eina_Model_Type_Mixin_Data *priv = eina_model_type_private_data_get - (model, EINA_MODEL_TYPE_MIXIN); - - DBG("mix-in constructor of %p (priv=%p)", model, priv); - - priv->if_properties = eina_model_interface_get - (model, EINA_MODEL_INTERFACE_NAME_PROPERTIES); - if (priv->if_properties) - { - if (!eina_model_interface_constructor(priv->if_properties, model)) - { - ERR("Could not construct properties interface %p of %p (%s)", - model, priv->if_properties, model->desc->cache.types[0]->name); - return EINA_FALSE; - } - } - - priv->if_children = eina_model_interface_get - (model, EINA_MODEL_INTERFACE_NAME_CHILDREN); - if (priv->if_children) - { - if (!eina_model_interface_constructor(priv->if_children, model)) - { - ERR("Could not construct children interface %p of %p (%s)", - model, priv->if_children, model->desc->cache.types[0]->name); - return EINA_FALSE; - } - } - - if ((!priv->if_properties) && (!priv->if_children)) - { - ERR("Mix-in model %p (%s) does not implement properties or children " - "interfaces!", - model, model->desc->cache.types[0]->name); - return EINA_FALSE; - } - - return EINA_TRUE; -} - -#define EINA_MODEL_TYPE_MIXIN_GET(model) \ - Eina_Model_Type_Mixin_Data *priv = eina_model_type_private_data_get \ - (model, EINA_MODEL_TYPE_MIXIN) - -static Eina_Bool -_eina_model_type_mixin_destructor(Eina_Model *model) -{ - EINA_MODEL_TYPE_MIXIN_GET(model); - - DBG("mixin destructor of %p", model); - - if (priv->if_properties) - eina_model_interface_destructor(priv->if_properties, model); - - if (priv->if_children) - eina_model_interface_destructor(priv->if_children, model); - - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_type_mixin_compare(const Eina_Model *a, const Eina_Model *b, int *cmp) -{ - Eina_Bool ret = EINA_TRUE, did_prop = EINA_FALSE, did_child = EINA_FALSE; - - *cmp = 0; - - EINA_MODEL_TYPE_MIXIN_GET(a); - - if (priv->if_properties) - { - Eina_Bool (*compare)(const Eina_Model*, const Eina_Model*, int *) = - _eina_model_interface_find_offset - (priv->if_properties, - offsetof(Eina_Model_Interface_Properties, compare)); - - if (compare) - { - ret &= compare(a, b, cmp); - did_prop = EINA_TRUE; - } - } - - if ((ret) && (*cmp == 0)) - { - if (priv->if_children) - { - Eina_Bool (*compare)(const Eina_Model*, const Eina_Model*, int *) = - _eina_model_interface_find_offset - (priv->if_children, - offsetof(Eina_Model_Interface_Children, compare)); - - if (compare) - { - ret &= compare(a, b, cmp); - did_child = EINA_TRUE; - } - } - } - - if ((!did_prop) && (!did_child)) - return eina_model_type_compare(EINA_MODEL_TYPE_BASE, a, b, cmp); - - return ret; -} - -static Eina_Bool -_eina_model_type_mixin_load(Eina_Model *model) -{ - Eina_Bool ret = EINA_TRUE; - - EINA_MODEL_TYPE_MIXIN_GET(model); - - if (priv->if_properties) - ret &= eina_model_interface_properties_load(priv->if_properties, model); - - if (priv->if_children) - ret &= eina_model_interface_children_load(priv->if_children, model); - - return ret; -} - -static Eina_Bool -_eina_model_type_mixin_unload(Eina_Model *model) -{ - Eina_Bool ret = EINA_TRUE; - - EINA_MODEL_TYPE_MIXIN_GET(model); - - if (priv->if_properties) - ret &= eina_model_interface_properties_unload(priv->if_properties, model); - - if (priv->if_children) - ret &= eina_model_interface_children_unload(priv->if_children, model); - - return ret; -} - -static Eina_Bool -_eina_model_type_mixin_property_get(const Eina_Model *model, const char *name, Eina_Value *value) -{ - Eina_Bool ret = EINA_FALSE; - - EINA_MODEL_TYPE_MIXIN_GET(model); - - if (priv->if_properties) - ret = eina_model_interface_properties_get - (priv->if_properties, model, name, value); - - return ret; -} - -static Eina_Bool -_eina_model_type_mixin_property_set(Eina_Model *model, const char *name, const Eina_Value *value) -{ - Eina_Bool ret = EINA_FALSE; - - EINA_MODEL_TYPE_MIXIN_GET(model); - - if (priv->if_properties) - ret = eina_model_interface_properties_set - (priv->if_properties, model, name, value); - - return ret; -} - -static Eina_Bool -_eina_model_type_mixin_property_del(Eina_Model *model, const char *name) -{ - Eina_Bool ret = EINA_FALSE; - - EINA_MODEL_TYPE_MIXIN_GET(model); - - if (priv->if_properties) - ret = eina_model_interface_properties_del - (priv->if_properties, model, name); - - return ret; -} - -static Eina_List * -_eina_model_type_mixin_properties_names_list_get(const Eina_Model *model) -{ - Eina_List *ret = NULL; - - EINA_MODEL_TYPE_MIXIN_GET(model); - - if (priv->if_properties) - ret = eina_model_interface_properties_names_list_get - (priv->if_properties, model); - - return ret; -} - -static int -_eina_model_type_mixin_child_count(const Eina_Model *model) -{ - EINA_MODEL_TYPE_MIXIN_GET(model); - - if (!priv->if_children) - return 0; - - return eina_model_interface_children_count(priv->if_children, model); -} - -static Eina_Model * -_eina_model_type_mixin_child_get(const Eina_Model *model, unsigned int position) -{ - EINA_MODEL_TYPE_MIXIN_GET(model); - - if (!priv->if_children) - return 0; - - return eina_model_interface_children_get(priv->if_children, model, position); -} - -static Eina_Bool -_eina_model_type_mixin_child_set(Eina_Model *model, unsigned int position, Eina_Model *child) -{ - EINA_MODEL_TYPE_MIXIN_GET(model); - - if (!priv->if_children) - return 0; - - return eina_model_interface_children_set - (priv->if_children, model, position, child); -} - -static Eina_Bool -_eina_model_type_mixin_child_del(Eina_Model *model, unsigned int position) -{ - EINA_MODEL_TYPE_MIXIN_GET(model); - - if (!priv->if_children) - return 0; - - return eina_model_interface_children_del - (priv->if_children, model, position); -} - -static Eina_Bool -_eina_model_type_mixin_child_insert_at(Eina_Model *model, unsigned int position, Eina_Model *child) -{ - EINA_MODEL_TYPE_MIXIN_GET(model); - - if (!priv->if_children) - return 0; - - return eina_model_interface_children_insert_at - (priv->if_children, model, position, child); -} - -static void -_eina_model_type_mixin_child_sort(Eina_Model *model, Eina_Compare_Cb compare) -{ - EINA_MODEL_TYPE_MIXIN_GET(model); - - if (!priv->if_children) - return; - eina_model_interface_children_sort(priv->if_children, model, compare); -} - -static const Eina_Model_Type _EINA_MODEL_TYPE_MIXIN = { - EINA_MODEL_TYPE_VERSION, - sizeof(Eina_Model_Type_Mixin_Data), - sizeof(Eina_Model_Type), - "Eina_Model_Type_Mixin", - &_EINA_MODEL_TYPE_BASE, - NULL, /* no interfaces implemented */ - NULL, /* no extra events */ - _eina_model_type_mixin_setup, - _eina_model_type_mixin_flush, - _eina_model_type_mixin_constructor, - _eina_model_type_mixin_destructor, - NULL, /* no copy, as interface is called automatically */ - NULL, /* no deep copy, as interface is called automatically */ - _eina_model_type_mixin_compare, - _eina_model_type_mixin_load, - _eina_model_type_mixin_unload, - _eina_model_type_mixin_property_get, - _eina_model_type_mixin_property_set, - _eina_model_type_mixin_property_del, - _eina_model_type_mixin_properties_names_list_get, - _eina_model_type_mixin_child_count, - _eina_model_type_mixin_child_get, - _eina_model_type_mixin_child_set, - _eina_model_type_mixin_child_del, - _eina_model_type_mixin_child_insert_at, - NULL, /* use default find */ - NULL, /* use default criteria_match */ - _eina_model_type_mixin_child_sort, - NULL, /* use default iterator get */ - NULL, /* use default reversed iterator get */ - NULL, /* use default sorted iterator get */ - NULL, /* use default filtered iterator get */ - NULL, /* use default to string */ - NULL, /* extension pointer */ - NULL, /* extension pointer */ - NULL, /* extension pointer */ - NULL /* extension pointer */ -}; -#undef EINA_MODEL_TYPE_MIXIN_GET - -/* Events for all Properties interface */ -static const Eina_Model_Event_Description _eina_model_interface_properties_events[] = { - EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_properties_loaded, "", "model properties were loaded"), - EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_properties_unloaded, "", "model properties were unloaded"), - EINA_MODEL_EVENT_DESCRIPTION_SENTINEL -}; - -/* EINA_MODEL_INTERFACE_PROPERTIES_HASH ******************************/ - -#define EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET(model) \ - Eina_Hash *priv = *(Eina_Hash **)eina_model_interface_private_data_get \ - (model, EINA_MODEL_INTERFACE_PROPERTIES_HASH) - -static Eina_Bool -_eina_model_interface_properties_hash_setup(Eina_Model *model) -{ - Eina_Hash **p_priv = eina_model_interface_private_data_get - (model, EINA_MODEL_INTERFACE_PROPERTIES_HASH); - - DBG("setup interface properties (hash) at %p model %p (%s)", - p_priv, model, model->desc->cache.types[0]->name); - - *p_priv = eina_hash_string_small_new(NULL); - return !!*p_priv; -} - -static Eina_Bool -_eina_model_interface_properties_hash_flush(Eina_Model *model) -{ - EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET(model); - - DBG("flush interface properties (hash) at %p model %p (%s)", - priv, model, model->desc->cache.types[0]->name); - - if (priv) - { - ERR("interface properties flushed with values! priv=%p, model %p (%s)", - priv, model, model->desc->cache.types[0]->name); - eina_hash_free(priv); - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_interface_properties_hash_constructor(Eina_Model *model) -{ - EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET(model); - - DBG("construct interface properties (hash) at %p model %p (%s)", - priv, model, model->desc->cache.types[0]->name); - - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_interface_properties_hash_destructor_foreach(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__) -{ - eina_value_free(data); - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_interface_properties_hash_destructor(Eina_Model *model) -{ - Eina_Hash **p_priv = eina_model_interface_private_data_get - (model, EINA_MODEL_INTERFACE_PROPERTIES_HASH); - int count = eina_hash_population(*p_priv); - - DBG("destroy interface properties (hash) at %p model %p (%s). %d values.", - *p_priv, model, model->desc->cache.types[0]->name, count); - - eina_hash_foreach - (*p_priv, _eina_model_interface_properties_hash_destructor_foreach, NULL); - eina_hash_free(*p_priv); - *p_priv = NULL; - - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_interface_properties_hash_get(const Eina_Model *model, const char *name, Eina_Value *value) -{ - EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET(model); - const Eina_Value *prop = eina_hash_find(priv, name); - EINA_SAFETY_ON_NULL_RETURN_VAL(prop, EINA_FALSE); - return eina_value_copy(prop, value); -} - -static Eina_Bool -_eina_model_interface_properties_hash_set(Eina_Model *model, const char *name, const Eina_Value *value) -{ - EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET(model); - Eina_Value *prop, *old = eina_hash_find(priv, name); - - prop = eina_value_new(eina_value_type_get(value)); - EINA_SAFETY_ON_NULL_RETURN_VAL(prop, EINA_FALSE); - - eina_value_flush(prop); - if (!eina_value_copy(value, prop)) - { - ERR("Could not copy value '%s' from %p to %p", name, value, prop); - eina_value_free(prop); - return EINA_FALSE; - } - - if (!old) - { - if (!eina_hash_add(priv, name, prop)) - { - ERR("Could not add value %p to hash as key '%s'", prop, name); - eina_value_free(prop); - return EINA_FALSE; - } - } - else - { - eina_value_free(old); - if (!eina_hash_modify(priv, name, prop)) - { - ERR("Could not modify hash key '%s' value from %p to %p", - name, old, prop); - eina_hash_del_by_key(priv, name); - eina_value_free(prop); - return EINA_FALSE; - } - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_interface_properties_hash_del(Eina_Model *model, const char *name) -{ - EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET(model); - Eina_Value *old = eina_hash_find(priv, name); - EINA_SAFETY_ON_NULL_RETURN_VAL(old, EINA_FALSE); - eina_value_free(old); - return eina_hash_del_by_key(priv, name); -} - -static Eina_Bool -_eina_model_interface_properties_hash_names_list_foreach(const Eina_Hash *hash __UNUSED__, const void *key, void *data __UNUSED__, void *fdata) -{ - Eina_List **p_list = fdata; - *p_list = eina_list_append(*p_list, eina_stringshare_add(key)); - return EINA_TRUE; -} - -static Eina_List * -_eina_model_interface_properties_hash_names_list(const Eina_Model *model) -{ - EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET(model); - Eina_List *list = NULL; - eina_hash_foreach - (priv, _eina_model_interface_properties_hash_names_list_foreach, &list); - return list; -} -#undef EINA_MODEL_INTERFACE_PROPERTIES_HASH_GET - -static const Eina_Model_Interface_Properties _EINA_MODEL_INTERFACE_PROPERTIES_HASH = { - { - EINA_MODEL_INTERFACE_VERSION, - sizeof(Eina_Hash *), - sizeof(Eina_Model_Interface_Properties), - _EINA_MODEL_INTERFACE_NAME_PROPERTIES, - NULL, /* no parent interfaces */ - _eina_model_interface_properties_events, - _eina_model_interface_properties_hash_setup, - _eina_model_interface_properties_hash_flush, - _eina_model_interface_properties_hash_constructor, - _eina_model_interface_properties_hash_destructor, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL - }, - EINA_MODEL_INTERFACE_PROPERTIES_VERSION, - NULL, /* no compare */ - NULL, /* no load */ - NULL, /* no unload */ - _eina_model_interface_properties_hash_get, - _eina_model_interface_properties_hash_set, - _eina_model_interface_properties_hash_del, - _eina_model_interface_properties_hash_names_list -}; - -/* EINA_MODEL_INTERFACE_PROPERTIES_STRUCT ******************************/ - -static Eina_Value_Struct * -_eina_model_interface_properties_struct_private_get(const Eina_Model *model) -{ - Eina_Value *val = eina_model_interface_private_data_get - (model, EINA_MODEL_INTERFACE_PROPERTIES_STRUCT); - return eina_value_memory_get(val); -} - -#define EINA_MODEL_INTERFACE_PROPERTIES_STRUCT_GET(model) \ - Eina_Value_Struct *priv = \ - _eina_model_interface_properties_struct_private_get(model) - -static Eina_Bool -_eina_model_interface_properties_struct_setup(Eina_Model *model) -{ - Eina_Value *val = eina_model_interface_private_data_get - (model, EINA_MODEL_INTERFACE_PROPERTIES_STRUCT); - - DBG("setup interface properties (struct) at %p model %p (%s)", - val, model, model->desc->cache.types[0]->name); - - return eina_value_setup(val, EINA_VALUE_TYPE_STRUCT); -} - -static Eina_Bool -_eina_model_interface_properties_struct_flush(Eina_Model *model) -{ - Eina_Value *val = eina_model_interface_private_data_get - (model, EINA_MODEL_INTERFACE_PROPERTIES_STRUCT); - - DBG("flush interface properties (struct) at %p model %p (%s)", - val, model, model->desc->cache.types[0]->name); - - if (val->type) - { - ERR("interface properties flushed with values! val=%p, model %p (%s)", - val, model, model->desc->cache.types[0]->name); - eina_value_flush(val); - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_interface_properties_struct_constructor(Eina_Model *model) -{ - EINA_MODEL_INTERFACE_PROPERTIES_STRUCT_GET(model); - - DBG("construct interface properties (struct) at %p model %p (%s)", - priv, model, model->desc->cache.types[0]->name); - - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_interface_properties_struct_destructor(Eina_Model *model) -{ - Eina_Value *val = eina_model_interface_private_data_get - (model, EINA_MODEL_INTERFACE_PROPERTIES_STRUCT); - - DBG("destroy interface properties (struct) at %p model %p (%s)", - val, model, model->desc->cache.types[0]->name); - - eina_value_flush(val); - val->type = NULL; - - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_interface_properties_struct_get(const Eina_Model *model, const char *name, Eina_Value *val) -{ - const Eina_Value *v = eina_model_interface_private_data_get - (model, EINA_MODEL_INTERFACE_PROPERTIES_STRUCT); - return eina_value_struct_value_get(v, name, val); -} - -static Eina_Bool -_eina_model_interface_properties_struct_set(Eina_Model *model, const char *name, const Eina_Value *val) -{ - Eina_Value *v = eina_model_interface_private_data_get - (model, EINA_MODEL_INTERFACE_PROPERTIES_STRUCT); - return eina_value_struct_value_set(v, name, val); -} - -static Eina_Bool -_eina_model_interface_properties_struct_del(Eina_Model *model __UNUSED__, const char *name __UNUSED__) -{ - return EINA_FALSE; /* not allowed */ -} - -static Eina_List * -_eina_model_interface_properties_struct_names_list(const Eina_Model *model) -{ - EINA_MODEL_INTERFACE_PROPERTIES_STRUCT_GET(model); - const Eina_Value_Struct_Member *itr; - Eina_List *list = NULL; - - EINA_SAFETY_ON_NULL_RETURN_VAL(priv, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(priv->desc, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(priv->desc->members, NULL); - - itr = priv->desc->members; - if (priv->desc->member_count) - { - const Eina_Value_Struct_Member *end = itr + priv->desc->member_count; - for (; itr < end; itr++) - list = eina_list_append(list, eina_stringshare_add(itr->name)); - } - else - { - for (; itr->name != NULL; itr++) - list = eina_list_append(list, eina_stringshare_add(itr->name)); - } - - return list; -} -#undef EINA_MODEL_INTERFACE_PROPERTIES_STRUCT_GET - -static const Eina_Model_Interface_Properties _EINA_MODEL_INTERFACE_PROPERTIES_STRUCT = { - { - EINA_MODEL_INTERFACE_VERSION, - sizeof(Eina_Value), - sizeof(Eina_Model_Interface_Properties), - _EINA_MODEL_INTERFACE_NAME_PROPERTIES, - NULL, /* no parent interfaces */ - _eina_model_interface_properties_events, - _eina_model_interface_properties_struct_setup, - _eina_model_interface_properties_struct_flush, - _eina_model_interface_properties_struct_constructor, - _eina_model_interface_properties_struct_destructor, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL - }, - EINA_MODEL_INTERFACE_PROPERTIES_VERSION, - NULL, /* no compare */ - NULL, /* no load */ - NULL, /* no unload */ - _eina_model_interface_properties_struct_get, - _eina_model_interface_properties_struct_set, - _eina_model_interface_properties_struct_del, - _eina_model_interface_properties_struct_names_list -}; - -/* Events for all Children interface */ -static const Eina_Model_Event_Description _eina_model_interface_children_events[] = { - EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_children_loaded, "", "model children were loaded"), - EINA_MODEL_EVENT_DESCRIPTION(_eina_model_str_children_unloaded, "", "model children were unloaded"), - EINA_MODEL_EVENT_DESCRIPTION_SENTINEL -}; - -/* EINA_MODEL_INTERFACE_CHILDREN_INARRAY ******************************/ - -#define EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model) \ - Eina_Inarray *priv = eina_model_interface_private_data_get \ - (model, EINA_MODEL_INTERFACE_CHILDREN_INARRAY) - -static Eina_Bool -_eina_model_interface_children_inarray_setup(Eina_Model *model) -{ - EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model); - - DBG("setup interface children (inarray) at %p model %p (%s)", - priv, model, model->desc->cache.types[0]->name); - - eina_inarray_step_set(priv, sizeof(Eina_Inarray), sizeof(Eina_Model *), 0); - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_interface_children_inarray_flush(Eina_Model *model) -{ - EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model); - int count; - - DBG("flush interface children (inarray) at %p model %p (%s)", - priv, model, model->desc->cache.types[0]->name); - - count = eina_inarray_count(priv); - if (count > 0) - ERR("interface children flushed with %d members! priv=%p, model %p (%s)", - count, priv, model, model->desc->cache.types[0]->name); - - eina_inarray_flush(priv); - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_interface_children_inarray_constructor(Eina_Model *model) -{ - EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model); - - DBG("construct interface children (inarray) at %p model %p (%s)", - priv, model, model->desc->cache.types[0]->name); - - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_interface_children_inarray_destructor(Eina_Model *model) -{ - Eina_Model **itr, **itr_end; - int count; - - EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model); - - count = eina_inarray_count(priv); - - DBG("destroy interface children (inarray) at %p model %p (%s). %d members.", - priv, model, model->desc->cache.types[0]->name, count); - - itr = priv->members; - itr_end = itr + count; - for (; itr < itr_end; itr++) - eina_model_xunref(*itr, EINA_MODEL_INTERFACE_CHILDREN_INARRAY); - eina_inarray_flush(priv); - - return EINA_TRUE; -} - -static int -_eina_model_interface_children_inarray_count(const Eina_Model *model) -{ - EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model); - return eina_inarray_count(priv); -} - -static Eina_Model * -_eina_model_interface_children_inarray_get(const Eina_Model *model, unsigned int position) -{ - EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model); - Eina_Model **child = eina_inarray_nth(priv, position); - if (!child) - return NULL; - return eina_model_ref(*child); -} - -static Eina_Bool -_eina_model_interface_children_inarray_set(Eina_Model *model, unsigned int position, Eina_Model *child) -{ - EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model); - Eina_Model **p_old = eina_inarray_nth(priv, position); - Eina_Model *old; - - if (!p_old) - return EINA_FALSE; - - old = *p_old; - if (!eina_inarray_replace_at(priv, position, &child)) - return EINA_FALSE; - - eina_model_xref(child, EINA_MODEL_INTERFACE_CHILDREN_INARRAY, - "eina_model_child_set"); - eina_model_xunref(old, EINA_MODEL_INTERFACE_CHILDREN_INARRAY); - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_interface_children_inarray_del(Eina_Model *model, unsigned int position) -{ - EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model); - Eina_Model **p_old = eina_inarray_nth(priv, position); - Eina_Model *old; - - if (!p_old) - return EINA_FALSE; - - old = *p_old; - if (!eina_inarray_remove_at(priv, position)) - return EINA_FALSE; - - eina_model_xunref(old, EINA_MODEL_INTERFACE_CHILDREN_INARRAY); - return EINA_TRUE; -} - -static Eina_Bool -_eina_model_interface_children_inarray_insert_at(Eina_Model *model, unsigned int position, Eina_Model *child) -{ - EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model); - - if (!eina_inarray_insert_at(priv, position, &child)) - return EINA_FALSE; - - eina_model_xref(child, EINA_MODEL_INTERFACE_CHILDREN_INARRAY, - "eina_model_child_insert_at"); - return EINA_TRUE; -} - -static void -_eina_model_interface_children_inarray_sort(Eina_Model *model, Eina_Compare_Cb compare) -{ - EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET(model); - int count = eina_inarray_count(priv); - EINA_SAFETY_ON_FALSE_RETURN(count >= 0); - - if (count > 1) - _eina_model_array_sort(priv->members, 0, count - 1, compare); -} -#undef EINA_MODEL_INTERFACE_CHILDREN_INARRAY_GET - -static const Eina_Model_Interface_Children _EINA_MODEL_INTERFACE_CHILDREN_INARRAY = { - { - EINA_MODEL_INTERFACE_VERSION, - sizeof(Eina_Inarray), - sizeof(Eina_Model_Interface_Children), - _EINA_MODEL_INTERFACE_NAME_CHILDREN, - NULL, /* no parent interfaces */ - _eina_model_interface_children_events, - _eina_model_interface_children_inarray_setup, - _eina_model_interface_children_inarray_flush, - _eina_model_interface_children_inarray_constructor, - _eina_model_interface_children_inarray_destructor, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL - }, - EINA_MODEL_INTERFACE_CHILDREN_VERSION, - NULL, /* no compare */ - NULL, /* no load */ - NULL, /* no unload */ - _eina_model_interface_children_inarray_count, - _eina_model_interface_children_inarray_get, - _eina_model_interface_children_inarray_set, - _eina_model_interface_children_inarray_del, - _eina_model_interface_children_inarray_insert_at, - _eina_model_interface_children_inarray_sort -}; - -/* EINA_MODEL_TYPE_GENERIC ********************************************/ - -static const Eina_Model_Interface *_EINA_MODEL_TYPE_GENERIC_IFACES[] = { - &_EINA_MODEL_INTERFACE_PROPERTIES_HASH.base, - &_EINA_MODEL_INTERFACE_CHILDREN_INARRAY.base, - NULL -}; - -static const Eina_Model_Type _EINA_MODEL_TYPE_GENERIC = - EINA_MODEL_TYPE_INIT_NOPRIVATE("Eina_Model_Type_Generic", - Eina_Model_Type, - &_EINA_MODEL_TYPE_MIXIN, - _EINA_MODEL_TYPE_GENERIC_IFACES, - NULL); - -/* EINA_MODEL_TYPE_STRUCT ********************************************/ - -static const Eina_Model_Interface *_EINA_MODEL_TYPE_STRUCT_IFACES[] = { - &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base, - &_EINA_MODEL_INTERFACE_CHILDREN_INARRAY.base, - NULL -}; - -static const Eina_Model_Type _EINA_MODEL_TYPE_STRUCT = - EINA_MODEL_TYPE_INIT_NOPRIVATE("Eina_Model_Type_Struct", - Eina_Model_Type, - &_EINA_MODEL_TYPE_MIXIN, - _EINA_MODEL_TYPE_STRUCT_IFACES, - NULL); - -/** - */ - -/** - * @internal - * @brief Initialize the model module. - * - * @return #EINA_TRUE on success, #EINA_FALSE on failure. - * - * This function sets up the model module of Eina. It is called - * by eina_init(). - * - * @see eina_init() - */ -Eina_Bool -eina_model_init(void) -{ - const char *choice, *tmp; - - _eina_model_log_dom = eina_log_domain_register("eina_model", - EINA_LOG_COLOR_DEFAULT); - if (_eina_model_log_dom < 0) - { - EINA_LOG_ERR("Could not register log domain: eina_model"); - return EINA_FALSE; - } - - choice = getenv("EINA_MODEL_DEBUG"); - if (choice) - { - if (strcmp(choice, "1") == 0) - _eina_model_debug = EINA_MODEL_DEBUG_CHECK; - else if (strcmp(choice, "backtrace") == 0) - _eina_model_debug = EINA_MODEL_DEBUG_BACKTRACE; - } - -#ifdef EINA_DEFAULT_MEMPOOL - choice = "pass_through"; -#else - choice = "chained_mempool"; -#endif - tmp = getenv("EINA_MEMPOOL"); - if (tmp && tmp[0]) - choice = tmp; - - if (choice) - _eina_model_mp_choice = strdup(choice); - - _eina_model_mp = eina_mempool_add - (_eina_model_mp_choice, "model", NULL, sizeof(Eina_Model), 32); - if (!_eina_model_mp) - { - ERR("Mempool for model cannot be allocated in model init."); - goto on_init_fail_mp; - } - - if (!eina_lock_new(&_eina_model_inner_mps_lock)) - { - ERR("Cannot create inner mempools lock in model init."); - goto on_init_fail_lock_mp; - } - _eina_model_inner_mps = eina_hash_int32_new(NULL); - if (!_eina_model_inner_mps) - { - ERR("Cannot create hash for inner mempools in model init."); - goto on_init_fail_hash_mp; - } - - if (!eina_lock_new(&_eina_model_descriptions_lock)) - { - ERR("Cannot create model descriptions lock in model init."); - goto on_init_fail_lock_desc; - } - _eina_model_descriptions = eina_hash_pointer_new(NULL); - if (!_eina_model_descriptions) - { - ERR("Cannot create model descriptions hash in model init."); - goto on_init_fail_hash_desc; - } - - if (!eina_lock_new(&_eina_model_debug_list_lock)) - { - ERR("Cannot create model debug list lock in model init."); - goto on_init_fail_lock_debug; - } - - EINA_ERROR_MODEL_FAILED = eina_error_msg_static_register( - EINA_ERROR_MODEL_FAILED_STR); - EINA_ERROR_MODEL_METHOD_MISSING = eina_error_msg_static_register( - EINA_ERROR_MODEL_METHOD_MISSING_STR); - - EINA_MODEL_TYPE_BASE = &_EINA_MODEL_TYPE_BASE; - EINA_MODEL_TYPE_MIXIN = &_EINA_MODEL_TYPE_MIXIN; - EINA_MODEL_TYPE_GENERIC = &_EINA_MODEL_TYPE_GENERIC; - EINA_MODEL_TYPE_STRUCT = &_EINA_MODEL_TYPE_STRUCT; - - EINA_MODEL_INTERFACE_PROPERTIES_HASH = &_EINA_MODEL_INTERFACE_PROPERTIES_HASH.base; - EINA_MODEL_INTERFACE_PROPERTIES_STRUCT = &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base; - - EINA_MODEL_INTERFACE_CHILDREN_INARRAY = &_EINA_MODEL_INTERFACE_CHILDREN_INARRAY.base; - - EINA_MODEL_INTERFACE_NAME_PROPERTIES = _EINA_MODEL_INTERFACE_NAME_PROPERTIES; - EINA_MODEL_INTERFACE_NAME_CHILDREN = _EINA_MODEL_INTERFACE_NAME_CHILDREN; - - eina_magic_string_static_set(EINA_MAGIC_MODEL, EINA_MAGIC_MODEL_STR); - - return EINA_TRUE; - - on_init_fail_lock_debug: - eina_hash_free(_eina_model_descriptions); - on_init_fail_hash_desc: - eina_lock_free(&_eina_model_descriptions_lock); - on_init_fail_lock_desc: - eina_hash_free(_eina_model_inner_mps); - _eina_model_inner_mps = NULL; - on_init_fail_hash_mp: - eina_lock_free(&_eina_model_inner_mps_lock); - on_init_fail_lock_mp: - eina_mempool_del(_eina_model_mp); - on_init_fail_mp: - free(_eina_model_mp_choice); - _eina_model_mp_choice = NULL; - eina_log_domain_unregister(_eina_model_log_dom); - _eina_model_log_dom = -1; - return EINA_FALSE; -} - -/** - * @internal - * @brief Shut down the model module. - * - * @return #EINA_TRUE on success, #EINA_FALSE on failure. - * - * This function shuts down the model module set up by - * eina_model_init(). It is called by eina_shutdown(). - * - * @see eina_shutdown() - */ -Eina_Bool -eina_model_shutdown(void) -{ - eina_lock_take(&_eina_model_debug_list_lock); - if (eina_list_count(_eina_model_debug_list) > 0) - ERR("%d models are still alive!", eina_list_count(_eina_model_debug_list)); - eina_lock_release(&_eina_model_debug_list_lock); - eina_lock_free(&_eina_model_debug_list_lock); - - eina_lock_take(&_eina_model_inner_mps_lock); - if (eina_hash_population(_eina_model_inner_mps) != 0) - ERR("Cannot free eina_model internal memory pools -- still in use!"); - else - eina_hash_free(_eina_model_inner_mps); - eina_lock_release(&_eina_model_inner_mps_lock); - eina_lock_free(&_eina_model_inner_mps_lock); - - eina_lock_take(&_eina_model_descriptions_lock); - if (eina_hash_population(_eina_model_descriptions) != 0) - ERR("Cannot free eina_model internal descriptions -- still in use!"); - else - eina_hash_free(_eina_model_descriptions); - eina_lock_release(&_eina_model_descriptions_lock); - eina_lock_free(&_eina_model_descriptions_lock); - - free(_eina_model_mp_choice); - _eina_model_mp_choice = NULL; - eina_mempool_del(_eina_model_mp); - eina_log_domain_unregister(_eina_model_log_dom); - _eina_model_log_dom = -1; - return EINA_TRUE; -} - -/*============================================================================* - * Global * - *============================================================================*/ - -/*============================================================================* - * API * - *============================================================================*/ - - -EAPI Eina_Error EINA_ERROR_MODEL_FAILED = 0; -EAPI Eina_Error EINA_ERROR_MODEL_METHOD_MISSING = 0; - -EAPI const Eina_Model_Type *EINA_MODEL_TYPE_BASE = NULL; -EAPI const Eina_Model_Type *EINA_MODEL_TYPE_MIXIN = NULL; -EAPI const Eina_Model_Type *EINA_MODEL_TYPE_GENERIC = NULL; -EAPI const Eina_Model_Type *EINA_MODEL_TYPE_STRUCT = NULL; - -EAPI const Eina_Model_Interface *EINA_MODEL_INTERFACE_PROPERTIES_HASH = NULL; -EAPI const Eina_Model_Interface *EINA_MODEL_INTERFACE_PROPERTIES_STRUCT = NULL; -EAPI const Eina_Model_Interface *EINA_MODEL_INTERFACE_CHILDREN_INARRAY = NULL; - -EAPI const char *EINA_MODEL_INTERFACE_NAME_PROPERTIES = "Eina_Model_Interface_Properties"; -EAPI const char *EINA_MODEL_INTERFACE_NAME_CHILDREN = "Eina_Model_Interface_Children"; - -EAPI Eina_Model * -eina_model_new(const Eina_Model_Type *type) -{ - const Eina_Model_Description *desc; - Eina_Model *model; - unsigned int i; - - EINA_SAFETY_ON_NULL_RETURN_VAL(type, NULL); - EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_model_type_check(type), NULL); - - desc = _eina_model_description_get(type); - EINA_SAFETY_ON_NULL_RETURN_VAL(desc, NULL); - - model = eina_mempool_malloc(_eina_model_mp, sizeof(Eina_Model)); - EINA_SAFETY_ON_NULL_GOTO(model, failed_model); - - model->desc = desc; - model->listeners.entries = NULL; - model->listeners.deleted = NULL; - model->listeners.freeze = NULL; - model->listeners.walking = 0; - - if (desc->total.size == 0) - model->privates = NULL; - else - { - unsigned char *ptr; - - model->privates = _eina_model_inner_alloc - (desc->total.privates * sizeof(void *) + - desc->total.size); - EINA_SAFETY_ON_NULL_GOTO(model->privates, failed_privates); - - ptr = (unsigned char *)(model->privates + desc->total.privates); - for (i = 0; i < desc->total.privates; i++) - { - unsigned int size; - if (i < desc->total.types) - size = desc->cache.privates[i].type->private_size; - else - size = desc->cache.privates[i].iface->private_size; - - if (size == 0) - { - model->privates[i] = NULL; - continue; - } - - model->privates[i] = ptr; - memset(ptr, 0, size); - - if (size % sizeof(void *) != 0) - size += sizeof(void *) - (size % sizeof(void *)); - ptr += size; - } - } - - model->refcount = 1; - model->xrefs = NULL; - model->deleted = EINA_FALSE; - EINA_MAGIC_SET(model, EINA_MAGIC_MODEL); - - /* call setup of every type in the reverse order, - * they should not call parent's setup. - */ - for (i = desc->total.types; i > 0; i--) - { - if (desc->cache.types[i - 1]->setup) - { - if (!desc->cache.types[i - 1]->setup(model)) - { - ERR("Failed to setup model %p at type %p (%s)", - model, desc->cache.types[i - 1], - desc->cache.types[i - 1]->name); - goto failed_types; - } - } - } - - /* call setup of every interface in the reverse order, - * they should not call parent's setup. - */ - for (i = desc->total.ifaces; i > 0; i--) - { - if (desc->cache.ifaces[i - 1]->setup) - { - if (!desc->cache.ifaces[i - 1]->setup(model)) - { - ERR("Failed to setup model %p at interface %p (%s)", - model, desc->cache.ifaces[i - 1], - desc->cache.ifaces[i - 1]->name); - goto failed_ifaces; - } - } - } - - if (!desc->ops.type.constructor(model)) - { - ERR("Failed to construct model %p, type %p (%s)", - model, desc->cache.types[0], desc->cache.types[0]->name); - goto failed_constructor; - } - - if (EINA_UNLIKELY(_eina_model_debug)) - { - eina_lock_take(&_eina_model_debug_list_lock); - _eina_model_debug_list = eina_list_append - (_eina_model_debug_list, model); - eina_lock_release(&_eina_model_debug_list_lock); - } - - return model; - - failed_constructor: - i = 0; - failed_ifaces: - /* flush every setup interface, natural order */ - for (; i < desc->total.ifaces; i++) - desc->cache.ifaces[i]->flush(model); - i = 0; - failed_types: - /* flush every setup type, natural order */ - for (; i < desc->total.types; i++) - desc->cache.types[i]->flush(model); - - if (model->privates) - _eina_model_inner_free(desc->total.privates * sizeof(void *) + - desc->total.size, - model->privates); - - failed_privates: - EINA_MAGIC_SET(model, EINA_MAGIC_NONE); - eina_mempool_free(_eina_model_mp, model); - failed_model: - _eina_model_description_dispose(desc); - return NULL; -} - -static void -_eina_model_free(Eina_Model *model) -{ - const Eina_Model_Description *desc = model->desc; - unsigned int i; - - DBG("model %p (%s) refcount=%d deleted=%hhu", - model, model->desc->cache.types[0]->name, - model->refcount, model->deleted); - - if (EINA_UNLIKELY(_eina_model_debug)) - { - if (model->xrefs) - { - ERR("Model %p (%s) released with references pending:", - model, model->desc->cache.types[0]->name); - while (model->xrefs) - { - Eina_Model_XRef *ref = (Eina_Model_XRef *)model->xrefs; - model->xrefs = eina_inlist_remove(model->xrefs, model->xrefs); - - ERR("xref: %p '%s'", ref->id, ref->label); - free(ref); - } - } - - eina_lock_take(&_eina_model_debug_list_lock); - _eina_model_debug_list = eina_list_remove - (_eina_model_debug_list, model); - eina_lock_release(&_eina_model_debug_list_lock); - } - - /* flush every interface, natural order */ - for (i = 0; i < desc->total.ifaces; i++) - if (desc->cache.ifaces[i]->flush) - desc->cache.ifaces[i]->flush(model); - - /* flush every type, natural order */ - for (i = 0; i < desc->total.types; i++) - if (desc->cache.types[i]->flush) - desc->cache.types[i]->flush(model); - - model->refcount--; - _eina_model_event_callback_call(model, _eina_model_str_freed, NULL); - - if (model->privates) - _eina_model_inner_free(desc->total.privates * sizeof(void *) + - desc->total.size, - model->privates); - - if (model->listeners.deleted) - _eina_model_event_callback_free_deleted(model); - - if (model->listeners.entries) - { - for (i = 0; i < desc->total.events; i++) - { - Eina_Inlist *lst = model->listeners.entries[i]; - while (lst) - { - void *tmp = lst; - lst = lst->next; - _eina_model_inner_free(sizeof(Eina_Model_Event_Listener), - tmp); - } - } - - _eina_model_inner_free(desc->total.events * sizeof(Eina_Inlist *), - model->listeners.entries); - } - - if (model->listeners.freeze) - _eina_model_inner_free(model->desc->total.events * sizeof(int), - model->listeners.freeze); - - EINA_MAGIC_SET(model, EINA_MAGIC_NONE); - eina_mempool_free(_eina_model_mp, model); - - _eina_model_description_dispose(desc); -} - -static void -_eina_model_del(Eina_Model *model) -{ - const Eina_Model_Description *desc = model->desc; - - DBG("model %p (%s) refcount=%d deleted=%hhu", - model, model->desc->cache.types[0]->name, - model->refcount, model->deleted); - - EINA_SAFETY_ON_TRUE_RETURN(model->deleted); - - model->deleted = EINA_TRUE; - _eina_model_event_callback_call(model, _eina_model_str_deleted, NULL); - - if (!desc->ops.type.destructor(model)) - ERR("Failed to destroy model %p, type %p (%s)", - model, desc->cache.types[0], desc->cache.types[0]->name); -} - -static void -_eina_model_unref(Eina_Model *model) -{ - DBG("model %p (%s) refcount=%d deleted=%hhu", - model, model->desc->cache.types[0]->name, - model->refcount, model->deleted); - - if (model->refcount > 1) - { - model->refcount--; - return; - } - - if (!model->deleted) _eina_model_del(model); - _eina_model_free(model); -} - -#define EINA_MODEL_INSTANCE_CHECK_VAL(inst, retval) \ - do \ - { \ - if (!EINA_MAGIC_CHECK(inst, EINA_MAGIC_MODEL)) \ - { \ - EINA_MAGIC_FAIL(inst, EINA_MAGIC_MODEL); \ - return retval; \ - } \ - EINA_SAFETY_ON_NULL_RETURN_VAL(inst->desc, retval); \ - EINA_SAFETY_ON_FALSE_RETURN_VAL(inst->refcount > 0, retval); \ - EINA_SAFETY_ON_FALSE_RETURN_VAL(inst->desc->refcount > 0, retval); \ - } \ - while (0) - -#define EINA_MODEL_INSTANCE_CHECK(inst) \ - do \ - { \ - if (!EINA_MAGIC_CHECK(inst, EINA_MAGIC_MODEL)) \ - { \ - EINA_MAGIC_FAIL(inst, EINA_MAGIC_MODEL); \ - return; \ - } \ - EINA_SAFETY_ON_NULL_RETURN(inst->desc); \ - EINA_SAFETY_ON_FALSE_RETURN(inst->refcount > 0); \ - EINA_SAFETY_ON_FALSE_RETURN(inst->desc->refcount > 0); \ - } \ - while (0) - -#define EINA_MODEL_TYPE_CALL_OPTIONAL_RETURN(model, method, def_retval, ...) \ - do \ - { \ - eina_error_set(0); \ - if (model->desc->ops.type.method) \ - return model->desc->ops.type.method(model, ## __VA_ARGS__); \ - DBG("Optional method" # method "() not implemented for model %p (%s)", \ - model, model->desc->cache.types[0]->name); \ - return def_retval; \ - } \ - while (0) - -#define EINA_MODEL_TYPE_CALL_OPTIONAL(model, method, ...) \ - do \ - { \ - eina_error_set(0); \ - if (model->desc->ops.type.method) \ - model->desc->ops.type.method(model, ## __VA_ARGS__); \ - else \ - DBG("Optional method" # method "() not implemented for model %p (%s)", \ - model, model->desc->cache.types[0]->name); \ - } \ - while (0) - -#define EINA_MODEL_TYPE_CALL_MANDATORY_RETURN(model, method, def_retval, ...) \ - do \ - { \ - eina_error_set(0); \ - if (model->desc->ops.type.method) \ - return model->desc->ops.type.method(model, ## __VA_ARGS__); \ - eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING); \ - CRITICAL("Mandatory method" # method "() not implemented for model %p (%s)", \ - model, model->desc->cache.types[0]->name); \ - return def_retval; \ - } \ - while (0) - -#define EINA_MODEL_TYPE_CALL_MANDATORY(model, method, ...) \ - do \ - { \ - eina_error_set(0); \ - if (model->desc->ops.type.method) \ - model->desc->ops.type.method(model, ## __VA_ARGS__); \ - else \ - { \ - eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING); \ - CRITICAL("Mandatory method" # method "() not implemented for model %p (%s)", \ - model, model->desc->cache.types[0]->name); \ - } \ - } \ - while (0) - - -#define EINA_MODEL_TYPE_CALL_RETURN(model, method, def_retval, ...) \ - do \ - { \ - eina_error_set(0); \ - if (model->desc->ops.type.method) \ - return model->desc->ops.type.method(model, ## __VA_ARGS__); \ - eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING); \ - ERR("Method" # method "() not implemented for model %p (%s)", \ - model, model->desc->cache.types[0]->name); \ - return def_retval; \ - } \ - while (0) - -#define EINA_MODEL_TYPE_CALL(model, method, ...) \ - do \ - { \ - eina_error_set(0); \ - if (model->desc->ops.type.method) \ - model->desc->ops.type.method(model, ## __VA_ARGS__); \ - else \ - { \ - eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING); \ - ERR("Method" # method "() not implemented for model %p (%s)", \ - model, model->desc->cache.types[0]->name); \ - } \ - } \ - while (0) - -EAPI void -eina_model_del(Eina_Model *model) -{ - if (!model) - return; - - EINA_MODEL_INSTANCE_CHECK(model); - _eina_model_del(model); - _eina_model_unref(model); -} - -EAPI const Eina_Model_Type * -eina_model_type_get(const Eina_Model *model) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - return model->desc->cache.types[0]; -} - -EAPI const Eina_Model_Interface * -eina_model_interface_get(const Eina_Model *model, const char *name) -{ - const Eina_Model_Description *desc; - const Eina_Model_Interface **itr, **itr_end; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL); - - desc = model->desc; - itr = desc->cache.ifaces; - itr_end = itr + desc->total.ifaces; - - /* fallback to strcmp if user is lazy about speed */ - for (; itr < itr_end; itr++) - if (strcmp((*itr)->name, name) == 0) - return *itr; - - return NULL; -} - -static Eina_Bool -_eina_model_instance_check(const Eina_Model *model, const Eina_Model_Type *type) -{ - const Eina_Model_Type **itr, **itr_end; - - itr = model->desc->cache.types; - itr_end = itr + model->desc->total.types; - - for (; itr < itr_end; itr++) - if (*itr == type) - return EINA_TRUE; - - return EINA_FALSE; -} - -EAPI Eina_Bool -eina_model_instance_check(const Eina_Model *model, const Eina_Model_Type *type) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), EINA_FALSE); - return _eina_model_instance_check(model, type); -} - -EAPI Eina_Model * -eina_model_ref(Eina_Model *model) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - DBG("model %p (%s) refcount=%d deleted=%hhu", - model, model->desc->cache.types[0]->name, - model->refcount, model->deleted); - model->refcount++; - return model; -} - -static Eina_Model * -_eina_model_xref_add(Eina_Model *model, const void *id, const char *label) -{ - Eina_Model_XRef *ref; - void *bt[256]; - int btlen, labellen; - - labellen = label ? strlen(label): 0; - btlen = 0; - -#ifdef HAVE_BACKTRACE - if (_eina_model_debug == EINA_MODEL_DEBUG_BACKTRACE) - btlen = backtrace(bt, EINA_C_ARRAY_LENGTH(bt)); -#endif - - ref = calloc(1, sizeof(*ref) + (btlen * sizeof(void *)) + (labellen + 1)); - EINA_SAFETY_ON_NULL_RETURN_VAL(ref, NULL); - - ref->id = id; - memcpy(ref->label, label, labellen); - ref->label[labellen] = '\0'; - ref->backtrace.count = btlen; - if (btlen == 0) ref->backtrace.symbols = NULL; - else - { - void *ptr = (unsigned char *)ref + sizeof(*ref) + (labellen + 1); - ref->backtrace.symbols = ptr; - memcpy(ptr, bt, btlen * sizeof(void *)); - } - - model->xrefs = eina_inlist_append(model->xrefs, EINA_INLIST_GET(ref)); - return model; -} - -EAPI Eina_Model * -eina_model_xref(Eina_Model *model, const void *id, const char *label) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - DBG("model %p (%s) refcount=%d deleted=%hhu id=%p label=%s", - model, model->desc->cache.types[0]->name, - model->refcount, model->deleted, id, label ? label : ""); - - model->refcount++; - - if (EINA_LIKELY(!_eina_model_debug)) - return model; - - return _eina_model_xref_add(model, id, label); -} - -EAPI void -eina_model_unref(Eina_Model *model) -{ - EINA_MODEL_INSTANCE_CHECK(model); - _eina_model_unref(model); -} - -EAPI void -eina_model_xunref(Eina_Model *model, const void *id) -{ - Eina_Model_XRef *ref; - EINA_MODEL_INSTANCE_CHECK(model); - - if (EINA_LIKELY(!_eina_model_debug)) - { - _eina_model_unref(model); - return; - } - - EINA_INLIST_FOREACH(model->xrefs, ref) - { - if (ref->id != id) continue; - - model->xrefs = eina_inlist_remove(model->xrefs, EINA_INLIST_GET(ref)); - free(ref); - _eina_model_unref(model); - return; - } - - ERR("Could not find existing reference %p to model %p", id, model); -} - -EAPI int -eina_model_refcount(const Eina_Model *model) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, -1); - return model->refcount; -} - -EAPI const Eina_Inlist * -eina_model_xrefs_get(const Eina_Model *model) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - return model->xrefs; -} - -EAPI Eina_Bool -eina_model_event_callback_add(Eina_Model *model, const char *event_name, Eina_Model_Event_Cb cb, const void *data) -{ - const Eina_Model_Description *desc; - Eina_Model_Event_Listener *el; - int event_id; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(event_name, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE); - - desc = model->desc; - event_id = _eina_model_description_event_id_find(desc, event_name); - if (event_id < 0) - { - ERR("No event named %s for model %p (%s)", - event_name, model, model->desc->cache.types[0]->name); - return EINA_FALSE; - } - - if (!model->listeners.entries) - { - model->listeners.entries = _eina_model_inner_alloc - (desc->total.events * sizeof(Eina_Inlist *)); - EINA_SAFETY_ON_NULL_RETURN_VAL(model->listeners.entries, EINA_FALSE); - memset(model->listeners.entries, 0, - desc->total.events * sizeof(Eina_Inlist *)); - } - - el = _eina_model_inner_alloc(sizeof(Eina_Model_Event_Listener)); - EINA_SAFETY_ON_NULL_RETURN_VAL(el, EINA_FALSE); - - el->cb = cb; - el->data = data; - el->deleted = EINA_FALSE; - model->listeners.entries[event_id] = eina_inlist_append - (model->listeners.entries[event_id], EINA_INLIST_GET(el)); - - return EINA_TRUE; -} - -EAPI Eina_Bool -eina_model_event_callback_del(Eina_Model *model, const char *event_name, Eina_Model_Event_Cb cb, const void *data) -{ - int event_id; - Eina_Inlist *lst; - Eina_Model_Event_Listener *el; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(event_name, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(cb, EINA_FALSE); - - if (!model->listeners.entries) - { - ERR("No event callbacks for model %p (%s)", - model, model->desc->cache.types[0]->name); - return EINA_FALSE; - } - - event_id = _eina_model_description_event_id_find(model->desc, event_name); - if (event_id < 0) - { - ERR("No event named %s for model %p (%s)", - event_name, model, model->desc->cache.types[0]->name); - return EINA_FALSE; - } - - lst = model->listeners.entries[event_id]; - EINA_INLIST_FOREACH(lst, el) - { - if (el->cb != cb) continue; - if ((data) && (el->data != data)) continue; - - if (model->listeners.walking == 0) - { - model->listeners.entries[event_id] = eina_inlist_remove - (model->listeners.entries[event_id], EINA_INLIST_GET(el)); - _eina_model_inner_free(sizeof(Eina_Model_Event_Listener), el); - } - else - { - el->deleted = EINA_TRUE; - if (!model->listeners.deleted) - { - model->listeners.deleted = _eina_model_inner_alloc - (model->desc->total.events * sizeof(Eina_List *)); - EINA_SAFETY_ON_NULL_RETURN_VAL(model->listeners.deleted, - EINA_FALSE); - - memset(model->listeners.deleted, 0, - model->desc->total.events * sizeof(Eina_List *)); - - } - model->listeners.deleted[event_id] = eina_list_append - (model->listeners.deleted[event_id], el); - } - return EINA_TRUE; - } - - ERR("No callback %p data %p found for event named %s for model %p (%s)", - cb, data, event_name, model, model->desc->cache.types[0]->name); - return EINA_FALSE; -} - -EAPI const Eina_Model_Event_Description * -eina_model_event_description_get(const Eina_Model *model, const char *event_name) -{ - const Eina_Model_Description *desc; - int event_id; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(event_name, NULL); - - desc = model->desc; - event_id = _eina_model_description_event_id_find(desc, event_name); - if (event_id < 0) - return NULL; - - return desc->cache.events[event_id].desc; -} - -EAPI Eina_List * -eina_model_event_names_list_get(const Eina_Model *model) -{ - const Eina_Model_Event_Description_Cache *itr, *itr_end; - Eina_List *lst = NULL; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - - itr = model->desc->cache.events; - itr_end = itr + model->desc->total.events; - - for (; itr < itr_end; itr++) - lst = eina_list_append(lst, eina_stringshare_add(itr->name)); - - return lst; -} - -EAPI void -eina_model_event_names_list_free(Eina_List *list) -{ - const char *str; - EINA_LIST_FREE(list, str) - eina_stringshare_del(str); -} - -EAPI Eina_Bool -eina_model_event_callback_call(Eina_Model *model, const char *name, const void *event_info) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE); - return _eina_model_event_callback_call(model, name, event_info); -} - -EAPI int -eina_model_event_callback_freeze(Eina_Model *model, const char *name) -{ - int event_id; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(name, -1); - - event_id = _eina_model_description_event_id_find(model->desc, name); - if (event_id < 0) return -1; - - if (!model->listeners.freeze) - { - model->listeners.freeze = _eina_model_inner_alloc - (model->desc->total.events * sizeof(int)); - EINA_SAFETY_ON_NULL_RETURN_VAL(model->listeners.freeze, -1); - - memset(model->listeners.freeze, 0, - model->desc->total.events * sizeof(int)); - } - - if (model->listeners.freeze[event_id] == 0) - DBG("model %p (%s) event %s frozen", - model, model->desc->cache.types[0]->name, name); - - model->listeners.freeze[event_id]++; - return model->listeners.freeze[event_id]; -} - -EAPI int -eina_model_event_callback_thaw(Eina_Model *model, const char *name) -{ - int event_id; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(name, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(model->listeners.freeze, -1); - - event_id = _eina_model_description_event_id_find(model->desc, name); - if (event_id < 0) return -1; - - model->listeners.freeze[event_id]--; - if (model->listeners.freeze[event_id] == 0) - DBG("model %p (%s) event %s unfrozen", - model, model->desc->cache.types[0]->name, name); - return model->listeners.freeze[event_id]; -} - -EAPI Eina_Model * -eina_model_copy(const Eina_Model *model) -{ - const Eina_Model_Description *desc; - Eina_Model *copy; - unsigned int i; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - desc = model->desc; - copy = eina_model_new(desc->cache.types[0]); - EINA_SAFETY_ON_NULL_RETURN_VAL(copy, NULL); - - /* call copy of every type in the reverse order, - * they should not call parent's copy. - */ - for (i = desc->total.types; i > 0; i--) - { - if (desc->cache.types[i - 1]->copy) - { - if (!desc->cache.types[i - 1]->copy(model, copy)) - goto failed; - } - } - - /* call copy of every interface in the reverse order, - * they should not call parent's copy. - */ - for (i = desc->total.ifaces; i > 0; i--) - { - if (desc->cache.ifaces[i - 1]->copy) - { - if (!desc->cache.ifaces[i - 1]->copy(model, copy)) - goto failed; - } - } - - return copy; - - failed: - ERR("Failed to copy model %p %s", model, desc->cache.types[0]->name); - eina_model_del(copy); - return NULL; -} - -EAPI Eina_Model * -eina_model_deep_copy(const Eina_Model *model) -{ - const Eina_Model_Description *desc; - Eina_Model *deep_copy; - unsigned int i; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - desc = model->desc; - deep_copy = eina_model_new(desc->cache.types[0]); - EINA_SAFETY_ON_NULL_RETURN_VAL(deep_copy, NULL); - - /* call deep_copy of every type in the reverse order, - * they should not call parent's deep_copy. - */ - for (i = desc->total.types; i > 0; i--) - { - if (desc->cache.types[i - 1]->deep_copy) - { - if (!desc->cache.types[i - 1]->deep_copy(model, deep_copy)) - goto failed; - } - } - - /* call deep_copy of every interface in the reverse order, - * they should not call parent's deep_copy. - */ - for (i = desc->total.ifaces; i > 0; i--) - { - if (desc->cache.ifaces[i - 1]->deep_copy) - { - if (!desc->cache.ifaces[i - 1]->deep_copy(model, deep_copy)) - goto failed; - } - } - - return deep_copy; - - failed: - ERR("Failed to deep copy model %p %s", model, desc->cache.types[0]->name); - eina_model_del(deep_copy); - return NULL; -} - -EAPI int -eina_model_compare(const Eina_Model *a, const Eina_Model *b) -{ - const Eina_Model_Description *desc_a, *desc_b; - Eina_Bool ok; - int cmp = -1; - - EINA_MODEL_INSTANCE_CHECK_VAL(a, -1); - EINA_MODEL_INSTANCE_CHECK_VAL(b, -1); - desc_a = a->desc; - desc_b = b->desc; - - if ((!desc_a->ops.type.compare) && (!desc_b->ops.type.compare)) - { - ERR("Models %p (%s) and %p (%s) can't compare", - a, desc_a->cache.types[0]->name, - b, desc_b->cache.types[0]->name); - eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING); - return -1; - } - else if ((desc_a->ops.type.compare) && (desc_b->ops.type.compare)) - { - ok = desc_a->ops.type.compare(a, b, &cmp); - if (!ok) - { - ok = desc_b->ops.type.compare(b, a, &cmp); - if (ok) - cmp = -cmp; /* swapped sides! */ - } - } - else if (desc_a->ops.type.compare) - ok = desc_a->ops.type.compare(a, b, &cmp); - else - { - ok = desc_b->ops.type.compare(b, a, &cmp); - if (ok) - cmp = -cmp; /* swapped sides! */ - } - - if (!ok) - { - ERR("Could not compare models %p (%s) and %p (%s)", - a, desc_a->cache.types[0]->name, - b, desc_b->cache.types[0]->name); - eina_error_set(EINA_ERROR_MODEL_FAILED); - return -1; - } - - return cmp; -} - -EAPI Eina_Bool -eina_model_load(Eina_Model *model) -{ - Eina_Bool ret; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE); - - eina_error_set(0); - if (model->desc->ops.type.load) - { - ret = model->desc->ops.type.load(model); - if (ret) - _eina_model_event_callback_call(model, _eina_model_str_loaded, NULL); - } - else - { - eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING); - ret = EINA_FALSE; - ERR("Method load() not implemented for model %p (%s)", - model, model->desc->cache.types[0]->name); - } - - return ret; -} - -EAPI Eina_Bool -eina_model_unload(Eina_Model *model) -{ - Eina_Bool ret; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE); - - eina_error_set(0); - if (model->desc->ops.type.unload) - { - ret = model->desc->ops.type.unload(model); - if (ret) - _eina_model_event_callback_call - (model, _eina_model_str_unloaded, NULL); - } - else - { - eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING); - ret = EINA_FALSE; - ERR("Method unload() not implemented for model %p (%s)", - model, model->desc->cache.types[0]->name); - } - - return ret; -} - -EAPI Eina_Bool -eina_model_property_get(const Eina_Model *model, const char *name, Eina_Value *value) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE); - EINA_MODEL_TYPE_CALL_MANDATORY_RETURN(model, property_get, EINA_FALSE, - name, value); -} - -EAPI Eina_Bool -eina_model_property_set(Eina_Model *model, const const char *name, const Eina_Value *value) -{ - Eina_Bool ret; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), EINA_FALSE); - - eina_error_set(0); - if (model->desc->ops.type.property_set) - { - ret = model->desc->ops.type.property_set(model, name, value); - if (ret) - _eina_model_event_callback_call - (model, _eina_model_str_property_set, name); - } - else - { - eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING); - ret = EINA_FALSE; - ERR("Method property_set() not implemented for model %p (%s)", - model, model->desc->cache.types[0]->name); - } - - return ret; -} - -EAPI Eina_Bool -eina_model_property_del(Eina_Model *model, const char *name) -{ - Eina_Bool ret; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE); - - eina_error_set(0); - if (model->desc->ops.type.property_del) - { - ret = model->desc->ops.type.property_del(model, name); - if (ret) - _eina_model_event_callback_call - (model, _eina_model_str_property_del, name); - } - else - { - eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING); - ret = EINA_FALSE; - ERR("Method property_del() not implemented for model %p (%s)", - model, model->desc->cache.types[0]->name); - } - - return ret; -} - -EAPI Eina_List * -eina_model_properties_names_list_get(const Eina_Model *model) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - EINA_MODEL_TYPE_CALL_OPTIONAL_RETURN(model, properties_names_list_get, NULL); -} - -EAPI void -eina_model_properties_names_list_free(Eina_List *list) -{ - const char *str; - EINA_LIST_FREE(list, str) - eina_stringshare_del(str); -} - -EAPI int -eina_model_child_count(const Eina_Model *model) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, -1); - EINA_MODEL_TYPE_CALL_OPTIONAL_RETURN(model, child_count, 0); -} - -EAPI Eina_Model * -eina_model_child_get(const Eina_Model *model, unsigned int position) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - EINA_MODEL_TYPE_CALL_RETURN(model, child_get, NULL, position); -} - -EAPI Eina_Bool -eina_model_child_set(Eina_Model *model, unsigned int position, Eina_Model *child) -{ - Eina_Bool ret; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE); - EINA_MODEL_INSTANCE_CHECK_VAL(child, EINA_FALSE); - - eina_error_set(0); - if (model->desc->ops.type.child_set) - { - ret = model->desc->ops.type.child_set(model, position, child); - if (ret) - _eina_model_event_callback_call - (model, _eina_model_str_child_set, &position); - } - else - { - eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING); - ret = EINA_FALSE; - ERR("Method child_set() not implemented for model %p (%s)", - model, model->desc->cache.types[0]->name); - } - - return ret; -} - -EAPI Eina_Bool -eina_model_child_del(Eina_Model *model, unsigned int position) -{ - Eina_Bool ret; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE); - - eina_error_set(0); - if (model->desc->ops.type.child_del) - { - ret = model->desc->ops.type.child_del(model, position); - if (ret) - { - _eina_model_event_callback_call - (model, _eina_model_str_child_del, &position); - _eina_model_event_callback_call - (model, _eina_model_str_children_changed, NULL); - } - } - else - { - eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING); - ret = EINA_FALSE; - ERR("Method child_del() not implemented for model %p (%s)", - model, model->desc->cache.types[0]->name); - } - - return ret; -} - -EAPI Eina_Bool -eina_model_child_insert_at(Eina_Model *model, unsigned int position, Eina_Model *child) -{ - Eina_Bool ret; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(child, EINA_FALSE); - - eina_error_set(0); - if (model->desc->ops.type.child_insert_at) - { - ret = model->desc->ops.type.child_insert_at(model, position, child); - if (ret) - { - _eina_model_event_callback_call - (model, _eina_model_str_child_inserted, &position); - _eina_model_event_callback_call - (model, _eina_model_str_children_changed, NULL); - } - } - else - { - eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING); - ret = EINA_FALSE; - ERR("Method child_insert_at() not implemented for model %p (%s)", - model, model->desc->cache.types[0]->name); - } - - return ret; -} - -EAPI int -eina_model_child_append(Eina_Model *model, Eina_Model *child) -{ - Eina_Bool ret; - int position; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(child, -1); - - position = eina_model_child_count(model); - if (position < 0) - return -1; - - eina_error_set(0); - if (model->desc->ops.type.child_insert_at) - { - ret = model->desc->ops.type.child_insert_at(model, position, child); - if (ret) - { - _eina_model_event_callback_call - (model, _eina_model_str_child_inserted, &position); - _eina_model_event_callback_call - (model, _eina_model_str_children_changed, NULL); - } - } - else - { - eina_error_set(EINA_ERROR_MODEL_METHOD_MISSING); - ret = EINA_FALSE; - ERR("Method child_insert_at() not implemented for model %p (%s)", - model, model->desc->cache.types[0]->name); - } - - return ret ? position : -1; -} - -EAPI int -eina_model_child_find(const Eina_Model *model, unsigned int start_position, const Eina_Model *other) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(other, -1); - EINA_MODEL_TYPE_CALL_RETURN(model, child_find, -1, start_position, other); -} - -EAPI int -eina_model_child_criteria_match(const Eina_Model *model, unsigned int start_position, Eina_Each_Cb match, const void *data) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(match, -1); - EINA_MODEL_TYPE_CALL_RETURN(model, child_criteria_match, -1, - start_position, match, data); -} - -EAPI Eina_Bool -eina_model_child_sort(Eina_Model *model, Eina_Compare_Cb compare) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(compare, EINA_FALSE); - EINA_MODEL_TYPE_CALL(model, child_sort, compare); - _eina_model_event_callback_call - (model, _eina_model_str_children_changed, NULL); - return EINA_TRUE; -} - -EAPI Eina_Iterator * -eina_model_child_iterator_get(Eina_Model *model) -{ - int count; - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - count = eina_model_child_count(model); - if (count < 0) - return NULL; - EINA_MODEL_TYPE_CALL_RETURN(model, child_iterator_get, NULL, 0, count); -} - -EAPI Eina_Iterator * -eina_model_child_slice_iterator_get(Eina_Model *model, unsigned int start, unsigned int count) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - EINA_MODEL_TYPE_CALL_RETURN(model, child_iterator_get, NULL, start, count); -} - -EAPI Eina_Iterator * -eina_model_child_reversed_iterator_get(Eina_Model *model) -{ - int count; - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - count = eina_model_child_count(model); - if (count < 0) - return NULL; - EINA_MODEL_TYPE_CALL_RETURN(model, child_reversed_iterator_get, NULL, - 0, count); -} - -EAPI Eina_Iterator * -eina_model_child_slice_reversed_iterator_get(Eina_Model *model, unsigned int start, unsigned int count) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - EINA_MODEL_TYPE_CALL_RETURN(model, child_reversed_iterator_get, NULL, - start, count); -} - -EAPI Eina_Iterator * -eina_model_child_sorted_iterator_get(Eina_Model *model, Eina_Compare_Cb compare) -{ - int count; - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(compare, NULL); - count = eina_model_child_count(model); - if (count < 0) - return NULL; - EINA_MODEL_TYPE_CALL_RETURN(model, child_sorted_iterator_get, NULL, - 0, count, compare); -} - -EAPI Eina_Iterator * -eina_model_child_slice_sorted_iterator_get(Eina_Model *model, unsigned int start, unsigned int count, Eina_Compare_Cb compare) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(compare, NULL); - EINA_MODEL_TYPE_CALL_RETURN(model, child_sorted_iterator_get, NULL, - start, count, compare); -} - -EAPI Eina_Iterator * -eina_model_child_filtered_iterator_get(Eina_Model *model, Eina_Each_Cb match, const void *data) -{ - int count; - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(match, NULL); - count = eina_model_child_count(model); - if (count < 0) - return NULL; - EINA_MODEL_TYPE_CALL_RETURN(model, child_filtered_iterator_get, NULL, - 0, count, match, data); -} - -EAPI Eina_Iterator * -eina_model_child_slice_filtered_iterator_get(Eina_Model *model, unsigned int start, unsigned int count, Eina_Each_Cb match, const void *data) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(match, NULL); - EINA_MODEL_TYPE_CALL_RETURN(model, child_filtered_iterator_get, NULL, - start, count, match, data); -} - -EAPI char * -eina_model_to_string(const Eina_Model *model) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - EINA_MODEL_TYPE_CALL_RETURN(model, to_string, NULL); -} - -/* type functions *****************************************************/ - -EAPI Eina_Bool -eina_model_type_check(const Eina_Model_Type *type) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE); - return _eina_model_type_check(type); -} - -EAPI const char * -eina_model_type_name_get(const Eina_Model_Type *type) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(type, NULL); - EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), NULL); - return type->name; -} - -EAPI const Eina_Model_Type * -eina_model_type_parent_get(const Eina_Model_Type *type) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(type, NULL); - EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), NULL); - return type->parent; -} - -#define EINA_MODEL_TYPE_INSTANCE_CHECK(type, model) \ - EINA_SAFETY_ON_NULL_RETURN(type); \ - EINA_SAFETY_ON_FALSE_RETURN(_eina_model_type_check(type)); \ - EINA_MODEL_INSTANCE_CHECK(model); \ - EINA_SAFETY_ON_FALSE_RETURN(_eina_model_instance_check(model, type)); - -#define EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, retval) \ - EINA_SAFETY_ON_NULL_RETURN_VAL(type, retval); \ - EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), retval); \ - EINA_MODEL_INSTANCE_CHECK_VAL(model, retval); \ - EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_instance_check(model, type), retval); - -EAPI Eina_Bool -eina_model_type_constructor(const Eina_Model_Type *type, Eina_Model *model) -{ - Eina_Bool (*constructor)(Eina_Model *); - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE); - - constructor = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, constructor)); - EINA_SAFETY_ON_NULL_RETURN_VAL(constructor, EINA_FALSE); - - return constructor(model); -} - -EAPI Eina_Bool -eina_model_type_destructor(const Eina_Model_Type *type, Eina_Model *model) -{ - Eina_Bool (*destructor)(Eina_Model *); - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE); - - destructor = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, destructor)); - EINA_SAFETY_ON_NULL_RETURN_VAL(destructor, EINA_FALSE); - - return destructor(model); -} - -EAPI Eina_Bool -eina_model_type_copy(const Eina_Model_Type *type, const Eina_Model *src, Eina_Model *dst) -{ - Eina_Bool (*copy)(const Eina_Model *, Eina_Model *); - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, src, EINA_FALSE); - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, dst, EINA_FALSE); - - copy = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, copy)); - EINA_SAFETY_ON_NULL_RETURN_VAL(copy, EINA_FALSE); - - return copy(src, dst); -} - -EAPI Eina_Bool -eina_model_type_deep_copy(const Eina_Model_Type *type, const Eina_Model *src, Eina_Model *dst) -{ - Eina_Bool (*deep_copy)(const Eina_Model *, Eina_Model *); - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, src, EINA_FALSE); - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, dst, EINA_FALSE); - - deep_copy = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, deep_copy)); - EINA_SAFETY_ON_NULL_RETURN_VAL(deep_copy, EINA_FALSE); - - return deep_copy(src, dst); -} - -EAPI Eina_Bool -eina_model_type_compare(const Eina_Model_Type *type, const Eina_Model *a, const Eina_Model *b, int *cmp) -{ - Eina_Bool (*compare)(const Eina_Model *, const Eina_Model *, int *); - - EINA_SAFETY_ON_NULL_RETURN_VAL(cmp, EINA_FALSE); - *cmp = 0; - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, a, EINA_FALSE); - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, b, EINA_FALSE); - - compare = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, compare)); - EINA_SAFETY_ON_NULL_RETURN_VAL(compare, EINA_FALSE); - - return compare(a, b, cmp); -} - -EAPI Eina_Bool -eina_model_type_load(const Eina_Model_Type *type, Eina_Model *model) -{ - Eina_Bool (*load)(Eina_Model *); - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE); - - load = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, load)); - EINA_SAFETY_ON_NULL_RETURN_VAL(load, EINA_FALSE); - - return load(model); -} - -EAPI Eina_Bool -eina_model_type_unload(const Eina_Model_Type *type, Eina_Model *model) -{ - Eina_Bool (*unload)(Eina_Model *); - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE); - - unload = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, unload)); - EINA_SAFETY_ON_NULL_RETURN_VAL(unload, EINA_FALSE); - - return unload(model); -} - -EAPI Eina_Bool -eina_model_type_property_get(const Eina_Model_Type *type, const Eina_Model *model, const char *name, Eina_Value *value) -{ - Eina_Bool (*property_get)(const Eina_Model *, const char *, Eina_Value *); - - EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE); - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE); - - property_get = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, property_get)); - EINA_SAFETY_ON_NULL_RETURN_VAL(property_get, EINA_FALSE); - - return property_get(model, name, value); -} - -EAPI Eina_Bool -eina_model_type_property_set(const Eina_Model_Type *type, Eina_Model *model, const char *name, const Eina_Value *value) -{ - Eina_Bool (*property_set)(Eina_Model *, const char *, const Eina_Value *); - - EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), EINA_FALSE); - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE); - - property_set = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, property_set)); - EINA_SAFETY_ON_NULL_RETURN_VAL(property_set, EINA_FALSE); - - return property_set(model, name, value); -} - -EAPI Eina_Bool -eina_model_type_property_del(const Eina_Model_Type *type, Eina_Model *model, const char *name) -{ - Eina_Bool (*property_del)(const Eina_Model *, const char *); - - EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE); - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE); - - property_del = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, property_del)); - EINA_SAFETY_ON_NULL_RETURN_VAL(property_del, EINA_FALSE); - - return property_del(model, name); -} - -EAPI Eina_List * -eina_model_type_properties_names_list_get(const Eina_Model_Type *type, const Eina_Model *model) -{ - Eina_List *(*properties_names_list_get)(const Eina_Model *); - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL); - - properties_names_list_get = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, properties_names_list_get)); - EINA_SAFETY_ON_NULL_RETURN_VAL(properties_names_list_get, NULL); - - return properties_names_list_get(model); -} - -EAPI int -eina_model_type_child_count(const Eina_Model_Type *type, const Eina_Model *model) -{ - int (*child_count)(const Eina_Model *); - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, -1); - - child_count = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, child_count)); - EINA_SAFETY_ON_NULL_RETURN_VAL(child_count, -1); - - return child_count(model); -} - -EAPI Eina_Model * -eina_model_type_child_get(const Eina_Model_Type *type, const Eina_Model *model, unsigned int position) -{ - Eina_Model *(*child_get)(const Eina_Model *, unsigned int); - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL); - - child_get = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, child_get)); - EINA_SAFETY_ON_NULL_RETURN_VAL(child_get, NULL); - - return child_get(model, position); -} - -EAPI Eina_Bool -eina_model_type_child_set(const Eina_Model_Type *type, Eina_Model *model, unsigned int position, Eina_Model *child) -{ - Eina_Bool (*child_set)(Eina_Model *, unsigned int, Eina_Model *); - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE); - EINA_MODEL_INSTANCE_CHECK_VAL(child, EINA_FALSE); - - child_set = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, child_set)); - EINA_SAFETY_ON_NULL_RETURN_VAL(child_set, EINA_FALSE); - - return child_set(model, position, child); -} - -EAPI Eina_Bool -eina_model_type_child_del(const Eina_Model_Type *type, Eina_Model *model, unsigned int position) -{ - Eina_Bool (*child_del)(Eina_Model *, unsigned int); - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE); - - child_del = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, child_del)); - EINA_SAFETY_ON_NULL_RETURN_VAL(child_del, EINA_FALSE); - - return child_del(model, position); -} - -EAPI Eina_Bool -eina_model_type_child_insert_at(const Eina_Model_Type *type, Eina_Model *model, unsigned int position, Eina_Model *child) -{ - Eina_Bool (*child_insert_at)(Eina_Model *, unsigned int, Eina_Model *); - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, EINA_FALSE); - EINA_MODEL_INSTANCE_CHECK_VAL(child, EINA_FALSE); - - child_insert_at = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, child_insert_at)); - EINA_SAFETY_ON_NULL_RETURN_VAL(child_insert_at, EINA_FALSE); - - return child_insert_at(model, position, child); -} - -EAPI int -eina_model_type_child_find(const Eina_Model_Type *type, const Eina_Model *model, unsigned int start_position, const Eina_Model *other) -{ - int (*child_find)(const Eina_Model *, unsigned int, const Eina_Model *); - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, -1); - EINA_MODEL_INSTANCE_CHECK_VAL(other, -1); - - child_find = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, child_find)); - EINA_SAFETY_ON_NULL_RETURN_VAL(child_find, -1); - - return child_find(model, start_position, other); -} - -EAPI int -eina_model_type_child_criteria_match(const Eina_Model_Type *type, const Eina_Model *model, unsigned int start_position, Eina_Each_Cb match, const void *data) -{ - int (*child_criteria_match)(const Eina_Model *, unsigned int, Eina_Each_Cb, const void *); - - EINA_SAFETY_ON_NULL_RETURN_VAL(match, -1); - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, -1); - - child_criteria_match = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, child_criteria_match)); - EINA_SAFETY_ON_NULL_RETURN_VAL(child_criteria_match, -1); - - return child_criteria_match(model, start_position, match, data); -} - -EAPI void -eina_model_type_child_sort(const Eina_Model_Type *type, Eina_Model *model, Eina_Compare_Cb compare) -{ - void (*child_sort)(Eina_Model *, Eina_Compare_Cb); - - EINA_SAFETY_ON_NULL_RETURN(compare); - EINA_MODEL_TYPE_INSTANCE_CHECK(type, model); - - child_sort = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, child_sort)); - EINA_SAFETY_ON_NULL_RETURN(child_sort); - - return child_sort(model, compare); -} - -EAPI Eina_Iterator * -eina_model_type_child_iterator_get(const Eina_Model_Type *type, Eina_Model *model, unsigned int start, unsigned int count) -{ - Eina_Iterator *(*child_iterator_get)(const Eina_Model *, unsigned int, unsigned int); - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL); - - child_iterator_get = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, child_iterator_get)); - EINA_SAFETY_ON_NULL_RETURN_VAL(child_iterator_get, NULL); - - return child_iterator_get(model, start, count); -} - -EAPI Eina_Iterator * -eina_model_type_child_reversed_iterator_get(const Eina_Model_Type *type, Eina_Model *model, unsigned int start, unsigned int count) -{ - Eina_Iterator *(*child_reversed_iterator_get)(const Eina_Model *, unsigned int, unsigned int); - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL); - - child_reversed_iterator_get = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, child_reversed_iterator_get)); - EINA_SAFETY_ON_NULL_RETURN_VAL(child_reversed_iterator_get, NULL); - - return child_reversed_iterator_get(model, start, count); -} - -EAPI Eina_Iterator * -eina_model_type_child_sorted_iterator_get(const Eina_Model_Type *type, Eina_Model *model, unsigned int start, unsigned int count, Eina_Compare_Cb compare) -{ - Eina_Iterator *(*child_sorted_iterator_get)(const Eina_Model *, unsigned int, unsigned int, Eina_Compare_Cb); - - EINA_SAFETY_ON_NULL_RETURN_VAL(compare, NULL); - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL); - - child_sorted_iterator_get = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, child_sorted_iterator_get)); - EINA_SAFETY_ON_NULL_RETURN_VAL(child_sorted_iterator_get, NULL); - - return child_sorted_iterator_get(model, start, count, compare); -} - -EAPI Eina_Iterator * -eina_model_type_child_filtered_iterator_get(const Eina_Model_Type *type, Eina_Model *model, unsigned int start, unsigned int count, Eina_Each_Cb match, const void *data) -{ - Eina_Iterator *(*child_filtered_iterator_get)(const Eina_Model *, unsigned int, unsigned int, Eina_Each_Cb, const void *); - - EINA_SAFETY_ON_NULL_RETURN_VAL(match, NULL); - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL); - - child_filtered_iterator_get = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, child_filtered_iterator_get)); - EINA_SAFETY_ON_NULL_RETURN_VAL(child_filtered_iterator_get, NULL); - - return child_filtered_iterator_get(model, start, count, match, data); -} - -EAPI char * -eina_model_type_to_string(const Eina_Model_Type *type, const Eina_Model *model) -{ - char *(*to_string)(const Eina_Model *); - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL); - - to_string = _eina_model_type_find_offset - (type, offsetof(Eina_Model_Type, to_string)); - EINA_SAFETY_ON_NULL_RETURN_VAL(to_string, NULL); - - return to_string(model); -} - -EAPI Eina_Bool -eina_model_type_subclass_setup(Eina_Model_Type *type, const Eina_Model_Type *parent) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(parent, EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(parent), EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL(type->version == EINA_MODEL_TYPE_VERSION, - EINA_FALSE); - - type->parent = parent; - type->type_size = parent->type_size; - type->interfaces = NULL; - type->events = NULL; - - type->setup = NULL; - type->flush = NULL; - type->constructor = NULL; - type->destructor = NULL; - type->copy = NULL; - type->deep_copy = NULL; - type->compare = NULL; - type->load = NULL; - type->unload = NULL; - type->property_get = NULL; - type->property_set = NULL; - type->property_del = NULL; - type->properties_names_list_get = NULL; - type->child_count = NULL; - type->child_get = NULL; - type->child_set = NULL; - type->child_del = NULL; - type->child_insert_at = NULL; - type->child_find = NULL; - type->child_criteria_match = NULL; - type->child_sort = NULL; - type->child_iterator_get = NULL; - type->child_reversed_iterator_get = NULL; - type->child_sorted_iterator_get = NULL; - type->child_filtered_iterator_get = NULL; - type->to_string = NULL; - type->__extension_ptr0 = NULL; - type->__extension_ptr1 = NULL; - type->__extension_ptr2 = NULL; - type->__extension_ptr3 = NULL; - - if (type->type_size > sizeof(Eina_Model_Type)) - { - unsigned char *p = (unsigned char *)type; - p += sizeof(Eina_Model_Type); - memset(p, 0, type->type_size - sizeof(Eina_Model_Type)); - } - - return EINA_TRUE; -} - -EAPI Eina_Bool -eina_model_type_subclass_check(const Eina_Model_Type *type, const Eina_Model_Type *self_or_parent) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(self_or_parent, EINA_FALSE); - - for (; type != NULL; type = type->parent) - { - if (type == self_or_parent) - return EINA_TRUE; - } - - return EINA_FALSE; -} - -static inline const Eina_Model_Interface * -_eina_model_type_interface_get(const Eina_Model_Type *type, const char *name, Eina_Bool ptr_cmp __UNUSED__) -{ - const Eina_Model_Interface **itr; - - if (!type) - return NULL; - - if (!type->interfaces) - return _eina_model_type_interface_get(type->parent, name, ptr_cmp); - - { - for (itr = type->interfaces ; itr != NULL ; itr++) - if (strcmp((*itr)->name, name) == 0) - return *itr; - } - - return NULL; -} - -static inline Eina_Bool -_eina_model_interface_check(const Eina_Model_Interface *iface) -{ - EINA_SAFETY_ON_FALSE_RETURN_VAL - (iface->version == EINA_MODEL_INTERFACE_VERSION, EINA_FALSE); - return EINA_TRUE; -} - -EAPI const Eina_Model_Interface * -eina_model_type_interface_get(const Eina_Model_Type *type, const char *name) -{ - const Eina_Model_Interface *iface; - - EINA_SAFETY_ON_NULL_RETURN_VAL(type, NULL); - EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), NULL); - - /* search for pointer, make speed-aware users fast */ - iface = _eina_model_type_interface_get(type, name, EINA_TRUE); - - if (!iface) - { - /* search using strcmp(), slow users don't care */ - iface = _eina_model_type_interface_get(type, name, EINA_FALSE); - } - else if (!_eina_model_interface_check(iface)) - iface = NULL; - - return iface; -} - -EAPI void * -eina_model_type_private_data_get(const Eina_Model *model, const Eina_Model_Type *type) -{ - const Eina_Model_Description *desc; - unsigned int i; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(type, NULL); - EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_type_check(type), NULL); - - desc = model->desc; - - for (i = 0; i < desc->total.types; i++) - if (desc->cache.types[i] == type) - return model->privates[i]; - - CRITICAL("Model %p (%s) is not an instance of type %p (%s)", - model, desc->cache.types[0]->name, - type, type->name); - return NULL; -} - -EAPI const void * -eina_model_method_offset_resolve(const Eina_Model *model, unsigned int offset) -{ - const Eina_Model_Description *desc; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - EINA_SAFETY_ON_FALSE_RETURN_VAL(offset >= sizeof(Eina_Model_Type), NULL); - EINA_SAFETY_ON_FALSE_RETURN_VAL(offset % sizeof(void *) == 0, NULL); - - desc = model->desc; - EINA_SAFETY_ON_FALSE_RETURN_VAL - (offset + sizeof(void *) <= desc->cache.types[0]->type_size, NULL); - - offset -= sizeof(Eina_Model_Type); - offset /= sizeof(void *); - return desc->ops.type.extension[offset]; -} - -EAPI const void * -eina_model_type_method_offset_resolve(const Eina_Model_Type *type, const Eina_Model *model, unsigned int offset) -{ - const Eina_Model_Description *desc; - - EINA_MODEL_TYPE_INSTANCE_CHECK_VAL(type, model, NULL); - EINA_SAFETY_ON_FALSE_RETURN_VAL(offset >= sizeof(Eina_Model_Type), NULL); - EINA_SAFETY_ON_FALSE_RETURN_VAL(offset % sizeof(void *) == 0, NULL); - - desc = model->desc; - EINA_SAFETY_ON_FALSE_RETURN_VAL - (offset + sizeof(void *) <= desc->cache.types[0]->type_size, NULL); - - return _eina_model_type_find_offset(type, offset); -} - -/* interface functions ************************************************/ - -EAPI Eina_Bool -eina_model_interface_check(const Eina_Model_Interface *iface) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(iface, EINA_FALSE); - return _eina_model_interface_check(iface); -} - -EAPI void * -eina_model_interface_private_data_get(const Eina_Model *model, const Eina_Model_Interface *iface) -{ - const Eina_Model_Description *desc; - unsigned int i; - - EINA_MODEL_INSTANCE_CHECK_VAL(model, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(iface, NULL); - EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_interface_check(iface), NULL); - - desc = model->desc; - - for (i = 0; i < desc->total.ifaces; i++) - if (desc->cache.ifaces[i] == iface) - return model->privates[desc->total.types + i]; - - CRITICAL("Model %p (%s) does not implement interface %p (%s)", - model, desc->cache.types[0]->name, - iface, iface->name); - return NULL; -} - -static Eina_Bool -_eina_model_interface_implemented(const Eina_Model *model, const Eina_Model_Interface *iface) -{ - const Eina_Model_Interface **itr, **itr_end; - - itr = model->desc->cache.ifaces; - itr_end = itr + model->desc->total.ifaces; - - for (; itr < itr_end; itr++) - if (*itr == iface) - return EINA_TRUE; - - return EINA_FALSE; -} - -EAPI Eina_Bool -eina_model_interface_implemented(const Eina_Model *model, const Eina_Model_Interface *iface) -{ - EINA_MODEL_INSTANCE_CHECK_VAL(model, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(iface, EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_interface_check(iface), - EINA_FALSE); - return _eina_model_interface_implemented(model, iface); -} - -#define EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK(iface, model) \ - EINA_SAFETY_ON_NULL_RETURN(iface); \ - EINA_SAFETY_ON_FALSE_RETURN(_eina_model_interface_check(iface)); \ - EINA_MODEL_INSTANCE_CHECK(model); \ - EINA_SAFETY_ON_FALSE_RETURN(_eina_model_interface_implemented(model, iface)); - -#define EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, retval) \ - EINA_SAFETY_ON_NULL_RETURN_VAL(iface, retval); \ - EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_interface_check(iface), retval); \ - EINA_MODEL_INSTANCE_CHECK_VAL(model, retval); \ - EINA_SAFETY_ON_FALSE_RETURN_VAL(_eina_model_interface_implemented(model, iface), retval); - - -EAPI Eina_Bool -eina_model_interface_constructor(const Eina_Model_Interface *iface, Eina_Model *model) -{ - Eina_Bool (*constructor)(Eina_Model *); - - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - - constructor = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface, constructor)); - EINA_SAFETY_ON_NULL_RETURN_VAL(constructor, EINA_FALSE); - return constructor(model); -} - -EAPI Eina_Bool -eina_model_interface_destructor(const Eina_Model_Interface *iface, Eina_Model *model) -{ - Eina_Bool (*destructor)(Eina_Model *); - - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - - destructor = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface, destructor)); - EINA_SAFETY_ON_NULL_RETURN_VAL(destructor, EINA_FALSE); - return destructor(model); -} - -EAPI Eina_Bool -eina_model_interface_copy(const Eina_Model_Interface *iface, const Eina_Model *src, Eina_Model *dst) -{ - Eina_Bool (*copy)(const Eina_Model *, Eina_Model *); - - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, src, EINA_FALSE); - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, dst, EINA_FALSE); - - copy = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface, copy)); - EINA_SAFETY_ON_NULL_RETURN_VAL(copy, EINA_FALSE); - return copy(src, dst); -} - -EAPI Eina_Bool -eina_model_interface_deep_copy(const Eina_Model_Interface *iface, const Eina_Model *src, Eina_Model *dst) -{ - Eina_Bool (*deep_copy)(const Eina_Model *, Eina_Model *); - - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, src, EINA_FALSE); - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, dst, EINA_FALSE); - - deep_copy = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface, deep_copy)); - EINA_SAFETY_ON_NULL_RETURN_VAL(deep_copy, EINA_FALSE); - return deep_copy(src, dst); -} - -EAPI const void -*eina_model_interface_method_offset_resolve(const Eina_Model_Interface *iface, const Eina_Model *model, unsigned int offset) -{ - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, NULL); - EINA_SAFETY_ON_FALSE_RETURN_VAL(offset >= sizeof(Eina_Model_Interface), NULL); - EINA_SAFETY_ON_FALSE_RETURN_VAL(offset % sizeof(void *) == 0, NULL); - return _eina_model_interface_find_offset(iface, offset); -} - - -/* Eina_Model_Interface_Properties ************************************/ - -EAPI Eina_Bool -eina_model_interface_properties_compare(const Eina_Model_Interface *iface, const Eina_Model *a, const Eina_Model *b, int *cmp) -{ - Eina_Bool (*compare)(const Eina_Model *, const Eina_Model *, int *cmp); - - EINA_SAFETY_ON_NULL_RETURN_VAL(cmp, EINA_FALSE); - - *cmp = 0; - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, a, EINA_FALSE); - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, b, EINA_FALSE); - - compare = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface_Properties, compare)); - EINA_SAFETY_ON_NULL_RETURN_VAL(compare, EINA_FALSE); - return compare(a, b, cmp); -} - -EAPI Eina_Bool -eina_model_interface_properties_load(const Eina_Model_Interface *iface, Eina_Model *model) -{ - Eina_Bool (*load)(Eina_Model *); - Eina_Bool ret; - - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - - load = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface_Properties, load)); - EINA_SAFETY_ON_NULL_RETURN_VAL(load, EINA_FALSE); - ret = load(model); - - if (ret) - _eina_model_event_callback_call - (model, _eina_model_str_properties_loaded, NULL); - - return ret; -} - -EAPI Eina_Bool -eina_model_interface_properties_unload(const Eina_Model_Interface *iface, Eina_Model *model) -{ - Eina_Bool (*unload)(Eina_Model *); - Eina_Bool ret; - - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - - unload = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface_Properties, unload)); - EINA_SAFETY_ON_NULL_RETURN_VAL(unload, EINA_FALSE); - ret = unload(model); - - if (ret) - _eina_model_event_callback_call - (model, _eina_model_str_properties_unloaded, NULL); - - return ret; -} - -EAPI Eina_Bool -eina_model_interface_properties_get(const Eina_Model_Interface *iface, const Eina_Model *model, const char *name, Eina_Value *value) -{ - Eina_Bool (*get)(const Eina_Model *, const char *, Eina_Value *); - - EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE); - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - - get = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface_Properties, get)); - EINA_SAFETY_ON_NULL_RETURN_VAL(get, EINA_FALSE); - return get(model, name, value); -} - -EAPI Eina_Bool -eina_model_interface_properties_set(const Eina_Model_Interface *iface, Eina_Model *model, const char *name, const Eina_Value *value) -{ - Eina_Bool (*set)(Eina_Model *, const char *, const Eina_Value *); - - EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), EINA_FALSE); - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - - set = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface_Properties, set)); - EINA_SAFETY_ON_NULL_RETURN_VAL(set, EINA_FALSE); - return set(model, name, value); -} - -EAPI Eina_Bool -eina_model_interface_properties_del(const Eina_Model_Interface *iface, Eina_Model *model, const char *name) -{ - Eina_Bool (*del)(Eina_Model *, const char *); - - EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE); - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - - del = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface_Properties, del)); - EINA_SAFETY_ON_NULL_RETURN_VAL(del, EINA_FALSE); - return del(model, name); -} - -EAPI Eina_List * -eina_model_interface_properties_names_list_get(const Eina_Model_Interface *iface, const Eina_Model *model) -{ - Eina_List *(*names_list_get)(const Eina_Model *); - - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, NULL); - - names_list_get = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface_Properties, names_list_get)); - EINA_SAFETY_ON_NULL_RETURN_VAL(names_list_get, NULL); - return names_list_get(model); -} - -/* Eina_Model_Interface_Children **************************************/ - -EAPI Eina_Bool -eina_model_interface_children_compare(const Eina_Model_Interface *iface, const Eina_Model *a, const Eina_Model *b, int *cmp) -{ - Eina_Bool (*compare)(const Eina_Model *, const Eina_Model *, int *); - - EINA_SAFETY_ON_NULL_RETURN_VAL(cmp, EINA_FALSE); - - *cmp = 0; - - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, a, EINA_FALSE); - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, b, EINA_FALSE); - - compare = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface_Children, compare)); - EINA_SAFETY_ON_NULL_RETURN_VAL(compare, EINA_FALSE); - return compare(a, b, cmp); -} - -EAPI Eina_Bool -eina_model_interface_children_load(const Eina_Model_Interface *iface, Eina_Model *model) -{ - Eina_Bool (*load)(Eina_Model *); - Eina_Bool ret; - - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - - load = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface_Children, load)); - EINA_SAFETY_ON_NULL_RETURN_VAL(load, EINA_FALSE); - ret = load(model); - - if (ret) - _eina_model_event_callback_call - (model, _eina_model_str_children_loaded, NULL); - - return ret; -} - -EAPI Eina_Bool -eina_model_interface_children_unload(const Eina_Model_Interface *iface, Eina_Model *model) -{ - Eina_Bool (*unload)(Eina_Model *); - Eina_Bool ret; - - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - - unload = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface_Children, unload)); - EINA_SAFETY_ON_NULL_RETURN_VAL(unload, EINA_FALSE); - ret = unload(model); - - if (ret) - _eina_model_event_callback_call - (model, _eina_model_str_children_unloaded, NULL); - - return ret; -} - -EAPI int -eina_model_interface_children_count(const Eina_Model_Interface *iface, const Eina_Model *model) -{ - int (*count)(const Eina_Model *); - - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, -1); - - count = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface_Children, count)); - EINA_SAFETY_ON_NULL_RETURN_VAL(count, -1); - return count(model); -} - -EAPI Eina_Model * -eina_model_interface_children_get(const Eina_Model_Interface *iface, const Eina_Model *model, unsigned int position) -{ - Eina_Model *(*get)(const Eina_Model *, unsigned int); - - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, NULL); - - get = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface_Children, get)); - EINA_SAFETY_ON_NULL_RETURN_VAL(get, NULL); - return get(model, position); -} - -EAPI Eina_Bool eina_model_interface_children_set(const Eina_Model_Interface *iface, Eina_Model *model, unsigned int position, Eina_Model *child) -{ - Eina_Bool (*set)(const Eina_Model *, unsigned int, Eina_Model *); - - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - EINA_MODEL_INSTANCE_CHECK_VAL(child, EINA_FALSE); - - set = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface_Children, set)); - EINA_SAFETY_ON_NULL_RETURN_VAL(set, EINA_FALSE); - return set(model, position, child); -} - -EAPI Eina_Bool -eina_model_interface_children_del(const Eina_Model_Interface *iface, Eina_Model *model, unsigned int position) -{ - Eina_Bool (*del)(Eina_Model *, unsigned int); - - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - - del = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface_Children, del)); - EINA_SAFETY_ON_NULL_RETURN_VAL(del, EINA_FALSE); - return del(model, position); -} - - -EAPI Eina_Bool -eina_model_interface_children_insert_at(const Eina_Model_Interface *iface, Eina_Model *model, unsigned int position, Eina_Model *child) -{ - Eina_Bool (*insert_at)(const Eina_Model *, unsigned int, Eina_Model *); - - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL(iface, model, EINA_FALSE); - EINA_MODEL_INSTANCE_CHECK_VAL(child, EINA_FALSE); - - insert_at = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface_Children, insert_at)); - EINA_SAFETY_ON_NULL_RETURN_VAL(insert_at, EINA_FALSE); - return insert_at(model, position, child); -} - -EAPI void -eina_model_interface_children_sort(const Eina_Model_Interface *iface, Eina_Model *model, Eina_Compare_Cb compare) -{ - void (*sort)(const Eina_Model *, Eina_Compare_Cb); - - EINA_SAFETY_ON_NULL_RETURN(compare); - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK(iface, model); - - sort = _eina_model_interface_find_offset - (iface, offsetof(Eina_Model_Interface_Children, sort)); - EINA_SAFETY_ON_NULL_RETURN(sort); - return sort(model, compare); -} - -static Eina_Bool -_eina_model_struct_set(Eina_Model *m, const Eina_Value_Struct_Desc *desc, void *memory) -{ - Eina_Value_Struct st = {desc, memory}; - Eina_Value *val = eina_model_interface_private_data_get - (m, &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base); - return eina_value_pset(val, &st); -} - -EAPI Eina_Model * -eina_model_struct_new(const Eina_Value_Struct_Desc *desc) -{ - Eina_Model *m; - - EINA_SAFETY_ON_NULL_RETURN_VAL(desc, NULL); - EINA_SAFETY_ON_FALSE_RETURN_VAL - (desc->version == EINA_VALUE_STRUCT_DESC_VERSION, NULL); - - m = eina_model_new(EINA_MODEL_TYPE_STRUCT); - EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL); - - EINA_SAFETY_ON_FALSE_GOTO(_eina_model_struct_set(m, desc, NULL), error); - return m; - - error: - eina_model_del(m); - return NULL; -} - -EAPI Eina_Model * -eina_model_type_struct_new(const Eina_Model_Type *type, const Eina_Value_Struct_Desc *desc) -{ - Eina_Model *m; - - EINA_SAFETY_ON_FALSE_RETURN_VAL - (eina_model_type_subclass_check(type, EINA_MODEL_TYPE_STRUCT), NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(desc, NULL); - EINA_SAFETY_ON_FALSE_RETURN_VAL - (desc->version == EINA_VALUE_STRUCT_DESC_VERSION, NULL); - - m = eina_model_new(type); - EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL); - - EINA_SAFETY_ON_FALSE_GOTO(_eina_model_struct_set(m, desc, NULL), error); - return m; - - error: - eina_model_del(m); - return NULL; -} - -EAPI Eina_Bool -eina_model_struct_set(Eina_Model *model, const Eina_Value_Struct_Desc *desc, void *memory) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(desc, EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL - (desc->version == EINA_VALUE_STRUCT_DESC_VERSION, EINA_FALSE); - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL - (&_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base, model, EINA_FALSE); - - return _eina_model_struct_set(model, desc, memory); -} - -EAPI Eina_Bool -eina_model_struct_get(const Eina_Model *model, const Eina_Value_Struct_Desc **p_desc, void **p_memory) -{ - const Eina_Value *val; - Eina_Value_Struct st; - - EINA_SAFETY_ON_NULL_RETURN_VAL(p_desc, EINA_FALSE); - - *p_desc = NULL; - if (p_memory) *p_memory = NULL; - - EINA_MODEL_INTERFACE_IMPLEMENTED_CHECK_VAL - (&_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base, model, EINA_FALSE); - - val = eina_model_interface_private_data_get - (model, &_EINA_MODEL_INTERFACE_PROPERTIES_STRUCT.base); - - EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_pget(val, &st), EINA_FALSE); - - *p_desc = st.desc; - if (p_memory) *p_memory = st.memory; - return EINA_FALSE; -} - -EAPI void -eina_models_usage_dump(void) -{ - const Eina_List *l; - const Eina_Model *m; - - eina_lock_take(&_eina_model_debug_list_lock); - - puts("DDD: model refs info (type, holders, backtrace)"); - puts("DDD: -------------- -------------- ---------------------------------"); - - EINA_LIST_FOREACH(_eina_model_debug_list, l, m) - { - Eina_Model_XRef *ref; - - printf("DDD: %14p %14d %s\n", - m, m->refcount, m->desc->cache.types[0]->name); - - EINA_INLIST_FOREACH(m->xrefs, ref) - { - printf("DDD: id: %p '%s'\n", - ref->id, ref->label); - if (ref->backtrace.count) - { - char **symbols; - unsigned int i; - -#ifdef HAVE_BACKTRACE_SYMBOLS - symbols = backtrace_symbols((void * const *)ref->backtrace.symbols, - ref->backtrace.count); -#else - symbols = NULL; -#endif - - printf("DDD: Backtrace: Address Symbol\n"); - for (i = 0; i < ref->backtrace.count; i++) - printf("DDD: %14p %s\n", - ref->backtrace.symbols[i], - symbols ? symbols[i] : "???"); - - free(symbols); - puts("DDD:"); - } - } - } - - eina_lock_release(&_eina_model_debug_list_lock); -} - -EAPI Eina_List * -eina_models_list_get(void) -{ - const Eina_List *l; - Eina_Model *m; - Eina_List *ret = NULL; - - eina_lock_take(&_eina_model_debug_list_lock); - - EINA_LIST_FOREACH(_eina_model_debug_list, l, m) - { - ret = eina_list_append - (ret, eina_model_xref - (m, eina_models_list_get, "eina_models_list_get")); - } - - eina_lock_release(&_eina_model_debug_list_lock); - - return ret; -} - -EAPI void -eina_models_list_free(Eina_List *list) -{ - Eina_Model *m; - - EINA_LIST_FREE(list, m) - eina_model_xunref(m, eina_models_list_get); -} diff --git a/src/lib/eina_module.c b/src/lib/eina_module.c deleted file mode 100644 index 736df0d..0000000 --- a/src/lib/eina_module.c +++ /dev/null @@ -1,603 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_ALLOCA_H -# include <alloca.h> -#elif defined __GNUC__ -# define alloca __builtin_alloca -#elif defined _AIX -# define alloca __alloca -#elif defined _MSC_VER -# include <malloc.h> -# define alloca _alloca -#else -# include <stddef.h> -# ifdef __cplusplus -extern "C" -# endif -void *alloca (size_t); -#endif - -#include <stdlib.h> -#include <stdio.h> -#include <sys/types.h> -#include <string.h> - -#ifdef HAVE_LIBGEN_H -# include <libgen.h> -#endif - -#ifdef HAVE_DLOPEN -# include <dlfcn.h> -#endif - -#ifdef HAVE_EVIL -# include <Evil.h> -#endif - -#ifdef HAVE_ESCAPE -# include <Escape.h> -#endif - -#ifdef HAVE_EXOTIC_H -# include <Exotic.h> -#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, or the init function failed", - 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/src/lib/eina_object.c b/src/lib/eina_object.c deleted file mode 100644 index f82aef3..0000000 --- a/src/lib/eina_object.c +++ /dev/null @@ -1,852 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <string.h> - -#include "eina_private.h" -#include "eina_inlist.h" -#include "eina_rbtree.h" -#include "eina_mempool.h" -#include "eina_trash.h" -#include "eina_log.h" -#include "eina_stringshare.h" -#include "eina_lock.h" - -#include "eina_object.h" - -/*============================================================================* - * Local * - *============================================================================*/ - -/** - * @cond LOCAL - */ - -/* If we are on a 64bits computer user bigger generation and ID */ -/* FIXME: make it GCC independent */ -/* FIXME: maybe having 2^32 objects doesn't make sense and 2^24 are enough - so instead of increasing the object count, we could just add a magic - to first check if the pointer is valid at all (and maybe use a pointer - that will always trigger a segv if we try to use it directly). -*/ -#ifdef _LP64 -typedef unsigned long Eina_Object_ID; -typedef unsigned short Eina_Object_Generation; -# define EINA_GEN_OFFSET 48 -# define EINA_ID_STR "%lu" -#elif _WIN64 -typedef unsigned __int64 Eina_Object_ID; -typedef unsigned short Eina_Object_Generation; -# define EINA_GEN_OFFSET 48 -# define EINA_ID_STR "%I64u" -#else -typedef unsigned int Eina_Object_ID; -typedef unsigned char Eina_Object_Generation; -# define EINA_GEN_OFFSET 24 -# define EINA_ID_STR "%u" -#endif - -typedef struct _Eina_Class_Range Eina_Class_Range; -typedef struct _Eina_Object_Item Eina_Object_Item; -typedef struct _Eina_Range Eina_Range; -typedef struct _Eina_Class_Top Eina_Class_Top; - -struct _Eina_Range -{ - EINA_INLIST; - - unsigned int start; - unsigned int end; -}; - -struct _Eina_Object_Item -{ - EINA_INLIST; - Eina_Class_Range *range; - - Eina_Object_Item *parent; - Eina_Inlist *link; - - unsigned int index; -}; - -struct _Eina_Class_Range -{ - EINA_INLIST; - EINA_RBTREE; - - unsigned int start; - unsigned int end; - unsigned int current; - unsigned int empty_count; - - Eina_Class *type; - Eina_Trash *empty; - - Eina_Object_Item **pointer_array; - Eina_Object_Generation generation_array[1]; -}; - -struct _Eina_Class_Top -{ - Eina_Class *top_parent; - Eina_Rbtree *range; - Eina_Inlist *available; - - unsigned int upper_limit; -}; - -struct _Eina_Class -{ - EINA_INLIST; - - const char *name; - - Eina_Class_Top *top; - - Eina_Class *parent; - Eina_Inlist *childs; - - Eina_Class_Callback constructor; - Eina_Class_Callback destructor; - void *data; - - Eina_Inlist *allocated_range; - - Eina_Mempool *mempool; - unsigned int class_size; - unsigned int object_size; - unsigned int pool_size; - - Eina_Bool repack_needed : 1; - -#ifdef EINA_HAVE_DEBUG_THREADS - pthread_t self; -#endif - Eina_Lock mutex; - - EINA_MAGIC; -}; - -static const char EINA_MAGIC_CLASS_STR[] = "Eina Class"; - -static Eina_Mempool *_eina_class_mp = NULL; -static Eina_Mempool *_eina_top_mp = NULL; -static Eina_Mempool *_eina_range_mp = NULL; -static int _eina_object_log_dom = -1; -static unsigned int _eina_object_item_size = 0; - -#ifdef ERR -#undef ERR -#endif -#define ERR(...) EINA_LOG_DOM_ERR(_eina_object_log_dom, __VA_ARGS__) - -#ifdef DBG -#undef DBG -#endif -#define DBG(...) EINA_LOG_DOM_DBG(_eina_object_log_dom, __VA_ARGS__) - -#define EINA_MAGIC_CHECK_CLASS(d, ...) \ - do { \ - if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_CLASS)) \ - { \ - EINA_MAGIC_FAIL(d, EINA_MAGIC_CLASS); \ - return __VA_ARGS__; \ - } \ - } while(0) - -static int -_eina_rbtree_cmp_range(const Eina_Rbtree *node, const void *key, - __UNUSED__ int length, __UNUSED__ void *data) -{ - Eina_Class_Range *range; - Eina_Object_ID id; - - range = EINA_RBTREE_CONTAINER_GET(node, Eina_Class_Range); - id = (Eina_Object_ID) key; - - if (id < range->start) return -1; - else if (id >= range->end) return 1; - return 0; -} - -static Eina_Rbtree_Direction -_eina_class_direction_range(const Eina_Rbtree *left, - const Eina_Rbtree *right, - __UNUSED__ void *data) -{ - Eina_Class_Range *rl; - Eina_Class_Range *rr; - - rl = EINA_RBTREE_CONTAINER_GET(left, Eina_Class_Range); - rr = EINA_RBTREE_CONTAINER_GET(right, Eina_Class_Range); - - if (rl->start < rr->start) return EINA_RBTREE_LEFT; - return EINA_RBTREE_RIGHT; -} - -/* really destroying a range and handling that case is a complex - problem to solve. Not handling it right now, exposing myself to - DoS. */ -static void -_eina_range_cleanup(Eina_Class_Range *range) -{ - range->current = 0; - range->empty = NULL; -} - -static void -_eina_object_constructor_call(Eina_Class *class, void *object) -{ - if (class->parent) _eina_object_constructor_call(class->parent, object); - - if (class->constructor) class->constructor(class, object, class->data); -} - -static void -_eina_object_destructor_call(Eina_Class *class, void *object) -{ - if (class->destructor) class->destructor(class, object, class->data); - - if (class->parent) _eina_object_destructor_call(class->parent, object); -} - -static Eina_Object* -_eina_object_get(Eina_Object_Item *item) -{ - Eina_Object_Generation gen; - Eina_Object_ID id; - - if (!item) return NULL; - - gen = item->range->generation_array[item->index]; - - id = ((Eina_Object_ID) gen << EINA_GEN_OFFSET) + item->range->start + item->index; - - return (Eina_Object *) id; -} - -static Eina_Object_Item * -_eina_object_find_item(Eina_Class *class, Eina_Object *object) -{ - Eina_Class_Range *matched; - Eina_Object_Item *item; - Eina_Class *search; - Eina_Rbtree *match; - Eina_Object_Generation generation; - Eina_Object_ID id; - Eina_Object_ID idx; - - id = (Eina_Object_ID) object; - idx = id & (((Eina_Object_ID) 1 << EINA_GEN_OFFSET) - 1); - generation = id & !(((Eina_Object_ID) 1 << EINA_GEN_OFFSET) - 1); - - /* Try to find the ID */ - match = eina_rbtree_inline_lookup(class->top->range, - (void*) idx, sizeof (Eina_Object_ID), - _eina_rbtree_cmp_range, NULL); - /* ID not found, invalid pointer ! */ - if (!match) - { - ERR("%p: ID ["EINA_ID_STR"] not found in class hiearchy of [%s].", - object, idx, class->name); - return NULL; - } - matched = EINA_RBTREE_CONTAINER_GET(match, Eina_Class_Range); - - /* generation mismatch, invalid pointer ! */ - if (generation != matched->generation_array[idx - matched->start]) - { - ERR("%p: generation mismatch [%i] vs [%i].", - object, generation, matched->generation_array[idx - matched->start]); - return NULL; - } - - /* does it belong to the right class ? */ - for (search = matched->type; search && search != class; search = search->parent) - ; - - /* class match request or invalid pointer ! */ - if (search != class) - { - ERR("%p: from class [%s] is not in the hierarchie of [%s].", - object, matched->type->name, class->name); - return NULL; - } - - /* retrieve pointer */ - item = matched->pointer_array[id - matched->start]; - /* allocated or invalid pointer ? */ - if (!item) - { - ERR("%p: ID is not allocated.", object); - return NULL; - } - - /* be aware, that because we use eina_trash to store empty pointer after first use, - pointer could be != NULL and still be empty. Need another pool of data somewhere - to store the state of the allocation... Is it needed ? - */ - - return item; -} - -static void -_eina_object_item_del(Eina_Object_Item *item) -{ - Eina_Class *class; - - class = item->range->type; - _eina_object_destructor_call(class, - (unsigned char*) item + _eina_object_item_size); - - eina_trash_push(&item->range->empty, item->range->pointer_array + item->index); - item->range->generation_array[item->index]++; - item->range->empty_count++; - - if (item->range->empty_count == item->range->end - item->range->start) - _eina_range_cleanup(item->range); - item->range = NULL; - - if (item->parent) - item->parent->link = eina_inlist_remove(item->parent->link, EINA_INLIST_GET(item)); - item->parent = NULL; - - while (item->link) - { - Eina_Object_Item *child; - - child = EINA_INLIST_CONTAINER_GET(item->link, Eina_Object_Item); - _eina_object_item_del(child); - } - - eina_mempool_free(class->mempool, item); -} - -static Eina_Class_Range * -_eina_class_empty_range_get(Eina_Inlist *list) -{ - while (list) - { - Eina_Class_Range *range; - - range = EINA_INLIST_CONTAINER_GET(list, Eina_Class_Range); - if (range->empty_count > 0) - return range; - - list = list->next; - } - - return NULL; -} - -static Eina_Class_Range * -_eina_class_range_add(Eina_Class *class) -{ - Eina_Class_Range *range; - unsigned char *tmp; - Eina_Range *av = NULL; - - range = malloc(sizeof (Eina_Class_Range) - + sizeof (Eina_Object_Item*) * class->pool_size - + sizeof (Eina_Object_Generation) * (class->pool_size - 1)); - if (!range) return NULL; - - tmp = (void*) (range + 1); - tmp += sizeof (Eina_Object_Generation) * (class->pool_size - 1); - - range->pointer_array = (Eina_Object_Item**) tmp; - - /* no need to fix generation to a specific value as random value should be just fine */ - memset(range->pointer_array, 0, sizeof (Eina_Object_Item*) * class->pool_size); - - range->current = 0; - range->type = class; - range->empty = NULL; - - /* and now find an empty block */ - EINA_INLIST_FOREACH(class->top->available, av) - if ((av->end - av->start) == class->pool_size) - break; - - if (av) - { - range->start = av->start; - range->end = av->end; - - class->top->available = eina_inlist_remove(class->top->available, - EINA_INLIST_GET(av)); - eina_mempool_free(_eina_range_mp, av); - } - else - { - range->start = class->top->upper_limit; - range->end = range->start + class->pool_size; - class->top->upper_limit = range->end; - } - - return range; -} - -static void -_eina_class_range_del(Eina_Class_Range *range) -{ - Eina_Class_Top *top; - Eina_Range *keep; - - top = range->type->top; - - keep = eina_mempool_malloc(_eina_range_mp, sizeof (Eina_Range)); - if (!keep) - { - ERR("Not enougth memory to keep track of allocated range."); - goto delete_class_range; - } - - keep->start = range->start; - keep->end = range->end; - - top->available = eina_inlist_prepend(top->available, - EINA_INLIST_GET(keep)); - - delete_class_range: - top->range = eina_rbtree_inline_remove(top->range, EINA_RBTREE_GET(range), - _eina_class_direction_range, NULL); - range->type->allocated_range = eina_inlist_remove(range->type->allocated_range, - EINA_INLIST_GET(range)); - free(range); -} - -static void -_eina_class_range_repack(void *dst, void *src, void *data) -{ - Eina_Object_Item *di = dst; - Eina_Object_Item *si = src; - Eina_Class *class = data; - - (void) class; - - si->range->pointer_array[si->index] = di; - - /* FIXME: We could just lock the right Eina_Class_Range - here instead of locking all the Class */ -} - -/** - * @endcond - */ - -Eina_Bool -eina_object_init(void) -{ - _eina_object_log_dom = eina_log_domain_register("eina_object", - EINA_LOG_COLOR_DEFAULT); - if (_eina_object_log_dom < 0) - { - EINA_LOG_ERR("Could not register log domain: eina_list"); - return EINA_FALSE; - } - - _eina_class_mp = eina_mempool_add("chained_mempool", "class", - NULL, sizeof (Eina_Class), 16); - if (!_eina_class_mp) - { - ERR("ERROR: Mempool for Eina_Class cannot be allocated in object init."); - goto on_init_fail; - } - - _eina_top_mp = eina_mempool_add("chained_mempool", "top", - NULL, sizeof (Eina_Class_Top), 16); - if (!_eina_top_mp) - { - ERR("ERROR: Mempool for Eina_Class_Top cannot be allocated in object init."); - goto on_init_fail; - } - - _eina_range_mp = eina_mempool_add("chained_mempool", "range", - NULL, sizeof (Eina_Range), 16); - if (!_eina_range_mp) - { - ERR("ERROR: Mempool for Eina_Class_Top cannot be allocated in object init."); - goto on_init_fail; - } - -#define EMS(n) eina_magic_string_static_set(n, n ## _STR) - EMS(EINA_MAGIC_CLASS); -#undef EMS - - _eina_object_item_size = eina_mempool_alignof(sizeof (Eina_Object_Item)); - - return EINA_TRUE; - - on_init_fail: - eina_log_domain_unregister(_eina_object_log_dom); - _eina_object_log_dom = -1; - - if (_eina_top_mp) - { - eina_mempool_del(_eina_top_mp); - _eina_top_mp = NULL; - } - - if (_eina_class_mp) - { - eina_mempool_del(_eina_class_mp); - _eina_class_mp = NULL; - } - - return EINA_FALSE; -} - -Eina_Bool -eina_object_shutdown(void) -{ - eina_mempool_del(_eina_class_mp); - eina_mempool_del(_eina_top_mp); - - eina_log_domain_unregister(_eina_object_log_dom); - _eina_object_log_dom = -1; - return EINA_TRUE; -} - -Eina_Class * -eina_class_new(const char *name, - unsigned int class_size, - unsigned int pool_size, - Eina_Class_Callback constructor, - Eina_Class_Callback destructor, - Eina_Class *parent, - void *data) -{ - Eina_Class *c; - unsigned int object_size = class_size; - - if (parent) EINA_MAGIC_CHECK_CLASS(parent, NULL); - - c = eina_mempool_malloc(_eina_class_mp, sizeof (Eina_Class)); - if (!c) return NULL; - - c->parent = parent; - if (parent) - { - parent->childs = eina_inlist_append(parent->childs, - EINA_INLIST_GET(c)); - c->top = parent->top; - } - else - { - c->top = eina_mempool_malloc(_eina_top_mp, sizeof (Eina_Class_Top)); - - c->top->top_parent = c; - c->top->range = NULL; - c->top->available = NULL; - c->top->upper_limit = 0; - } - - /* Build complete object size and find top parent */ - if (parent) object_size += parent->object_size; - - c->name = eina_stringshare_add(name); - c->class_size = class_size; - c->pool_size = pool_size; - c->object_size = object_size; - c->mempool = eina_mempool_add("chained_mempool", "range", - NULL, - _eina_object_item_size + object_size, pool_size); - - c->constructor = constructor; - c->destructor = destructor; - c->data = data; - - c->allocated_range = NULL; - c->childs = NULL; - -#ifdef EINA_HAVE_DEBUG_THREADS - c->self = pthread_self(); -#endif - eina_lock_new(&c->mutex); - - EINA_MAGIC_SET(c, EINA_MAGIC_CLASS); - - return c; -} - -const char * -eina_class_name_get(Eina_Class *class) -{ - EINA_MAGIC_CHECK_CLASS(class, NULL); - - return class->name; -} - -unsigned int -eina_class_size_get(Eina_Class *class) -{ - EINA_MAGIC_CHECK_CLASS(class, 0); - - return class->class_size; -} - -unsigned int -eina_class_object_size_get(Eina_Class *class) -{ - EINA_MAGIC_CHECK_CLASS(class, 0); - - return class->object_size; -} - -void -eina_class_del(Eina_Class *class) -{ - EINA_MAGIC_CHECK_CLASS(class); - - EINA_MAGIC_SET(class, 0); - - while (class->allocated_range) - _eina_class_range_del(EINA_INLIST_CONTAINER_GET(class->allocated_range, - Eina_Class_Range)); - - while (class->childs) - { - Eina_Class *child; - - child = EINA_INLIST_CONTAINER_GET(class->childs, Eina_Class); - eina_class_del(child); - } - - if (class->parent) - { - class->parent->childs = eina_inlist_remove(class->parent->childs, - EINA_INLIST_GET(class)); - } - else - { - while (class->top->available) - { - Eina_Range *range; - - range = EINA_INLIST_CONTAINER_GET(class->top->available, Eina_Range); - class->top->available = eina_inlist_remove(class->top->available, - class->top->available); - eina_mempool_free(_eina_range_mp, range); - } - } - -#ifdef EINA_HAVE_DEBUG_THREADS - assert(pthread_equal(class->self, pthread_self())); -#endif - eina_lock_free(&class->mutex); - - eina_mempool_del(class->mempool); - eina_mempool_free(_eina_class_mp, class); -} - -void -eina_class_repack(Eina_Class *class) -{ - Eina_Class *child; - - EINA_MAGIC_CHECK_CLASS(class); - - if (!eina_lock_take(&class->mutex)) - { -#ifdef EINA_HAVE_DEBUG_THREADS - assert(pthread_equal(class->self, pthread_self())); -#endif - } - - eina_mempool_repack(class->mempool, _eina_class_range_repack, class); - - eina_lock_release(&class->mutex); - - EINA_INLIST_FOREACH(class->childs, child) - eina_class_repack(child); -} - -Eina_Object * -eina_object_add(Eina_Class *class) -{ - Eina_Class_Range *range; - Eina_Object_Item **object; - int localid; - - EINA_MAGIC_CHECK_CLASS(class, NULL); - - /* No need to lock the class as we don't access/modify the pointer inside - * this function. */ - - range = _eina_class_empty_range_get(class->allocated_range); - if (!range) range = _eina_class_range_add(class); - - if (range->empty_count == 0) - { - ERR("The impossible happen, range is empty when it should not !"); - return NULL; - } - - range->empty_count--; - - object = eina_trash_pop(&range->empty); - if (!object) object = range->pointer_array + range->current++; - - localid = object - range->pointer_array; - - *object = eina_mempool_malloc(class->mempool, - class->object_size + _eina_object_item_size); - - (*object)->index = localid; - (*object)->link = NULL; - (*object)->range = range; - - _eina_object_constructor_call(class, - ((unsigned char*)(*object)) + _eina_object_item_size); - - if (!(++range->generation_array[localid])) - ++range->generation_array[localid]; - - return _eina_object_get(*object); -} - -void * -eina_object_pointer_get(Eina_Class *class, - Eina_Object *object) -{ - Eina_Object_Item *item; - unsigned char *mem = NULL; - - if (!object) return NULL; - EINA_MAGIC_CHECK_CLASS(class, NULL); - - if (!eina_lock_take(&class->mutex)) - { -#ifdef EINA_HAVE_DEBUG_THREADS - assert(pthread_equal(class->self, pthread_self())); -#endif - } - - item = _eina_object_find_item(class, object); - if (!item) goto on_error; - - mem = (unsigned char*) item + _eina_object_item_size; - - on_error: - eina_lock_release(&class->mutex); - - return mem; -} - -void -eina_object_del(Eina_Class *class, - Eina_Object *object) -{ - Eina_Object_Item *item; - - if (!object) return ; - EINA_MAGIC_CHECK_CLASS(class); - - if (!eina_lock_take(&class->mutex)) - { -#ifdef EINA_HAVE_DEBUG_THREADS - assert(pthread_equal(class->self, pthread_self())); -#endif - } - - item = _eina_object_find_item(class, object); - if (!item) goto on_error; - - _eina_object_item_del(item); - - on_error: - eina_lock_release(&class->mutex); -} - -Eina_Bool -eina_object_parent_set(Eina_Class *parent_class, Eina_Object *parent, - Eina_Class *object_class, Eina_Object *object) -{ - Eina_Object_Item *parent_item; - Eina_Object_Item *object_item; - - if (!parent) return EINA_FALSE; - if (!object) return EINA_FALSE; - EINA_MAGIC_CHECK_CLASS(parent_class, EINA_FALSE); - EINA_MAGIC_CHECK_CLASS(object_class, EINA_FALSE); - - if (!eina_lock_take(&parent_class->mutex)) - { -#ifdef EINA_HAVE_DEBUG_THREADS - assert(pthread_equal(parent_class->self, pthread_self())); -#endif - } - - if (!eina_lock_take(&object_class->mutex)) - { -#ifdef EINA_HAVE_DEBUG_THREADS - assert(pthread_equal(object_class->self, pthread_self())); -#endif - } - - parent_item = _eina_object_find_item(parent_class, parent); - if (!parent_item) return EINA_FALSE; - - object_item = _eina_object_find_item(object_class, object); - if (!object_item) return EINA_FALSE; - - if (object_item->parent) - object_item->parent->link = eina_inlist_remove(object_item->parent->link, - EINA_INLIST_GET(object_item)); - - object_item->parent = parent_item; - parent_item->link = eina_inlist_append(parent_item->link, - EINA_INLIST_GET(object_item)); - - eina_lock_release(&parent_class->mutex); - eina_lock_release(&object_class->mutex); - - return EINA_TRUE; -} - -Eina_Object * -eina_object_parent_get(Eina_Class *class, Eina_Object *object) -{ - Eina_Object_Item *object_item; - Eina_Object *or = NULL; - - if (!object) return EINA_FALSE; - EINA_MAGIC_CHECK_CLASS(class, EINA_FALSE); - - if (!eina_lock_take(&class->mutex)) - { -#ifdef EINA_HAVE_DEBUG_THREADS - assert(pthread_equal(class->self, pthread_self())); -#endif - } - - object_item = _eina_object_find_item(class, object); - if (object_item) - or = _eina_object_get(object_item->parent); - - eina_lock_release(&class->mutex); - - return or; -} - diff --git a/src/lib/eina_prefix.c b/src/lib/eina_prefix.c deleted file mode 100644 index c020a10..0000000 --- a/src/lib/eina_prefix.c +++ /dev/null @@ -1,746 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef STDC_HEADERS -# include <stdlib.h> -# include <stddef.h> -#else -# ifdef HAVE_STDLIB_H -# include <stdlib.h> -# endif -#endif -#ifdef HAVE_ALLOCA_H -# include <alloca.h> -#elif !defined alloca -# ifdef __GNUC__ -# define alloca __builtin_alloca -# elif defined _AIX -# define alloca __alloca -# elif defined _MSC_VER -# include <malloc.h> -# define alloca _alloca -# elif !defined HAVE_ALLOCA -# ifdef __cplusplus -extern "C" -# endif -void *alloca (size_t); -# endif -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <limits.h> - -#ifdef HAVE_UNISTD_H -# include <unistd.h> -#endif - -#ifdef HAVE_DLADDR -# include <dlfcn.h> -#endif - -#ifdef HAVE_EVIL -# include <Evil.h> -#endif - -#ifdef HAVE_ESCAPE -# include <Escape.h> -#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); - WRN("Could not determine its installed prefix for '%s'\n" - " so am falling back on the compiled in default:\n" - " %s\n" - " implied by the following:\n" - " bindir = %s\n" - " libdir = %s\n" - " datadir = %s\n" - " localedir = %s\n" - " Try setting the following environment variables:\n" - " %s_PREFIX - points to the base prefix of install\n" - " or the next 4 variables\n" - " %s_BIN_DIR - provide a specific binary directory\n" - " %s_LIB_DIR - provide a specific library directory\n" - " %s_DATA_DIR - provide a specific data directory\n" - " %s_LOCALE_DIR - provide a specific locale directory", - envprefix, - pfx->prefix_path, pkg_bin, pkg_lib, pkg_data, pkg_locale, - envprefix, envprefix, envprefix, envprefix, envprefix); - pfx->fallback = 1; - return 1; -} - -#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 (evil_path_is_absolute(argv0)) -#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 (evil_path_is_absolute(info_dl.dli_fname)) -# 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 - * - * new case - debian multiarch goop. - * exe = /blah/whatever/lib/arch/libexe.so - */ - 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) - { - if (pfx->prefix_path) free(pfx->prefix_path); - 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 - { - if (buf[0]) - { - for (;p > pfx->exe_path; p--) - { - if (*p == DSEP_C) - { - p--; - break; - } - } - if (p > pfx->exe_path) - { - continue; - DBG("Go back one directory"); - } - } - 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/src/lib/eina_private.h b/src/lib/eina_private.h deleted file mode 100644 index 255959b..0000000 --- a/src/lib/eina_private.h +++ /dev/null @@ -1,150 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifndef EINA_PRIVATE_H_ -#define EINA_PRIVATE_H_ - -#include <stdarg.h> - -#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_INARRAY 0x98761270 -#define EINA_MAGIC_INARRAY_ITERATOR 0x98761271 -#define EINA_MAGIC_INARRAY_ACCESSOR 0x98761272 - -#define EINA_MAGIC_MODEL 0x98761280 - -#define EINA_MAGIC_CLASS 0x9877CB30 - -/* undef the following, we want out version */ -#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 - -void eina_cpu_count_internal(void); - -void eina_file_mmap_faulty(void *addr, long page_size); - -#endif /* EINA_PRIVATE_H_ */ - diff --git a/src/lib/eina_quadtree.c b/src/lib/eina_quadtree.c deleted file mode 100644 index e163e6f..0000000 --- a/src/lib/eina_quadtree.c +++ /dev/null @@ -1,937 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -/** - * @page tutorial_quadtree_page QuadTree Tutorial - * - * to be written... - * - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> -#include <stdio.h> - -#ifdef HAVE_EVIL -# include <Evil.h> -#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; - - EINA_MAGIC_CHECK_QUADTREE_ITEM(object); - - 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), 32); - eina_quadtree_root_mp = eina_mempool_add(choice, "QuadTree Root", NULL, - sizeof (Eina_QuadTree_Root), 8); - - 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/src/lib/eina_rbtree.c b/src/lib/eina_rbtree.c deleted file mode 100644 index 394007f..0000000 --- a/src/lib/eina_rbtree.c +++ /dev/null @@ -1,530 +0,0 @@ -/* EINA - EFL data type library - * Copyright (C) 2008 Cedric Bail - * Copyright (C) 2011 Alexandre Becoulet - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stdint.h> - -#include "eina_config.h" -#include "eina_private.h" -#include "eina_array.h" -#include "eina_trash.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; - Eina_Trash *trash; - - 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(Eina_Iterator_Rbtree *it, const Eina_Rbtree *tree) -{ - Eina_Iterator_Rbtree_List *new; - - eina_error_set(0); - new = eina_trash_pop(&it->trash); - if (!new) - { - 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(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; - void *last; - - EINA_ARRAY_ITER_NEXT(it->stack, i, item, et) - free(item); - - eina_array_free(it->stack); - while ((last = eina_trash_pop(&it->trash))) - free(last); - 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(it->stack) <= 0) - return EINA_FALSE; - - last = eina_array_data_get(it->stack, eina_array_count(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) - { - eina_trash_push(&it->trash, last); - - if (eina_array_count(it->stack) > 0) - { - last = eina_array_data_get(it->stack, - eina_array_count( - it-> - stack) - - 1); - last->up = EINA_TRUE; - } - - goto onfix; - } - - eina_trash_push(&it->trash, 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(it, 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; - } - - eina_trash_init(&it->trash); - - it->stack = eina_array_new(8); - if (!it->stack) - goto on_error2; - - first = _eina_rbtree_iterator_list_new(it, 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 ^ 1]; - - node->son[dir ^ 1] = 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 ^ 1] = _eina_rbtree_inline_single_rotation(node->son[dir ^ 1], dir ^ 1); - 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 **r = &root; - Eina_Rbtree *q = root; - uintptr_t stack[48]; - unsigned int s = 0; - - EINA_SAFETY_ON_NULL_RETURN_VAL(node, root); - EINA_SAFETY_ON_NULL_RETURN_VAL( cmp, root); - - /* Find insertion leaf */ - while (q != NULL) - { - Eina_Rbtree_Direction dir = cmp(q, node, (void *)data); - - /* Keep path in stack */ - stack[s++] = (uintptr_t)r | dir; - - r = q->son + dir; - q = *r; - } - - /* Insert */ - *r = node; - _eina_rbtree_node_init(node); - - /* Rebalance */ - while (s > 0) - { - Eina_Rbtree *a, *b; - uintptr_t top = stack[--s]; /* Pop link pointer and direction */ - Eina_Rbtree_Direction dir = top & 1; - - r = (Eina_Rbtree **)(top & ~(uintptr_t)1); - q = *r; - - a = q->son[dir]; - /* Rebalance done ? */ - if (a == NULL || a->color == EINA_RBTREE_BLACK) - break; - - b = q->son[dir ^ 1]; - if (b != NULL && b->color == EINA_RBTREE_RED) - { - q->color = EINA_RBTREE_RED; - b->color = a->color = EINA_RBTREE_BLACK; - } - else - { - Eina_Rbtree *c = a->son[dir]; - Eina_Rbtree *d = a->son[dir ^ 1]; - - if (c != NULL && c->color == EINA_RBTREE_RED) - *r = _eina_rbtree_inline_single_rotation(*r, dir ^ 1); - else if (d != NULL && d->color == EINA_RBTREE_RED) - *r = _eina_rbtree_inline_double_rotation(*r, dir ^ 1); - } - } - - 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 *l0, *l1, *r, **rt = &root; - Eina_Rbtree_Direction dir; - uintptr_t stack[48]; - unsigned int s = 0; - - EINA_SAFETY_ON_NULL_RETURN_VAL(node, root); - EINA_SAFETY_ON_NULL_RETURN_VAL( cmp, root); - - /* Item search loop */ - for (r = *rt; r != NULL; r = *rt) - { - if (r == node) - goto found; - - dir = cmp(r, node, (void*)data); - stack[s++] = (uintptr_t)rt | dir; - rt = r->son + dir; - } - return root; - - found: - /* remove entry */ - l0 = node->son[0]; - l1 = node->son[1]; - - if (l0 != NULL && l1 != NULL) /* two links case */ - { - Eina_Rbtree *q, **t, **p; - uintptr_t ss; - - stack[s++] = (uintptr_t)rt | 1; - ss = s; /* keep predecessor right link stack index */ - - /* find predecessor */ - p = node->son + 1; - q = *p; - - while (1) - { - t = q->son; - q = *t; - if (q == NULL) - break; - stack[s++] = (uintptr_t)p | 0; - p = t; - } - - /* detach predecessor */ - q = *p; - *p = q->son[1]; - - int c = q->color; - - /* replace entry by predecessor */ - memcpy(q, node, sizeof(Eina_Rbtree)); - *rt = q; - - if (c == EINA_RBTREE_RED) - goto end; - - /* fix stack for replaced entry */ - if (s > ss) - stack[ss] = (uintptr_t)(q->son + 1) | 0; - } - else /* single link case */ - { - if (l0 == NULL) - l0 = l1; - - *rt = l0; - - if (node->color == EINA_RBTREE_RED) - goto end; /* removed red */ - - if (l0 != NULL && l0->color == EINA_RBTREE_RED) - { - /* red child replace removed black */ - l0->color = EINA_RBTREE_BLACK; - goto end; - } - } - - /* rebalance */ - while (s > 0) - { - Eina_Rbtree *q; - uintptr_t st = stack[--s]; - - rt = (Eina_Rbtree**)(st & ~(uintptr_t)1); - dir = st & 1; - r = *rt; - q = r->son[dir ^ 1]; - - if (q != NULL && q->color == EINA_RBTREE_RED) - { - *rt = _eina_rbtree_inline_single_rotation(*rt, dir); - q = r->son[dir ^ 1]; - rt = (*rt)->son + dir; - } - - if (q != NULL) - { - int r_color = r->color; - Eina_Rbtree *nd = q->son[dir ^ 1]; - - if (nd != NULL && nd->color == EINA_RBTREE_RED) - { - *rt = _eina_rbtree_inline_single_rotation(*rt, dir); - } - else - { - Eina_Rbtree *d = q->son[dir]; - - if (d != NULL && d->color == EINA_RBTREE_RED) - { - *rt = _eina_rbtree_inline_double_rotation(*rt, dir); - } - else - { - r->color = EINA_RBTREE_BLACK; - q->color = EINA_RBTREE_RED; - if (r_color == EINA_RBTREE_RED) - break; - continue; - } - } - - r = *rt; - r->color = r_color; - r->son[1]->color = r->son[0]->color = EINA_RBTREE_BLACK; - - break; - } - } - - end: - if (root != NULL) - root->color = EINA_RBTREE_BLACK; - return root; -} - -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/src/lib/eina_rectangle.c b/src/lib/eina_rectangle.c deleted file mode 100644 index 85cf310..0000000 --- a/src/lib/eina_rectangle.c +++ /dev/null @@ -1,571 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdio.h> -#include <stdlib.h> - -#ifdef HAVE_EVIL -# include <Evil.h> -#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), 64); - 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), 32); - 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; - - if ((w <= 0) || (h <= 0)) - return NULL; - - 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/src/lib/eina_safety_checks.c b/src/lib/eina_safety_checks.c deleted file mode 100644 index eed7c59..0000000 --- a/src/lib/eina_safety_checks.c +++ /dev/null @@ -1,90 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#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/src/lib/eina_sched.c b/src/lib/eina_sched.c deleted file mode 100644 index b8e7000..0000000 --- a/src/lib/eina_sched.c +++ /dev/null @@ -1,101 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef EFL_HAVE_POSIX_THREADS -# include <pthread.h> -# ifdef __linux__ -# include <sched.h> -# include <sys/time.h> -# include <sys/resource.h> -# include <errno.h> -# endif -#endif - -#ifdef EFL_HAVE_WIN32_THREADS -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# include <windows.h> -# undef WIN32_LEAN_AND_MEAN -#endif - -#include "eina_sched.h" -#include "eina_log.h" - -#define RTNICENESS 1 -#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)) - { - param.sched_priority -= RTNICENESS; - - /* We don't change the policy */ - if (param.sched_priority < 1) - { - EINA_LOG_INFO("RT prio < 1, setting to 1 instead"); - param.sched_priority = 1; - } - - pthread_setschedparam(pthread_id, pol, ¶m); - } -# ifdef __linux__ - else - { - errno = 0; - prio = getpriority(PRIO_PROCESS, 0); - if (errno == 0) - { - prio += NICENESS; - if (prio > 19) - { - EINA_LOG_INFO("Max niceness reached; keeping max (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/src/lib/eina_share_common.c b/src/lib/eina_share_common.c deleted file mode 100644 index 91ad0db..0000000 --- a/src/lib/eina_share_common.c +++ /dev/null @@ -1,949 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stddef.h> - -#ifdef EFL_HAVE_POSIX_THREADS -# include <pthread.h> -#endif - -#ifdef HAVE_EVIL -# include <Evil.h> -#endif - -#include "eina_config.h" -#include "eina_private.h" -#include "eina_hash.h" -#include "eina_rbtree.h" -#include "eina_error.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; - -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 %u, 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; - - share->share = calloc(1, sizeof(Eina_Share_Common)); - if (!share->share) 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); - - 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; -} - - -Eina_Bool -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_TRUE; - - 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 EINA_TRUE; - } - - 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), EINA_FALSE); - - 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 EINA_TRUE; - -on_error: - eina_lock_release(&_mutex_big); - /* possible segfault happened before here, but... */ - return EINA_FALSE; -} - -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 %u, 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/src/lib/eina_share_common.h b/src/lib/eina_share_common.h deleted file mode 100644 index 6bc11ef..0000000 --- a/src/lib/eina_share_common.h +++ /dev/null @@ -1,86 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - * - * 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); -Eina_Bool eina_share_common_del(Eina_Share *share, const char *str) EINA_WARN_UNUSED_RESULT; -int eina_share_common_length(Eina_Share *share, - const char *str) EINA_CONST -EINA_WARN_UNUSED_RESULT; -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); - -#endif /* EINA_SHARE_COMMON_H_ */ diff --git a/src/lib/eina_simple_xml_parser.c b/src/lib/eina_simple_xml_parser.c deleted file mode 100644 index eeb5a96..0000000 --- a/src/lib/eina_simple_xml_parser.c +++ /dev/null @@ -1,1170 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_ALLOCA_H -# include <alloca.h> -#elif defined __GNUC__ -# define alloca __builtin_alloca -#elif defined _AIX -# define alloca __alloca -#elif defined _MSC_VER -# include <malloc.h> -# define alloca _alloca -#else -# include <stddef.h> -# ifdef __cplusplus -extern "C" -# endif -void *alloca (size_t); -#endif - -#ifdef HAVE_STRINGS_H -# include <strings.h> -#endif -#include <stdlib.h> -#include <string.h> -#include <ctype.h> - -#ifdef HAVE_EVIL -# include <Evil.h> -#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((unsigned char)*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((unsigned char)*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((unsigned char)*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; -} - -static inline const char * -_eina_simple_xml_tag_comment_end_find(const char *itr, const char *itr_end) -{ - for (; itr < itr_end; itr++) - if ((*itr == '-') && - ((itr + 1 < itr_end) && (*(itr + 1) == '-')) && - ((itr + 2 < itr_end) && (*(itr + 2) == '>'))) - return itr + 2; - return NULL; -} - -static inline const char * -_eina_simple_xml_tag_cdata_end_find(const char *itr, const char *itr_end) -{ - for (; itr < itr_end; itr++) - if ((*itr == ']') && - ((itr + 1 < itr_end) && (*(itr + 1) == ']')) && - ((itr + 2 < itr_end) && (*(itr + 2) == '>'))) - return itr + 2; - return NULL; -} - -static inline const char * -_eina_simple_xml_tag_doctype_child_end_find(const char *itr, const char *itr_end) -{ - for (; itr < itr_end; itr++) - if (*itr == '>') - 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), 32); - 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), 8); - 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("<!DOCTYPE>") - 1 < itr_end) && - (!memcmp(itr + 2, "DOCTYPE", - sizeof("DOCTYPE") - 1)) && - ((itr[2 + sizeof("DOCTYPE") - 1] == '>') || - (isspace((unsigned char)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("<![CDATA[]]>") - 1 < itr_end) && - (!memcmp(itr + 2, "[CDATA[", - sizeof("[CDATA[") - 1))) - { - type = EINA_SIMPLE_XML_CDATA; - toff = sizeof("![CDATA[") - 1; - } - else if ((itr + sizeof("<!>") - 1 < itr_end) && - (!memcmp(itr + 2, "", - sizeof("") - 1))) - { - type = EINA_SIMPLE_XML_DOCTYPE_CHILD; - toff = sizeof("!") - 1; - } - else - { - type = EINA_SIMPLE_XML_OPEN; - toff = 0; - } - } - else - { - type = EINA_SIMPLE_XML_OPEN; - toff = 0; - } - - if (type == EINA_SIMPLE_XML_CDATA) - p = _eina_simple_xml_tag_cdata_end_find(itr + 1 + toff, itr_end); - else if (type == EINA_SIMPLE_XML_DOCTYPE_CHILD) - p = _eina_simple_xml_tag_doctype_child_end_find(itr + 1 + toff, itr_end); - else if (type == EINA_SIMPLE_XML_COMMENT) - p = _eina_simple_xml_tag_comment_end_find(itr + 1 + toff, itr_end); - else - p = _eina_simple_xml_tag_end_find(itr + 1 + toff, 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_DOCTYPE_CHILD: - 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((unsigned char)*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((unsigned char)*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((unsigned char)*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) -{ - if (!attr) - return; - - 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) -{ - if (!tag) - return; - - 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; - - if (!content) return NULL; - - n = malloc(sizeof(*n) + length + 1); - - 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) -{ - if (!node) - return; - - 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) -{ - if (!node) - return; - - 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_Doctype_Child * -eina_simple_xml_node_doctype_child_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_CHILD, contents, length); -} - -EAPI void -eina_simple_xml_node_doctype_child_free(Eina_Simple_XML_Node_Data *node) -{ - if (!node) - return; - - EINA_MAGIC_CHECK_DATA(&node->base); - if (node->base.type != EINA_SIMPLE_XML_NODE_DOCTYPE_CHILD) - { - ERR("expected node of type: doctype child!"); - 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) -{ - if (!node) - return; - - 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) -{ - if (!node) - return; - - 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) -{ - if (!node) - return; - - 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_DOCTYPE_CHILD: - return !!eina_simple_xml_node_doctype_child_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, "</", sizeof("</") - 1); - eina_strbuf_append_length - (buf, n->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, "<![CDATA[", sizeof("<![CDATA[") - 1); - eina_strbuf_append_length(buf, n->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, "<?", sizeof("<?") - 1); - eina_strbuf_append_length(buf, n->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, "<!DOCTYPE ", sizeof("<!DOCTYPE ") - 1); - eina_strbuf_append_length(buf, n->data, n->length); - eina_strbuf_append_char(buf, '>'); - if (indent) eina_strbuf_append_char(buf, '\n'); - } - break; - - case EINA_SIMPLE_XML_NODE_DOCTYPE_CHILD: - { - 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); - eina_strbuf_append_length(buf, n->data, n->length); - eina_strbuf_append_length(buf, ">", sizeof(">") - 1); - 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); - eina_strbuf_append_length(buf, n->data, n->length); - 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/src/lib/eina_str.c b/src/lib/eina_str.c deleted file mode 100644 index 5db3839..0000000 --- a/src/lib/eina_str.c +++ /dev/null @@ -1,572 +0,0 @@ -/* 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 <Todd.Miller@courtesan.com> - * - * 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 <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <limits.h> -#include <ctype.h> - -#ifdef HAVE_ICONV -# include <errno.h> -# include <iconv.h> -#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, *pos, **str_array; - const char *src; - size_t len, dlen; - unsigned int tokens = 0, x; - const char *idx[256] = {NULL}; - - if (max_tokens < 0) max_tokens = 0; - if (max_tokens == 1) - { - str_array = malloc(sizeof(char *) * 2); - if (!str_array) - { - if (elements) - *elements = 0; - - return NULL; - } - - s = strdup(str); - if (!s) - { - free(str_array); - if (elements) - *elements = 0; - - return NULL; - } - if (elements) - *elements = 1; - str_array[0] = s; - return str_array; - } - dlen = strlen(delim); - if (dlen == 0) - { - if (elements) - *elements = 0; - - return NULL; - } - - 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; - if (tokens < (sizeof(idx) / sizeof(idx[0]))) - { - idx[tokens] = tmp; - //printf("token %d='%s'\n", tokens + 1, idx[tokens]); - } - tokens++; - if (tokens && (tokens == (unsigned int)max_tokens)) break; - } - else - src++; - } - len = src - str + strlen(src); - - str_array = malloc(sizeof(char *) * (tokens + 2)); - if (!str_array) - { - if (elements) - *elements = 0; - - return NULL; - } - - if (!tokens) - { - s = strdup(str); - if (!s) - { - free(str_array); - if (elements) - *elements = 0; - - return NULL; - } - str_array[0] = s; - str_array[1] = NULL; - if (elements) - *elements = 1; - return str_array; - } - - s = malloc(len + 1); - if (!s) - { - free(str_array); - if (elements) - *elements = 0; - - return NULL; - } - - str_array[0] = s; - - if (len == tokens * dlen) - { - /* someone's having a laugh somewhere */ - memset(s, 0, len + 1); - for (x = 1; x < tokens + 1; x++) - str_array[x] = s + x; - str_array[x] = NULL; - if (elements) - *elements = x; - return str_array; - } - /* copy tokens and string */ - if (idx[0] - str - dlen > len) - { - /* FIXME: don't think this can happen but putting this here just in case */ - abort(); - } - pos = s; - for (x = 0; x < MIN(tokens, (sizeof(idx) / sizeof(idx[0]))); x++) - { - if (x + 1 < (sizeof(idx) / sizeof(idx[0]))) - { - /* first one is special */ - if (!x) - { - eina_strlcpy(pos, str, idx[x] - str - dlen + 1); - str_array[x] = pos; - //printf("str_array[%d] = '%s'\n", x, str_array[x]); - pos += idx[x] - str - dlen + 1; - if ((tokens == 1) && (idx[0])) - { - eina_strlcpy(pos, idx[x], len + 1 - (pos - s)); - x++, tokens++; - str_array[x] = pos; - } - } - /* more tokens */ - else if (idx[x + 1]) - { - eina_strlcpy(pos, idx[x - 1], idx[x] - idx[x - 1] - dlen + 1); - str_array[x] = pos; - //printf("str_array[%d] = '%s'\n", x, str_array[x]); - pos += idx[x] - idx[x - 1] - dlen + 1; - } - /* last token */ - else - { - if (max_tokens && ((unsigned int)max_tokens < tokens + 1)) - eina_strlcpy(pos, idx[x - 1], len + 1 - (pos - s)); - else - { - //printf("diff: %d\n", len + 1 - (pos - s)); - eina_strlcpy(pos, idx[x - 1], idx[x] - idx[x - 1] - dlen + 1); - str_array[x] = pos; - //printf("str_array[%d] = '%s'\n", x, str_array[x]); - pos += idx[x] - idx[x - 1] - dlen + 1; - x++, tokens++; - eina_strlcpy(pos, idx[x - 1], len + 1 - (pos - s)); - } - str_array[x] = pos; - //printf("str_array[%d] = '%s'\n", x, str_array[x]); - } - } - /* no more tokens saved after this one */ - else - { - eina_strlcpy(pos, idx[x - 1], idx[x] - idx[x - 1] - dlen + 1); - str_array[x] = pos; - //printf("str_array[%d] = '%s'\n", x, str_array[x]); - pos += idx[x] - idx[x - 1] - dlen + 1; - src = idx[x]; - x++, tokens++; - str_array[x] = s = pos; - break; - } - } - if ((x != tokens) && ((!max_tokens) || (x < tokens))) - { - 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 (((!max_tokens) || (((tokens == (unsigned int)max_tokens) || x < tokens - 2))) && (EINA_UNLIKELY(d == d_end))) - { - src = tmp; - *s = '\0'; - s++, x++; - //printf("str_array[%d] = '%s'\n", x, str_array[x - 1]); - str_array[x] = s; - } - else - { - *s = *src; - s++, src++; - } - } - *s = 0; - } - str_array[tokens] = NULL; - if (elements) - *elements = tokens; - - 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 (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; - - if (!str) - return NULL; - - 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/src/lib/eina_strbuf.c b/src/lib/eina_strbuf.c deleted file mode 100644 index 828d842..0000000 --- a/src/lib/eina_strbuf.c +++ /dev/null @@ -1,202 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdio.h> -#include <string.h> -#include <ctype.h> - -#ifdef HAVE_EVIL -# include <Evil.h> -#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) -{ - unsigned char *c = buf->buf; - - while (buf->len > 0 && isspace(c[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) -{ - unsigned 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/src/lib/eina_strbuf_common.c b/src/lib/eina_strbuf_common.c deleted file mode 100644 index 64c2c14..0000000 --- a/src/lib/eina_strbuf_common.c +++ /dev/null @@ -1,874 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#ifdef _WIN32 -# include <Evil.h> -#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/src/lib/eina_strbuf_common.h b/src/lib/eina_strbuf_common.h deleted file mode 100644 index 06a1353..0000000 --- a/src/lib/eina_strbuf_common.h +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef EINA_STRBUF_COMMON_H -#define EINA_STRBUF_COMMON_H - -#include <stdlib.h> - -#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/src/lib/eina_strbuf_template_c.x b/src/lib/eina_strbuf_template_c.x deleted file mode 100644 index e8c3b61..0000000 --- a/src/lib/eina_strbuf_template_c.x +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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/src/lib/eina_stringshare.c b/src/lib/eina_stringshare.c deleted file mode 100644 index 2a457f4..0000000 --- a/src/lib/eina_stringshare.c +++ /dev/null @@ -1,797 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_ALLOCA_H -# include <alloca.h> -#elif defined __GNUC__ -# define alloca __builtin_alloca -#elif defined _AIX -# define alloca __alloca -#elif defined _MSC_VER -# include <malloc.h> -# define alloca _alloca -#else -# include <stddef.h> -# ifdef __cplusplus -extern "C" -# endif -void *alloca (size_t); -#endif - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#ifdef HAVE_EVIL -# include <Evil.h> -#endif - -#include "eina_config.h" -#include "eina_private.h" -#include "eina_error.h" -#include "eina_log.h" -#include "eina_lock.h" -#include "eina_share_common.h" - -/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ -#include "eina_safety_checks.h" -#include "eina_stringshare.h" - - -#ifdef CRITICAL -#undef CRITICAL -#endif -#define CRITICAL(...) EINA_LOG_DOM_CRIT(_eina_share_stringshare_log_dom, __VA_ARGS__) - -#ifdef ERR -#undef ERR -#endif -#define ERR(...) EINA_LOG_DOM_ERR(_eina_share_stringshare_log_dom, __VA_ARGS__) - -#ifdef DBG -#undef DBG -#endif -#define DBG(...) EINA_LOG_DOM_DBG(_eina_share_stringshare_log_dom, __VA_ARGS__) - -static int _eina_share_stringshare_log_dom = -1; - -/* The actual share */ -static Eina_Share *stringshare_share; -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; - - printf("DDD: %5hhu %5hu '%s'\n", *l, *r, *s); - - 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; - - if (_eina_share_stringshare_log_dom < 0) - { - _eina_share_stringshare_log_dom = eina_log_domain_register - ("eina_stringshare", EINA_LOG_COLOR_DEFAULT); - - if (_eina_share_stringshare_log_dom < 0) - { - EINA_LOG_ERR("Could not register log domain: eina_stringshare"); - return EINA_FALSE; - } - } - - ret = eina_share_common_init(&stringshare_share, - EINA_MAGIC_STRINGSHARE_NODE, - EINA_MAGIC_STRINGSHARE_NODE_STR); - if (ret) - _eina_stringshare_small_init(); - else - { - eina_log_domain_unregister(_eina_share_stringshare_log_dom); - _eina_share_stringshare_log_dom = -1; - } - - return ret; -} - -/** - * @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); - - if (_eina_share_stringshare_log_dom >= 0) - { - eina_log_domain_unregister(_eina_share_stringshare_log_dom); - _eina_share_stringshare_log_dom = -1; - } - - return ret; -} - -/*============================================================================* - * API * - *============================================================================*/ - -EAPI void -eina_stringshare_del(Eina_Stringshare *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; - } - - if (!eina_share_common_del(stringshare_share, str)) - CRITICAL("EEEK trying to del non-shared stringshare \"%s\"", str); -} - -EAPI Eina_Stringshare * -eina_stringshare_add_length(const char *str, unsigned int slen) -{ - if (!str) - return NULL; - else if (slen == 0) - return ""; - else if (slen == 1) - return (Eina_Stringshare *) _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 Eina_Stringshare * -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 Eina_Stringshare * -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 Eina_Stringshare * -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 Eina_Stringshare * -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 Eina_Stringshare * -eina_stringshare_ref(Eina_Stringshare *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(Eina_Stringshare *str) -{ - int len; - - if (!str) return 0; - - /* 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, (Eina_Stringshare *) 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/src/lib/eina_thread.c b/src/lib/eina_thread.c deleted file mode 100644 index 993b479..0000000 --- a/src/lib/eina_thread.c +++ /dev/null @@ -1,313 +0,0 @@ -/* EINA - EFL data type library - * Copyright (C) 2012 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> - -#ifdef HAVE_EVIL -# include <Evil.h> -#endif - -#include "eina_config.h" -#include "eina_thread.h" -#include "eina_sched.h" - -#ifdef EINA_HAVE_THREADS -# ifdef _WIN32_WCE - -# elif defined(_WIN32) - -# define WIN32_LEAN_AND_MEAN -# include <windows.h> -# undef WIN32_LEAN_AND_MEAN - -typedef struct _Eina_Thread_Win32 Eina_Thread_Win32; -struct _Eina_Thread_Win32 -{ - HANDLE thread; - Eina_Thread_Cb func; - void *data; - void *ret; - - Eina_Thread index; -}; - -/* FIXME: For the moment Eina_Thread is considered not - thread safe, wondering if it's worth it */ -static unsigned long int _current_index = 1; /* start from one as the main loop == 0 */ -static Eina_List *_thread_pool = NULL; -static Eina_List *_thread_running = NULL; - -static Eina_Thread_Win32 * -_eina_thread_win32_find(Eina_Thread index) -{ - Eina_Thread_Win32 *tw; - Eina_List *l; - - EINA_LIST_FOREACH(_thread_running, l, tw) - if (tw->index == index) - return tw; - return NULL; -} - -static Eina_Thread -_eina_thread_win32_self(void) -{ - HANDLE t; - - t = GetCurrentThread(); - EINA_LIST_FOREACH(_thread_running, l, tw) - if (tw->thread == t) - return tw->index; - - /* We assume main loop == 0 on Windows */ - return 0; -} - -static Eina_Bool -_eina_thread_win32_equal(Eina_Thread t1, Eina_Thread t2) -{ - if (t1 == t2) return EINA_TRUE; - return EINA_FALSE; -} - -static DWORD WINAPI -_eina_thread_win32_cb(LPVOID lpParam) -{ - Eina_Thread_Win32 *tw = lpParam; - - tw->ret = tw->func(tw->data, tw->index); - - return 0; -} - -static Eina_Bool -_eina_thread_win32_create(Eina_Thread *t, - int affinity, - Eina_Thread_Cb func, - const void *data) -{ - Eina_Thread_Win32 *tw; - Eina_List *l; - - tw = eina_list_data_get(_thread_pool); - _thread_pool = eina_list_remove_list(_thread_pool, _thread_pool); - - if (!tw) - { - tw = malloc(sizeof (Eina_Thread_Win32)); - if (!tw) goto on_error; - - do { - tw->index = _current_index++; - } while (tw->index == 0); /* prevent having a "false" main loop */ - } - - tw->func = f; - tw->data = d; - - tw->thread = CreateThread(NULL, 0, _eina_thread_win32_cb, tw, 0, NULL); - if (!tw->thread) goto on_error; - - _thread_running = eina_list_append(_thread_running, tw); - - *t = tw->index; - return EINA_TRUE; - - on_error: - _thread_pool = eina_list_append(_thread_pool, tw); - return EINA_FALSE; -} - -static void * -_eina_thread_win32_join(Eina_Thread t) -{ - Eina_Thread_Win32 *tw; - void *ret; - - tw = _eina_thread_win32_find(index); - if (!tw) return NULL; - - WaitForSingleObject(tw->thread, INFINITE); - CloseHandle(tw->thread); - - ret = tw->ret; - - tw->ret = NULL; - tw->thread = NULL; - tw->func = NULL; - tw->data = NULL; - - _thread_running = eina_list_remove(_thread_running, tw); - _thread_pool = eina_list_append(_thread_pool, _thread_pool); - - return ret; -} - -# define PHE(x, y) _eina_thread_win32_equal(x, y) -# define PHS() _eina_thread_win32_self() -# define PHC(x, a, f, d) _eina_thread_win32_create(x, a, f, d) -# define PHJ(x) _eina_thread_win32_join(x) -# define PHA(a) - -# else -# include <pthread.h> - -# ifdef __linux__ -# include <sched.h> -# include <sys/resource.h> -# include <unistd.h> -# include <sys/syscall.h> -# include <errno.h> -# endif - -static void * -_eina_thread_join(Eina_Thread t) -{ - void *ret = NULL; - - if (!pthread_join(t, &ret)) - return ret; - return NULL; -} - -static Eina_Bool -_eina_thread_create(Eina_Thread *t, int affinity, void *(*func)(void *data), void *data) -{ - Eina_Bool r; - pthread_attr_t attr; -#ifdef EINA_HAVE_PTHREAD_AFFINITY - cpu_set_t cpu; - int cpunum; -#endif - - pthread_attr_init(&attr); -#ifdef EINA_HAVE_PTHREAD_AFFINITY - if (affinity >= 0) - { - cpunum = eina_cpu_count(); - - CPU_ZERO(&cpu); - CPU_SET(affinity % cpunum, &cpu); - pthread_attr_setaffinity_np(&attr, sizeof(cpu), &cpu); - } -#else - (void) affinity; -#endif - /* setup initial locks */ - r = pthread_create(t, &attr, func, data) == 0; - pthread_attr_destroy(&attr); - - return r; -} - -# define PHE(x, y) pthread_equal(x, y) -# define PHS() pthread_self() -# define PHC(x, a, f, d) _eina_thread_create(x, a, f, d) -# define PHJ(x) _eina_thread_join(x) - -# endif -#else -# error "Not supported any more" -#endif - -typedef struct _Eina_Thread_Call Eina_Thread_Call; -struct _Eina_Thread_Call -{ - Eina_Thread_Cb func; - const void *data; - - Eina_Thread_Priority prio; - int affinity; -}; - -#include "eina_thread.h" - -static void * -_eina_internal_call(void *context) -{ - Eina_Thread_Call *c = context; - void *r; - - if (c->prio == EINA_THREAD_BACKGROUND || - c->prio == EINA_THREAD_IDLE) - eina_sched_prio_drop(); - - /* FIXME: set priority and affinity */ - r = c->func((void*) c->data, eina_thread_self()); - - free(c); - - return r; -} - -EAPI Eina_Thread -eina_thread_self(void) -{ - return PHS(); -} - -EAPI Eina_Bool -eina_thread_equal(Eina_Thread t1, Eina_Thread t2) -{ - return !!(PHE(t1, t2)); -} - -EAPI Eina_Bool -eina_thread_create(Eina_Thread *t, - Eina_Thread_Priority prio, int affinity, - Eina_Thread_Cb func, const void *data) -{ - Eina_Thread_Call *c; - - c = malloc(sizeof (Eina_Thread_Call)); - if (!c) return EINA_FALSE; - - c->func = func; - c->data = data; - c->prio = prio; - c->affinity = affinity; - - if (PHC(t, affinity, _eina_internal_call, c)) - return EINA_TRUE; - - free(c); - - return EINA_FALSE; -} - -EAPI void * -eina_thread_join(Eina_Thread t) -{ - return PHJ(t); -} - -Eina_Bool -eina_thread_init(void) -{ - return EINA_TRUE; -} - -Eina_Bool -eina_thread_shutdown(void) -{ - return EINA_TRUE; -} diff --git a/src/lib/eina_tiler.c b/src/lib/eina_tiler.c deleted file mode 100644 index b436ba6..0000000 --- a/src/lib/eina_tiler.c +++ /dev/null @@ -1,1290 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -/* 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 <stdlib.h> -#include <stdio.h> - -#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("<rect(%d, %d, %d, %d)>", 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; - - if ((w <= 0) || (h <= 0)) - return NULL; - - 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) -{ - if (!t) - return; - - 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); - EINA_SAFETY_ON_NULL_RETURN_VAL(r, 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); - EINA_SAFETY_ON_NULL_RETURN(r); - - 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; - - if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || - (tile_w <= 0) || (tile_h <= 0)) - return NULL; - - 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/src/lib/eina_unicode.c b/src/lib/eina_unicode.c deleted file mode 100644 index a1993de..0000000 --- a/src/lib/eina_unicode.c +++ /dev/null @@ -1,452 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "eina_config.h" -#include "eina_private.h" -#include <string.h> - -/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ -#include "eina_safety_checks.h" -#include "eina_unicode.h" - -/* FIXME: check if sizeof(wchar_t) == sizeof(Eina_Unicode) if so, - * 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) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(a, -1); - EINA_SAFETY_ON_NULL_RETURN_VAL(b, -1); - - for (; *a && *a == *b; a++, b++) - ; - if (*a == *b) - 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; - - EINA_SAFETY_ON_NULL_RETURN_VAL(dest, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(source, NULL); - - 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; - - EINA_SAFETY_ON_NULL_RETURN_VAL(dest, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(source, NULL); - - for ( ; n && *source ; n--) - *dest++ = *source++; - for (; n; n--) - *dest++ = 0; - return ret; -} - -EAPI size_t -eina_unicode_strlen(const Eina_Unicode *ustr) -{ - const Eina_Unicode *end; - - EINA_SAFETY_ON_NULL_RETURN_VAL(ustr, 0); - - for (end = ustr; *end; end++) - ; - return end - ustr; -} - -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 ;-) */ - - EINA_SAFETY_ON_NULL_RETURN_VAL(ustr, 0); - - 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; - - EINA_SAFETY_ON_NULL_RETURN_VAL(text, NULL); - - ustr = malloc((n + 1) * sizeof(Eina_Unicode)); - memcpy(ustr, text, n * sizeof(Eina_Unicode)); - ustr[n] = 0; - return ustr; -} - -EAPI Eina_Unicode * -eina_unicode_strdup(const Eina_Unicode *text) -{ - size_t len; - - EINA_SAFETY_ON_NULL_RETURN_VAL(text, NULL); - - len = eina_unicode_strlen(text); - return eina_unicode_strndup(text, len); -} - -EAPI Eina_Unicode * -eina_unicode_strstr(const Eina_Unicode *haystack, const Eina_Unicode *needle) -{ - const Eina_Unicode *i, *j; - - EINA_SAFETY_ON_NULL_RETURN_VAL(haystack, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(needle, NULL); - - for (i = haystack; *i; i++) - { - haystack = i; /* set this location as the base position */ - 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; - - EINA_SAFETY_ON_NULL_RETURN_VAL(str, NULL); - - 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; - Eina_Unicode r; - unsigned char d; - - EINA_SAFETY_ON_NULL_RETURN_VAL(buf, 0); - EINA_SAFETY_ON_NULL_RETURN_VAL(iindex, 0); - - ind = *iindex; - - /* 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, ind; - - EINA_SAFETY_ON_NULL_RETURN_VAL(buf, 0); - EINA_SAFETY_ON_NULL_RETURN_VAL(iindex, 0); - - ind = *iindex; - /* First obtain the codepoint at iindex */ - r = eina_unicode_utf8_get_next(buf, &ind); - - /* 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; - - EINA_SAFETY_ON_NULL_RETURN_VAL(buf, 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; - - EINA_SAFETY_ON_NULL_RETURN_VAL(utf, NULL); - - 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; - - EINA_SAFETY_ON_NULL_RETURN_VAL(uni, NULL); - - 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/src/lib/eina_ustrbuf.c b/src/lib/eina_ustrbuf.c deleted file mode 100644 index 7c1c2db..0000000 --- a/src/lib/eina_ustrbuf.c +++ /dev/null @@ -1,74 +0,0 @@ -#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/src/lib/eina_ustringshare.c b/src/lib/eina_ustringshare.c deleted file mode 100644 index 33be242..0000000 --- a/src/lib/eina_ustringshare.c +++ /dev/null @@ -1,189 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - - */ -/** - * @page tutorial_ustringshare_page UStringshare Tutorial - * - * to be written... - * - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "eina_config.h" -#include "eina_private.h" -#include "eina_unicode.h" -#include "eina_log.h" -#include "eina_share_common.h" - -/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ -#include "eina_safety_checks.h" -#include "eina_ustringshare.h" - - -#ifdef CRITICAL -#undef CRITICAL -#endif -#define CRITICAL(...) EINA_LOG_DOM_CRIT(_eina_share_ustringshare_log_dom, __VA_ARGS__) - -#ifdef ERR -#undef ERR -#endif -#define ERR(...) EINA_LOG_DOM_ERR(_eina_share_ustringshare_log_dom, __VA_ARGS__) - -#ifdef DBG -#undef DBG -#endif -#define DBG(...) EINA_LOG_DOM_DBG(_eina_share_ustringshare_log_dom, __VA_ARGS__) - -static int _eina_share_ustringshare_log_dom = -1; - -/* The actual share */ -static Eina_Share *ustringshare_share; -static const char EINA_MAGIC_USTRINGSHARE_NODE_STR[] = "Eina UStringshare Node"; - -/*============================================================================* -* 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) -{ - Eina_Bool ret; - - if (_eina_share_ustringshare_log_dom < 0) - { - _eina_share_ustringshare_log_dom = eina_log_domain_register - ("eina_ustringshare", EINA_LOG_COLOR_DEFAULT); - - if (_eina_share_ustringshare_log_dom < 0) - { - EINA_LOG_ERR("Could not register log domain: eina_ustringshare"); - return EINA_FALSE; - } - } - - ret = eina_share_common_init(&ustringshare_share, - EINA_MAGIC_USTRINGSHARE_NODE, - EINA_MAGIC_USTRINGSHARE_NODE_STR); - - if (!ret) - { - eina_log_domain_unregister(_eina_share_ustringshare_log_dom); - _eina_share_ustringshare_log_dom = -1; - } - - return ret; -} - -/** - * @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); - - if (_eina_share_ustringshare_log_dom >= 0) - { - eina_log_domain_unregister(_eina_share_ustringshare_log_dom); - _eina_share_ustringshare_log_dom = -1; - } - - return ret; -} - -/*============================================================================* -* API * -*============================================================================*/ - -EAPI void -eina_ustringshare_del(const Eina_Unicode *str) -{ - if (!str) - return; - - if (!eina_share_common_del(ustringshare_share, (const char *)str)) - CRITICAL("EEEK trying to del non-shared ustringshare \"%s\"", (const char *)str); -} - -EAPI const Eina_Unicode * -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/src/lib/eina_value.c b/src/lib/eina_value.c deleted file mode 100644 index 368c08d..0000000 --- a/src/lib/eina_value.c +++ /dev/null @@ -1,5309 +0,0 @@ -/* EINA - EFL data type library - * Copyright (C) 2012 ProFUSION embedded systems - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; - * if not, see <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_ALLOCA_H -# include <alloca.h> -#elif defined __GNUC__ -# define alloca __builtin_alloca -#elif defined _AIX -# define alloca __alloca -#elif defined _MSC_VER -# include <malloc.h> -# define alloca _alloca -#else -# include <stddef.h> -# ifdef __cplusplus -extern "C" -# endif -void *alloca (size_t); -#endif - -#include <stdio.h> /* asprintf() */ -#include <inttypes.h> /* PRId64 and PRIu64 */ -#include <sys/time.h> /* struct timeval */ - -#ifdef HAVE_EVIL -# include <Evil.h> -#endif - -#include "eina_config.h" -#include "eina_private.h" -#include "eina_error.h" -#include "eina_log.h" -#include "eina_strbuf.h" -#include "eina_mempool.h" -#include "eina_lock.h" - -/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ -#include "eina_safety_checks.h" -#include "eina_value.h" -/* no model for now -#include "eina_model.h" // uses eina_value.h - */ - -/*============================================================================* -* Local * -*============================================================================*/ - -/** - * @cond LOCAL - */ - -static Eina_Mempool *_eina_value_mp = NULL; -static Eina_Hash *_eina_value_inner_mps = NULL; -static Eina_Lock _eina_value_inner_mps_lock; -static char *_eina_value_mp_choice = NULL; -static int _eina_value_log_dom = -1; - -#ifdef ERR -#undef ERR -#endif -#define ERR(...) EINA_LOG_DOM_ERR(_eina_value_log_dom, __VA_ARGS__) - -#ifdef DBG -#undef DBG -#endif -#define DBG(...) EINA_LOG_DOM_DBG(_eina_value_log_dom, __VA_ARGS__) - -static const unsigned char eina_value_uchar_max = 255U; -static const char eina_value_char_max = 127; -static const signed char eina_value_char_min = -127 - 1; - -static const unsigned short eina_value_ushort_max = 65535U; -static const short eina_value_short_max = 32767; -static const short eina_value_short_min = -32767 - 1; - -static const unsigned int eina_value_uint_max = 4294967295U; -static const int eina_value_int_max = 2147483647; -static const int eina_value_int_min = -2147483647 - 1; - -static const uint64_t eina_value_uint64_max = 18446744073709551615ULL; -static const int64_t eina_value_int64_max = 9223372036854775807LL; -static const int64_t eina_value_int64_min = -9223372036854775807LL - 1LL; - -#if __WORDSIZE == 64 -static const unsigned long eina_value_ulong_max = 18446744073709551615ULL; -static const long eina_value_long_max = 9223372036854775807LL; -static const long eina_value_long_min = -9223372036854775807LL - 1LL; -#else -static const unsigned long eina_value_ulong_max = 4294967295U; -static const long eina_value_long_max = 2147483647; -static const long eina_value_long_min = -2147483647 - 1; -#endif - - -static Eina_Bool -_eina_value_type_uchar_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - unsigned char *tmem = mem; - *tmem = 0; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_uchar_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) -{ - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_uchar_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const unsigned char *s = src; - unsigned char *d = dst; - *d = *s; - return EINA_TRUE; -} - -static int -_eina_value_type_uchar_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const unsigned char *ta = a, *tb = b; - if (*ta < *tb) - return -1; - else if (*ta > *tb) - return 1; - return 0; -} - -static Eina_Bool -_eina_value_type_uchar_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const unsigned char v = *(const unsigned char *)type_mem; - - eina_error_set(0); - - if (convert == EINA_VALUE_TYPE_UCHAR) - { - unsigned char other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_USHORT) - { - unsigned short other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT) - { - unsigned int other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) - { - unsigned long other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT64) - { - uint64_t other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_CHAR) - { - signed char other_mem = v; - if (EINA_UNLIKELY(v > (unsigned char)eina_value_char_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_SHORT) - { - short other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT) - { - int other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_LONG) - { - long other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT64) - { - int64_t other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_FLOAT) - { - float other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_DOUBLE) - { - double other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_STRINGSHARE || - convert == EINA_VALUE_TYPE_STRING) - { - const char *other_mem; - char buf[64]; - snprintf(buf, sizeof(buf), "%hhu", v); - other_mem = buf; /* required due &buf == buf */ - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_uchar_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) -{ - unsigned char *tmem = mem; - *tmem = va_arg(args, unsigned int); /* char is promoted to int for va_arg */ - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_uchar_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) -{ - unsigned char *tmem = mem; - const unsigned char *p = ptr; - *tmem = *p; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_uchar_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - const unsigned char *tmem = mem; - unsigned char *p = ptr; - *p = *tmem; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_ushort_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - unsigned short *tmem = mem; - *tmem = 0; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_ushort_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) -{ - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_ushort_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const unsigned short *s = src; - unsigned short *d = dst; - *d = *s; - return EINA_TRUE; -} - -static int -_eina_value_type_ushort_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const unsigned short *ta = a, *tb = b; - if (*ta < *tb) - return -1; - else if (*ta > *tb) - return 1; - return 0; -} - -static Eina_Bool -_eina_value_type_ushort_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const unsigned short v = *(const unsigned short *)type_mem; - - eina_error_set(0); - - if (convert == EINA_VALUE_TYPE_UCHAR) - { - unsigned char other_mem = v; - if (EINA_UNLIKELY(v > eina_value_uchar_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_USHORT) - { - unsigned short other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT) - { - unsigned int other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) - { - unsigned long other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT64) - { - uint64_t other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_CHAR) - { - signed char other_mem = v; - if (EINA_UNLIKELY(v > (unsigned char)eina_value_char_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_SHORT) - { - short other_mem = v; - if (EINA_UNLIKELY(v > (unsigned short)eina_value_short_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT) - { - int other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_LONG) - { - long other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT64) - { - int64_t other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_FLOAT) - { - float other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_DOUBLE) - { - double other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_STRINGSHARE || - convert == EINA_VALUE_TYPE_STRING) - { - const char *other_mem; - char buf[64]; - snprintf(buf, sizeof(buf), "%hu", v); - other_mem = buf; /* required due &buf == buf */ - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_ushort_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) -{ - unsigned short *tmem = mem; - *tmem = va_arg(args, unsigned int); /* short is promoted to int for va_arg */ - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_ushort_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) -{ - unsigned short *tmem = mem; - const unsigned short *p = ptr; - *tmem = *p; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_ushort_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - const unsigned short *tmem = mem; - unsigned short *p = ptr; - *p = *tmem; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_uint_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - unsigned int *tmem = mem; - *tmem = 0; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_uint_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) -{ - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_uint_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const unsigned int *s = src; - unsigned int *d = dst; - *d = *s; - return EINA_TRUE; -} - -static int -_eina_value_type_uint_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const unsigned int *ta = a, *tb = b; - if (*ta < *tb) - return -1; - else if (*ta > *tb) - return 1; - return 0; -} - -static Eina_Bool -_eina_value_type_uint_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const unsigned int v = *(const unsigned int *)type_mem; - - eina_error_set(0); - - if (convert == EINA_VALUE_TYPE_UCHAR) - { - unsigned char other_mem = v; - if (EINA_UNLIKELY(v > eina_value_uchar_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_USHORT) - { - unsigned short other_mem = v; - if (EINA_UNLIKELY(v > eina_value_ushort_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT) - { - unsigned int other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) - { - unsigned long other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT64) - { - uint64_t other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_CHAR) - { - signed char other_mem = v; - if (EINA_UNLIKELY(v > (unsigned char)eina_value_char_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_SHORT) - { - short other_mem = v; - if (EINA_UNLIKELY(v > (unsigned short)eina_value_short_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT) - { - int other_mem = v; - if (EINA_UNLIKELY(v > (unsigned int)eina_value_int_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_LONG) - { - long other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT64) - { - int64_t other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_FLOAT) - { - float other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_DOUBLE) - { - double other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_STRINGSHARE || - convert == EINA_VALUE_TYPE_STRING) - { - const char *other_mem; - char buf[64]; - snprintf(buf, sizeof(buf), "%u", v); - other_mem = buf; /* required due &buf == buf */ - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_uint_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) -{ - unsigned int *tmem = mem; - *tmem = va_arg(args, unsigned int); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_uint_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) -{ - unsigned int *tmem = mem; - const unsigned int *p = ptr; - *tmem = *p; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_uint_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - const unsigned int *tmem = mem; - unsigned int *p = ptr; - *p = *tmem; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_ulong_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - unsigned long *tmem = mem; - *tmem = 0; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_ulong_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) -{ - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_ulong_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const unsigned long *s = src; - unsigned long *d = dst; - *d = *s; - return EINA_TRUE; -} - -static int -_eina_value_type_ulong_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const unsigned long *ta = a, *tb = b; - if (*ta < *tb) - return -1; - else if (*ta > *tb) - return 1; - return 0; -} - -static Eina_Bool -_eina_value_type_ulong_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const unsigned long v = *(const unsigned long *)type_mem; - - eina_error_set(0); - - if (convert == EINA_VALUE_TYPE_UCHAR) - { - unsigned char other_mem = v; - if (EINA_UNLIKELY(v > eina_value_uchar_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_USHORT) - { - unsigned short other_mem = v; - if (EINA_UNLIKELY(v > eina_value_ushort_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT) - { - unsigned int other_mem = v; - if (EINA_UNLIKELY(v > eina_value_uint_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) - { - unsigned long other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT64) - { - uint64_t other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_CHAR) - { - signed char other_mem = v; - if (EINA_UNLIKELY(v > (unsigned char)eina_value_char_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_SHORT) - { - short other_mem = v; - if (EINA_UNLIKELY(v > (unsigned short)eina_value_short_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT) - { - int other_mem = v; - if (EINA_UNLIKELY(v > (unsigned int)eina_value_int_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_LONG) - { - long other_mem = v; - if (EINA_UNLIKELY(v > (unsigned long)eina_value_long_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT64) - { - int64_t other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_FLOAT) - { - float other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_DOUBLE) - { - double other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_STRINGSHARE || - convert == EINA_VALUE_TYPE_STRING) - { - const char *other_mem; - char buf[64]; - snprintf(buf, sizeof(buf), "%lu", v); - other_mem = buf; /* required due &buf == buf */ - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_ulong_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) -{ - unsigned long *tmem = mem; - *tmem = va_arg(args, unsigned long); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_ulong_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) -{ - unsigned long *tmem = mem; - const unsigned long *p = ptr; - *tmem = *p; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_ulong_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - const unsigned long *tmem = mem; - unsigned long *p = ptr; - *p = *tmem; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_uint64_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - uint64_t *tmem = mem; - *tmem = 0; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_uint64_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) -{ - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_uint64_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const uint64_t *s = src; - uint64_t *d = dst; - *d = *s; - return EINA_TRUE; -} - -static int -_eina_value_type_uint64_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const uint64_t *ta = a, *tb = b; - if (*ta < *tb) - return -1; - else if (*ta > *tb) - return 1; - return 0; -} - -static Eina_Bool -_eina_value_type_uint64_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const uint64_t v = *(const uint64_t *)type_mem; - - eina_error_set(0); - - if (convert == EINA_VALUE_TYPE_UCHAR) - { - unsigned char other_mem = v; - if (EINA_UNLIKELY(v > eina_value_uchar_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_USHORT) - { - unsigned short other_mem = v; - if (EINA_UNLIKELY(v > eina_value_ushort_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT) - { - unsigned int other_mem = v; - if (EINA_UNLIKELY(v > eina_value_uint_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) - { - unsigned long other_mem = v; - if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) && - (v > eina_value_ulong_max))) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT64) - { - uint64_t other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_CHAR) - { - signed char other_mem = v; - if (EINA_UNLIKELY(v > (unsigned char)eina_value_char_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_SHORT) - { - short other_mem = v; - if (EINA_UNLIKELY(v > (unsigned short)eina_value_short_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT) - { - int other_mem = v; - if (EINA_UNLIKELY(v > (unsigned int)eina_value_int_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_LONG) - { - long other_mem = v; - if (EINA_UNLIKELY(v > (unsigned long)eina_value_long_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT64) - { - int64_t other_mem = v; - if (EINA_UNLIKELY(v > (uint64_t)eina_value_int64_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_FLOAT) - { - float other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_DOUBLE) - { - double other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_STRINGSHARE || - convert == EINA_VALUE_TYPE_STRING) - { - const char *other_mem; - char buf[64]; - snprintf(buf, sizeof(buf), "%"PRIu64, v); - other_mem = buf; /* required due &buf == buf */ - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_uint64_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) -{ - uint64_t *tmem = mem; - *tmem = va_arg(args, uint64_t); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_uint64_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) -{ - uint64_t *tmem = mem; - const uint64_t *p = ptr; - *tmem = *p; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_uint64_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - const uint64_t *tmem = mem; - uint64_t *p = ptr; - *p = *tmem; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_char_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - char *tmem = mem; - *tmem = 0; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_char_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) -{ - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_char_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const char *s = src; - char *d = dst; - *d = *s; - return EINA_TRUE; -} - -static int -_eina_value_type_char_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const char *ta = a, *tb = b; - if (*ta < *tb) - return -1; - else if (*ta > *tb) - return 1; - return 0; -} - -static Eina_Bool -_eina_value_type_char_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const signed char v = *(const signed char *)type_mem; - - eina_error_set(0); - - if (convert == EINA_VALUE_TYPE_UCHAR) - { - unsigned char other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_USHORT) - { - unsigned short other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT) - { - unsigned int other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) - { - unsigned long other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT64) - { - uint64_t other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_CHAR) - { - signed char other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_SHORT) - { - short other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT) - { - int other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_LONG) - { - long other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT64) - { - int64_t other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_FLOAT) - { - float other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_DOUBLE) - { - double other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_STRINGSHARE || - convert == EINA_VALUE_TYPE_STRING) - { - const char *other_mem; - char buf[64]; - snprintf(buf, sizeof(buf), "%hhd", v); - other_mem = buf; /* required due &buf == buf */ - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_char_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) -{ - char *tmem = mem; - *tmem = va_arg(args, int); /* char is promoted to int for va_arg */ - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_char_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) -{ - char *tmem = mem; - const char *p = ptr; - *tmem = *p; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_char_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - const char *tmem = mem; - char *p = ptr; - *p = *tmem; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_short_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - short *tmem = mem; - *tmem = 0; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_short_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) -{ - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_short_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const short *s = src; - short *d = dst; - *d = *s; - return EINA_TRUE; -} - -static int -_eina_value_type_short_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const short *ta = a, *tb = b; - if (*ta < *tb) - return -1; - else if (*ta > *tb) - return 1; - return 0; -} - -static Eina_Bool -_eina_value_type_short_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const short v = *(const short *)type_mem; - - eina_error_set(0); - - if (convert == EINA_VALUE_TYPE_UCHAR) - { - unsigned char other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_uchar_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_USHORT) - { - unsigned short other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT) - { - unsigned int other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) - { - unsigned long other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT64) - { - uint64_t other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_CHAR) - { - signed char other_mem = v; - if (EINA_UNLIKELY(v < eina_value_char_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_char_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_SHORT) - { - short other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT) - { - int other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_LONG) - { - long other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT64) - { - int64_t other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_FLOAT) - { - float other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_DOUBLE) - { - double other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_STRINGSHARE || - convert == EINA_VALUE_TYPE_STRING) - { - const char *other_mem; - char buf[64]; - snprintf(buf, sizeof(buf), "%hd", v); - other_mem = buf; /* required due &buf == buf */ - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_short_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) -{ - short *tmem = mem; - *tmem = va_arg(args, int); /* short int is promoted to int for va_arg */ - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_short_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) -{ - short *tmem = mem; - const short *p = ptr; - *tmem = *p; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_short_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - const short *tmem = mem; - short *p = ptr; - *p = *tmem; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_int_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - int *tmem = mem; - *tmem = 0; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_int_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) -{ - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_int_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const int *s = src; - int *d = dst; - *d = *s; - return EINA_TRUE; -} - -static int -_eina_value_type_int_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const int *ta = a, *tb = b; - if (*ta < *tb) - return -1; - else if (*ta > *tb) - return 1; - return 0; -} - -static Eina_Bool -_eina_value_type_int_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const int v = *(const int *)type_mem; - - eina_error_set(0); - - if (convert == EINA_VALUE_TYPE_UCHAR) - { - unsigned char other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_uchar_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_USHORT) - { - unsigned short other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_ushort_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT) - { - unsigned int other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) - { - unsigned long other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT64) - { - uint64_t other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_CHAR) - { - signed char other_mem = v; - if (EINA_UNLIKELY(v < eina_value_char_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_char_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_SHORT) - { - short other_mem = v; - if (EINA_UNLIKELY(v < eina_value_short_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_short_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT) - { - int other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_LONG) - { - long other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT64) - { - int64_t other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_FLOAT) - { - float other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_DOUBLE) - { - double other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_STRINGSHARE || - convert == EINA_VALUE_TYPE_STRING) - { - const char *other_mem; - char buf[64]; - snprintf(buf, sizeof(buf), "%d", v); - other_mem = buf; /* required due &buf == buf */ - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_int_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) -{ - int *tmem = mem; - *tmem = va_arg(args, int); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_int_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) -{ - int *tmem = mem; - const int *p = ptr; - *tmem = *p; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_int_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - const int *tmem = mem; - int *p = ptr; - *p = *tmem; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_long_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - long *tmem = mem; - *tmem = 0; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_long_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) -{ - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_long_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const long *s = src; - long *d = dst; - *d = *s; - return EINA_TRUE; -} - -static int -_eina_value_type_long_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const long *ta = a, *tb = b; - if (*ta < *tb) - return -1; - else if (*ta > *tb) - return 1; - return 0; -} - -static Eina_Bool -_eina_value_type_long_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const long v = *(const long *)type_mem; - - eina_error_set(0); - - if (convert == EINA_VALUE_TYPE_UCHAR) - { - unsigned char other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY((unsigned long) v > eina_value_uchar_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_USHORT) - { - unsigned short other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY((unsigned long) v > eina_value_ushort_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT) - { - unsigned int other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY((unsigned long) v > eina_value_uint_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) - { - unsigned long other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT64) - { - uint64_t other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_CHAR) - { - signed char other_mem = v; - if (EINA_UNLIKELY(v < eina_value_char_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_char_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_SHORT) - { - short other_mem = v; - if (EINA_UNLIKELY(v < eina_value_short_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_short_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT) - { - int other_mem = v; - if (EINA_UNLIKELY(v < eina_value_int_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_int_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_LONG) - { - long other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT64) - { - int64_t other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_FLOAT) - { - float other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_DOUBLE) - { - double other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_STRINGSHARE || - convert == EINA_VALUE_TYPE_STRING) - { - const char *other_mem; - char buf[64]; - snprintf(buf, sizeof(buf), "%ld", v); - other_mem = buf; /* required due &buf == buf */ - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_long_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) -{ - long *tmem = mem; - *tmem = va_arg(args, long); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_long_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) -{ - long *tmem = mem; - const long *p = ptr; - *tmem = *p; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_long_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - const long *tmem = mem; - long *p = ptr; - *p = *tmem; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_int64_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - int64_t *tmem = mem; - *tmem = 0; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_int64_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) -{ - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_int64_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const int64_t *s = src; - int64_t *d = dst; - *d = *s; - return EINA_TRUE; -} - -static int -_eina_value_type_int64_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const int64_t *ta = a, *tb = b; - if (*ta < *tb) - return -1; - else if (*ta > *tb) - return 1; - return 0; -} - -static Eina_Bool -_eina_value_type_int64_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const int64_t v = *(const int64_t *)type_mem; - - eina_error_set(0); - - if (convert == EINA_VALUE_TYPE_UCHAR) - { - unsigned char other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_uchar_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_USHORT) - { - unsigned short other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_ushort_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT) - { - unsigned int other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_uint_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) - { - unsigned long other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) && - (v > eina_value_ulong_max))) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT64) - { - uint64_t other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_CHAR) - { - signed char other_mem = v; - if (EINA_UNLIKELY(v < eina_value_char_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_char_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_SHORT) - { - short other_mem = v; - if (EINA_UNLIKELY(v < eina_value_short_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_short_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT) - { - int other_mem = v; - if (EINA_UNLIKELY(v < eina_value_int_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_int_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_LONG) - { - long other_mem = v; - if (EINA_UNLIKELY(v < eina_value_long_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_long_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT64) - { - int64_t other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_FLOAT) - { - float other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_DOUBLE) - { - double other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_STRINGSHARE || - convert == EINA_VALUE_TYPE_STRING) - { - const char *other_mem; - char buf[64]; - snprintf(buf, sizeof(buf), "%"PRId64, v); - other_mem = buf; /* required due &buf == buf */ - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_int64_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) -{ - int64_t *tmem = mem; - *tmem = va_arg(args, int64_t); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_int64_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) -{ - int64_t *tmem = mem; - const int64_t *p = ptr; - *tmem = *p; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_int64_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - const int64_t *tmem = mem; - int64_t *p = ptr; - *p = *tmem; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_float_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - float *tmem = mem; - *tmem = 0; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_float_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) -{ - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_float_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const float *s = src; - float *d = dst; - *d = *s; - return EINA_TRUE; -} - -static int -_eina_value_type_float_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const float *ta = a, *tb = b; - if (*ta < *tb) - return -1; - else if (*ta > *tb) - return 1; - return 0; -} - -static Eina_Bool -_eina_value_type_float_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const float v = *(const float *)type_mem; - - eina_error_set(0); - - if (convert == EINA_VALUE_TYPE_UCHAR) - { - unsigned char other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_uchar_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_USHORT) - { - unsigned short other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_ushort_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT) - { - unsigned int other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_uint_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) - { - unsigned long other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) && - (v > eina_value_ulong_max))) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT64) - { - uint64_t other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_uint64_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_CHAR) - { - signed char other_mem = v; - if (EINA_UNLIKELY(v < eina_value_char_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_char_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_SHORT) - { - short other_mem = v; - if (EINA_UNLIKELY(v < eina_value_short_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_short_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT) - { - int other_mem = v; - if (EINA_UNLIKELY(v < eina_value_int_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_int_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_LONG) - { - long other_mem = v; - if (EINA_UNLIKELY(v < eina_value_long_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_long_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT64) - { - int64_t other_mem = v; - if (EINA_UNLIKELY(v < eina_value_int64_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_int64_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_FLOAT) - { - float other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_DOUBLE) - { - double other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_STRINGSHARE || - convert == EINA_VALUE_TYPE_STRING) - { - const char *other_mem; - char buf[64]; - snprintf(buf, sizeof(buf), "%f", v); - other_mem = buf; /* required due &buf == buf */ - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_float_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) -{ - float *tmem = mem; - *tmem = va_arg(args, double); /* float is promoted to double for va_args */ - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_float_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) -{ - float *tmem = mem; - const float *p = ptr; - *tmem = *p; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_float_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - const float *tmem = mem; - float *p = ptr; - *p = *tmem; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_double_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - double *tmem = mem; - *tmem = 0; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_double_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) -{ - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_double_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const double *s = src; - double *d = dst; - *d = *s; - return EINA_TRUE; -} - -static int -_eina_value_type_double_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const double *ta = a, *tb = b; - if (*ta < *tb) - return -1; - else if (*ta > *tb) - return 1; - return 0; -} - -static Eina_Bool -_eina_value_type_double_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const double v = *(const double *)type_mem; - - eina_error_set(0); - - if (convert == EINA_VALUE_TYPE_UCHAR) - { - unsigned char other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_uchar_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_USHORT) - { - unsigned short other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_ushort_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT) - { - unsigned int other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_uint_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) - { - unsigned long other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) && - (v > eina_value_ulong_max))) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT64) - { - uint64_t other_mem = v; - if (EINA_UNLIKELY(v < 0)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_CHAR) - { - signed char other_mem = v; - if (EINA_UNLIKELY(v < eina_value_char_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_char_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_SHORT) - { - short other_mem = v; - if (EINA_UNLIKELY(v < eina_value_short_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_short_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT) - { - int other_mem = v; - if (EINA_UNLIKELY(v < eina_value_int_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_int_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_LONG) - { - long other_mem = v; - if (EINA_UNLIKELY(v < eina_value_long_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v > eina_value_long_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT64) - { - int64_t other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_FLOAT) - { - float other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_DOUBLE) - { - double other_mem = v; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_STRINGSHARE || - convert == EINA_VALUE_TYPE_STRING) - { - const char *other_mem; - char buf[64]; - snprintf(buf, sizeof(buf), "%g", (double)v); - other_mem = buf; /* required due &buf == buf */ - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_double_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) -{ - double *tmem = mem; - *tmem = va_arg(args, double); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_double_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) -{ - double *tmem = mem; - const double *p = ptr; - *tmem = *p; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_double_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - const double *tmem = mem; - double *p = ptr; - *p = *tmem; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_string_common_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - const char **tmem = mem; - *tmem = NULL; - return EINA_TRUE; -} - -static int -_eina_value_type_string_common_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const char *sa = *(const char **)a; - const char *sb = *(const char **)b; - if (sa == sb) - return 0; - if (sa == NULL) - return -1; - if (sb == NULL) - return 1; - return strcmp(sa, sb); -} - -static Eina_Bool -_eina_value_type_string_common_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const char *v = *(const char **)type_mem; - - eina_error_set(0); - - if (convert == EINA_VALUE_TYPE_UCHAR) - { - unsigned char other_mem; - if ((sscanf(v, "%hhu", &other_mem) != 1) && - (sscanf(v, "%hhx", &other_mem) != 1) && - (sscanf(v, "%hho", &other_mem) != 1)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_USHORT) - { - unsigned short other_mem; - if ((sscanf(v, "%hu", &other_mem) != 1) && - (sscanf(v, "%hx", &other_mem) != 1) && - (sscanf(v, "%ho", &other_mem) != 1)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT) - { - unsigned int other_mem; - if ((sscanf(v, "%u", &other_mem) != 1) && - (sscanf(v, "%x", &other_mem) != 1) && - (sscanf(v, "%o", &other_mem) != 1)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) - { - unsigned long other_mem; - if ((sscanf(v, "%lu", &other_mem) != 1) && - (sscanf(v, "%lx", &other_mem) != 1) && - (sscanf(v, "%lo", &other_mem) != 1)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT64) - { - uint64_t other_mem; - if ((sscanf(v, "%"SCNu64, &other_mem) != 1) && - (sscanf(v, "%"SCNx64, &other_mem) != 1) && - (sscanf(v, "%"SCNo64, &other_mem) != 1)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_CHAR) - { - signed char other_mem; - if ((sscanf(v, "%hhd", &other_mem) != 1) && - (sscanf(v, "%hhx", &other_mem) != 1) && - (sscanf(v, "%hho", &other_mem) != 1)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_SHORT) - { - short other_mem; - if ((sscanf(v, "%hd", &other_mem) != 1) && - (sscanf(v, "%hx", &other_mem) != 1) && - (sscanf(v, "%ho", &other_mem) != 1)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT) - { - int other_mem; - if ((sscanf(v, "%d", &other_mem) != 1) && - (sscanf(v, "%x", &other_mem) != 1) && - (sscanf(v, "%o", &other_mem) != 1)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_LONG) - { - long other_mem; - if ((sscanf(v, "%ld", &other_mem) != 1) && - (sscanf(v, "%lx", &other_mem) != 1) && - (sscanf(v, "%lo", &other_mem) != 1)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT64) - { - int64_t other_mem; - if ((sscanf(v, "%"SCNd64, &other_mem) != 1) && - (sscanf(v, "%"SCNx64, &other_mem) != 1) && - (sscanf(v, "%"SCNo64, &other_mem) != 1)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_FLOAT) - { - float other_mem; - if (sscanf(v, "%f", &other_mem) != 1) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_DOUBLE) - { - double other_mem; - if (sscanf(v, "%lf", &other_mem) != 1) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_STRINGSHARE || - convert == EINA_VALUE_TYPE_STRING) - { - return eina_value_type_pset(convert, convert_mem, &v); - } - else - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_string_common_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - memcpy(ptr, mem, sizeof(const char *)); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_stringshare_flush(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - const char **tmem = mem; - if (*tmem) - { - eina_stringshare_del(*tmem); - *tmem = NULL; - } - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_stringshare_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const char * const*s = src; - const char **d = dst; - *d = eina_stringshare_add(*s); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_stringshare_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) -{ - const char *str = va_arg(args, const char *); - return eina_stringshare_replace((const char **)mem, str); -} - -static Eina_Bool -_eina_value_type_stringshare_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) -{ - const char * const *str = ptr; - return eina_stringshare_replace((const char **)mem, *str); -} - -static Eina_Bool -_eina_value_type_string_flush(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - char **tmem = mem; - if (*tmem) - { - free(*tmem); - *tmem = NULL; - } - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_string_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const char * const *s = src; - char **d = dst; - if (*s == NULL) - *d = NULL; - else - { - *d = strdup(*s); - if (*d == NULL) - { - eina_error_set(EINA_ERROR_OUT_OF_MEMORY); - return EINA_FALSE; - } - } - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_string_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) -{ - char **tmem = mem; - const char *str = va_arg(args, const char *); - eina_error_set(0); - if (str == *tmem) return EINA_TRUE; - if (!str) - { - free(*tmem); - *tmem = NULL; - } - else - { - char *tmp = strdup(str); - if (!tmp) - { - eina_error_set(EINA_ERROR_OUT_OF_MEMORY); - return EINA_FALSE; - } - free(*tmem); - *tmem = tmp; - } - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_string_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) -{ - char **tmem = mem; - const char * const *str = ptr; - eina_error_set(0); - if (*str == *tmem) return EINA_TRUE; - if (!*str) - { - free(*tmem); - *tmem = NULL; - } - else - { - char *tmp = strdup(*str); - if (!tmp) - { - eina_error_set(EINA_ERROR_OUT_OF_MEMORY); - return EINA_FALSE; - } - free(*tmem); - *tmem = tmp; - } - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_array_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - memset(mem, 0, sizeof(Eina_Value_Array)); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_array_flush_elements(Eina_Value_Array *tmem) -{ - const Eina_Value_Type *subtype = tmem->subtype; - Eina_Bool ret = EINA_TRUE; - unsigned char sz; - char *ptr, *ptr_end; - - if (!tmem->array) return EINA_TRUE; - - sz = tmem->array->member_size; - ptr = tmem->array->members; - ptr_end = ptr + tmem->array->len * sz; - - for (; ptr < ptr_end; ptr += sz) - ret &= eina_value_type_flush(subtype, ptr); - - eina_inarray_flush(tmem->array); - return ret; -} - -static Eina_Bool -_eina_value_type_array_flush(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - Eina_Value_Array *tmem = mem; - Eina_Bool ret =_eina_value_type_array_flush_elements(tmem); - - if (tmem->array) eina_inarray_free(tmem->array); - tmem->array = NULL; - tmem->subtype = NULL; - return ret; -} - -static Eina_Bool -_eina_value_type_array_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const Eina_Value_Type *subtype; - const Eina_Value_Array *s = src; - Eina_Value_Array *d = dst; - unsigned int i, count, sz; - char *ptr, *ptr_end; - - d->subtype = subtype = s->subtype; - d->step = s->step; - - if ((!s->array) || (!s->subtype)) - { - d->array = NULL; - return EINA_TRUE; - } - - if (!subtype->copy) - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - - d->array = eina_inarray_new(subtype->value_size, s->step); - if (!d->array) - return EINA_FALSE; - - sz = s->array->member_size; - - count = eina_inarray_count(s->array); - ptr = s->array->members; - ptr_end = ptr + (count * sz); - - for (i = 0; ptr < ptr_end; ptr += sz, i++) - { - void *imem = eina_inarray_alloc_at(d->array, i, 1); - if (!imem) goto error; - if (!subtype->copy(subtype, ptr, imem)) - { - eina_inarray_pop(d->array); - goto error; - } - } - - return EINA_TRUE; - - error: - _eina_value_type_array_flush_elements(d); - return EINA_FALSE; -} - -static int -_eina_value_type_array_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const Eina_Value_Type *subtype; - const Eina_Value_Array *eva_a = a, *eva_b = b; - const char *a_ptr, *a_ptr_end, *b_ptr; - unsigned int count_a, count_b, count, sz; - int cmp = 0; - - if (eva_a->subtype != eva_b->subtype) - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return -1; - } - - subtype = eva_a->subtype; - if (!subtype->compare) - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return 0; - } - - if ((!eva_a->array) && (!eva_b->array)) - return 0; - else if (!eva_a->array) - return -1; - else if (!eva_b->array) - return 1; - - count_a = eina_inarray_count(eva_a->array); - count_b = eina_inarray_count(eva_b->array); - - if (count_a <= count_b) - count = count_a; - else - count = count_b; - - sz = eva_a->array->member_size; - - a_ptr = eva_a->array->members; - a_ptr_end = a_ptr + (count * sz); - b_ptr = eva_b->array->members; - - for (; (cmp == 0) && (a_ptr < a_ptr_end); a_ptr += sz, b_ptr += sz) - cmp = subtype->compare(subtype, a_ptr, b_ptr); - - if (cmp == 0) - { - if (count_a < count_b) - return -1; - else if (count_a > count_b) - return 1; - return 0; - } - - return cmp; -} - -static Eina_Bool -_eina_value_type_array_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const Eina_Value_Array *tmem = type_mem; - Eina_Bool ret = EINA_FALSE; - - if ((convert == EINA_VALUE_TYPE_STRING) || - (convert == EINA_VALUE_TYPE_STRINGSHARE)) - { - Eina_Strbuf *str = eina_strbuf_new(); - const char *ptr; - if (!tmem->array) eina_strbuf_append(str, "[]"); - else - { - const Eina_Value_Type *subtype = tmem->subtype; - unsigned char sz; - const char *ptr_end; - Eina_Value tmp; - Eina_Bool first = EINA_TRUE; - - eina_value_setup(&tmp, EINA_VALUE_TYPE_STRING); - - eina_strbuf_append_char(str, '['); - - sz = tmem->array->member_size; - ptr = tmem->array->members; - ptr_end = ptr + tmem->array->len * sz; - for (; ptr < ptr_end; ptr += sz) - { - Eina_Bool r = EINA_FALSE; - if (subtype->convert_to) - { - r = subtype->convert_to(subtype, EINA_VALUE_TYPE_STRING, - ptr, tmp.value.buf); - if (r) - { - if (first) first = EINA_FALSE; - else eina_strbuf_append_length(str, ", ", 2); - eina_strbuf_append(str, tmp.value.ptr); - free(tmp.value.ptr); - tmp.value.ptr = NULL; - } - } - - if (!r) - { - if (first) - { - first = EINA_FALSE; - eina_strbuf_append_char(str, '?'); - } - else - eina_strbuf_append_length(str, ", ?", 3); - } - } - - eina_strbuf_append_char(str, ']'); - } - ptr = eina_strbuf_string_get(str); - ret = eina_value_type_pset(convert, convert_mem, &ptr); - eina_strbuf_free(str); - } - else if ((tmem->array) && (tmem->array->len == 1)) - { - const Eina_Value_Type *subtype = tmem->subtype; - void *imem = tmem->array->members; - - if (subtype->convert_to) - ret = subtype->convert_to(subtype, convert, imem, convert_mem); - if ((!ret) && (convert->convert_from)) - ret = convert->convert_from(convert, subtype, convert_mem, imem); - } - - if (!ret) - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_array_convert_from(const Eina_Value_Type *type, const Eina_Value_Type *convert, void *type_mem, const void *convert_mem) -{ - Eina_Value_Array *tmem = type_mem; - Eina_Value_Array desc = {convert, tmem->step, NULL}; - char *buf; - void *imem; - - if (!eina_value_type_pset(type, tmem, &desc)) - return EINA_FALSE; - - buf = alloca(convert->value_size); - if (!eina_value_type_pget(convert, convert_mem, &buf)) - return EINA_FALSE; - - imem = eina_inarray_alloc_at(tmem->array, 0, 1); - if (!imem) - return EINA_FALSE; - - if (!eina_value_type_setup(convert, imem)) goto error_setup; - if (!eina_value_type_pset(convert, imem, &buf)) goto error_set; - return EINA_TRUE; - - error_set: - eina_value_type_flush(convert, imem); - error_setup: - eina_inarray_remove_at(tmem->array, 0); - return EINA_FALSE; -} - -static Eina_Bool -_eina_value_type_array_pset(const Eina_Value_Type *type, void *mem, const void *ptr) -{ - Eina_Value_Array *tmem = mem; - const Eina_Value_Array *desc = ptr; - Eina_Inarray *desc_array; - - eina_error_set(0); - if ((!tmem->subtype) && (!desc->subtype)) - return EINA_TRUE; - - desc_array = desc->array; - if (desc_array) - { - Eina_Value_Array tmp; - - EINA_SAFETY_ON_FALSE_RETURN_VAL - (desc_array->member_size == desc->subtype->value_size, EINA_FALSE); - - if (desc_array == tmem->array) - { - tmem->subtype = desc->subtype; - return EINA_TRUE; - } - - if (!_eina_value_type_array_copy(type, desc, &tmp)) - return EINA_FALSE; - - _eina_value_type_array_flush(type, tmem); - memcpy(tmem, &tmp, sizeof(tmp)); - return EINA_TRUE; - } - - if (tmem->array) - { - _eina_value_type_array_flush_elements(tmem); - eina_inarray_step_set(tmem->array, sizeof (Eina_Inarray), desc->subtype->value_size, desc->step); - } - else - { - tmem->array = eina_inarray_new(desc->subtype->value_size, desc->step); - if (!tmem->array) - return EINA_FALSE; - } - - tmem->subtype = desc->subtype; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_array_vset(const Eina_Value_Type *type, void *mem, va_list args) -{ - const Eina_Value_Array desc = va_arg(args, Eina_Value_Array); - _eina_value_type_array_pset(type, mem, &desc); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_array_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - memcpy(ptr, mem, sizeof(Eina_Value_Array)); - return EINA_TRUE; -} - -static const Eina_Value_Type _EINA_VALUE_TYPE_ARRAY = { - EINA_VALUE_TYPE_VERSION, - sizeof(Eina_Value_Array), - "Eina_Value_Array", - _eina_value_type_array_setup, - _eina_value_type_array_flush, - _eina_value_type_array_copy, - _eina_value_type_array_compare, - _eina_value_type_array_convert_to, - _eina_value_type_array_convert_from, - _eina_value_type_array_vset, - _eina_value_type_array_pset, - _eina_value_type_array_pget -}; - -static Eina_Bool -_eina_value_type_list_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - memset(mem, 0, sizeof(Eina_Value_List)); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_list_flush_elements(Eina_Value_List *tmem) -{ - const Eina_Value_Type *subtype = tmem->subtype; - Eina_Bool ret = EINA_TRUE; - - if (!tmem->list) return EINA_TRUE; - - while (tmem->list) - { - void *mem = eina_value_list_node_memory_get(tmem->subtype, tmem->list); - ret &= eina_value_type_flush(subtype, mem); - eina_value_list_node_memory_flush(tmem->subtype, tmem->list); - tmem->list = eina_list_remove_list(tmem->list, tmem->list); - } - - return ret; -} - -static Eina_Bool -_eina_value_type_list_flush(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - Eina_Value_List *tmem = mem; - Eina_Bool ret =_eina_value_type_list_flush_elements(tmem); - - if (tmem->list) eina_list_free(tmem->list); - tmem->list = NULL; - tmem->subtype = NULL; - return ret; -} - -static Eina_Bool -_eina_value_type_list_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const Eina_Value_Type *subtype; - const Eina_Value_List *s = src; - Eina_Value_List *d = dst; - const Eina_List *snode; - - d->subtype = subtype = s->subtype; - if ((!s->list) || (!s->subtype)) - { - d->list = NULL; - return EINA_TRUE; - } - - if (!subtype->copy) - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - - d->list = NULL; - for (snode = s->list; snode != NULL; snode = snode->next) - { - const void *ptr = eina_value_list_node_memory_get(subtype, snode); - Eina_List *dnode; - void *imem; - - d->list = eina_list_append(d->list, (void*)1L); - dnode = eina_list_last(d->list); - EINA_SAFETY_ON_NULL_GOTO(dnode, error); - EINA_SAFETY_ON_FALSE_GOTO(dnode->data == (void*)1L, error); - - imem = eina_value_list_node_memory_setup(subtype, dnode); - if (!subtype->copy(subtype, ptr, imem)) - { - eina_value_list_node_memory_flush(subtype, dnode); - d->list = eina_list_remove_list(d->list, dnode); - goto error; - } - } - return EINA_TRUE; - - error: - _eina_value_type_list_flush_elements(d); - return EINA_FALSE; -} - -static int -_eina_value_type_list_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const Eina_Value_Type *subtype; - const Eina_Value_List *eva_a = a, *eva_b = b; - const Eina_List *anode, *bnode; - int cmp = 0; - - if (eva_a->subtype != eva_b->subtype) - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return -1; - } - - subtype = eva_a->subtype; - if (!subtype->compare) - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return 0; - } - - if ((!eva_a->list) && (!eva_b->list)) - return 0; - else if (!eva_a->list) - return -1; - else if (!eva_b->list) - return 1; - - for (anode = eva_a->list, bnode = eva_b->list; - (cmp == 0) && (anode) && (bnode); - anode = anode->next, bnode = bnode->next) - { - const void *amem = eina_value_list_node_memory_get(subtype, anode); - const void *bmem = eina_value_list_node_memory_get(subtype, bnode); - cmp = subtype->compare(subtype, amem, bmem); - } - - if (cmp == 0) - { - if ((!anode) && (bnode)) - return -1; - else if ((anode) && (!bnode)) - return 1; - return 0; - } - - return cmp; -} - -static Eina_Bool -_eina_value_type_list_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const Eina_Value_List *tmem = type_mem; - Eina_Bool ret = EINA_FALSE; - - if ((convert == EINA_VALUE_TYPE_STRING) || - (convert == EINA_VALUE_TYPE_STRINGSHARE)) - { - Eina_Strbuf *str = eina_strbuf_new(); - const char *s; - if (!tmem->list) eina_strbuf_append(str, "[]"); - else - { - const Eina_Value_Type *subtype = tmem->subtype; - const Eina_List *node; - Eina_Value tmp; - Eina_Bool first = EINA_TRUE; - - eina_value_setup(&tmp, EINA_VALUE_TYPE_STRING); - - eina_strbuf_append_char(str, '['); - - for (node = tmem->list; node != NULL; node = node->next) - { - Eina_Bool r = EINA_FALSE; - - if (subtype->convert_to) - { - const void *ptr; - ptr = eina_value_list_node_memory_get(subtype, node); - r = subtype->convert_to(subtype, EINA_VALUE_TYPE_STRING, - ptr, tmp.value.buf); - if (r) - { - if (first) first = EINA_FALSE; - else eina_strbuf_append_length(str, ", ", 2); - eina_strbuf_append(str, tmp.value.ptr); - free(tmp.value.ptr); - tmp.value.ptr = NULL; - } - } - - if (!r) - { - if (first) - { - first = EINA_FALSE; - eina_strbuf_append_char(str, '?'); - } - else - eina_strbuf_append_length(str, ", ?", 3); - } - } - - eina_strbuf_append_char(str, ']'); - } - s = eina_strbuf_string_get(str); - ret = eina_value_type_pset(convert, convert_mem, &s); - eina_strbuf_free(str); - } - else if ((tmem->list) && (tmem->list->next == NULL)) - { - const Eina_Value_Type *subtype = tmem->subtype; - void *imem = eina_value_list_node_memory_get(subtype, tmem->list); - - if (subtype->convert_to) - ret = subtype->convert_to(subtype, convert, imem, convert_mem); - if ((!ret) && (convert->convert_from)) - ret = convert->convert_from(convert, subtype, convert_mem, imem); - } - - if (!ret) - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_list_convert_from(const Eina_Value_Type *type, const Eina_Value_Type *convert, void *type_mem, const void *convert_mem) -{ - Eina_Value_List *tmem = type_mem; - Eina_Value_List desc = {convert, NULL}; - Eina_List *node; - char *buf; - void *imem; - - if (!eina_value_type_pset(type, tmem, &desc)) - return EINA_FALSE; - - buf = alloca(convert->value_size); - if (!eina_value_type_pget(convert, convert_mem, &buf)) - return EINA_FALSE; - - tmem->list = eina_list_append(tmem->list, (void*)1L); - node = eina_list_last(tmem->list); - EINA_SAFETY_ON_NULL_RETURN_VAL(node, EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL(node->data == (void*)1L, EINA_FALSE); - - imem = eina_value_list_node_memory_setup(tmem->subtype, node); - if (!imem) - { - tmem->list = eina_list_remove_list(tmem->list, node); - return EINA_FALSE; - } - - if (!eina_value_type_setup(tmem->subtype, imem)) goto error_setup; - if (!eina_value_type_pset(tmem->subtype, imem, &buf)) goto error_set; - return EINA_TRUE; - - error_set: - eina_value_type_flush(tmem->subtype, imem); - error_setup: - eina_value_list_node_memory_flush(tmem->subtype, node); - tmem->list = eina_list_remove_list(tmem->list, node); - return EINA_FALSE; -} - -static Eina_Bool -_eina_value_type_list_pset(const Eina_Value_Type *type, void *mem, const void *ptr) -{ - Eina_Value_List *tmem = mem; - const Eina_Value_List *desc = ptr; - - eina_error_set(0); - if ((!tmem->subtype) && (!desc->subtype)) - return EINA_TRUE; - - if ((tmem->list) && (tmem->list == desc->list)) - { - tmem->subtype = desc->subtype; - return EINA_TRUE; - } - - if (desc->list) - { - Eina_Value_List tmp; - - if (!_eina_value_type_list_copy(type, desc, &tmp)) - return EINA_FALSE; - - _eina_value_type_list_flush(type, tmem); - memcpy(tmem, &tmp, sizeof(tmp)); - return EINA_TRUE; - } - - _eina_value_type_list_flush_elements(tmem); - - tmem->subtype = desc->subtype; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_list_vset(const Eina_Value_Type *type, void *mem, va_list args) -{ - const Eina_Value_List desc = va_arg(args, Eina_Value_List); - _eina_value_type_list_pset(type, mem, &desc); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_list_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - memcpy(ptr, mem, sizeof(Eina_Value_List)); - return EINA_TRUE; -} - -static const Eina_Value_Type _EINA_VALUE_TYPE_LIST = { - EINA_VALUE_TYPE_VERSION, - sizeof(Eina_Value_List), - "Eina_Value_List", - _eina_value_type_list_setup, - _eina_value_type_list_flush, - _eina_value_type_list_copy, - _eina_value_type_list_compare, - _eina_value_type_list_convert_to, - _eina_value_type_list_convert_from, - _eina_value_type_list_vset, - _eina_value_type_list_pset, - _eina_value_type_list_pget -}; - -static Eina_Bool -_eina_value_type_hash_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - memset(mem, 0, sizeof(Eina_Value_Hash)); - return EINA_TRUE; -} - -struct _eina_value_type_hash_flush_each_ctx -{ - const Eina_Value_Type *subtype; - Eina_Bool ret; -}; - -static Eina_Bool -_eina_value_type_hash_flush_each(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *mem, void *user_data) -{ - struct _eina_value_type_hash_flush_each_ctx *ctx = user_data; - ctx->ret &= eina_value_type_flush(ctx->subtype, mem); - free(mem); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_hash_flush_elements(Eina_Value_Hash *tmem) -{ - struct _eina_value_type_hash_flush_each_ctx ctx = { - tmem->subtype, - EINA_TRUE - }; - - if (!tmem->hash) return EINA_TRUE; - - eina_hash_foreach(tmem->hash, _eina_value_type_hash_flush_each, &ctx); - eina_hash_free(tmem->hash); - tmem->hash = NULL; - return ctx.ret; -} - -static Eina_Bool -_eina_value_type_hash_flush(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - Eina_Value_Hash *tmem = mem; - Eina_Bool ret =_eina_value_type_hash_flush_elements(tmem); - tmem->subtype = NULL; - return ret; -} - -static unsigned int -_eina_value_hash_key_length(const void *key) -{ - if (!key) - return 0; - return (int)strlen(key) + 1; -} - -static int -_eina_value_hash_key_cmp(const void *key1, int key1_len, const void *key2, int key2_len) -{ - int r = key1_len - key2_len; - if (r != 0) - return r; - return strcmp(key1, key2); -} - -static Eina_Bool -_eina_value_type_hash_create(Eina_Value_Hash *desc) -{ - if (!desc->buckets_power_size) - desc->buckets_power_size = 5; - - desc->hash = eina_hash_new(_eina_value_hash_key_length, - _eina_value_hash_key_cmp, - EINA_KEY_HASH(eina_hash_superfast), - NULL, desc->buckets_power_size); - return !!desc->hash; -} - -struct _eina_value_type_hash_copy_each_ctx -{ - const Eina_Value_Type *subtype; - Eina_Value_Hash *dest; - Eina_Bool ret; -}; - -static Eina_Bool -_eina_value_type_hash_copy_each(const Eina_Hash *hash __UNUSED__, const void *key, void *_ptr, void *user_data) -{ - struct _eina_value_type_hash_copy_each_ctx *ctx = user_data; - const void *ptr = _ptr; - void *imem = malloc(ctx->subtype->value_size); - if (!imem) - { - ctx->ret = EINA_FALSE; - return EINA_FALSE; - } - if (!ctx->subtype->copy(ctx->subtype, ptr, imem)) - { - free(imem); - ctx->ret = EINA_FALSE; - return EINA_FALSE; - } - if (!eina_hash_add(ctx->dest->hash, key, imem)) - { - eina_value_type_flush(ctx->subtype, imem); - free(imem); - ctx->ret = EINA_FALSE; - return EINA_FALSE; - } - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_hash_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const Eina_Value_Hash *s = src; - Eina_Value_Hash *d = dst; - struct _eina_value_type_hash_copy_each_ctx ctx = {s->subtype, d, EINA_TRUE}; - - d->subtype = s->subtype; - d->buckets_power_size = s->buckets_power_size; - - if ((!s->hash) || (!s->subtype)) - { - d->hash = NULL; - return EINA_TRUE; - } - - if (!s->subtype->copy) - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - - if (!_eina_value_type_hash_create(d)) - return EINA_FALSE; - - eina_hash_foreach(s->hash, _eina_value_type_hash_copy_each, &ctx); - if (!ctx.ret) - { - _eina_value_type_hash_flush_elements(d); - return EINA_FALSE; - } - return EINA_TRUE; -} - -struct _eina_value_type_hash_compare_each_ctx -{ - const Eina_Value_Type *subtype; - const Eina_Hash *other; - int cmp; -}; - -static Eina_Bool -_eina_value_type_hash_compare_each(const Eina_Hash *hash __UNUSED__, const void *key, void *_ptr, void *user_data) -{ - struct _eina_value_type_hash_compare_each_ctx *ctx = user_data; - const void *self_ptr = _ptr; - const void *other_ptr = eina_hash_find(ctx->other, key); - if (!other_ptr) return EINA_TRUE; - ctx->cmp = ctx->subtype->compare(ctx->subtype, self_ptr, other_ptr); - return ctx->cmp == 0; -} - -static int -_eina_value_type_hash_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const Eina_Value_Hash *eva_a = a, *eva_b = b; - struct _eina_value_type_hash_compare_each_ctx ctx = { - eva_a->subtype, eva_b->hash, 0 - }; - - if (eva_a->subtype != eva_b->subtype) - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return -1; - } - - if (!eva_a->subtype->compare) - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return 0; - } - - if ((!eva_a->hash) && (!eva_b->hash)) - return 0; - else if (!eva_a->hash) - return -1; - else if (!eva_b->hash) - return 1; - - eina_hash_foreach(eva_a->hash, _eina_value_type_hash_compare_each, &ctx); - if (ctx.cmp == 0) - { - unsigned int count_a = eina_hash_population(eva_a->hash); - unsigned int count_b = eina_hash_population(eva_b->hash); - if (count_a < count_b) - return -1; - else if (count_a > count_b) - return 1; - return 0; - } - - return ctx.cmp; -} - -static Eina_Bool -_eina_value_type_hash_find_first(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *ptr, void *user_data) -{ - void **ret = user_data; - *ret = ptr; - return EINA_FALSE; -} - -struct _eina_value_type_hash_convert_to_string_each_ctx -{ - const Eina_Value_Type *subtype; - Eina_Strbuf *str; - Eina_Value tmp; - Eina_Bool first; -}; - -static Eina_Bool -_eina_value_type_hash_convert_to_string_each(const Eina_Hash *hash __UNUSED__, const void *_key, void *_ptr, void *user_data) -{ - struct _eina_value_type_hash_convert_to_string_each_ctx *ctx = user_data; - const char *key = _key; - const void *ptr = _ptr; - Eina_Bool r = EINA_FALSE; - - if (ctx->first) ctx->first = EINA_FALSE; - else eina_strbuf_append_length(ctx->str, ", ", 2); - - eina_strbuf_append(ctx->str, key); - eina_strbuf_append_length(ctx->str, ": ", 2); - - if (ctx->subtype->convert_to) - { - r = ctx->subtype->convert_to(ctx->subtype, EINA_VALUE_TYPE_STRING, - ptr, ctx->tmp.value.buf); - if (r) - { - eina_strbuf_append(ctx->str, ctx->tmp.value.ptr); - free(ctx->tmp.value.ptr); - ctx->tmp.value.ptr = NULL; - } - } - - if (!r) - eina_strbuf_append_char(ctx->str, '?'); - - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_hash_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const Eina_Value_Hash *tmem = type_mem; - Eina_Bool ret = EINA_FALSE; - - if ((convert == EINA_VALUE_TYPE_STRING) || - (convert == EINA_VALUE_TYPE_STRINGSHARE)) - { - Eina_Strbuf *str = eina_strbuf_new(); - const char *s; - if (!tmem->hash) eina_strbuf_append(str, "{}"); - else - { - struct _eina_value_type_hash_convert_to_string_each_ctx ctx; - - ctx.subtype = tmem->subtype; - ctx.str = str; - ctx.first = EINA_TRUE; - eina_value_setup(&ctx.tmp, EINA_VALUE_TYPE_STRING); - - eina_strbuf_append_char(str, '{'); - - eina_hash_foreach(tmem->hash, - _eina_value_type_hash_convert_to_string_each, - &ctx); - - eina_strbuf_append_char(str, '}'); - } - s = eina_strbuf_string_get(str); - ret = eina_value_type_pset(convert, convert_mem, &s); - eina_strbuf_free(str); - } - else if ((tmem->hash) && (eina_hash_population(tmem->hash) == 1)) - { - const Eina_Value_Type *subtype = tmem->subtype; - void *imem = NULL; - - eina_hash_foreach(tmem->hash, _eina_value_type_hash_find_first, &imem); - if (!imem) /* shouldn't happen... */ - ret = EINA_FALSE; - else - { - if (subtype->convert_to) - ret = subtype->convert_to(subtype, convert, imem, convert_mem); - if ((!ret) && (convert->convert_from)) - ret = convert->convert_from(convert, subtype, convert_mem, imem); - } - } - - if (!ret) - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_hash_pset(const Eina_Value_Type *type, void *mem, const void *ptr) -{ - Eina_Value_Hash *tmem = mem; - const Eina_Value_Hash *desc = ptr; - - eina_error_set(0); - if ((!tmem->subtype) && (!desc->subtype)) - return EINA_TRUE; - - if ((tmem->hash) && (tmem->hash == desc->hash)) - { - tmem->subtype = desc->subtype; - return EINA_TRUE; - } - - if (desc->hash) - { - Eina_Value_Hash tmp; - - if (!_eina_value_type_hash_copy(type, desc, &tmp)) - return EINA_FALSE; - - _eina_value_type_hash_flush(type, tmem); - memcpy(tmem, &tmp, sizeof(tmp)); - return EINA_TRUE; - } - - if (tmem->hash) _eina_value_type_hash_flush_elements(tmem); - - tmem->subtype = desc->subtype; - if (!_eina_value_type_hash_create(tmem)) - return EINA_FALSE; - - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_hash_vset(const Eina_Value_Type *type, void *mem, va_list args) -{ - const Eina_Value_Hash desc = va_arg(args, Eina_Value_Hash); - _eina_value_type_hash_pset(type, mem, &desc); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_hash_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - memcpy(ptr, mem, sizeof(Eina_Value_Hash)); - return EINA_TRUE; -} - -static const Eina_Value_Type _EINA_VALUE_TYPE_HASH = { - EINA_VALUE_TYPE_VERSION, - sizeof(Eina_Value_Hash), - "Eina_Value_Hash", - _eina_value_type_hash_setup, - _eina_value_type_hash_flush, - _eina_value_type_hash_copy, - _eina_value_type_hash_compare, - _eina_value_type_hash_convert_to, - NULL, /* no convert from */ - _eina_value_type_hash_vset, - _eina_value_type_hash_pset, - _eina_value_type_hash_pget -}; - -static Eina_Bool -_eina_value_type_timeval_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - memset(mem, 0, sizeof(struct timeval)); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_timeval_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) -{ - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_timeval_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const struct timeval *s = src; - struct timeval *d = dst; - *d = *s; - return EINA_TRUE; -} - -static inline struct timeval _eina_value_type_timeval_fix(const struct timeval *input) -{ - struct timeval ret = *input; - if (EINA_UNLIKELY(ret.tv_usec < 0)) - { - ret.tv_sec -= 1; - ret.tv_usec += 1e6; - } - return ret; -} - -static int -_eina_value_type_timeval_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - struct timeval va = _eina_value_type_timeval_fix(a); - struct timeval vb = _eina_value_type_timeval_fix(b); - - if (va.tv_sec < vb.tv_sec) - return -1; - else if (va.tv_sec > vb.tv_sec) - return 1; - - if (va.tv_usec < vb.tv_usec) - return -1; - else if (va.tv_usec > vb.tv_usec) - return 1; - - return 0; -} - -static Eina_Bool -_eina_value_type_timeval_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - struct timeval v = _eina_value_type_timeval_fix(type_mem); - - eina_error_set(0); - - if (convert == EINA_VALUE_TYPE_UCHAR) - { - unsigned char other_mem = v.tv_sec; - if (EINA_UNLIKELY(v.tv_sec < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY(v.tv_sec > eina_value_uchar_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_USHORT) - { - unsigned short other_mem = v.tv_sec; - if (EINA_UNLIKELY(v.tv_sec < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY(v.tv_sec > eina_value_ushort_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT) - { - unsigned int other_mem = v.tv_sec; - if (EINA_UNLIKELY(v.tv_sec < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY((unsigned long) v.tv_sec > eina_value_uint_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP)) - { - unsigned long other_mem = v.tv_sec; - if (EINA_UNLIKELY(v.tv_sec < 0)) - return EINA_FALSE; - if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) && - ((unsigned long)v.tv_sec > eina_value_ulong_max))) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_UINT64) - { - uint64_t other_mem = v.tv_sec; - if (EINA_UNLIKELY(v.tv_sec < 0)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_CHAR) - { - signed char other_mem = v.tv_sec; - if (EINA_UNLIKELY(v.tv_sec < eina_value_char_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v.tv_sec > eina_value_char_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_SHORT) - { - short other_mem = v.tv_sec; - if (EINA_UNLIKELY(v.tv_sec < eina_value_short_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v.tv_sec > eina_value_short_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT) - { - int other_mem = v.tv_sec; - if (EINA_UNLIKELY(v.tv_sec < eina_value_int_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v.tv_sec > eina_value_int_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_LONG) - { - long other_mem = v.tv_sec; - if (EINA_UNLIKELY(v.tv_sec < eina_value_long_min)) - return EINA_FALSE; - if (EINA_UNLIKELY(v.tv_sec > eina_value_long_max)) - return EINA_FALSE; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_INT64) - { - int64_t other_mem = v.tv_sec; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_FLOAT) - { - float other_mem = (float)v.tv_sec + (float)v.tv_usec / 1.0e6; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_DOUBLE) - { - double other_mem = (double)v.tv_sec + (double)v.tv_usec / 1.0e6; - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else if (convert == EINA_VALUE_TYPE_STRINGSHARE || - convert == EINA_VALUE_TYPE_STRING) - { - const char *other_mem; - char buf[64]; - strftime(buf, sizeof buf, "%Y-%m-%d %H:%M:%S", localtime(&(v.tv_sec))); - - other_mem = buf; /* required due &buf == buf */ - return eina_value_type_pset(convert, convert_mem, &other_mem); - } - else - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } -} - -static Eina_Bool -_eina_value_type_timeval_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) -{ - struct timeval *tmem = mem; - *tmem = _eina_value_type_timeval_fix(ptr); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_timeval_vset(const Eina_Value_Type *type, void *mem, va_list args) -{ - const struct timeval desc = va_arg(args, struct timeval); - _eina_value_type_timeval_pset(type, mem, &desc); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_timeval_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - memcpy(ptr, mem, sizeof(struct timeval)); - return EINA_TRUE; -} - -static const Eina_Value_Type _EINA_VALUE_TYPE_TIMEVAL = { - EINA_VALUE_TYPE_VERSION, - sizeof(struct timeval), - "struct timeval", - _eina_value_type_timeval_setup, - _eina_value_type_timeval_flush, - _eina_value_type_timeval_copy, - _eina_value_type_timeval_compare, - _eina_value_type_timeval_convert_to, - NULL, /* no convert from */ - _eina_value_type_timeval_vset, - _eina_value_type_timeval_pset, - _eina_value_type_timeval_pget -}; - -static Eina_Bool -_eina_value_type_blob_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - memset(mem, 0, sizeof(Eina_Value_Blob)); - return EINA_TRUE; -} - -static inline const Eina_Value_Blob_Operations * -_eina_value_type_blob_ops_get(const Eina_Value_Blob *blob) -{ - if (!blob) return NULL; - if (!blob->ops) return NULL; - EINA_SAFETY_ON_FALSE_RETURN_VAL - (blob->ops->version == EINA_VALUE_BLOB_OPERATIONS_VERSION, NULL); - return blob->ops; -} - -static Eina_Bool -_eina_value_type_blob_flush(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - const Eina_Value_Blob_Operations *ops = _eina_value_type_blob_ops_get(mem); - Eina_Value_Blob *tmem = mem; - if ((ops) && (ops->free)) - ops->free(ops, (void *)tmem->memory, tmem->size); - tmem->memory = NULL; - tmem->size = 0; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_blob_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const Eina_Value_Blob_Operations *ops = _eina_value_type_blob_ops_get(src); - const Eina_Value_Blob *s = src; - Eina_Value_Blob *d = dst; - - *d = *s; - - if ((ops) && (ops->copy)) - { - d->memory = ops->copy(ops, s->memory, s->size); - if ((d->memory == NULL) && (s->size > 0)) - return EINA_FALSE; - } - - return EINA_TRUE; -} - -static int -_eina_value_type_blob_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const Eina_Value_Blob_Operations *ops = _eina_value_type_blob_ops_get(a); - const Eina_Value_Blob *ta = a, *tb = b; - size_t minsize; - if (ta->ops != tb->ops) - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return -1; - } - if ((ops) && (ops->compare)) - return ops->compare(ops, ta->memory, ta->size, tb->memory, tb->size); - - if (ta->size < tb->size) - minsize = ta->size; - else - minsize = tb->size; - - return memcmp(ta->memory, tb->memory, minsize); -} - -static Eina_Bool -_eina_value_type_blob_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const Eina_Value_Blob *tmem = type_mem; - - eina_error_set(0); - if (convert == EINA_VALUE_TYPE_STRINGSHARE || - convert == EINA_VALUE_TYPE_STRING) - { - const Eina_Value_Blob_Operations *ops; - Eina_Strbuf *str; - const char *other_mem; - Eina_Bool ret = EINA_FALSE, first = EINA_TRUE; - const unsigned char *ptr, *ptr_end; - - ops = _eina_value_type_blob_ops_get(tmem); - if ((ops) && (ops->to_string)) - { - char *x = ops->to_string(ops, tmem->memory, tmem->size); - if (x) - { - ret = eina_value_type_pset(convert, convert_mem, &x); - free(x); - } - return ret; - } - - str = eina_strbuf_new(); - if (!str) - return EINA_FALSE; - - if (!eina_strbuf_append_printf(str, "BLOB(%u, [", tmem->size)) - goto error; - - ptr = tmem->memory; - ptr_end = ptr + tmem->size; - for (; ptr < ptr_end; ptr++) - { - if (first) - { - first = EINA_FALSE; - if (!eina_strbuf_append_printf(str, "%02hhx", *ptr)) - goto error; - } - else - { - if (!eina_strbuf_append_printf(str, " %02hhx", *ptr)) - goto error; - } - } - - if (!eina_strbuf_append(str, "])")) - goto error; - - other_mem = eina_strbuf_string_get(str); - ret = eina_value_type_pset(convert, convert_mem, &other_mem); - - error: - eina_strbuf_free(str); - return ret; - } - else - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } -} - -static Eina_Bool -_eina_value_type_blob_convert_from(const Eina_Value_Type *type, const Eina_Value_Type *convert, void *type_mem, const void *convert_mem) -{ - Eina_Value_Blob desc; - char *buf; - - desc.ops = EINA_VALUE_BLOB_OPERATIONS_MALLOC; - - if ((convert == EINA_VALUE_TYPE_STRING) || - (convert == EINA_VALUE_TYPE_STRINGSHARE)) - { - const char *str = *(const char **)convert_mem; - if (!str) - { - desc.size = 0; - desc.memory = NULL; - } - else - { - desc.size = strlen(str) + 1; - desc.memory = buf = malloc(desc.size); - if (!desc.memory) - { - eina_error_set(EINA_ERROR_OUT_OF_MEMORY); - return EINA_FALSE; - } - memcpy(buf, str, desc.size); - } - } - else if (convert == EINA_VALUE_TYPE_ARRAY) - { - const Eina_Value_Array *a = convert_mem; - if ((!a->array) || (a->array->len == 0)) - { - desc.size = 0; - desc.memory = NULL; - } - else - { - desc.size = a->array->len * a->array->member_size; - desc.memory = buf = malloc(desc.size); - if (!desc.memory) - { - eina_error_set(EINA_ERROR_OUT_OF_MEMORY); - return EINA_FALSE; - } - memcpy(buf, a->array->members, desc.size); - } - } - else if (convert == EINA_VALUE_TYPE_BLOB) - { - const Eina_Value_Blob *b = convert_mem; - if (b->size == 0) - { - desc.size = 0; - desc.memory = NULL; - } - else - { - desc.size = b->size; - desc.memory = buf = malloc(desc.size); - if (!desc.memory) - { - eina_error_set(EINA_ERROR_OUT_OF_MEMORY); - return EINA_FALSE; - } - memcpy(buf, b->memory, desc.size); - } - } - else - { - desc.size = convert->value_size; - desc.memory = buf = malloc(convert->value_size); - if (!desc.memory) - { - eina_error_set(EINA_ERROR_OUT_OF_MEMORY); - return EINA_FALSE; - } - if (!eina_value_type_pget(convert, convert_mem, buf)) - { - free(buf); - return EINA_FALSE; - } - } - return eina_value_type_pset(type, type_mem, &desc); -} - -static Eina_Bool -_eina_value_type_blob_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) -{ - const Eina_Value_Blob_Operations *ops = _eina_value_type_blob_ops_get(mem); - Eina_Value_Blob *tmem = mem; - const Eina_Value_Blob *desc = ptr; - - eina_error_set(0); - if ((tmem->memory) && (tmem->memory == desc->memory)) - { - tmem->ops = desc->ops; - tmem->size = desc->size; - return EINA_TRUE; - } - - if ((ops) && (ops->free)) - ops->free(ops, (void *)tmem->memory, tmem->size); - - *tmem = *desc; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_blob_vset(const Eina_Value_Type *type, void *mem, va_list args) -{ - const Eina_Value_Blob desc = va_arg(args, Eina_Value_Blob); - _eina_value_type_blob_pset(type, mem, &desc); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_blob_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - memcpy(ptr, mem, sizeof(Eina_Value_Blob)); - return EINA_TRUE; -} - -static const Eina_Value_Type _EINA_VALUE_TYPE_BLOB = { - EINA_VALUE_TYPE_VERSION, - sizeof(Eina_Value_Blob), - "Eina_Value_Blob", - _eina_value_type_blob_setup, - _eina_value_type_blob_flush, - _eina_value_type_blob_copy, - _eina_value_type_blob_compare, - _eina_value_type_blob_convert_to, - _eina_value_type_blob_convert_from, - _eina_value_type_blob_vset, - _eina_value_type_blob_pset, - _eina_value_type_blob_pget -}; - -static int -_eina_value_struct_operations_binsearch_cmp(const void *pa, const void *pb) -{ - const Eina_Value_Struct_Member *a = pa, *b = pb; - return strcmp(a->name, b->name); -} - -static const Eina_Value_Struct_Member * -_eina_value_struct_operations_binsearch_find_member(const Eina_Value_Struct_Operations *ops __UNUSED__, const Eina_Value_Struct_Desc *desc, const char *name) -{ - unsigned int count = desc->member_count; - Eina_Value_Struct_Member search; - if (count == 0) - { - const Eina_Value_Struct_Member *itr = desc->members; - for (; itr->name != NULL; itr++) - count++; - } - - search.name = name; - return bsearch(&search, desc->members, count, - sizeof(Eina_Value_Struct_Member), - _eina_value_struct_operations_binsearch_cmp); -} - -static Eina_Value_Struct_Operations _EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH = { - EINA_VALUE_STRUCT_OPERATIONS_VERSION, - NULL, /* default alloc */ - NULL, /* default free */ - NULL, /* default copy */ - NULL, /* default compare */ - _eina_value_struct_operations_binsearch_find_member -}; - -static const Eina_Value_Struct_Member * -_eina_value_struct_operations_stringshare_find_member(const Eina_Value_Struct_Operations *ops __UNUSED__, const Eina_Value_Struct_Desc *desc, const char *name) -{ - const Eina_Value_Struct_Member *itr = desc->members; - - /* assumes name is stringshared. - * - * we do this because it's the recommended usage pattern, moreover - * we expect to find the member, as users shouldn't look for - * non-existent members! - */ - if (desc->member_count > 0) - { - const Eina_Value_Struct_Member *itr_end = itr + desc->member_count; - for (; itr < itr_end; itr++) - if (itr->name == name) - return itr; - } - else - { - for (; itr->name != NULL; itr++) - if (itr->name == name) - return itr; - } - - itr = desc->members; - name = eina_stringshare_add(name); - eina_stringshare_del(name); /* we'll not use the contents, this is fine */ - /* stringshare and look again */ - if (desc->member_count > 0) - { - const Eina_Value_Struct_Member *itr_end = itr + desc->member_count; - for (; itr < itr_end; itr++) - if (itr->name == name) - return itr; - } - else - { - for (; itr->name != NULL; itr++) - if (itr->name == name) - return itr; - } - - return NULL; -} - -static Eina_Value_Struct_Operations _EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE = { - EINA_VALUE_STRUCT_OPERATIONS_VERSION, - NULL, /* default alloc */ - NULL, /* default free */ - NULL, /* default copy */ - NULL, /* default compare */ - _eina_value_struct_operations_stringshare_find_member -}; - -static inline const Eina_Value_Struct_Operations * -_eina_value_type_struct_ops_get(const Eina_Value_Struct *st) -{ - if (!st) return NULL; - if (!st->desc) return NULL; - if (!st->desc->ops) return NULL; - EINA_SAFETY_ON_FALSE_RETURN_VAL - (st->desc->ops->version == EINA_VALUE_STRUCT_OPERATIONS_VERSION, NULL); - return st->desc->ops; -} - -EAPI const Eina_Value_Struct_Member * -eina_value_struct_member_find(const Eina_Value_Struct *st, const char *name) -{ - const Eina_Value_Struct_Operations *ops; - const Eina_Value_Struct_Member *itr; - - EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(st->desc, NULL); - - ops = _eina_value_type_struct_ops_get(st); - if ((ops) && (ops->find_member)) - return ops->find_member(ops, st->desc, name); - - itr = st->desc->members; - if (st->desc->member_count) - { - const Eina_Value_Struct_Member *itr_end = itr + st->desc->member_count; - for (; itr < itr_end; itr++) - { - if (strcmp(name, itr->name) == 0) - return itr; - } - return NULL; - } - else - { - for (; itr->name != NULL; itr++) - { - if (strcmp(name, itr->name) == 0) - return itr; - } - return NULL; - } -} - -static Eina_Bool -_eina_value_type_struct_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - memset(mem, 0, sizeof(Eina_Value_Struct)); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_struct_setup_member(const Eina_Value_Struct_Member *member, Eina_Value_Struct *st) -{ - unsigned char *base = st->memory; - return eina_value_type_setup(member->type, base + member->offset); -} - -static Eina_Bool -_eina_value_type_struct_flush_member(const Eina_Value_Struct_Member *member, Eina_Value_Struct *st) -{ - unsigned char *base = st->memory; - return eina_value_type_flush(member->type, base + member->offset); -} - -static Eina_Bool -_eina_value_type_struct_flush(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - const Eina_Value_Struct_Operations *ops; - const Eina_Value_Struct_Member *itr; - Eina_Value_Struct *tmem = mem; - Eina_Bool ret = EINA_TRUE; - - if ((!tmem->desc) || (!tmem->memory)) - return EINA_TRUE; - - itr = tmem->desc->members; - if (tmem->desc->member_count > 0) - { - const Eina_Value_Struct_Member *itr_end; - itr_end = itr + tmem->desc->member_count; - for (; itr < itr_end; itr++) - ret &= _eina_value_type_struct_flush_member(itr, tmem); - } - else - { - for (; itr->name != NULL; itr++) - ret &= _eina_value_type_struct_flush_member(itr, tmem); - } - - ops = _eina_value_type_struct_ops_get(mem); - if ((ops) && (ops->free)) - ops->free(ops, tmem->desc, tmem->memory); - else - free(tmem->memory); - - tmem->memory = NULL; - tmem->desc = NULL; - - return ret; -} - -static Eina_Bool -_eina_value_type_struct_copy_member(const Eina_Value_Struct_Member *member, const Eina_Value_Struct *s, Eina_Value_Struct *d) -{ - const unsigned char *base_s = s->memory; - unsigned char *base_d = d->memory; - return eina_value_type_copy(member->type, - base_s + member->offset, - base_d + member->offset); -} - -static Eina_Bool -_eina_value_type_struct_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const Eina_Value_Struct_Operations *ops; - const Eina_Value_Struct_Member *itr; - const Eina_Value_Struct *s = src; - Eina_Value_Struct *d = dst; - - *d = *s; - - if ((!s->desc) || (!s->memory)) - return EINA_TRUE; - - ops = _eina_value_type_struct_ops_get(src); - if ((ops) && (ops->copy)) - { - d->memory = ops->copy(ops, s->desc, s->memory); - if (d->memory == NULL) - return EINA_FALSE; - return EINA_TRUE; - } - - if ((ops) && (ops->alloc)) - d->memory = ops->alloc(ops, s->desc); - else - d->memory = malloc(s->desc->size); - if (!d->memory) - { - eina_error_set(EINA_ERROR_OUT_OF_MEMORY); - return EINA_FALSE; - } - - itr = s->desc->members; - if (s->desc->member_count > 0) - { - const Eina_Value_Struct_Member *itr_end = itr + s->desc->member_count; - for (; itr < itr_end; itr++) - if (!_eina_value_type_struct_copy_member(itr, s, d)) - goto error; - } - else - { - for (; itr->name != NULL; itr++) - if (!_eina_value_type_struct_copy_member(itr, s, d)) - goto error; - } - - return EINA_TRUE; - - error: - itr--; - for (; itr >= s->desc->members; itr--) - _eina_value_type_struct_flush_member(itr, d); - - if ((ops) && (ops->free)) - ops->free(ops, s->desc, d->memory); - else - free(d->memory); - return EINA_FALSE; -} - -static inline int -_eina_value_type_struct_compare_member(const Eina_Value_Struct_Member *member, const Eina_Value_Struct *ta, const Eina_Value_Struct *tb) -{ - const unsigned char *base_a = ta->memory; - const unsigned char *base_b = tb->memory; - return eina_value_type_compare(member->type, - base_a + member->offset, - base_b + member->offset); -} - -static int -_eina_value_type_struct_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const Eina_Value_Struct_Operations *ops = _eina_value_type_struct_ops_get(a); - const Eina_Value_Struct *ta = a, *tb = b; - const Eina_Value_Struct_Member *itr; - int cmp = 0; - - if ((!ta->desc) && (!tb->desc)) - return 0; - else if (ta->desc != tb->desc) - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return -1; - } - if (ta->desc->ops != tb->desc->ops) - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return -1; - } - if ((!ta->memory) && (!tb->memory)) - return 0; - else if (!ta->memory) - return -1; - else if (!tb->memory) - return 1; - - if ((ops) && (ops->compare)) - return ops->compare(ops, ta->desc, ta->memory, tb->memory); - - itr = ta->desc->members; - if (ta->desc->member_count > 0) - { - const Eina_Value_Struct_Member *itr_end = itr + ta->desc->member_count; - for (; (cmp == 0) && (itr < itr_end); itr++) - cmp = _eina_value_type_struct_compare_member(itr, ta, tb); - } - else - { - for (; (cmp == 0) && (itr->name != NULL); itr++) - cmp = _eina_value_type_struct_compare_member(itr, ta, tb); - } - return cmp; -} - -static void -_eina_value_type_struct_convert_to_string_member(const Eina_Value_Struct *st, const Eina_Value_Struct_Member *member, Eina_Strbuf *str) -{ - const unsigned char *p = st->memory; - Eina_Bool first = st->desc->members == member; - Eina_Bool r = EINA_FALSE; - - if (first) eina_strbuf_append_printf(str, "%s: ", member->name); - else eina_strbuf_append_printf(str, ", %s: ", member->name); - - if ((member->type) && (member->type->convert_to)) - { - const Eina_Value_Type *type = member->type; - char *conv = NULL; - - r = eina_value_type_convert_to(type, EINA_VALUE_TYPE_STRING, - p + member->offset, &conv); - if (r) - { - eina_strbuf_append(str, conv); - free(conv); - } - } - - if (!r) - eina_strbuf_append_char(str, '?'); -} - -static Eina_Bool -_eina_value_type_struct_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const Eina_Value_Struct *tmem = type_mem; - - eina_error_set(0); - if (convert == EINA_VALUE_TYPE_STRINGSHARE || - convert == EINA_VALUE_TYPE_STRING) - { - Eina_Strbuf *str = eina_strbuf_new(); - const char *s; - Eina_Bool ret; - - if (!tmem->memory) eina_strbuf_append(str, "{}"); - else - { - const Eina_Value_Struct_Member *itr = tmem->desc->members; - - eina_strbuf_append_char(str, '{'); - - if (tmem->desc->member_count > 0) - { - const Eina_Value_Struct_Member *itr_end; - - itr_end = itr + tmem->desc->member_count; - for (; itr < itr_end; itr++) - _eina_value_type_struct_convert_to_string_member - (tmem, itr, str); - } - else - { - for (; itr->name != NULL; itr++) - _eina_value_type_struct_convert_to_string_member - (tmem, itr, str); - } - - eina_strbuf_append_char(str, '}'); - } - s = eina_strbuf_string_get(str); - ret = eina_value_type_pset(convert, convert_mem, &s); - eina_strbuf_free(str); - return ret; - } - else - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } -} - -static Eina_Bool -_eina_value_type_struct_desc_check(const Eina_Value_Struct_Desc *desc) -{ - unsigned int minsize = 0; - const Eina_Value_Struct_Member *itr; - - EINA_SAFETY_ON_NULL_RETURN_VAL(desc, EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL - (desc->version == EINA_VALUE_STRUCT_DESC_VERSION, EINA_FALSE); - - itr = desc->members; - if (desc->member_count > 0) - { - const Eina_Value_Struct_Member *itr_end = itr + desc->member_count; - for (; itr < itr_end; itr++) - { - unsigned int member_end; - - EINA_SAFETY_ON_FALSE_RETURN_VAL - (eina_value_type_check(itr->type), EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL - (itr->type->value_size > 0, EINA_FALSE); - - member_end = itr->offset + itr->type->value_size; - if (minsize < member_end) - minsize = member_end; - } - } - else - { - for (; itr->name != NULL; itr++) - { - unsigned int member_end; - - EINA_SAFETY_ON_FALSE_RETURN_VAL - (eina_value_type_check(itr->type), EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL - (itr->type->value_size > 0, EINA_FALSE); - - member_end = itr->offset + itr->type->value_size; - if (minsize < member_end) - minsize = member_end; - } - } - - EINA_SAFETY_ON_FALSE_RETURN_VAL(minsize > 0, EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL(desc->size >= minsize, EINA_FALSE); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_struct_pset(const Eina_Value_Type *type, void *mem, const void *ptr) -{ - const Eina_Value_Struct_Operations *ops; - Eina_Value_Struct *tmem = mem; - const Eina_Value_Struct *desc = ptr; - const Eina_Value_Struct_Member *itr; - - if (!_eina_value_type_struct_desc_check(desc->desc)) - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - - eina_error_set(0); - if ((tmem->memory) && (tmem->memory == desc->memory)) - { - tmem->desc = desc->desc; - return EINA_TRUE; - } - - if (desc->memory) - { - Eina_Value_Struct tmp; - - if (!_eina_value_type_struct_copy(type, desc, &tmp)) - return EINA_FALSE; - - _eina_value_type_struct_flush(type, tmem); - memcpy(tmem, &tmp, sizeof(tmp)); - return EINA_TRUE; - } - - if (tmem->memory) _eina_value_type_struct_flush(type, mem); - - tmem->desc = desc->desc; - - ops = _eina_value_type_struct_ops_get(desc); - if ((ops) && (ops->alloc)) - tmem->memory = ops->alloc(ops, tmem->desc); - else - tmem->memory = malloc(tmem->desc->size); - - if (!tmem->memory) - { - eina_error_set(EINA_ERROR_OUT_OF_MEMORY); - return EINA_FALSE; - } - - itr = tmem->desc->members; - if (tmem->desc->member_count > 0) - { - const Eina_Value_Struct_Member *itr_end; - itr_end = itr + tmem->desc->member_count; - for (; itr < itr_end; itr++) - if (!_eina_value_type_struct_setup_member(itr, tmem)) - goto error; - } - else - { - for (; itr->name != NULL; itr++) - if (!_eina_value_type_struct_setup_member(itr, tmem)) - goto error; - } - - return EINA_TRUE; - - error: - itr--; - for (; itr >= tmem->desc->members; itr--) - _eina_value_type_struct_flush_member(itr, tmem); - - if ((ops) && (ops->free)) - ops->free(ops, tmem->desc, tmem->memory); - else - free(tmem->memory); - tmem->memory = NULL; - tmem->desc = NULL; - return EINA_FALSE; -} - -static Eina_Bool -_eina_value_type_struct_vset(const Eina_Value_Type *type, void *mem, va_list args) -{ - const Eina_Value_Struct desc = va_arg(args, Eina_Value_Struct); - _eina_value_type_struct_pset(type, mem, &desc); - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_struct_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - memcpy(ptr, mem, sizeof(Eina_Value_Struct)); - return EINA_TRUE; -} - -static const Eina_Value_Type _EINA_VALUE_TYPE_STRUCT = { - EINA_VALUE_TYPE_VERSION, - sizeof(Eina_Value_Struct), - "Eina_Value_Struct", - _eina_value_type_struct_setup, - _eina_value_type_struct_flush, - _eina_value_type_struct_copy, - _eina_value_type_struct_compare, - _eina_value_type_struct_convert_to, - NULL, /* no convert from */ - _eina_value_type_struct_vset, - _eina_value_type_struct_pset, - _eina_value_type_struct_pget -}; - -/* no model for now -static Eina_Bool -_eina_value_type_model_setup(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - Eina_Model **tmem = mem; - *tmem = NULL; - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_model_flush(const Eina_Value_Type *type __UNUSED__, void *mem) -{ - Eina_Model **tmem = mem; - if (*tmem) - { - eina_model_unref(*tmem); - *tmem = NULL; - } - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_model_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) -{ - const Eina_Model * const *s = src; - Eina_Model **d = dst; - if (*s) - *d = eina_model_copy(*s); // is it better to deep-copy? - else - *d = NULL; - return EINA_TRUE; -} - -static int -_eina_value_type_model_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) -{ - const Eina_Model * const *ta = a; - const Eina_Model * const *tb = b; - - if ((!*ta) && (!*tb)) return 0; - else if (!*ta) return 1; - else if (!*tb) return -1; - else return eina_model_compare(*ta, *tb); -} - -static Eina_Bool -_eina_value_type_model_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) -{ - const Eina_Model *v = *(const Eina_Model **)type_mem; - - eina_error_set(0); - - if (convert == EINA_VALUE_TYPE_STRINGSHARE || - convert == EINA_VALUE_TYPE_STRING) - { - char *other_mem = v ? eina_model_to_string(v) : NULL; - Eina_Bool ret = eina_value_type_pset(convert, convert_mem, &other_mem); - free(other_mem); - return ret; - } - else - { - eina_error_set(EINA_ERROR_VALUE_FAILED); - return EINA_FALSE; - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_model_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) -{ - Eina_Model **tmem = mem, *tmp; - - tmp = va_arg(args, Eina_Model *); - - if (tmp) eina_model_ref(tmp); - if (*tmem) eina_model_unref(*tmem); - - *tmem = tmp; - - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_model_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) -{ - Eina_Model **tmem = mem; - Eina_Model **p = (Eina_Model **)ptr; - - eina_error_set(0); - if (*tmem == *p) return EINA_TRUE; - - if (*p) eina_model_ref(*p); - if (*tmem) eina_model_unref(*tmem); - - *tmem = *p; - - return EINA_TRUE; -} - -static Eina_Bool -_eina_value_type_model_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) -{ - Eina_Model **tmem = (Eina_Model **)mem; - Eina_Model **p = ptr; - *p = *tmem; - return EINA_TRUE; -} - -static const Eina_Value_Type _EINA_VALUE_TYPE_MODEL = { - EINA_VALUE_TYPE_VERSION, - sizeof(Eina_Model *), - "Eina_Model", - _eina_value_type_model_setup, - _eina_value_type_model_flush, - _eina_value_type_model_copy, - _eina_value_type_model_compare, - _eina_value_type_model_convert_to, - NULL, // no convert from - _eina_value_type_model_vset, - _eina_value_type_model_pset, - _eina_value_type_model_pget -}; -*/ - -/* keep all basic types inlined in an array so we can compare if it's - * a basic type using pointer arithmetic. - * - * NOTE-1: JUST BASIC TYPES, DO NOT ADD MORE TYPES HERE!!! - * NOTE-2: KEEP ORDER, see eina_value_init() - */ -static const Eina_Value_Type _EINA_VALUE_TYPE_BASICS[] = { - { - EINA_VALUE_TYPE_VERSION, - sizeof(unsigned char), - "unsigned char", - _eina_value_type_uchar_setup, - _eina_value_type_uchar_flush, - _eina_value_type_uchar_copy, - _eina_value_type_uchar_compare, - _eina_value_type_uchar_convert_to, - NULL, /* no convert from */ - _eina_value_type_uchar_vset, - _eina_value_type_uchar_pset, - _eina_value_type_uchar_pget - }, - { - EINA_VALUE_TYPE_VERSION, - sizeof(unsigned short), - "unsigned short", - _eina_value_type_ushort_setup, - _eina_value_type_ushort_flush, - _eina_value_type_ushort_copy, - _eina_value_type_ushort_compare, - _eina_value_type_ushort_convert_to, - NULL, /* no convert from */ - _eina_value_type_ushort_vset, - _eina_value_type_ushort_pset, - _eina_value_type_ushort_pget - }, - { - EINA_VALUE_TYPE_VERSION, - sizeof(unsigned int), - "unsigned int", - _eina_value_type_uint_setup, - _eina_value_type_uint_flush, - _eina_value_type_uint_copy, - _eina_value_type_uint_compare, - _eina_value_type_uint_convert_to, - NULL, /* no convert from */ - _eina_value_type_uint_vset, - _eina_value_type_uint_pset, - _eina_value_type_uint_pget - }, - { - EINA_VALUE_TYPE_VERSION, - sizeof(unsigned long), - "unsigned long", - _eina_value_type_ulong_setup, - _eina_value_type_ulong_flush, - _eina_value_type_ulong_copy, - _eina_value_type_ulong_compare, - _eina_value_type_ulong_convert_to, - NULL, /* no convert from */ - _eina_value_type_ulong_vset, - _eina_value_type_ulong_pset, - _eina_value_type_ulong_pget - }, - { - EINA_VALUE_TYPE_VERSION, - sizeof(uint64_t), - "uint64_t", - _eina_value_type_uint64_setup, - _eina_value_type_uint64_flush, - _eina_value_type_uint64_copy, - _eina_value_type_uint64_compare, - _eina_value_type_uint64_convert_to, - NULL, /* no convert from */ - _eina_value_type_uint64_vset, - _eina_value_type_uint64_pset, - _eina_value_type_uint64_pget - }, - { - EINA_VALUE_TYPE_VERSION, - sizeof(char), - "char", - _eina_value_type_char_setup, - _eina_value_type_char_flush, - _eina_value_type_char_copy, - _eina_value_type_char_compare, - _eina_value_type_char_convert_to, - NULL, /* no convert from */ - _eina_value_type_char_vset, - _eina_value_type_char_pset, - _eina_value_type_char_pget - }, - { - EINA_VALUE_TYPE_VERSION, - sizeof(short), - "short", - _eina_value_type_short_setup, - _eina_value_type_short_flush, - _eina_value_type_short_copy, - _eina_value_type_short_compare, - _eina_value_type_short_convert_to, - NULL, /* no convert from */ - _eina_value_type_short_vset, - _eina_value_type_short_pset, - _eina_value_type_short_pget - }, - { - EINA_VALUE_TYPE_VERSION, - sizeof(int), - "int", - _eina_value_type_int_setup, - _eina_value_type_int_flush, - _eina_value_type_int_copy, - _eina_value_type_int_compare, - _eina_value_type_int_convert_to, - NULL, /* no convert from */ - _eina_value_type_int_vset, - _eina_value_type_int_pset, - _eina_value_type_int_pget - }, - { - EINA_VALUE_TYPE_VERSION, - sizeof(long), - "long", - _eina_value_type_long_setup, - _eina_value_type_long_flush, - _eina_value_type_long_copy, - _eina_value_type_long_compare, - _eina_value_type_long_convert_to, - NULL, /* no convert from */ - _eina_value_type_long_vset, - _eina_value_type_long_pset, - _eina_value_type_long_pget - }, - { - EINA_VALUE_TYPE_VERSION, - sizeof(int64_t), - "int64_t", - _eina_value_type_int64_setup, - _eina_value_type_int64_flush, - _eina_value_type_int64_copy, - _eina_value_type_int64_compare, - _eina_value_type_int64_convert_to, - NULL, /* no convert from */ - _eina_value_type_int64_vset, - _eina_value_type_int64_pset, - _eina_value_type_int64_pget - }, - { - EINA_VALUE_TYPE_VERSION, - sizeof(float), - "float", - _eina_value_type_float_setup, - _eina_value_type_float_flush, - _eina_value_type_float_copy, - _eina_value_type_float_compare, - _eina_value_type_float_convert_to, - NULL, /* no convert from */ - _eina_value_type_float_vset, - _eina_value_type_float_pset, - _eina_value_type_float_pget - }, - { - EINA_VALUE_TYPE_VERSION, - sizeof(double), - "double", - _eina_value_type_double_setup, - _eina_value_type_double_flush, - _eina_value_type_double_copy, - _eina_value_type_double_compare, - _eina_value_type_double_convert_to, - NULL, /* no convert from */ - _eina_value_type_double_vset, - _eina_value_type_double_pset, - _eina_value_type_double_pget - }, - { - EINA_VALUE_TYPE_VERSION, - sizeof(const char *), - "stringshare", - _eina_value_type_string_common_setup, - _eina_value_type_stringshare_flush, - _eina_value_type_stringshare_copy, - _eina_value_type_string_common_compare, - _eina_value_type_string_common_convert_to, - NULL, /* no convert from */ - _eina_value_type_stringshare_vset, - _eina_value_type_stringshare_pset, - _eina_value_type_string_common_pget - }, - { - EINA_VALUE_TYPE_VERSION, - sizeof(char *), - "string", - _eina_value_type_string_common_setup, - _eina_value_type_string_flush, - _eina_value_type_string_copy, - _eina_value_type_string_common_compare, - _eina_value_type_string_common_convert_to, - NULL, /* no convert from */ - _eina_value_type_string_vset, - _eina_value_type_string_pset, - _eina_value_type_string_common_pget - }, - { - EINA_VALUE_TYPE_VERSION, - sizeof(unsigned long), - "timestamp", - _eina_value_type_ulong_setup, - _eina_value_type_ulong_flush, - _eina_value_type_ulong_copy, - _eina_value_type_ulong_compare, - _eina_value_type_ulong_convert_to, - NULL, /* no convert from */ - _eina_value_type_ulong_vset, - _eina_value_type_ulong_pset, - _eina_value_type_ulong_pget - } -}; - -static void -_eina_value_blob_operations_malloc_free(const Eina_Value_Blob_Operations *ops __UNUSED__, void *memory, size_t size __UNUSED__) -{ - free(memory); -} - -static void * -_eina_value_blob_operations_malloc_copy(const Eina_Value_Blob_Operations *ops __UNUSED__, const void *memory, size_t size) -{ - void *ret = malloc(size); - if (!ret) - { - eina_error_set(EINA_ERROR_OUT_OF_MEMORY); - return NULL; - } - memcpy(ret, memory, size); - return ret; -} - -static const Eina_Value_Blob_Operations _EINA_VALUE_BLOB_OPERATIONS_MALLOC = { - EINA_VALUE_BLOB_OPERATIONS_VERSION, - _eina_value_blob_operations_malloc_free, - _eina_value_blob_operations_malloc_copy, - NULL, - NULL -}; - -typedef struct _Eina_Value_Inner_Mp Eina_Value_Inner_Mp; -struct _Eina_Value_Inner_Mp -{ - Eina_Mempool *mempool; - int references; -}; - -/** - * @endcond - */ - -static const char EINA_ERROR_VALUE_FAILED_STR[] = "Value check failed."; - -/** - */ - -static inline void -_eina_value_inner_mp_dispose(int size, Eina_Value_Inner_Mp *imp) -{ - EINA_SAFETY_ON_FALSE_RETURN(imp->references == 0); - - eina_hash_del_by_key(_eina_value_inner_mps, &size); - eina_mempool_del(imp->mempool); - free(imp); -} - -static inline Eina_Value_Inner_Mp * -_eina_value_inner_mp_get(int size) -{ - Eina_Value_Inner_Mp *imp = eina_hash_find(_eina_value_inner_mps, &size); - if (imp) return imp; - - imp = malloc(sizeof(Eina_Value_Inner_Mp)); - if (!imp) - return NULL; - - imp->references = 0; - - imp->mempool = eina_mempool_add(_eina_value_mp_choice, - "Eina_Value_Inner_Mp", NULL, size, 16); - if (!imp->mempool) - { - free(imp); - return NULL; - } - - if (!eina_hash_add(_eina_value_inner_mps, &size, imp)) - { - eina_mempool_del(imp->mempool); - free(imp); - return NULL; - } - - return imp; -} - -static inline void * -_eina_value_inner_alloc_internal(int size) -{ - Eina_Value_Inner_Mp *imp; - void *mem; - - imp = _eina_value_inner_mp_get(size); - if (!imp) return NULL; - - mem = eina_mempool_malloc(imp->mempool, size); - if (mem) imp->references++; - else if (imp->references == 0) _eina_value_inner_mp_dispose(size, imp); - - return mem; -} - -static inline void -_eina_value_inner_free_internal(int size, void *mem) -{ - Eina_Value_Inner_Mp *imp = eina_hash_find(_eina_value_inner_mps, &size); - EINA_SAFETY_ON_NULL_RETURN(imp); - - eina_mempool_free(imp->mempool, mem); - - imp->references--; - if (imp->references > 0) return; - _eina_value_inner_mp_dispose(size, imp); -} - -EAPI void * -eina_value_inner_alloc(size_t size) -{ - void *mem; - - if (size > 256) return malloc(size); - - eina_lock_take(&_eina_value_inner_mps_lock); - mem = _eina_value_inner_alloc_internal(size); - eina_lock_release(&_eina_value_inner_mps_lock); - - return mem; -} - -EAPI void -eina_value_inner_free(size_t size, void *mem) -{ - if (size > 256) - { - free(mem); - return; - } - - eina_lock_take(&_eina_value_inner_mps_lock); - _eina_value_inner_free_internal(size, mem); - eina_lock_release(&_eina_value_inner_mps_lock); -} - -/** - * @internal - * @brief Initialize the value module. - * - * @return #EINA_TRUE on success, #EINA_FALSE on failure. - * - * This function sets up the value module of Eina. It is called - * by eina_init(). - * - * @see eina_init() - */ -Eina_Bool -eina_value_init(void) -{ - const char *choice, *tmp; - - _eina_value_log_dom = eina_log_domain_register("eina_value", - EINA_LOG_COLOR_DEFAULT); - if (_eina_value_log_dom < 0) - { - EINA_LOG_ERR("Could not register log domain: eina_value"); - return EINA_FALSE; - } - -#ifdef EINA_DEFAULT_MEMPOOL - choice = "pass_through"; -#else - choice = "chained_mempool"; -#endif - tmp = getenv("EINA_MEMPOOL"); - if (tmp && tmp[0]) - choice = tmp; - - _eina_value_mp_choice = strdup(choice); - - _eina_value_mp = eina_mempool_add - (_eina_value_mp_choice, "value", NULL, sizeof(Eina_Value), 32); - if (!_eina_value_mp) - { - ERR("Mempool for value cannot be allocated in value init."); - goto on_init_fail_mp; - } - - if (!eina_lock_new(&_eina_value_inner_mps_lock)) - { - ERR("Cannot create lock in value init."); - goto on_init_fail_lock; - } - _eina_value_inner_mps = eina_hash_int32_new(NULL); - if (!_eina_value_inner_mps) - { - ERR("Cannot create hash for inner mempools in value init."); - goto on_init_fail_hash; - } - - EINA_ERROR_VALUE_FAILED = eina_error_msg_static_register( - EINA_ERROR_VALUE_FAILED_STR); - - EINA_VALUE_TYPE_UCHAR = _EINA_VALUE_TYPE_BASICS + 0; - EINA_VALUE_TYPE_USHORT = _EINA_VALUE_TYPE_BASICS + 1; - EINA_VALUE_TYPE_UINT = _EINA_VALUE_TYPE_BASICS + 2; - EINA_VALUE_TYPE_ULONG = _EINA_VALUE_TYPE_BASICS + 3; - EINA_VALUE_TYPE_UINT64 = _EINA_VALUE_TYPE_BASICS + 4; - EINA_VALUE_TYPE_CHAR = _EINA_VALUE_TYPE_BASICS + 5; - EINA_VALUE_TYPE_SHORT = _EINA_VALUE_TYPE_BASICS + 6; - EINA_VALUE_TYPE_INT = _EINA_VALUE_TYPE_BASICS + 7; - EINA_VALUE_TYPE_LONG = _EINA_VALUE_TYPE_BASICS + 8; - EINA_VALUE_TYPE_INT64 = _EINA_VALUE_TYPE_BASICS + 9; - EINA_VALUE_TYPE_FLOAT = _EINA_VALUE_TYPE_BASICS + 10; - EINA_VALUE_TYPE_DOUBLE = _EINA_VALUE_TYPE_BASICS + 11; - EINA_VALUE_TYPE_STRINGSHARE = _EINA_VALUE_TYPE_BASICS + 12; - EINA_VALUE_TYPE_STRING = _EINA_VALUE_TYPE_BASICS + 13; - EINA_VALUE_TYPE_TIMESTAMP = _EINA_VALUE_TYPE_BASICS + 14; - - _EINA_VALUE_TYPE_BASICS_START = _EINA_VALUE_TYPE_BASICS + 0; - _EINA_VALUE_TYPE_BASICS_END = _EINA_VALUE_TYPE_BASICS + 14; - - EINA_SAFETY_ON_FALSE_RETURN_VAL((sizeof(_EINA_VALUE_TYPE_BASICS)/sizeof(_EINA_VALUE_TYPE_BASICS[0])) == 15, EINA_FALSE); - - - EINA_VALUE_TYPE_ARRAY = &_EINA_VALUE_TYPE_ARRAY; - EINA_VALUE_TYPE_LIST = &_EINA_VALUE_TYPE_LIST; - EINA_VALUE_TYPE_HASH = &_EINA_VALUE_TYPE_HASH; - EINA_VALUE_TYPE_TIMEVAL = &_EINA_VALUE_TYPE_TIMEVAL; - EINA_VALUE_TYPE_BLOB = &_EINA_VALUE_TYPE_BLOB; - EINA_VALUE_TYPE_STRUCT = &_EINA_VALUE_TYPE_STRUCT; -/* no model for now - EINA_VALUE_TYPE_MODEL = &_EINA_VALUE_TYPE_MODEL; - */ - - EINA_VALUE_BLOB_OPERATIONS_MALLOC = &_EINA_VALUE_BLOB_OPERATIONS_MALLOC; - - EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH = &_EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH; - EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE = &_EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE; - - return EINA_TRUE; - - on_init_fail_hash: - eina_lock_free(&_eina_value_inner_mps_lock); - on_init_fail_lock: - eina_mempool_del(_eina_value_mp); - on_init_fail_mp: - free(_eina_value_mp_choice); - _eina_value_mp_choice = NULL; - eina_log_domain_unregister(_eina_value_log_dom); - _eina_value_log_dom = -1; - return EINA_FALSE; -} - -/** - * @internal - * @brief Shut down the value module. - * - * @return #EINA_TRUE on success, #EINA_FALSE on failure. - * - * This function shuts down the value module set up by - * eina_value_init(). It is called by eina_shutdown(). - * - * @see eina_shutdown() - */ -Eina_Bool -eina_value_shutdown(void) -{ - eina_lock_take(&_eina_value_inner_mps_lock); - if (eina_hash_population(_eina_value_inner_mps) != 0) - ERR("Cannot free eina_value internal memory pools -- still in use!"); - else - eina_hash_free(_eina_value_inner_mps); - eina_lock_release(&_eina_value_inner_mps_lock); - eina_lock_free(&_eina_value_inner_mps_lock); - - free(_eina_value_mp_choice); - _eina_value_mp_choice = NULL; - eina_mempool_del(_eina_value_mp); - eina_log_domain_unregister(_eina_value_log_dom); - _eina_value_log_dom = -1; - return EINA_TRUE; -} - -/*============================================================================* -* Global * -*============================================================================*/ - -/*============================================================================* -* API * -*============================================================================*/ - -EAPI const Eina_Value_Type *_EINA_VALUE_TYPE_BASICS_START = NULL; -EAPI const Eina_Value_Type *_EINA_VALUE_TYPE_BASICS_END = NULL; - -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_UCHAR = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_USHORT = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_UINT = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_ULONG = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_TIMESTAMP = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_UINT64 = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_CHAR = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_SHORT = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_INT = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_LONG = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_INT64 = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_FLOAT = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_DOUBLE = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_STRINGSHARE = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_STRING = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_ARRAY = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_LIST = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_HASH = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_TIMEVAL = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_BLOB = NULL; -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_STRUCT = NULL; -/* no model for now -EAPI const Eina_Value_Type *EINA_VALUE_TYPE_MODEL = NULL; - */ - -EAPI const Eina_Value_Blob_Operations *EINA_VALUE_BLOB_OPERATIONS_MALLOC = NULL; - -EAPI const Eina_Value_Struct_Operations *EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH = NULL; -EAPI const Eina_Value_Struct_Operations *EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE = NULL; - -EAPI Eina_Error EINA_ERROR_VALUE_FAILED = 0; - -EAPI const unsigned int eina_prime_table[] = -{ - 17, 31, 61, 127, 257, 509, 1021, - 2053, 4093, 8191, 16381, 32771, 65537, 131071, 262147, 524287, 1048573, - 2097143, 4194301, 8388617, 16777213 -}; - -EAPI Eina_Value * -eina_value_new(const Eina_Value_Type *type) -{ - Eina_Value *value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));; - if (!value) - { - eina_error_set(EINA_ERROR_OUT_OF_MEMORY); - return NULL; - } - if (!eina_value_setup(value, type)) - { - free(value); - return NULL; - } - return value; -} - -EAPI void -eina_value_free(Eina_Value *value) -{ - EINA_SAFETY_ON_NULL_RETURN(value); - eina_value_flush(value); - eina_mempool_free(_eina_value_mp, value); -} - - -EAPI Eina_Bool -eina_value_copy(const Eina_Value *value, Eina_Value *copy) -{ - const Eina_Value_Type *type; - const void *src; - void *dst; - Eina_Bool ret; - - EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), - EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(copy, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(value->type->copy, EINA_FALSE); - - type = value->type; - if (!eina_value_setup(copy, type)) - return EINA_FALSE; - - src = eina_value_memory_get(value); - dst = eina_value_memory_get(copy); - ret = type->copy(type, src, dst); - if (!ret) - eina_value_flush(copy); - - return ret; -} - -EAPI Eina_Bool -eina_value_convert(const Eina_Value *value, Eina_Value *convert) -{ - Eina_Bool ret = EINA_FALSE; - const Eina_Value_Type *type, *convert_type; - const void *type_mem; - void *convert_mem; - - EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(convert, EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), - EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(convert->type), - EINA_FALSE); - - type = value->type; - convert_type = convert->type; - - type_mem = eina_value_memory_get(value); - convert_mem = eina_value_memory_get(convert); - - if (type->convert_to) - ret = type->convert_to(type, convert_type, type_mem, convert_mem); - - if ((!ret) && (convert_type->convert_from)) - ret = convert_type->convert_from(convert_type, type, convert_mem, - type_mem); - - return ret; -} - -EAPI char * -eina_value_to_string(const Eina_Value *value) -{ - Eina_Value tmp; - - EINA_SAFETY_ON_NULL_RETURN_VAL(value, NULL); - EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), NULL); - - if (!eina_value_setup(&tmp, EINA_VALUE_TYPE_STRING)) - return NULL; - if (!eina_value_convert(value, &tmp)) - return NULL; - - return tmp.value.ptr; /* steal value */ -} - -EAPI Eina_Value * -eina_value_array_new(const Eina_Value_Type *subtype, unsigned int step) -{ - Eina_Value *value; - - EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(subtype), EINA_FALSE); - - value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));; - if (!value) - return NULL; - - if (!eina_value_array_setup(value, subtype, step)) - { - eina_mempool_free(_eina_value_mp, value); - return NULL; - } - - return value; -} - -EAPI Eina_Value * -eina_value_list_new(const Eina_Value_Type *subtype) -{ - Eina_Value *value; - - EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(subtype), EINA_FALSE); - - value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));; - if (!value) - return NULL; - - if (!eina_value_list_setup(value, subtype)) - { - eina_mempool_free(_eina_value_mp, value); - return NULL; - } - - return value; -} - -EAPI Eina_Value * -eina_value_hash_new(const Eina_Value_Type *subtype, unsigned int buckets_power_size) -{ - Eina_Value *value; - - EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(subtype), EINA_FALSE); - - value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));; - if (!value) - return NULL; - - if (!eina_value_hash_setup(value, subtype, buckets_power_size)) - { - eina_mempool_free(_eina_value_mp, value); - return NULL; - } - - return value; -} - -EAPI Eina_Value * -eina_value_struct_new(const Eina_Value_Struct_Desc *desc) -{ - Eina_Value *value; - - value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));; - if (!value) - return NULL; - - if (!eina_value_struct_setup(value, desc)) - { - eina_mempool_free(_eina_value_mp, value); - return NULL; - } - - return value; -} - -EAPI Eina_Bool -eina_value_type_check(const Eina_Value_Type *type) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE); - return type->version == EINA_VALUE_TYPE_VERSION; -} - -EAPI const char * -eina_value_type_name_get(const Eina_Value_Type *type) -{ - EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(type), NULL); - return type->name; -} diff --git a/src/lib/eina_xattr.c b/src/lib/eina_xattr.c deleted file mode 100644 index d4ed139..0000000 --- a/src/lib/eina_xattr.c +++ /dev/null @@ -1,483 +0,0 @@ -/* 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> -#include <sys/types.h> -#include <string.h> -#include <math.h> - -#ifdef HAVE_XATTR -# include <sys/xattr.h> -#endif - -#include "eina_config.h" -#include "eina_private.h" - -#include "eina_safety_checks.h" -#include "eina_xattr.h" -#include "eina_convert.h" -#include "eina_stringshare.h" - -/*============================================================================* - * Local * - *============================================================================*/ - -/** - * @cond LOCAL - */ - -typedef struct _Eina_Xattr_Iterator Eina_Xattr_Iterator; - -struct _Eina_Xattr_Iterator -{ - Eina_Iterator iterator; - - const char *file; - Eina_Xattr *attr; - - ssize_t length; - ssize_t offset; - - int fd; - - char xattr[1]; -}; - -#ifdef HAVE_XATTR -static Eina_Bool -_eina_xattr_value_ls_fd_iterator_next(Eina_Xattr_Iterator *it, void **data) -{ - char *tmp; - - if (it->offset >= it->length) - return EINA_FALSE; - - *data = it->attr; - it->attr->name = it->xattr + it->offset; - - it->attr->length = fgetxattr(it->fd, it->attr->name, NULL, 0); - if (it->attr->length) - { - tmp = realloc((void*) it->attr->value, it->attr->length); - if (!tmp) - { - free((void*) it->attr->value); - it->attr->value = NULL; - it->attr->length = 0; - } - else - { - it->attr->length = fgetxattr(it->fd, it->attr->name, - (void *) it->attr->value, - it->attr->length); - } - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_xattr_value_ls_iterator_next(Eina_Xattr_Iterator *it, void **data) -{ - char *tmp; - - if (it->offset >= it->length) - return EINA_FALSE; - - *data = it->attr; - it->attr->name = it->xattr + it->offset; - - it->attr->length = getxattr(it->file, it->attr->name, NULL, 0); - if (it->attr->length) - { - tmp = realloc((void*) it->attr->value, it->attr->length); - if (!tmp) - { - free((void*) it->attr->value); - it->attr->value = NULL; - it->attr->length = 0; - } - else - { - it->attr->length = getxattr(it->file, it->attr->name, - (void*) it->attr->value, - it->attr->length); - } - } - - return EINA_TRUE; -} - -static Eina_Bool -_eina_xattr_ls_iterator_next(Eina_Xattr_Iterator *it, void **data) -{ - if (it->offset >= it->length) - 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); - if (it->attr) free((void *) it->attr->value); - eina_stringshare_del(it->file); - free(it->attr); - free(it); -} -#endif - -/** - * @endcond - */ - - -/*============================================================================* - * Global * - *============================================================================*/ - - -/*============================================================================* - * API * - *============================================================================*/ - -EAPI Eina_Iterator * -eina_xattr_value_fd_ls(int fd) -{ -#ifdef HAVE_XATTR - Eina_Xattr_Iterator *it; - ssize_t length; - - if (fd < 0) return NULL; - - length = flistxattr(fd, NULL, 0); - if (length <= 0) return NULL; - - it = calloc(1, sizeof (Eina_Xattr_Iterator) + length - 1); - if (!it) return NULL; - - it->attr = calloc(1, sizeof (Eina_Xattr)); - if (!it->attr) - { - free(it); - return NULL; - } - - EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); - - it->fd = fd; - it->length = flistxattr(fd, it->xattr, length); - if (it->length != length) - { - free(it); - return NULL; - } - - it->iterator.version = EINA_ITERATOR_VERSION; - it->iterator.next = FUNC_ITERATOR_NEXT(_eina_xattr_value_ls_fd_iterator_next); - it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_xattr_ls_iterator_container); - it->iterator.free = FUNC_ITERATOR_FREE(_eina_xattr_ls_iterator_free); - - return &it->iterator; -#else - return NULL; - (void)fd; -#endif -} - -EAPI Eina_Iterator * -eina_xattr_fd_ls(int fd) -{ -#ifdef HAVE_XATTR - Eina_Xattr_Iterator *it; - ssize_t length; - - if (fd < 0) return NULL; - - length = flistxattr(fd, NULL, 0); - if (length <= 0) return NULL; - - it = calloc(1, sizeof (Eina_Xattr_Iterator) + length - 1); - if (!it) return NULL; - - EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); - - it->length = flistxattr(fd, it->xattr, length); - if (it->length != length) - { - free(it); - return NULL; - } - - it->iterator.version = EINA_ITERATOR_VERSION; - it->iterator.next = FUNC_ITERATOR_NEXT(_eina_xattr_ls_iterator_next); - it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_xattr_ls_iterator_container); - it->iterator.free = FUNC_ITERATOR_FREE(_eina_xattr_ls_iterator_free); - - return &it->iterator; -#else - return NULL; - (void)fd; -#endif -} - -EAPI Eina_Iterator * -eina_xattr_ls(const char *file) -{ -#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 Eina_Iterator * -eina_xattr_value_ls(const char *file) -{ -#ifdef HAVE_XATTR - Eina_Xattr_Iterator *it; - ssize_t length; - - EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); - - length = listxattr(file, NULL, 0); - if (length <= 0) return NULL; - - it = calloc(1, sizeof (Eina_Xattr_Iterator) + length - 1); - if (!it) return NULL; - - EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); - - it->length = listxattr(file, it->xattr, length); - if (it->length != length) - { - free(it); - return NULL; - } - - it->file = eina_stringshare_add(file); - - it->iterator.version = EINA_ITERATOR_VERSION; - it->iterator.next = FUNC_ITERATOR_NEXT(_eina_xattr_value_ls_iterator_next); - it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_xattr_ls_iterator_container); - it->iterator.free = FUNC_ITERATOR_FREE(_eina_xattr_ls_iterator_free); - - return &it->iterator; -#else - return NULL; - (void)file; -#endif -} - -EAPI void * -eina_xattr_get(const char *file, const char *attribute, ssize_t *size) -{ -#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; -} |