| // This file is part of Jiffy released under the MIT license. |
| // See the LICENSE file for more information. |
| |
| #include <assert.h> |
| #include <stdio.h> |
| #include <string.h> |
| |
| #include "jiffy.h" |
| #include "termstack.h" |
| |
| ERL_NIF_TERM |
| termstack_save(ErlNifEnv* env, TermStack* stack) |
| { |
| return enif_make_tuple_from_array(env, stack->elements, stack->top); |
| } |
| |
| int |
| termstack_restore(ErlNifEnv* env, ERL_NIF_TERM from, TermStack* stack) |
| { |
| const ERL_NIF_TERM* elements; |
| int arity; |
| |
| if(enif_get_tuple(env, from, &arity, &elements)) { |
| stack->top = arity; |
| |
| if(arity <= SMALL_TERMSTACK_SIZE) { |
| stack->elements = &stack->__default_elements[0]; |
| stack->size = SMALL_TERMSTACK_SIZE; |
| } else { |
| stack->size = arity * 2; |
| stack->elements = enif_alloc(stack->size * sizeof(ERL_NIF_TERM)); |
| |
| if(!stack->elements) { |
| return 0; |
| } |
| } |
| |
| memcpy(stack->elements, elements, arity * sizeof(ERL_NIF_TERM)); |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| void |
| termstack_destroy(TermStack* stack) |
| { |
| if(stack->elements != &stack->__default_elements[0]) { |
| enif_free(stack->elements); |
| } |
| } |
| |
| inline void |
| termstack_push(TermStack* stack, ERL_NIF_TERM term) |
| { |
| |
| if(stack->top == stack->size) { |
| size_t new_size = stack->size * 2; |
| size_t num_bytes = new_size * sizeof(ERL_NIF_TERM); |
| |
| if (stack->elements == &stack->__default_elements[0]) { |
| ERL_NIF_TERM* elems = enif_alloc(num_bytes); |
| memcpy(elems, stack->elements, num_bytes); |
| stack->elements = elems; |
| } else { |
| stack->elements = enif_realloc(stack->elements, num_bytes); |
| } |
| |
| stack->size = new_size; |
| } |
| |
| assert(stack->top < stack->size); |
| stack->elements[stack->top++] = term; |
| } |
| |
| inline ERL_NIF_TERM |
| termstack_pop(TermStack* stack) |
| { |
| assert(stack->top > 0 && stack->top <= stack->size); |
| return stack->elements[--stack->top]; |
| } |
| |
| inline int |
| termstack_is_empty(TermStack* stack) |
| { |
| return stack->top == 0; |
| } |