Arrays.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "vm/Arrays.h"
  4. #define MAX_ALLOCATED_BYTES (1024LL * 1024LL * 1024LL * 4LL)
  5. static long long allocatedBytes = 0;
  6. void asInit(SnuviArrays* as) {
  7. as->capacity = 0;
  8. as->usedStart = -1;
  9. as->freeStart = -1;
  10. as->data = NULL;
  11. }
  12. void asDelete(SnuviArrays* as) {
  13. for(int i = 0; i < as->capacity; i++) {
  14. allocatedBytes -= as->data[i].size;
  15. free(as->data[i].data);
  16. }
  17. allocatedBytes -= as->capacity * sizeof(SnuviArray);
  18. free(as->data);
  19. }
  20. static void aInitArray(SnuviArray* a, int previous, int next) {
  21. a->size = 0;
  22. a->length = 0;
  23. a->next = next;
  24. a->previous = previous;
  25. a->data = NULL;
  26. }
  27. static void asInitArrays(SnuviArrays* as, int start) {
  28. int end = as->capacity - 1;
  29. aInitArray(as->data + start, -1, start + 1);
  30. for(int i = start + 1; i < end; i++) {
  31. aInitArray(as->data + i, i - 1, i + 1);
  32. }
  33. aInitArray(as->data + end, end - 1, -1);
  34. as->freeStart = start;
  35. }
  36. static bool asEnsureCapacity(SnuviArrays* as) {
  37. if(as->freeStart != -1) {
  38. return false;
  39. }
  40. int oldCapacity = as->capacity;
  41. int capacity = (as->data == NULL) ? 4 : as->capacity * 2;
  42. int oldBytes = sizeof(SnuviArray) * oldCapacity;
  43. int bytes = sizeof(SnuviArray) * capacity;
  44. if(bytes < 0 || allocatedBytes - oldBytes + bytes > MAX_ALLOCATED_BYTES) {
  45. return true;
  46. }
  47. allocatedBytes += bytes - oldBytes;
  48. as->data = realloc(as->data, bytes);
  49. as->capacity = capacity;
  50. asInitArrays(as, oldCapacity);
  51. return false;
  52. }
  53. static void asPrintDebug(SnuviArrays* as) {
  54. printf("Free: %d, Used: %d\n", as->freeStart, as->usedStart);
  55. for(int i = 0; i < as->capacity; i++) {
  56. SnuviArray* a = as->data + i;
  57. printf("%d: %s, size: %d, next: %d, previous: %d\n", i,
  58. a->data == NULL ? "null" : "valid", a->size, a->next,
  59. a->previous);
  60. }
  61. }
  62. int asAllocate(SnuviArrays* as, int typeSize, int length) {
  63. (void)asPrintDebug;
  64. if(asEnsureCapacity(as)) {
  65. return -1;
  66. }
  67. int bytes = typeSize * length;
  68. if(bytes < 0) {
  69. return -2;
  70. } else if(allocatedBytes + bytes > MAX_ALLOCATED_BYTES) {
  71. return -1;
  72. }
  73. allocatedBytes += bytes;
  74. int index = as->freeStart;
  75. SnuviArray* array = as->data + index;
  76. as->freeStart = array->next;
  77. if(array->next != -1) {
  78. as->data[array->next].previous = -1;
  79. }
  80. array->next = as->usedStart;
  81. if(as->usedStart != -1) {
  82. as->data[as->usedStart].previous = index;
  83. }
  84. as->usedStart = index;
  85. array->size = bytes;
  86. array->length = length;
  87. array->data = malloc(bytes);
  88. return index;
  89. }
  90. SnuviArray* asGet(SnuviArrays* as, int p) {
  91. if(p < 0 || p >= as->capacity || as->data[p].size == 0) {
  92. return NULL;
  93. }
  94. return as->data + p;
  95. }
  96. void asDeleteArray(SnuviArrays* as, SnuviArray* a, int p) {
  97. if(a->previous != -1) {
  98. as->data[a->previous].next = a->next;
  99. } else {
  100. as->usedStart = a->next;
  101. }
  102. if(a->next != -1) {
  103. as->data[a->next].previous = a->previous;
  104. }
  105. if(as->freeStart != -1) {
  106. a->next = as->freeStart;
  107. as->data[as->freeStart].previous = p;
  108. } else {
  109. a->next = -1;
  110. }
  111. as->freeStart = p;
  112. allocatedBytes -= a->size;
  113. a->previous = -1;
  114. a->size = 0;
  115. a->length = 0;
  116. free(a->data);
  117. a->data = NULL;
  118. }