Moved data structures to new collections subfolder

This commit is contained in:
Tobias Brunner
2012-10-24 16:00:49 +02:00
parent fdee6b5f5a
commit 12642a6831
229 changed files with 338 additions and 332 deletions
+1 -1
View File
@@ -54,7 +54,7 @@ struct private_backtrace_t {
#ifdef HAVE_BFD_H
#include <bfd.h>
#include <utils/hashtable.h>
#include <collections/hashtable.h>
#include <threading/mutex.h>
/**
-129
View File
@@ -1,129 +0,0 @@
/*
* Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2012 Giuliano Grassi
* Copyright (C) 2012 Ralf Sager
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "blocking_queue.h"
#include <threading/mutex.h>
#include <threading/thread.h>
#include <threading/condvar.h>
#include <utils/linked_list.h>
typedef struct private_blocking_queue_t private_blocking_queue_t;
/**
* Private data of a blocking_queue_t object.
*/
struct private_blocking_queue_t {
/**
* Public part
*/
blocking_queue_t public;
/**
* Linked list containing all items in the queue
*/
linked_list_t *list;
/**
* Mutex used to synchronize access to the queue
*/
mutex_t *mutex;
/**
* Condvar used to wait for items
*/
condvar_t *condvar;
};
METHOD(blocking_queue_t, enqueue, void,
private_blocking_queue_t *this, void *item)
{
this->mutex->lock(this->mutex);
this->list->insert_first(this->list, item);
this->condvar->signal(this->condvar);
this->mutex->unlock(this->mutex);
}
METHOD(blocking_queue_t, dequeue, void*,
private_blocking_queue_t *this)
{
bool oldstate;
void *item;
this->mutex->lock(this->mutex);
thread_cleanup_push((thread_cleanup_t)this->mutex->unlock, this->mutex);
/* ensure that a canceled thread does not dequeue any items */
thread_cancellation_point();
while (this->list->remove_last(this->list, &item) != SUCCESS)
{
oldstate = thread_cancelability(TRUE);
this->condvar->wait(this->condvar, this->mutex);
thread_cancelability(oldstate);
}
thread_cleanup_pop(TRUE);
return item;
}
METHOD(blocking_queue_t, destroy, void,
private_blocking_queue_t *this)
{
this->list->destroy(this->list);
this->condvar->destroy(this->condvar);
this->mutex->destroy(this->mutex);
free(this);
}
METHOD(blocking_queue_t, destroy_offset, void,
private_blocking_queue_t *this, size_t offset)
{
this->list->invoke_offset(this->list, offset);
destroy(this);
}
METHOD(blocking_queue_t, destroy_function, void,
private_blocking_queue_t *this, void (*fn)(void*))
{
this->list->invoke_function(this->list, (linked_list_invoke_t)fn);
destroy(this);
}
/*
* Described in header.
*/
blocking_queue_t *blocking_queue_create()
{
private_blocking_queue_t *this;
INIT(this,
.public = {
.enqueue = _enqueue,
.dequeue = _dequeue,
.destroy = _destroy,
.destroy_offset = _destroy_offset,
.destroy_function = _destroy_function,
},
.list = linked_list_create(),
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
);
return &this->public;
}
-97
View File
@@ -1,97 +0,0 @@
/*
* Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2012 Giuliano Grassi
* Copyright (C) 2012 Ralf Sager
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup blocking_queue blocking_queue
* @{ @ingroup utils
*/
#ifndef BLOCKING_QUEUE_H_
#define BLOCKING_QUEUE_H_
typedef struct blocking_queue_t blocking_queue_t;
#include <library.h>
/**
* Class implementing a synchronized blocking queue based on linked_list_t
*/
struct blocking_queue_t {
/**
* Inserts a new item at the tail of the queue
*
* @param item item to insert in queue
*/
void (*enqueue)(blocking_queue_t *this, void *item);
/**
* Removes the first item in the queue and returns its value.
* If the queue is empty, this call blocks until a new item is inserted.
*
* @note This is a thread cancellation point
*
* @return removed item
*/
void *(*dequeue)(blocking_queue_t *this);
/**
* Destroys a blocking_queue_t object.
*
* @note No thread must wait in dequeue() when this function is called
*/
void (*destroy)(blocking_queue_t *this);
/**
* Destroys a queue and its objects using the given destructor.
*
* If a queue and the contained objects should be destroyed, use
* destroy_offset. The supplied offset specifies the destructor to
* call on each object. The offset may be calculated using the offsetof
* macro, e.g.: queue->destroy_offset(queue, offsetof(object_t, destroy));
*
* @note No thread must wait in dequeue() when this function is called
*
* @param offset offset of the objects destructor
*/
void (*destroy_offset)(blocking_queue_t *this, size_t offset);
/**
* Destroys a queue and its objects using a cleanup function.
*
* If a queue and its contents should get destroyed using a specific
* cleanup function, use destroy_function. This is useful when the
* list contains malloc()-ed blocks which should get freed,
* e.g.: queue->destroy_function(queue, free);
*
* @note No thread must wait in dequeue() when this function is called
*
* @param function function to call on each object
*/
void (*destroy_function)(blocking_queue_t *this, void (*)(void*));
};
/**
* Creates an empty queue object.
*
* @return blocking_queue_t object.
*/
blocking_queue_t *blocking_queue_create();
#endif /** BLOCKING_QUEUE_H_ @}*/
-560
View File
@@ -1,560 +0,0 @@
/*
* Copyright (C) 2008 Tobias Brunner
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "enumerator.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <limits.h>
#include <stdio.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <debug.h>
/**
* Implementation of enumerator_create_empty().enumerate
*/
static bool enumerate_empty(enumerator_t *enumerator, ...)
{
return FALSE;
}
/**
* See header
*/
enumerator_t* enumerator_create_empty()
{
enumerator_t *this = malloc_thing(enumerator_t);
this->enumerate = enumerate_empty;
this->destroy = (void*)free;
return this;
}
/**
* Enumerator implementation for directory enumerator
*/
typedef struct {
/** implements enumerator_t */
enumerator_t public;
/** directory handle */
DIR *dir;
/** absolute path of current file */
char full[PATH_MAX];
/** where directory part of full ends and relative file gets written */
char *full_end;
} dir_enum_t;
/**
* Implementation of enumerator_create_directory().destroy
*/
static void destroy_dir_enum(dir_enum_t *this)
{
closedir(this->dir);
free(this);
}
/**
* Implementation of enumerator_create_directory().enumerate
*/
static bool enumerate_dir_enum(dir_enum_t *this, char **relative,
char **absolute, struct stat *st)
{
struct dirent *entry = readdir(this->dir);
size_t remaining;
int len;
if (!entry)
{
return FALSE;
}
if (streq(entry->d_name, ".") || streq(entry->d_name, ".."))
{
return enumerate_dir_enum(this, relative, absolute, st);
}
if (relative)
{
*relative = entry->d_name;
}
if (absolute || st)
{
remaining = sizeof(this->full) - (this->full_end - this->full);
len = snprintf(this->full_end, remaining, "%s", entry->d_name);
if (len < 0 || len >= remaining)
{
DBG1(DBG_LIB, "buffer too small to enumerate file '%s'",
entry->d_name);
return FALSE;
}
if (absolute)
{
*absolute = this->full;
}
if (st)
{
if (stat(this->full, st))
{
DBG1(DBG_LIB, "stat() on '%s' failed: %s", this->full,
strerror(errno));
return FALSE;
}
}
}
return TRUE;
}
/**
* See header
*/
enumerator_t* enumerator_create_directory(const char *path)
{
int len;
dir_enum_t *this = malloc_thing(dir_enum_t);
this->public.enumerate = (void*)enumerate_dir_enum;
this->public.destroy = (void*)destroy_dir_enum;
if (*path == '\0')
{
path = "./";
}
len = snprintf(this->full, sizeof(this->full)-1, "%s", path);
if (len < 0 || len >= sizeof(this->full)-1)
{
DBG1(DBG_LIB, "path string '%s' too long", path);
free(this);
return NULL;
}
/* append a '/' if not already done */
if (this->full[len-1] != '/')
{
this->full[len++] = '/';
this->full[len] = '\0';
}
this->full_end = &this->full[len];
this->dir = opendir(path);
if (this->dir == NULL)
{
DBG1(DBG_LIB, "opening directory '%s' failed: %s", path, strerror(errno));
free(this);
return NULL;
}
return &this->public;
}
/**
* Enumerator implementation for directory enumerator
*/
typedef struct {
/** implements enumerator_t */
enumerator_t public;
/** string to parse */
char *string;
/** current position */
char *pos;
/** separater chars */
const char *sep;
/** trim chars */
const char *trim;
} token_enum_t;
/**
* Implementation of enumerator_create_token().destroy
*/
static void destroy_token_enum(token_enum_t *this)
{
free(this->string);
free(this);
}
/**
* Implementation of enumerator_create_token().enumerate
*/
static bool enumerate_token_enum(token_enum_t *this, char **token)
{
const char *sep, *trim;
char *pos = NULL, *tmp;
bool last = FALSE;
/* trim leading characters/separators */
while (*this->pos)
{
trim = this->trim;
while (*trim)
{
if (*trim == *this->pos)
{
this->pos++;
break;
}
trim++;
}
sep = this->sep;
while (*sep)
{
if (*sep == *this->pos)
{
this->pos++;
break;
}
sep++;
}
if (!*trim && !*sep)
{
break;
}
}
switch (*this->pos)
{
case '"':
case '\'':
{
/* read quoted token */
tmp = strchr(this->pos + 1, *this->pos);
if (tmp)
{
*token = this->pos + 1;
*tmp = '\0';
this->pos = tmp + 1;
return TRUE;
}
/* unterminated string, FALL-THROUGH */
}
default:
{
/* find nearest separator */
sep = this->sep;
while (*sep)
{
tmp = strchr(this->pos, *sep);
if (tmp && (pos == NULL || tmp < pos))
{
pos = tmp;
}
sep++;
}
*token = this->pos;
if (pos)
{
*pos = '\0';
this->pos = pos + 1;
}
else
{
last = TRUE;
pos = this->pos = strchr(this->pos, '\0');
}
break;
}
}
/* trim trailing characters/separators */
pos--;
while (pos >= *token)
{
trim = this->trim;
while (*trim)
{
if (*trim == *pos)
{
*(pos--) = '\0';
break;
}
trim++;
}
sep = this->sep;
while (*sep)
{
if (*sep == *pos)
{
*(pos--) = '\0';
break;
}
sep++;
}
if (!*trim && !*sep)
{
break;
}
}
if (!last || pos >= *token)
{
return TRUE;
}
return FALSE;
}
/**
* See header
*/
enumerator_t* enumerator_create_token(const char *string, const char *sep,
const char *trim)
{
token_enum_t *enumerator = malloc_thing(token_enum_t);
enumerator->public.enumerate = (void*)enumerate_token_enum;
enumerator->public.destroy = (void*)destroy_token_enum;
enumerator->string = strdup(string);
enumerator->pos = enumerator->string;
enumerator->sep = sep;
enumerator->trim = trim;
return &enumerator->public;
}
/**
* enumerator for nested enumerations
*/
typedef struct {
/* implements enumerator_t */
enumerator_t public;
/* outer enumerator */
enumerator_t *outer;
/* inner enumerator */
enumerator_t *inner;
/* constructor for inner enumerator */
enumerator_t *(*create_inner)(void *outer, void *data);
/* data to pass to constructor above */
void *data;
/* destructor for data */
void (*destroy_data)(void *data);
} nested_enumerator_t;
/**
* Implementation of enumerator_create_nested().enumerate()
*/
static bool enumerate_nested(nested_enumerator_t *this, void *v1, void *v2,
void *v3, void *v4, void *v5)
{
while (TRUE)
{
while (this->inner == NULL)
{
void *outer;
if (!this->outer->enumerate(this->outer, &outer))
{
return FALSE;
}
this->inner = this->create_inner(outer, this->data);
}
if (this->inner->enumerate(this->inner, v1, v2, v3, v4, v5))
{
return TRUE;
}
this->inner->destroy(this->inner);
this->inner = NULL;
}
}
/**
* Implementation of enumerator_create_nested().destroy()
**/
static void destroy_nested(nested_enumerator_t *this)
{
if (this->destroy_data)
{
this->destroy_data(this->data);
}
DESTROY_IF(this->inner);
this->outer->destroy(this->outer);
free(this);
}
/**
* See header
*/
enumerator_t *enumerator_create_nested(enumerator_t *outer,
enumerator_t *(inner_constructor)(void *outer, void *data),
void *data, void (*destroy_data)(void *data))
{
nested_enumerator_t *enumerator = malloc_thing(nested_enumerator_t);
enumerator->public.enumerate = (void*)enumerate_nested;
enumerator->public.destroy = (void*)destroy_nested;
enumerator->outer = outer;
enumerator->inner = NULL;
enumerator->create_inner = (void*)inner_constructor;
enumerator->data = data;
enumerator->destroy_data = destroy_data;
return &enumerator->public;
}
/**
* enumerator for filtered enumerator
*/
typedef struct {
enumerator_t public;
enumerator_t *unfiltered;
void *data;
bool (*filter)(void *data, ...);
void (*destructor)(void *data);
} filter_enumerator_t;
/**
* Implementation of enumerator_create_filter().destroy
*/
static void destroy_filter(filter_enumerator_t *this)
{
if (this->destructor)
{
this->destructor(this->data);
}
this->unfiltered->destroy(this->unfiltered);
free(this);
}
/**
* Implementation of enumerator_create_filter().enumerate
*/
static bool enumerate_filter(filter_enumerator_t *this, void *o1, void *o2,
void *o3, void *o4, void *o5)
{
void *i1, *i2, *i3, *i4, *i5;
while (this->unfiltered->enumerate(this->unfiltered, &i1, &i2, &i3, &i4, &i5))
{
if (this->filter(this->data, &i1, o1, &i2, o2, &i3, o3, &i4, o4, &i5, o5))
{
return TRUE;
}
}
return FALSE;
}
/**
* see header
*/
enumerator_t *enumerator_create_filter(enumerator_t *unfiltered,
bool (*filter)(void *data, ...),
void *data, void (*destructor)(void *data))
{
filter_enumerator_t *this = malloc_thing(filter_enumerator_t);
this->public.enumerate = (void*)enumerate_filter;
this->public.destroy = (void*)destroy_filter;
this->unfiltered = unfiltered;
this->filter = filter;
this->data = data;
this->destructor = destructor;
return &this->public;
}
/**
* enumerator for cleaner enumerator
*/
typedef struct {
enumerator_t public;
enumerator_t *wrapped;
void (*cleanup)(void *data);
void *data;
} cleaner_enumerator_t;
/**
* Implementation of enumerator_create_cleanup().destroy
*/
static void destroy_cleaner(cleaner_enumerator_t *this)
{
this->cleanup(this->data);
this->wrapped->destroy(this->wrapped);
free(this);
}
/**
* Implementation of enumerator_create_cleaner().enumerate
*/
static bool enumerate_cleaner(cleaner_enumerator_t *this, void *v1, void *v2,
void *v3, void *v4, void *v5)
{
return this->wrapped->enumerate(this->wrapped, v1, v2, v3, v4, v5);
}
/**
* see header
*/
enumerator_t *enumerator_create_cleaner(enumerator_t *wrapped,
void (*cleanup)(void *data), void *data)
{
cleaner_enumerator_t *this = malloc_thing(cleaner_enumerator_t);
this->public.enumerate = (void*)enumerate_cleaner;
this->public.destroy = (void*)destroy_cleaner;
this->wrapped = wrapped;
this->cleanup = cleanup;
this->data = data;
return &this->public;
}
/**
* enumerator for single enumerator
*/
typedef struct {
enumerator_t public;
void *item;
void (*cleanup)(void *item);
bool done;
} single_enumerator_t;
/**
* Implementation of enumerator_create_single().destroy
*/
static void destroy_single(single_enumerator_t *this)
{
if (this->cleanup)
{
this->cleanup(this->item);
}
free(this);
}
/**
* Implementation of enumerator_create_single().enumerate
*/
static bool enumerate_single(single_enumerator_t *this, void **item)
{
if (this->done)
{
return FALSE;
}
*item = this->item;
this->done = TRUE;
return TRUE;
}
/**
* see header
*/
enumerator_t *enumerator_create_single(void *item, void (*cleanup)(void *item))
{
single_enumerator_t *this = malloc_thing(single_enumerator_t);
this->public.enumerate = (void*)enumerate_single;
this->public.destroy = (void*)destroy_single;
this->item = item;
this->cleanup = cleanup;
this->done = FALSE;
return &this->public;
}
-159
View File
@@ -1,159 +0,0 @@
/*
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup enumerator enumerator
* @{ @ingroup utils
*/
#ifndef ENUMERATOR_H_
#define ENUMERATOR_H_
typedef struct enumerator_t enumerator_t;
#include "../utils.h"
/**
* Enumerator interface, allows enumeration over collections.
*/
struct enumerator_t {
/**
* Enumerate collection.
*
* The enumerate function takes a variable argument list containing
* pointers where the enumerated values get written.
*
* @param ... variable list of enumerated items, implementation dependent
* @return TRUE if pointers returned
*/
bool (*enumerate)(enumerator_t *this, ...);
/**
* Destroy a enumerator instance.
*/
void (*destroy)(enumerator_t *this);
};
/**
* Create an enumerator which enumerates over nothing
*
* @return an enumerator over no values
*/
enumerator_t* enumerator_create_empty();
/**
* Create an enumerator which enumerates over a single item
*
* @param item item to enumerate
* @param cleanup cleanup function called on destroy with the item
* @return an enumerator over a single value
*/
enumerator_t *enumerator_create_single(void *item, void (*cleanup)(void *item));
/**
* Create an enumerator over files/subdirectories in a directory.
*
* This enumerator_t.enumerate() function returns a (to the directory) relative
* filename (as a char*), an absolute filename (as a char*) and a file status
* (to a struct stat), which all may be NULL. "." and ".." entries are
* skipped. Example:
*
* @code
char *rel, *abs;
struct stat st;
enumerator_t *e;
e = enumerator_create_directory("/tmp");
if (e)
{
while (e->enumerate(e, &rel, &abs, &st))
{
if (S_ISDIR(st.st_mode) && *rel != '.')
{
printf("%s\n", abs);
}
}
e->destroy(e);
}
@endcode
*
* @param path path of the directory
* @return the directory enumerator, NULL on failure
*/
enumerator_t* enumerator_create_directory(const char *path);
/**
* Create an enumerator over tokens of a string.
*
* Tokens are separated by one of the characters in sep and trimmed by the
* characters in trim.
*
* @param string string to parse
* @param sep separator characters
* @param trim characters to trim from tokens
* @return enumerator over char* tokens
*/
enumerator_t* enumerator_create_token(const char *string, const char *sep,
const char *trim);
/**
* Creates an enumerator which enumerates over enumerated enumerators :-).
*
* The variable argument list of enumeration values is limit to 5.
*
* @param outer outer enumerator
* @param inner_constructor constructor to inner enumerator
* @param data data to pass to each inner_constructor call
* @param destroy_data destructor to pass to data
* @return the nested enumerator
*/
enumerator_t *enumerator_create_nested(enumerator_t *outer,
enumerator_t *(*inner_constructor)(void *outer, void *data),
void *data, void (*destroy_data)(void *data));
/**
* Creates an enumerator which filters output of another enumerator.
*
* The filter function receives the user supplied "data" followed by a
* unfiltered enumeration item, followed by an output pointer where to write
* the filtered data. Then the next input/output pair follows.
* It returns TRUE to deliver the
* values to the caller of enumerate(), FALSE to filter this enumeration.
*
* The variable argument list of enumeration values is limit to 5.
*
* @param unfiltered unfiltered enumerator to wrap, gets destroyed
* @param filter filter function
* @param data user data to supply to filter
* @param destructor destructor function to clean up data after use
* @return the filtered enumerator
*/
enumerator_t *enumerator_create_filter(enumerator_t *unfiltered,
bool (*filter)(void *data, ...),
void *data, void (*destructor)(void *data));
/**
* Create an enumerator wrapper which does a cleanup on destroy.
*
* @param wrapped wrapped enumerator
* @param cleanup cleanup function called on destroy
* @param data user data to supply to cleanup
* @return the enumerator with cleanup
*/
enumerator_t *enumerator_create_cleaner(enumerator_t *wrapped,
void (*cleanup)(void *data), void *data);
#endif /** ENUMERATOR_H_ @}*/
-444
View File
@@ -1,444 +0,0 @@
/*
* Copyright (C) 2008-2012 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "hashtable.h"
/** The maximum capacity of the hash table (MUST be a power of 2) */
#define MAX_CAPACITY (1 << 30)
typedef struct pair_t pair_t;
/**
* This pair holds a pointer to the key and value it represents.
*/
struct pair_t {
/**
* Key of a hash table item.
*/
void *key;
/**
* Value of a hash table item.
*/
void *value;
/**
* Cached hash (used in case of a resize).
*/
u_int hash;
/**
* Next pair in an overflow list.
*/
pair_t *next;
};
/**
* Creates an empty pair object.
*/
static inline pair_t *pair_create(void *key, void *value, u_int hash)
{
pair_t *this;
INIT(this,
.key = key,
.value = value,
.hash = hash,
);
return this;
}
typedef struct private_hashtable_t private_hashtable_t;
/**
* Private data of a hashtable_t object.
*
*/
struct private_hashtable_t {
/**
* Public part of hash table.
*/
hashtable_t public;
/**
* The number of items in the hash table.
*/
u_int count;
/**
* The current capacity of the hash table (always a power of 2).
*/
u_int capacity;
/**
* The current mask to calculate the row index (capacity - 1).
*/
u_int mask;
/**
* The load factor.
*/
float load_factor;
/**
* The actual table.
*/
pair_t **table;
/**
* The hashing function.
*/
hashtable_hash_t hash;
/**
* The equality function.
*/
hashtable_equals_t equals;
};
typedef struct private_enumerator_t private_enumerator_t;
/**
* hash table enumerator implementation
*/
struct private_enumerator_t {
/**
* implements enumerator interface
*/
enumerator_t enumerator;
/**
* associated hash table
*/
private_hashtable_t *table;
/**
* current row index
*/
u_int row;
/**
* number of remaining items in hashtable
*/
u_int count;
/**
* current pair
*/
pair_t *current;
/**
* previous pair (used by remove_at)
*/
pair_t *prev;
};
/**
* This function returns the next-highest power of two for the given number.
* The algorithm works by setting all bits on the right-hand side of the most
* significant 1 to 1 and then increments the whole number so it rolls over
* to the nearest power of two. Note: returns 0 for n == 0
*/
static u_int get_nearest_powerof2(u_int n)
{
u_int i;
--n;
for (i = 1; i < sizeof(u_int) * 8; i <<= 1)
{
n |= n >> i;
}
return ++n;
}
/**
* Init hash table parameters
*/
static void init_hashtable(private_hashtable_t *this, u_int capacity)
{
capacity = max(1, min(capacity, MAX_CAPACITY));
this->capacity = get_nearest_powerof2(capacity);
this->mask = this->capacity - 1;
this->load_factor = 0.75;
this->table = calloc(this->capacity, sizeof(pair_t*));
}
/**
* Double the size of the hash table and rehash all the elements.
*/
static void rehash(private_hashtable_t *this)
{
pair_t **old_table;
u_int row, old_capacity;
if (this->capacity >= MAX_CAPACITY)
{
return;
}
old_capacity = this->capacity;
old_table = this->table;
init_hashtable(this, old_capacity << 1);
for (row = 0; row < old_capacity; row++)
{
pair_t *pair, *next;
u_int new_row;
pair = old_table[row];
while (pair)
{ /* insert pair at the front of new bucket*/
next = pair->next;
new_row = pair->hash & this->mask;
pair->next = this->table[new_row];
this->table[new_row] = pair;
pair = next;
}
}
free(old_table);
}
METHOD(hashtable_t, put, void*,
private_hashtable_t *this, void *key, void *value)
{
void *old_value = NULL;
pair_t *pair;
u_int hash, row;
hash = this->hash(key);
row = hash & this->mask;
pair = this->table[row];
while (pair)
{ /* search existing bucket for key */
if (this->equals(key, pair->key))
{
old_value = pair->value;
pair->value = value;
pair->key = key;
break;
}
pair = pair->next;
}
if (!pair)
{ /* insert at the front of bucket */
pair = pair_create(key, value, hash);
pair->next = this->table[row];
this->table[row] = pair;
this->count++;
}
if (this->count >= this->capacity * this->load_factor)
{
rehash(this);
}
return old_value;
}
static void *get_internal(private_hashtable_t *this, void *key,
hashtable_equals_t equals)
{
void *value = NULL;
pair_t *pair;
if (!this->count)
{ /* no need to calculate the hash */
return NULL;
}
pair = this->table[this->hash(key) & this->mask];
while (pair)
{
if (equals(key, pair->key))
{
value = pair->value;
break;
}
pair = pair->next;
}
return value;
}
METHOD(hashtable_t, get, void*,
private_hashtable_t *this, void *key)
{
return get_internal(this, key, this->equals);
}
METHOD(hashtable_t, get_match, void*,
private_hashtable_t *this, void *key, hashtable_equals_t match)
{
return get_internal(this, key, match);
}
METHOD(hashtable_t, remove_, void*,
private_hashtable_t *this, void *key)
{
void *value = NULL;
pair_t *pair, *prev = NULL;
u_int row;
row = this->hash(key) & this->mask;
pair = this->table[row];
while (pair)
{
if (this->equals(key, pair->key))
{
if (prev)
{
prev->next = pair->next;
}
else
{
this->table[row] = pair->next;
}
value = pair->value;
this->count--;
free(pair);
break;
}
prev = pair;
pair = pair->next;
}
return value;
}
METHOD(hashtable_t, remove_at, void,
private_hashtable_t *this, private_enumerator_t *enumerator)
{
if (enumerator->table == this && enumerator->current)
{
pair_t *current = enumerator->current;
if (enumerator->prev)
{
enumerator->prev->next = current->next;
}
else
{
this->table[enumerator->row] = current->next;
}
enumerator->current = enumerator->prev;
free(current);
this->count--;
}
}
METHOD(hashtable_t, get_count, u_int,
private_hashtable_t *this)
{
return this->count;
}
METHOD(enumerator_t, enumerate, bool,
private_enumerator_t *this, void **key, void **value)
{
while (this->count && this->row < this->table->capacity)
{
this->prev = this->current;
if (this->current)
{
this->current = this->current->next;
}
else
{
this->current = this->table->table[this->row];
}
if (this->current)
{
if (key)
{
*key = this->current->key;
}
if (value)
{
*value = this->current->value;
}
this->count--;
return TRUE;
}
this->row++;
}
return FALSE;
}
METHOD(hashtable_t, create_enumerator, enumerator_t*,
private_hashtable_t *this)
{
private_enumerator_t *enumerator;
INIT(enumerator,
.enumerator = {
.enumerate = (void*)_enumerate,
.destroy = (void*)free,
},
.table = this,
.count = this->count,
);
return &enumerator->enumerator;
}
METHOD(hashtable_t, destroy, void,
private_hashtable_t *this)
{
pair_t *pair, *next;
u_int row;
for (row = 0; row < this->capacity; row++)
{
pair = this->table[row];
while (pair)
{
next = pair->next;
free(pair);
pair = next;
}
}
free(this->table);
free(this);
}
/*
* Described in header.
*/
hashtable_t *hashtable_create(hashtable_hash_t hash, hashtable_equals_t equals,
u_int capacity)
{
private_hashtable_t *this;
INIT(this,
.public = {
.put = _put,
.get = _get,
.get_match = _get_match,
.remove = _remove_,
.remove_at = (void*)_remove_at,
.get_count = _get_count,
.create_enumerator = _create_enumerator,
.destroy = _destroy,
},
.hash = hash,
.equals = equals,
);
init_hashtable(this, capacity);
return &this->public;
}
-138
View File
@@ -1,138 +0,0 @@
/*
* Copyright (C) 2008-2012 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup hashtable hashtable
* @{ @ingroup utils
*/
#ifndef HASHTABLE_H_
#define HASHTABLE_H_
#include <utils/enumerator.h>
typedef struct hashtable_t hashtable_t;
/**
* Prototype for a function that computes the hash code from the given key.
*
* @param key key to hash
* @return hash code
*/
typedef u_int (*hashtable_hash_t)(void *key);
/**
* Prototype for a function that compares the two keys for equality.
*
* @param key first key (the one we are looking for)
* @param other_key second key
* @return TRUE if the keys are equal
*/
typedef bool (*hashtable_equals_t)(void *key, void *other_key);
/**
* Class implementing a hash table.
*
* General purpose hash table. This hash table is not synchronized.
*/
struct hashtable_t {
/**
* Create an enumerator over the hash table key/value pairs.
*
* @return enumerator over (void *key, void *value)
*/
enumerator_t *(*create_enumerator) (hashtable_t *this);
/**
* Adds the given value with the given key to the hash table, if there
* exists no entry with that key. NULL is returned in this case.
* Otherwise the existing value is replaced and the function returns the
* old value.
*
* @param key the key to store
* @param value the value to store
* @return NULL if no item was replaced, the old value otherwise
*/
void *(*put) (hashtable_t *this, void *key, void *value);
/**
* Returns the value with the given key, if the hash table contains such an
* entry, otherwise NULL is returned.
*
* @param key the key of the requested value
* @return the value, NULL if not found
*/
void *(*get) (hashtable_t *this, void *key);
/**
* Returns the value with a matching key, if the hash table contains such an
* entry, otherwise NULL is returned.
*
* Compared to get() the given match function is used to compare the keys
* for equality. The hash function does have to be deviced properly in
* order to make this work if the match function compares keys differently
* than the equals function provided to the constructor. This basically
* allows to enumerate all entries with the same hash value.
*
* @param key the key to match against
* @param match match function to be used when comparing keys
* @return the value, NULL if not found
*/
void *(*get_match) (hashtable_t *this, void *key, hashtable_equals_t match);
/**
* Removes the value with the given key from the hash table and returns the
* removed value (or NULL if no such value existed).
*
* @param key the key of the value to remove
* @return the removed value, NULL if not found
*/
void *(*remove) (hashtable_t *this, void *key);
/**
* Removes the key and value pair from the hash table at which the given
* enumerator currently points.
*
* @param enumerator enumerator, from create_enumerator
*/
void (*remove_at) (hashtable_t *this, enumerator_t *enumerator);
/**
* Gets the number of items in the hash table.
*
* @return number of items
*/
u_int (*get_count) (hashtable_t *this);
/**
* Destroys a hash table object.
*/
void (*destroy) (hashtable_t *this);
};
/**
* Creates an empty hash table object.
*
* @param hash hash function
* @param equals equals function
* @param capacity initial capacity
* @return hashtable_t object.
*/
hashtable_t *hashtable_create(hashtable_hash_t hash, hashtable_equals_t equals,
u_int capacity);
#endif /** HASHTABLE_H_ @}*/
+1 -1
View File
@@ -30,7 +30,7 @@ typedef enum id_match_t id_match_t;
typedef enum id_part_t id_part_t;
#include <chunk.h>
#include <utils/enumerator.h>
#include <collections/enumerator.h>
/**
* Matches returned from identification_t.match
+1 -1
View File
@@ -34,7 +34,7 @@
#include <library.h>
#include <debug.h>
#include <utils/backtrace.h>
#include <utils/hashtable.h>
#include <collections/hashtable.h>
typedef struct private_leak_detective_t private_leak_detective_t;
-615
View File
@@ -1,615 +0,0 @@
/*
* Copyright (C) 2007-2011 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stdlib.h>
#include <stdarg.h>
#include "linked_list.h"
typedef struct element_t element_t;
/**
* This element holds a pointer to the value it represents.
*/
struct element_t {
/**
* Value of a list item.
*/
void *value;
/**
* Previous list element.
*
* NULL if first element in list.
*/
element_t *previous;
/**
* Next list element.
*
* NULL if last element in list.
*/
element_t *next;
};
/**
* Creates an empty linked list object.
*/
element_t *element_create(void *value)
{
element_t *this;
INIT(this,
.value = value,
);
return this;
}
typedef struct private_linked_list_t private_linked_list_t;
/**
* Private data of a linked_list_t object.
*
*/
struct private_linked_list_t {
/**
* Public part of linked list.
*/
linked_list_t public;
/**
* Number of items in the list.
*/
int count;
/**
* First element in list.
* NULL if no elements in list.
*/
element_t *first;
/**
* Last element in list.
* NULL if no elements in list.
*/
element_t *last;
};
typedef struct private_enumerator_t private_enumerator_t;
/**
* linked lists enumerator implementation
*/
struct private_enumerator_t {
/**
* implements enumerator interface
*/
enumerator_t enumerator;
/**
* associated linked list
*/
private_linked_list_t *list;
/**
* current item
*/
element_t *current;
/**
* enumerator has enumerated all items
*/
bool finished;
};
METHOD(enumerator_t, enumerate, bool,
private_enumerator_t *this, void **item)
{
if (this->finished)
{
return FALSE;
}
if (!this->current)
{
this->current = this->list->first;
}
else
{
this->current = this->current->next;
}
if (!this->current)
{
this->finished = TRUE;
return FALSE;
}
*item = this->current->value;
return TRUE;
}
METHOD(linked_list_t, create_enumerator, enumerator_t*,
private_linked_list_t *this)
{
private_enumerator_t *enumerator;
INIT(enumerator,
.enumerator = {
.enumerate = (void*)_enumerate,
.destroy = (void*)free,
},
.list = this,
);
return &enumerator->enumerator;
}
METHOD(linked_list_t, reset_enumerator, void,
private_linked_list_t *this, private_enumerator_t *enumerator)
{
enumerator->current = NULL;
enumerator->finished = FALSE;
}
METHOD(linked_list_t, has_more, bool,
private_linked_list_t *this, private_enumerator_t *enumerator)
{
if (enumerator->current)
{
return enumerator->current->next != NULL;
}
return !enumerator->finished && this->first != NULL;
}
METHOD(linked_list_t, get_count, int,
private_linked_list_t *this)
{
return this->count;
}
METHOD(linked_list_t, insert_first, void,
private_linked_list_t *this, void *item)
{
element_t *element;
element = element_create(item);
if (this->count == 0)
{
/* first entry in list */
this->first = element;
this->last = element;
}
else
{
element->next = this->first;
this->first->previous = element;
this->first = element;
}
this->count++;
}
/**
* unlink an element form the list, returns following element
*/
static element_t* remove_element(private_linked_list_t *this,
element_t *element)
{
element_t *next, *previous;
next = element->next;
previous = element->previous;
free(element);
if (next)
{
next->previous = previous;
}
else
{
this->last = previous;
}
if (previous)
{
previous->next = next;
}
else
{
this->first = next;
}
if (--this->count == 0)
{
this->first = NULL;
this->last = NULL;
}
return next;
}
METHOD(linked_list_t, get_first, status_t,
private_linked_list_t *this, void **item)
{
if (this->count == 0)
{
return NOT_FOUND;
}
*item = this->first->value;
return SUCCESS;
}
METHOD(linked_list_t, remove_first, status_t,
private_linked_list_t *this, void **item)
{
if (get_first(this, item) == SUCCESS)
{
remove_element(this, this->first);
return SUCCESS;
}
return NOT_FOUND;
}
METHOD(linked_list_t, insert_last, void,
private_linked_list_t *this, void *item)
{
element_t *element;
element = element_create(item);
if (this->count == 0)
{
/* first entry in list */
this->first = element;
this->last = element;
}
else
{
element->previous = this->last;
this->last->next = element;
this->last = element;
}
this->count++;
}
METHOD(linked_list_t, insert_before, void,
private_linked_list_t *this, private_enumerator_t *enumerator,
void *item)
{
element_t *current, *element;
current = enumerator->current;
if (!current)
{
if (enumerator->finished)
{
this->public.insert_last(&this->public, item);
}
else
{
this->public.insert_first(&this->public, item);
}
return;
}
element = element_create(item);
if (current->previous)
{
current->previous->next = element;
element->previous = current->previous;
current->previous = element;
element->next = current;
}
else
{
current->previous = element;
element->next = current;
this->first = element;
}
this->count++;
}
METHOD(linked_list_t, replace, void*,
private_linked_list_t *this, private_enumerator_t *enumerator,
void *item)
{
void *old = NULL;
if (enumerator->current)
{
old = enumerator->current->value;
enumerator->current->value = item;
}
return old;
}
METHOD(linked_list_t, get_last, status_t,
private_linked_list_t *this, void **item)
{
if (this->count == 0)
{
return NOT_FOUND;
}
*item = this->last->value;
return SUCCESS;
}
METHOD(linked_list_t, remove_last, status_t,
private_linked_list_t *this, void **item)
{
if (get_last(this, item) == SUCCESS)
{
remove_element(this, this->last);
return SUCCESS;
}
return NOT_FOUND;
}
METHOD(linked_list_t, remove_, int,
private_linked_list_t *this, void *item, bool (*compare)(void*,void*))
{
element_t *current = this->first;
int removed = 0;
while (current)
{
if ((compare && compare(current->value, item)) ||
(!compare && current->value == item))
{
removed++;
current = remove_element(this, current);
}
else
{
current = current->next;
}
}
return removed;
}
METHOD(linked_list_t, remove_at, void,
private_linked_list_t *this, private_enumerator_t *enumerator)
{
element_t *current;
if (enumerator->current)
{
current = enumerator->current;
enumerator->current = current->previous;
remove_element(this, current);
}
}
METHOD(linked_list_t, find_first, status_t,
private_linked_list_t *this, linked_list_match_t match,
void **item, void *d1, void *d2, void *d3, void *d4, void *d5)
{
element_t *current = this->first;
while (current)
{
if ((match && match(current->value, d1, d2, d3, d4, d5)) ||
(!match && item && current->value == *item))
{
if (item != NULL)
{
*item = current->value;
}
return SUCCESS;
}
current = current->next;
}
return NOT_FOUND;
}
METHOD(linked_list_t, find_last, status_t,
private_linked_list_t *this, linked_list_match_t match,
void **item, void *d1, void *d2, void *d3, void *d4, void *d5)
{
element_t *current = this->last;
while (current)
{
if ((match && match(current->value, d1, d2, d3, d4, d5)) ||
(!match && item && current->value == *item))
{
if (item != NULL)
{
*item = current->value;
}
return SUCCESS;
}
current = current->previous;
}
return NOT_FOUND;
}
METHOD(linked_list_t, invoke_offset, void,
private_linked_list_t *this, size_t offset,
void *d1, void *d2, void *d3, void *d4, void *d5)
{
element_t *current = this->first;
linked_list_invoke_t *method;
while (current)
{
method = current->value + offset;
(*method)(current->value, d1, d2, d3, d4, d5);
current = current->next;
}
}
METHOD(linked_list_t, invoke_function, void,
private_linked_list_t *this, linked_list_invoke_t fn,
void *d1, void *d2, void *d3, void *d4, void *d5)
{
element_t *current = this->first;
while (current)
{
fn(current->value, d1, d2, d3, d4, d5);
current = current->next;
}
}
METHOD(linked_list_t, clone_offset, linked_list_t*,
private_linked_list_t *this, size_t offset)
{
element_t *current = this->first;
linked_list_t *clone;
clone = linked_list_create();
while (current)
{
void* (**method)(void*) = current->value + offset;
clone->insert_last(clone, (*method)(current->value));
current = current->next;
}
return clone;
}
METHOD(linked_list_t, clone_function, linked_list_t*,
private_linked_list_t *this, void* (*fn)(void*))
{
element_t *current = this->first;
linked_list_t *clone;
clone = linked_list_create();
while (current)
{
clone->insert_last(clone, fn(current->value));
current = current->next;
}
return clone;
}
METHOD(linked_list_t, destroy, void,
private_linked_list_t *this)
{
void *value;
/* Remove all list items before destroying list */
while (remove_first(this, &value) == SUCCESS)
{
/* values are not destroyed so memory leaks are possible
* if list is not empty when deleting */
}
free(this);
}
METHOD(linked_list_t, destroy_offset, void,
private_linked_list_t *this, size_t offset)
{
element_t *current = this->first, *next;
while (current)
{
void (**method)(void*) = current->value + offset;
(*method)(current->value);
next = current->next;
free(current);
current = next;
}
free(this);
}
METHOD(linked_list_t, destroy_function, void,
private_linked_list_t *this, void (*fn)(void*))
{
element_t *current = this->first, *next;
while (current)
{
fn(current->value);
next = current->next;
free(current);
current = next;
}
free(this);
}
/*
* Described in header.
*/
linked_list_t *linked_list_create()
{
private_linked_list_t *this;
INIT(this,
.public = {
.get_count = _get_count,
.create_enumerator = _create_enumerator,
.reset_enumerator = (void*)_reset_enumerator,
.has_more = (void*)_has_more,
.get_first = _get_first,
.get_last = _get_last,
.find_first = (void*)_find_first,
.find_last = (void*)_find_last,
.insert_first = _insert_first,
.insert_last = _insert_last,
.insert_before = (void*)_insert_before,
.replace = (void*)_replace,
.remove_first = _remove_first,
.remove_last = _remove_last,
.remove = _remove_,
.remove_at = (void*)_remove_at,
.invoke_offset = (void*)_invoke_offset,
.invoke_function = (void*)_invoke_function,
.clone_offset = _clone_offset,
.clone_function = _clone_function,
.destroy = _destroy,
.destroy_offset = _destroy_offset,
.destroy_function = _destroy_function,
},
);
return &this->public;
}
/*
* See header.
*/
linked_list_t *linked_list_create_from_enumerator(enumerator_t *enumerator)
{
linked_list_t *list;
void *item;
list = linked_list_create();
while (enumerator->enumerate(enumerator, &item))
{
list->insert_last(list, item);
}
enumerator->destroy(enumerator);
return list;
}
/*
* See header.
*/
linked_list_t *linked_list_create_with_items(void *item, ...)
{
linked_list_t *list;
va_list args;
list = linked_list_create();
va_start(args, item);
while (item)
{
list->insert_last(list, item);
item = va_arg(args, void*);
}
va_end(args);
return list;
}
-319
View File
@@ -1,319 +0,0 @@
/*
* Copyright (C) 2007-2011 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup linked_list linked_list
* @{ @ingroup utils
*/
#ifndef LINKED_LIST_H_
#define LINKED_LIST_H_
typedef struct linked_list_t linked_list_t;
#include <utils/enumerator.h>
/**
* Method to match elements in a linked list (used in find_* functions)
*
* @param item current list item
* @param ... user supplied data (only pointers, at most 5)
* @return
* - TRUE, if the item matched
* - FALSE, otherwise
*/
typedef bool (*linked_list_match_t)(void *item, ...);
/**
* Method to be invoked on elements in a linked list (used in invoke_* functions)
*
* @param item current list item
* @param ... user supplied data (only pointers, at most 5)
*/
typedef void (*linked_list_invoke_t)(void *item, ...);
/**
* Class implementing a double linked list.
*
* General purpose linked list. This list is not synchronized.
*/
struct linked_list_t {
/**
* Gets the count of items in the list.
*
* @return number of items in list
*/
int (*get_count) (linked_list_t *this);
/**
* Create an enumerator over the list.
*
* @note The enumerator's position is invalid before the first call
* to enumerate().
*
* @return enumerator over list items
*/
enumerator_t* (*create_enumerator)(linked_list_t *this);
/**
* Resets the enumerator's current position to the beginning of the list.
*
* @param enumerator enumerator to reset
*/
void (*reset_enumerator)(linked_list_t *this, enumerator_t *enumerator);
/**
* Checks if there are more elements following after the enumerator's
* current position.
*
* @param enumerator enumerator to check
*/
bool (*has_more)(linked_list_t *this, enumerator_t *enumerator);
/**
* Inserts a new item at the beginning of the list.
*
* @param item item value to insert in list
*/
void (*insert_first) (linked_list_t *this, void *item);
/**
* Removes the first item in the list and returns its value.
*
* @param item returned value of first item, or NULL
* @return SUCCESS, or NOT_FOUND if list is empty
*/
status_t (*remove_first) (linked_list_t *this, void **item);
/**
* Inserts a new item before the item the enumerator currently points to.
*
* If this method is called before starting the enumeration the item is
* inserted first. If it is called after all items have been enumerated
* the item is inserted last. This is helpful when inserting items into
* a sorted list.
*
* @note The position of the enumerator is not changed.
*
* @param enumerator enumerator with position
* @param item item value to insert in list
*/
void (*insert_before)(linked_list_t *this, enumerator_t *enumerator,
void *item);
/**
* Replaces the item the enumerator currently points to with the given item.
*
* @param enumerator enumerator with position
* @param item item value to replace current item with
* @return current item or NULL if the enumerator is at an
* invalid position
*/
void *(*replace)(linked_list_t *this, enumerator_t *enumerator, void *item);
/**
* Remove an item from the list where the enumerator points to.
*
* @param enumerator enumerator with position
*/
void (*remove_at)(linked_list_t *this, enumerator_t *enumerator);
/**
* Remove items from the list matching the given item.
*
* If a compare function is given, it is called for each item, with the
* first parameter being the current list item and the second parameter
* being the supplied item. Return TRUE from the compare function to remove
* the item, return FALSE to keep it in the list.
*
* If compare is NULL, comparison is done by pointers.
*
* @param item item to remove/pass to comparator
* @param compare compare function, or NULL
* @return number of removed items
*/
int (*remove)(linked_list_t *this, void *item, bool (*compare)(void*,void*));
/**
* Returns the value of the first list item without removing it.
*
* @param item returned value of first item
* @return SUCCESS, NOT_FOUND if list is empty
*/
status_t (*get_first) (linked_list_t *this, void **item);
/**
* Inserts a new item at the end of the list.
*
* @param item value to insert into list
*/
void (*insert_last) (linked_list_t *this, void *item);
/**
* Removes the last item in the list and returns its value.
*
* @param item returned value of last item, or NULL
* @return SUCCESS, NOT_FOUND if list is empty
*/
status_t (*remove_last) (linked_list_t *this, void **item);
/**
* Returns the value of the last list item without removing it.
*
* @param item returned value of last item
* @return SUCCESS, NOT_FOUND if list is empty
*/
status_t (*get_last) (linked_list_t *this, void **item);
/** Find the first matching element in the list.
*
* The first object passed to the match function is the current list item,
* followed by the user supplied data.
* If the supplied function returns TRUE this function returns SUCCESS, and
* the current object is returned in the third parameter, otherwise,
* the next item is checked.
*
* If match is NULL, *item and the current object are compared.
*
* @warning Only use pointers as user supplied data.
*
* @param match comparison function to call on each object, or NULL
* @param item the list item, if found
* @param ... user data to supply to match function (limited to 5 arguments)
* @return SUCCESS if found, NOT_FOUND otherwise
*/
status_t (*find_first) (linked_list_t *this, linked_list_match_t match,
void **item, ...);
/** Find the last matching element in the list.
*
* The first object passed to the match function is the current list item,
* followed by the user supplied data.
* If the supplied function returns TRUE this function returns SUCCESS, and
* the current object is returned in the third parameter, otherwise,
* the next item is checked.
*
* If match is NULL, *item and the current object are compared.
*
* @warning Only use pointers as user supplied data.
*
* @param match comparison function to call on each object, or NULL
* @param item the list item, if found
* @param ... user data to supply to match function (limited to 5 arguments)
* @return SUCCESS if found, NOT_FOUND otherwise
*/
status_t (*find_last) (linked_list_t *this, linked_list_match_t match,
void **item, ...);
/**
* Invoke a method on all of the contained objects.
*
* If a linked list contains objects with function pointers,
* invoke() can call a method on each of the objects. The
* method is specified by an offset of the function pointer,
* which can be evalutated at compile time using the offsetof
* macro, e.g.: list->invoke(list, offsetof(object_t, method));
*
* @warning Only use pointers as user supplied data.
*
* @param offset offset of the method to invoke on objects
* @param ... user data to supply to called function (limited to 5 arguments)
*/
void (*invoke_offset) (linked_list_t *this, size_t offset, ...);
/**
* Invoke a function on all of the contained objects.
*
* @warning Only use pointers as user supplied data.
*
* @param function offset of the method to invoke on objects
* @param ... user data to supply to called function (limited to 5 arguments)
*/
void (*invoke_function) (linked_list_t *this, linked_list_invoke_t function, ...);
/**
* Clones a list and its objects using the objects' clone method.
*
* @param offset offset ot the objects clone function
* @return cloned list
*/
linked_list_t *(*clone_offset) (linked_list_t *this, size_t offset);
/**
* Clones a list and its objects using a given function.
*
* @param function function that clones an object
* @return cloned list
*/
linked_list_t *(*clone_function) (linked_list_t *this, void*(*)(void*));
/**
* Destroys a linked_list object.
*/
void (*destroy) (linked_list_t *this);
/**
* Destroys a list and its objects using the destructor.
*
* If a linked list and the contained objects should be destroyed, use
* destroy_offset. The supplied offset specifies the destructor to
* call on each object. The offset may be calculated using the offsetof
* macro, e.g.: list->destroy_offset(list, offsetof(object_t, destroy));
*
* @param offset offset of the objects destructor
*/
void (*destroy_offset) (linked_list_t *this, size_t offset);
/**
* Destroys a list and its contents using a a cleanup function.
*
* If a linked list and its contents should get destroyed using a specific
* cleanup function, use destroy_function. This is useful when the
* list contains malloc()-ed blocks which should get freed,
* e.g.: list->destroy_function(list, free);
*
* @param function function to call on each object
*/
void (*destroy_function) (linked_list_t *this, void (*)(void*));
};
/**
* Creates an empty linked list object.
*
* @return linked_list_t object.
*/
linked_list_t *linked_list_create(void);
/**
* Creates a linked list from an enumerator.
*
* @param enumerator enumerator over void*, gets destroyed
* @return linked_list_t object, containing enumerated values
*/
linked_list_t *linked_list_create_from_enumerator(enumerator_t *enumerator);
/**
* Creates a linked list from a NULL terminated vararg list of items.
*
* @param first first item
* @param ... subsequent items, terminated by NULL
* @return linked_list_t object, containing passed items
*/
linked_list_t *linked_list_create_with_items(void *first, ...);
#endif /** LINKED_LIST_H_ @}*/