#include <stdio.h>
#include "linklist.h"
LinkedList *CreateList()
{
LinkedList *list = (LinkedList *)
malloc
(
sizeof
(LinkedList));
if
(list)
{
#ifdef DEBUG
printf
(
"(linklist.c) Created new LinkedList at address 0x%p \n"
,list);
#endif
InitList(list);
list->
free
= 1;
}
return
list;
}
void
InitList(LinkedList *list)
{
memset
(list,0,
sizeof
(LinkedList));
#ifdef THREADED
pthread_mutex_init(&list->lock,NULL);
#endif
#ifdef DEBUG
printf
(
"(linklist.c) Initialized LinkedList at address 0x%p \n"
,list);
#endif
}
void
DestroyList(LinkedList *list)
{
if
(list)
{
ClearList(list);
#ifdef THREADED
pthread_mutex_destroy(&list->lock);
#endif
if
(list->
free
)
free
(list);
}
#ifdef DEBUG
printf
(
"(linklist.c) Destroyed LinkedList at address 0x%p \n"
,list);
#endif
}
void
ClearList(LinkedList *list)
{
ListEntry *e;
while
((e = ShiftEntry(list)) != NULL)
{
if
(e->tagged && e->value)
DestroyTaggedValue(e->value);
DestroyEntry(e);
}
}
unsigned
long
ListLength(LinkedList *l)
{
unsigned
long
len;
#ifdef THREADED
pthread_mutex_lock(&l->lock);
#endif
len = l->length;
#ifdef THREADED
pthread_mutex_unlock(&l->lock);
#endif
return
len;
}
ListEntry *CreateEntry()
{
ListEntry *newEntry = (ListEntry *)
calloc
(1,
sizeof
(ListEntry));
#ifdef DEBUG
printf
(
"(linklist.c) Created Entry at address 0x%p \n"
,newEntry);
#endif
return
newEntry;
}
void
DestroyEntry(ListEntry *entry)
{
unsigned
long
pos;
if
(entry)
{
if
(entry->list)
{
pos = GetEntryPosition(entry);
if
(pos) RemoveEntry(entry->list,pos);
}
#ifdef DEBUG
printf
(
"(linklist.c) Destroyed Entry at address 0x%p \n"
,entry);
#endif
free
(entry);
}
}
void
*GetEntryValue(ListEntry *entry)
{
return
entry->value;
}
void
SetEntryValue(ListEntry *entry,
void
*val)
{
entry->value = val;
}
ListEntry *PopEntry(LinkedList *list)
{
ListEntry *entry;
#ifdef THREADED
pthread_mutex_lock(&list->lock);
#endif
entry = list->tail;
if
(entry)
{
list->tail = entry->prev;
if
(list->tail)
list->tail->next = NULL;
list->length--;
entry->list = NULL;
}
if
(list->length == 0)
list->head = list->tail = NULL;
#ifdef THREADED
pthread_mutex_unlock(&list->lock);
#endif
return
entry;
}
int
PushEntry(LinkedList *list,ListEntry *entry)
{
ListEntry *p;
if
(!entry)
return
0;
#ifdef THREADED
pthread_mutex_lock(&list->lock);
#endif
if
(list->length == 0)
{
list->head = list->tail = entry;
}
else
{
p = list->tail;
p->next = entry;
entry->prev = p;
entry->next = NULL;
list->tail = entry;
}
list->length++;
entry->list = list;
#ifdef THREADED
pthread_mutex_unlock(&list->lock);
#endif
return
1;
}
ListEntry *ShiftEntry(LinkedList *list)
{
ListEntry *entry;
#ifdef THREADED
pthread_mutex_lock(&list->lock);
#endif
entry = list->head;
if
(entry)
{
list->head = entry->next;
if
(list->head)
list->head->prev = NULL;
list->length--;
entry->list = NULL;
}
if
(list->length == 0)
list->head = list->tail = NULL;
#ifdef THREADED
pthread_mutex_unlock(&list->lock);
#endif
return
entry;
}
int
UnshiftEntry(LinkedList *list,ListEntry *entry)
{
ListEntry *p;
if
(!entry)
return
0;
#ifdef THREADED
pthread_mutex_lock(&list->lock);
#endif
if
(list->length == 0)
{
list->head = list->tail = entry;
}
else
{
p = list->head;
p->prev = entry;
entry->prev = NULL;
entry->next = p;
list->head = entry;
}
list->length++;
entry->list = list;
#ifdef THREADED
pthread_mutex_unlock(&list->lock);
#endif
return
1;
}
int
InsertEntry(LinkedList *list,ListEntry *entry,unsigned
long
pos)
{
ListEntry *prev,*next;
if
(pos == 1)
return
UnshiftEntry(list,entry);
else
if
(pos == list->length)
return
PushEntry(list,entry);
prev = PickEntry(list,pos);
#ifdef THREADED
pthread_mutex_lock(&list->lock);
#endif
if
(prev)
{
next = prev->next;
prev->next = entry;
entry->prev = prev;
entry->next = next;
next->prev = entry;
list->length++;
#ifdef THREADED
pthread_mutex_unlock(&list->lock);
#endif
return
1;
}
#ifdef THREADED
pthread_mutex_unlock(&list->lock);
#endif
return
0;
}
ListEntry *PickEntry(LinkedList *list,unsigned
long
pos)
{
int
i;
ListEntry *entry;
if
(list->length < pos)
return
NULL;
#ifdef THREADED
pthread_mutex_lock(&list->lock);
#endif
if
(pos > list->length/2)
{
entry = list->tail;
for
(i=list->length;i>(
int
)pos;i--)
entry = entry->prev;
}
else
{
entry = list->head;
for
(i=1;i<(
int
)pos;i++)
entry = entry->next;
}
#ifdef THREADED
pthread_mutex_unlock(&list->lock);
#endif
return
entry;
}
ListEntry *FetchEntry(LinkedList *list,unsigned
long
pos)
{
ListEntry *entry;
if
(pos == 1 )
return
ShiftEntry(list);
else
if
(pos == list->length)
return
PopEntry(list);
entry = PickEntry(list,pos);
if
(RemoveEntry(list,pos) == 0)
return
entry;
return
NULL;
}
int
MoveEntry(LinkedList *list,unsigned
long
srcPos,unsigned
long
dstPos)
{
ListEntry *e;
e = FetchEntry(list,srcPos);
if
(e)
{
if
(InsertEntry(list,e,dstPos) == 0)
return
0;
else
{
if
(!InsertEntry(list,e,srcPos) != 0)
{
#ifdef DEBUG
printf
(
"(linklist.c) Can't restore entry at index %lu while moving to %lu\n"
,srcPos,dstPos);
#endif
}
}
}
return
-1;
}
int
SwapEntries(LinkedList *list,unsigned
long
pos1,unsigned
long
pos2)
{
ListEntry *e1;
ListEntry *e2;
if
(pos2 > pos1)
{
e2 = FetchEntry(list,pos2);
InsertEntry(list,e2,pos1);
e1 = FetchEntry(list,pos1+1);
InsertEntry(list,e1,pos2);
}
else
if
(pos1 > pos2)
{
e1 = FetchEntry(list,pos1);
InsertEntry(list,e1,pos2);
e2 = FetchEntry(list,pos2+1);
InsertEntry(list,e2,pos1);
}
else
return
-1;
return
0;
}
ListEntry *SubstEntry(LinkedList *list,unsigned
long
pos,ListEntry *entry)
{
ListEntry *old;
old = FetchEntry(list,pos);
if
(!old)
return
NULL;
InsertEntry(list,entry,pos);
return
old;
}
ListEntry *RemoveEntry(LinkedList *list,unsigned
long
pos)
{
ListEntry *next,*prev;
ListEntry *entry = PickEntry(list,pos);
#ifdef THREADED
pthread_mutex_lock(&list->lock);
#endif
if
(entry)
{
prev = entry->prev;
next = entry->next;
if
(prev)
prev->next = next;
if
(next)
next->prev = prev;
list->length--;
entry->list = NULL;
#ifdef THREADED
pthread_mutex_unlock(&list->lock);
#endif
return
entry;
}
#ifdef THREADED
pthread_mutex_unlock(&list->lock);
#endif
return
NULL;
}
unsigned
long
GetEntryPosition(ListEntry *entry)
{
int
i = 0;
LinkedList *list;
ListEntry *p;
list = entry->list;
if
(list)
{
p = list->head;
while
(p)
{
i++;
if
(p == entry)
return
i;
p = p->next;
}
}
return
0;
}
void
*PopValue(LinkedList *list)
{
void
*val = NULL;
ListEntry *entry = PopEntry(list);
if
(entry)
{
val = GetEntryValue(entry);
DestroyEntry(entry);
}
return
val;
}
int
PushValue(LinkedList *list,
void
*val)
{
int
res;
ListEntry *newEntry = CreateEntry();
if
(!newEntry)
return
-1;
SetEntryValue(newEntry,val);
res = PushEntry(list,newEntry);
if
(!res) DestroyEntry(newEntry);
return
res;
}
int
UnshiftValue(LinkedList *list,
void
*val)
{
int
res;
ListEntry *newEntry = CreateEntry();
if
(!newEntry)
return
-1;
SetEntryValue(newEntry,val);
res = UnshiftEntry(list,newEntry);
if
(!res) DestroyEntry(newEntry);
return
res;
}
void
*ShiftValue(LinkedList *list)
{
void
*val = NULL;
ListEntry *entry = ShiftEntry(list);
if
(entry)
{
val = GetEntryValue(entry);
DestroyEntry(entry);
}
return
val;
}
int
InsertValue(LinkedList *list,
void
*val,unsigned
long
pos)
{
int
res;
ListEntry *newEntry = CreateEntry();
if
(!newEntry)
return
-1;
SetEntryValue(newEntry,val);
res=InsertEntry(list,newEntry,pos);
if
(!res) DestroyEntry(newEntry);
return
res;
}
void
*PickValue(LinkedList *list,unsigned
long
pos)
{
ListEntry *entry = PickEntry(list,pos);
if
(entry)
return
GetEntryValue(entry);
return
NULL;
}
void
*FetchValue(LinkedList *list,unsigned
long
pos)
{
void
*val = NULL;
ListEntry *entry = FetchEntry(list,pos);
if
(entry)
{
val = GetEntryValue(entry);
DestroyEntry(entry);
}
return
val;
}
int
MoveValue(LinkedList *list,unsigned
long
srcPos,unsigned
long
dstPos)
{
return
MoveEntry(list,srcPos,dstPos);
}
void
*SubstValue(LinkedList *list,unsigned
long
pos,
void
*newVal)
{
ListEntry *newEntry;
ListEntry *oldEntry;
void
*oldVal;
newEntry = CreateEntry();
if
(newEntry)
{
SetEntryValue(newEntry,newVal);
oldEntry = SubstEntry(list,pos,newEntry);
if
(oldEntry)
{
oldVal = GetEntryValue(oldEntry);
DestroyEntry(oldEntry);
return
oldVal;
}
}
return
NULL;
}
int
SwapValues(LinkedList *list,unsigned
long
pos1,unsigned
long
pos2)
{
return
SwapEntries(list,pos1,pos2);
}
void
ForEachListValue(LinkedList *list,
void
(*itemHandler)(
void
*item,unsigned
long
idx,
void
*user),
void
*user)
{
unsigned
long
i;
unsigned
long
len = ListLength(list);
for
(i=1;i<=len;i++)
itemHandler(PickValue(list,i),i,user);
}
TaggedValue *CreateTaggedValue(
char
*tag,
void
*val,unsigned
long
vLen)
{
TaggedValue *newVal = (TaggedValue *)
calloc
(1,
sizeof
(TaggedValue));
if
(!newVal)
return
NULL;
if
(tag) newVal->tag = strdup(tag);
if
(val)
{
if
(vLen)
{
newVal->value =
malloc
(vLen+1);
if
(newVal->value)
{
memcpy
(newVal->value,val,vLen);
memset
((
char
*)newVal->value+vLen,0,1);
newVal->vLen = vLen;
}
}
else
{
newVal->value = (
void
*)strdup((
char
*)val);
newVal->vLen = (unsigned
long
)
strlen
((
char
*)val);
}
}
#ifdef DEBUG
printf
(
"(linklist.c) Created TaggedValue at address 0x%p \n"
,newVal);
#endif
return
newVal;
}
void
DestroyTaggedValue(TaggedValue *tVal)
{
if
(tVal)
{
if
(tVal->tag)
free
(tVal->tag);
if
(tVal->value)
free
(tVal->value);
free
(tVal);
}
#ifdef DEBUG
printf
(
"(linklist.c) Destroyed TaggedValue at address 0x%p \n"
,tVal);
#endif
}
TaggedValue *PopTaggedValue(LinkedList *list)
{
return
(TaggedValue *)PopValue(list);
}
int
PushTaggedValue(LinkedList *list,TaggedValue *tVal)
{
ListEntry *newEntry;
int
res = 0;
if
(tVal)
{
newEntry = CreateEntry();
if
(newEntry)
{
newEntry->tagged = 1;
newEntry->value = tVal;
res = PushEntry(list,newEntry);
if
(!res) DestroyEntry(newEntry);
}
}
return
res;
}
int
UnshiftTaggedValue(LinkedList *list,TaggedValue *tVal)
{
int
res = 0;
ListEntry *newEntry;
if
(tVal)
{
newEntry = CreateEntry();
if
(newEntry)
{
newEntry->tagged = 1;
newEntry->value = tVal;
res = UnshiftEntry(list,newEntry);
if
(!res) DestroyEntry(newEntry);
}
}
return
res;
}
TaggedValue *ShiftTaggedValue(LinkedList *list)
{
return
(TaggedValue *)ShiftValue(list);
}
int
InsertTaggedValue(LinkedList *list,TaggedValue *tVal,unsigned
long
pos)
{
int
res = 0;
ListEntry *newEntry;
if
(tVal)
{
newEntry = CreateEntry();
if
(newEntry)
{
newEntry->tagged = 1;
newEntry->value = tVal;
res = InsertEntry(list,newEntry,pos);
if
(!res) DestroyEntry(newEntry);
}
}
return
res;
}
TaggedValue *PickTaggedValue(LinkedList *list,unsigned
long
pos)
{
return
(TaggedValue *)PickValue(list,pos);
}
TaggedValue *FetchTaggedValue(LinkedList *list,unsigned
long
pos)
{
return
(TaggedValue *)FetchValue(list,pos);
}
TaggedValue *GetTaggedValue(LinkedList *list,
char
*tag)
{
int
i;
TaggedValue *tVal;
for
(i = 1;i <= (
int
)ListLength(list); i++)
{
tVal = PickTaggedValue(list,i);
if
(
strcmp
(tVal->tag,tag) == 0)
return
tVal;
}
return
NULL;
}
unsigned
long
GetTaggedValues(LinkedList *list,
char
*tag, LinkedList *values)
{
int
i;
int
ret;
TaggedValue *tVal;
ret = 0;
for
(i = 1;i <= (
int
)ListLength(list); i++)
{
tVal = PickTaggedValue(list,i);
if
(
strcmp
(tVal->tag,tag) == 0)
{
PushValue(values,tVal->value);
ret++;
}
}
return
ret;
}