char cvsroot_list_c[] = "$Id: list.c 10926 2008-11-11 22:17:40Z wsfulton $";
#include "dohint.h"
typedef struct List {
int maxitems;
int nitems;
DOH *file;
int line;
DOH **items;
} List;
extern DohObjInfo DohListType;
static
void more(List *l) {
l->items = (void **) DohRealloc(l->items, l->maxitems * 2 * sizeof(void *));
assert(l->items);
l->maxitems *= 2;
}
static DOH *CopyList(DOH *lo) {
List *l, *nl;
int i;
l = (List *) ObjData(lo);
nl = (List *) DohMalloc(sizeof(List));
nl->nitems = l->nitems;
nl->maxitems = l->maxitems;
nl->items = (void **) DohMalloc(l->maxitems * sizeof(void *));
for (i = 0; i < l->nitems; i++) {
nl->items[i] = l->items[i];
Incref(nl->items[i]);
}
nl->file = l->file;
if (nl->file)
Incref(nl->file);
nl->line = l->line;
return DohObjMalloc(&DohListType, nl);
}
static void DelList(DOH *lo) {
List *l = (List *) ObjData(lo);
int i;
for (i = 0; i < l->nitems; i++)
Delete(l->items[i]);
DohFree(l->items);
DohFree(l);
}
static void List_clear(DOH *lo) {
List *l = (List *) ObjData(lo);
int i;
for (i = 0; i < l->nitems; i++) {
Delete(l->items[i]);
}
l->nitems = 0;
}
static int List_insert(DOH *lo, int pos, DOH *item) {
List *l = (List *) ObjData(lo);
int i;
if (!item)
return -1;
if (!DohCheck(item)) {
item = NewString(item);
Decref(item);
}
if (pos == DOH_END)
pos = l->nitems;
if (pos < 0)
pos = 0;
if (pos > l->nitems)
pos = l->nitems;
if (l->nitems == l->maxitems)
more(l);
for (i = l->nitems; i > pos; i--) {
l->items[i] = l->items[i - 1];
}
l->items[pos] = item;
Incref(item);
l->nitems++;
return 0;
}
static int List_remove(DOH *lo, int pos) {
List *l = (List *) ObjData(lo);
int i;
if (pos == DOH_END)
pos = l->nitems - 1;
if (pos == DOH_BEGIN)
pos = 0;
assert(!((pos < 0) || (pos >= l->nitems)));
Delete(l->items[pos]);
for (i = pos; i < l->nitems - 1; i++) {
l->items[i] = l->items[i + 1];
}
l->nitems--;
return 0;
}
static int List_len(DOH *lo) {
List *l = (List *) ObjData(lo);
return l->nitems;
}
static DOH *List_get(DOH *lo, int n) {
List *l = (List *) ObjData(lo);
if (n == DOH_END)
n = l->nitems - 1;
if (n == DOH_BEGIN)
n = 0;
assert(!((n < 0) || (n >= l->nitems)));
return l->items[n];
}
static int List_set(DOH *lo, int n, DOH *val) {
List *l = (List *) ObjData(lo);
if (!val)
return -1;
assert(!((n < 0) || (n >= l->nitems)));
if (!DohCheck(val)) {
val = NewString(val);
Decref(val);
}
Delete(l->items[n]);
l->items[n] = val;
Incref(val);
Delete(val);
return 0;
}
static DohIterator List_first(DOH *lo) {
DohIterator iter;
List *l = (List *) ObjData(lo);
iter.object = lo;
iter._index = 0;
iter._current = 0;
iter.key = 0;
if (l->nitems > 0) {
iter.item = l->items[0];
} else {
iter.item = 0;
}
return iter;
}
static DohIterator List_next(DohIterator iter) {
List *l = (List *) ObjData(iter.object);
iter._index = iter._index + 1;
if (iter._index >= l->nitems) {
iter.item = 0;
iter.key = 0;
} else {
iter.item = l->items[iter._index];
}
return iter;
}
static DOH *List_str(DOH *lo) {
DOH *s;
int i;
List *l = (List *) ObjData(lo);
s = NewStringEmpty();
if (ObjGetMark(lo)) {
Printf(s, "List(%x)", lo);
return s;
}
ObjSetMark(lo, 1);
Printf(s, "List[ ");
for (i = 0; i < l->nitems; i++) {
Printf(s, "%s", l->items[i]);
if ((i + 1) < l->nitems)
Printf(s, ", ");
}
Printf(s, " ]\n");
ObjSetMark(lo, 0);
return s;
}
static int List_dump(DOH *lo, DOH *out) {
int nsent = 0;
int i, ret;
List *l = (List *) ObjData(lo);
for (i = 0; i < l->nitems; i++) {
ret = Dump(l->items[i], out);
if (ret < 0)
return -1;
nsent += ret;
}
return nsent;
}
static void List_setfile(DOH *lo, DOH *file) {
DOH *fo;
List *l = (List *) ObjData(lo);
if (!DohCheck(file)) {
fo = NewString(file);
Decref(fo);
} else
fo = file;
Incref(fo);
Delete(l->file);
l->file = fo;
}
static DOH *List_getfile(DOH *lo) {
List *l = (List *) ObjData(lo);
return l->file;
}
static void List_setline(DOH *lo, int line) {
List *l = (List *) ObjData(lo);
l->line = line;
}
static int List_getline(DOH *lo) {
List *l = (List *) ObjData(lo);
return l->line;
}
static DohListMethods ListListMethods = {
List_get,
List_set,
List_remove,
List_insert,
0,
};
DohObjInfo DohListType = {
"List",
DelList,
CopyList,
List_clear,
List_str,
0,
List_dump,
List_len,
0,
0,
0,
List_first,
List_next,
List_setfile,
List_getfile,
List_setline,
List_getline,
0,
&ListListMethods,
0,
0,
0,
0,
};
#define MAXLISTITEMS 8
DOH *DohNewList(void) {
List *l;
int i;
l = (List *) DohMalloc(sizeof(List));
l->nitems = 0;
l->maxitems = MAXLISTITEMS;
l->items = (void **) DohMalloc(l->maxitems * sizeof(void *));
for (i = 0; i < MAXLISTITEMS; i++) {
l->items[i] = 0;
}
l->file = 0;
l->line = 0;
return DohObjMalloc(&DohListType, l);
}
static int (*List_sort_compare_func) (const DOH *, const DOH *);
static int List_qsort_compare(const void *a, const void *b) {
return List_sort_compare_func(*((DOH **) a), *((DOH **) b));
}
void DohSortList(DOH *lo, int (*cmp) (const DOH *, const DOH *)) {
List *l = (List *) ObjData(lo);
if (cmp) {
List_sort_compare_func = cmp;
} else {
List_sort_compare_func = DohCmp;
}
qsort(l->items, l->nitems, sizeof(DOH *), List_qsort_compare);
}