#ifndef _ECORE_DATA_H # define _ECORE_DATA_H /** * @file Ecore_Data.h * @brief Contains threading, list, hash, debugging and tree functions. */ # ifdef __cplusplus extern "C" { # endif # 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 \ struct { \ int readers; \ pthread_mutex_t readers_mutex; \ pthread_mutex_t writers_mutex; \ pthread_cond_t readers_cond; \ } locks # define ECORE_INIT_LOCKS(structure) \ if (structure) { \ structure->readers = 0; \ pthread_mutex_init(&structure->locks.readers_mutex, NULL); \ pthread_mutex_init(&structure->locks.writers_mutex, NULL); \ pthread_cond_init(&structure->locks.readers_cond, NULL); \ } # define ECORE_DESTROY_LOCKS(structure) \ if (structure) { \ pthread_mutex_destroy(&structure->locks.readers_mutex); \ pthread_mutex_destroy(&structure->locks.writers_mutex); \ pthread_cond_destroy(&structure->readers_cond); \ } # define ECORE_READ_LOCK(structure) \ if (structure) { \ pthread_mutex_lock(&structure->locks.readers_mutex); \ structure->locks.readers++; \ pthread_mutex_unlock(&structure->locks.readers_mutex); \ } # define ECORE_READ_UNLOCK(structure) \ if (structure) { \ pthread_mutex_lock(&structure->locks.readers_mutex); \ if (--structure->locks.readers == 0) \ pthread_cond_broadcast(&structure->locks.readers_cond); \ pthread_mutex_unlock(&structure->locks.readers_mutex); \ } # define ECORE_WRITE_LOCK(structure) \ if (structure) { \ pthread_mutex_lock(&structure->locks.readers_mutex); \ pthread_mutex_lock(&structure->locks.writers_mutex); \ while (structure->locks.readers > 0) \ pthread_cond_wait(&structure->locks.readers_cond, \ &structure->locks.readers_mutex); \ pthread_mutex_unlock(&structure->locks.readers_mutex); \ } # define ECORE_WRITE_UNLOCK(structure) \ if (structure) \ pthread_mutex_unlock(&structure->locks.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 struct { } 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(void); 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(void); 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(void); 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(void); /* 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(const 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(void); /* 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); #ifdef __cplusplus } #endif #endif /* _ECORE_DATA_H */