herb 0.7.4-aarch64-linux-gnu → 0.8.0-aarch64-linux-gnu

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +8 -5
  3. data/config.yml +40 -20
  4. data/ext/herb/error_helpers.c +57 -3
  5. data/ext/herb/error_helpers.h +1 -1
  6. data/ext/herb/extconf.rb +1 -0
  7. data/ext/herb/extension.c +10 -24
  8. data/ext/herb/extension_helpers.c +12 -18
  9. data/ext/herb/extension_helpers.h +4 -4
  10. data/ext/herb/nodes.c +72 -37
  11. data/herb.gemspec +0 -2
  12. data/lib/herb/3.0/herb.so +0 -0
  13. data/lib/herb/3.1/herb.so +0 -0
  14. data/lib/herb/3.2/herb.so +0 -0
  15. data/lib/herb/3.3/herb.so +0 -0
  16. data/lib/herb/3.4/herb.so +0 -0
  17. data/lib/herb/ast/helpers.rb +11 -0
  18. data/lib/herb/ast/node.rb +15 -6
  19. data/lib/herb/ast/nodes.rb +609 -392
  20. data/lib/herb/cli.rb +31 -0
  21. data/lib/herb/colors.rb +82 -0
  22. data/lib/herb/engine/compiler.rb +140 -14
  23. data/lib/herb/engine/debug_visitor.rb +1 -5
  24. data/lib/herb/engine/parser_error_overlay.rb +1 -1
  25. data/lib/herb/engine.rb +18 -20
  26. data/lib/herb/errors.rb +166 -56
  27. data/lib/herb/location.rb +2 -2
  28. data/lib/herb/project.rb +86 -21
  29. data/lib/herb/token.rb +14 -2
  30. data/lib/herb/version.rb +1 -1
  31. data/lib/herb.rb +1 -0
  32. data/sig/herb/ast/helpers.rbs +3 -0
  33. data/sig/herb/ast/node.rbs +12 -5
  34. data/sig/herb/ast/nodes.rbs +124 -62
  35. data/sig/herb/colors.rbs +35 -0
  36. data/sig/herb/engine/compiler.rbs +23 -1
  37. data/sig/herb/errors.rbs +74 -20
  38. data/sig/herb/token.rbs +8 -0
  39. data/sig/herb_c_extension.rbs +1 -1
  40. data/sig/serialized_ast_errors.rbs +8 -0
  41. data/src/analyze.c +461 -249
  42. data/src/analyze_helpers.c +5 -0
  43. data/src/analyze_missing_end.c +147 -0
  44. data/src/analyze_transform.c +196 -0
  45. data/src/analyzed_ruby.c +23 -2
  46. data/src/ast_node.c +14 -17
  47. data/src/ast_nodes.c +179 -181
  48. data/src/ast_pretty_print.c +232 -232
  49. data/src/element_source.c +7 -6
  50. data/src/errors.c +272 -152
  51. data/src/extract.c +92 -34
  52. data/src/herb.c +37 -49
  53. data/src/html_util.c +34 -96
  54. data/src/include/analyze.h +10 -2
  55. data/src/include/analyze_helpers.h +3 -0
  56. data/src/include/analyzed_ruby.h +4 -2
  57. data/src/include/ast_node.h +4 -4
  58. data/src/include/ast_nodes.h +68 -67
  59. data/src/include/ast_pretty_print.h +2 -2
  60. data/src/include/element_source.h +3 -1
  61. data/src/include/errors.h +42 -26
  62. data/src/include/extract.h +4 -4
  63. data/src/include/herb.h +6 -7
  64. data/src/include/html_util.h +4 -5
  65. data/src/include/lexer.h +1 -3
  66. data/src/include/lexer_peek_helpers.h +21 -19
  67. data/src/include/lexer_struct.h +12 -10
  68. data/src/include/location.h +10 -13
  69. data/src/include/macros.h +4 -0
  70. data/src/include/parser.h +12 -6
  71. data/src/include/parser_helpers.h +26 -16
  72. data/src/include/position.h +3 -14
  73. data/src/include/pretty_print.h +38 -28
  74. data/src/include/prism_helpers.h +1 -1
  75. data/src/include/range.h +4 -13
  76. data/src/include/token.h +5 -11
  77. data/src/include/token_struct.h +2 -2
  78. data/src/include/utf8.h +3 -2
  79. data/src/include/util/hb_arena.h +31 -0
  80. data/src/include/util/hb_arena_debug.h +8 -0
  81. data/src/include/util/hb_array.h +33 -0
  82. data/src/include/util/hb_buffer.h +34 -0
  83. data/src/include/util/hb_string.h +29 -0
  84. data/src/include/util/hb_system.h +9 -0
  85. data/src/include/util.h +3 -14
  86. data/src/include/version.h +1 -1
  87. data/src/include/visitor.h +1 -1
  88. data/src/io.c +7 -4
  89. data/src/lexer.c +62 -88
  90. data/src/lexer_peek_helpers.c +42 -38
  91. data/src/location.c +9 -37
  92. data/src/main.c +19 -23
  93. data/src/parser.c +373 -313
  94. data/src/parser_helpers.c +60 -54
  95. data/src/parser_match_tags.c +316 -0
  96. data/src/pretty_print.c +88 -117
  97. data/src/prism_helpers.c +7 -7
  98. data/src/range.c +2 -35
  99. data/src/token.c +36 -87
  100. data/src/utf8.c +4 -4
  101. data/src/util/hb_arena.c +179 -0
  102. data/src/util/hb_arena_debug.c +237 -0
  103. data/src/{array.c → util/hb_array.c} +26 -27
  104. data/src/util/hb_buffer.c +203 -0
  105. data/src/util/hb_string.c +85 -0
  106. data/src/util/hb_system.c +30 -0
  107. data/src/util.c +29 -99
  108. data/src/visitor.c +54 -54
  109. data/templates/ext/herb/error_helpers.c.erb +3 -3
  110. data/templates/ext/herb/error_helpers.h.erb +1 -1
  111. data/templates/ext/herb/nodes.c.erb +11 -6
  112. data/templates/java/error_helpers.c.erb +75 -0
  113. data/templates/java/error_helpers.h.erb +20 -0
  114. data/templates/java/nodes.c.erb +97 -0
  115. data/templates/java/nodes.h.erb +23 -0
  116. data/templates/java/org/herb/ast/Errors.java.erb +121 -0
  117. data/templates/java/org/herb/ast/NodeVisitor.java.erb +14 -0
  118. data/templates/java/org/herb/ast/Nodes.java.erb +220 -0
  119. data/templates/java/org/herb/ast/Visitor.java.erb +56 -0
  120. data/templates/javascript/packages/core/src/visitor.ts.erb +29 -1
  121. data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +8 -8
  122. data/templates/javascript/packages/node/extension/error_helpers.h.erb +1 -1
  123. data/templates/javascript/packages/node/extension/nodes.cpp.erb +9 -9
  124. data/templates/javascript/packages/node/extension/nodes.h.erb +1 -1
  125. data/templates/lib/herb/ast/nodes.rb.erb +28 -16
  126. data/templates/lib/herb/errors.rb.erb +17 -12
  127. data/templates/rust/src/ast/nodes.rs.erb +220 -0
  128. data/templates/rust/src/errors.rs.erb +216 -0
  129. data/templates/rust/src/nodes.rs.erb +374 -0
  130. data/templates/src/analyze_missing_end.c.erb +36 -0
  131. data/templates/src/analyze_transform.c.erb +24 -0
  132. data/templates/src/ast_nodes.c.erb +14 -16
  133. data/templates/src/ast_pretty_print.c.erb +36 -36
  134. data/templates/src/errors.c.erb +36 -38
  135. data/templates/src/include/ast_nodes.h.erb +11 -10
  136. data/templates/src/include/ast_pretty_print.h.erb +2 -2
  137. data/templates/src/include/errors.h.erb +9 -9
  138. data/templates/src/parser_match_tags.c.erb +38 -0
  139. data/templates/src/visitor.c.erb +4 -4
  140. data/templates/template.rb +22 -3
  141. data/templates/wasm/error_helpers.cpp.erb +9 -9
  142. data/templates/wasm/error_helpers.h.erb +1 -1
  143. data/templates/wasm/nodes.cpp.erb +9 -9
  144. data/templates/wasm/nodes.h.erb +1 -1
  145. data/vendor/prism/Rakefile +4 -1
  146. data/vendor/prism/config.yml +2 -1
  147. data/vendor/prism/include/prism/ast.h +31 -1
  148. data/vendor/prism/include/prism/diagnostic.h +1 -0
  149. data/vendor/prism/include/prism/version.h +3 -3
  150. data/vendor/prism/src/diagnostic.c +3 -1
  151. data/vendor/prism/src/prism.c +130 -71
  152. data/vendor/prism/src/util/pm_string.c +6 -8
  153. data/vendor/prism/templates/include/prism/ast.h.erb +2 -0
  154. data/vendor/prism/templates/java/org/prism/Loader.java.erb +2 -2
  155. data/vendor/prism/templates/javascript/src/deserialize.js.erb +2 -2
  156. data/vendor/prism/templates/lib/prism/serialize.rb.erb +2 -2
  157. data/vendor/prism/templates/sig/prism.rbs.erb +4 -0
  158. data/vendor/prism/templates/src/diagnostic.c.erb +1 -0
  159. metadata +34 -21
  160. data/lib/herb/libherb/array.rb +0 -51
  161. data/lib/herb/libherb/ast_node.rb +0 -50
  162. data/lib/herb/libherb/buffer.rb +0 -56
  163. data/lib/herb/libherb/extract_result.rb +0 -20
  164. data/lib/herb/libherb/lex_result.rb +0 -32
  165. data/lib/herb/libherb/libherb.rb +0 -52
  166. data/lib/herb/libherb/parse_result.rb +0 -20
  167. data/lib/herb/libherb/token.rb +0 -46
  168. data/lib/herb/libherb.rb +0 -35
  169. data/src/buffer.c +0 -232
  170. data/src/include/array.h +0 -33
  171. data/src/include/buffer.h +0 -39
  172. data/src/include/json.h +0 -28
  173. data/src/include/memory.h +0 -12
  174. data/src/json.c +0 -205
  175. data/src/memory.c +0 -53
  176. data/src/position.c +0 -33
@@ -0,0 +1,179 @@
1
+ #include "../include/util/hb_arena.h"
2
+ #include "../include/macros.h"
3
+ #include "../include/util/hb_system.h"
4
+
5
+ #include <assert.h>
6
+ #include <stdbool.h>
7
+ #include <stdint.h>
8
+ #include <string.h>
9
+
10
+ #define hb_arena_for_each_page(allocator, page) \
11
+ for (hb_arena_page_T* page = (allocator)->head; page != NULL; page = page->next)
12
+
13
+ static inline size_t hb_arena_align_size(size_t size, size_t alignment) {
14
+ assert(size <= SIZE_MAX - (alignment - 1));
15
+
16
+ return ((size + (alignment - 1)) / alignment) * alignment;
17
+ }
18
+
19
+ static inline bool hb_arena_page_has_capacity(hb_arena_page_T* page, size_t required_size) {
20
+ assert(page->position <= page->capacity);
21
+
22
+ return page->position + required_size <= page->capacity;
23
+ }
24
+
25
+ static inline void* hb_arena_page_alloc_from(hb_arena_page_T* page, size_t size) {
26
+ assert(size > 0);
27
+ assert(page->position + size <= page->capacity);
28
+
29
+ void* result = &page->memory[page->position];
30
+ page->position += size;
31
+
32
+ return result;
33
+ }
34
+
35
+ static inline void hb_arena_page_reset(hb_arena_page_T* page) {
36
+ page->position = 0;
37
+ }
38
+
39
+ static inline void hb_arena_reset_pages_after(hb_arena_page_T* start_page) {
40
+ for (hb_arena_page_T* page = start_page; page != NULL; page = page->next) {
41
+ hb_arena_page_reset(page);
42
+ }
43
+ }
44
+
45
+ static bool hb_arena_append_page(hb_arena_T* allocator, size_t minimum_size) {
46
+ assert(minimum_size > 0);
47
+
48
+ size_t page_size = MAX(allocator->default_page_size, minimum_size);
49
+
50
+ assert(page_size <= SIZE_MAX - sizeof(hb_arena_page_T));
51
+ size_t total_size = page_size + sizeof(hb_arena_page_T);
52
+
53
+ hb_arena_page_T* page = hb_system_allocate_memory(total_size);
54
+ if (page == NULL) { return false; }
55
+
56
+ *page = (hb_arena_page_T) { .next = NULL, .capacity = page_size, .position = 0 };
57
+
58
+ if (allocator->head == NULL) {
59
+ allocator->head = page;
60
+ allocator->tail = page;
61
+ } else {
62
+ hb_arena_page_T* last = allocator->head;
63
+
64
+ while (last->next != NULL) {
65
+ last = last->next;
66
+ }
67
+
68
+ last->next = page;
69
+ allocator->tail = page;
70
+ }
71
+
72
+ return true;
73
+ }
74
+
75
+ bool hb_arena_init(hb_arena_T* allocator, size_t initial_size) {
76
+ assert(initial_size > 0);
77
+
78
+ allocator->head = NULL;
79
+ allocator->tail = NULL;
80
+ allocator->default_page_size = initial_size;
81
+ allocator->allocation_count = 0;
82
+
83
+ return hb_arena_append_page(allocator, initial_size);
84
+ }
85
+
86
+ void* hb_arena_alloc(hb_arena_T* allocator, size_t size) {
87
+ assert(allocator->tail != NULL);
88
+ assert(size > 0);
89
+
90
+ size_t required_size = hb_arena_align_size(size, 8);
91
+
92
+ allocator->allocation_count++;
93
+
94
+ if (hb_arena_page_has_capacity(allocator->tail, required_size)) {
95
+ return hb_arena_page_alloc_from(allocator->tail, required_size);
96
+ }
97
+
98
+ for (hb_arena_page_T* page = allocator->tail->next; page != NULL; page = page->next) {
99
+ if (hb_arena_page_has_capacity(page, required_size)) {
100
+ allocator->tail = page;
101
+ return hb_arena_page_alloc_from(allocator->tail, required_size);
102
+ }
103
+ }
104
+
105
+ bool allocated = hb_arena_append_page(allocator, required_size);
106
+
107
+ if (!allocated) { return NULL; }
108
+
109
+ return hb_arena_page_alloc_from(allocator->tail, required_size);
110
+ }
111
+
112
+ size_t hb_arena_position(hb_arena_T* allocator) {
113
+ size_t total = 0;
114
+
115
+ hb_arena_for_each_page(allocator, page) {
116
+ total += page->position;
117
+ }
118
+
119
+ return total;
120
+ }
121
+
122
+ size_t hb_arena_capacity(hb_arena_T* allocator) {
123
+ size_t total = 0;
124
+
125
+ hb_arena_for_each_page(allocator, page) {
126
+ total += page->capacity;
127
+ }
128
+
129
+ return total;
130
+ }
131
+
132
+ void hb_arena_reset(hb_arena_T* allocator) {
133
+ hb_arena_for_each_page(allocator, page) {
134
+ hb_arena_page_reset(page);
135
+ }
136
+
137
+ allocator->tail = allocator->head;
138
+ allocator->allocation_count = 0;
139
+ }
140
+
141
+ void hb_arena_reset_to(hb_arena_T* allocator, size_t target_position) {
142
+ if (target_position == 0) {
143
+ hb_arena_reset(allocator);
144
+
145
+ return;
146
+ }
147
+
148
+ size_t accumulated = 0;
149
+
150
+ hb_arena_for_each_page(allocator, page) {
151
+ if (accumulated + page->capacity >= target_position) {
152
+ page->position = target_position - accumulated;
153
+ allocator->tail = page;
154
+
155
+ hb_arena_reset_pages_after(page->next);
156
+
157
+ return;
158
+ }
159
+
160
+ accumulated += page->capacity;
161
+ page->position = page->capacity;
162
+ }
163
+ }
164
+
165
+ void hb_arena_free(hb_arena_T* allocator) {
166
+ if (allocator->head == NULL) { return; }
167
+
168
+ for (hb_arena_page_T* current = allocator->head; current != NULL;) {
169
+ hb_arena_page_T* next = current->next;
170
+ size_t total_size = sizeof(hb_arena_page_T) + current->capacity;
171
+ hb_system_free_memory(current, total_size);
172
+
173
+ current = next;
174
+ }
175
+
176
+ allocator->head = NULL;
177
+ allocator->tail = NULL;
178
+ allocator->default_page_size = 0;
179
+ }
@@ -0,0 +1,237 @@
1
+ #include <stdarg.h>
2
+ #include <stdio.h>
3
+ #include <string.h>
4
+
5
+ #include "../include/util/hb_arena.h"
6
+
7
+ #define ANSI_COLOR_GREEN "\033[32m"
8
+ #define ANSI_COLOR_YELLOW "\033[33m"
9
+ #define ANSI_COLOR_RED "\033[31m"
10
+ #define ANSI_COLOR_RESET "\033[0m"
11
+
12
+ #define UTF8_BULLET_OVERHEAD 2
13
+ #define BOX_WIDTH 100
14
+
15
+ static const char* get_usage_color(double percentage) {
16
+ if (percentage >= 90.0) {
17
+ return ANSI_COLOR_RED;
18
+ } else if (percentage >= 70.0) {
19
+ return ANSI_COLOR_YELLOW;
20
+ } else {
21
+ return ANSI_COLOR_GREEN;
22
+ }
23
+ }
24
+
25
+ static void format_bytes(size_t bytes, char* buffer, size_t buffer_size) {
26
+ if (bytes >= 1024 * 1024) {
27
+ snprintf(buffer, buffer_size, "%.2f MB", bytes / (1024.0 * 1024.0));
28
+ } else if (bytes >= 1024) {
29
+ snprintf(buffer, buffer_size, "%zu KB", bytes / 1024);
30
+ } else {
31
+ snprintf(buffer, buffer_size, "%zu B", bytes);
32
+ }
33
+ }
34
+
35
+ static void print_progress_bar(size_t used, size_t capacity, int width, const char* color) {
36
+ int filled = (int) ((double) used / (double) capacity * width);
37
+
38
+ printf("%s[", color);
39
+
40
+ for (int i = 0; i < width; i++) {
41
+ if (i < filled) {
42
+ printf("█");
43
+ } else {
44
+ printf("░");
45
+ }
46
+ }
47
+
48
+ printf("]%s", ANSI_COLOR_RESET);
49
+ }
50
+
51
+ static void print_box_top(void) {
52
+ printf("╔");
53
+ for (int i = 0; i < BOX_WIDTH; i++) {
54
+ printf("═");
55
+ }
56
+ printf("╗\n");
57
+ }
58
+
59
+ static void print_box_separator(void) {
60
+ printf("╠");
61
+ for (int i = 0; i < BOX_WIDTH; i++) {
62
+ printf("═");
63
+ }
64
+ printf("╣\n");
65
+ }
66
+
67
+ static void print_box_bottom(void) {
68
+ printf("╚");
69
+ for (int i = 0; i < BOX_WIDTH; i++) {
70
+ printf("═");
71
+ }
72
+ printf("╝\n");
73
+ }
74
+
75
+ static void print_box_line(const char* format, ...) {
76
+ char line[256];
77
+ va_list args;
78
+ va_start(args, format);
79
+ int length = vsnprintf(line, sizeof(line), format, args);
80
+ va_end(args);
81
+
82
+ printf("║%s%*s║\n", line, BOX_WIDTH - length, "");
83
+ }
84
+
85
+ static void print_box_line_centered(const char* format, ...) {
86
+ char line[256];
87
+ va_list args;
88
+ va_start(args, format);
89
+ int length = vsnprintf(line, sizeof(line), format, args);
90
+ va_end(args);
91
+
92
+ int total_padding = BOX_WIDTH - length;
93
+ int left_padding = total_padding / 2;
94
+ int right_padding = total_padding - left_padding;
95
+
96
+ printf("║%*s%s%*s║\n", left_padding, "", line, right_padding, "");
97
+ }
98
+
99
+ static void print_box_line_with_bullet(const char* format, ...) {
100
+ char line[256];
101
+ va_list args;
102
+ va_start(args, format);
103
+ int length = vsnprintf(line, sizeof(line), format, args);
104
+ va_end(args);
105
+
106
+ printf("║%s%*s║\n", line, BOX_WIDTH - (length - UTF8_BULLET_OVERHEAD), "");
107
+ }
108
+
109
+ static void print_box_line_with_bullet_and_color(const char* color, const char* format, ...) {
110
+ char line[256];
111
+ va_list args;
112
+ va_start(args, format);
113
+ int length = vsnprintf(line, sizeof(line), format, args);
114
+ va_end(args);
115
+
116
+ int visual_length = length - UTF8_BULLET_OVERHEAD - (int) strlen(color) - (int) strlen(ANSI_COLOR_RESET);
117
+ printf("║%s%*s║\n", line, BOX_WIDTH - visual_length, "");
118
+ }
119
+
120
+ void hb_arena_print_stats(const hb_arena_T* allocator) {
121
+ if (allocator->head == NULL) {
122
+ print_box_top();
123
+ print_box_line_centered("ARENA MEMORY LAYOUT");
124
+ print_box_separator();
125
+ print_box_line(" Arena is empty (not initialized)");
126
+ print_box_bottom();
127
+
128
+ return;
129
+ }
130
+
131
+ size_t num_pages = 0;
132
+ size_t total_capacity = 0;
133
+ size_t total_used = 0;
134
+ size_t fragmentation = 0;
135
+
136
+ for (const hb_arena_page_T* page = allocator->head; page != NULL; page = page->next) {
137
+ num_pages++;
138
+ total_capacity += page->capacity;
139
+ total_used += page->position;
140
+
141
+ if (page != allocator->tail && page->position < page->capacity) {
142
+ fragmentation += (page->capacity - page->position);
143
+ }
144
+ }
145
+
146
+ size_t total_available = total_capacity - total_used;
147
+ double usage_percentage = (double) total_used / (double) total_capacity * 100.0;
148
+ double fragmentation_percentage = (double) fragmentation / (double) total_capacity * 100.0;
149
+ const char* overall_color = get_usage_color(usage_percentage);
150
+
151
+ char capacity_string[32], used_string[32], available_string[32], fragmentation_string[32], default_size_string[32];
152
+ format_bytes(total_capacity, capacity_string, sizeof(capacity_string));
153
+ format_bytes(total_used, used_string, sizeof(used_string));
154
+ format_bytes(total_available, available_string, sizeof(available_string));
155
+ format_bytes(fragmentation, fragmentation_string, sizeof(fragmentation_string));
156
+ format_bytes(allocator->default_page_size, default_size_string, sizeof(default_size_string));
157
+
158
+ print_box_top();
159
+ print_box_line_centered("ARENA MEMORY LAYOUT");
160
+ print_box_separator();
161
+ print_box_line(" Statistics:");
162
+
163
+ print_box_line_with_bullet(" • Pages: %zu", num_pages);
164
+ print_box_line_with_bullet(" • Default Page Size: %s", default_size_string);
165
+ print_box_line_with_bullet(" • Total Capacity: %s", capacity_string);
166
+ print_box_line_with_bullet_and_color(
167
+ overall_color,
168
+ " • Total Used: %s%s%s",
169
+ overall_color,
170
+ used_string,
171
+ ANSI_COLOR_RESET
172
+ );
173
+ print_box_line_with_bullet(" • Total Available: %s", available_string);
174
+ print_box_line_with_bullet_and_color(
175
+ overall_color,
176
+ " • Usage: %s%.1f%%%s",
177
+ overall_color,
178
+ usage_percentage,
179
+ ANSI_COLOR_RESET
180
+ );
181
+ print_box_line_with_bullet(" • Allocations: %zu", allocator->allocation_count);
182
+ print_box_line_with_bullet(" • Fragmentation: %s", fragmentation_string);
183
+
184
+ if (fragmentation > 0) { print_box_line(" (%.1f%% skipped in non-tail pages)", fragmentation_percentage); }
185
+
186
+ print_box_separator();
187
+
188
+ size_t page_number = 0;
189
+
190
+ for (const hb_arena_page_T* page = allocator->head; page != NULL; page = page->next) {
191
+ double page_usage = (double) page->position / (double) page->capacity * 100.0;
192
+ const char* page_color = get_usage_color(page_usage);
193
+
194
+ char page_capacity_string[32], page_used_string[32];
195
+ format_bytes(page->capacity, page_capacity_string, sizeof(page_capacity_string));
196
+ format_bytes(page->position, page_used_string, sizeof(page_used_string));
197
+
198
+ if (page == allocator->tail) {
199
+ char header_line[256];
200
+ snprintf(header_line, sizeof(header_line), " Page %zu @ %p ← CURRENT", page_number, (void*) page);
201
+ int visual_length = (int) strlen(header_line) - 2;
202
+ printf("║%s%*s║\n", header_line, BOX_WIDTH - visual_length, "");
203
+ } else {
204
+ print_box_line(" Page %zu @ %p", page_number, (void*) page);
205
+ }
206
+
207
+ char stats_line[128];
208
+ int stats_length =
209
+ snprintf(stats_line, sizeof(stats_line), "%s / %s (%.0f%%)", page_used_string, page_capacity_string, page_usage);
210
+
211
+ int bar_width = BOX_WIDTH - 4 - 2 - 2 - stats_length - 1;
212
+ int bar_with_brackets = bar_width + 2;
213
+
214
+ printf("║ ");
215
+ print_progress_bar(page->position, page->capacity, bar_width, page_color);
216
+ printf(" %s %*s║\n", stats_line, BOX_WIDTH - 4 - bar_with_brackets - 2 - stats_length - 1, "");
217
+
218
+ size_t unused = page->capacity - page->position;
219
+
220
+ if (unused > 0) {
221
+ char unused_string[32];
222
+ format_bytes(unused, unused_string, sizeof(unused_string));
223
+
224
+ if (page == allocator->tail) {
225
+ print_box_line(" Unused: %s (available for allocations)", unused_string);
226
+ } else {
227
+ print_box_line(" Unused: %s", unused_string);
228
+ }
229
+ }
230
+
231
+ printf("║%*s║\n", BOX_WIDTH, "");
232
+
233
+ page_number++;
234
+ }
235
+
236
+ print_box_bottom();
237
+ }
@@ -1,20 +1,19 @@
1
1
  #include <stdint.h>
2
2
  #include <stdio.h>
3
3
 
4
- #include "include/array.h"
5
- #include "include/macros.h"
6
- #include "include/memory.h"
4
+ #include "../include/macros.h"
5
+ #include "../include/util/hb_array.h"
7
6
 
8
- size_t array_sizeof(void) {
9
- return sizeof(array_T);
7
+ size_t hb_array_sizeof(void) {
8
+ return sizeof(hb_array_T);
10
9
  }
11
10
 
12
- array_T* array_init(const size_t capacity) {
13
- array_T* array = safe_malloc(array_sizeof());
11
+ hb_array_T* hb_array_init(const size_t capacity) {
12
+ hb_array_T* array = malloc(hb_array_sizeof());
14
13
 
15
14
  array->size = 0;
16
15
  array->capacity = capacity;
17
- array->items = nullable_safe_malloc(sizeof(void*) * capacity);
16
+ array->items = malloc(capacity * sizeof(void*));
18
17
 
19
18
  if (!array->items) {
20
19
  free(array);
@@ -24,7 +23,7 @@ array_T* array_init(const size_t capacity) {
24
23
  return array;
25
24
  }
26
25
 
27
- void array_append(array_T* array, void* item) {
26
+ void hb_array_append(hb_array_T* array, void* item) {
28
27
  if (array->size >= array->capacity) {
29
28
  size_t new_capacity;
30
29
 
@@ -45,7 +44,7 @@ void array_append(array_T* array, void* item) {
45
44
  }
46
45
 
47
46
  size_t new_size_bytes = new_capacity * sizeof(void*);
48
- void* new_items = safe_realloc(array->items, new_size_bytes);
47
+ void* new_items = realloc(array->items, new_size_bytes);
49
48
 
50
49
  if (unlikely(new_items == NULL)) { return; }
51
50
 
@@ -57,29 +56,29 @@ void array_append(array_T* array, void* item) {
57
56
  array->size++;
58
57
  }
59
58
 
60
- void* array_get(const array_T* array, const size_t index) {
59
+ void* hb_array_get(const hb_array_T* array, const size_t index) {
61
60
  if (index >= array->size) { return NULL; }
62
61
 
63
62
  return array->items[index];
64
63
  }
65
64
 
66
- void* array_first(array_T* array) {
65
+ void* hb_array_first(hb_array_T* array) {
67
66
  if (!array || array->size == 0) { return NULL; }
68
67
  return array->items[0];
69
68
  }
70
69
 
71
- void* array_last(array_T* array) {
70
+ void* hb_array_last(hb_array_T* array) {
72
71
  if (!array || array->size == 0) { return NULL; }
73
72
  return array->items[array->size - 1];
74
73
  }
75
74
 
76
- void array_set(const array_T* array, const size_t index, void* item) {
75
+ void hb_array_set(const hb_array_T* array, const size_t index, void* item) {
77
76
  if (index >= array->size) { return; }
78
77
 
79
78
  array->items[index] = item;
80
79
  }
81
80
 
82
- void array_remove(array_T* array, const size_t index) {
81
+ void hb_array_remove(hb_array_T* array, const size_t index) {
83
82
  if (index >= array->size) { return; }
84
83
 
85
84
  for (size_t i = index; i < array->size - 1; i++) {
@@ -89,7 +88,7 @@ void array_remove(array_T* array, const size_t index) {
89
88
  array->size--;
90
89
  }
91
90
 
92
- size_t array_index_of(array_T* array, void* item) {
91
+ size_t hb_array_index_of(hb_array_T* array, void* item) {
93
92
  for (size_t i = 0; i < array->size; i++) {
94
93
  if (array->items[i] == item) { return i; }
95
94
  }
@@ -97,37 +96,37 @@ size_t array_index_of(array_T* array, void* item) {
97
96
  return SIZE_MAX;
98
97
  }
99
98
 
100
- void array_remove_item(array_T* array, void* item) {
101
- size_t index = array_index_of(array, item);
99
+ void hb_array_remove_item(hb_array_T* array, void* item) {
100
+ size_t index = hb_array_index_of(array, item);
102
101
 
103
- if (index != SIZE_MAX) { array_remove(array, index); }
102
+ if (index != SIZE_MAX) { hb_array_remove(array, index); }
104
103
  }
105
104
 
106
- // Alias for array_append
107
- void array_push(array_T* array, void* item) {
108
- array_append(array, item);
105
+ // Alias for hb_array_append
106
+ void hb_array_push(hb_array_T* array, void* item) {
107
+ hb_array_append(array, item);
109
108
  }
110
109
 
111
- void* array_pop(array_T* array) {
110
+ void* hb_array_pop(hb_array_T* array) {
112
111
  if (!array || array->size == 0) { return NULL; }
113
112
 
114
- void* last_item = array_last(array);
113
+ void* last_item = hb_array_last(array);
115
114
  array->size--;
116
115
 
117
116
  return last_item;
118
117
  }
119
118
 
120
- size_t array_size(const array_T* array) {
119
+ size_t hb_array_size(const hb_array_T* array) {
121
120
  if (array == NULL) { return 0; }
122
121
 
123
122
  return array->size;
124
123
  }
125
124
 
126
- size_t array_capacity(const array_T* array) {
125
+ size_t hb_array_capacity(const hb_array_T* array) {
127
126
  return array->capacity;
128
127
  }
129
128
 
130
- void array_free(array_T** array) {
129
+ void hb_array_free(hb_array_T** array) {
131
130
  if (!array || !*array) { return; }
132
131
 
133
132
  free((*array)->items);