herb 0.8.10-arm-linux-gnu → 0.9.1-arm-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 (212) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +11 -3
  3. data/README.md +64 -34
  4. data/Rakefile +48 -40
  5. data/config.yml +473 -34
  6. data/ext/herb/error_helpers.c +535 -140
  7. data/ext/herb/error_helpers.h +1 -0
  8. data/ext/herb/extconf.rb +67 -28
  9. data/ext/herb/extension.c +321 -51
  10. data/ext/herb/extension.h +1 -0
  11. data/ext/herb/extension_helpers.c +24 -14
  12. data/ext/herb/extension_helpers.h +2 -2
  13. data/ext/herb/nodes.c +647 -270
  14. data/ext/herb/nodes.h +1 -0
  15. data/herb.gemspec +3 -2
  16. data/lib/herb/3.0/herb.so +0 -0
  17. data/lib/herb/3.1/herb.so +0 -0
  18. data/lib/herb/3.2/herb.so +0 -0
  19. data/lib/herb/3.3/herb.so +0 -0
  20. data/lib/herb/3.4/herb.so +0 -0
  21. data/lib/herb/4.0/herb.so +0 -0
  22. data/lib/herb/ast/helpers.rb +3 -3
  23. data/lib/herb/ast/node.rb +15 -2
  24. data/lib/herb/ast/nodes.rb +1530 -179
  25. data/lib/herb/bootstrap.rb +87 -0
  26. data/lib/herb/cli.rb +341 -31
  27. data/lib/herb/configuration.rb +248 -0
  28. data/lib/herb/defaults.yml +32 -0
  29. data/lib/herb/engine/compiler.rb +78 -11
  30. data/lib/herb/engine/debug_visitor.rb +13 -3
  31. data/lib/herb/engine/error_formatter.rb +13 -9
  32. data/lib/herb/engine/parser_error_overlay.rb +10 -6
  33. data/lib/herb/engine/validator.rb +8 -3
  34. data/lib/herb/engine/validators/nesting_validator.rb +2 -2
  35. data/lib/herb/engine.rb +119 -43
  36. data/lib/herb/errors.rb +808 -88
  37. data/lib/herb/lex_result.rb +1 -0
  38. data/lib/herb/location.rb +7 -3
  39. data/lib/herb/parse_result.rb +12 -2
  40. data/lib/herb/parser_options.rb +62 -0
  41. data/lib/herb/position.rb +1 -0
  42. data/lib/herb/prism_inspect.rb +120 -0
  43. data/lib/herb/project.rb +923 -331
  44. data/lib/herb/range.rb +1 -0
  45. data/lib/herb/token.rb +7 -1
  46. data/lib/herb/version.rb +1 -1
  47. data/lib/herb/visitor.rb +47 -2
  48. data/lib/herb/warnings.rb +6 -1
  49. data/lib/herb.rb +35 -3
  50. data/sig/herb/ast/helpers.rbs +2 -2
  51. data/sig/herb/ast/node.rbs +12 -2
  52. data/sig/herb/ast/nodes.rbs +773 -128
  53. data/sig/herb/bootstrap.rbs +31 -0
  54. data/sig/herb/configuration.rbs +89 -0
  55. data/sig/herb/engine/compiler.rbs +9 -1
  56. data/sig/herb/engine/debug_visitor.rbs +2 -0
  57. data/sig/herb/engine/validator.rbs +5 -1
  58. data/sig/herb/engine.rbs +21 -3
  59. data/sig/herb/errors.rbs +372 -63
  60. data/sig/herb/location.rbs +4 -0
  61. data/sig/herb/parse_result.rbs +4 -2
  62. data/sig/herb/parser_options.rbs +46 -0
  63. data/sig/herb/position.rbs +1 -0
  64. data/sig/herb/prism_inspect.rbs +28 -0
  65. data/sig/herb/range.rbs +1 -0
  66. data/sig/herb/token.rbs +6 -0
  67. data/sig/herb/visitor.rbs +31 -4
  68. data/sig/herb/warnings.rbs +6 -1
  69. data/sig/herb.rbs +14 -0
  70. data/sig/herb_c_extension.rbs +5 -2
  71. data/sig/rubyvm.rbs +5 -0
  72. data/sig/serialized_ast_errors.rbs +82 -6
  73. data/sig/serialized_ast_nodes.rbs +91 -6
  74. data/src/analyze/action_view/attribute_extraction_helpers.c +303 -0
  75. data/src/analyze/action_view/content_tag.c +78 -0
  76. data/src/analyze/action_view/link_to.c +167 -0
  77. data/src/analyze/action_view/registry.c +83 -0
  78. data/src/analyze/action_view/tag.c +70 -0
  79. data/src/analyze/action_view/tag_helper_node_builders.c +305 -0
  80. data/src/analyze/action_view/tag_helpers.c +815 -0
  81. data/src/analyze/action_view/turbo_frame_tag.c +88 -0
  82. data/src/analyze/analyze.c +885 -0
  83. data/src/{analyzed_ruby.c → analyze/analyzed_ruby.c} +13 -11
  84. data/src/analyze/builders.c +343 -0
  85. data/src/analyze/conditional_elements.c +594 -0
  86. data/src/analyze/conditional_open_tags.c +640 -0
  87. data/src/analyze/control_type.c +250 -0
  88. data/src/{analyze_helpers.c → analyze/helpers.c} +48 -23
  89. data/src/analyze/invalid_structures.c +193 -0
  90. data/src/{analyze_missing_end.c → analyze/missing_end.c} +33 -22
  91. data/src/analyze/parse_errors.c +84 -0
  92. data/src/analyze/prism_annotate.c +399 -0
  93. data/src/analyze/render_nodes.c +761 -0
  94. data/src/{analyze_transform.c → analyze/transform.c} +24 -3
  95. data/src/ast_node.c +17 -7
  96. data/src/ast_nodes.c +759 -387
  97. data/src/ast_pretty_print.c +264 -6
  98. data/src/errors.c +1454 -519
  99. data/src/extract.c +145 -49
  100. data/src/herb.c +52 -34
  101. data/src/html_util.c +241 -12
  102. data/src/include/analyze/action_view/attribute_extraction_helpers.h +36 -0
  103. data/src/include/analyze/action_view/tag_helper_handler.h +43 -0
  104. data/src/include/analyze/action_view/tag_helper_node_builders.h +70 -0
  105. data/src/include/analyze/action_view/tag_helpers.h +38 -0
  106. data/src/include/{analyze.h → analyze/analyze.h} +14 -4
  107. data/src/include/{analyzed_ruby.h → analyze/analyzed_ruby.h} +3 -3
  108. data/src/include/analyze/builders.h +27 -0
  109. data/src/include/analyze/conditional_elements.h +9 -0
  110. data/src/include/analyze/conditional_open_tags.h +9 -0
  111. data/src/include/analyze/control_type.h +14 -0
  112. data/src/include/{analyze_helpers.h → analyze/helpers.h} +4 -2
  113. data/src/include/analyze/invalid_structures.h +11 -0
  114. data/src/include/analyze/prism_annotate.h +16 -0
  115. data/src/include/analyze/render_nodes.h +11 -0
  116. data/src/include/ast_node.h +11 -5
  117. data/src/include/ast_nodes.h +154 -38
  118. data/src/include/ast_pretty_print.h +5 -0
  119. data/src/include/element_source.h +3 -8
  120. data/src/include/errors.h +206 -55
  121. data/src/include/extract.h +21 -5
  122. data/src/include/herb.h +18 -6
  123. data/src/include/herb_prism_node.h +13 -0
  124. data/src/include/html_util.h +7 -2
  125. data/src/include/io.h +3 -1
  126. data/src/include/lex_helpers.h +29 -0
  127. data/src/include/lexer.h +1 -1
  128. data/src/include/lexer_peek_helpers.h +87 -13
  129. data/src/include/lexer_struct.h +2 -0
  130. data/src/include/location.h +2 -1
  131. data/src/include/parser.h +28 -2
  132. data/src/include/parser_helpers.h +19 -3
  133. data/src/include/pretty_print.h +10 -5
  134. data/src/include/prism_context.h +45 -0
  135. data/src/include/prism_helpers.h +10 -7
  136. data/src/include/prism_serialized.h +12 -0
  137. data/src/include/token.h +16 -4
  138. data/src/include/token_struct.h +10 -3
  139. data/src/include/utf8.h +2 -1
  140. data/src/include/util/hb_allocator.h +78 -0
  141. data/src/include/util/hb_arena.h +6 -1
  142. data/src/include/util/hb_arena_debug.h +12 -1
  143. data/src/include/util/hb_array.h +7 -3
  144. data/src/include/util/hb_buffer.h +6 -4
  145. data/src/include/util/hb_foreach.h +79 -0
  146. data/src/include/util/hb_narray.h +8 -4
  147. data/src/include/util/hb_string.h +56 -9
  148. data/src/include/util.h +6 -3
  149. data/src/include/version.h +1 -1
  150. data/src/io.c +3 -2
  151. data/src/lexer.c +42 -30
  152. data/src/lexer_peek_helpers.c +12 -74
  153. data/src/location.c +2 -2
  154. data/src/main.c +53 -28
  155. data/src/parser.c +784 -247
  156. data/src/parser_helpers.c +110 -23
  157. data/src/parser_match_tags.c +129 -48
  158. data/src/pretty_print.c +29 -24
  159. data/src/prism_helpers.c +30 -27
  160. data/src/ruby_parser.c +2 -0
  161. data/src/token.c +151 -66
  162. data/src/token_matchers.c +0 -1
  163. data/src/utf8.c +7 -6
  164. data/src/util/hb_allocator.c +341 -0
  165. data/src/util/hb_arena.c +81 -56
  166. data/src/util/hb_arena_debug.c +32 -17
  167. data/src/util/hb_array.c +30 -15
  168. data/src/util/hb_buffer.c +17 -21
  169. data/src/util/hb_narray.c +22 -7
  170. data/src/util/hb_string.c +49 -35
  171. data/src/util.c +21 -11
  172. data/src/visitor.c +67 -0
  173. data/templates/ext/herb/error_helpers.c.erb +24 -11
  174. data/templates/ext/herb/error_helpers.h.erb +1 -0
  175. data/templates/ext/herb/nodes.c.erb +50 -16
  176. data/templates/ext/herb/nodes.h.erb +1 -0
  177. data/templates/java/error_helpers.c.erb +1 -1
  178. data/templates/java/nodes.c.erb +30 -8
  179. data/templates/java/org/herb/ast/Errors.java.erb +24 -1
  180. data/templates/java/org/herb/ast/Nodes.java.erb +80 -21
  181. data/templates/javascript/packages/core/src/errors.ts.erb +16 -3
  182. data/templates/javascript/packages/core/src/node-type-guards.ts.erb +3 -1
  183. data/templates/javascript/packages/core/src/nodes.ts.erb +109 -32
  184. data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +13 -4
  185. data/templates/javascript/packages/node/extension/nodes.cpp.erb +43 -4
  186. data/templates/lib/herb/ast/nodes.rb.erb +95 -32
  187. data/templates/lib/herb/errors.rb.erb +15 -3
  188. data/templates/lib/herb/visitor.rb.erb +2 -2
  189. data/templates/rust/src/ast/nodes.rs.erb +97 -44
  190. data/templates/rust/src/errors.rs.erb +2 -1
  191. data/templates/rust/src/nodes.rs.erb +168 -16
  192. data/templates/rust/src/union_types.rs.erb +60 -0
  193. data/templates/rust/src/visitor.rs.erb +81 -0
  194. data/templates/src/{analyze_missing_end.c.erb → analyze/missing_end.c.erb} +9 -6
  195. data/templates/src/{analyze_transform.c.erb → analyze/transform.c.erb} +2 -2
  196. data/templates/src/ast_nodes.c.erb +34 -26
  197. data/templates/src/ast_pretty_print.c.erb +24 -5
  198. data/templates/src/errors.c.erb +60 -54
  199. data/templates/src/include/ast_nodes.h.erb +6 -2
  200. data/templates/src/include/ast_pretty_print.h.erb +5 -0
  201. data/templates/src/include/errors.h.erb +15 -11
  202. data/templates/src/include/util/hb_foreach.h.erb +20 -0
  203. data/templates/src/parser_match_tags.c.erb +10 -4
  204. data/templates/src/visitor.c.erb +2 -2
  205. data/templates/template.rb +204 -29
  206. data/templates/wasm/error_helpers.cpp.erb +9 -5
  207. data/templates/wasm/nodes.cpp.erb +41 -4
  208. metadata +60 -16
  209. data/src/analyze.c +0 -1608
  210. data/src/element_source.c +0 -12
  211. data/src/include/util/hb_system.h +0 -9
  212. data/src/util/hb_system.c +0 -30
data/src/util/hb_array.c CHANGED
@@ -2,28 +2,39 @@
2
2
  #include <stdio.h>
3
3
 
4
4
  #include "../include/macros.h"
5
+ #include "../include/util/hb_allocator.h"
5
6
  #include "../include/util/hb_array.h"
6
7
 
7
8
  size_t hb_array_sizeof(void) {
8
9
  return sizeof(hb_array_T);
9
10
  }
10
11
 
11
- hb_array_T* hb_array_init(const size_t capacity) {
12
- hb_array_T* array = malloc(hb_array_sizeof());
12
+ hb_array_T* hb_array_init(const size_t capacity, hb_allocator_T* allocator) {
13
+ hb_array_T* array = hb_allocator_alloc(allocator, hb_array_sizeof());
14
+
15
+ if (!array) { return NULL; }
13
16
 
14
17
  array->size = 0;
15
18
  array->capacity = capacity;
16
- array->items = malloc(capacity * sizeof(void*));
19
+ array->allocator = allocator;
20
+
21
+ if (capacity == 0) {
22
+ array->items = NULL;
23
+ } else {
24
+ array->items = hb_allocator_alloc(allocator, capacity * sizeof(void*));
17
25
 
18
- if (!array->items) {
19
- free(array);
20
- return NULL;
26
+ if (!array->items) {
27
+ hb_allocator_dealloc(allocator, array);
28
+ return NULL;
29
+ }
21
30
  }
22
31
 
23
32
  return array;
24
33
  }
25
34
 
26
- void hb_array_append(hb_array_T* array, void* item) {
35
+ bool hb_array_append(hb_array_T* array, void* item) {
36
+ if (!array) { return false; }
37
+
27
38
  if (array->size >= array->capacity) {
28
39
  size_t new_capacity;
29
40
 
@@ -40,20 +51,23 @@ void hb_array_append(hb_array_T* array, void* item) {
40
51
 
41
52
  if (new_capacity > SIZE_MAX / sizeof(void*)) {
42
53
  fprintf(stderr, "Error: Array allocation would exceed system limits.\n");
43
- return;
54
+ return false;
44
55
  }
45
56
 
57
+ size_t old_size_bytes = array->capacity * sizeof(void*);
46
58
  size_t new_size_bytes = new_capacity * sizeof(void*);
47
- void* new_items = realloc(array->items, new_size_bytes);
59
+ void** new_items = hb_allocator_realloc(array->allocator, array->items, old_size_bytes, new_size_bytes);
48
60
 
49
- if (unlikely(new_items == NULL)) { return; }
61
+ if (unlikely(new_items == NULL)) { return false; }
50
62
 
51
- array->items = (void**) new_items;
63
+ array->items = new_items;
52
64
  array->capacity = new_capacity;
53
65
  }
54
66
 
55
67
  array->items[array->size] = item;
56
68
  array->size++;
69
+
70
+ return true;
57
71
  }
58
72
 
59
73
  void* hb_array_get(const hb_array_T* array, const size_t index) {
@@ -103,8 +117,8 @@ void hb_array_remove_item(hb_array_T* array, void* item) {
103
117
  }
104
118
 
105
119
  // Alias for hb_array_append
106
- void hb_array_push(hb_array_T* array, void* item) {
107
- hb_array_append(array, item);
120
+ bool hb_array_push(hb_array_T* array, void* item) {
121
+ return hb_array_append(array, item);
108
122
  }
109
123
 
110
124
  void* hb_array_pop(hb_array_T* array) {
@@ -130,8 +144,9 @@ size_t hb_array_capacity(const hb_array_T* array) {
130
144
  void hb_array_free(hb_array_T** array) {
131
145
  if (!array || !*array) { return; }
132
146
 
133
- free((*array)->items);
134
- free(*array);
147
+ hb_allocator_T* allocator = (*array)->allocator;
148
+ hb_allocator_dealloc(allocator, (*array)->items);
149
+ hb_allocator_dealloc(allocator, *array);
135
150
 
136
151
  *array = NULL;
137
152
  }
data/src/util/hb_buffer.c CHANGED
@@ -3,7 +3,7 @@
3
3
  #include <string.h>
4
4
 
5
5
  #include "../include/macros.h"
6
- #include "../include/util.h"
6
+ #include "../include/util/hb_allocator.h"
7
7
  #include "../include/util/hb_buffer.h"
8
8
 
9
9
  static bool hb_buffer_has_capacity(hb_buffer_T* buffer, const size_t required_length) {
@@ -22,14 +22,8 @@ static bool hb_buffer_resize(hb_buffer_T* buffer, const size_t new_capacity) {
22
22
  fprintf(stderr, "Error: Buffer capacity would overflow system limits.\n");
23
23
  exit(1);
24
24
  }
25
- char* new_value = NULL;
26
25
 
27
- if (buffer->allocator == NULL) {
28
- new_value = realloc(buffer->value, new_capacity + 1);
29
- } else {
30
- new_value = hb_arena_alloc(buffer->allocator, new_capacity + 1);
31
- memcpy(new_value, buffer->value, buffer->capacity + 1);
32
- }
26
+ char* new_value = hb_allocator_realloc(buffer->allocator, buffer->value, buffer->capacity + 1, new_capacity + 1);
33
27
 
34
28
  if (unlikely(new_value == NULL)) {
35
29
  fprintf(stderr, "Error: Failed to resize buffer to %zu.\n", new_capacity);
@@ -66,11 +60,11 @@ static bool hb_buffer_expand_if_needed(hb_buffer_T* buffer, const size_t require
66
60
  return hb_buffer_resize(buffer, new_capacity);
67
61
  }
68
62
 
69
- bool hb_buffer_init(hb_buffer_T* buffer, const size_t capacity) {
70
- buffer->allocator = NULL;
63
+ bool hb_buffer_init(hb_buffer_T* buffer, const size_t capacity, struct hb_allocator* allocator) {
64
+ buffer->allocator = allocator;
71
65
  buffer->capacity = capacity;
72
66
  buffer->length = 0;
73
- buffer->value = malloc(sizeof(char) * (buffer->capacity + 1));
67
+ buffer->value = hb_allocator_alloc(allocator, sizeof(char) * (buffer->capacity + 1));
74
68
 
75
69
  if (!buffer->value) {
76
70
  fprintf(stderr, "Error: Failed to initialize buffer with capacity of %zu.\n", buffer->capacity);
@@ -83,16 +77,6 @@ bool hb_buffer_init(hb_buffer_T* buffer, const size_t capacity) {
83
77
  return true;
84
78
  }
85
79
 
86
- bool hb_buffer_init_arena(hb_buffer_T* buffer, hb_arena_T* allocator, size_t capacity) {
87
- buffer->allocator = allocator;
88
- buffer->capacity = capacity;
89
- buffer->length = 0;
90
- buffer->value = hb_arena_alloc(allocator, sizeof(char) * (buffer->capacity + 1));
91
- buffer->value[0] = '\0';
92
-
93
- return true;
94
- }
95
-
96
80
  char* hb_buffer_value(const hb_buffer_T* buffer) {
97
81
  return buffer->value;
98
82
  }
@@ -101,6 +85,10 @@ size_t hb_buffer_length(const hb_buffer_T* buffer) {
101
85
  return buffer->length;
102
86
  }
103
87
 
88
+ bool hb_buffer_is_empty(const hb_buffer_T* buffer) {
89
+ return buffer->length == 0;
90
+ }
91
+
104
92
  size_t hb_buffer_capacity(const hb_buffer_T* buffer) {
105
93
  return buffer->capacity;
106
94
  }
@@ -205,6 +193,14 @@ void hb_buffer_concat(hb_buffer_T* destination, hb_buffer_T* source) {
205
193
  destination->value[destination->length] = '\0';
206
194
  }
207
195
 
196
+ void hb_buffer_free(hb_buffer_T* buffer) {
197
+ if (!buffer) { return; }
198
+ hb_allocator_dealloc(buffer->allocator, buffer->value);
199
+ buffer->value = NULL;
200
+ buffer->length = 0;
201
+ buffer->capacity = 0;
202
+ }
203
+
208
204
  void hb_buffer_clear(hb_buffer_T* buffer) {
209
205
  buffer->length = 0;
210
206
  buffer->value[0] = '\0';
data/src/util/hb_narray.c CHANGED
@@ -4,25 +4,40 @@
4
4
  #include <stdbool.h>
5
5
  #include <string.h>
6
6
 
7
- void hb_narray_init(hb_narray_T* array, size_t item_size, size_t initial_capacity) {
7
+ bool hb_narray_init(hb_narray_T* array, size_t item_size, size_t initial_capacity, hb_allocator_T* allocator) {
8
8
  assert(initial_capacity != 0);
9
9
 
10
+ array->allocator = allocator;
10
11
  array->item_size = item_size;
11
12
  array->capacity = initial_capacity;
12
13
  array->size = 0;
13
- array->items = malloc(array->capacity * array->item_size);
14
+ array->items = hb_allocator_alloc(array->allocator, array->capacity * array->item_size);
15
+
16
+ if (!array->items) { return false; }
17
+
18
+ return true;
14
19
  }
15
20
 
16
- void hb_narray_append(hb_narray_T* array, void* item) {
21
+ bool hb_narray_append(hb_narray_T* array, void* item) {
17
22
  if (array->size + 1 > array->capacity) {
18
- array->capacity *= 2;
19
- void* new_buffer = realloc(array->items, array->capacity * array->item_size);
20
- assert(new_buffer != NULL);
23
+ size_t new_capacity = array->capacity * 2;
24
+ void* new_buffer = hb_allocator_realloc(
25
+ array->allocator,
26
+ array->items,
27
+ array->capacity * array->item_size,
28
+ new_capacity * array->item_size
29
+ );
30
+
31
+ if (!new_buffer) { return false; }
32
+
21
33
  array->items = new_buffer;
34
+ array->capacity = new_capacity;
22
35
  }
23
36
 
24
37
  memcpy(array->items + (array->size * array->item_size), item, array->item_size);
25
38
  array->size += 1;
39
+
40
+ return true;
26
41
  }
27
42
 
28
43
  static inline uint8_t* hb_narray_memory_position(const hb_narray_T* array, size_t index) {
@@ -71,7 +86,7 @@ void hb_narray_deinit(hb_narray_T* array) {
71
86
  array->item_size = 0;
72
87
  array->capacity = 0;
73
88
  array->size = 0;
74
- free(array->items);
89
+ hb_allocator_dealloc(array->allocator, array->items);
75
90
  }
76
91
 
77
92
  size_t hb_narray_size(const hb_narray_T* array) {
data/src/util/hb_string.c CHANGED
@@ -1,11 +1,14 @@
1
1
  #include "../include/util/hb_string.h"
2
2
  #include "../include/macros.h"
3
+ #include "../include/util.h"
3
4
 
4
5
  #include <stdlib.h>
5
6
  #include <string.h>
6
7
  #include <strings.h>
7
8
 
8
- hb_string_T hb_string(const char* null_terminated_c_string) {
9
+ hb_string_T hb_string_from_c_string(const char* null_terminated_c_string) {
10
+ if (null_terminated_c_string == NULL) { return HB_STRING_NULL; }
11
+
9
12
  hb_string_T string;
10
13
 
11
14
  string.data = (char*) null_terminated_c_string;
@@ -14,61 +17,72 @@ hb_string_T hb_string(const char* null_terminated_c_string) {
14
17
  return string;
15
18
  }
16
19
 
17
- hb_string_T hb_string_slice(hb_string_T string, uint32_t offset) {
18
- hb_string_T slice;
19
- if (string.length < offset) {
20
- slice.data = NULL;
21
- slice.length = 0;
22
-
23
- return slice;
24
- }
25
-
26
- slice.data = string.data + offset;
27
- slice.length = string.length - offset;
20
+ hb_string_T hb_string_truncate(hb_string_T string, uint32_t max_length) {
21
+ hb_string_T truncated_string = { .data = string.data, .length = MIN(string.length, max_length) };
28
22
 
29
- return slice;
23
+ return truncated_string;
30
24
  }
31
25
 
32
- bool hb_string_equals(hb_string_T a, hb_string_T b) {
33
- if (a.length != b.length) { return false; }
34
-
35
- return strncmp(a.data, b.data, a.length) == 0;
26
+ hb_string_T hb_string_range(hb_string_T string, uint32_t from, uint32_t to) {
27
+ return hb_string_truncate(hb_string_slice(string, from), to - from);
36
28
  }
37
29
 
38
- bool hb_string_equals_case_insensitive(hb_string_T a, hb_string_T b) {
39
- if (a.length != b.length) { return false; }
30
+ hb_string_T hb_string_trim_start(hb_string_T string) {
31
+ if (hb_string_is_empty(string)) { return string; }
40
32
 
41
- return strncasecmp(a.data, b.data, a.length) == 0;
33
+ uint32_t offset = 0;
34
+ while (offset < string.length && is_whitespace(string.data[offset])) {
35
+ offset++;
36
+ }
37
+
38
+ return hb_string_slice(string, offset);
42
39
  }
43
40
 
44
- bool hb_string_starts_with(hb_string_T string, hb_string_T expected_prefix) {
45
- if (hb_string_is_empty(string) || hb_string_is_empty(expected_prefix)) { return false; }
46
- if (string.length < expected_prefix.length) { return false; }
41
+ hb_string_T hb_string_trim_end(hb_string_T string) {
42
+ if (hb_string_is_empty(string)) { return string; }
43
+
44
+ uint32_t length = string.length;
45
+ while (length > 0 && is_whitespace(string.data[length - 1])) {
46
+ length--;
47
+ }
47
48
 
48
- return strncmp(string.data, expected_prefix.data, expected_prefix.length) == 0;
49
+ return hb_string_truncate(string, length);
49
50
  }
50
51
 
51
- bool hb_string_is_empty(hb_string_T string) {
52
- return string.length == 0;
52
+ hb_string_T hb_string_trim(hb_string_T string) {
53
+ return hb_string_trim_end(hb_string_trim_start(string));
53
54
  }
54
55
 
55
- hb_string_T hb_string_truncate(hb_string_T string, uint32_t max_length) {
56
- hb_string_T truncated_string = { .data = string.data, .length = MIN(string.length, max_length) };
56
+ bool hb_string_is_blank(hb_string_T string) {
57
+ if (hb_string_is_empty(string)) { return true; }
57
58
 
58
- return truncated_string;
59
+ for (uint32_t i = 0; i < string.length; i++) {
60
+ if (!is_whitespace(string.data[i])) { return false; }
61
+ }
62
+
63
+ return true;
59
64
  }
60
65
 
61
- hb_string_T hb_string_range(hb_string_T string, uint32_t from, uint32_t to) {
62
- return hb_string_truncate(hb_string_slice(string, from), to - from);
66
+ hb_string_T hb_string_copy(hb_string_T string, hb_allocator_T* allocator) {
67
+ if (hb_string_is_null(string)) { return HB_STRING_NULL; }
68
+ if (hb_string_is_empty(string)) { return HB_STRING_EMPTY; }
69
+
70
+ char* copy = hb_allocator_strndup(allocator, string.data, string.length);
71
+
72
+ return (hb_string_T) { .data = copy, .length = string.length };
63
73
  }
64
74
 
65
75
  char* hb_string_to_c_string_using_malloc(hb_string_T string) {
66
- size_t string_length_in_bytes = sizeof(char) * (string.length);
67
- char* buffer = malloc(string_length_in_bytes + sizeof(char) * 1);
76
+ if (hb_string_is_null(string)) { return NULL; }
68
77
 
69
- if (!hb_string_is_empty(string)) { memcpy(buffer, string.data, string_length_in_bytes); }
78
+ size_t length = string.length;
79
+ char* buffer = malloc(length + 1);
70
80
 
71
- buffer[string_length_in_bytes] = '\0';
81
+ if (!buffer) { return NULL; }
82
+
83
+ if (length > 0) { memcpy(buffer, string.data, length); }
84
+
85
+ buffer[length] = '\0';
72
86
 
73
87
  return buffer;
74
88
  }
data/src/util.c CHANGED
@@ -1,4 +1,5 @@
1
1
  #include "include/util.h"
2
+ #include "include/util/hb_allocator.h"
2
3
  #include "include/util/hb_buffer.h"
3
4
  #include "include/util/hb_string.h"
4
5
 
@@ -10,10 +11,14 @@ int is_newline(int character) {
10
11
  return character == '\n' || character == '\r';
11
12
  }
12
13
 
13
- hb_string_T escape_newlines(hb_string_T input) {
14
+ int is_whitespace(int character) {
15
+ return character == ' ' || character == '\t' || character == '\n' || character == '\r';
16
+ }
17
+
18
+ hb_string_T escape_newlines(hb_allocator_T* allocator, hb_string_T input) {
14
19
  hb_buffer_T buffer;
15
20
 
16
- hb_buffer_init(&buffer, input.length);
21
+ hb_buffer_init(&buffer, input.length, allocator);
17
22
 
18
23
  for (size_t i = 0; i < input.length; ++i) {
19
24
  switch (input.data[i]) {
@@ -34,10 +39,10 @@ hb_string_T escape_newlines(hb_string_T input) {
34
39
  return hb_string(buffer.value);
35
40
  }
36
41
 
37
- static hb_string_T wrap_string(hb_string_T input, char character) {
42
+ static hb_string_T wrap_string(hb_allocator_T* allocator, hb_string_T input, char character) {
38
43
  hb_buffer_T buffer;
39
44
 
40
- hb_buffer_init(&buffer, input.length + 2);
45
+ hb_buffer_init(&buffer, input.length + 2, allocator);
41
46
 
42
47
  hb_buffer_append_char(&buffer, character);
43
48
  hb_buffer_append_string(&buffer, input);
@@ -46,15 +51,20 @@ static hb_string_T wrap_string(hb_string_T input, char character) {
46
51
  return hb_string(buffer.value);
47
52
  }
48
53
 
49
- hb_string_T quoted_string(hb_string_T input) {
50
- return wrap_string(input, '"');
54
+ hb_string_T quoted_string(hb_allocator_T* allocator, hb_string_T input) {
55
+ return wrap_string(allocator, input, '"');
51
56
  }
52
57
 
53
- char* herb_strdup(const char* s) {
54
- size_t len = strlen(s) + 1;
55
- char* copy = malloc(len);
58
+ char* convert_underscores_to_dashes(const char* input) {
59
+ if (!input) { return NULL; }
56
60
 
57
- if (copy) { memcpy(copy, s, len); }
61
+ size_t len = strlen(input);
62
+ char* output = calloc(len + 1, sizeof(char));
63
+ if (!output) { return NULL; }
64
+
65
+ for (size_t i = 0; i < len; i++) {
66
+ output[i] = (input[i] == '_') ? '-' : input[i];
67
+ }
58
68
 
59
- return copy;
69
+ return output;
60
70
  }
data/src/visitor.c CHANGED
@@ -42,6 +42,15 @@ void herb_visit_child_nodes(const AST_NODE_T *node, bool (*visitor)(const AST_NO
42
42
 
43
43
  } break;
44
44
 
45
+ case AST_HTML_CONDITIONAL_OPEN_TAG_NODE: {
46
+ const AST_HTML_CONDITIONAL_OPEN_TAG_NODE_T* html_conditional_open_tag_node = ((const AST_HTML_CONDITIONAL_OPEN_TAG_NODE_T *) node);
47
+
48
+ if (html_conditional_open_tag_node->conditional != NULL) {
49
+ herb_visit_node((AST_NODE_T *) html_conditional_open_tag_node->conditional, visitor, data);
50
+ }
51
+
52
+ } break;
53
+
45
54
  case AST_HTML_CLOSE_TAG_NODE: {
46
55
  const AST_HTML_CLOSE_TAG_NODE_T* html_close_tag_node = ((const AST_HTML_CLOSE_TAG_NODE_T *) node);
47
56
 
@@ -72,6 +81,33 @@ void herb_visit_child_nodes(const AST_NODE_T *node, bool (*visitor)(const AST_NO
72
81
 
73
82
  } break;
74
83
 
84
+ case AST_HTML_CONDITIONAL_ELEMENT_NODE: {
85
+ const AST_HTML_CONDITIONAL_ELEMENT_NODE_T* html_conditional_element_node = ((const AST_HTML_CONDITIONAL_ELEMENT_NODE_T *) node);
86
+
87
+ if (html_conditional_element_node->open_conditional != NULL) {
88
+ herb_visit_node((AST_NODE_T *) html_conditional_element_node->open_conditional, visitor, data);
89
+ }
90
+
91
+ if (html_conditional_element_node->open_tag != NULL) {
92
+ herb_visit_node((AST_NODE_T *) html_conditional_element_node->open_tag, visitor, data);
93
+ }
94
+
95
+ if (html_conditional_element_node->body != NULL) {
96
+ for (size_t index = 0; index < hb_array_size(html_conditional_element_node->body); index++) {
97
+ herb_visit_node(hb_array_get(html_conditional_element_node->body, index), visitor, data);
98
+ }
99
+ }
100
+
101
+ if (html_conditional_element_node->close_tag != NULL) {
102
+ herb_visit_node((AST_NODE_T *) html_conditional_element_node->close_tag, visitor, data);
103
+ }
104
+
105
+ if (html_conditional_element_node->close_conditional != NULL) {
106
+ herb_visit_node((AST_NODE_T *) html_conditional_element_node->close_conditional, visitor, data);
107
+ }
108
+
109
+ } break;
110
+
75
111
  case AST_HTML_ATTRIBUTE_VALUE_NODE: {
76
112
  const AST_HTML_ATTRIBUTE_VALUE_NODE_T* html_attribute_value_node = ((const AST_HTML_ATTRIBUTE_VALUE_NODE_T *) node);
77
113
 
@@ -107,6 +143,17 @@ void herb_visit_child_nodes(const AST_NODE_T *node, bool (*visitor)(const AST_NO
107
143
 
108
144
  } break;
109
145
 
146
+ case AST_ERB_OPEN_TAG_NODE: {
147
+ const AST_ERB_OPEN_TAG_NODE_T* erb_open_tag_node = ((const AST_ERB_OPEN_TAG_NODE_T *) node);
148
+
149
+ if (erb_open_tag_node->children != NULL) {
150
+ for (size_t index = 0; index < hb_array_size(erb_open_tag_node->children); index++) {
151
+ herb_visit_node(hb_array_get(erb_open_tag_node->children, index), visitor, data);
152
+ }
153
+ }
154
+
155
+ } break;
156
+
110
157
  case AST_HTML_COMMENT_NODE: {
111
158
  const AST_HTML_COMMENT_NODE_T* html_comment_node = ((const AST_HTML_COMMENT_NODE_T *) node);
112
159
 
@@ -374,6 +421,26 @@ void herb_visit_child_nodes(const AST_NODE_T *node, bool (*visitor)(const AST_NO
374
421
 
375
422
  } break;
376
423
 
424
+ case AST_RUBY_RENDER_LOCAL_NODE: {
425
+ const AST_RUBY_RENDER_LOCAL_NODE_T* ruby_render_local_node = ((const AST_RUBY_RENDER_LOCAL_NODE_T *) node);
426
+
427
+ if (ruby_render_local_node->value != NULL) {
428
+ herb_visit_node((AST_NODE_T *) ruby_render_local_node->value, visitor, data);
429
+ }
430
+
431
+ } break;
432
+
433
+ case AST_ERB_RENDER_NODE: {
434
+ const AST_ERB_RENDER_NODE_T* erb_render_node = ((const AST_ERB_RENDER_NODE_T *) node);
435
+
436
+ if (erb_render_node->locals != NULL) {
437
+ for (size_t index = 0; index < hb_array_size(erb_render_node->locals); index++) {
438
+ herb_visit_node(hb_array_get(erb_render_node->locals, index), visitor, data);
439
+ }
440
+ }
441
+
442
+ } break;
443
+
377
444
  case AST_ERB_IN_NODE: {
378
445
  const AST_ERB_IN_NODE_T* erb_in_node = ((const AST_ERB_IN_NODE_T *) node);
379
446
 
@@ -7,23 +7,33 @@
7
7
  #include "../../src/include/errors.h"
8
8
  #include "../../src/include/herb.h"
9
9
  #include "../../src/include/token.h"
10
+ #include "../../src/include/util/hb_string.h"
10
11
 
11
12
  VALUE rb_error_from_c_struct(ERROR_T* error);
12
13
 
14
+ static VALUE mErrors;
15
+ static VALUE cError;
16
+ <%- errors.each do |error| -%>
17
+ static VALUE c<%= error.name %>;
18
+ <%- end -%>
19
+
20
+ void rb_init_error_classes(void) {
21
+ mErrors = rb_define_module_under(mHerb, "Errors");
22
+ cError = rb_define_class_under(mErrors, "Error", rb_cObject);
23
+ <%- errors.each do |error| -%>
24
+ c<%= error.name %> = rb_define_class_under(mErrors, "<%= error.name %>", cError);
25
+ <%- end -%>
26
+ }
27
+
13
28
  <%- errors.each do |error| -%>
14
29
  static VALUE rb_<%= error.human %>_from_c_struct(<%= error.struct_type %>* <%= error.human %>) {
15
30
  if (<%= error.human %> == NULL) { return Qnil; }
16
31
 
17
32
  ERROR_T* error = &<%= error.human %>->base;
18
33
 
19
- VALUE Herb = rb_define_module("Herb");
20
- VALUE Errors = rb_define_module_under(Herb, "Errors");
21
- VALUE Error = rb_define_class_under(Errors, "Error", rb_cObject);
22
- VALUE <%= error.name %> = rb_define_class_under(Errors, "<%= error.name %>", Error);
23
-
24
- VALUE type = rb_utf8_str_new_cstr(error_type_to_string(error));
34
+ VALUE type = rb_string_from_hb_string(error_type_to_string(error));
25
35
  VALUE location = rb_location_from_c_struct(error->location);
26
- VALUE message = rb_utf8_str_new_cstr(error->message);
36
+ VALUE message = rb_string_from_hb_string(error->message);
27
37
 
28
38
  <%- error.fields.each do |field| -%>
29
39
  <%- case field -%>
@@ -32,11 +42,14 @@ static VALUE rb_<%= error.human %>_from_c_struct(<%= error.struct_type %>* <%= e
32
42
  <%- when Herb::Template::TokenField -%>
33
43
  VALUE <%= error.human %>_<%= field.name %> = rb_token_from_c_struct(<%= error.human %>-><%= field.name %>);
34
44
  <%- when Herb::Template::TokenTypeField -%>
35
- VALUE <%= error.human %>_<%= field.name %> = rb_utf8_str_new_cstr(token_type_to_string(<%= error.human %>-><%= field.name %>));
45
+ hb_string_T _<%= field.name %>_string = token_type_to_string(<%= error.human %>-><%= field.name %>);
46
+ VALUE <%= error.human %>_<%= field.name %> = rb_utf8_str_new(_<%= field.name %>_string.data, _<%= field.name %>_string.length);
36
47
  <%- when Herb::Template::StringField -%>
37
- VALUE <%= error.human %>_<%= field.name %> = rb_utf8_str_new_cstr(<%= error.human %>-><%= field.name %>);
48
+ VALUE <%= error.human %>_<%= field.name %> = rb_utf8_str_new(<%= error.human %>-><%= field.name %>.data, <%= error.human %>-><%= field.name %>.length);
49
+ <%- when Herb::Template::SizeTField -%>
50
+ VALUE <%= error.human %>_<%= field.name %> = ULONG2NUM(<%= error.human %>-><%= field.name %>);
38
51
  <%- else -%>
39
- /* <%= field.inspect %> */
52
+ /* Unhandled field type: <%= field.class.name %> */
40
53
  VALUE <%= error.human %>_<%= field.name %> = Qnil;
41
54
  <%- end -%>
42
55
  <%- end -%>
@@ -50,7 +63,7 @@ static VALUE rb_<%= error.human %>_from_c_struct(<%= error.struct_type %>* <%= e
50
63
  <%- end -%>
51
64
  };
52
65
 
53
- return rb_class_new_instance(<%= 3 + error.fields.count %>, args, <%= error.name %>);
66
+ return rb_class_new_instance(<%= 3 + error.fields.count %>, args, c<%= error.name %>);
54
67
  };
55
68
 
56
69
  <%- end -%>
@@ -6,6 +6,7 @@
6
6
 
7
7
  #include <ruby.h>
8
8
 
9
+ void rb_init_error_classes(void);
9
10
  VALUE rb_error_from_c_struct(ERROR_T* error);
10
11
  VALUE rb_errors_array_from_c_array(hb_array_T* array);
11
12