Merge remote-tracking branch 'origin/list' into locations

This commit is contained in:
Walter Julius Hennecke 2013-04-14 22:55:28 +02:00
commit 52b278f3af
8 changed files with 373 additions and 288 deletions

View file

@ -510,13 +510,13 @@ static char *TimedMessage( void ){
} }
if(iterTimedMessages == NULL) { if(iterTimedMessages == NULL) {
iterTimedMessages = list_iterator(level.timedMessages, LIST_FRONT); iterTimedMessages = level.timedMessages->iterator(level.timedMessages, LIST_FRONT);
if(iterTimedMessages == NULL) { // something went wrong if(iterTimedMessages == NULL) { // something went wrong
return "^1RPG-X ERROR: No messages to display"; return "^1RPG-X ERROR: No messages to display";
} }
} }
c = list_cycl_next(iterTimedMessages); c = level.timedMessages->cycl_next(iterTimedMessages);
message = c->data; message = c->data;
return message; return message;

View file

@ -6338,8 +6338,8 @@ static void Cmd_getEntByTarget_f(gentity_t *ent) {
list_init(&entities, free); list_init(&entities, free);
G_GetEntityByTarget(arg, &entities); G_GetEntityByTarget(arg, &entities);
iter = list_iterator(&entities, LIST_FRONT); iter = entities.iterator(&entities, LIST_FRONT);
for(c = list_next(iter); c != NULL; c = list_next(iter)) { for(c = entities.next(iter); c != NULL; c = entities.next(iter)) {
t = c->data; t = c->data;
if(t == NULL) { if(t == NULL) {
@ -6353,7 +6353,7 @@ static void Cmd_getEntByTarget_f(gentity_t *ent) {
G_PrintfClient(ent, "ENT %i: %s\n\"", t->s.number, t->classname); G_PrintfClient(ent, "ENT %i: %s\n\"", t->s.number, t->classname);
} }
destroy_iterator(iter); destroy_iterator(iter);
list_clear(&entities); entities.clear(&entities);
} }
/* /*
@ -7379,12 +7379,12 @@ static void Cmd_findEntitiesInRadius(gentity_t *ent) {
list_init(&entities, free); list_init(&entities, free);
list_init(&ignore, free); list_init(&ignore, free);
list_append_ptr(&ignore, ent, LT_DATA); ignore.append_ptr(&ignore, ent, LT_DATA);
G_RadiusList(ent->r.currentOrigin, radius, &ignore, takeDamage, &entities); G_RadiusList(ent->r.currentOrigin, radius, &ignore, takeDamage, &entities);
list_clear(&ignore); ignore.clear(&ignore);
iter = list_iterator(&entities, LIST_FRONT); iter = entities.iterator(&entities, LIST_FRONT);
for(c = list_next(iter); c != NULL; c = list_next(iter)) { for(c = entities.next(iter); c != NULL; c = entities.next(iter)) {
t = c->data; t = c->data;
if(t == NULL) { if(t == NULL) {
@ -7400,7 +7400,7 @@ static void Cmd_findEntitiesInRadius(gentity_t *ent) {
} }
} }
destroy_iterator(iter); destroy_iterator(iter);
list_clear(&entities); entities.clear(&entities);
} }
// CCAM // CCAM
@ -7444,19 +7444,20 @@ void addShaderToList(list_p list, char *shader) {
return; return;
} }
i = list_iterator(list, LIST_FRONT); i = list->iterator(list, LIST_FRONT);
if(i == NULL) { if(i == NULL) {
return; return;
} }
for(c = list_next(i)->data; c != NULL; c = list_next(i)->data) { for(c = list->next(i); c != NULL; c = list->next(i)) {
t = c->data; t = c->data;
if(!strcmp(shader, t)) { if(!strcmp(shader, t)) {
return; return;
} }
} }
destroy_iterator(i);
list_append(list, s, LT_STRING, strlen(s)+1); list->append(list, s, LT_STRING, strlen(s)+1);
} }
extern target_alert_Shaders_s alertShaders; extern target_alert_Shaders_s alertShaders;
@ -7513,14 +7514,14 @@ void Cmd_GeneratePrecacheFile(gentity_t *ent) {
} }
} }
iter = list_iterator(shaders, LIST_FRONT); iter = shaders->iterator(shaders, LIST_FRONT);
if(iter == NULL) { if(iter == NULL) {
trap_FS_FCloseFile(f); trap_FS_FCloseFile(f);
destroy_list(shaders); destroy_list(shaders);
return; return;
} }
for(c = list_next(iter)->data; c != NULL; c = list_next(iter)->data) { for(c = shaders->next(iter); c != NULL; c = shaders->next(iter)) {
s = c->data; s = c->data;
G_Printf("\t%s\n", s); G_Printf("\t%s\n", s);
if(first) { if(first) {
@ -7535,6 +7536,7 @@ void Cmd_GeneratePrecacheFile(gentity_t *ent) {
} }
} }
trap_FS_Write("\n\"END\"", 6, f); trap_FS_Write("\n\"END\"", 6, f);
destroy_iterator(iter);
G_Printf("Done.\n"); G_Printf("Done.\n");

View file

@ -960,7 +960,7 @@ static void G_LoadTimedMessages(void) {
continue; continue;
} }
list_append(level.timedMessages, token, LT_STRING, strlen(token)+1); level.timedMessages->append(level.timedMessages, token, LT_STRING, strlen(token)+1);
} else { } else {
if(token[0] == '}') { if(token[0] == '}') {
break; break;

View file

@ -557,15 +557,15 @@ void turret_base_think (gentity_t *self)
list_init(&ignore, free); list_init(&ignore, free);
if(lastEnemy && lastEnemy->lastEnemy) { if(lastEnemy && lastEnemy->lastEnemy) {
list_append_ptr(&ignore, lastEnemy->lastEnemy, LT_DATA); ignore.append_ptr(&ignore, lastEnemy->lastEnemy, LT_DATA);
G_RadiusList( self->r.currentOrigin, self->random, &ignore, qtrue, &entity_list ); G_RadiusList( self->r.currentOrigin, self->random, &ignore, qtrue, &entity_list );
} else { } else {
G_RadiusList( self->r.currentOrigin, self->random, NULL, qtrue, &entity_list ); G_RadiusList( self->r.currentOrigin, self->random, NULL, qtrue, &entity_list );
} }
list_clear(&ignore); ignore.clear(&ignore);
iter = list_iterator(&entity_list, LIST_FRONT); iter = entity_list.iterator(&entity_list, LIST_FRONT);
for(c = list_next(iter); c != NULL; c = list_next(iter)) { for(c = entity_list.next(iter); c != NULL; c = entity_list.next(iter)) {
target = c->data; target = c->data;
if(target == NULL) { if(target == NULL) {
@ -616,7 +616,7 @@ void turret_base_think (gentity_t *self)
} }
} }
destroy_iterator(iter); destroy_iterator(iter);
list_clear(&entity_list); entity_list.clear(&entity_list);
} }
if ( self->enemy ) if ( self->enemy )

View file

@ -821,8 +821,8 @@ int G_RadiusList ( vec3_t origin, float radius, list_p ignore, qboolean takeDama
} }
if(ignore != NULL) { if(ignore != NULL) {
iter = list_iterator(ignore, LIST_FRONT); iter = ignore->iterator(ignore, LIST_FRONT);
for(c = list_next(iter); c != NULL; c = list_next(iter)) { for(c = ignore->next(iter); c != NULL; c = ignore->next(iter)) {
t = c->data; t = c->data;
if(t == NULL) { if(t == NULL) {
@ -863,7 +863,7 @@ int G_RadiusList ( vec3_t origin, float radius, list_p ignore, qboolean takeDama
} }
/* ok, we are within the radius, add us to the incoming list */ /* ok, we are within the radius, add us to the incoming list */
list_append_ptr(ent_list, ent, LT_DATA); ent_list->append_ptr(ent_list, ent, LT_DATA);
} }
/* we are done, return how many we found */ /* we are done, return how many we found */
return ent_list->length; return ent_list->length;
@ -914,8 +914,8 @@ int G_RadiusListOfTypes(list_p classnames, vec3_t origin, float radius, list_p i
} }
if(ignore != NULL) { if(ignore != NULL) {
iter = list_iterator(ignore, LIST_FRONT); iter = ignore->iterator(ignore, LIST_FRONT);
for(c = list_next(iter); c != NULL; c = list_next(iter)) { for(c = ignore->next(iter); c != NULL; c = ignore->next(iter)) {
t = c->data; t = c->data;
if(t == NULL) { if(t == NULL) {
@ -934,8 +934,8 @@ int G_RadiusListOfTypes(list_p classnames, vec3_t origin, float radius, list_p i
continue; continue;
} }
iter = list_iterator(classnames, LIST_FRONT); iter = classnames->iterator(classnames, LIST_FRONT);
for(c = list_next(iter); c != NULL; c = list_next(iter)) { for(c = classnames->next(iter); c != NULL; c = classnames->next(iter)) {
if(!strcmp(ent->classname, (char*)c->data)) { if(!strcmp(ent->classname, (char*)c->data)) {
valid = qtrue; valid = qtrue;
break; break;
@ -969,7 +969,7 @@ int G_RadiusListOfTypes(list_p classnames, vec3_t origin, float radius, list_p i
} }
/* ok, we are within the radius, add us to the incoming list */ /* ok, we are within the radius, add us to the incoming list */
list_append_ptr(ent_list, ent, LT_DATA); ent_list->append_ptr(ent_list, ent, LT_DATA);
valid = qfalse; valid = qfalse;
} }
@ -1007,8 +1007,8 @@ gentity_t *G_GetNearestEnt(char *classname, vec3_t origin, float radius, list_p
list_init(&entList, free); list_init(&entList, free);
G_RadiusList(origin, radius, ignore, takeDamage, &entList); G_RadiusList(origin, radius, ignore, takeDamage, &entList);
iter = list_iterator(&entList, LIST_FRONT); iter = entList.iterator(&entList, LIST_FRONT);
for(c = list_next(iter); c != NULL; c = list_next(iter)) { for(c = entList.next(iter); c != NULL; c = entList.next(iter)) {
t = c->data; t = c->data;
if(t == NULL) { if(t == NULL) {
@ -1039,7 +1039,7 @@ gentity_t *G_GetNearestEnt(char *classname, vec3_t origin, float radius, list_p
} }
} }
destroy_iterator(iter); destroy_iterator(iter);
list_clear(&entList); entList.clear(&entList);
return nearest; return nearest;
} }
@ -1072,8 +1072,8 @@ gentity_t *G_GetNearestPlayer(vec3_t origin, float radius, list_p ignore ) {
list_init(&entList, free); list_init(&entList, free);
G_RadiusList(origin, radius, ignore, qtrue, &entList); G_RadiusList(origin, radius, ignore, qtrue, &entList);
iter = list_iterator(&entList, LIST_FRONT); iter = entList.iterator(&entList, LIST_FRONT);
for(c = list_next(iter); c != NULL; c = list_next(iter)) { for(c = entList.next(iter); c != NULL; c = entList.next(iter)) {
t = c->data; t = c->data;
if(t == NULL) { if(t == NULL) {
@ -1092,7 +1092,7 @@ gentity_t *G_GetNearestPlayer(vec3_t origin, float radius, list_p ignore ) {
} }
} }
destroy_iterator(iter); destroy_iterator(iter);
list_clear(&entList); entList.clear(&entList);
return nearest; return nearest;
} }
@ -1109,7 +1109,7 @@ int G_GetEntityByTargetname(const char *targetname, list_p entities) {
if(!&g_entities[i]) continue; if(!&g_entities[i]) continue;
t = &g_entities[i]; t = &g_entities[i];
if(t->targetname && !Q_strncmp(t->targetname, targetname, strlen(targetname))) { if(t->targetname && !Q_strncmp(t->targetname, targetname, strlen(targetname))) {
list_append_ptr(entities, t, LT_DATA); entities->append_ptr(entities, t, LT_DATA);
} }
} }
@ -1128,7 +1128,7 @@ int G_GetEntityByTarget(const char *target, list_p entities) {
if(!&g_entities[i]) continue; if(!&g_entities[i]) continue;
t = &g_entities[i]; t = &g_entities[i];
if(t->target && !Q_strncmp(t->target, target, strlen(target))) { if(t->target && !Q_strncmp(t->target, target, strlen(target))) {
list_append_ptr(entities, t, LT_DATA); entities->append_ptr(entities, t, LT_DATA);
} }
} }
@ -1147,7 +1147,7 @@ int G_GetEntityByBmodel(char *bmodel, list_p entities) {
if(!&g_entities[i]) continue; if(!&g_entities[i]) continue;
t = &g_entities[i]; t = &g_entities[i];
if(t->model && !Q_strncmp(t->model, bmodel, strlen(bmodel))) { if(t->model && !Q_strncmp(t->model, bmodel, strlen(bmodel))) {
list_append_ptr(entities, t, LT_DATA); entities->append_ptr(entities, t, LT_DATA);
} }
} }

View file

@ -116,18 +116,18 @@ static void WP_FireHyperspanner(gentity_t *ent, qboolean alt_fire) {
/* prepare lists */ /* prepare lists */
list_init(&classnames, free); list_init(&classnames, free);
list_init(&validEnts, free); list_init(&validEnts, free);
list_append(&classnames, "func_breakable", LT_STRING, strlen("func_breakable")+1); classnames.append(&classnames, "func_breakable", LT_STRING, strlen("func_breakable")+1);
list_append(&classnames, "misc_model_breakable", LT_STRING, strlen("misc_model_breakable")+1); classnames.append(&classnames, "misc_model_breakable", LT_STRING, strlen("misc_model_breakable")+1);
/* find all vlaid entities in range */ /* find all vlaid entities in range */
count = G_RadiusListOfTypes(&classnames, ent->r.currentOrigin, 512, NULL, &validEnts); count = G_RadiusListOfTypes(&classnames, ent->r.currentOrigin, 512, NULL, &validEnts);
list_clear(&classnames); classnames.clear(&classnames);
//G_Printf("Found %d possible candidates\n", count); //G_Printf("Found %d possible candidates\n", count);
if(count) { if(count) {
trace_t tr; trace_t tr;
iter = list_iterator(&validEnts, LIST_FRONT); iter = validEnts.iterator(&validEnts, LIST_FRONT);
for(cont = list_next(iter); cont != NULL; cont = list_next(iter)) { for(cont = validEnts.next(iter); cont != NULL; cont = validEnts.next(iter)) {
e = cont->data; e = cont->data;
// TODO: fix problems with small distance // TODO: fix problems with small distance
@ -161,7 +161,7 @@ static void WP_FireHyperspanner(gentity_t *ent, qboolean alt_fire) {
} }
if(nearest == NULL || nearest->inuse == qfalse) { if(nearest == NULL || nearest->inuse == qfalse) {
list_clear(&validEnts); validEnts.clear(&validEnts);
return; return;
} }
@ -179,7 +179,7 @@ static void WP_FireHyperspanner(gentity_t *ent, qboolean alt_fire) {
G_Repair(ent, nearest, HYPERSPANNER_RATE * modifier); G_Repair(ent, nearest, HYPERSPANNER_RATE * modifier);
} }
list_clear(&validEnts); validEnts.clear(&validEnts);
} }
/* /*

View file

@ -22,22 +22,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "list.h" #include "list.h"
#include <string.h> #include <string.h>
list_p create_list() { /**
list_p list = (list_p)malloc(sizeof(struct list)); * Create a list_iter object for the linked_list list. The flag init can be
* either LIST_FRONT or LIST_BACK and indicates whether to start the iterator from the first
if(list == NULL) { * or last item in the list
return NULL; *
} * \param list pointer to a list
* \param init indicator where to start from
list->length = 0; * \return A new list iterator.
list->first = NULL; *
list->last = NULL; */
list->destructor = free; static list_iter_p list_iterator(list_p list, char init) {
return list;
}
list_iter_p list_iterator(list_p list, char init) {
list_iter_p iter = (list_iter_p)malloc(sizeof(struct list_iter)); list_iter_p iter = (list_iter_p)malloc(sizeof(struct list_iter));
if(iter == NULL) { if(iter == NULL) {
@ -58,7 +53,20 @@ list_iter_p list_iterator(list_p list, char init) {
return iter; return iter;
} }
int list_add(list_p list, void* data, dataType_t type, size_t size, char end) { /**
* Add an item with the given value, type, and size to the list.
* The data is copied by value, so the original pointer must be freed if it
* was allocated on the heap.
* Returns the length of the list if succesfull else returns 0.
*
* \param list pointer to a list
* \param data pointer to data
* \param type type of data
* \param size size of data
* \param end indicator where to add the data
* \return Count of elements in the list
*/
static int list_add(list_p list, void* data, dataType_t type, size_t size, char end) {
lnode_p node = (lnode_p)malloc(sizeof(struct linked_node)); lnode_p node = (lnode_p)malloc(sizeof(struct linked_node));
node->cont = (container_p)malloc(sizeof(container)); node->cont = (container_p)malloc(sizeof(container));
@ -101,15 +109,49 @@ int list_add(list_p list, void* data, dataType_t type, size_t size, char end) {
return list->length; return list->length;
} }
int list_append(list_p list, void* data, dataType_t type, size_t size) { /**
* Add an item with the given calue, type, and size to the end of the list.
* The data is copied by value, so the original pointer must be freed if it
* was allocated on the heap.
* Returns the length of the list if successfull else returns 0.
*
* \param list pointer to a list
* \param data pointer to data
* \param type type of data
* \param size size of data
* \return Count of elements in the list
*/
static int list_append(list_p list, void* data, dataType_t type, size_t size) {
return list_add(list, data, type, size, LIST_BACK); return list_add(list, data, type, size, LIST_BACK);
} }
int list_prepend(list_p list, void* data, dataType_t type, size_t size) { /**
* Add an item with the given calue, type, and size to the front of the list.
* The data is copied by value, so the original pointer must be freed if it
* was allocated on the heap.
* Returns the length of the list if successfull else returns 0.
*
* \param list pointer to a list
* \param data pointer to data
* \param type type of data
* \param size size of data
* \return Count of elements in the list
*/
static int list_prepend(list_p list, void* data, dataType_t type, size_t size) {
return list_add(list, data, type, size, LIST_FRONT); return list_add(list, data, type, size, LIST_FRONT);
} }
int list_add_ptr(list_p list, void* data, dataType_t type, char end) { /**
* Add a pointer to an item with the given value and type to the list.
* Returns the length of the list if succesfull else returns 0.
*
* \param list pointer to a list
* \param data pointer to data
* \param type type of the data
* \param end indicator where to insert
* \return Count of elements in the list
*/
static int list_add_ptr(list_p list, void* data, dataType_t type, char end) {
lnode_p node = (lnode_p)malloc(sizeof(struct linked_node)); lnode_p node = (lnode_p)malloc(sizeof(struct linked_node));
node->cont = (container_p)malloc(sizeof(container)); node->cont = (container_p)malloc(sizeof(container));
@ -148,15 +190,39 @@ int list_add_ptr(list_p list, void* data, dataType_t type, char end) {
return list->length; return list->length;
} }
int list_append_ptr(list_p list, void* data, dataType_t type) { /**
* Add a pointer to an item with the given calue, type, and size to the end of the list.
* Returns the length of the list if successfull else returns 0.
*
* \param list pointer to a list
* \param data pointer to data
* \param type type of data
* \return Count of elements in list
*/
static int list_append_ptr(list_p list, void* data, dataType_t type) {
return list_add_ptr(list, data, type, LIST_BACK); return list_add_ptr(list, data, type, LIST_BACK);
} }
int list_prepend_ptr(list_p list, void* data, dataType_t type) { /**
* Add a pointer to an item with the given calue, type, and size to the front of the list.
* Returns the length of the list if successfull else returns 0.
*
* \param list pointer to a list
* \param data pointer to data
* \param type type of data
* \return Count of elements in list
*/
static int list_prepend_ptr(list_p list, void* data, dataType_t type) {
return list_add_ptr(list, data, type, LIST_FRONT); return list_add_ptr(list, data, type, LIST_FRONT);
} }
container_p list_current(list_iter_p iter){ /**
* Return the data held by the current item pointed to by the iterator
*
* \param list pointer to a iterator
* \return container for the current element
*/
static container_p list_current(list_iter_p iter){
if(iter->started && iter->current != NULL) { if(iter->started && iter->current != NULL) {
return iter->current->cont; return iter->current->cont;
} }
@ -164,7 +230,14 @@ container_p list_current(list_iter_p iter){
return NULL; return NULL;
} }
container_p list_next(list_iter_p iter) { /**
* Advances the iterator to the next item in the list and returns the data
* stored there.
*
* \param list pointer to a iterator
* \return container of the next element
*/
static container_p list_next(list_iter_p iter) {
if(!iter->started && iter->current != NULL) { if(!iter->started && iter->current != NULL) {
iter->started = 1; iter->started = 1;
return iter->current->cont; return iter->current->cont;
@ -178,7 +251,15 @@ container_p list_next(list_iter_p iter) {
return NULL; return NULL;
} }
container_p list_cycl_next(list_iter_p iter) { /**
* Advances the iterator to the next item in the list and returns the data
* stored there. If the end of the list is reached it continues with the first
* element of the list.
*
* \param list pointer to a iterator
* \return container of the next element
*/
static container_p list_cycl_next(list_iter_p iter) {
if(!iter->started && iter->current != NULL) { if(!iter->started && iter->current != NULL) {
iter->started = 1; iter->started = 1;
return iter->current->cont; return iter->current->cont;
@ -193,7 +274,14 @@ container_p list_cycl_next(list_iter_p iter) {
return NULL; return NULL;
} }
container_p list_prev(list_iter_p iter) { /**
* Advances the iterator to the previous item in the list and returns the data
* stored there.
*
* \param list pointer to a iterator
* \return container of the previous element
*/
static container_p list_prev(list_iter_p iter) {
if(!iter->started&&iter->current!=NULL) { if(!iter->started&&iter->current!=NULL) {
iter->started = 1; iter->started = 1;
return iter->current->cont; return iter->current->cont;
@ -205,7 +293,15 @@ container_p list_prev(list_iter_p iter) {
return NULL; return NULL;
} }
container_p list_cycl_prev(list_iter_p iter){ /**
* Advances the iterator to the previous item in the list and returns the data
* stored there. If the start of the list is reached it continues with the last
* element of the list.
*
* \param list pointer to a iterator
* \return container of the previous element
*/
static container_p list_cycl_prev(list_iter_p iter){
if(!iter->started && iter->current != NULL) { if(!iter->started && iter->current != NULL) {
iter->started =1 ; iter->started =1 ;
return iter->current->cont; return iter->current->cont;
@ -222,15 +318,34 @@ container_p list_cycl_prev(list_iter_p iter){
return NULL; return NULL;
} }
container_p list_first(list_p list) { /**
* Gets the data stored in the first item of the list or NULL if the list is empty
*
* \param list pointer to a list
* \return container for the first element of the list
*/
static container_p list_first(list_p list) {
return list->first->cont; return list->first->cont;
} }
container_p list_last(list_p list) { /**
* Gets the data stored in the last item of the list or NULL if the list is empty
*
* \param list pointer to a list
* \return container for the last element of the list
*/
static container_p list_last(list_p list) {
return list->last->cont; return list->last->cont;
} }
container_p list_pop(list_p list) { /**
* Removes the last item in the list (LIFO order) and returns the data stored
* there. The data returned must be freed later in order to remain memory safe.
*
* \param list pointer to a list
* \return container for the last element of the list
*/
static container_p list_pop(list_p list) {
container_p cont; container_p cont;
lnode_p last = list->last; lnode_p last = list->last;
@ -255,7 +370,14 @@ container_p list_pop(list_p list) {
return cont; return cont;
} }
container_p list_poll(list_p list){ /**
* Removes the first item in the list (FIFO order) and returns the data stored
* there. The data return must be freed later in order to remain memory safe.
*
* \param list pointer to a list
* \return container for the first element of the list
*/
static container_p list_poll(list_p list){
container_p cont; container_p cont;
lnode_p first = list->first; lnode_p first = list->first;
@ -280,7 +402,16 @@ container_p list_poll(list_p list){
return cont; return cont;
} }
void list_remove(list_p list, char end) { /**
* Convenience function for completely destroying an item in the list. If the end
* flag is LIST_FRONT, an item will be polled from the front of the list and its data
* freed. If the end flag is set to LIST_BACK, an item will be popped off the end of
* the list and the data freed.
*
* \param list pointer to a list
* \param end indicator where to remove
*/
static void list_remove(list_p list, char end) {
container_p cont; container_p cont;
if(end == LIST_FRONT) { if(end == LIST_FRONT) {
@ -300,6 +431,64 @@ void list_remove(list_p list, char end) {
} }
} }
/**
* Function for completely destroying an item in the list at a given index.
*
* \param list pointer to a list
* \param idx index of the element to remove
*/
static void list_remove_at(list_p list, int idx) {
container_p cont;
list_iter_p iter;
lnode_p target = NULL;
int i;
if(idx < 0 || idx >= list->length || list->length == 0) {
return;
}
iter = list_iterator(list, LIST_FRONT);
for(cont = list_next(iter), i = 0; cont != NULL; cont = list_next(iter), i++) {
if(i == idx) {
target = iter->current;
break;
}
}
destroy_iterator(iter);
if(target == NULL) {
return;
}
if(list->length == 1) {
list->first = list->last = NULL;
list->length--;
free(target);
} else {
target->prev->next = target->next;
target->next->prev = target->prev;
if(target == list->first) {
list->first = target->next;
}
if(target == list->last) {
list->last = target->prev;
}
list->length--;
free(target);
}
if(cont != NULL) {
if(cont->pointer == 0 && cont->data != NULL) {
list->destructor(cont->data);
}
free(cont);
}
}
void destroy_list(list_p list) { void destroy_list(list_p list) {
lnode_p cur = list->first; lnode_p cur = list->first;
lnode_p next; lnode_p next;
@ -318,7 +507,12 @@ void destroy_list(list_p list) {
free(list); free(list);
} }
void list_clear(list_p list) { /**
* Remove all elements.
*
* \param list pointer to a list
*/
static void list_clear(list_p list) {
while(list->length > 0) { while(list->length > 0) {
list_remove(list, LIST_BACK); list_remove(list, LIST_BACK);
} }
@ -332,12 +526,14 @@ void destroy_iterator(list_iter_p iter) {
free(iter); free(iter);
} }
void list_init(struct list * l, void (*destructor)(void*)) { /**
memset(l, 0, sizeof(struct list)); * Get the element at the given index.
l->destructor = destructor; *
} * \param list a list
* \param idx index
container_p list_at(list_p list, int idx) { * \return element at given index or NULL if index is out of bounds
*/
static container_p list_at(list_p list, int idx) {
list_iter_p iter; list_iter_p iter;
container_p c = NULL; container_p c = NULL;
int i; int i;
@ -356,3 +552,63 @@ container_p list_at(list_p list, int idx) {
return c; return c;
} }
list_p create_list() {
list_p list = (list_p)malloc(sizeof(struct list));
if(list == NULL) {
return NULL;
}
list->length = 0;
list->first = NULL;
list->last = NULL;
list->destructor = free;
list->add = list_add;
list->add_ptr = list_add_ptr;
list->append = list_append;
list->append_ptr = list_append_ptr;
list->at = list_at;
list->clear = list_clear;
list->current = list_current;
list->cycl_next = list_cycl_next;
list->cycl_prev = list_cycl_prev;
list->end = list_first;
list->front = list_last;
list->iterator = list_iterator;
list->next = list_next;
list->poll = list_poll;
list->pop = list_pop;
list->prepend = list_prepend;
list->prepend_ptr = list_prepend_ptr;
list->prev = list_prev;
list->remove = list_remove;
list->removeAt = list_remove_at;
return list;
}
void list_init(struct list * l, void (*destructor)(void*)) {
memset(l, 0, sizeof(struct list));
l->destructor = destructor;
l->add = list_add;
l->add_ptr = list_add_ptr;
l->append = list_append;
l->append_ptr = list_append_ptr;
l->at = list_at;
l->clear = list_clear;
l->current = list_current;
l->cycl_next = list_cycl_next;
l->cycl_prev = list_cycl_prev;
l->end = list_first;
l->front = list_last;
l->iterator = list_iterator;
l->next = list_next;
l->poll = list_poll;
l->pop = list_pop;
l->prepend = list_prepend;
l->prepend_ptr = list_prepend_ptr;
l->prev = list_prev;
l->remove = list_remove;
l->removeAt = list_remove_at;
}

View file

@ -81,6 +81,16 @@ struct linked_node {
*/ */
typedef struct linked_node* lnode_p; typedef struct linked_node* lnode_p;
/**
* Type for a pointer to a list iterator.
*/
typedef struct list_iter * list_iter_p;
/**
* Type for a pointer to a list.
*/
typedef struct list * list_p;
/** /**
* Struct describing a list. * Struct describing a list.
*/ */
@ -89,27 +99,37 @@ struct list{
lnode_p first; /*!< first element of the list */ lnode_p first; /*!< first element of the list */
lnode_p last; /*!< last element of the list */ lnode_p last; /*!< last element of the list */
void (*destructor)(void*); /*!< pointer to destructor for data. Default is free. */ void (*destructor)(void*); /*!< pointer to destructor for data. Default is free. */
list_iter_p (*iterator)(list_p list, char init); /*!< creates a new list iterator */
int (*add_ptr)(list_p list, void* data, dataType_t type, char end); /*!< add a pointer to the list */
int (*append_ptr)(list_p list, void* data, dataType_t type); /*!< append a pointer to the list */
int (*prepend_ptr)(list_p list, void* data, dataType_t type); /*!< prepend a pointer to the list */
int (*add)(list_p list, void* data, dataType_t type, size_t size, char end); /*!< add data to the list */
int (*append)(list_p list, void* data, dataType_t type, size_t size); /*!< append data to the list */
int (*prepend)(list_p list, void* data, dataType_t type, size_t size); /*!< prepend data to the list */
container_p (*at)(list_p list, int idx); /*!< get container at given index */
void (*clear)(list_p list); /*!< clear the list */
container_p (*current)(list_iter_p iter); /*!< get the current element for the iterator */
container_p (*cycl_next)(list_iter_p iter); /*!< get the next element for the iterator (cyclic access) */
container_p (*cycl_prev)(list_iter_p iter); /*!< get the previous element for the iterator (cyclic acccess) */
container_p (*front)(list_p list); /*!< get the first element of the list */
container_p (*end)(list_p list); /*!< get the last element of the list */
container_p (*next)(list_iter_p iter); /*!< get the next element for the iterator */
container_p (*prev)(list_iter_p iter); /*!< get the previous element for the iterator */
container_p (*poll)(list_p list); /*<! poll */
container_p (*pop)(list_p list); /*<! pop */
void (*remove)(list_p list, char end); /*!< remove an element from the list */
void (*removeAt)(list_p list, int idx); /*!< remove an element at a specified index */
}; };
/**
* Type for a pointer to a list.
*/
typedef struct list * list_p;
/** /**
* Struct describing a list iterator. * Struct describing a list iterator.
*/ */
struct list_iter{ struct list_iter {
list_p list; /*!< the list */ list_p list; /*!< the list */
lnode_p current; /*!< current node */ lnode_p current; /*!< current node */
char started; /*!< has iteration started */ char started; /*!< has iteration started */
}; };
/**
* Type for a pointer to a list iterator.
*/
typedef struct list_iter * list_iter_p;
/** /**
* Create a linked_list object. This pointer is created on the heap and must be * Create a linked_list object. This pointer is created on the heap and must be
* cleared with a call to destroy_list to avoid memory leaks. * cleared with a call to destroy_list to avoid memory leaks.
@ -118,137 +138,6 @@ typedef struct list_iter * list_iter_p;
*/ */
list_p create_list(void); list_p create_list(void);
/**
* Create a list_iter object for the linked_list list. The flag init can be
* either LIST_FRONT or LIST_BACK and indicates whether to start the iterator from the first
* or last item in the list
*
* \param list pointer to a list
* \param init indicator where to start from
* \return A new list iterator.
*
*/
list_iter_p list_iterator(list_p list, char init);
/**
* Add a pointer to an item with the given value and type to the list.
* Returns the length of the list if succesfull else returns 0.
*
* \param list pointer to a list
* \param data pointer to data
* \param type type of the data
* \param end indicator where to insert
* \return Count of elements in the list
*/
int list_add_ptr(list_p list, void* data, dataType_t type, char end);
/**
* Add a pointer to an item with the given calue, type, and size to the end of the list.
* Returns the length of the list if successfull else returns 0.
*
* \param list pointer to a list
* \param data pointer to data
* \param type type of data
* \return Count of elements in list
*/
int list_append_ptr(list_p list, void* data, dataType_t type);
/**
* Add a pointer to an item with the given calue, type, and size to the front of the list.
* Returns the length of the list if successfull else returns 0.
*
* \param list pointer to a list
* \param data pointer to data
* \param type type of data
* \return Count of elements in list
*/
int list_prepend_ptr(list_p list, void* data, dataType_t type);
/**
* Add an item with the given value, type, and size to the list.
* The data is copied by value, so the original pointer must be freed if it
* was allocated on the heap.
* Returns the length of the list if succesfull else returns 0.
*
* \param list pointer to a list
* \param data pointer to data
* \param type type of data
* \param size size of data
* \param end indicator where to add the data
* \return Count of elements in the list
*/
int list_add(list_p list, void* data, dataType_t type, size_t size, char end);
/**
* Add an item with the given calue, type, and size to the end of the list.
* The data is copied by value, so the original pointer must be freed if it
* was allocated on the heap.
* Returns the length of the list if successfull else returns 0.
*
* \param list pointer to a list
* \param data pointer to data
* \param type type of data
* \param size size of data
* \return Count of elements in the list
*/
int list_append(list_p list, void* data, dataType_t type, size_t size);
/**
* Add an item with the given calue, type, and size to the front of the list.
* The data is copied by value, so the original pointer must be freed if it
* was allocated on the heap.
* Returns the length of the list if successfull else returns 0.
*
* \param list pointer to a list
* \param data pointer to data
* \param type type of data
* \param size size of data
* \return Count of elements in the list
*/
int list_prepend(list_p list, void* data, dataType_t type, size_t size);
/**
* Gets the data stored in the first item of the list or NULL if the list is empty
*
* \param list pointer to a list
* \return container for the first element of the list
*/
container_p list_first(list_p list);
/**
* Gets the data stored in the last item of the list or NULL if the list is empty
*
* \param list pointer to a list
* \return container for the last element of the list
*/
container_p list_last(list_p list);
/**
* Removes the last item in the list (LIFO order) and returns the data stored
* there. The data returned must be freed later in order to remain memory safe.
*
* \param list pointer to a list
* \return container for the last element of the list
*/
container_p list_pop(list_p list);
/**
* Removes the first item in the list (FIFO order) and returns the data stored
* there. The data return must be freed later in order to remain memory safe.
*
* \param list pointer to a list
* \return container for the first element of the list
*/
container_p list_poll(list_p list);
/**
* Convenience function for completely destroying an item in the list. If the end
* flag is LIST_FRONT, an item will be polled from the front of the list and its data
* freed. If the end flag is set to LIST_BACK, an item will be popped off the end of
* the list and the data freed.
*
* \param list pointer to a list
* \param end indicator where to remove
*/
void list_remove(list_p list, char end);
/** /**
* Completely free the data associated with the list. * Completely free the data associated with the list.
* *
@ -263,59 +152,6 @@ void destroy_list(list_p list);
*/ */
void destroy_iterator(list_iter_p iter); void destroy_iterator(list_iter_p iter);
/**
* Return the data held by the current item pointed to by the iterator
*
* \param list pointer to a iterator
* \return container for the current element
*/
container_p list_current(list_iter_p list);
/**
* Advances the iterator to the next item in the list and returns the data
* stored there.
*
* \param list pointer to a iterator
* \return container of the next element
*/
container_p list_next(list_iter_p list);
/**
* Advances the iterator to the previous item in the list and returns the data
* stored there.
*
* \param list pointer to a iterator
* \return container of the previous element
*/
container_p list_prev(list_iter_p list);
/**
* Advances the iterator to the next item in the list and returns the data
* stored there. If the end of the list is reached it continues with the first
* element of the list.
*
* \param list pointer to a iterator
* \return container of the next element
*/
container_p list_cycl_next(list_iter_p list);
/**
* Advances the iterator to the previous item in the list and returns the data
* stored there. If the start of the list is reached it continues with the last
* element of the list.
*
* \param list pointer to a iterator
* \return container of the previous element
*/
container_p list_cycl_prev(list_iter_p list);
/**
* Remove all elements.
*
* \param list pointer to a list
*/
void list_clear(list_p list);
/** /**
* Initialize list. For use on lists that are NOT allocated on the heap. * Initialize list. For use on lists that are NOT allocated on the heap.
* *
@ -324,13 +160,4 @@ void list_clear(list_p list);
*/ */
void list_init(struct list * l, void (*destructor)(void*)); void list_init(struct list * l, void (*destructor)(void*));
/**
* Get the element at the given index.
*
* \param list a list
* \param idx index
* \return element at given index or NULL if index is out of bounds
*/
container_p list_at(list_p list, int idx);
#endif #endif