miller/c/containers/loop_stack.c
2016-10-14 19:52:13 -04:00

77 lines
3.2 KiB
C

#include "lib/mlr_globals.h"
#include "lib/mlrutil.h"
#include "loop_stack.h"
#define INITIAL_SIZE 32
// Example states:
// num_allocated = 4 num_allocated = 4 num_allocated = 4 num_allocated = 4
// num_used = 1 num_used = 2 num_used = 3 num_used = 4
// num_used_minus_one = 0 num_used_minus_one = 1 num_used_minus_one = 2 num_used_minus_one = 3
//
// +---+ +---+ +---+ +---+
// | 2 | 0 <--- top | 2 | 0 | 2 | 0 | 2 | 0
// +---+ +---+ +---+ +---+
// |///| 1 | 0 | 1 <--- top | 0 | 1 | 0 |
// +---+ +---+ +---+ +---+
// |///| 2 |///| 2 | 4 | 2 <--- top | 4 |
// +---+ +---+ +---+ +---+
// |///| 3 |///| 3 |///| 3 | 6 | 3 <--- top
// +---+ +---+ +---+ +---+
// ----------------------------------------------------------------
loop_stack_t* loop_stack_alloc() {
loop_stack_t* pstack = mlr_malloc_or_die(sizeof(loop_stack_t));
// Guard zone of one. As noted in the header file, set/get are intentionally not bounds-checked.
// If set is called without push, or after final pop, we can at least not corrupt other code.
pstack->num_used_minus_one = 0;
pstack->num_allocated = INITIAL_SIZE;
pstack->pframes = mlr_malloc_or_die(pstack->num_allocated * sizeof(int));
memset(pstack->pframes, 0, pstack->num_allocated * sizeof(int));
return pstack;
}
// ----------------------------------------------------------------
void loop_stack_free(loop_stack_t* pstack) {
if (pstack == NULL)
return;
free(pstack->pframes);
free(pstack);
}
// ----------------------------------------------------------------
void loop_stack_push(loop_stack_t* pstack) {
if (pstack->num_used_minus_one >= pstack->num_allocated - 1) {
pstack->num_allocated += INITIAL_SIZE;
pstack->pframes = mlr_realloc_or_die(pstack->pframes, pstack->num_allocated * sizeof(int));
}
pstack->num_used_minus_one++;
pstack->pframes[pstack->num_used_minus_one] = 0;
}
// ----------------------------------------------------------------
int loop_stack_pop(loop_stack_t* pstack) {
MLR_INTERNAL_CODING_ERROR_IF(pstack->num_used_minus_one <= 0);
int rv = pstack->pframes[pstack->num_used_minus_one];
pstack->num_used_minus_one--;
return rv;
}
// ----------------------------------------------------------------
// Not bounds-checked, as noted in the header file.
void loop_stack_set(loop_stack_t* pstack, int bits) {
pstack->pframes[pstack->num_used_minus_one] |= bits;
}
void loop_stack_clear(loop_stack_t* pstack, int bits) {
pstack->pframes[pstack->num_used_minus_one] &= ~bits;
}
// ----------------------------------------------------------------
// Not bounds-checked, as noted in the header file.
int loop_stack_get(loop_stack_t* pstack) {
return pstack->pframes[pstack->num_used_minus_one];
}