Merge Ewd code into Ecore.

The new functions (Ecore_Data.h) have not been tested yet, be warned! :)


SVN revision: 9384
This commit is contained in:
xcomputerman 2004-03-18 05:29:54 +00:00 committed by xcomputerman
parent 002beaf9a6
commit 1034f13443
19 changed files with 4541 additions and 67 deletions

View File

@ -6,12 +6,32 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <limits.h>
#include <Ecore_Data.h>
#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))

View File

@ -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 <pthread.h>
#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 */

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -0,0 +1,648 @@
#include <Ecore.h>
#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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -0,0 +1,276 @@
#include <Ecore.h>
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;
}

View File

@ -0,0 +1,95 @@
#include <Ecore.h>
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;
}

View File

@ -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;

View File

@ -0,0 +1,402 @@
#include <Ecore.h>
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);
}

View File

@ -0,0 +1,69 @@
#include <Ecore.h>
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);
}
}

View File

@ -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;

View File

@ -0,0 +1,852 @@
/* ecore_tree.c
Copyright (C) 2001 Nathan Ingersoll <ningerso@d.umn.edu>
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 <Ecore.h>
/* 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;
}

View File

@ -0,0 +1,122 @@
/* ecore_value.c
Copyright (C) 2001 Christopher Rosendahl <smugg@fatelabs.com>
Nathan Ingersoll <ningerso@d.umn.edu>
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 <Ecore.h>
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);
}