/*#io docCopyright("Steve Dekorte", 2002) docLicense("BSD revised") docDescription(""" Notes: first element of items is always 0x0. """) */ #define STACK_C #include "Stack.h" #undef STACK_C #if !defined(_MSC_VER) #include #endif #include "Datum.h" Stack *Stack_new(void) { // size is the number of pointers, including the starting NULL. int size = STACK_START_SIZE; Stack *self = (Stack *)calloc(1, sizeof(Stack)); self->items = (void **)calloc(1, size*sizeof(void *)); // memEnd points past the end of the items memory block. self->memEnd = self->items + size; self->top = self->items; //self->lastMark = self->items; return self; } void Stack_free(Stack *self) { free(self->items); free(self); } Stack *Stack_clone(Stack *self) { Stack *s = (Stack *)cpalloc(self, sizeof(Stack)); ptrdiff_t nItems = self->top - self->items; ptrdiff_t size = nItems + 1; s->items = (void **)cpalloc(self->items, size*sizeof(void *)); s->memEnd = s->items + size; s->top = s->items + nItems; return s; } void Stack_copy_(Stack *self, Stack *other) { ptrdiff_t nItems = self->top - self->items; ptrdiff_t size = nItems + 1; ptrdiff_t sizeInBytes = size*sizeof(void *); self->items = (void **)realloc(self->items, sizeInBytes); memcpy(self->items, other->items, sizeInBytes); self->memEnd = self->items + size; self->top = self->items + nItems; } // stack -------------------------------------------------- size_t Stack_memorySize(Stack *self) { return sizeof(Stack) + (self->memEnd - self->items); } void Stack_compact(Stack *self) { int oldSize = (1 + self->top - self->items)*sizeof(void *); self->items = (void **)realloc(self->items, oldSize); } void Stack_resize(Stack *self) { int oldSize = (self->memEnd - self->items)*sizeof(void *); int newSize = oldSize*STACK_RESIZE_FACTOR; int i = self->top - self->items; self->items = (void **)realloc(self->items, newSize); self->top = self->items + i; self->memEnd = self->items + (newSize/sizeof(void *)); } // sizing ------------------------------------------------ void Stack_do_on_(Stack *self, StackDoOnCallback *callback, void *target) { Stack *stack = Stack_newCopyWithNullMarks(self); int i; for(i = 0; i < Stack_count(stack) - 1; i ++) { void *v = Stack_at_(stack, i); if (v) (*callback)(target, v); } Stack_free(stack); } void Stack_makeMarksNull(Stack *self) { ptrdiff_t mark = self->lastMark; while (mark) { ptrdiff_t nextMark = (ptrdiff_t)self->items[mark]; self->items[mark] = NULL; mark = nextMark; } } Stack *Stack_newCopyWithNullMarks(Stack *self) { Stack *newStack = Stack_clone(self); Stack_makeMarksNull(newStack); return newStack; } void Stack_popToMark_(Stack *self, ptrdiff_t mark) { while (self->lastMark && self->lastMark != mark) { Stack_popMark(self); } if (self->lastMark == 0) { printf("Stack error: unable to find mark %p in %p\n", (void *)mark, (void *)self); exit(1); } Stack_popMark(self); } List *Stack_asList(Stack *self) // slow { List *list = List_new(); Stack_do_on_(self, (StackDoOnCallback *)List_append_, list); return list; }