// 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;
|
|
}
|