You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
2.0 KiB

  1. // This file is part of Jiffy released under the MIT license.
  2. // See the LICENSE file for more information.
  3. #include <assert.h>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include "jiffy.h"
  7. #include "termstack.h"
  8. ERL_NIF_TERM
  9. termstack_save(ErlNifEnv* env, TermStack* stack)
  10. {
  11. return enif_make_tuple_from_array(env, stack->elements, stack->top);
  12. }
  13. int
  14. termstack_restore(ErlNifEnv* env, ERL_NIF_TERM from, TermStack* stack)
  15. {
  16. const ERL_NIF_TERM* elements;
  17. int arity;
  18. if(enif_get_tuple(env, from, &arity, &elements)) {
  19. stack->top = arity;
  20. if(arity <= SMALL_TERMSTACK_SIZE) {
  21. stack->elements = &stack->__default_elements[0];
  22. stack->size = SMALL_TERMSTACK_SIZE;
  23. } else {
  24. stack->size = arity * 2;
  25. stack->elements = enif_alloc(stack->size * sizeof(ERL_NIF_TERM));
  26. if(!stack->elements) {
  27. return 0;
  28. }
  29. }
  30. memcpy(stack->elements, elements, arity * sizeof(ERL_NIF_TERM));
  31. return 1;
  32. }
  33. return 0;
  34. }
  35. void
  36. termstack_destroy(TermStack* stack)
  37. {
  38. if(stack->elements != &stack->__default_elements[0]) {
  39. enif_free(stack->elements);
  40. }
  41. }
  42. inline void
  43. termstack_push(TermStack* stack, ERL_NIF_TERM term)
  44. {
  45. if(stack->top == stack->size) {
  46. size_t new_size = stack->size * 2;
  47. size_t num_bytes = new_size * sizeof(ERL_NIF_TERM);
  48. if (stack->elements == &stack->__default_elements[0]) {
  49. ERL_NIF_TERM* elems = enif_alloc(num_bytes);
  50. memcpy(elems, stack->elements, num_bytes);
  51. stack->elements = elems;
  52. } else {
  53. stack->elements = enif_realloc(stack->elements, num_bytes);
  54. }
  55. stack->size = new_size;
  56. }
  57. assert(stack->top < stack->size);
  58. stack->elements[stack->top++] = term;
  59. }
  60. inline ERL_NIF_TERM
  61. termstack_pop(TermStack* stack)
  62. {
  63. assert(stack->top > 0 && stack->top <= stack->size);
  64. return stack->elements[--stack->top];
  65. }
  66. inline int
  67. termstack_is_empty(TermStack* stack)
  68. {
  69. return stack->top == 0;
  70. }