* -fno-strict-aliasing is checked at linked time (to make sure

that it is disabled for suncc)
 * add old evas data types in tests. Tell me if you encounter problems
   with them


SVN revision: 46136
This commit is contained in:
Vincent Torri 2010-02-13 12:32:22 +00:00
parent 0a87819b44
commit b87e1d6fae
15 changed files with 2326 additions and 101 deletions

View File

@ -294,7 +294,6 @@ if ! test "x${VMIC}" = "x" ; then
fi
EFL_COMPILER_FLAG([-Wshadow])
EFL_COMPILER_FLAG([-fno-strict-aliasing])
AC_SUBST(EINA_CPPFLAGS)
AC_SUBST(EINA_CFLAGS)
@ -327,6 +326,8 @@ esac
AC_SUBST(EINA_LIBS)
AC_SUBST(lt_enable_auto_import)
EFL_LINKER_FLAG([-fno-strict-aliasing])
### Checks for library functions
AC_FUNC_ALLOCA
@ -483,7 +484,6 @@ if test "x$enable_coverage" = "xyes" ; then
fi
EFL_CHECK_BENCHMARK([enable_benchmark="yes"], [enable_benchmark="no"])
EINA_BENCH_MODULE([evas], [${enable_benchmark}], [evas], [enable_benchmark_evas="yes"], [enable_benchmark_evas="no"])
EINA_BENCH_MODULE([glib], [${enable_benchmark}], [glib-2.0], [enable_benchmark_glib="yes"], [enable_benchmark_glib="no"])
AC_SUBST(requirement_eina)
@ -554,7 +554,6 @@ echo " Coverage.............: ${enable_coverage}"
echo " Benchmark............: ${enable_benchmark}"
if test "x${enable_benchmark}" = "xyes" ; then
echo " Glib...............: ${enable_benchmark_glib}"
echo " Evas...............: ${enable_benchmark_evas}"
echo " E17 real data......: ${enable_benchmark_e17}"
fi
echo

View File

@ -1,5 +1,11 @@
dnl Checks if a given compiler switch is supported.
dnl If so, this macro adds the flag to the CFLAGS
dnl Copyright (C) 2010 Vincent Torri <vtorri at univ-evry dot fr>
dnl and Albin Tonnerre <albin dot tonnerre at gmail dot com>
dnl That code is public domain and can be freely used or copied.
dnl Macro that checks if a compiler flag is supported by the compiler.
dnl Usage: EFL_COMPILER_FLAG(flag)
dnl flag is added to CFLAGS if supported.
AC_DEFUN([EFL_COMPILER_FLAG],
[
@ -22,3 +28,30 @@ fi
AC_LANG_POP([C])
])
dnl Macro that checks if a linker flag is supported by the compiler.
dnl Usage: EFL_LINKER_FLAG(flag)
dnl flag is added to CFLAGS if supported (will be passed to ld anyway).
AC_DEFUN([EFL_LINKER_FLAG],
[
CFLAGS_save="${CFLAGS}"
CFLAGS="${CFLAGS} $1"
AC_LANG_PUSH([C])
AC_MSG_CHECKING([whether the compiler supports $1])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[]])],
[have_flag="yes"],
[have_flag="no"])
AC_MSG_RESULT([${have_flag}])
if test "x${have_flag}" = "xno" ; then
CFLAGS="${CFLAGS_save}"
fi
AC_LANG_POP([C])
])

View File

@ -0,0 +1,151 @@
#ifndef _EVAS_DATA_H
#define _EVAS_DATA_H
#ifdef EAPI
# undef EAPI
#endif
#ifdef _WIN32
# ifdef EFL_EVAS_BUILD
# ifdef DLL_EXPORT
# define EAPI __declspec(dllexport)
# else
# define EAPI
# endif /* ! DLL_EXPORT */
# else
# define EAPI __declspec(dllimport)
# endif /* ! EFL_EVAS_BUILD */
#else
# ifdef __GNUC__
# if __GNUC__ >= 4
# define EAPI __attribute__ ((visibility("default")))
# else
# define EAPI
# endif
# else
# define EAPI
# endif
#endif /* ! _WIN32 */
/**
* @file
* @brief These routines are used for Evas data types.
*/
typedef unsigned char Evas_Bool;
typedef struct _Evas_Array_Hash Evas_Array_Hash;
typedef struct _Evas_Hash Evas_Hash; /**< A Hash table handle */
typedef struct _Evas_List Evas_List; /**< A generic linked list node handle */
typedef struct _Evas_Object_List Evas_Object_List;
struct _Evas_Hash
{
int population;
Evas_Object_List *buckets[256];
};
struct _Evas_List /** A linked list node */
{
void *data; /**< Pointer to list element payload */
Evas_List *next; /**< Next member in the list */
Evas_List *prev; /**< Previous member in the list */
struct _Evas_List_Accounting *accounting; /**< Private list accounting info - don't touch */
};
struct _Evas_Object_List
{
Evas_Object_List *next, *prev;
Evas_Object_List *last;
};
#ifdef __cplusplus
extern "C" {
#endif
/*
* Evas Array Hash functions
*/
EAPI Evas_Array_Hash *evas_array_hash_new (void);
EAPI void evas_array_hash_free (Evas_Array_Hash *hash);
EAPI void evas_array_hash_add (Evas_Array_Hash *hash, int key, int data);
EAPI int evas_array_hash_search (Evas_Array_Hash *hash, int key);
/*
* Evas Hash functions
*/
/* FIXME: add:
* api to add find, del members by data, size not just string and also
* provide hash generation functions settable by the app
*
* do we really need this? hmmm - let me think... there may be a better way
*/
EAPI Evas_Hash *evas_hash_add (Evas_Hash *hash, const char *key, const void *data);
EAPI Evas_Hash *evas_hash_direct_add (Evas_Hash *hash, const char *key, const void *data);
EAPI Evas_Hash *evas_hash_del (Evas_Hash *hash, const char *key, const void *data);
EAPI void *evas_hash_find (const Evas_Hash *hash, const char *key);
EAPI void *evas_hash_modify (Evas_Hash *hash, const char *key, const void *data);
EAPI int evas_hash_size (const Evas_Hash *hash);
EAPI void evas_hash_free (Evas_Hash *hash);
EAPI void evas_hash_foreach (const Evas_Hash *hash, Evas_Bool (*func) (const Evas_Hash *hash, const char *key, void *data, void *fdata), const void *fdata);
EAPI int evas_hash_alloc_error (void);
/*
* Evas List functions
*/
EAPI Evas_List *evas_list_append (Evas_List *list, const void *data);
EAPI Evas_List *evas_list_prepend (Evas_List *list, const void *data);
EAPI Evas_List *evas_list_append_relative (Evas_List *list, const void *data, const void *relative);
EAPI Evas_List *evas_list_append_relative_list (Evas_List *list, const void *data, Evas_List *relative);
EAPI Evas_List *evas_list_prepend_relative (Evas_List *list, const void *data, const void *relative);
EAPI Evas_List *evas_list_prepend_relative_list (Evas_List *list, const void *data, Evas_List *relative);
EAPI Evas_List *evas_list_remove (Evas_List *list, const void *data);
EAPI Evas_List *evas_list_remove_list (Evas_List *list, Evas_List *remove_list);
EAPI Evas_List *evas_list_promote_list (Evas_List *list, Evas_List *move_list);
EAPI void *evas_list_find (const Evas_List *list, const void *data);
EAPI Evas_List *evas_list_find_list (const Evas_List *list, const void *data);
EAPI Evas_List *evas_list_free (Evas_List *list);
EAPI Evas_List *evas_list_last (const Evas_List *list);
EAPI Evas_List *evas_list_next (const Evas_List *list);
EAPI Evas_List *evas_list_prev (const Evas_List *list);
EAPI void *evas_list_data (const Evas_List *list);
EAPI int evas_list_count (const Evas_List *list);
EAPI void *evas_list_nth (const Evas_List *list, int n);
EAPI Evas_List *evas_list_nth_list (const Evas_List *list, int n);
EAPI Evas_List *evas_list_reverse (Evas_List *list);
EAPI Evas_List *evas_list_sort (Evas_List *list, int size, int(*func)(void*,void*));
EAPI int evas_list_alloc_error (void);
/*
* Evas Object List functions
*/
EAPI void *evas_object_list_append (void *in_list, void *in_item);
EAPI void *evas_object_list_prepend (void *in_list, void *in_item);
EAPI void *evas_object_list_append_relative (void *in_list, void *in_item, void *in_relative);
EAPI void *evas_object_list_prepend_relative (void *in_list, void *in_item, void *in_relative);
EAPI void *evas_object_list_remove (void *in_list, void *in_item);
EAPI void *evas_object_list_find (void *in_list, void *in_item);
/*
* Evas Stringshare functions
*/
EAPI void evas_stringshare_init (void); /* not implemented */
EAPI void evas_stringshare_shutdown (void); /* not implemented */
EAPI const char *evas_stringshare_add (const char *str);
EAPI void evas_stringshare_del (const char *str);
#ifdef __cplusplus
}
#endif
#endif /* _EVAS_DATA_H */

View File

@ -12,8 +12,7 @@ AM_CPPFLAGS = \
-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
-DPACKAGE_BUILD_DIR=\"`pwd`/$(top_builddir)\" \
@CHECK_CFLAGS@ \
@GLIB_CFLAGS@ \
@EVAS_CFLAGS@
@GLIB_CFLAGS@
if EINA_HAVE_GLIB
@ -21,12 +20,6 @@ AM_CPPFLAGS += -DEINA_BENCH_HAVE_GLIB
endif
if EINA_HAVE_EVAS
AM_CPPFLAGS += -DEINA_BENCH_HAVE_EVAS
endif
if EINA_ENABLE_BENCHMARK_E17
AM_CPPFLAGS += -DEINA_ENABLE_BENCH_E17
@ -94,11 +87,16 @@ eina_bench_rectangle_pool.c \
ecore_list.c \
ecore_strings.c \
ecore_hash.c \
ecore_sheap.c
ecore_sheap.c \
evas_hash.c \
evas_list.c \
evas_mempool.c \
evas_object_list.c \
evas_stringshare.c
eina_bench_LDADD = @EVAS_LIBS@ @GLIB_LIBS@ $(top_builddir)/src/lib/libeina.la
eina_bench_LDADD = @GLIB_LIBS@ $(top_builddir)/src/lib/libeina.la
endif
EXTRA_DIST = eina_bench.h eina_suite.h
EXTRA_DIST = eina_bench.h eina_suite.h Ecore_Data.h Evas_Data.h evas_mempool.h

View File

@ -28,16 +28,14 @@
# include <glib.h>
#endif
#ifdef EINA_BENCH_HAVE_EVAS
# include <Evas.h>
#endif
# include "Ecore_Data.h"
#include "Evas_Data.h"
#include "Ecore_Data.h"
#include "eina_bench.h"
#include "eina_array.h"
#include "eina_list.h"
#include "eina_inlist.h"
#include "eina_main.h"
typedef struct _Eina_Bench_Object Eina_Bench_Object;
struct _Eina_Bench_Object
@ -557,8 +555,6 @@ eina_bench_gptrarray_4evas_render(int request)
}
#endif
#ifdef EINA_BENCH_HAVE_EVAS
#if 0
static void
eina_bench_evas_list_4evas_render(int request)
{
@ -568,8 +564,6 @@ eina_bench_evas_list_4evas_render(int request)
int i;
int j;
evas_init();
for (i = 0; i < 1000; ++i)
{
for (j = 0; j < request; ++j)
@ -624,11 +618,7 @@ eina_bench_evas_list_4evas_render(int request)
free(evas_list_data(list));
list = evas_list_remove_list(list, list);
}
evas_shutdown();
}
#endif
#endif
static void
_eina_ecore_for_each_remove(void *value, void *user_data)
@ -701,11 +691,7 @@ void eina_bench_array(Eina_Benchmark *bench)
eina_benchmark_register(bench, "glist", EINA_BENCHMARK(eina_bench_glist_4evas_render), 200, 4000, 100);
eina_benchmark_register(bench, "gptrarray", EINA_BENCHMARK(eina_bench_gptrarray_4evas_render), 200, 4000, 100);
#endif
#ifdef EINA_BENCH_HAVE_EVAS
#if 0
eina_benchmark_register(bench, "evas", EINA_BENCHMARK(eina_bench_evas_list_4evas_render), 200, 4000, 100);
#endif
#endif
eina_benchmark_register(bench, "ecore", EINA_BENCHMARK(eina_bench_ecore_list_4evas_render), 200, 1000, 100);
}

View File

@ -29,11 +29,8 @@
# include <glib.h>
#endif
#ifdef EINA_BENCH_HAVE_EVAS
# include <Evas.h>
#endif
# include <Ecore_Data.h>
#include "Evas_Data.h"
#include "Ecore_Data.h"
#include "eina_hash.h"
#include "eina_array.h"
@ -278,8 +275,6 @@ eina_bench_lookup_ghash(int request)
}
#endif
#ifdef EINA_BENCH_HAVE_EVAS
#if 0
static void
eina_bench_lookup_evas(int request)
{
@ -298,7 +293,7 @@ eina_bench_lookup_evas(int request)
tmp_val = malloc(sizeof (int));
if (!tmp_key || !tmp_val) continue ;
if (!tmp_val) continue ;
eina_convert_itoa(i, tmp_key);
*tmp_val = i;
@ -327,8 +322,6 @@ eina_bench_lookup_evas(int request)
eina_array_free(array);
}
#endif
#endif
typedef struct _Eina_Bench_Ecore Eina_Bench_Ecore;
struct _Eina_Bench_Ecore
@ -386,10 +379,6 @@ void eina_bench_hash(Eina_Benchmark *bench)
#ifdef EINA_BENCH_HAVE_GLIB
eina_benchmark_register(bench, "ghash-lookup", EINA_BENCHMARK(eina_bench_lookup_ghash), 10, 3000, 10);
#endif
#ifdef EINA_BENCH_HAVE_EVAS
#if 0
eina_benchmark_register(bench, "evas-lookup", EINA_BENCHMARK(eina_bench_lookup_evas), 10, 3000, 10);
#endif
#endif
eina_benchmark_register(bench, "ecore-lookup", EINA_BENCHMARK(eina_bench_lookup_ecore), 10, 3000, 10);
}

View File

@ -27,14 +27,13 @@
# include <glib.h>
#endif
#ifdef EINA_BENCH_HAVE_EVAS
# include <Evas.h>
#endif
# include "Ecore_Data.h"
#include "Evas_Data.h"
#include "Ecore_Data.h"
#include "eina_bench.h"
#include "Eina.h"
#include "eina_convert.h"
#include "eina_list.h"
#include "eina_main.h"
static int
_eina_cmp_str(const char *a, const char *b)
@ -72,16 +71,12 @@ eina_bench_sort_eina(int request)
eina_shutdown();
}
#ifdef EINA_BENCH_HAVE_EVAS
#if 0
static void
eina_bench_sort_evas(int request)
{
Evas_List *list = NULL;
int i;
evas_init();
srand(time(NULL));
for (i = 0; i < request; ++i)
@ -100,11 +95,7 @@ eina_bench_sort_evas(int request)
free(evas_list_data(list));
list = evas_list_remove_list(list, list);
}
evas_shutdown();
}
#endif
#endif
#ifdef EINA_BENCH_HAVE_GLIB
static void
@ -212,11 +203,7 @@ void eina_bench_sort(Eina_Benchmark *bench)
eina_benchmark_register(bench, "ecore", EINA_BENCHMARK(eina_bench_sort_ecore_default), 10, 10000, 100);
eina_benchmark_register(bench, "ecore-merge", EINA_BENCHMARK(eina_bench_sort_ecore_merge), 10, 10000, 100);
eina_benchmark_register(bench, "ecore-heap", EINA_BENCHMARK(eina_bench_sort_ecore_heap), 10, 10000, 100);
#ifdef EINA_BENCH_HAVE_EVAS
#if 0
eina_benchmark_register(bench, "evas", EINA_BENCHMARK(eina_bench_sort_evas), 10, 10000, 100);
#endif
#endif
}

View File

@ -28,15 +28,13 @@
# include <glib.h>
#endif
#ifdef EINA_BENCH_HAVE_EVAS
# include <Evas.h>
#endif
# include "Ecore_Data.h"
#include "Evas_Data.h"
#include "Ecore_Data.h"
#include "eina_stringshare.h"
#include "eina_bench.h"
#include "eina_convert.h"
#include "eina_main.h"
static void
eina_bench_stringshare_job(int request)
@ -102,8 +100,6 @@ eina_bench_stringchunk_job(int request)
}
#endif
#ifdef EINA_BENCH_HAVE_EVAS
#if 0
static void
eina_bench_evas_job(int request)
{
@ -111,9 +107,6 @@ eina_bench_evas_job(int request)
unsigned int j;
int i;
evas_init();
/* evas_stringshare_init(); */
for (i = 0; i < request; ++i)
{
char build[64] = "string_";
@ -132,12 +125,7 @@ eina_bench_evas_job(int request)
eina_convert_xtoa(rand() % request, build + 7);
tmp = evas_stringshare_add(build);
}
/* evas_stringshare_shutdown(); */
evas_shutdown();
}
#endif
#endif
static void
eina_bench_ecore_job(int request)
@ -176,10 +164,6 @@ void eina_bench_stringshare(Eina_Benchmark *bench)
#ifdef EINA_BENCH_HAVE_GLIB
eina_benchmark_register(bench, "stringchunk (glib)", EINA_BENCHMARK(eina_bench_stringchunk_job), 100, 20100, 500);
#endif
#ifdef EINA_BENCH_HAVE_EVAS
#if 0
eina_benchmark_register(bench, "stringshare (evas)", EINA_BENCHMARK(eina_bench_evas_job), 100, 20100, 500);
#endif
#endif
eina_benchmark_register(bench, "stringshare (ecore)", EINA_BENCHMARK(eina_bench_ecore_job), 100, 20100, 500);
}

View File

@ -28,13 +28,8 @@
# include <glib.h>
#endif
#ifdef EINA_BENCH_HAVE_EVAS
# include <Evas.h>
#endif
#ifdef EINA_BENCH_HAVE_ECORE
# include <Ecore_Data.h>
#endif
#include "Evas_Data.h"
#include "Ecore_Data.h"
#include "Eina.h"
@ -60,17 +55,14 @@ static Eina_Stringshare_Test eina_str = {
eina_shutdown
};
#ifdef EINA_BENCH_HAVE_EVAS
static Eina_Stringshare_Test evas_str = {
"evas",
evas_init,
evas_stringshare_init,
evas_stringshare_add,
evas_stringshare_del,
evas_shutdown
evas_stringshare_shutdown
};
#endif
#ifdef EINA_BENCH_HAVE_ECORE
static Eina_Stringshare_Test ecore_str = {
"ecore",
ecore_string_init,
@ -78,16 +70,11 @@ static Eina_Stringshare_Test ecore_str = {
ecore_string_release,
ecore_string_shutdown
};
#endif
static Eina_Stringshare_Test* str[] = {
&eina_str,
#ifdef EINA_BENCH_HAVE_EVAS
&evas_str,
#endif
#ifdef EINA_BENCH_HAVE_ECORE
&ecore_str,
#endif
NULL
};

View File

@ -0,0 +1,498 @@
/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include "Evas_Data.h"
typedef struct _Evas_Hash_El Evas_Hash_El;
struct _Evas_Hash_El
{
Evas_Object_List _list_data;
const char *key;
void *data;
};
static inline int _evas_hash_gen(const char *key);
static int _evas_hash_alloc_error = 0;
static inline int
_evas_hash_gen(const char *key)
{
unsigned int hash_num = 5381;
const unsigned char *ptr;
if (!key) return 0;
for (ptr = (unsigned char *)key; *ptr; ptr++)
hash_num = (hash_num * 33) ^ *ptr;
hash_num &= 0xff;
return (int)hash_num;
}
/**
* @defgroup Evas_Hash_Data Hash Data Functions
*
* Functions that add, access or remove data from hashes.
*
* The following example shows how to add and then access data in a
* hash table:
* @code
* Evas_Hash *hash = NULL;
* extern void *my_data;
*
* hash = evas_hash_add(hash, "My Data", my_data);
* if (evas_hash_alloc_error())
* {
* fprintf(stderr, "ERROR: Memory is low. Hash allocation failed.\n");
* exit(-1);
* }
* if (evas_hash_find(hash, "My Data") == my_data)
* {
* printf("My Data inserted and successfully found.\n");
* }
* @endcode
*
* What follows is another example, showing how the @ref evas_hash_del
* function is used:
* @code
* extern Evas_Hash *hash;
* extern void *data;
*
* printf("Insert some data...\n");
* hash = evas_hash_add(hash, "My Data", my_data);
* printf("Removing by key...\n");
* hash = evas_hash_del(hash, "My Data", NULL);
* printf("Insert some more data as a NULL key...\n");
* hash = evas_hash_add(hash, NULL, my_data);
* printf("Removing by data as a NULL key...\n");
* hash = evas_hash_del(hash, NULL, my_data);
* @endcode
*/
/**
* Adds an entry to the given hash table.
*
* @p key is expected to be a unique string within the hash table.
* Otherwise, you cannot be sure which inserted data pointer will be
* accessed with @ref evas_hash_find , and removed with
* @ref evas_hash_del .
*
* Key strings are case sensitive.
*
* @ref evas_hash_alloc_error should be used to determine if an
* allocation error occurred during this function.
*
* @param hash The given hash table. Can be @c NULL, in which case a
* new hash table is allocated and returned.
* @param key A unique string. Can be @c NULL.
* @param data Data to associate with the string given by @p key.
* @return Either the given hash table, or if the given value for @p
* hash is @c NULL, then a new one. @c NULL will be returned
* if memory could not be allocated for a new table.
* @ingroup Evas_Hash_Data
*/
EAPI Evas_Hash *
evas_hash_add(Evas_Hash *hash, const char *key, const void *data)
{
int hash_num;
Evas_Hash_El *el;
if ((!key) || (!data)) return hash;
_evas_hash_alloc_error = 0;
if (!hash)
{
hash = calloc(1, sizeof(struct _Evas_Hash));
if (!hash)
{
_evas_hash_alloc_error = 1;
return NULL;
}
}
if (!(el = malloc(sizeof(struct _Evas_Hash_El) + strlen(key) + 1)))
{
if (hash->population <= 0)
{
free(hash);
hash = NULL;
}
_evas_hash_alloc_error = 1;
return hash;
};
el->key = ((char *)el) + sizeof(struct _Evas_Hash_El);
strcpy((char *) el->key, key);
el->data = (void *)data;
hash_num = _evas_hash_gen(key);
hash->buckets[hash_num] = evas_object_list_prepend(hash->buckets[hash_num], el);
hash->population++;
return hash;
}
/**
* Adds an entry to the given hash table and does not duplicate the string key.
*
* @p key is expected to be a unique string within the hash table.
* Otherwise, you cannot be sure which inserted data pointer will be
* accessed with @ref evas_hash_find , and removed with
* @ref evas_hash_del . This call does not make a copy of the key so it must
* be a string constant or stored elsewhere (in the object being added) etc.
*
* Key strings are case sensitive.
*
* @ref evas_hash_alloc_error should be used to determine if an
* allocation error occurred during this function.
*
* @param hash The given hash table. Can be @c NULL, in which case a
* new hash table is allocated and returned.
* @param key A unique string. Can be @c NULL.
* @param data Data to associate with the string given by @p key.
* @return Either the given hash table, or if the given value for @p
* hash is @c NULL, then a new one. @c NULL will be returned
* if memory could not be allocated for a new table.
* @ingroup Evas_Hash_Data
*/
EAPI Evas_Hash *
evas_hash_direct_add(Evas_Hash *hash, const char *key, const void *data)
{
int hash_num;
Evas_Hash_El *el;
if ((!key) || (!data)) return hash;
_evas_hash_alloc_error = 0;
if (!hash)
{
hash = calloc(1, sizeof(struct _Evas_Hash));
if (!hash)
{
_evas_hash_alloc_error = 1;
return NULL;
}
}
if (!(el = malloc(sizeof(struct _Evas_Hash_El))))
{
if (hash->population <= 0)
{
free(hash);
hash = NULL;
}
_evas_hash_alloc_error = 1;
return hash;
};
el->key = key;
el->data = (void *)data;
hash_num = _evas_hash_gen(key);
hash->buckets[hash_num] = evas_object_list_prepend(hash->buckets[hash_num], el);
hash->population++;
return hash;
}
/**
* Removes the entry identified by @p key or @p data from the given
* hash table.
*
* If @p key is @c NULL, then @p data is used to find a match to
* remove.
*
* @param hash The given hash table.
* @param key The key string. Can be @c NULL.
* @param data The data pointer to remove if @p key is @c NULL.
* Otherwise, not required and can be @c NULL.
* @return The modified hash table. If there are no entries left, the
* hash table will be freed and @c NULL will be returned.
* @ingroup Evas_Hash_Data
*/
EAPI Evas_Hash *
evas_hash_del(Evas_Hash *hash, const char *key, const void *data)
{
int hash_num;
Evas_Hash_El *el;
Evas_Object_List *l;
if (!hash) return NULL;
if (!key)
{
for (hash_num = 0; hash_num < 256; hash_num++)
{
for (l = hash->buckets[hash_num]; l; l = l->next)
{
el = (Evas_Hash_El *)l;
if (el->data == data)
{
hash->buckets[hash_num] = evas_object_list_remove(hash->buckets[hash_num], el);
free(el);
hash->population--;
if (hash->population <= 0)
{
free(hash);
hash = NULL;
}
return hash;
}
}
}
}
else
{
hash_num = _evas_hash_gen(key);
for (l = hash->buckets[hash_num]; l; l = l->next)
{
el = (Evas_Hash_El *)l;
if (!strcmp(el->key, key))
{
if ((!data) || (el->data == data))
{
hash->buckets[hash_num] = evas_object_list_remove(hash->buckets[hash_num], el);
free(el);
hash->population--;
if (hash->population <= 0)
{
free(hash);
hash = NULL;
}
return hash;
}
}
}
}
return hash;
}
/**
* Retrieves a specific entry in the given hash table.
* @param hash The given hash table.
* @param key The key string of the entry to find.
* @return The data pointer for the stored entry, or @c NULL if not
* found.
* @ingroup Evas_Hash_Data
*/
EAPI void *
evas_hash_find(const Evas_Hash *hash, const char *key)
{
int hash_num;
Evas_Hash_El *el;
Evas_Object_List *l;
_evas_hash_alloc_error = 0;
if ((!hash) || (!key)) return NULL;
hash_num = _evas_hash_gen(key);
for (l = hash->buckets[hash_num]; l; l = l->next)
{
el = (Evas_Hash_El *)l;
if (!strcmp(el->key, key))
{
if (l != hash->buckets[hash_num])
{
Evas_Object_List *bucket;
bucket = hash->buckets[hash_num];
bucket = evas_object_list_remove(bucket, el);
bucket = evas_object_list_prepend(bucket, el);
((Evas_Hash *)hash)->buckets[hash_num] = bucket;
}
return el->data;
}
}
return NULL;
}
/**
* Modifies the entry pointer at the specified key and returns the old entry
* @param hash The given hash table.
* @param key The key string of the entry to modify.
* @param data The data to replace the old entry, if it exists.
* @return The data pointer for the old stored entry, or @c NULL if not
* found. If an existing entry is not found, nothing is added to the
* hash.
* @ingroup Evas_Hash_Data
*/
EAPI void *
evas_hash_modify(Evas_Hash *hash, const char *key, const void *data)
{
int hash_num;
Evas_Hash_El *el;
Evas_Object_List *l;
_evas_hash_alloc_error = 0;
if (!hash) return NULL;
hash_num = _evas_hash_gen(key);
for (l = hash->buckets[hash_num]; l; l = l->next)
{
el = (Evas_Hash_El *)l;
if ((key) && (!strcmp(el->key, key)))
{
void *old_data;
if (l != hash->buckets[hash_num])
{
hash->buckets[hash_num] = evas_object_list_remove(hash->buckets[hash_num], el);
hash->buckets[hash_num] = evas_object_list_prepend(hash->buckets[hash_num], el);
}
old_data = el->data;
el->data = (void *) data;
return old_data;
}
}
return NULL;
}
/**
* @defgroup Evas_Hash_General_Group Hash General Functions
*
* Miscellaneous functions that operate on hash objects.
*/
/**
* Retrieves the number of buckets available in the given hash table.
* @param hash The given hash table.
* @return @c 256 if @p hash is not @c NULL. @c 0 otherwise.
* @ingroup Evas_Hash_General_Group
*/
EAPI int
evas_hash_size(const Evas_Hash *hash)
{
if (!hash) return 0;
return 256;
}
/**
* @todo Complete polishing documentation for evas_hash.c. The
* functions' docs may be grouped, but they need some simplification.
*/
/**
* Free an entire hash table
* @param hash The hash table to be freed
*
* This function frees up all the memory allocated to storing the specified
* hash tale pointed to by @p hash. Any entries in the table that the program
* has no more pointers for elsewhere may now be lost, so this should only be
* called if the program has lready freed any allocated data in the hash table
* or has the pointers for data in teh table stored elswehere as well.
*
* Example:
* @code
* extern Evas_Hash *hash;
*
* evas_hash_free(hash);
* hash = NULL;
* @endcode
* @ingroup Evas_Hash_General_Group
*/
EAPI void
evas_hash_free(Evas_Hash *hash)
{
int i, size;
if (!hash) return;
size = evas_hash_size(hash);
for (i = 0; i < size; i++)
{
while (hash->buckets[i])
{
Evas_Hash_El *el;
el = (Evas_Hash_El *)hash->buckets[i];
hash->buckets[i] = evas_object_list_remove(hash->buckets[i], el);
free(el);
}
}
free(hash);
}
/**
* Call a function on every member stored in the hash table
* @param hash The hash table whose members will be walked
* @param func The function to call on each parameter
* @param fdata The data pointer to pass to the function being called
*
* This function goes through every entry in the hash table @p hash and calls
* the function @p func on each member. The function should NOT modify the
* hash table contents if it returns 1. IF the hash table contents are
* modified by this function or the function wishes to stop processing it must
* return 0, otherwise return 1 to keep processing.
*
* Example:
* @code
* extern Evas_Hash *hash;
*
* Evas_Bool hash_fn(Evas_Hash *hash, const char *key, void *data, void *fdata)
* {
* printf("Func data: %s, Hash entry: %s / %p\n", fdata, key, data);
* return 1;
* }
*
* int main(int argc, char **argv)
* {
* char *hash_fn_data;
*
* hash_fn_data = strdup("Hello World");
* evas_hash_foreach(hash, hash_fn, hash_fn_data);
* free(hash_fn_data);
* }
* @endcode
* @ingroup Evas_Hash_General_Group
*/
EAPI void
evas_hash_foreach(const Evas_Hash *hash, Evas_Bool (*func) (const Evas_Hash *hash, const char *key, void *data, void *fdata), const void *fdata)
{
int i, size;
if (!hash) return;
size = evas_hash_size(hash);
for (i = 0; i < size; i++)
{
Evas_Object_List *l, *next_l;
for (l = hash->buckets[i]; l;)
{
Evas_Hash_El *el;
next_l = l->next;
el = (Evas_Hash_El *)l;
if (!func(hash, el->key, el->data, (void *)fdata)) return;
l = next_l;
}
}
}
/**
* Return memory allocation failure flag after an function requiring allocation
* @return The state of the allocation flag
*
* This function returns the state of the memory allocation flag. This flag is
* set if memory allocations fail during evas_hash_add() calls. If they do, 1
* will be returned, otherwise 0 will be returned. The flag will remain in its
* current state until the next call that requires allocation is called, and
* is then reset.
*
* Example:
* @code
* Evas_Hash *hash = NULL;
* extern void *my_data;
*
* hash = evas_hash_add(hash, "My Data", my_data);
* if (evas_hash_alloc_error())
* {
* fprintf(stderr, "ERROR: Memory is low. Hash allocation failed.\n");
* exit(-1);
* }
* if (evas_hash_find(hash, "My Data") == my_data)
* {
* printf("My Data inserted and successfully found.\n");
* }
* @endcode
* @ingroup Evas_Hash_General_Group
*/
EAPI int
evas_hash_alloc_error(void)
{
return _evas_hash_alloc_error;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,188 @@
/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include "Evas_Data.h"
#include "evas_mempool.h"
//#define NOPOOL
typedef struct _Pool Pool;
struct _Pool
{
int usage;
void *base;
Pool *prev, *next;
};
Pool *
_evas_mp_pool_new(Evas_Mempool *pool)
#ifdef NOPOOL
{
static Pool thepool;
return &thepool;
}
#else
{
Pool *p;
void **ptr;
int item_alloc, i;
item_alloc = ((pool->item_size + sizeof(void *) - 1) / sizeof(void *)) * sizeof(void *);
p = malloc(sizeof(Pool) + (pool->pool_size * item_alloc));
ptr = (void **)(((unsigned char *)p) + sizeof(Pool));
p->usage = 0;
p->base = ptr;
for (i = 0; i < pool->pool_size - 1; i++)
{
*ptr = (void **)(((unsigned char *)ptr) + item_alloc);
ptr = *ptr;
}
*ptr = NULL;
return p;
}
#endif
void
_evas_mp_pool_free(Pool *p)
#ifdef NOPOOL
{
}
#else
{
free(p);
}
#endif
void *
evas_mempool_malloc(Evas_Mempool *pool, int size)
#ifdef NOPOOL
{
return malloc(size);
}
#else
{
Pool *p;
void *mem;
for (p = pool->first; p; p = p->next) // look 4 pool from 2nd bucket on
{
if (p->base) // base is not NULL - has a free slot
{
if (p->prev)
{
if (pool->last == p) pool->last = p->prev;
p->prev->next = p->next;
p->prev = NULL;
p->next = pool->first;
p->next->prev = p;
pool->first = p;
}
break;
}
}
if (!p) // we have reached the end of the list - no free pools
{
p = _evas_mp_pool_new(pool);
if (!p) return NULL;
p->prev = NULL;
p->next = pool->first;
if (p->next) p->next->prev = p;
if (!pool->last) pool->last = p;
pool->first = p;
}
mem = p->base; // this points to the next free block - so take it
p->base = *((void **)mem); // base now points to the next free block
if (!p->base) // move to end - it just filled up
{
if (p->next)
{
if (p->prev) p->prev->next = p->next;
else pool->first = p->next;
p->next->prev = p->prev;
((Pool *)pool->last)->next = p;
p->prev = pool->last;
p->next = NULL;
pool->last = p;
}
}
p->usage++;
pool->usage++;
return mem;
}
#endif
void
evas_mempool_free(Evas_Mempool *pool, void *ptr)
#ifdef NOPOOL
{
free(ptr);
}
#else
{
Pool *p;
void *pmem;
int item_alloc, psize;
item_alloc = ((pool->item_size + sizeof(void *) - 1) / sizeof(void *)) * sizeof(void *);
psize = item_alloc * pool->pool_size;
for (p = (Pool *)(pool->first); p; p = p->next) // look 4 pool
{
pmem = (void *)(((unsigned char *)p) + sizeof(Pool)); // pool mem base
if ((ptr >= pmem) && ((unsigned char *)ptr < (((unsigned char *)pmem) + psize))) // is it in pool mem?
{
*((void **)ptr) = p->base; // freed node points to prev free node
p->base = ptr; // next free node is now the one we freed
p->usage--;
pool->usage--;
if (p->usage == 0) // free bucket
{
if (p->prev) p->prev->next = p->next;
if (p->next) p->next->prev = p->prev;
if (pool->last == p) pool->last = p->prev;
if (pool->first == p) pool->first = p->next;
_evas_mp_pool_free(p);
}
else
{
if (p->prev) // if not the first - move to front
{
p->prev->next = p->next;
if (p->next) p->next->prev = p->prev;
if (pool->last == p) pool->last = p->prev;
p->prev = NULL;
p->next = pool->first;
p->next->prev = p;
pool->first = p;
}
}
break;
}
}
}
#endif
void *
evas_mempool_calloc(Evas_Mempool *pool, int size)
#ifdef NOPOOL
{
return calloc(1, size);
}
#else
{
void *mem;
mem = evas_mempool_malloc(pool, size);
memset(mem, 0, size);
return mem;
}
#endif

View File

@ -0,0 +1,25 @@
/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#ifndef _EVAS_MEMPOOL_H
#define _EVAS_MEMPOOL_H
typedef struct _Evas_Mempool Evas_Mempool;
struct _Evas_Mempool
{
int item_size;
int pool_size;
int usage;
void *first, *last;
};
void *evas_mempool_malloc(Evas_Mempool *pool, int size);
void evas_mempool_free(Evas_Mempool *pool, void *ptr);
void *evas_mempool_calloc(Evas_Mempool *pool, int size);
#endif /* _EVAS_MEMPOOL_H */

View File

@ -0,0 +1,164 @@
/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include "Evas_Data.h"
/* list ops */
void *
evas_object_list_append(void *in_list, void *in_item)
{
Evas_Object_List *l, *new_l;
Evas_Object_List *list;
list = in_list;
new_l = in_item;
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;
}
void *
evas_object_list_prepend(void *in_list, void *in_item)
{
Evas_Object_List *new_l;
Evas_Object_List *list;
list = in_list;
new_l = in_item;
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;
}
void *
evas_object_list_append_relative(void *in_list, void *in_item, void *in_relative)
{
Evas_Object_List *list, *relative, *new_l;
list = in_list;
new_l = in_item;
relative = in_relative;
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 evas_object_list_append(list, new_l);
}
void *
evas_object_list_prepend_relative(void *in_list, void *in_item, void *in_relative)
{
Evas_Object_List *list, *relative, *new_l;
list = in_list;
new_l = in_item;
relative = in_relative;
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;
if (!new_l->next)
list->last = new_l;
return list;
}
else
{
if (!new_l->next)
new_l->last = new_l;
else
{
new_l->last = list->last;
list->last = NULL;
}
return new_l;
}
}
return evas_object_list_prepend(list, new_l);
}
void *
evas_object_list_remove(void *in_list, void *in_item)
{
Evas_Object_List *return_l;
Evas_Object_List *list, *item;
/* checkme */
if(!in_list)
return in_list;
list = in_list;
item = in_item;
if (!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;
}
void *
evas_object_list_find(void *in_list, void *in_item)
{
Evas_Object_List *l;
Evas_Object_List *list, *item;
list = in_list;
item = in_item;
for (l = list; l; l = l->next)
{
if (l == item) return item;
}
return NULL;
}

View File

@ -0,0 +1,205 @@
/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "Evas_Data.h"
typedef struct _Evas_Stringshare Evas_Stringshare;
typedef struct _Evas_Stringshare_El Evas_Stringshare_El;
struct _Evas_Stringshare
{
Evas_Stringshare_El *buckets[1024];
};
struct _Evas_Stringshare_El
{
Evas_Stringshare_El *next;
// int op;
int references;
};
static Evas_Stringshare share =
{
{
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
}
};
//static int op = 0;
//static FILE *f = NULL;
static inline int
_evas_stringshare_hash_gen(const char *str, int *len)
{
unsigned int hash_num = 5381;
const unsigned char *ptr;
for (ptr = (const unsigned char *)str; *ptr; ptr++)
{
hash_num = (hash_num * 33) ^ *ptr;
}
hash_num &= 0x3ff;
*len = ptr - (const unsigned char *)str;
return (int)hash_num;
}
EAPI const char *
evas_stringshare_add(const char *str)
{
int hash_num, slen;
char *el_str;
Evas_Stringshare_El *el, *pel = NULL;
if (!str) return NULL;
// if (!f)
// {
// char bf[256];
// snprintf(bf, sizeof(bf), "strlog-%i", getpid());
// f = fopen(bf, "w");
// }
hash_num = _evas_stringshare_hash_gen(str, &slen);
for (el = share.buckets[hash_num]; el; pel = el, el = el->next)
{
el_str = ((char *)el) + sizeof(Evas_Stringshare_El);
if (!strcmp(el_str, str))
{
if (pel)
{
pel->next = el->next;
el->next = share.buckets[hash_num];
share.buckets[hash_num] = el;
}
el->references++;
// fprintf(f, "strings[%i] = str->add(strings[%i]);\n", el->op, el->op);
// fflush(f);
return el_str;
}
}
if (!(el = malloc(sizeof(Evas_Stringshare_El) + slen + 1))) return NULL;
el_str = ((char *)el) + sizeof(Evas_Stringshare_El);
strcpy(el_str, str);
el->references = 1;
el->next = share.buckets[hash_num];
share.buckets[hash_num] = el;
// el->op = op;
// fprintf(f, "strings[%i] = str->add(\"%s\");\n", el->op, el_str);
// fflush(f);
// op++;
return el_str;
}
EAPI void
evas_stringshare_del(const char *str)
{
int hash_num, slen;
char *el_str;
Evas_Stringshare_El *el, *pel = NULL;
if (!str) return;
hash_num = _evas_stringshare_hash_gen(str, &slen);
for (el = share.buckets[hash_num]; el; pel = el, el = el->next)
{
el_str = ((char *)el) + sizeof(Evas_Stringshare_El);
if (el_str == str)
{
el->references--;
// fprintf(f, "str->del(strings[%i]);\n", el->op);
// fflush(f);
if (el->references == 0)
{
if (pel) pel->next = el->next;
else share.buckets[hash_num] = el->next;
free(el);
}
else
{
if (pel)
{
pel->next = el->next;
el->next = share.buckets[hash_num];
share.buckets[hash_num] = el;
}
}
return;
}
}
printf("EEEK trying to del non-shared stringshare \"%s\"\n", str);
abort();
}