mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-20 12:58:08 +01:00
453 lines
7.0 KiB
C
453 lines
7.0 KiB
C
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "WUtil.h"
|
|
|
|
|
|
typedef struct W_Item {
|
|
struct W_Item *next;
|
|
struct W_Item *prev;
|
|
void *data;
|
|
int index;
|
|
} W_Item;
|
|
|
|
|
|
typedef struct W_ListBag {
|
|
W_Item *first;
|
|
W_Item *last;
|
|
int count;
|
|
} W_ListBag;
|
|
|
|
|
|
|
|
static int getItemCount(WMBag *self);
|
|
static int appendBag(WMBag *self, WMBag *bag);
|
|
static int putInBag(WMBag *self, void *item);
|
|
static int insertInBag(WMBag *self, int index, void *item);
|
|
static int removeFromBag(WMBag *bag, void *item);
|
|
static int deleteFromBag(WMBag *bag, int index);
|
|
static void *getFromBag(WMBag *bag, int index);
|
|
static int countInBag(WMBag *bag, void *item);
|
|
static int firstInBag(WMBag *bag, void *item);
|
|
static void *replaceInBag(WMBag *bag, int index, void *item);
|
|
static void sortBag(WMBag *bag, int (*comparer)(const void*, const void*));
|
|
static void emptyBag(WMBag *bag);
|
|
static void freeBag(WMBag *bag);
|
|
static void mapBag(WMBag *bag, void (*function)(void*, void*), void *data);
|
|
static int findInBag(WMBag *bag, int (*match)(void*));;
|
|
static void *first(WMBag *bag, WMBagIterator *ptr);
|
|
static void *last(WMBag *bag, WMBagIterator *ptr);
|
|
static void *next(WMBag *bag, WMBagIterator *ptr);
|
|
static void *previous(WMBag *bag, WMBagIterator *ptr);
|
|
static void *iteratorAtIndex(WMBag *bag, int index, WMBagIterator *ptr);
|
|
static int indexForIterator(WMBag *bag, WMBagIterator ptr);
|
|
|
|
|
|
static W_BagFunctions bagFunctions = {
|
|
getItemCount,
|
|
appendBag,
|
|
putInBag,
|
|
insertInBag,
|
|
removeFromBag,
|
|
deleteFromBag,
|
|
getFromBag,
|
|
firstInBag,
|
|
countInBag,
|
|
replaceInBag,
|
|
sortBag,
|
|
emptyBag,
|
|
freeBag,
|
|
mapBag,
|
|
findInBag,
|
|
first,
|
|
last,
|
|
next,
|
|
previous,
|
|
iteratorAtIndex,
|
|
indexForIterator
|
|
};
|
|
|
|
|
|
#define SELF ((W_ListBag*)self->data)
|
|
|
|
WMBag *WMCreateListBag(void)
|
|
{
|
|
return WMCreateListBagWithDestructor(NULL);
|
|
}
|
|
|
|
|
|
WMBag *WMCreateListBagWithDestructor(void (*destructor)(void*))
|
|
{
|
|
WMBag *bag;
|
|
|
|
bag = wmalloc(sizeof(WMBag));
|
|
|
|
bag->data = wmalloc(sizeof(W_ListBag));
|
|
memset(bag->data, 0, sizeof(W_ListBag));
|
|
|
|
bag->destructor = destructor;
|
|
|
|
bag->func = bagFunctions;
|
|
|
|
return bag;
|
|
}
|
|
|
|
|
|
static int getItemCount(WMBag *self)
|
|
{
|
|
return SELF->count;
|
|
}
|
|
|
|
|
|
static int appendBag(WMBag *self, WMBag *bag)
|
|
{
|
|
void *ptr;
|
|
void *data;
|
|
|
|
for (data = first(bag, &ptr); data != NULL; data = next(bag, &ptr)) {
|
|
if (!putInBag(self, data))
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int putInBag(WMBag *self, void *item)
|
|
{
|
|
W_Item *ptr;
|
|
|
|
ptr = wmalloc(sizeof(W_Item));
|
|
|
|
ptr->next = NULL;
|
|
ptr->prev = SELF->last;
|
|
ptr->data = item;
|
|
|
|
SELF->count++;
|
|
|
|
if (SELF->last)
|
|
SELF->last->next = ptr;
|
|
else {
|
|
SELF->last = ptr;
|
|
SELF->first = ptr;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int insertInBag(WMBag *self, int index, void *item)
|
|
{
|
|
W_Item *tmp;
|
|
W_Item *ptr;
|
|
|
|
if (index < 0)
|
|
index = 0;
|
|
|
|
if (index >= SELF->count) {
|
|
return putInBag(self, item);
|
|
}
|
|
|
|
ptr = wmalloc(sizeof(W_Item));
|
|
|
|
ptr->next = NULL;
|
|
ptr->prev = NULL;
|
|
ptr->data = item;
|
|
|
|
SELF->count++;
|
|
|
|
if (!SELF->first) {
|
|
SELF->first = ptr;
|
|
SELF->last = ptr;
|
|
|
|
return 1;
|
|
}
|
|
|
|
tmp = SELF->first;
|
|
while (index-- && tmp->next)
|
|
tmp = tmp->next;
|
|
|
|
if (tmp->prev) {
|
|
tmp->prev->next = ptr;
|
|
ptr->prev = tmp->prev;
|
|
ptr->next = tmp;
|
|
tmp->prev = ptr;
|
|
} else {
|
|
assert(SELF->first == tmp);
|
|
|
|
SELF->first->prev = ptr;
|
|
ptr->next = SELF->first;
|
|
|
|
SELF->first = ptr;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
static int removeFromBag(WMBag *self, void *item)
|
|
{
|
|
W_Item *ptr = SELF->first;
|
|
|
|
while (ptr) {
|
|
|
|
if (ptr->data == item) {
|
|
|
|
SELF->count--;
|
|
|
|
if (self->destructor) {
|
|
self->destructor(item);
|
|
}
|
|
if (ptr->next)
|
|
ptr->next->prev = ptr->prev;
|
|
if (ptr->prev)
|
|
ptr->prev->next = ptr->next;
|
|
|
|
if (SELF->first == ptr)
|
|
SELF->first = ptr->next;
|
|
if (SELF->last == ptr)
|
|
SELF->last = ptr->prev;
|
|
|
|
free(ptr);
|
|
return 1;
|
|
}
|
|
|
|
ptr = ptr->next;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
static int deleteFromBag(WMBag *self, int index)
|
|
{
|
|
W_Item *ptr = SELF->first;
|
|
|
|
while (ptr && index--) {
|
|
ptr = ptr->next;
|
|
}
|
|
|
|
if (ptr && index==0) {
|
|
SELF->count--;
|
|
if (self->destructor) {
|
|
self->destructor(ptr->data);
|
|
}
|
|
if (ptr->next)
|
|
ptr->next->prev = ptr->prev;
|
|
if (ptr->prev)
|
|
ptr->prev->next = ptr->next;
|
|
|
|
if (SELF->first == ptr)
|
|
SELF->first = ptr->next;
|
|
if (SELF->last == ptr)
|
|
SELF->last = ptr->prev;
|
|
|
|
free(ptr);
|
|
|
|
return 1;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
static void *getFromBag(WMBag *self, int index)
|
|
{
|
|
W_Item *ptr = SELF->first;
|
|
|
|
if (index < 0 || index > SELF->count)
|
|
return NULL;
|
|
|
|
while (ptr && index--)
|
|
ptr = ptr->next;
|
|
|
|
return ptr;
|
|
}
|
|
|
|
|
|
|
|
static int firstInBag(WMBag *self, void *item)
|
|
{
|
|
int index = 0;
|
|
W_Item *ptr = SELF->first;
|
|
|
|
while (ptr) {
|
|
if (ptr->data == item)
|
|
return index;
|
|
index++;
|
|
ptr = ptr->next;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
static int countInBag(WMBag *self, void *item)
|
|
{
|
|
int count = 0;
|
|
W_Item *ptr = SELF->first;
|
|
|
|
while (ptr) {
|
|
if (ptr->data == item)
|
|
count++;
|
|
ptr = ptr->next;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
static void *replaceInBag(WMBag *self, int index, void *item)
|
|
{
|
|
void *old;
|
|
W_Item *ptr = SELF->first;
|
|
|
|
while (ptr && index--)
|
|
ptr = ptr->next;
|
|
|
|
if (!ptr || index!=0)
|
|
return NULL;
|
|
|
|
old = ptr->data;
|
|
|
|
ptr->data = item;
|
|
|
|
return old;
|
|
}
|
|
|
|
|
|
|
|
static void sortBag(WMBag *self, int (*comparer)(const void*, const void*))
|
|
{
|
|
assert(0&&"not implemented");
|
|
}
|
|
|
|
|
|
static void emptyBag(WMBag *self)
|
|
{
|
|
W_Item *ptr = SELF->first;
|
|
W_Item *tmp;
|
|
|
|
while (ptr) {
|
|
tmp = ptr->next;
|
|
|
|
if (self->destructor) {
|
|
self->destructor(ptr->data);
|
|
}
|
|
free(ptr);
|
|
|
|
ptr = tmp;
|
|
}
|
|
SELF->count = 0;
|
|
}
|
|
|
|
|
|
static void freeBag(WMBag *self)
|
|
{
|
|
emptyBag(self);
|
|
|
|
free(self);
|
|
}
|
|
|
|
|
|
static WMBag *mapBag(WMBag *self, void * (*function)(void*, void*), void *data)
|
|
{
|
|
WMBag *bag = WMCreateListBagWithDestructor(self->destructor);
|
|
W_Item *ptr = SELF->first;
|
|
|
|
while (ptr) {
|
|
(*function)(ptr->data, data);
|
|
|
|
ptr = ptr->next;
|
|
}
|
|
return bag;
|
|
}
|
|
|
|
|
|
static int findInBag(WMBag *self, int (*match)(void*))
|
|
{
|
|
W_Item *ptr = SELF->first;
|
|
int index = 0;
|
|
|
|
while (ptr) {
|
|
if ((*match)(ptr)) {
|
|
return index;
|
|
}
|
|
index++;
|
|
ptr = ptr->next;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *first(WMBag *self, WMBagIterator *ptr)
|
|
{
|
|
*ptr = SELF->first;
|
|
|
|
if (!*ptr)
|
|
return NULL;
|
|
|
|
return SELF->first->data;
|
|
}
|
|
|
|
|
|
|
|
static void *last(WMBag *self, WMBagIterator *ptr)
|
|
{
|
|
*ptr = SELF->last;
|
|
|
|
if (!*ptr)
|
|
return NULL;
|
|
|
|
return SELF->last->data;
|
|
}
|
|
|
|
|
|
|
|
static void *next(WMBag *bag, WMBagIterator *ptr)
|
|
{
|
|
W_Item *item = *(W_Item**)ptr;
|
|
|
|
if (!item)
|
|
return NULL;
|
|
|
|
*ptr = item->next;
|
|
|
|
return item->next->data;
|
|
}
|
|
|
|
|
|
|
|
static void *previous(WMBag *bag, WMBagIterator *ptr)
|
|
{
|
|
W_Item *item = *(W_Item**)ptr;
|
|
|
|
if (!item)
|
|
return NULL;
|
|
|
|
*ptr = item->prev;
|
|
|
|
return item->prev->data;
|
|
}
|
|
|
|
|
|
|
|
static void *iteratorAtIndex(WMBag *bag, int index, WMBagIterator *ptr)
|
|
{
|
|
}
|
|
|
|
|
|
static int indexForIterator(WMBag *bag, WMBagIterator ptr)
|
|
{
|
|
}
|
|
|