diff --git a/legacy/ecore/src/lib/ecore/Ecore.h b/legacy/ecore/src/lib/ecore/Ecore.h index 096ade4c61..68838852db 100644 --- a/legacy/ecore/src/lib/ecore/Ecore.h +++ b/legacy/ecore/src/lib/ecore/Ecore.h @@ -6,12 +6,32 @@ #include #include #include +#include +#include +#include +#include +#include +#include + +#include + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif #ifdef __cplusplus extern "C" { #endif -/* Convenience macros */ +/* FIXME: [deprecated] Convenience macros */ #define ECORE_MIN(x, y) (((x) > (y)) ? (y) : (x)) #define ECORE_MAX(x, y) (((x) > (y)) ? (x) : (y)) diff --git a/legacy/ecore/src/lib/ecore/Ecore_Data.h b/legacy/ecore/src/lib/ecore/Ecore_Data.h new file mode 100644 index 0000000000..9ce47769a2 --- /dev/null +++ b/legacy/ecore/src/lib/ecore/Ecore_Data.h @@ -0,0 +1,546 @@ +#ifndef _ECORE_DATA_H +#define _ECORE_DATA_H + +#define PRIME_TABLE_MAX 21 +#define PRIME_MIN 17 +#define PRIME_MAX 16777213 + +extern const unsigned int ecore_prime_table[]; + +typedef void (*Ecore_For_Each) (void *value); +#define ECORE_FOR_EACH(function) ((Ecore_For_Each)function) + +typedef void (*Ecore_Free_Cb) (void *data); +#define ECORE_FREE_CB(func) ((Ecore_Free_Cb)func) + +typedef unsigned int (*Ecore_Hash_Cb) (void *key); +#define ECORE_HASH_CB(function) ((Ecore_Hash_Cb)function) + +typedef int (*Ecore_Compare_Cb) (void *data1, void *data2); +#define ECORE_COMPARE_CB(function) ((Ecore_Compare_Cb)function) + +int ecore_direct_compare(void *key1, void *key2); +int ecore_str_compare(void *key1, void *key2); + +unsigned int ecore_direct_hash(void *key); +unsigned int ecore_str_hash(void *key); + + +#ifdef HAVE_PTHREADS /* pthreads are installed */ + +#include + +#define ECORE_DECLARE_LOCKS \ +int readers; \ +pthread_mutex_t readers_mutex; \ +pthread_mutex_t writers_mutex; \ +pthread_cond_t readers_cond; + +#define ECORE_INIT_LOCKS(structure) \ +if (structure) { \ + structure->readers = 0; \ + pthread_mutex_init(&structure->readers_mutex, NULL); \ + pthread_mutex_init(&structure->writers_mutex, NULL); \ + pthread_cond_init(&structure->readers_cond, NULL); \ +} + +#define ECORE_DESTROY_LOCKS(structure) \ +if (structure) { \ + pthread_mutex_destroy(&structure->readers_mutex); \ + pthread_mutex_destroy(&structure->writers_mutex); \ + pthread_cond_destroy(&structure->readers_cond); \ +} + +#define ECORE_READ_LOCK(structure) \ +if (structure) { \ + pthread_mutex_lock(&structure->readers_mutex); \ + structure->readers++; \ + pthread_mutex_unlock(&structure->readers_mutex); \ +} + +#define ECORE_READ_UNLOCK(structure) \ +if (structure) { \ + pthread_mutex_lock(&structure->readers_mutex); \ + if (--structure->readers == 0) \ + pthread_cond_broadcast(&structure->readers_cond); \ + pthread_mutex_unlock(&structure->readers_mutex); \ +} + +#define ECORE_WRITE_LOCK(structure) \ +if (structure) { \ + pthread_mutex_lock(&structure->readers_mutex); \ + pthread_mutex_lock(&structure->writers_mutex); \ + while (structure->readers > 0) \ + pthread_cond_wait(&structure->readers_cond, \ + &structure->readers_mutex); \ + pthread_mutex_unlock(&structure->readers_mutex); \ +} + +#define ECORE_WRITE_UNLOCK(structure) \ +if (structure) \ + pthread_mutex_unlock(&structure->writers_mutex); \ + +#define ECORE_THREAD_CREATE(function, arg) \ +if (function) { \ + pthread_t thread; \ + pthread_create(&thread, NULL, function, arg); \ + pthread_detach(thread); \ +} + +#define ECORE_NO_THREADS(function, arg) + +#else /* No pthreads available */ + +#define ECORE_DECLARE_LOCKS +#define ECORE_INIT_LOCKS(structure) +#define ECORE_READ_LOCK(structure) +#define ECORE_READ_UNLOCK(structure) +#define ECORE_WRITE_LOCK(structure) +#define ECORE_WRITE_UNLOCK(structure) +#define ECORE_THREAD_CREATE(function, args) +#define ECORE_DESTROY_LOCKS(structure) + +#define ECORE_NO_THREADS(function, arg) if (function) function(arg); + +#endif /* HAVE_PTHREADS */ + +typedef struct _ecore_list Ecore_List; +#define ECORE_LIST(list) ((Ecore_List *)list) + +typedef struct _ecore_list_node Ecore_List_Node; +#define ECORE_LIST_NODE(node) ((Ecore_List_Node *)node) + +struct _ecore_list_node { + void *data; + struct _ecore_list_node *next; + + ECORE_DECLARE_LOCKS; +}; + +struct _ecore_list { + Ecore_List_Node *first; /* The first node in the list */ + Ecore_List_Node *last; /* The last node in the list */ + Ecore_List_Node *current; /* The current node in the list */ + + Ecore_Free_Cb free_func; /* The callback to free data in nodes */ + + int nodes; /* The number of nodes in the list */ + int index; /* The position from the front of the + list of current node */ + ECORE_DECLARE_LOCKS; +}; + + +/* Creating and initializing new list structures */ +Ecore_List *ecore_list_new(); +int ecore_list_init(Ecore_List *list); + +/* Adding items to the list */ +inline int ecore_list_append(Ecore_List * list, void *_data); +inline int ecore_list_prepend(Ecore_List * list, void *_data); +inline int ecore_list_insert(Ecore_List * list, void *_data); + +/* Removing items from the list */ +inline int ecore_list_remove_destroy(Ecore_List *list); +inline void *ecore_list_remove(Ecore_List * list); +inline void *ecore_list_remove_first(Ecore_List * list); +inline void *ecore_list_remove_last(Ecore_List * list); + +/* Retrieve the current position in the list */ +inline void *ecore_list_current(Ecore_List * list); +int ecore_list_index(Ecore_List * list); +int ecore_list_nodes(Ecore_List * list); + +/* Traversing the list */ +int ecore_list_for_each(Ecore_List *list, Ecore_For_Each function); +inline void *ecore_list_goto_first(Ecore_List * list); +inline void *ecore_list_goto_last(Ecore_List * list); +inline void *ecore_list_goto_index(Ecore_List * list, int index); +inline void *ecore_list_goto(Ecore_List * list, void *_data); + +/* Traversing the list and returning data */ +inline void *ecore_list_next(Ecore_List * list); + +/* Check to see if there is any data in the list */ +int ecore_list_is_empty(Ecore_List * list); + +/* Remove every node in the list without freeing the list itself */ +int ecore_list_clear(Ecore_List * list); +/* Free the list and it's contents */ +void ecore_list_destroy(Ecore_List *list); + +/* Creating and initializing list nodes */ +Ecore_List_Node *ecore_list_node_new(); +int ecore_list_node_init(Ecore_List_Node *newNode); + +/* Destroying nodes */ +int ecore_list_node_destroy(Ecore_List_Node * _e_node, Ecore_Free_Cb free_func); + +int ecore_list_set_free_cb(Ecore_List * list, Ecore_Free_Cb free_func); + +typedef Ecore_List Ecore_DList; +#define ECORE_DLIST(dlist) ((Ecore_DList *)dlist) + +typedef struct _ecore_dlist_node Ecore_DList_Node; +#define ECORE_DLIST_NODE(dlist) ((Ecore_DList_Node *)dlist) + +struct _ecore_dlist_node { + Ecore_List_Node single; + Ecore_DList_Node *previous; +}; + +/* Creating and initializing new list structures */ +Ecore_DList *ecore_dlist_new(); +int ecore_dlist_init(Ecore_DList *list); +void ecore_dlist_destroy(Ecore_DList *list); + +/* Adding items to the list */ +int ecore_dlist_append(Ecore_DList * _e_dlist, void *_data); +int ecore_dlist_prepend(Ecore_DList * _e_dlist, void *_data); +int ecore_dlist_insert(Ecore_DList * _e_dlist, void *_data); + +/* Info about list's state */ +void *ecore_dlist_current(Ecore_DList *list); +int ecore_dlist_index(Ecore_DList *list); +#define ecore_dlist_nodes(list) ecore_list_nodes(ECORE_LIST(list)) + +/* Removing items from the list */ +void *ecore_dlist_remove(Ecore_DList * _e_dlist); +void *ecore_dlist_remove_first(Ecore_DList * _e_dlist); +void *ecore_dlist_remove_last(Ecore_DList * _e_dlist); + +/* Traversing the list */ +#define ecore_dlist_for_each(list, function) \ + ecore_list_for_each(ECORE_LIST(list), function) +inline void *ecore_dlist_goto_first(Ecore_DList * _e_dlist); +inline void *ecore_dlist_goto_last(Ecore_DList * _e_dlist); +inline void *ecore_dlist_goto_index(Ecore_DList * _e_dlist, int index); +inline void *ecore_dlist_goto(Ecore_DList * _e_dlist, void *_data); + +/* Traversing the list and returning data */ +inline void *ecore_dlist_next(Ecore_DList * list); +inline void *ecore_dlist_previous(Ecore_DList * list); + +/* Check to see if there is any data in the list */ +int ecore_dlist_is_empty(Ecore_DList * _e_dlist); + +/* Remove every node in the list without free'ing it */ +int ecore_dlist_clear(Ecore_DList * _e_dlist); + +/* Creating and initializing list nodes */ +Ecore_DList_Node *ecore_dlist_node_new(); + +/* Destroying nodes */ +int ecore_dlist_node_destroy(Ecore_DList_Node * node, Ecore_Free_Cb free_func); + +int ecore_dlist_set_free_cb(Ecore_DList * dlist, Ecore_Free_Cb free_func); + + + +/* + * Hash Table Implementation: + * + * Traditional hash table implementation. I had tried a list of tables + * approach to save on the realloc's but it ended up being much slower than + * the traditional approach. + */ + +typedef struct _ecore_hash_node Ecore_Hash_Node; +#define ECORE_HASH_NODE(hash) ((Ecore_Hash_Node *)hash) + +struct _ecore_hash_node { + void *key; /* The key for the data node */ + void *value; /* The value associated with this node */ + + ECORE_DECLARE_LOCKS +}; + +typedef struct _ecore_hash Ecore_Hash; +#define ECORE_HASH(hash) ((Ecore_Hash *)hash) + +struct _ecore_hash { + Ecore_List **buckets; + int size; /* An index into the table of primes to + determine size */ + int nodes; /* The number of nodes currently in the hash */ + + Ecore_Compare_Cb compare; /* The function used to compare node values */ + Ecore_Hash_Cb hash_func; /* The function used to compare node values */ + + Ecore_Free_Cb free_key; /* The callback function to free key */ + Ecore_Free_Cb free_value; /* The callback function to determine hash */ + + ECORE_DECLARE_LOCKS +}; + +/* Create and initialize a hash */ +Ecore_Hash *ecore_hash_new(Ecore_Hash_Cb hash_func, Ecore_Compare_Cb compare); +int ecore_hash_init(Ecore_Hash *hash, Ecore_Hash_Cb hash_func, Ecore_Compare_Cb compare); + +/* Functions related to freeing the data in the hash table */ +int ecore_hash_set_free_key(Ecore_Hash *hash, Ecore_Free_Cb function); +int ecore_hash_set_free_value(Ecore_Hash *hash, Ecore_Free_Cb function); +void ecore_hash_destroy(Ecore_Hash *hash); +int ecore_hash_for_each_node(Ecore_Hash *hash, Ecore_For_Each for_each_func); + +/* Retrieve and store data into the hash */ +void *ecore_hash_get(Ecore_Hash *hash, void *key); +int ecore_hash_set(Ecore_Hash *hash, void *key, void *value); +void *ecore_hash_remove(Ecore_Hash *hash, void *key); +void ecore_hash_dump_graph(Ecore_Hash *hash); + + +inline void ecore_print_warning(char *function, char *sparam); + +/* Wrappers around free() that helps debug free() bugs such as freeing NULL + * or accessing a pointer that has already been freed */ +#ifndef IF_FREE +#define IF_FREE(ptr) if (ptr) free(ptr); ptr = NULL; +#endif + +#ifndef FREE +#define FREE(ptr) free(ptr); ptr = NULL; +#endif + +/* Debugging printf, basically a wrapper to fprintf that checks the level + * of the message and checks that it is to be printed at the current debugging + * level */ +#ifndef DPRINTF +#define DPRINTF(debug, format, args...) \ +if (debug >= DEBUG_LEVEL) \ + fprintf(stderr, format, args); +#endif + +/* convenience macros for checking pointer parameters for non-NULL */ +#ifndef CHECK_PARAM_POINTER_RETURN +#define CHECK_PARAM_POINTER_RETURN(sparam, param, ret) \ +if (!(param)) \ +{ \ + ecore_print_warning(__FUNCTION__, sparam); \ + return ret; \ +} +#endif + +#ifndef CHECK_PARAM_POINTER +#define CHECK_PARAM_POINTER(sparam, param) \ +if (!(param)) \ +{ \ + ecore_print_warning(__FUNCTION__, sparam); \ + return; \ +} +#endif + +/* Use the larger of a and b */ +#ifndef MAX +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +/* Use the smaller of a and b */ +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + + +typedef struct _ecore_path_group Ecore_Path_Group; +struct _ecore_path_group +{ + int id; + char *name; + Ecore_List *paths; +}; + +/* + * Create a new path group + */ +int ecore_path_group_new(char *group_name); + +/* + * Destroy a previous path group + */ +void ecore_path_group_del(int group_id); + +/* + * Add a directory to be searched for files + */ +void ecore_path_group_add(int group_id, char *path); + +/* + * Remove a directory to be searched for files + */ +void ecore_path_group_remove(int group_id, char *path); + +/* + * Find the absolute path if it exists in the group of paths + */ +char * ecore_path_group_find(int group_id, char *name); + +/* + * Get a list of all the available files in a path set + */ +Ecore_List * ecore_path_group_available(int group_id); + + +typedef struct _ecore_plugin Ecore_Plugin; +struct _ecore_plugin +{ + int group; + char *name; + void *handle; +}; + +/* + * Load the specified plugin + */ +Ecore_Plugin *ecore_plugin_load(int group_id, char *plugin); + +/* + * Unload the specified plugin + */ +void ecore_plugin_unload(Ecore_Plugin * plugin); + +/* + * Lookup the specified symbol for the plugin + */ +void *ecore_plugin_call(Ecore_Plugin * plugin, char *symbol_name); + +Ecore_List *ecore_plugin_get_available(int group_id); + + +#define ECORE_SHEAP_MIN 0 +#define ECORE_SHEAP_MAX 1 + +#define HEAP_INCREMENT 4096 + +#define PARENT(i) (i / 2) +#define LEFT(i) (2 * i) +#define RIGHT(i) (2 * i + 1) + +typedef struct _ecore_heap Ecore_Sheap; +#define ECORE_HEAP(heap) ((Ecore_Sheap *)heap) + +struct _ecore_heap { + void **data; + int size; + int space; + + char order, sorted; + + Ecore_Compare_Cb compare; +}; + +Ecore_Sheap *ecore_sheap_new(Ecore_Compare_Cb compare, int size); +void ecore_sheap_destroy(Ecore_Sheap *heap); +int ecore_sheap_init(Ecore_Sheap *heap, Ecore_Compare_Cb compare, int size); +int ecore_sheap_insert(Ecore_Sheap *heap, void *data); +void *ecore_sheap_extract(Ecore_Sheap *heap); +void *ecore_sheap_extreme(Ecore_Sheap *heap); +int ecore_sheap_change(Ecore_Sheap *heap, void *item, void *newval); +void ecore_sheap_destroy(Ecore_Sheap *heap); +void ecore_sheap_sort(Ecore_Sheap *heap); + +inline void *ecore_sheap_item(Ecore_Sheap *heap, int i); + + +typedef struct _ecore_string Ecore_String; +struct _ecore_string { + char *string; + int references; +}; + +char *ecore_string_instance(char *string); +void ecore_string_release(char *string); + + +typedef struct _Ecore_Tree_Node Ecore_Tree_Node; +#define ECORE_TREE_NODE(object) ((Ecore_Tree_Node *)object) +struct _Ecore_Tree_Node { + + /* The actual data for each node */ + void *key; + void *value; + + /* Pointers to surrounding nodes */ + Ecore_Tree_Node *parent; + Ecore_Tree_Node *left_child; + Ecore_Tree_Node *right_child; + + /* Book keeping information for quicker balancing of the tree */ + int max_right; + int max_left; + + ECORE_DECLARE_LOCKS; +}; + +typedef struct _Ecore_Tree Ecore_Tree; +#define ECORE_TREE(object) ((Ecore_Tree *)object) +struct _Ecore_Tree { + /* Nodes of the tree */ + Ecore_Tree_Node *tree; + + /* Callback for comparing node values, default is direct comparison */ + Ecore_Compare_Cb compare_func; + + /* Callback for freeing node data, default is NULL */ + Ecore_Free_Cb free_func; + + ECORE_DECLARE_LOCKS; +}; + +/* Some basic tree functions */ +/* Allocate and initialize a new tree */ +Ecore_Tree *ecore_tree_new(Ecore_Compare_Cb compare_func); +/* Initialize a new tree */ +int ecore_tree_init(Ecore_Tree * tree, Ecore_Compare_Cb compare_func); + +/* Free the tree */ +int ecore_tree_destroy(Ecore_Tree * tree); +/* Check to see if the tree has any nodes in it */ +int ecore_tree_is_empty(Ecore_Tree * tree); + +/* Retrieve the value associated with key */ +void *ecore_tree_get(Ecore_Tree * tree, void *key); +Ecore_Tree_Node *ecore_tree_get_node(Ecore_Tree * tree, void *key); +/* Retrieve the value of node with key greater than or equal to key */ +void *ecore_tree_get_closest_larger(Ecore_Tree * tree, void *key); +/* Retrieve the value of node with key less than or equal to key */ +void *ecore_tree_get_closest_smaller(Ecore_Tree * tree, void *key); + +/* Set the value associated with key to value */ +int ecore_tree_set(Ecore_Tree * tree, void *key, void *value); +/* Remove the key from the tree */ +int ecore_tree_remove(Ecore_Tree * tree, void *key); + +/* Add a node to the tree */ +int ecore_tree_add_node(Ecore_Tree * tree, Ecore_Tree_Node * node); +/* Remove a node from the tree */ +int ecore_tree_remove_node(Ecore_Tree * tree, Ecore_Tree_Node * node); + +/* For each node in the tree perform the for_each_func function */ +/* For this one pass in the node */ +int ecore_tree_for_each_node(Ecore_Tree * tree, Ecore_For_Each for_each_func); +/* And here pass in the node's value */ +int ecore_tree_for_each_node_value(Ecore_Tree * tree, + Ecore_For_Each for_each_func); + +/* Some basic node functions */ +/* Initialize a node */ +int ecore_tree_node_init(Ecore_Tree_Node * new_node); +/* Allocate and initialize a new node */ +Ecore_Tree_Node *ecore_tree_node_new(); +/* Free the desired node */ +int ecore_tree_node_destroy(Ecore_Tree_Node * node, Ecore_Free_Cb free_data); + +/* Set the node's key to key */ +int ecore_tree_node_key_set(Ecore_Tree_Node * node, void *key); +/* Retrieve the key in node */ +void *ecore_tree_node_key_get(Ecore_Tree_Node * node); + +/* Set the node's value to value */ +int ecore_tree_node_value_set(Ecore_Tree_Node * node, void *value); +/* Retrieve the value in node */ +void *ecore_tree_node_value_get(Ecore_Tree_Node * node); + +/* Add a function to free the data stored in nodes */ +int ecore_tree_set_free_cb(Ecore_Tree * tree, Ecore_Free_Cb free_func); + +#endif /* _ECORE_DATA_H */ diff --git a/legacy/ecore/src/lib/ecore/Makefile.am b/legacy/ecore/src/lib/ecore/Makefile.am index 53ed30d411..3864dbae5d 100644 --- a/legacy/ecore/src/lib/ecore/Makefile.am +++ b/legacy/ecore/src/lib/ecore/Makefile.am @@ -4,22 +4,30 @@ INCLUDES = lib_LTLIBRARIES = libecore.la include_HEADERS = \ -Ecore.h +Ecore.h \ +Ecore_Data.h libecore_la_SOURCES = \ ecore.c \ ecore_app.c \ ecore_events.c \ ecore_exe.c \ +ecore_hash.c \ ecore_idle_enterer.c \ ecore_idle_exiter.c \ ecore_idler.c \ ecore_list.c \ ecore_main.c \ +ecore_path.c \ +ecore_plugin.c \ +ecore_sheap.c \ ecore_signal.c \ +ecore_strings.c \ ecore_time.c \ ecore_timer.c \ +ecore_tree.c \ +ecore_value.c \ ecore_private.h -libecore_la_LIBADD = +libecore_la_LIBADD = -lm @dlopen_libs@ libecore_la_LDFLAGS = -version-info 1:0:0 diff --git a/legacy/ecore/src/lib/ecore/ecore_events.c b/legacy/ecore/src/lib/ecore/ecore_events.c index f0fe43fbc0..df3438c6f8 100644 --- a/legacy/ecore/src/lib/ecore/ecore_events.c +++ b/legacy/ecore/src/lib/ecore/ecore_events.c @@ -353,20 +353,20 @@ _ecore_event_del(Ecore_Event *event) void _ecore_event_call(void) { - Ecore_List *l; + Ecore_Oldlist *l; - for (l = (Ecore_List *)event_filters; l; l = l->next) + for (l = (Ecore_Oldlist *)event_filters; l; l = l->next) { Ecore_Event_Filter *ef; ef = (Ecore_Event_Filter *)l; if (!ef->delete_me) { - Ecore_List *ll; + Ecore_Oldlist *ll; if (ef->func_start) ef->loop_data = ef->func_start(ef->data); - for (ll = (Ecore_List *)events; ll; ll = ll->next) + for (ll = (Ecore_Oldlist *)events; ll; ll = ll->next) { Ecore_Event *e; @@ -381,7 +381,7 @@ _ecore_event_call(void) } if (event_filters_delete_me) { - for (l = (Ecore_List *)event_filters; l;) + for (l = (Ecore_Oldlist *)event_filters; l;) { Ecore_Event_Filter *ef; @@ -396,9 +396,9 @@ _ecore_event_call(void) } event_filters_delete_me = 0; } - for (l = (Ecore_List *)events; l; l = l->next) + for (l = (Ecore_Oldlist *)events; l; l = l->next) { - Ecore_List *ll; + Ecore_Oldlist *ll; Ecore_Event *e; e = (Ecore_Event *)l; @@ -409,7 +409,7 @@ _ecore_event_call(void) handle_count = 0; ecore_raw_event_type = e->type; ecore_raw_event_event = e->event; - for (ll = (Ecore_List *)event_handlers; ll; ll = ll->next) + for (ll = (Ecore_Oldlist *)event_handlers; ll; ll = ll->next) { Ecore_Event_Handler *eh; @@ -434,7 +434,7 @@ _ecore_event_call(void) } while (events) _ecore_event_del(events); if (!event_handlers_delete_me) return; - for (l = (Ecore_List *)event_handlers; l;) + for (l = (Ecore_Oldlist *)event_handlers; l;) { Ecore_Event_Handler *eh; diff --git a/legacy/ecore/src/lib/ecore/ecore_exe.c b/legacy/ecore/src/lib/ecore/ecore_exe.c index 4f10d9a2a8..ad0503187e 100644 --- a/legacy/ecore/src/lib/ecore/ecore_exe.c +++ b/legacy/ecore/src/lib/ecore/ecore_exe.c @@ -237,9 +237,9 @@ _ecore_exe_shutdown(void) Ecore_Exe * _ecore_exe_find(pid_t pid) { - Ecore_List *l; + Ecore_Oldlist *l; - for (l = (Ecore_List *)exes; l; l = l->next) + for (l = (Ecore_Oldlist *)exes; l; l = l->next) { Ecore_Exe *exe; diff --git a/legacy/ecore/src/lib/ecore/ecore_hash.c b/legacy/ecore/src/lib/ecore/ecore_hash.c new file mode 100644 index 0000000000..a202c25332 --- /dev/null +++ b/legacy/ecore/src/lib/ecore/ecore_hash.c @@ -0,0 +1,648 @@ +#include + +#define ECORE_HASH_CHAIN_MAX 3 + +#define ECORE_COMPUTE_HASH(hash, key) hash->hash_func(key) % \ + ecore_prime_table[hash->size]; + +#define ECORE_HASH_INCREASE(hash) ((hash && hash->size < PRIME_MAX) ? \ + (hash->nodes / ecore_prime_table[hash->size]) > \ + ECORE_HASH_CHAIN_MAX : FALSE) +#define ECORE_HASH_REDUCE(hash) ((hash && hash->size > PRIME_MIN) ? \ + (double)hash->nodes / (double)ecore_prime_table[hash->size-1] \ + < ((double)ECORE_HASH_CHAIN_MAX * 0.375) : FALSE) + + +/* Private hash manipulation functions */ +static int _ecore_hash_add_node(Ecore_Hash *hash, Ecore_Hash_Node *node); +static Ecore_Hash_Node * _ecore_hash_get_node(Ecore_Hash *hash, void *key); +static int _ecore_hash_increase(Ecore_Hash *hash); +static int _ecore_hash_decrease(Ecore_Hash *hash); +inline int _ecore_hash_rehash(Ecore_Hash *hash, Ecore_List **old_table, int old_size); +static int _ecore_hash_bucket_destroy(Ecore_List *list, Ecore_Free_Cb keyd, + Ecore_Free_Cb valued); +inline Ecore_Hash_Node * _ecore_hash_get_bucket(Ecore_Hash *hash, Ecore_List *bucket, + void *key); + +static Ecore_Hash_Node *_ecore_hash_node_new(void *key, void *value); +static int _ecore_hash_node_init(Ecore_Hash_Node *node, void *key, void *value); +static int _ecore_hash_node_destroy(Ecore_Hash_Node *node, Ecore_Free_Cb keyd, + Ecore_Free_Cb valued); + + +/** + * ecore_hash_new - create and initialize a new hash + * @hash_func: the function for determining hash position + * @compare: the function for comparing node keys + * + * Returns NULL on error, a new hash on success + */ +Ecore_Hash *ecore_hash_new(Ecore_Hash_Cb hash_func, Ecore_Compare_Cb compare) +{ + Ecore_Hash *new_hash = (Ecore_Hash *)malloc(sizeof(Ecore_Hash)); + if (!new_hash) + return NULL; + + if (!ecore_hash_init(new_hash, hash_func, compare)) { + FREE(new_hash); + return NULL; + } + + return new_hash; +} + +/** + * ecore_hash_init - initialize a hash to some sane starting values + * @hash: the hash table to initialize + * @hash_func: the function for hashing node keys + * @compare: the function for comparing node keys + * + * Returns TRUE on success, FALSE on an error. + */ +int ecore_hash_init(Ecore_Hash *hash, Ecore_Hash_Cb hash_func, Ecore_Compare_Cb compare) +{ + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + + memset(hash, 0, sizeof(Ecore_Hash)); + + hash->hash_func = hash_func; + hash->compare = compare; + + hash->buckets = (Ecore_List **)malloc(ecore_prime_table[0] * + sizeof(Ecore_List *)); + memset(hash->buckets, 0, ecore_prime_table[0] * sizeof(Ecore_List *)); + + ECORE_INIT_LOCKS(hash); + + return TRUE; +} + +/** + * ecore_hash_set_free_key - set the function to destroy the keys of entries + * @hash: the hash that this will affect + * @function: the function that will free the node keys + * + * Returns TRUE on success, FALSE on error + */ +int ecore_hash_set_free_key(Ecore_Hash *hash, Ecore_Free_Cb function) +{ + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + CHECK_PARAM_POINTER_RETURN("function", function, FALSE); + + ECORE_WRITE_LOCK(hash); + hash->free_key = function; + ECORE_WRITE_UNLOCK(hash); + + return TRUE; +} + +/** + * ecore_hash_set_free_value - set the function to destroy the value + * @hash: the hash that this will affect + * @function: the function that will free the node values + * + * Returns TRUE on success, FALSE on error + */ +int ecore_hash_set_free_value(Ecore_Hash *hash, Ecore_Free_Cb function) +{ + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + CHECK_PARAM_POINTER_RETURN("function", function, FALSE); + + ECORE_WRITE_LOCK(hash); + hash->free_value = function; + ECORE_WRITE_UNLOCK(hash); + + return TRUE; +} + +/** + * ecore_hash_set - set the key/value pair in the hash table + * @hash: the hash table to set the the value in + * @key: the key for this value pair + * @value: the value corresponding with the key + * + * Returns TRUE if successful, FALSE if not + */ +int ecore_hash_set(Ecore_Hash *hash, void *key, void *value) +{ + int ret = FALSE; + Ecore_Hash_Node *node; + + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + + ECORE_WRITE_LOCK(hash); + node = _ecore_hash_get_node(hash, key); + if (node) + node->value = value; + else { + node = _ecore_hash_node_new(key, value); + if (node) + ret = _ecore_hash_add_node(hash, node); + } + ECORE_WRITE_UNLOCK(hash); + + return ret; +} + +/** + * ecore_hash_destroy - free the hash table and the data contained inside it + * @hash: the hash table to destroy + * + * Returns TRUE on success, FALSE on error + */ +void ecore_hash_destroy(Ecore_Hash *hash) +{ + int i = 0; + + CHECK_PARAM_POINTER("hash", hash); + + ECORE_WRITE_LOCK(hash); + + while (i < ecore_prime_table[hash->size]) { + if (hash->buckets[i]) + _ecore_hash_bucket_destroy(hash->buckets[i], + hash->free_key, hash->free_value); + i++; + } + + FREE(hash->buckets); + + ECORE_WRITE_UNLOCK(hash); + ECORE_DESTROY_LOCKS(hash); + + FREE(hash); + + return; +} + +/** + * ecore_hash_for_each - iterate over the entries in the hash table + */ +int ecore_hash_for_each_node(Ecore_Hash *hash, Ecore_For_Each for_each_func) +{ + int i = 0; + + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + CHECK_PARAM_POINTER_RETURN("for_each_func", for_each_func, FALSE); + + ECORE_READ_LOCK(hash); + + while (i < ecore_prime_table[hash->size]) { + if (hash->buckets[i]) { + Ecore_Hash_Node *node; + + ecore_list_goto_first(hash->buckets[i]); + while ((node = ecore_list_next(hash->buckets[i]))) { + for_each_func(node); + } + } + i++; + } + + ECORE_READ_UNLOCK(hash); + + return TRUE; +} + +/** + * ecore_hash_dump_graph - print the distribution of the hash table for graphing + * @hash: the hash table to print + * + * Returns no value. + */ +void +ecore_hash_dump_graph(Ecore_Hash *hash) +{ + int i; + + for (i = 0; i < ecore_prime_table[hash->size]; i++) + if (hash->buckets[i]) + printf("%d\t%u\n", i, ecore_list_nodes(hash->buckets[i])); + else + printf("%d\t0\n", i); +} + +static int +_ecore_hash_bucket_destroy(Ecore_List *list, Ecore_Free_Cb keyd, Ecore_Free_Cb valued) +{ + Ecore_Hash_Node *node; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + while ((node = ecore_list_remove_first(list)) != NULL) + _ecore_hash_node_destroy(node, keyd, valued); + + ecore_list_destroy(list); + + return TRUE; +} + +/* + * Description: Add the node to the hash table + * Parameters: 1. hash - the hash table to add the key + * 2. node - the node to add to the hash table + * Returns: FALSE on error, TRUE on success + */ +static int +_ecore_hash_add_node(Ecore_Hash *hash, Ecore_Hash_Node *node) +{ + unsigned int hash_val; + + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + /* Check to see if the hash needs to be resized */ + if (ECORE_HASH_INCREASE(hash)) + _ecore_hash_increase(hash); + + /* Compute the position in the table */ + if (!hash->hash_func) + hash_val = (unsigned int)node->key % + ecore_prime_table[hash->size]; + else + hash_val = ECORE_COMPUTE_HASH(hash, node->key); + + /* Create the list if it's not already present */ + if (!hash->buckets[hash_val]) + hash->buckets[hash_val] = ecore_list_new(); + + /* Append the node to the list at the index position */ + if (!ecore_list_prepend(hash->buckets[hash_val], node)) + return FALSE; + hash->nodes++; + + return TRUE; +} + +/** + * ecore_hash_get - retrieve the value associated with key + * @hash: the hash table to search for the key + * @key: the key to search for in the hash table + * + * Returns NULL on error, value corresponding to key on success + */ +void *ecore_hash_get(Ecore_Hash *hash, void *key) +{ + void *data; + Ecore_Hash_Node *node; + + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + + node = _ecore_hash_get_node(hash, key); + if (!node) + return NULL; + + ECORE_READ_LOCK(node); + data = node->value; + ECORE_READ_UNLOCK(node); + + return data; +} + + +/** + * ecore_hash_remove - remove the value associated with key + * @hash: the hash table to remove the key from + * @key: the key to search for in the hash table + * + * Returns NULL on error, value corresponding to key on success + */ +void *ecore_hash_remove(Ecore_Hash *hash, void *key) +{ + Ecore_Hash_Node *node = NULL; + Ecore_List *list; + unsigned int hash_val; + void *ret = NULL; + + CHECK_PARAM_POINTER_RETURN("hash", hash, NULL); + + ECORE_WRITE_LOCK(hash); + + /* Compute the position in the table */ + if (!hash->hash_func) + hash_val = (unsigned int)key % ecore_prime_table[hash->size]; + else + hash_val = ECORE_COMPUTE_HASH(hash, key); + + /* + * If their is a list that could possibly hold the key/value pair + * traverse it and remove the hash node. + */ + if (hash->buckets[hash_val]) { + list = hash->buckets[hash_val]; + ecore_list_goto_first(list); + + /* + * Traverse the list to find the specified key + */ + if (hash->compare) { + while ((node = ecore_list_current(list)) && + hash->compare(node->key, key) != 0) + ecore_list_next(list); + } + else { + while ((node = ecore_list_current(list)) && + node->key != key) + ecore_list_next(list); + } + + if (node) { + ecore_list_remove(list); + + ret = node->value; + FREE(node); + } + } + + if (ECORE_HASH_REDUCE(hash)) + _ecore_hash_decrease(hash); + + ECORE_WRITE_UNLOCK(hash); + + return ret; +} + +/* + * Description: Retrieve the node associated with key + * Parameters: 1. hash - the hash table to search for the key + * 2. key - the key to search for in the hash table + * Returns: NULL on error, node corresponding to key on success + */ +static Ecore_Hash_Node * +_ecore_hash_get_node(Ecore_Hash *hash, void *key) +{ + unsigned int hash_val; + Ecore_Hash_Node *node = NULL; + + CHECK_PARAM_POINTER_RETURN("hash", hash, NULL); + + ECORE_READ_LOCK(hash); + + /* Compute the position in the table */ + if (!hash->hash_func) + hash_val = (unsigned int)key % ecore_prime_table[hash->size]; + else + hash_val = ECORE_COMPUTE_HASH(hash, key); + + /* Grab the bucket at the specified position */ + if (hash->buckets[hash_val]) + node = _ecore_hash_get_bucket(hash, hash->buckets[hash_val], key); + + ECORE_READ_UNLOCK(hash); + + return node; +} + +/* + * Description: Search the hash bucket for a specified key + * Parameters: 1. hash - the hash table to retrieve the comparison function + * 2. bucket - the list to search for the key + * 3. key - the key to search for in the list + * Returns: NULL on error or not found, the found node on success + */ +inline Ecore_Hash_Node * +_ecore_hash_get_bucket(Ecore_Hash *hash, Ecore_List *bucket, void *key) +{ + Ecore_Hash_Node *node = NULL; + + ECORE_READ_LOCK(hash); + ecore_list_goto_first(bucket); + + /* + * Traverse the list to find the desired node, if the node is in the + * list, then return the node. + */ + if (hash->compare) { + while ((node = ecore_list_next(bucket)) != NULL) { + ECORE_READ_LOCK(node); + if (hash->compare(node->key, key) == 0) { + ECORE_READ_UNLOCK(node); + ECORE_READ_UNLOCK(hash); + return node; + } + ECORE_READ_UNLOCK(node); + } + } + else { + while ((node = ecore_list_next(bucket)) != NULL) { + ECORE_READ_LOCK(node); + if (node->key == key) { + ECORE_READ_UNLOCK(node); + ECORE_READ_UNLOCK(hash); + return node; + } + ECORE_READ_UNLOCK(node); + } + } + ECORE_READ_UNLOCK(hash); + + return NULL; +} + +/* + * Description: Increase the size of the hash table by approx. 2 * current size + * Parameters: 1. hash - the hash table to increase the size of + * Returns: TRUE on success, FALSE on error + */ +static int +_ecore_hash_increase(Ecore_Hash *hash) +{ + void *old; + + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + + /* Max size reached so return FALSE */ + if (hash->size == PRIME_TABLE_MAX) + return FALSE; + + /* + * Increase the size of the hash and save a pointer to the old data + */ + hash->size++; + old = hash->buckets; + + /* + * Allocate a new bucket area, of the new larger size + */ + hash->buckets = (Ecore_List **)calloc(ecore_prime_table[hash->size], + sizeof(Ecore_List *)); + + /* + * Make sure the allocation succeeded, if not replace the old data and + * return a failure. + */ + if (!hash->buckets) { + hash->buckets = old; + hash->size--; + return FALSE; + } + hash->nodes = 0; + + /* + * Now move all of the old data into the new bucket area + */ + if (_ecore_hash_rehash(hash, old, hash->size - 1)) { + FREE(old); + return TRUE; + } + + /* + * Free the old buckets regardless of success. + */ + FREE(old); + + return FALSE; +} + +/* + * Description: Decrease the size of the hash table by < 1/2 * current size + * Parameters: 1. hash - the hash table to decrease the size of + * Returns: TRUE on success, FALSE on error + */ +static int +_ecore_hash_decrease(Ecore_Hash *hash) +{ + Ecore_List **old; + + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + + if (ecore_prime_table[hash->size] == PRIME_MIN) + return FALSE; + + /* + * Decrease the hash size and store a pointer to the old data + */ + hash->size--; + old = hash->buckets; + + /* + * Allocate a new area to store the data + */ + hash->buckets = (Ecore_List **)malloc(ecore_prime_table[hash->size] * + sizeof(Ecore_List *)); + + /* + * Make sure allocation succeeded otherwise rreturn to the previous + * state + */ + if (!hash->buckets) { + hash->buckets = old; + hash->size++; + return FALSE; + } + + /* + * Zero out the new area + */ + memset(hash->buckets, 0, ecore_prime_table[hash->size] + * sizeof(Ecore_List *)); + hash->nodes = 0; + + if (_ecore_hash_rehash(hash, old, hash->size - 1)) { + FREE(old); + return TRUE; + } + + return FALSE; +} + +/* + * Description: Rehash the nodes of a table into the hash table + * Parameters: 1. hash - the hash to place the nodes of the table + * 2. table - the table to remove the nodes from and place in hash + * Returns: TRUE on success, FALSE on success + */ +inline int +_ecore_hash_rehash(Ecore_Hash *hash, Ecore_List **old_table, int old_size) +{ + int i; + Ecore_Hash_Node *node; + Ecore_List *old; + + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + CHECK_PARAM_POINTER_RETURN("old_table", old_table, FALSE); + + for (i = 0; i < ecore_prime_table[old_size]; i++) { + /* Hash into a new list to avoid loops of rehashing the same + * nodes */ + old = old_table[i]; + old_table[i] = NULL; + + /* Loop through re-adding each node to the hash table */ + while (old && (node = ecore_list_remove_last(old))) { + _ecore_hash_add_node(hash, node); + } + + /* Now free up the old list space */ + if (old) + ecore_list_destroy(old); + } + + return TRUE; +} + +/* + * Description: Create a new hash node for key and value storage + * Parameters: 1. key - the key for this node + * 2. value - the value that the key references + * Returns: NULL on error, a new hash node on success + */ +static Ecore_Hash_Node * +_ecore_hash_node_new(void *key, void *value) +{ + Ecore_Hash_Node *node; + + node = (Ecore_Hash_Node *)malloc(sizeof(Ecore_Hash_Node)); + if (!node) + return NULL; + + if (!_ecore_hash_node_init(node, key, value)) { + FREE(node); + return NULL; + } + + return node; +} + +/* + * Description: Initialize a hash node to some sane default values + * Parameters: 1. node - the node to set the values + * 2. key - the key to reference this node + * 3. value - the value that key refers to + * Returns: TRUE on success, FALSE on error + */ +static int +_ecore_hash_node_init(Ecore_Hash_Node *node, void *key, void *value) +{ + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + ECORE_INIT_LOCKS(node); + node->key = key; + node->value = value; + + return TRUE; +} + +/* + * Description: Destroy a node and call the specified callbacks to free data + * Parameters: 1. node - the node to be destroyed + * 2. keyd - the function to free the key + * 3. valued - the function to free the value + * Returns: TRUE on success, FALSE on error + */ +static int +_ecore_hash_node_destroy(Ecore_Hash_Node *node, Ecore_Free_Cb keyd, + Ecore_Free_Cb valued) +{ + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + if (keyd) + keyd(node->key); + + if (valued) + valued(node->value); + + FREE(node); + + return TRUE; +} diff --git a/legacy/ecore/src/lib/ecore/ecore_idle_enterer.c b/legacy/ecore/src/lib/ecore/ecore_idle_enterer.c index a52dbd4380..16143ce119 100644 --- a/legacy/ecore/src/lib/ecore/ecore_idle_enterer.c +++ b/legacy/ecore/src/lib/ecore/ecore_idle_enterer.c @@ -75,9 +75,9 @@ _ecore_idle_enterer_shutdown(void) void _ecore_idle_enterer_call(void) { - Ecore_List *l; + Ecore_Oldlist *l; - for (l = (Ecore_List *)idle_enterers; l; l = l->next) + for (l = (Ecore_Oldlist *)idle_enterers; l; l = l->next) { Ecore_Idle_Enterer *ie; @@ -89,7 +89,7 @@ _ecore_idle_enterer_call(void) } if (idle_enterers_delete_me) { - for (l = (Ecore_List *)idle_enterers; l;) + for (l = (Ecore_Oldlist *)idle_enterers; l;) { Ecore_Idle_Enterer *ie; diff --git a/legacy/ecore/src/lib/ecore/ecore_idle_exiter.c b/legacy/ecore/src/lib/ecore/ecore_idle_exiter.c index c6d123abdc..da45db166c 100644 --- a/legacy/ecore/src/lib/ecore/ecore_idle_exiter.c +++ b/legacy/ecore/src/lib/ecore/ecore_idle_exiter.c @@ -72,9 +72,9 @@ _ecore_idle_exiter_shutdown(void) void _ecore_idle_exiter_call(void) { - Ecore_List *l; + Ecore_Oldlist *l; - for (l = (Ecore_List *)idle_exiters; l; l = l->next) + for (l = (Ecore_Oldlist *)idle_exiters; l; l = l->next) { Ecore_Idle_Exiter *ie; @@ -86,7 +86,7 @@ _ecore_idle_exiter_call(void) } if (idle_exiters_delete_me) { - for (l = (Ecore_List *)idle_exiters; l;) + for (l = (Ecore_Oldlist *)idle_exiters; l;) { Ecore_Idle_Exiter *ie; diff --git a/legacy/ecore/src/lib/ecore/ecore_idler.c b/legacy/ecore/src/lib/ecore/ecore_idler.c index bae74d88c8..ed0b3ba675 100644 --- a/legacy/ecore/src/lib/ecore/ecore_idler.c +++ b/legacy/ecore/src/lib/ecore/ecore_idler.c @@ -76,9 +76,9 @@ _ecore_idler_shutdown(void) int _ecore_idler_call(void) { - Ecore_List *l; + Ecore_Oldlist *l; - for (l = (Ecore_List *)idlers; l; l = l->next) + for (l = (Ecore_Oldlist *)idlers; l; l = l->next) { Ecore_Idler *ie; @@ -90,7 +90,7 @@ _ecore_idler_call(void) } if (idlers_delete_me) { - for (l = (Ecore_List *)idlers; l;) + for (l = (Ecore_Oldlist *)idlers; l;) { Ecore_Idler *ie; diff --git a/legacy/ecore/src/lib/ecore/ecore_list.c b/legacy/ecore/src/lib/ecore/ecore_list.c index 2048a19e7c..f064445a66 100644 --- a/legacy/ecore/src/lib/ecore/ecore_list.c +++ b/legacy/ecore/src/lib/ecore/ecore_list.c @@ -1,11 +1,40 @@ #include "ecore_private.h" #include "Ecore.h" +/* Return information about the list */ +static void *_ecore_list_current(Ecore_List * list); + +/* Adding functions */ +static int _ecore_list_insert(Ecore_List * list, Ecore_List_Node *node); +static int _ecore_list_append_0(Ecore_List * list, Ecore_List_Node *node); +static int _ecore_list_prepend_0(Ecore_List * list, Ecore_List_Node *node); + +/* Remove functions */ +static void *_ecore_list_remove_0(Ecore_List * list); +static void *_ecore_list_remove_first(Ecore_List * list); +static void *_ecore_list_remove_last(Ecore_List * list); + +/* Basic traversal functions */ +static void *_ecore_list_next(Ecore_List * list); +static void *_ecore_list_goto_last(Ecore_List * list); +static void *_ecore_list_goto_first(Ecore_List * list); +static void *_ecore_list_goto(Ecore_List * list, void *data); +static void *_ecore_list_goto_index(Ecore_List *list, int index); + +/* Iterative function */ +static int _ecore_list_for_each(Ecore_List *list, Ecore_For_Each function); + +/* Private double linked list functions */ +static void *_ecore_dlist_previous(Ecore_DList * list); +static void *_ecore_dlist_remove_first(Ecore_DList *list); +static void *_ecore_dlist_goto_index(Ecore_DList *list, int index); + +/* XXX: Begin deprecated code */ void * _ecore_list_append(void *in_list, void *in_item) { - Ecore_List *l, *new_l; - Ecore_List *list, *item; + Ecore_Oldlist *l, *new_l; + Ecore_Oldlist *list, *item; list = in_list; item = in_item; @@ -28,8 +57,8 @@ _ecore_list_append(void *in_list, void *in_item) void * _ecore_list_prepend(void *in_list, void *in_item) { - Ecore_List *new_l; - Ecore_List *list, *item; + Ecore_Oldlist *new_l; + Ecore_Oldlist *list, *item; list = in_list; item = in_item; @@ -51,8 +80,8 @@ _ecore_list_prepend(void *in_list, void *in_item) void * _ecore_list_append_relative(void *in_list, void *in_item, void *in_relative) { - Ecore_List *l; - Ecore_List *list, *item, *relative; + Ecore_Oldlist *l; + Ecore_Oldlist *list, *item, *relative; list = in_list; item = in_item; @@ -61,7 +90,7 @@ _ecore_list_append_relative(void *in_list, void *in_item, void *in_relative) { if (l == relative) { - Ecore_List *new_l; + Ecore_Oldlist *new_l; new_l = item; if (l->next) @@ -84,8 +113,8 @@ _ecore_list_append_relative(void *in_list, void *in_item, void *in_relative) void * _ecore_list_prepend_relative(void *in_list, void *in_item, void *in_relative) { - Ecore_List *l; - Ecore_List *list, *item, *relative; + Ecore_Oldlist *l; + Ecore_Oldlist *list, *item, *relative; list = in_list; item = in_item; @@ -94,7 +123,7 @@ _ecore_list_prepend_relative(void *in_list, void *in_item, void *in_relative) { if (l == relative) { - Ecore_List *new_l; + Ecore_Oldlist *new_l; new_l = item; new_l->prev = l->prev; @@ -126,8 +155,8 @@ _ecore_list_prepend_relative(void *in_list, void *in_item, void *in_relative) void * _ecore_list_remove(void *in_list, void *in_item) { - Ecore_List *return_l; - Ecore_List *list, *item; + Ecore_Oldlist *return_l; + Ecore_Oldlist *list, *item; /* checkme */ if(!in_list) @@ -159,8 +188,8 @@ _ecore_list_remove(void *in_list, void *in_item) void * _ecore_list_find(void *in_list, void *in_item) { - Ecore_List *l; - Ecore_List *list, *item; + Ecore_Oldlist *l; + Ecore_Oldlist *list, *item; list = in_list; item = in_item; @@ -170,3 +199,1410 @@ _ecore_list_find(void *in_list, void *in_item) } return NULL; } +/* XXX: End deprecated code */ + +/** + * ecore_list_new - create and initialize a new list. + * + * Returns a new initialized list on success, NULL on failure. + */ +Ecore_List *ecore_list_new() +{ + Ecore_List *list; + + list = (Ecore_List *)malloc(sizeof(Ecore_List)); + if (!list) + return NULL; + + if (!ecore_list_init(list)) { + FREE(list); + return NULL; + } + + return list; +} + +/** + * ecore_list_init - initialize a list to some sane starting values. + * @list: the list to initialize + * + * Returns FALSE if an error occurs, TRUE if successful + */ +int ecore_list_init(Ecore_List *list) +{ + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + memset(list, 0, sizeof(Ecore_List)); + + ECORE_INIT_LOCKS(list); + + return TRUE; +} + +/** + * ecore_list_destroy - Free a list and all of it's nodes. + * @list: the list to be freed + * + * Returns no value + */ +void ecore_list_destroy(Ecore_List * list) +{ + void *data; + + CHECK_PARAM_POINTER("list", list); + + ECORE_WRITE_LOCK(list); + + while (list->first) { + data = _ecore_list_remove_first(list); + if (list->free_func) + list->free_func(data); + } + + ECORE_WRITE_UNLOCK(list); + ECORE_DESTROY_LOCKS(list); + + FREE(list); +} + +/** + * ecore_list_set_free_cb - set the function for freeing data + * @list: the list that will use this function when nodes are destroyed. + * @free_func: the function that will free the key data + * + * Returns TRUE on successful set, FALSE otherwise. + */ +int ecore_list_set_free_cb(Ecore_List * list, Ecore_Free_Cb free_func) +{ + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + + list->free_func = free_func; + + ECORE_WRITE_UNLOCK(list); + + return TRUE; +} + +/** + * ecore_list_is_empty - checks the list for any nodes. + * @list: the list to check for nodes + * + * Returns TRUE if no nodes in list, FALSE if the list contains nodes + */ +int ecore_list_is_empty(Ecore_List * list) +{ + int ret = TRUE; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_READ_LOCK(list); + + if (list->nodes) + ret = FALSE; + + ECORE_READ_UNLOCK(list); + + return ret; +} + +/** + * ecore_list_index - returns the number of the current node + * @list: the list to return the number of the current node + * + * Returns the number of the current node in the list. + */ +int ecore_list_index(Ecore_List * list) +{ + int ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_READ_LOCK(list); + + ret = list->index; + + ECORE_READ_UNLOCK(list); + + return ret; +} + +/** + * ecore_list_nodes - find the number of nodes in the list. + * @list: the list to find the number of nodes + * + * Returns the number of nodes in the list. + */ +int ecore_list_nodes(Ecore_List * list) +{ + int ret = 0; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_READ_LOCK(list); + + ret = list->nodes; + + ECORE_READ_UNLOCK(list); + + return ret; +} + +/** + * ecore_list_append - append data to the list. + * @list: the list to append @data + * @data: the data to append to @list. + * + * Returns FALSE if an error occurs, TRUE if @data is appended successfully + */ +inline int ecore_list_append(Ecore_List * list, void *data) +{ + int ret; + Ecore_List_Node *node; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + node = ecore_list_node_new(); + node->data = data; + + ECORE_WRITE_LOCK(list); + + ret = _ecore_list_append_0(list, node); + + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/* For adding items to the end of the list */ +static int _ecore_list_append_0(Ecore_List * list, Ecore_List_Node *end) +{ + if (list->last) { + ECORE_WRITE_LOCK(list->last); + list->last->next = end; + ECORE_WRITE_UNLOCK(list->last); + } + + list->last = end; + + if (list->first == NULL) { + list->first = end; + list->index = 1; + } + + list->nodes++; + + return TRUE; +} + +/** + * ecore_list_prepend - prepend data to the beginning of the list + * @list: the list to prepend @data + * @data: the data to prepend to @list + * + * Returns FALSE if an error occurs, TRUE if data prepended successfully + */ +inline int ecore_list_prepend(Ecore_List * list, void *data) +{ + int ret; + Ecore_List_Node *node; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + node = ecore_list_node_new(); + node->data = data; + + ECORE_WRITE_LOCK(list); + ret = _ecore_list_prepend_0(list, node); + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/* For adding items to the beginning of the list */ +static int _ecore_list_prepend_0(Ecore_List * list, Ecore_List_Node *start) +{ + /* Put it at the beginning of the list */ + ECORE_WRITE_LOCK(start); + start->next = list->first; + ECORE_WRITE_UNLOCK(start); + + list->first = start; + + /* If no last node, then the first node is the last node */ + if (list->last == NULL) + list->last = list->first; + + list->nodes++; + list->index++; + + return TRUE; +} + +/** + * ecore_list_insert - insert data at the current point in the list + * @list: the list to hold the inserted @data + * @data: the data to insert into @list + * + * Returns FALSE on an error, TRUE on success + */ +inline int ecore_list_insert(Ecore_List * list, void *data) +{ + int ret; + Ecore_List_Node *node; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + node = ecore_list_node_new(); + node->data = data; + + ECORE_WRITE_LOCK(list); + ret = _ecore_list_insert(list, node); + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/* For adding items in front of the current position in the list */ +static int _ecore_list_insert(Ecore_List * list, Ecore_List_Node *new_node) +{ + /* + * If the current point is at the beginning of the list, then it's the + * same as prepending it to the list. + */ + if (list->current == list->first) + return _ecore_list_prepend_0(list, new_node); + + if (list->current == NULL) { + int ret_value; + + ret_value = _ecore_list_append_0(list, new_node); + list->current = list->last; + + return ret_value; + } + + /* Setup the fields of the new node */ + ECORE_WRITE_LOCK(new_node); + new_node->next = list->current; + ECORE_WRITE_UNLOCK(new_node); + + /* And hook the node into the list */ + _ecore_list_goto_index(list, ecore_list_index(list) - 1); + + ECORE_WRITE_LOCK(list->current); + list->current->next = new_node; + ECORE_WRITE_UNLOCK(list->current); + + /* Now move the current item to the inserted item */ + list->current = new_node; + list->index++; + list->nodes++; + + return TRUE; +} + +/** + * ecore_list_remove - remove the current item from the list. + * @list: the list to remove the current item + * + * Returns a pointer to the removed data on success, NULL on failure. + */ +inline void *ecore_list_remove(Ecore_List * list) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + ret = _ecore_list_remove_0(list); + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/* Remove the current item from the list */ +static void *_ecore_list_remove_0(Ecore_List * list) +{ + void *ret = NULL; + Ecore_List_Node *old; + + if (!list) + return FALSE; + + if (ecore_list_is_empty(list)) + return FALSE; + + if (!list->current) + return FALSE; + + if (list->current == list->first) + return _ecore_list_remove_first(list); + + if (list->current == list->last) + return _ecore_list_remove_last(list); + + old = list->current; + + _ecore_list_goto_index(list, list->index - 1); + + ECORE_WRITE_LOCK(list->current); + ECORE_WRITE_LOCK(old); + + list->current->next = old->next; + old->next = NULL; + ret = old->data; + old->data = NULL; + + _ecore_list_next(list); + + ECORE_WRITE_UNLOCK(old); + ECORE_WRITE_UNLOCK(list->current); + + ecore_list_node_destroy(old, NULL); + list->nodes--; + + return ret; +} + +/** + * ecore_list_remove_destroy - remove and free the data in lists current position + * @list: the list to remove and free the current item + * + * Returns TRUE on success, FALSE on error + */ +int ecore_list_remove_destroy(Ecore_List *list) +{ + void *data; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + data = _ecore_list_remove_0(list); + if (list->free_func) + list->free_func(data); + + ECORE_WRITE_UNLOCK(list); + + return TRUE; +} + +/** + * ecore_list_remove_first - remove the first item from the list. + * @list: the list to remove the current item + * + * Returns a pointer to the removed data on success, NULL on failure. + */ +inline void *ecore_list_remove_first(Ecore_List * list) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + ret = _ecore_list_remove_first(list); + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/* Remove the first item from the list */ +static void *_ecore_list_remove_first(Ecore_List * list) +{ + void *ret = NULL; + Ecore_List_Node *old; + + if (!list) + return FALSE; + + ECORE_WRITE_UNLOCK(list); + if (ecore_list_is_empty(list)) + return FALSE; + ECORE_WRITE_LOCK(list); + + if (!list->first) + return FALSE; + + old = list->first; + + list->first = list->first->next; + + if (list->current == old) + list->current = list->first; + else + list->index--; + + if (list->last == old) + list->last = list->first; + + ECORE_WRITE_LOCK(old); + ret = old->data; + old->data = NULL; + ECORE_WRITE_UNLOCK(old); + + ecore_list_node_destroy(old, NULL); + list->nodes--; + + return ret; +} + +/** + * ecore_list_remove_first - remove the last item from the list. + * @list: the list to remove the last node from + * + * Returns a pointer to the removed data on success, NULL on failure. + */ +inline void *ecore_list_remove_last(Ecore_List * list) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + ret = _ecore_list_remove_last(list); + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/* Remove the last item from the list */ +static void *_ecore_list_remove_last(Ecore_List * list) +{ + void *ret = NULL; + Ecore_List_Node *old, *prev; + + if (!list) + return FALSE; + + if (ecore_list_is_empty(list)) + return FALSE; + + if (!list->last) + return FALSE; + + old = list->last; + if (list->current == old) + list->current = NULL; + + if (list->first == old) + list->first = NULL; + for (prev = list->first; prev && prev->next != old; prev = prev->next); + if (prev) { + prev->next = NULL; + list->last = prev; + if (list->current == old) { + list->current = NULL; + } + } + + + ECORE_WRITE_LOCK(old); + if (old) { + old->next = NULL; + ret = old->data; + old->data = NULL; + } + ECORE_WRITE_UNLOCK(old); + + ecore_list_node_destroy(old, NULL); + list->nodes--; + + return ret; +} + +/** + * ecore_list_goto_index - move the current item to the index number + * @list: the list to move the current item + * @index: the position to move the current item + * + * Returns a pointer to the new current item on success, NULL on failure. + */ +inline void *ecore_list_goto_index(Ecore_List * list, int index) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + ret = _ecore_list_goto_index(list, index); + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/* This is the non-threadsafe version, use this inside internal functions that + * already lock the list */ +static void *_ecore_list_goto_index(Ecore_List *list, int index) +{ + int i; + + if (!list) + return FALSE; + + if (ecore_list_is_empty(list)) + return FALSE; + + if (index > ecore_list_nodes(list) || index < 0) + return FALSE; + + _ecore_list_goto_first(list); + + for (i = 1; i < index && _ecore_list_next(list); i++); + + list->index = i; + + return list->current->data; +} + +/** + * ecore_list_goto - move the current item to the node that contains data + * @list: the list to move the current item in + * @data: the data to find and set the current item to + * + * Returns a pointer to @data on success, NULL on failure. + */ +inline void *ecore_list_goto(Ecore_List * list, void *data) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + ret = _ecore_list_goto(list, data); + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/* Set the current position to the node containing data */ +static void *_ecore_list_goto(Ecore_List * list, void *data) +{ + int index; + Ecore_List_Node *node; + + if (!list) + return NULL; + + index = 1; + + node = list->first; + ECORE_READ_LOCK(node); + while (node && node->data) { + Ecore_List_Node *next; + + if (node->data == data) + break; + + next = node->next; + ECORE_READ_UNLOCK(node); + + node = next; + + ECORE_READ_LOCK(node); + index++; + } + + ECORE_READ_UNLOCK(node); + if (!node) + return NULL; + + list->current = node; + list->index = index; + + return list->current->data; +} + +/** + * ecore_list_goto_first - move the current pointer to the first item in the list + * @list: the list to move the current pointer in + * + * Returns a pointer to the first item on success, NULL on failure + */ +inline void *ecore_list_goto_first(Ecore_List *list) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + + ret = _ecore_list_goto_first(list); + + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/* Set the current position to the start of the list */ +static void *_ecore_list_goto_first(Ecore_List * list) +{ + if (!list || !list->first) + return NULL; + + list->current = list->first; + list->index = 1; + + return list->current->data; +} + +/** + * ecore_list_goto_last - move the pointer to current to the last item in the list + * @list: the list to move the current pointer in + * + * Returns a pointer to the last item on success, NULL on failure. + */ +inline void *ecore_list_goto_last(Ecore_List * list) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + ret = _ecore_list_goto_last(list); + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/* Set the current position to the end of the list */ +static void *_ecore_list_goto_last(Ecore_List * list) +{ + if (!list || !list->last) + return NULL; + + list->current = list->last; + list->index = list->nodes; + + return list->current->data; +} + +/** + * ecore_list_current - retrieve the data in the current node + * @list: the list to retrieve the current data from + * + * Returns the data at the current position on success, NULL on failure or if + * no current item set. + */ +inline void *ecore_list_current(Ecore_List * list) +{ + void *ret; + + ECORE_READ_LOCK(list); + ret = _ecore_list_current(list); + ECORE_READ_UNLOCK(list); + + return ret; +} + +/* Return the data of the current node without incrementing */ +static void *_ecore_list_current(Ecore_List * list) +{ + void *ret; + + if (!list->current) + return NULL; + + ECORE_READ_LOCK(list->current); + ret = list->current->data; + ECORE_READ_UNLOCK(list->current); + + return ret; +} + +/** + * ecore_list_next - retrieve the data at the current node and move to the next + * @list: the list to move to the next item + * + * Returns the current item in the list on success, NULL on failure. + */ +inline void *ecore_list_next(Ecore_List * list) +{ + void *data; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + data = _ecore_list_next(list); + ECORE_WRITE_UNLOCK(list); + + return data; +} + +/* Return the data contained in the current node and go to the next node */ +static void *_ecore_list_next(Ecore_List * list) +{ + void *data; + Ecore_List_Node *ret; + Ecore_List_Node *next; + + if (!list->current) + return NULL; + + ECORE_READ_LOCK(list->current); + ret = list->current; + next = list->current->next; + ECORE_READ_UNLOCK(list->current); + + list->current = next; + list->index++; + + ECORE_READ_LOCK(ret); + data = ret->data; + ECORE_READ_UNLOCK(ret); + + return data; +} + +/** + * ecore_list_clear - remove all nodes from the list + * @list: the list that will have it's nodes removed + * + * Returns TRUE on success, FALSE on error. The data for each item on the list + * is not freed by ecore_list_clear. + */ +int ecore_list_clear(Ecore_List * list) +{ + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + + while (!ecore_list_is_empty(list)) + _ecore_list_remove_first(list); + + ECORE_WRITE_UNLOCK(list); + + return TRUE; +} + +/** + * ecore_list_for_each - execute function for each node in the list. + * @list: the list to retrieve nodes from. + * @function: The function to pass each node from the list to. + * + * Returns TRUE on success, FALSE on failure. + */ +int ecore_list_for_each(Ecore_List *list, Ecore_For_Each function) +{ + int ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_READ_LOCK(list); + ret = _ecore_list_for_each(list, function); + ECORE_READ_UNLOCK(list); + + return ret; +} + +/* The real meat of executing the function for each data node */ +static int _ecore_list_for_each(Ecore_List *list, Ecore_For_Each function) +{ + void *value; + + if (!list || !function) + return FALSE; + + _ecore_list_goto_first(list); + while ((value = _ecore_list_next(list)) != NULL) + function(value); + + return TRUE; +} + +/* Initialize a node to starting values */ +int ecore_list_node_init(Ecore_List_Node * node) +{ + + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + node->next = NULL; + node->data = NULL; + + ECORE_INIT_LOCKS(node); + + return TRUE; +} + +/* Allocate and initialize a new list node */ +Ecore_List_Node *ecore_list_node_new() +{ + Ecore_List_Node *new_node; + + new_node = malloc(sizeof(Ecore_List_Node)); + + if (!ecore_list_node_init(new_node)) { + FREE(new_node); + return NULL; + } + + return new_node; +} + +/* Here we actually call the function to free the data and free the node */ +int ecore_list_node_destroy(Ecore_List_Node * node, Ecore_Free_Cb free_func) +{ + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + ECORE_WRITE_LOCK(node); + + if (free_func && node->data) + free_func(node->data); + + ECORE_WRITE_UNLOCK(node); + ECORE_DESTROY_LOCKS(node); + + FREE(node); + + return TRUE; +} + +/** + * ecore_dlist_new - create and initialize a new list. + * + * Returns a new initialized list on success, NULL on failure. + */ +Ecore_DList *ecore_dlist_new() +{ + Ecore_DList *list = NULL; + + list = (Ecore_DList *)malloc(sizeof(Ecore_DList)); + if (!list) + return NULL; + + if (!ecore_dlist_init(list)) { + IF_FREE(list); + return NULL; + } + + return list; +} + +/** + * ecore_dlist_init - initialize a list to some sane starting values. + * @list: the list to initialize + * + * Returns FALSE if an error occurs, TRUE if successful + */ +int ecore_dlist_init(Ecore_DList *list) +{ + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + memset(list, 0, sizeof(Ecore_DList)); + + ECORE_INIT_LOCKS(list); + + return TRUE; +} + +/** + * ecore_dlist_destroy - free a list and all of it's nodes. + * @list: the list to be freed + * + * Returns no value + */ +void ecore_dlist_destroy(Ecore_DList * list) +{ + void *data; + CHECK_PARAM_POINTER("list", list); + + ECORE_WRITE_LOCK(list); + + while (list->first) { + data = _ecore_dlist_remove_first(list); + if (list->free_func) + list->free_func(data); + } + + ECORE_WRITE_UNLOCK(list); + ECORE_DESTROY_LOCKS(list); + + FREE(list); +} + +/** + * ecore_dlist_set_free_cb - set the function for freeing data + * @list: the list that will use this function when nodes are destroyed. + * @free_func: the function that will free the key data + * + * Returns TRUE on success, FALSE on failure. + */ +int ecore_dlist_set_free_cb(Ecore_DList * list, Ecore_Free_Cb free_func) +{ + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + return ecore_list_set_free_cb(ECORE_LIST(list), free_func); +} + +/** + * ecore_dlist_is_empty - checks the list for any nodes. + * @list: the list to check for nodes + * + * Returns TRUE if no nodes in list, FALSE if the list contains nodes + */ +int ecore_dlist_is_empty(Ecore_DList * list) +{ + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + return ecore_list_is_empty(ECORE_LIST(list)); +} + +/** + * ecore_dlist_index - returns the number of the current node + * @list: the list to return the number of the current node + * + * Returns the number of the current node in the list. + */ +inline int ecore_dlist_index(Ecore_DList * list) +{ + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + return ecore_list_index(ECORE_LIST(list)); +} + +/** + * ecore_dlist_append - append data to the list. + * @list: the list to append @data + * @data: the data to append to @list + * + * Returns FALSE if an error occurs, TRUE if the data is appended successfully + */ +int ecore_dlist_append(Ecore_DList * list, void *data) +{ + int ret; + Ecore_DList_Node *prev; + Ecore_DList_Node *node; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + + node = ecore_dlist_node_new(); + ECORE_LIST_NODE(node)->data = data; + + prev = ECORE_DLIST_NODE(ECORE_LIST(list)->last); + ret = _ecore_list_append_0(ECORE_LIST(list), ECORE_LIST_NODE(node)); + if (ret) { + node->previous = prev; + } + + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/** + * ecore_dlist_prepend - prepend data to the beginning of the list + * @list: the list to prepend @data + * @data: the data to prepend to @list + * + * Returns FALSE if an error occurs, TRUE if data prepended successfully + */ +int ecore_dlist_prepend(Ecore_DList * list, void *data) +{ + int ret; + Ecore_DList_Node *prev; + Ecore_DList_Node *node; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + + node = ecore_dlist_node_new(); + ECORE_LIST_NODE(node)->data = data; + + prev = ECORE_DLIST_NODE(ECORE_LIST(list)->first); + ret = _ecore_list_prepend_0(ECORE_LIST(list), ECORE_LIST_NODE(node)); + if (ret && prev) + prev->previous = node; + + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/** + * ecore_dlist_insert - insert data at the current point in the list + * @list: the list to hold the inserted @data + * @data: the data to insert into @list + * + * Returns FALSE on an error, TRUE on success + */ +int ecore_dlist_insert(Ecore_DList * list, void *data) +{ + int ret; + Ecore_DList_Node *prev; + Ecore_DList_Node *node; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + + prev = ECORE_DLIST_NODE(ECORE_LIST(list)->current); + if (!prev) + prev = ECORE_DLIST_NODE(ECORE_LIST(list)->last); + + if (prev) + prev = prev->previous; + + node = ecore_dlist_node_new(); + ECORE_LIST_NODE(node)->data = data; + + ret = _ecore_list_insert(list, ECORE_LIST_NODE(node)); + if (!ret) { + ECORE_WRITE_UNLOCK(list); + return ret; + } + + if (ECORE_LIST_NODE(node)->next) + ECORE_DLIST_NODE(ECORE_LIST_NODE(node)->next)->previous = node; + + if (prev) + node->previous = prev; + + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/** + * ecore_dlist_remove - remove the current item from the list. + * @list: the list to remove the current item + * + * Returns a pointer to the removed data on success, NULL on failure. + */ +void *ecore_dlist_remove(Ecore_DList * list) +{ + void *ret; + Ecore_List_Node *node; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + + if (list->current) { + node = list->current->next; + ECORE_DLIST_NODE(node)->previous = + ECORE_DLIST_NODE(ECORE_LIST(list)->current)->previous; + } + ret = _ecore_list_remove_0(list); + + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/** + * ecore_dlist_remove_first - remove the first item from the list. + * @list: the list to remove the current item + * + * Returns a pointer to the removed data on success, NULL on failure. + */ +void *ecore_dlist_remove_first(Ecore_DList * list) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + ret = _ecore_dlist_remove_first(list); + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/** + * ecore_dlist_remove_destroy - remove and free the data at the current position + * @list: the list to remove the data from + * + * Returns TRUE on success, FALSE on error + */ +int ecore_dlist_remove_destroy(Ecore_DList *list) +{ + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + return ecore_list_remove_destroy(list); +} + +static void *_ecore_dlist_remove_first(Ecore_DList *list) +{ + void *ret; + + if (!list) + return FALSE; + + ret = _ecore_list_remove_first(list); + if (ret && ECORE_LIST(list)->first) + ECORE_DLIST_NODE(ECORE_LIST(list)->first)->previous = NULL; + + return ret; +} + +/** + * ecore_dlist_remove_last - remove the last item from the list + * @list: the list to remove the last node from + * + * Returns a pointer to the removed data on success, NULL on failure. + */ +void *ecore_dlist_remove_last(Ecore_DList * list) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + ret = _ecore_list_remove_last(list); + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/** + * ecore_dlist_goto_index - move the current item to the index number + * @list: the list to move the current item + * @index: the position to move the current item + * + * Returns node at specified index on success, NULL on error + */ +void *ecore_dlist_goto_index(Ecore_DList * list, int index) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + ret = _ecore_dlist_goto_index(list, index); + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/* This is the non-threadsafe version, use this inside internal functions that + * already lock the list */ +static void *_ecore_dlist_goto_index(Ecore_DList *list, int index) +{ + int i, increment; + + if (!list) + return FALSE; + + if (ecore_list_is_empty(ECORE_LIST(list))) + return FALSE; + + if (index > ecore_list_nodes(ECORE_LIST(list)) || index < 1) + return FALSE; + + if (ECORE_LIST(list)->index > ECORE_LIST(list)->nodes) + _ecore_list_goto_last(ECORE_LIST(list)); + + if (index < ECORE_LIST(list)->index) + increment = -1; + else + increment = 1; + + for (i = ECORE_LIST(list)->index; i != index; i += increment) { + if (increment > 0) + _ecore_list_next(list); + else + _ecore_dlist_previous(list); + } + + return _ecore_list_current(list); +} + +/** + * ecore_dlist_goto - move the current item to the node that contains data + * @list: the list to move the current item in + * @data: the data to find and set the current item to + * + * Returns specified data on success, NULL on error + */ +void *ecore_dlist_goto(Ecore_DList * list, void *data) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + ret = _ecore_list_goto(ECORE_LIST(list), data); + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/** + * ecore_dlist_goto_first - move the current pointer to the first item in the list + * @list: the list to change the current to the first item + * + * Returns a pointer to the first item on success, NULL on failure. + */ +void *ecore_dlist_goto_first(Ecore_DList *list) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + ret = _ecore_list_goto_first(list); + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/** + * ecore_dlist_goto_last - move the pointer to the current item to the last item + * @list: the list to move the current item pointer to the last + * + * Returns a pointer to the last item in the list on success, NULL on failure. + */ +void *ecore_dlist_goto_last(Ecore_DList * list) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ECORE_WRITE_LOCK(list); + ret = _ecore_list_goto_last(ECORE_LIST(list)); + ECORE_WRITE_UNLOCK(list); + + return ret; +} + +/** + * ecore_dlist_current - return the data in the current list item + * @list: the list to the return the current data + * + * Returns value of the current data item, NULL if no current item + */ +void *ecore_dlist_current(Ecore_DList * list) +{ + void *ret; + + ECORE_READ_LOCK(list); + ret = _ecore_list_current(ECORE_LIST(list)); + ECORE_READ_UNLOCK(list); + + return ret; +} + +/** + * ecore_dlist_next - move to the next item in the list and return current item + * @list: the list to move to the next item in. + * + * Returns data in the current list node, or NULL on error + */ +void *ecore_dlist_next(Ecore_DList * list) +{ + void *data; + + ECORE_WRITE_LOCK(list); + data = _ecore_list_next(list); + ECORE_WRITE_UNLOCK(list); + + return data; +} + +/** + * ecore_dlist_previous - move to the previous item and return current item + * @list: the list to move to the previous item in. + * + * Returns data in the current list node, or NULL on error + */ +void *ecore_dlist_previous(Ecore_DList * list) +{ + void *data; + + ECORE_WRITE_LOCK(list); + data = _ecore_dlist_previous(list); + ECORE_WRITE_UNLOCK(list); + + return data; +} + +static void *_ecore_dlist_previous(Ecore_DList * list) +{ + void *data = NULL; + + if (!list) + return NULL; + + if (ECORE_LIST(list)->current) { + data = ECORE_LIST(list)->current->data; + ECORE_LIST(list)->current = ECORE_LIST_NODE(ECORE_DLIST_NODE( + ECORE_LIST(list)->current)->previous); + ECORE_LIST(list)->index--; + } + else + _ecore_list_goto_last(ECORE_LIST(list)); + + return data; +} + +/** + * ecore_dlist_clear - remove all nodes from the list. + * @list: the list to remove all nodes from + * + * Returns TRUE on success, FALSE on errors + */ +int ecore_dlist_clear(Ecore_DList * list) +{ + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ecore_list_clear(ECORE_LIST(list)); + + return TRUE; +} + +/* + * Description: Initialize a node to sane starting values + * Parameters: 1. node - the node to initialize + * Returns: TRUE on success, FALSE on errors + */ +int ecore_dlist_node_init(Ecore_DList_Node * node) +{ + int ret; + + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + ret = ecore_list_node_init(ECORE_LIST_NODE(node)); + if (ret) + node->previous = NULL; + + return ret; +} + +/* + * Description: Allocate and initialize a new list node + * Parameters: None + * Returns: NULL on error, new list node on success + */ +Ecore_DList_Node *ecore_dlist_node_new() +{ + Ecore_DList_Node *new_node; + + new_node = malloc(sizeof(Ecore_DList_Node)); + + if (!new_node) + return NULL; + + if (!ecore_dlist_node_init(new_node)) { + FREE(new_node); + return NULL; + } + + return new_node; +} + +/* + * Description: Call the data's free callback function, then free the node + * Parameters: 1. node - the node to be freed + * 2. free_func - the callback function to execute on the data + * Returns: TRUE on success, FALSE on error + */ +int ecore_dlist_node_destroy(Ecore_DList_Node * node, Ecore_Free_Cb free_func) +{ + CHECK_PARAM_POINTER_RETURN("node", node, + FALSE); + + return ecore_list_node_destroy(ECORE_LIST_NODE(node), free_func); +} diff --git a/legacy/ecore/src/lib/ecore/ecore_main.c b/legacy/ecore/src/lib/ecore/ecore_main.c index 275d009664..e36e40e50b 100644 --- a/legacy/ecore/src/lib/ecore/ecore_main.c +++ b/legacy/ecore/src/lib/ecore/ecore_main.c @@ -239,7 +239,7 @@ _ecore_main_select(double timeout) fd_set rfds, wfds, exfds; int max_fd; int ret; - Ecore_List *l; + Ecore_Oldlist *l; t = NULL; if (timeout > 0.0) @@ -262,7 +262,7 @@ _ecore_main_select(double timeout) FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&exfds); - for (l = (Ecore_List *)fd_handlers; l; l = l->next) + for (l = (Ecore_Oldlist *)fd_handlers; l; l = l->next) { Ecore_Fd_Handler *fdh; @@ -291,7 +291,7 @@ _ecore_main_select(double timeout) } if (ret > 0) { - for (l = (Ecore_List *)fd_handlers; l; l = l->next) + for (l = (Ecore_Oldlist *)fd_handlers; l; l = l->next) { Ecore_Fd_Handler *fdh; @@ -315,10 +315,10 @@ _ecore_main_select(double timeout) static void _ecore_main_fd_handlers_cleanup(void) { - Ecore_List *l; + Ecore_Oldlist *l; if (!fd_handlers_delete_me) return; - for (l = (Ecore_List *)fd_handlers; l;) + for (l = (Ecore_Oldlist *)fd_handlers; l;) { Ecore_Fd_Handler *fdh; @@ -337,9 +337,9 @@ _ecore_main_fd_handlers_cleanup(void) static void _ecore_main_fd_handlers_call(void) { - Ecore_List *l; + Ecore_Oldlist *l; - for (l = (Ecore_List *)fd_handlers; l; l = l->next) + for (l = (Ecore_Oldlist *)fd_handlers; l; l = l->next) { Ecore_Fd_Handler *fdh; @@ -366,11 +366,11 @@ _ecore_main_fd_handlers_call(void) static int _ecore_main_fd_handlers_buf_call(void) { - Ecore_List *l; + Ecore_Oldlist *l; int ret; ret = 0; - for (l = (Ecore_List *)fd_handlers; l; l = l->next) + for (l = (Ecore_Oldlist *)fd_handlers; l; l = l->next) { Ecore_Fd_Handler *fdh; diff --git a/legacy/ecore/src/lib/ecore/ecore_path.c b/legacy/ecore/src/lib/ecore/ecore_path.c new file mode 100644 index 0000000000..bd7e009f8b --- /dev/null +++ b/legacy/ecore/src/lib/ecore/ecore_path.c @@ -0,0 +1,276 @@ +#include + +static Ecore_List *group_list = NULL; + +Ecore_Path_Group *__ecore_path_group_find(char *name); +Ecore_Path_Group *__ecore_path_group_find_id(int id); + +/** + * ecore_path_group_new - create a new path group + * @group_name: the name of the new group + * + * Returns 0 on error, the integer id of the new group on success. + */ +int +ecore_path_group_new(char *group_name) +{ + Ecore_Path_Group *last; + Ecore_Path_Group *group; + + CHECK_PARAM_POINTER_RETURN("group_name", group_name, -1); + + if (!group_list) { + group_list = ecore_list_new(); + } + else { + group = __ecore_path_group_find(group_name); + if (group) + return -1; + } + + group = (Ecore_Path_Group *)malloc(sizeof(Ecore_Path_Group)); + memset(group, 0, sizeof(Ecore_Path_Group)); + + group->name = strdup(group_name); + ecore_list_append(group_list, group); + + last = ecore_list_goto_last(group_list); + group->id = last->id + 1; + + return group->id; +} + +/** + * ecore_path_group_del - destroy a previously created path group + * @group_id: the unique identifier for the group + * + * Returns no value. + */ +void +ecore_path_group_del(int group_id) +{ + Ecore_Path_Group *group; + + group = __ecore_path_group_find_id(group_id); + + if (!group) + return; + + if (group->paths) { + ecore_list_for_each(group->paths, + ECORE_FOR_EACH(free)); + ecore_list_destroy(group->paths); + } + + free(group->name); + free(group); +} + +/** + * ecore_path_group_add - add a directory to be searched for files + * @group_id: the unique identifier for the group to add the path + * @path: the new path to be added to the group + * + * Returns no value. + */ +void +ecore_path_group_add(int group_id, char *path) +{ + Ecore_Path_Group *group; + + CHECK_PARAM_POINTER("path", path); + + group = __ecore_path_group_find_id(group_id); + + if (!group) + return; + + if (!group->paths) + group->paths = ecore_list_new(); + + ecore_list_append(group->paths, strdup(path)); +} + +/** + * ecore_path_group_remove - remove a directory to be searched for files + * @group_id: the identifier for the group to remove a path + * @path: the path to be removed from @group_id + * + * Returns no value. Removes @path from the list of directories to search for + * files. + */ +void +ecore_path_group_remove(int group_id, char *path) +{ + char *found; + Ecore_Path_Group *group; + + CHECK_PARAM_POINTER("path", path); + + group = __ecore_path_group_find_id(group_id); + + if (!group || !group->paths) + return; + + /* + * Find the path in the list of available paths + */ + ecore_list_goto_first(group->paths); + + while ((found = ecore_list_current(group->paths)) + && strcmp(found, path)) + ecore_list_next(group->paths); + + /* + * If the path is found, remove and free it + */ + if (found) { + ecore_list_remove(group->paths); + free(found); + } +} + +/** + * ecore_path_group_find - find a file in a group of paths + * @group_id - the path group id to search for @file + * @file: the name of the file to find in the path group @group_id + * + * Returns a pointer to a newly allocated path location of the found file + * on success, NULL on failure. + */ +char * +ecore_path_group_find(int group_id, char *name) +{ + char *p; + struct stat st; + char path[PATH_MAX]; + Ecore_Path_Group *group; + + CHECK_PARAM_POINTER_RETURN("name", name, NULL); + + group = __ecore_path_group_find_id(group_id); + + /* + * Search the paths of the path group for the specified file name + */ + ecore_list_goto_first(group->paths); + p = ecore_list_next(group->paths); + do { + snprintf(path, PATH_MAX, "%s/%s", p, name); + stat(path, &st); + } while (!S_ISREG(st.st_mode) && (p = ecore_list_next(group->paths))); + + if (p) + p = strdup(path); + + return p; +} + +/** + * ecore_path_group_available - get a list of all available files in the path + * @group_id: the identifier for the path to get all available files + * + * Returns a pointer to a newly allocated list of all files found in the paths + * identified by @group_id, NULL on failure. + */ +Ecore_List * +ecore_path_group_available(int group_id) +{ + Ecore_List *avail = NULL; + Ecore_Path_Group *group; + char *path; + + group = __ecore_path_group_find_id(group_id); + + if (!group || !group->paths || ecore_list_is_empty(group->paths)) + return NULL; + + ecore_list_goto_first(group->paths); + + while ((path = ecore_list_next(group->paths)) != NULL) + { + DIR *dir; + struct stat st; + struct dirent *d; + + stat(path, &st); + + if (!S_ISDIR(st.st_mode)) + continue; + + dir = opendir(path); + + if (!dir) + continue; + + while ((d = readdir(dir)) != NULL) + { + char ppath[PATH_MAX]; + char *ext; + char n[PATH_MAX]; + int l; + + if (!strncmp(d->d_name, ".", 1)) + continue; + + ext = strrchr(d->d_name, '.'); + + if (!ext || strncmp(ext, ".so", 3)) + continue; + + snprintf(ppath, PATH_MAX, "%s/%s", path, d->d_name); + + stat(ppath, &st); + + if (!S_ISREG(st.st_mode)) + continue; + + l = strlen(d->d_name); + + strncpy(n, d->d_name, l - 2); + + if (!avail) + avail = ecore_list_new(); + + ecore_list_append(avail, strdup(n)); + } + } + + return avail; +} + +/* + * Find the specified group name + */ +Ecore_Path_Group * +__ecore_path_group_find(char *name) +{ + Ecore_Path_Group *group; + + CHECK_PARAM_POINTER_RETURN("name", name, NULL); + + ecore_list_goto_first(group_list); + + while ((group = ecore_list_next(group_list)) != NULL) + if (!strcmp(group->name, name)) + return group; + + return NULL; +} + +/* + * Find the specified group id + */ +Ecore_Path_Group * +__ecore_path_group_find_id(int id) +{ + Ecore_Path_Group *group; + + ecore_list_goto_first(group_list); + + while ((group = ecore_list_next(group_list)) != NULL) + if (group->id == id) + return group; + + return NULL; +} diff --git a/legacy/ecore/src/lib/ecore/ecore_plugin.c b/legacy/ecore/src/lib/ecore/ecore_plugin.c new file mode 100644 index 0000000000..4a4cc2f43c --- /dev/null +++ b/legacy/ecore/src/lib/ecore/ecore_plugin.c @@ -0,0 +1,95 @@ +#include + +static Ecore_List *loaded_plugins = NULL; + +/** + * ecore_plugin_load - load the specified plugin from the specified path group + * @group_id: the path group to search for the plugin to load + * @plugin_name: the name of the plugin to load + * + * Returns a pointer to the newly loaded plugin on success, NULL on failure. + */ +Ecore_Plugin * +ecore_plugin_load(int group_id, char *plugin_name) +{ + char *path; + char temp[PATH_MAX]; + + Ecore_Plugin *plugin; + void *handle = NULL; + + CHECK_PARAM_POINTER_RETURN("plugin_name", plugin_name, NULL); + + snprintf(temp, PATH_MAX, "%s.so", plugin_name); + path = ecore_path_group_find(group_id, temp); + if (!path) + return NULL; + + handle = dlopen(path, RTLD_LAZY); + if (!handle) + return NULL; + + /* + * Allocate the new plugin and initialize it's fields + */ + plugin = malloc(sizeof(Ecore_Plugin)); + memset(plugin, 0, sizeof(Ecore_Plugin)); + + plugin->group = group_id; + plugin->name = strdup(plugin_name); + plugin->handle = handle; + + /* + * Now add it to the list of the groups loaded plugins + */ + if (!loaded_plugins) + loaded_plugins = ecore_list_new(); + + ecore_list_append(loaded_plugins, plugin); + + FREE(path); + + return plugin; +} + +/** + * ecore_plugin_unload - unload the specified plugin + * @plugin: the plugin to unload from memory + * + * Returns no value. + */ +void +ecore_plugin_unload(Ecore_Plugin * plugin) +{ + CHECK_PARAM_POINTER("plugin", plugin); + + if (!plugin->handle) + return; + + if (ecore_list_goto(loaded_plugins, plugin)) + ecore_list_remove(loaded_plugins); + + dlclose(plugin->handle); + + FREE(plugin->name); + FREE(plugin); +} + +/* + * Lookup the specified symbol for the plugin + */ +void * +ecore_plugin_call(Ecore_Plugin * plugin, char *symbol_name) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("plugin", plugin, NULL); + CHECK_PARAM_POINTER_RETURN("symbol_name", symbol_name, NULL); + + if (!plugin->handle) + return NULL; + + ret = dlsym(plugin->handle, symbol_name); + + return ret; +} diff --git a/legacy/ecore/src/lib/ecore/ecore_private.h b/legacy/ecore/src/lib/ecore/ecore_private.h index a650dfc080..11107b8cbf 100644 --- a/legacy/ecore/src/lib/ecore/ecore_private.h +++ b/legacy/ecore/src/lib/ecore/ecore_private.h @@ -31,12 +31,12 @@ typedef int Ecore_Magic; -typedef struct _Ecore_List Ecore_List; +typedef struct _Ecore_Oldlist Ecore_Oldlist; -struct _Ecore_List +struct _Ecore_Oldlist { - Ecore_List *next, *prev; - Ecore_List *last; + Ecore_Oldlist *next, *prev; + Ecore_Oldlist *last; }; #ifndef _ECORE_H @@ -60,7 +60,7 @@ typedef struct _Ecore_Event Ecore_Event; struct _Ecore_Exe { - Ecore_List __list_data; + Ecore_Oldlist __list_data; ECORE_MAGIC; pid_t pid; void *data; @@ -68,7 +68,7 @@ struct _Ecore_Exe struct _Ecore_Timer { - Ecore_List __list_data; + Ecore_Oldlist __list_data; ECORE_MAGIC; double in; double at; @@ -80,7 +80,7 @@ struct _Ecore_Timer struct _Ecore_Idler { - Ecore_List __list_data; + Ecore_Oldlist __list_data; ECORE_MAGIC; int delete_me : 1; int (*func) (void *data); @@ -89,7 +89,7 @@ struct _Ecore_Idler struct _Ecore_Idle_Enterer { - Ecore_List __list_data; + Ecore_Oldlist __list_data; ECORE_MAGIC; int delete_me : 1; int (*func) (void *data); @@ -98,7 +98,7 @@ struct _Ecore_Idle_Enterer struct _Ecore_Idle_Exiter { - Ecore_List __list_data; + Ecore_Oldlist __list_data; ECORE_MAGIC; int delete_me : 1; int (*func) (void *data); @@ -107,7 +107,7 @@ struct _Ecore_Idle_Exiter struct _Ecore_Fd_Handler { - Ecore_List __list_data; + Ecore_Oldlist __list_data; ECORE_MAGIC; int fd; Ecore_Fd_Handler_Flags flags; @@ -123,7 +123,7 @@ struct _Ecore_Fd_Handler struct _Ecore_Event_Handler { - Ecore_List __list_data; + Ecore_Oldlist __list_data; ECORE_MAGIC; int type; int delete_me : 1; @@ -133,7 +133,7 @@ struct _Ecore_Event_Handler struct _Ecore_Event_Filter { - Ecore_List __list_data; + Ecore_Oldlist __list_data; ECORE_MAGIC; int delete_me : 1; void * (*func_start) (void *data); @@ -145,7 +145,7 @@ struct _Ecore_Event_Filter struct _Ecore_Event { - Ecore_List __list_data; + Ecore_Oldlist __list_data; ECORE_MAGIC; int type; void *event; diff --git a/legacy/ecore/src/lib/ecore/ecore_sheap.c b/legacy/ecore/src/lib/ecore/ecore_sheap.c new file mode 100644 index 0000000000..4b2c70297c --- /dev/null +++ b/legacy/ecore/src/lib/ecore/ecore_sheap.c @@ -0,0 +1,402 @@ +#include + +static void _ecore_sheap_heapify(Ecore_Sheap *heap, int i); +static void _ecore_sheap_update_data(Ecore_Sheap *heap); + +/** + * ecore_sheap_new - allocate and initialize a new binary heap + * @compare: the function for comparing keys, NULL for direct comparison + * @size: the number of elements to allow in the heap + * + * Returns a pointer to the newly allocated binary heap on success, NULL on + * failure. + */ +Ecore_Sheap *ecore_sheap_new(Ecore_Compare_Cb compare, int size) +{ + Ecore_Sheap *heap = NULL; + + heap = (Ecore_Sheap *)malloc(sizeof(Ecore_Sheap)); + if (!heap) + return NULL; + memset(heap, 0, sizeof(Ecore_Sheap)); + + if (!ecore_sheap_init(heap, compare, size)) { + FREE(heap); + return NULL; + } + + return heap; +} + +/** + * ecore_sheap_init - initialize a binary heap to default values + * @heap: the heap to initialize + * @compare: the function for comparing keys, NULL for direct comparison + * @size: the number of elements to allow in the heap + * + * Returns TRUE on success, FALSE on failure + */ +int ecore_sheap_init(Ecore_Sheap *heap, Ecore_Compare_Cb compare, int size) +{ + CHECK_PARAM_POINTER_RETURN("heap", heap, FALSE); + + heap->space = size; + if (!compare) + heap->compare = ecore_direct_compare; + else + heap->compare = compare; + heap->order = ECORE_SHEAP_MIN; + + heap->data = (void **)malloc(heap->space * sizeof(void *)); + if (!heap->data) + return FALSE; + memset(heap->data, 0, heap->space * sizeof(void *)); + + return TRUE; +} + +/** + * ecore_sheap_destroy - free up the memory used by the heap + * @heap: the heap to be freed + * + * Returns no value. Free's the memory used by @heap, calls the destroy + * function on each data item if necessary. + */ +void ecore_sheap_destroy(Ecore_Sheap *heap) +{ + CHECK_PARAM_POINTER("heap", heap); + + /* + * FIXME: Need to setup destructor callbacks for this class. + */ + FREE(heap->data); + + FREE(heap); +} + +/** + * ecore_sheap_insert - insert new data into the heap + * @heap: the heap to insert @data + * @data: the data to add to @heap + * + * Returns TRUE on success, NULL on failure. Increases the size of the heap if + * it becomes larger than available space. + */ +int ecore_sheap_insert(Ecore_Sheap *heap, void *data) +{ + int i; + void *temp; + int parent; + int position; + + CHECK_PARAM_POINTER_RETURN("heap", heap, FALSE); + + /* + * Increase the size of the allocated data area if there isn't enough + * space available to add this data + */ + if (heap->size >= heap->space) + return FALSE; + + heap->sorted = FALSE; + + /* + * Place the data at the end of the heap initially. Then determine the + * parent and position in the array of it's parent. + */ + heap->data[heap->size] = data; + position = heap->size; + heap->size++; + i = heap->size; + parent = PARENT(i) - 1; + + /* + * Check the order of the heap to decide where to place the inserted + * data. The loop is placed inside the if statement to reduce the + * number of branching decisions that must be predicted. + */ + if (heap->order == ECORE_SHEAP_MIN) { + while ((position > 0) && heap->compare(heap->data[parent], + heap->data[position]) > 0) { + + /* + * Swap the data with it's parents to move it up in + * the heap. + */ + temp = heap->data[position]; + heap->data[position] = heap->data[parent]; + heap->data[parent] = temp; + + /* + * Now determine the new position for the next + * iteration of the loop, as well as it's parents + * position. + */ + i = PARENT(i); + position = i - 1; + parent = PARENT(i) - 1; + } + } + else { + while ((position > 0) && heap->compare(heap->data[parent], + heap->data[position]) < 0) { + + /* + * Swap the data with it's parents to move it up in + * the heap. + */ + temp = heap->data[position]; + heap->data[position] = heap->data[PARENT(i) - 1]; + heap->data[PARENT(i) - 1] = temp; + + /* + * Now determine the new position for the next + * iteration of the loop, as well as it's parents + * position. + */ + i = PARENT(i); + position = i - 1; + parent = PARENT(i) - 1; + } + } + + return TRUE; +} + +/** + * ecore_sheap_extract - extract the item at the top of the heap + * @heap: the heap to remove the top item + * + * Returns the top item of the heap on success, NULL on failure. The extract + * function maintains the heap properties after the extract. + */ +void *ecore_sheap_extract(Ecore_Sheap *heap) +{ + void *extreme; + + if (heap->size < 1) + return NULL; + + heap->sorted = FALSE; + + extreme = heap->data[0]; + heap->size--; + heap->data[0] = heap->data[heap->size]; + + _ecore_sheap_heapify(heap, 1); + + return extreme; +} + +/** + * ecore_sheap_extreme - examine the item at the top of the heap + * @heap: the heap to examine the top item + * + * Returns the top item of the heap on success, NULL on failure. The function + * does not alter the heap. + */ +void *ecore_sheap_extreme(Ecore_Sheap *heap) +{ + if (heap->size < 1) + return NULL; + + return heap->data[0]; +} + +/** + * ecore_sheap_change - change the value of the specified item in the heap + * @heap: the heap to search for the item to change + * @item: the item in the heap to change + * @newval: the new value assigned to the item in the heap + * + * Returns TRUE on success, FALSE on failure. The heap does not free the old + * data since it must be passed in, so the caller can perform the free if + * desired. + */ +int ecore_sheap_change(Ecore_Sheap *heap, void *item, void *newval) +{ + int i; + + CHECK_PARAM_POINTER_RETURN("heap", heap, FALSE); + + for (i = 0; i < heap->size && heap->data[i] != item; heap++); + + if (i < heap->size) + heap->data[i] = newval; + else + return FALSE; + + /* + * FIXME: This is not the correct procedure when a change occurs. + */ + _ecore_sheap_heapify(heap, 1); + + return TRUE; +} + +/** + * ecore_sheap_set_compare - change the comparison function for the heap + * @heap: the heap to change comparison function + * @compare: the new function for comparing nodes + * + * Returns TRUE on success, FALSE on failure. The comparison function is + * changed to @compare and the heap is heapified by the new comparison. + */ +int ecore_sheap_set_compare(Ecore_Sheap *heap, Ecore_Compare_Cb compare) +{ + CHECK_PARAM_POINTER_RETURN("heap", heap, FALSE); + + if (!compare) + heap->compare = ecore_direct_compare; + else + heap->compare = compare; + + _ecore_sheap_update_data(heap); + + return TRUE; +} + +/** + * ecore_sheap_set_order - change the order of the heap + * @heap: the heap to change the order + * @order: the new order of the heap + * + * Returns no value. Changes the heap order of @heap and re-heapifies the data + * to this new order. The default order is a min heap. + */ +void ecore_sheap_set_order(Ecore_Sheap *heap, char order) +{ + CHECK_PARAM_POINTER("heap", heap); + + heap->order = order; + + _ecore_sheap_update_data(heap); +} + +/** + * ecore_sheap_sort - sort the data in the heap + * @heap: the heap to be sorted + * + * Returns no value. Sorts the data in the heap into the order that is used + * for the heap's data. + */ +void ecore_sheap_sort(Ecore_Sheap *heap) +{ + int i = 0; + void **new_data; + + CHECK_PARAM_POINTER("heap", heap); + + new_data = (void **)malloc(heap->size * sizeof(void *)); + + /* + * Extract the heap and insert into the new data array in order. + */ + while (heap->size > 0) + new_data[i++] = ecore_sheap_extract(heap); + + /* + * Free the old data array and update the heap with the new data, also + * mark as sorted. + */ + FREE(heap->data); + heap->data = new_data; + heap->size = i; + heap->sorted = TRUE; +} + +/* + * ecore_sheap_item - access the item at the ith position in the heap + * @heap: the heap to access the internal data + * @i: the index of the data within the heap + * + * Returns the data located at the ith position within @heap on success, NULL + * on failure. The data is guaranteed to be in sorted order. + */ +inline void *ecore_sheap_item(Ecore_Sheap *heap, int i) +{ + if (i >= heap->size) + return NULL; + + /* + * Make sure the data is sorted so we return the correct value. + */ + if (!heap->sorted) + ecore_sheap_sort(heap); + + return heap->data[i]; +} + +/* + * _ecore_sheap_heapify - regain the heap properties starting at position i + * @heap: the heap to regain heap properties + * @i: the position to start heapifying + * + * Returns no value. + */ +static void _ecore_sheap_heapify(Ecore_Sheap *heap, int i) +{ + int extreme; + int left = LEFT(i); + int right = RIGHT(i); + + if (heap->order == ECORE_SHEAP_MIN) { + if (left <= heap->size && heap->compare(heap->data[left - 1], + heap->data[i - 1]) < 0) + extreme = left; + else + extreme = i; + + if (right <= heap->size && heap->compare(heap->data[right - 1], + heap->data[extreme - 1]) < 0) + extreme = right; + } + else { + if (left <= heap->size && heap->compare(heap->data[left - 1], + heap->data[i - 1]) > 0) + extreme = left; + else + extreme = i; + + if (right <= heap->size && heap->compare(heap->data[right - 1], + heap->data[extreme - 1]) > 0) + extreme = right; + } + + /* + * If the data needs to be swapped down the heap, recurse on + * heapifying it's new placement. + */ + if (extreme != i) { + void *temp; + + temp = heap->data[extreme - 1]; + heap->data[extreme - 1] = heap->data[i - 1]; + heap->data[i - 1] = temp; + + _ecore_sheap_heapify(heap, extreme); + } +} + +static void _ecore_sheap_update_data(Ecore_Sheap *heap) +{ + int i, old_size; + void **data; + + /* + * Track the old values from the heap + */ + old_size = heap->size; + data = heap->data; + + /* + * + */ + heap->size = 0; + heap->data = malloc(heap->space * sizeof(void *)); + + for (i = 0; i < old_size; i++) + ecore_sheap_insert(heap, data[i]); + + FREE(data); +} diff --git a/legacy/ecore/src/lib/ecore/ecore_strings.c b/legacy/ecore/src/lib/ecore/ecore_strings.c new file mode 100644 index 0000000000..6fc9e65dff --- /dev/null +++ b/legacy/ecore/src/lib/ecore/ecore_strings.c @@ -0,0 +1,69 @@ +#include + +static Ecore_Hash *ecore_strings = NULL; + +/** + * ecore_stringinstance - retrieve an instance of a string for use in an ecore + * @string: the string to retrieve an instance + * + * Returns a pointer to a the string on success, NULL on failure. + */ +char *ecore_string_instance(char *string) +{ + Ecore_String *str; + + CHECK_PARAM_POINTER_RETURN("string", string, NULL); + + /* + * No strings have been loaded at this point, so create the hash + * table for storing string info for later. + */ + if (!ecore_strings) + ecore_strings = ecore_hash_new(ecore_str_hash, ecore_str_compare); + + /* + * Check for a previous instance of the string, if not found, create + * it. + */ + str = ecore_hash_get(ecore_strings, string); + if (!str) { + + /* + * Allocate and initialize a new string reference. + */ + str = (Ecore_String *)malloc(sizeof(Ecore_String)); + + str->string = strdup(string); + str->references = 0; + + ecore_hash_set(ecore_strings, string, str); + } + + str->references++; + + return str->string; +} + +/** + * ecore_string_release - release an instance of a string + * @string: the string to release an instance + * + * Returns no value. Marks the string as losing an instance, will free the + * string if no other instances are present. + */ +void ecore_string_release(char *string) +{ + Ecore_String *str; + + CHECK_PARAM_POINTER("string", string); + + str = ecore_hash_get(ecore_strings, string); + if (!str) + return; + + str->references--; + if (str->references < 1) { + ecore_hash_remove(ecore_strings, string); + FREE(str->string); + } +} diff --git a/legacy/ecore/src/lib/ecore/ecore_timer.c b/legacy/ecore/src/lib/ecore/ecore_timer.c index 7f59a9ac1e..5ea73b1579 100644 --- a/legacy/ecore/src/lib/ecore/ecore_timer.c +++ b/legacy/ecore/src/lib/ecore/ecore_timer.c @@ -124,10 +124,10 @@ _ecore_timer_shutdown(void) void _ecore_timer_cleanup(void) { - Ecore_List *l; + Ecore_Oldlist *l; if (!timers_delete_me) return; - for (l = (Ecore_List *)timers; l;) + for (l = (Ecore_Oldlist *)timers; l;) { Ecore_Timer *timer; @@ -148,11 +148,11 @@ _ecore_timer_cleanup(void) void _ecore_timer_enable_new(void) { - Ecore_List *l; + Ecore_Oldlist *l; if (!timers_added) return; timers_added = 0; - for (l = (Ecore_List *)timers; l; l = l->next) + for (l = (Ecore_Oldlist *)timers; l; l = l->next) { Ecore_Timer *timer; @@ -177,11 +177,11 @@ _ecore_timer_next_get(void) int _ecore_timer_call(double when) { - Ecore_List *l; + Ecore_Oldlist *l; Ecore_Timer *timer; if (!timers) return 0; - for (l = (Ecore_List *)timers; l; l = l->next) + for (l = (Ecore_Oldlist *)timers; l; l = l->next) { timer = (Ecore_Timer *)l; if ((timer->at <= when) && @@ -203,7 +203,7 @@ _ecore_timer_call(double when) static void _ecore_timer_set(Ecore_Timer *timer, double at, double in, int (*func) (void *data), void *data) { - Ecore_List *l; + Ecore_Oldlist *l; timers_added = 1; timer->at = at; @@ -213,7 +213,7 @@ _ecore_timer_set(Ecore_Timer *timer, double at, double in, int (*func) (void *da timer->just_added = 1; if (timers) { - for (l = ((Ecore_List *)(timers))->last; l; l = l->prev) + for (l = ((Ecore_Oldlist *)(timers))->last; l; l = l->prev) { Ecore_Timer *t2; diff --git a/legacy/ecore/src/lib/ecore/ecore_tree.c b/legacy/ecore/src/lib/ecore/ecore_tree.c new file mode 100644 index 0000000000..b2a6e095bc --- /dev/null +++ b/legacy/ecore/src/lib/ecore/ecore_tree.c @@ -0,0 +1,852 @@ +/* ecore_tree.c + +Copyright (C) 2001 Nathan Ingersoll + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies of the Software and its documentation and acknowledgment shall be +given in the documentation and software packages that this Software was +used. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +#include + +/* A macro for determining the highest node at given branch */ +#define MAX_HEIGHT(node) (node ? MAX(node->max_left, node->max_right) : 0) + +/* Utility functions for searching the tree and returning a node, or its + * parent */ +Ecore_Tree_Node *tree_node_find(Ecore_Tree * tree, void *key); +Ecore_Tree_Node *tree_node_find_parent(Ecore_Tree * tree, void *key); + +/* Balancing functions, keep the tree balanced within a one node height + * difference */ +int tree_node_balance(Ecore_Tree * Tree, Ecore_Tree_Node * top_node); +int tree_node_rotate_right(Ecore_Tree * tree, Ecore_Tree_Node * top_node); +int tree_node_rotate_left(Ecore_Tree * tree, Ecore_Tree_Node * top_node); + +/* Fucntions for executing a specified function on each node of a tree */ +int tree_for_each_node(Ecore_Tree_Node * node, Ecore_For_Each for_each_func); +int tree_for_each_node_value(Ecore_Tree_Node * node, + Ecore_For_Each for_each_func); + +/** + * ecore_tree_new - allocate a new tree structure. + * @compare_func: function used to compare the two values + * + * Returns NULL if the operation fails, otherwise a pointer to the new tree + */ +Ecore_Tree *ecore_tree_new(Ecore_Compare_Cb compare_func) +{ + Ecore_Tree *new_tree; + + new_tree = ECORE_TREE(malloc(sizeof(Ecore_Tree))); + if (!new_tree) + return NULL; + + if (!ecore_tree_init(new_tree, compare_func)) { + IF_FREE(new_tree); + return NULL; + } + + return new_tree; +} + +/** + * ecore_tree_init - initialize a tree structure to some sane initial values + * @new_tree: the new tree structure to be initialized + * @compare_func: the function used to compare node keys + * + * Returns TRUE on successful initialization, FALSE on an error + */ +int ecore_tree_init(Ecore_Tree * new_tree, Ecore_Compare_Cb compare_func) +{ + CHECK_PARAM_POINTER_RETURN("new_tree", new_tree, FALSE); + + memset(new_tree, 0, sizeof(Ecore_Tree)); + + if (!compare_func) + new_tree->compare_func = ecore_direct_compare; + else + new_tree->compare_func = compare_func; + + ECORE_INIT_LOCKS(new_tree); + + return TRUE; +} + +/* + * ecore_tree_set_free_cb - add a function to be called at node destroy time + * @tree: the tree that will use this function when nodes are destroyed + * @free_func - the function that will be passed the node being freed + * + * Returns TRUE on successful set, FALSE otherwise. + */ +int ecore_tree_set_free_cb(Ecore_Tree * tree, Ecore_Free_Cb free_func) +{ + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + ECORE_WRITE_LOCK(tree); + tree->free_func = free_func; + ECORE_WRITE_UNLOCK(tree); + + return TRUE; +} + +/* + * ecore_tree_node_init - initialize a new tree node + * + * Returns FALSE if the operation fails, otherwise TRUE + */ +int ecore_tree_node_init(Ecore_Tree_Node * new_node) +{ + CHECK_PARAM_POINTER_RETURN("new_node", new_node, FALSE); + + new_node->key = NULL; + new_node->value = NULL; + + new_node->parent = NULL; + new_node->right_child = NULL; + new_node->left_child = NULL; + + new_node->max_left = new_node->max_right = 0; + + ECORE_INIT_LOCKS(new_node); + + return TRUE; +} + +/* + * Description: Allocate a new tree node + * Parameters: None. + * Returns: NULL if the operation fails, otherwise a pointer to the new node. + */ +Ecore_Tree_Node *ecore_tree_node_new() +{ + Ecore_Tree_Node *new_node; + + new_node = ECORE_TREE_NODE(malloc(sizeof(Ecore_Tree_Node))); + if (!new_node) + return NULL; + + if (!ecore_tree_node_init(new_node)) { + IF_FREE(new_node); + return NULL; + } + + return new_node; +} + +/* + * Description: Free a tree node and it's children. If you don't want the + * children free'd then you need to remove the node first. + * Parameters: 1. node - tree node to be free()'d + * 2. data_free - callback for destroying the data held in node + * Returns: TRUE if the node is destroyed successfully, FALSE if not. + */ +int ecore_tree_node_destroy(Ecore_Tree_Node * node, Ecore_Free_Cb data_free) +{ + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + ECORE_WRITE_LOCK(node); + if (data_free) + data_free(node->value); + ECORE_WRITE_UNLOCK(node); + + ECORE_DESTROY_LOCKS(node); + + FREE(node); + + return TRUE; +} + +/* + * ecore_tree_node_value_set - set the value of the node to value + * @node: the node to be set + * @value: the value to set the node to. + * + * Returns TRUE if the node is set successfully, FALSE if not. + */ +int ecore_tree_node_value_set(Ecore_Tree_Node * node, void *value) +{ + CHECK_PARAM_POINTER_RETURN("node", node, + FALSE); + + ECORE_WRITE_LOCK(node); + node->value = value; + ECORE_WRITE_UNLOCK(node); + + return TRUE; +} + +/* + * Description: Get the value of the node + * Parameters: 1. node - the node that contains the desired value + * Returns: NULL if an error, otherwise the value associated with node + */ +void *ecore_tree_node_value_get(Ecore_Tree_Node * node) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + ECORE_READ_LOCK(node); + ret = node->value; + ECORE_READ_UNLOCK(node); + + return ret; +} + +/* + * ecore_tree_node_key_set - set the value of the node's key to key + * @node: the node to be set + * @key: the value to set it's key to. + * + * Returns TRUE if the node is set successfully, FALSE if not. + */ +int ecore_tree_node_key_set(Ecore_Tree_Node * node, void *key) +{ + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + ECORE_WRITE_LOCK(node); + node->key = key; + ECORE_WRITE_UNLOCK(node); + + return TRUE; +} + +/* + * ecore_tree_node_key_get - get the value of the node's key + * @node: the node that contains the desired key + * + * Returns NULL if an error occurs, otherwise the key is returned + */ +void *ecore_tree_node_key_get(Ecore_Tree_Node * node) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + ECORE_READ_LOCK(node); + ret = node->key; + ECORE_READ_UNLOCK(node); + + return ret; +} + +/** + * ecore_tree_destroy - free the tree and it's stored data + * @tree: the tree to destroy + * + * Returns TRUE if tree destroyed successfully, FALSE if not. + */ +int ecore_tree_destroy(Ecore_Tree * tree) +{ + Ecore_Tree_Node *node; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + ECORE_WRITE_LOCK(tree); + while ((node = tree->tree)) { + ecore_tree_remove_node(tree, node); + ecore_tree_node_destroy(node, tree->free_func); + } + ECORE_WRITE_UNLOCK(tree); + ECORE_DESTROY_LOCKS(tree); + + FREE(tree); + + return TRUE; +} + +/** + * ecore_tree_get_node - return the node corresponding to key + * @tree: the tree to search + * @key: the key to search for in the tree + * + * Returns the node corresponding to the key if found, otherwise NULL. + */ +Ecore_Tree_Node *ecore_tree_get_node(Ecore_Tree * tree, void *key) +{ + Ecore_Tree_Node *ret; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + ECORE_READ_LOCK(tree); + ret = tree_node_find(tree, key); + ECORE_READ_UNLOCK(tree); + + return ret; +} + +/** + * ecore_tree_get - return the value corresponding to key + * @tree: the tree to search + * @key: the key to search for in @tree + * + * Returns the value corresponding to the key if found, otherwise NULL. + */ +void *ecore_tree_get(Ecore_Tree * tree, void *key) +{ + void *ret; + Ecore_Tree_Node *node; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + ECORE_READ_LOCK(tree); + node = tree_node_find(tree, key); + ECORE_READ_UNLOCK(tree); + + ECORE_READ_LOCK(node); + ret = (node ? node->value : NULL); + ECORE_READ_UNLOCK(node); + + return ret; +} + +/** + * ecore_tree_get_closest_larger - find the closest value greater >= key + * @tree: the tree to search + * @key: the key to search for in @tree + * + * Returns NULL if no valid nodes, otherwise the node >= key + */ +void *ecore_tree_get_closest_larger(Ecore_Tree * tree, void *key) +{ + Ecore_Tree_Node *node; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + ECORE_READ_LOCK(tree); + node = tree_node_find(tree, key); + ECORE_READ_UNLOCK(tree); + + if (node) + return node; + + ECORE_READ_LOCK(tree); + node = tree_node_find_parent(tree, key); + + if (!node) { + ECORE_READ_UNLOCK(tree); + return NULL; + } + + ECORE_READ_LOCK(node); + if (tree->compare_func(node->key, key) < 0) + return NULL; + ECORE_READ_UNLOCK(node); + ECORE_READ_UNLOCK(tree); + + return node; +} + +/** + * ecore_tree_get_closest_smaller - find the closest value <= key + * @tree: the tree to search + * @key: the key to search for in tree + * + * Returns NULL if no valid nodes, otherwise the node <= key + */ +void *ecore_tree_get_closest_smaller(Ecore_Tree * tree, void *key) +{ + Ecore_Tree_Node *node; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + ECORE_READ_LOCK(tree); + node = tree_node_find(tree, key); + ECORE_READ_UNLOCK(tree); + + if (node) + return node; + + ECORE_READ_LOCK(tree); + node = tree_node_find_parent(tree, key); + ECORE_READ_LOCK(tree); + + if (node) + node = node->right_child; + + return node; +} + +/** + * ecore_tree_set - set the value associated with key to @value + * @tree: the tree that contains the key/value pair + * @key: the key to identify which node to set a value + * @value: value to set the found node + * + * Returns TRUE if successful, FALSE if not. + */ +int ecore_tree_set(Ecore_Tree * tree, void *key, void *value) +{ + Ecore_Tree_Node *node = NULL; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + ECORE_READ_LOCK(tree); + node = tree_node_find(tree, key); + ECORE_READ_UNLOCK(tree); + + if (!node) { + node = ecore_tree_node_new(); + ecore_tree_node_key_set(node, key); + if (!ecore_tree_add_node(tree, node)) + return FALSE; + } + ecore_tree_node_value_set(node, value); + + ECORE_WRITE_LOCK(tree); + for (; node; node = node->parent) + tree_node_balance(tree, node); + ECORE_WRITE_UNLOCK(tree); + + return TRUE; +} + +/** + * ecore_tree_add_node - place a node in the tree + * @tree: the tree to add @node + * @node: the node to add to @tree + * + * Returns TRUE on a successful add, FALSE otherwise. + */ +int ecore_tree_add_node(Ecore_Tree * tree, Ecore_Tree_Node * node) +{ + Ecore_Tree_Node *travel = NULL; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + /* Find where to put this new node. */ + if (!tree->tree) { + tree->tree = node; + } else { + travel = tree_node_find_parent(tree, node->key); + node->parent = travel; + + /* The node is less than travel */ + if (tree->compare_func(node->key, travel->key) < 0) { + travel->right_child = node; + travel->max_left = 1; + /* The node is greater than travel */ + } else { + travel->left_child = node; + travel->max_right = 1; + } + } + + return TRUE; +} + + +/** + * ecore_tree_remove_node - remove the node from the tree + * @tree: the tree to remove @node + * @node: the node to remove from @tree + * + * Returns TRUE on a successful remove, FALSE otherwise. + */ +int ecore_tree_remove_node(Ecore_Tree * tree, Ecore_Tree_Node * node) +{ + Ecore_Tree_Node *traverse; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + /* + * Find the nearest value to the balanced one. + */ + if (node->left_child) { + traverse = node->left_child; + + /* Now work our way down right side of the traverse node. + * This will give us the node with the next closest value + * to the current node. If traverse had no right node, then + * this will stop at node's left node. */ + while (traverse->right_child) { + traverse = traverse->right_child; + } + + /* + * Hook any dropped leaves into the moved nodes spot + */ + if (traverse->parent) + traverse->parent->left_child = traverse->left_child; + } + else if (node->right_child) { + traverse = node->right_child; + + /* Now work our way down left side of the traverse node. + * This will give us the node with the next closest value + * to the current node. If traverse had no left node, then + * this will stop at node's right node. */ + while (traverse->left_child) { + traverse = traverse->left_child; + } + + /* + * Hook any dropped leaves into the moved nodes spot + */ + if (traverse->right_child) + traverse->right_child->parent = traverse->parent; + + if (traverse->parent) + traverse->parent->right_child = traverse->right_child; + else + tree->tree = traverse->right_child; + } + else + traverse = NULL; + + if (traverse) { + + /* + * Ensure that we don't get a recursive reference. + */ + if (node->right_child && node->right_child != traverse) { + node->right_child->parent = traverse; + traverse->right_child = node->right_child; + } + + if (node->left_child && node->left_child != traverse) { + node->left_child->parent = traverse; + traverse->left_child = node->left_child; + } + + /* + * Unlink the node to be moved from it's parent. + */ + if (traverse->parent) { + if (traverse->parent->left_child == traverse) + traverse->parent->left_child = NULL; + else + traverse->parent->right_child = NULL; + } + traverse->parent = node->parent; + } + + if (node->parent) { + if (node == node->parent->left_child) + node->parent->left_child = traverse; + else + node->parent->right_child = traverse; + } + + if (tree->tree == node) + tree->tree = traverse; + + node->parent = node->left_child = node->right_child = NULL; + + /* + * Rebalance the tree to ensure short search paths. + */ + while (traverse) { + tree_node_balance(tree, traverse); + traverse = traverse->parent; + } + + return TRUE; +} + +/** + * ecore_tree_remove - remove the key from the tree + * @tree: the tree to remove @key + * @key: the key to remove from @tree + * + * Returns TRUE on a successful remove, FALSE otherwise. + */ +int ecore_tree_remove(Ecore_Tree * tree, void *key) +{ + Ecore_Tree_Node *node; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + if (!tree->tree) + return FALSE; + + /* Find the node we need to remove */ + node = tree_node_find(tree, key); + if (!node) + return FALSE; + + if (!ecore_tree_remove_node(tree, node)) + return FALSE; + + ecore_tree_node_destroy(node, tree->free_func); + + return TRUE; +} + +/** + * ecore_tree_is_empty - test to see if the tree has any nodes + * @tree: the tree to check for nodes + * + * Returns TRUE if no nodes exist, FALSE otherwise + */ +int ecore_tree_is_empty(Ecore_Tree * tree) +{ + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + if (!tree->tree) + return TRUE; + + return FALSE; +} + +/** + * ecore_tree_for_each_node_value - execute function for each value in the tree + * @tree: the tree to traverse + * @for_each_func: the function to execute for each value in the tree + * + * Returns TRUE on success, FALSE on failure. + */ +int ecore_tree_for_each_node_value(Ecore_Tree * tree, + Ecore_For_Each for_each_func) +{ + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + CHECK_PARAM_POINTER_RETURN("for_each_func", for_each_func, FALSE); + + if (!tree->tree) + return FALSE; + + return tree_for_each_node_value(tree->tree, for_each_func); +} + +/** + * ecore_tree_for_each_node - execute the function for each node in the tree + * @tree: the tree to traverse + * @for_each_func: the function to execute for each node + * + * Returns TRUE on success, FALSE on failure. + */ +int ecore_tree_for_each_node(Ecore_Tree * tree, Ecore_For_Each for_each_func) +{ + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + CHECK_PARAM_POINTER_RETURN("for_each_func", for_each_func, FALSE); + + if (!tree->tree) + return FALSE; + + return tree_for_each_node(tree->tree, for_each_func); +} + +/* Find the parent for the key */ +Ecore_Tree_Node *tree_node_find_parent(Ecore_Tree * tree, void *key) +{ + Ecore_Tree_Node *parent, *travel; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + parent = tree_node_find(tree, key); + if (parent) + parent = parent->parent; + + travel = tree->tree; + if (!travel) + return NULL; + + while (!parent) { + int compare; + + if ((compare = tree->compare_func(key, travel->key)) < 0) { + if (!travel->right_child) + parent = travel; + travel = travel->right_child; + } else { + if (!travel->left_child) + parent = travel; + travel = travel->left_child; + } + } + + return parent; +} + +/* Search for the node with a specified key */ +Ecore_Tree_Node *tree_node_find(Ecore_Tree * tree, void *key) +{ + int compare; + Ecore_Tree_Node *node; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + node = tree->tree; + while (node && (compare = tree->compare_func(key, node->key)) != 0) { + + if (compare < 0) { + if (!node->right_child) { + return NULL; + } + + node = node->right_child; + } else { + if (!node->left_child) { + return NULL; + } + + node = node->left_child; + } + } + + return node; +} + +/* Balance the tree with respect to node */ +int tree_node_balance(Ecore_Tree * tree, Ecore_Tree_Node * top_node) +{ + int balance; + + CHECK_PARAM_POINTER_RETURN("top_node", top_node, FALSE); + + /* Get the height of the left branch. */ + if (top_node->right_child) { + top_node->max_left = MAX_HEIGHT(top_node->right_child) + 1; + } else + top_node->max_left = 0; + + /* Get the height of the right branch. */ + if (top_node->left_child) { + top_node->max_right = MAX_HEIGHT(top_node->left_child) + 1; + } else + top_node->max_right = 0; + + /* Determine which side has a larger height. */ + balance = top_node->max_right - top_node->max_left; + + /* if the left side has a height advantage >1 rotate right */ + if (balance < -1) + tree_node_rotate_right(tree, top_node); + /* else if the left side has a height advantage >1 rotate left */ + else if (balance > 1) + tree_node_rotate_left(tree, top_node); + + return TRUE; +} + +/* Tree is overbalanced to the left, so rotate nodes to the right. */ +int tree_node_rotate_right(Ecore_Tree * tree, Ecore_Tree_Node * top_node) +{ + Ecore_Tree_Node *temp; + + CHECK_PARAM_POINTER_RETURN("top_node", top_node, FALSE); + + /* The left branch's right branch becomes the nodes left branch, + * the left branch becomes the top node, and the node becomes the + * right branch. */ + temp = top_node->right_child; + top_node->right_child = temp->left_child; + temp->left_child = top_node; + + /* Make sure the nodes know who their new parents are and the tree + * structure knows the start of the tree. */ + temp->parent = top_node->parent; + if (temp->parent == NULL) + tree->tree = temp; + else { + if (temp->parent->left_child == top_node) + temp->parent->left_child = temp; + else + temp->parent->right_child = temp; + } + top_node->parent = temp; + + /* And recalculate node heights */ + tree_node_balance(tree, top_node); + tree_node_balance(tree, temp); + + return TRUE; +} + +/* The tree is overbalanced to the right, so we rotate nodes to the left */ +int tree_node_rotate_left(Ecore_Tree * tree, Ecore_Tree_Node * top_node) +{ + Ecore_Tree_Node *temp; + + CHECK_PARAM_POINTER_RETURN("top_node", top_node, FALSE); + + /* + * The right branch's left branch becomes the nodes right branch, + * the right branch becomes the top node, and the node becomes the + * left branch. + */ + temp = top_node->left_child; + top_node->left_child = temp->right_child; + temp->right_child = top_node; + + /* Make sure the nodes know who their new parents are. */ + temp->parent = top_node->parent; + if (temp->parent == NULL) + tree->tree = temp; + else { + if (temp->parent->left_child == top_node) + temp->parent->left_child = temp; + else + temp->parent->right_child = temp; + } + top_node->parent = temp; + + /* And recalculate node heights */ + tree_node_balance(tree, top_node); + tree_node_balance(tree, temp); + + return TRUE; +} + +/* + * Description: Execute a function for each node below this point in the tree. + * Parameters: 1. node - the highest node in the tree the function will be + * executed for + * 2. for_each_func - the function to pass the nodes as data into + * Returns: FALSE if an error condition occurs, otherwise TRUE + */ +int tree_for_each_node(Ecore_Tree_Node * node, Ecore_For_Each for_each_func) +{ + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + if (node->right_child) + tree_for_each_node(node->right_child, for_each_func); + + if (node->left_child) + tree_for_each_node(node->left_child, for_each_func); + + for_each_func(node); + + return TRUE; +} + + +/* + * Description: Execute a function for each node below this point in the tree. + * Parameters: 1. node - the highest node in the tree the function will be + * executed for + * 2. for_each_func - the function to pass the nodes values as data + * Returns: FALSE if an error condition occurs, otherwise TRUE + */ +int tree_for_each_node_value(Ecore_Tree_Node * node, + Ecore_For_Each for_each_func) +{ + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + if (node->right_child) + tree_for_each_node_value(node->right_child, for_each_func); + + if (node->left_child) + tree_for_each_node_value(node->left_child, for_each_func); + + for_each_func(node->value); + + return TRUE; +} diff --git a/legacy/ecore/src/lib/ecore/ecore_value.c b/legacy/ecore/src/lib/ecore/ecore_value.c new file mode 100644 index 0000000000..3e2d1d9156 --- /dev/null +++ b/legacy/ecore/src/lib/ecore/ecore_value.c @@ -0,0 +1,122 @@ +/* ecore_value.c + +Copyright (C) 2001 Christopher Rosendahl + Nathan Ingersoll + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies of the Software and its documentation and acknowledgment shall be +given in the documentation and software packages that this Software was +used. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +#include + +const unsigned int ecore_prime_table[] = { 17, 31, 61, 127, 257, 509, 1021, + 2053, 4093, 8191, 16381, 32771, 65537, 131071, 262147, 524287, 1048573, + 2097143, 4194301, 8388617, 16777213 +}; + +inline void ecore_print_warning(char *function, char *sparam) +{ + fprintf(stderr, "***** Developer Warning ***** :\n" + "\tThis program is calling:\n\n" + "\t%s();\n\n" + "\tWith the parameter:\n\n" + "\t%s\n\n" + "\tbeing NULL. Please fix your program.\n", function, sparam); + fflush(stderr); +} + +/** + * ecore_direct_hash - just casts the key to an unsigned int + * @key: the key to return compute a hash value + * + * Returns the key cast to an unsigned int. + */ +unsigned int ecore_direct_hash(void *key) +{ + return ((unsigned int) key); +} + +/** + * ecore_str_hash - compute the hash value of a string + * @key: a pointer to the string to compute a hash value + * + * Returns a computed hash value for @key. + */ +unsigned int ecore_str_hash(void *key) +{ + int i; + unsigned int value = 0; + char *k = (char *) key; + + if (!k) + return 0; + + for (i = 0; k[i] != '\0'; i++) { + value ^= ((unsigned int) k[i] << ((i * 5) % + (sizeof(unsigned int) * 8))); + } + + return value; +} + +/** + * ecore_direct_compare - perform a direct comparison of two keys values + * @key1: the first key to compare + * @key2: the second key to compare + * + * Return a strcmp style value to indicate the larger key + */ +int ecore_direct_compare(void *key1, void *key2) +{ + unsigned int k1, k2; + + k1 = (unsigned int) key1; + k2 = (unsigned int) key2; + + if (k1 > k2) + return 1; + + if (k1 < k2) + return -1; + + return 0; +} + +/** + * ecore_direct_compare - perform a string comparison of two keys values + * @key1: the first key to compare + * @key2: the second key to compare + * + * Return a strcmp style value to indicate the larger key + */ +int ecore_str_compare(void *key1, void *key2) +{ + char *k1, *k2; + + if (!key1 || !key2) + return ecore_direct_compare(key1, key2); + else if (key1 == key2) + return 0; + + k1 = (char *) key1; + k2 = (char *) key2; + + return strcmp(k1, k2); +}