that it is disabled for suncc) * add old evas data types in tests. Tell me if you encounter problems with them SVN revision: 46136devs/devilhorns/wayland_egl
parent
0a87819b44
commit
b87e1d6fae
15 changed files with 2326 additions and 101 deletions
@ -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 */ |
@ -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
@ -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 |
@ -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 */ |
@ -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; |
||||