/*------------------------------------------------------------------------------ stack.c - Operations on an expansion data stack Create the stack with new_stack(). When you are finished with the stack, it must be deallocated with delete_stack(). Other functions are: is_empty() - Determine if a stack is empty pop() - Pop an expansion data record from the stack push() - Push an expansion data record onto the stack ------------------------------------------------------------------------------*/ #include #include "stack.h" #define INITIAL_CAPACITY 16 /*------------------------------------------------------------------------------ delete_stack - Deallocate an expansion data stack stack = A pointer to the stack to be deallocated ------------------------------------------------------------------------------*/ void delete_stack (expansion_stack *stack) { if (stack != NULL) { for (int i = 0; i <= stack->top; i++) free (stack->data[i]); free (stack); } } /*------------------------------------------------------------------------------ is_empty - Determine if a stack is empty ------------------------------------------------------------------------------*/ int is_empty (expansion_stack *stack) { if (stack == NULL) return 1; return stack->top < 0; } /*------------------------------------------------------------------------------ new_stack - Create an expansion data stack ------------------------------------------------------------------------------*/ expansion_stack *new_stack () { expansion_stack *result = malloc (sizeof (expansion_stack) + sizeof (expansion_data *) * INITIAL_CAPACITY); if (result != NULL) { result->capacity = INITIAL_CAPACITY; result->top = -1; } return result; } /*------------------------------------------------------------------------------ pop - Pop an expansion data record from the stack ------------------------------------------------------------------------------*/ void pop (expansion_stack **stack) { if (stack != NULL && (*stack)->top >= 0 && (*stack)->top < (*stack)->capacity) { delete_expansion_data ((*stack)->data[(*stack)->top]); (*stack)->data[(*stack)->top] = NULL; (*stack)->top--; if ((*stack)->capacity > INITIAL_CAPACITY && (*stack)->top < (*stack)->capacity >> 2) { int newsize = (*stack)->capacity >> 1; if (newsize < INITIAL_CAPACITY) newsize = INITIAL_CAPACITY; expansion_stack *new = malloc (sizeof (expansion_stack) + sizeof (expansion_data *) * newsize); if (new != NULL) { *stack = new; (*stack)->capacity = newsize; } } } } /*------------------------------------------------------------------------------ push - Push an expansion data record onto the stack ------------------------------------------------------------------------------*/ int push (expansion_stack **stack, expansion_data *data) { int i, newtop; if ((*stack)->top + 1 >= (*stack)->capacity) { int newsize = sizeof (expansion_stack) + sizeof (expansion_data *) * ((*stack)->capacity << 1); expansion_stack *new = realloc (*stack, newsize); if (new == NULL) return FALSE; *stack = new; (*stack)->capacity <<= 1; } newtop = (*stack)->top + 1; (*stack)->data[newtop] = new_expansion_data (data->part_starts_at); if ((*stack)->data[newtop] == NULL) return FALSE; for (i = 0; i < data->expansions->length; i++) { append_string_to_list (&(*stack)->data[newtop]->expansions, data->expansions->list[i]); } (*stack)->top = newtop; return TRUE; }