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.
- checksums.yaml +4 -4
- data/Makefile +8 -5
- data/config.yml +40 -20
- data/ext/herb/error_helpers.c +57 -3
- data/ext/herb/error_helpers.h +1 -1
- data/ext/herb/extconf.rb +1 -0
- data/ext/herb/extension.c +10 -24
- data/ext/herb/extension_helpers.c +12 -18
- data/ext/herb/extension_helpers.h +4 -4
- data/ext/herb/nodes.c +72 -37
- data/herb.gemspec +0 -2
- data/lib/herb/3.0/herb.so +0 -0
- data/lib/herb/3.1/herb.so +0 -0
- data/lib/herb/3.2/herb.so +0 -0
- data/lib/herb/3.3/herb.so +0 -0
- data/lib/herb/3.4/herb.so +0 -0
- data/lib/herb/ast/helpers.rb +11 -0
- data/lib/herb/ast/node.rb +15 -6
- data/lib/herb/ast/nodes.rb +609 -392
- data/lib/herb/cli.rb +31 -0
- data/lib/herb/colors.rb +82 -0
- data/lib/herb/engine/compiler.rb +140 -14
- data/lib/herb/engine/debug_visitor.rb +1 -5
- data/lib/herb/engine/parser_error_overlay.rb +1 -1
- data/lib/herb/engine.rb +18 -20
- data/lib/herb/errors.rb +166 -56
- data/lib/herb/location.rb +2 -2
- data/lib/herb/project.rb +86 -21
- data/lib/herb/token.rb +14 -2
- data/lib/herb/version.rb +1 -1
- data/lib/herb.rb +1 -0
- data/sig/herb/ast/helpers.rbs +3 -0
- data/sig/herb/ast/node.rbs +12 -5
- data/sig/herb/ast/nodes.rbs +124 -62
- data/sig/herb/colors.rbs +35 -0
- data/sig/herb/engine/compiler.rbs +23 -1
- data/sig/herb/errors.rbs +74 -20
- data/sig/herb/token.rbs +8 -0
- data/sig/herb_c_extension.rbs +1 -1
- data/sig/serialized_ast_errors.rbs +8 -0
- data/src/analyze.c +461 -249
- data/src/analyze_helpers.c +5 -0
- data/src/analyze_missing_end.c +147 -0
- data/src/analyze_transform.c +196 -0
- data/src/analyzed_ruby.c +23 -2
- data/src/ast_node.c +14 -17
- data/src/ast_nodes.c +179 -181
- data/src/ast_pretty_print.c +232 -232
- data/src/element_source.c +7 -6
- data/src/errors.c +272 -152
- data/src/extract.c +92 -34
- data/src/herb.c +37 -49
- data/src/html_util.c +34 -96
- data/src/include/analyze.h +10 -2
- data/src/include/analyze_helpers.h +3 -0
- data/src/include/analyzed_ruby.h +4 -2
- data/src/include/ast_node.h +4 -4
- data/src/include/ast_nodes.h +68 -67
- data/src/include/ast_pretty_print.h +2 -2
- data/src/include/element_source.h +3 -1
- data/src/include/errors.h +42 -26
- data/src/include/extract.h +4 -4
- data/src/include/herb.h +6 -7
- data/src/include/html_util.h +4 -5
- data/src/include/lexer.h +1 -3
- data/src/include/lexer_peek_helpers.h +21 -19
- data/src/include/lexer_struct.h +12 -10
- data/src/include/location.h +10 -13
- data/src/include/macros.h +4 -0
- data/src/include/parser.h +12 -6
- data/src/include/parser_helpers.h +26 -16
- data/src/include/position.h +3 -14
- data/src/include/pretty_print.h +38 -28
- data/src/include/prism_helpers.h +1 -1
- data/src/include/range.h +4 -13
- data/src/include/token.h +5 -11
- data/src/include/token_struct.h +2 -2
- data/src/include/utf8.h +3 -2
- data/src/include/util/hb_arena.h +31 -0
- data/src/include/util/hb_arena_debug.h +8 -0
- data/src/include/util/hb_array.h +33 -0
- data/src/include/util/hb_buffer.h +34 -0
- data/src/include/util/hb_string.h +29 -0
- data/src/include/util/hb_system.h +9 -0
- data/src/include/util.h +3 -14
- data/src/include/version.h +1 -1
- data/src/include/visitor.h +1 -1
- data/src/io.c +7 -4
- data/src/lexer.c +62 -88
- data/src/lexer_peek_helpers.c +42 -38
- data/src/location.c +9 -37
- data/src/main.c +19 -23
- data/src/parser.c +373 -313
- data/src/parser_helpers.c +60 -54
- data/src/parser_match_tags.c +316 -0
- data/src/pretty_print.c +88 -117
- data/src/prism_helpers.c +7 -7
- data/src/range.c +2 -35
- data/src/token.c +36 -87
- data/src/utf8.c +4 -4
- data/src/util/hb_arena.c +179 -0
- data/src/util/hb_arena_debug.c +237 -0
- data/src/{array.c → util/hb_array.c} +26 -27
- data/src/util/hb_buffer.c +203 -0
- data/src/util/hb_string.c +85 -0
- data/src/util/hb_system.c +30 -0
- data/src/util.c +29 -99
- data/src/visitor.c +54 -54
- data/templates/ext/herb/error_helpers.c.erb +3 -3
- data/templates/ext/herb/error_helpers.h.erb +1 -1
- data/templates/ext/herb/nodes.c.erb +11 -6
- data/templates/java/error_helpers.c.erb +75 -0
- data/templates/java/error_helpers.h.erb +20 -0
- data/templates/java/nodes.c.erb +97 -0
- data/templates/java/nodes.h.erb +23 -0
- data/templates/java/org/herb/ast/Errors.java.erb +121 -0
- data/templates/java/org/herb/ast/NodeVisitor.java.erb +14 -0
- data/templates/java/org/herb/ast/Nodes.java.erb +220 -0
- data/templates/java/org/herb/ast/Visitor.java.erb +56 -0
- data/templates/javascript/packages/core/src/visitor.ts.erb +29 -1
- data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +8 -8
- data/templates/javascript/packages/node/extension/error_helpers.h.erb +1 -1
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +9 -9
- data/templates/javascript/packages/node/extension/nodes.h.erb +1 -1
- data/templates/lib/herb/ast/nodes.rb.erb +28 -16
- data/templates/lib/herb/errors.rb.erb +17 -12
- data/templates/rust/src/ast/nodes.rs.erb +220 -0
- data/templates/rust/src/errors.rs.erb +216 -0
- data/templates/rust/src/nodes.rs.erb +374 -0
- data/templates/src/analyze_missing_end.c.erb +36 -0
- data/templates/src/analyze_transform.c.erb +24 -0
- data/templates/src/ast_nodes.c.erb +14 -16
- data/templates/src/ast_pretty_print.c.erb +36 -36
- data/templates/src/errors.c.erb +36 -38
- data/templates/src/include/ast_nodes.h.erb +11 -10
- data/templates/src/include/ast_pretty_print.h.erb +2 -2
- data/templates/src/include/errors.h.erb +9 -9
- data/templates/src/parser_match_tags.c.erb +38 -0
- data/templates/src/visitor.c.erb +4 -4
- data/templates/template.rb +22 -3
- data/templates/wasm/error_helpers.cpp.erb +9 -9
- data/templates/wasm/error_helpers.h.erb +1 -1
- data/templates/wasm/nodes.cpp.erb +9 -9
- data/templates/wasm/nodes.h.erb +1 -1
- data/vendor/prism/Rakefile +4 -1
- data/vendor/prism/config.yml +2 -1
- data/vendor/prism/include/prism/ast.h +31 -1
- data/vendor/prism/include/prism/diagnostic.h +1 -0
- data/vendor/prism/include/prism/version.h +3 -3
- data/vendor/prism/src/diagnostic.c +3 -1
- data/vendor/prism/src/prism.c +130 -71
- data/vendor/prism/src/util/pm_string.c +6 -8
- data/vendor/prism/templates/include/prism/ast.h.erb +2 -0
- data/vendor/prism/templates/java/org/prism/Loader.java.erb +2 -2
- data/vendor/prism/templates/javascript/src/deserialize.js.erb +2 -2
- data/vendor/prism/templates/lib/prism/serialize.rb.erb +2 -2
- data/vendor/prism/templates/sig/prism.rbs.erb +4 -0
- data/vendor/prism/templates/src/diagnostic.c.erb +1 -0
- metadata +34 -21
- data/lib/herb/libherb/array.rb +0 -51
- data/lib/herb/libherb/ast_node.rb +0 -50
- data/lib/herb/libherb/buffer.rb +0 -56
- data/lib/herb/libherb/extract_result.rb +0 -20
- data/lib/herb/libherb/lex_result.rb +0 -32
- data/lib/herb/libherb/libherb.rb +0 -52
- data/lib/herb/libherb/parse_result.rb +0 -20
- data/lib/herb/libherb/token.rb +0 -46
- data/lib/herb/libherb.rb +0 -35
- data/src/buffer.c +0 -232
- data/src/include/array.h +0 -33
- data/src/include/buffer.h +0 -39
- data/src/include/json.h +0 -28
- data/src/include/memory.h +0 -12
- data/src/json.c +0 -205
- data/src/memory.c +0 -53
- data/src/position.c +0 -33
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
#include <stdint.h>
|
|
2
|
+
#include <stdio.h>
|
|
3
|
+
#include <string.h>
|
|
4
|
+
|
|
5
|
+
#include "../include/macros.h"
|
|
6
|
+
#include "../include/util.h"
|
|
7
|
+
#include "../include/util/hb_buffer.h"
|
|
8
|
+
|
|
9
|
+
static bool hb_buffer_has_capacity(hb_buffer_T* buffer, const size_t required_length) {
|
|
10
|
+
return (buffer->length + required_length <= buffer->capacity);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Resizes the capacity of the buffer to the specified new capacity.
|
|
15
|
+
*
|
|
16
|
+
* @param buffer The buffer to resize
|
|
17
|
+
* @param new_capacity The new capacity to resize the buffer to
|
|
18
|
+
* @return true if capacity was resized, false if reallocation failed
|
|
19
|
+
*/
|
|
20
|
+
static bool hb_buffer_resize(hb_buffer_T* buffer, const size_t new_capacity) {
|
|
21
|
+
if (new_capacity + 1 >= SIZE_MAX) {
|
|
22
|
+
fprintf(stderr, "Error: Buffer capacity would overflow system limits.\n");
|
|
23
|
+
exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
char* new_value = realloc(buffer->value, new_capacity + 1);
|
|
27
|
+
|
|
28
|
+
if (unlikely(new_value == NULL)) {
|
|
29
|
+
fprintf(stderr, "Error: Failed to resize buffer to %zu.\n", new_capacity);
|
|
30
|
+
exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
buffer->value = new_value;
|
|
34
|
+
buffer->capacity = new_capacity;
|
|
35
|
+
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Expands the capacity of the buffer if needed to accommodate additional content.
|
|
41
|
+
* This function is a convenience function that calls hb_buffer_has_capacity and
|
|
42
|
+
* hb_buffer_expand_capacity.
|
|
43
|
+
*
|
|
44
|
+
* @param buffer The buffer to expand capacity for
|
|
45
|
+
* @param required_length The additional length needed beyond current buffer capacity
|
|
46
|
+
* @return true if capacity was increased, false if reallocation failed
|
|
47
|
+
*/
|
|
48
|
+
static bool hb_buffer_expand_if_needed(hb_buffer_T* buffer, const size_t required_length) {
|
|
49
|
+
if (hb_buffer_has_capacity(buffer, required_length)) { return true; }
|
|
50
|
+
|
|
51
|
+
bool should_double_capacity = required_length < buffer->capacity;
|
|
52
|
+
size_t new_capacity = 0;
|
|
53
|
+
|
|
54
|
+
if (should_double_capacity) {
|
|
55
|
+
new_capacity = buffer->capacity * 2;
|
|
56
|
+
} else {
|
|
57
|
+
new_capacity = buffer->capacity + (required_length * 2);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return hb_buffer_resize(buffer, new_capacity);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
bool hb_buffer_init(hb_buffer_T* buffer, const size_t capacity) {
|
|
64
|
+
buffer->capacity = capacity;
|
|
65
|
+
buffer->length = 0;
|
|
66
|
+
buffer->value = malloc(sizeof(char) * (buffer->capacity + 1));
|
|
67
|
+
|
|
68
|
+
if (!buffer->value) {
|
|
69
|
+
fprintf(stderr, "Error: Failed to initialize buffer with capacity of %zu.\n", buffer->capacity);
|
|
70
|
+
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
buffer->value[0] = '\0';
|
|
75
|
+
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
char* hb_buffer_value(const hb_buffer_T* buffer) {
|
|
80
|
+
return buffer->value;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
size_t hb_buffer_length(const hb_buffer_T* buffer) {
|
|
84
|
+
return buffer->length;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
size_t hb_buffer_capacity(const hb_buffer_T* buffer) {
|
|
88
|
+
return buffer->capacity;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
size_t hb_buffer_sizeof(void) {
|
|
92
|
+
return sizeof(hb_buffer_T);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Appends a null-terminated string to the buffer.
|
|
97
|
+
* @note This function requires that 'text' is a properly null-terminated string.
|
|
98
|
+
* When reading data from files or other non-string sources, ensure the data is
|
|
99
|
+
* null-terminated before calling this function, or use hb_buffer_append_with_length instead.
|
|
100
|
+
*
|
|
101
|
+
* @param buffer The buffer to append to
|
|
102
|
+
* @param text A null-terminated string to append
|
|
103
|
+
* @return void
|
|
104
|
+
*/
|
|
105
|
+
void hb_buffer_append(hb_buffer_T* buffer, const char* text) {
|
|
106
|
+
if (!buffer || !text) { return; }
|
|
107
|
+
if (text[0] == '\0') { return; }
|
|
108
|
+
|
|
109
|
+
size_t text_length = strlen(text);
|
|
110
|
+
|
|
111
|
+
if (!hb_buffer_expand_if_needed(buffer, text_length)) { return; }
|
|
112
|
+
|
|
113
|
+
memcpy(buffer->value + buffer->length, text, text_length);
|
|
114
|
+
buffer->length += text_length;
|
|
115
|
+
buffer->value[buffer->length] = '\0';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Appends a string of specified length to the buffer.
|
|
120
|
+
* Unlike hb_buffer_append(), this function does not require the text to be
|
|
121
|
+
* null-terminated as it uses the provided length instead of strlen().
|
|
122
|
+
* This is particularly useful when working with data from files, network
|
|
123
|
+
* buffers, or other non-null-terminated sources.
|
|
124
|
+
*
|
|
125
|
+
* @param buffer The buffer to append to
|
|
126
|
+
* @param text The text to append (doesn't need to be null-terminated)
|
|
127
|
+
* @param length The number of bytes to append from text
|
|
128
|
+
* @return void
|
|
129
|
+
*/
|
|
130
|
+
void hb_buffer_append_with_length(hb_buffer_T* buffer, const char* text, const size_t length) {
|
|
131
|
+
if (!buffer || !text || length == 0) { return; }
|
|
132
|
+
if (!hb_buffer_expand_if_needed(buffer, length)) { return; }
|
|
133
|
+
|
|
134
|
+
memcpy(buffer->value + buffer->length, text, length);
|
|
135
|
+
|
|
136
|
+
buffer->length += length;
|
|
137
|
+
buffer->value[buffer->length] = '\0';
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
void hb_buffer_append_string(hb_buffer_T* buffer, hb_string_T string) {
|
|
141
|
+
if (!hb_string_is_empty(string)) { hb_buffer_append_with_length(buffer, string.data, string.length); }
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
void hb_buffer_append_char(hb_buffer_T* buffer, const char character) {
|
|
145
|
+
char string[2];
|
|
146
|
+
|
|
147
|
+
string[0] = character;
|
|
148
|
+
string[1] = '\0';
|
|
149
|
+
|
|
150
|
+
hb_buffer_append(buffer, string);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
static void hb_buffer_append_repeated(hb_buffer_T* buffer, const char character, size_t length) {
|
|
154
|
+
if (!buffer || length == 0) { return; }
|
|
155
|
+
if (!hb_buffer_expand_if_needed(buffer, length)) { return; }
|
|
156
|
+
|
|
157
|
+
memset(buffer->value + buffer->length, character, length);
|
|
158
|
+
|
|
159
|
+
buffer->length += length;
|
|
160
|
+
buffer->value[buffer->length] = '\0';
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
void hb_buffer_append_whitespace(hb_buffer_T* buffer, const size_t length) {
|
|
164
|
+
hb_buffer_append_repeated(buffer, ' ', length);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
void hb_buffer_prepend(hb_buffer_T* buffer, const char* text) {
|
|
168
|
+
if (!buffer || !text) { return; }
|
|
169
|
+
if (text[0] == '\0') { return; }
|
|
170
|
+
|
|
171
|
+
size_t text_length = strlen(text);
|
|
172
|
+
|
|
173
|
+
if (!hb_buffer_expand_if_needed(buffer, text_length)) { return; }
|
|
174
|
+
|
|
175
|
+
memmove(buffer->value + text_length, buffer->value, buffer->length + 1);
|
|
176
|
+
memcpy(buffer->value, text, text_length);
|
|
177
|
+
|
|
178
|
+
buffer->length += text_length;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
void hb_buffer_concat(hb_buffer_T* destination, hb_buffer_T* source) {
|
|
182
|
+
if (source->length == 0) { return; }
|
|
183
|
+
if (!hb_buffer_expand_if_needed(destination, source->length)) { return; }
|
|
184
|
+
|
|
185
|
+
memcpy(destination->value + destination->length, source->value, source->length);
|
|
186
|
+
|
|
187
|
+
destination->length += source->length;
|
|
188
|
+
destination->value[destination->length] = '\0';
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
void hb_buffer_clear(hb_buffer_T* buffer) {
|
|
192
|
+
buffer->length = 0;
|
|
193
|
+
buffer->value[0] = '\0';
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
void hb_buffer_free(hb_buffer_T** buffer) {
|
|
197
|
+
if (!buffer || !*buffer) { return; }
|
|
198
|
+
|
|
199
|
+
if ((*buffer)->value != NULL) { free((*buffer)->value); }
|
|
200
|
+
|
|
201
|
+
free(*buffer);
|
|
202
|
+
*buffer = NULL;
|
|
203
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#include "../include/util/hb_string.h"
|
|
2
|
+
#include "../include/macros.h"
|
|
3
|
+
|
|
4
|
+
#include <stdlib.h>
|
|
5
|
+
#include <string.h>
|
|
6
|
+
#include <strings.h>
|
|
7
|
+
|
|
8
|
+
hb_string_T hb_string(const char* null_terminated_c_string) {
|
|
9
|
+
hb_string_T string;
|
|
10
|
+
|
|
11
|
+
string.data = (char*) null_terminated_c_string;
|
|
12
|
+
string.length = (uint32_t) strlen(null_terminated_c_string);
|
|
13
|
+
|
|
14
|
+
return string;
|
|
15
|
+
}
|
|
16
|
+
|
|
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;
|
|
28
|
+
|
|
29
|
+
return slice;
|
|
30
|
+
}
|
|
31
|
+
|
|
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;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
bool hb_string_equals_case_insensitive(hb_string_T a, hb_string_T b) {
|
|
39
|
+
if (a.length != b.length) { return false; }
|
|
40
|
+
|
|
41
|
+
return strncasecmp(a.data, b.data, a.length) == 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
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; }
|
|
47
|
+
|
|
48
|
+
return strncmp(string.data, expected_prefix.data, expected_prefix.length) == 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
bool hb_string_is_empty(hb_string_T string) {
|
|
52
|
+
return string.length == 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
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) };
|
|
57
|
+
|
|
58
|
+
return truncated_string;
|
|
59
|
+
}
|
|
60
|
+
|
|
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);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
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);
|
|
68
|
+
|
|
69
|
+
if (!hb_string_is_empty(string)) { memcpy(buffer, string.data, string_length_in_bytes); }
|
|
70
|
+
|
|
71
|
+
buffer[string_length_in_bytes] = '\0';
|
|
72
|
+
|
|
73
|
+
return buffer;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
char* hb_string_to_c_string(hb_arena_T* allocator, hb_string_T string) {
|
|
77
|
+
size_t string_length_in_bytes = sizeof(char) * (string.length);
|
|
78
|
+
char* buffer = hb_arena_alloc(allocator, string_length_in_bytes + sizeof(char) * 1);
|
|
79
|
+
|
|
80
|
+
if (!hb_string_is_empty(string)) { memcpy(buffer, string.data, string_length_in_bytes); }
|
|
81
|
+
|
|
82
|
+
buffer[string_length_in_bytes] = '\0';
|
|
83
|
+
|
|
84
|
+
return buffer;
|
|
85
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#include "../include/util/hb_system.h"
|
|
2
|
+
|
|
3
|
+
#ifdef __linux__
|
|
4
|
+
#define _GNU_SOURCE
|
|
5
|
+
#endif
|
|
6
|
+
|
|
7
|
+
#ifdef HB_USE_MALLOC
|
|
8
|
+
#include <stdlib.h>
|
|
9
|
+
#else
|
|
10
|
+
#include <sys/mman.h>
|
|
11
|
+
#endif
|
|
12
|
+
|
|
13
|
+
void* hb_system_allocate_memory(size_t size) {
|
|
14
|
+
#ifdef HB_USE_MALLOC
|
|
15
|
+
return malloc(size);
|
|
16
|
+
#else
|
|
17
|
+
void* memory = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
|
18
|
+
if (memory == MAP_FAILED) { return NULL; }
|
|
19
|
+
|
|
20
|
+
return memory;
|
|
21
|
+
#endif
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
void hb_system_free_memory(void* ptr, size_t size) {
|
|
25
|
+
#ifdef HB_USE_MALLOC
|
|
26
|
+
free(ptr);
|
|
27
|
+
#else
|
|
28
|
+
munmap(ptr, size);
|
|
29
|
+
#endif
|
|
30
|
+
}
|
data/src/util.c
CHANGED
|
@@ -1,118 +1,55 @@
|
|
|
1
1
|
#include "include/util.h"
|
|
2
|
+
#include "include/util/hb_buffer.h"
|
|
3
|
+
#include "include/util/hb_string.h"
|
|
2
4
|
|
|
3
|
-
#include <ctype.h>
|
|
4
5
|
#include <stdio.h>
|
|
5
6
|
#include <stdlib.h>
|
|
6
7
|
#include <string.h>
|
|
7
8
|
|
|
8
|
-
int
|
|
9
|
-
return character == '
|
|
9
|
+
int is_newline(int character) {
|
|
10
|
+
return character == '\n' || character == '\r';
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
int count_in_string(const char* string, const char character) {
|
|
17
|
-
int count = 0;
|
|
13
|
+
hb_string_T escape_newlines(hb_string_T input) {
|
|
14
|
+
hb_buffer_T buffer;
|
|
18
15
|
|
|
19
|
-
|
|
20
|
-
if (*string == character) { count++; }
|
|
16
|
+
hb_buffer_init(&buffer, input.length);
|
|
21
17
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
} else if (*string == '\n') {
|
|
36
|
-
count++;
|
|
18
|
+
for (size_t i = 0; i < input.length; ++i) {
|
|
19
|
+
switch (input.data[i]) {
|
|
20
|
+
case '\n': {
|
|
21
|
+
hb_buffer_append_char(&buffer, '\\');
|
|
22
|
+
hb_buffer_append_char(&buffer, 'n');
|
|
23
|
+
} break;
|
|
24
|
+
case '\r': {
|
|
25
|
+
hb_buffer_append_char(&buffer, '\\');
|
|
26
|
+
hb_buffer_append_char(&buffer, 'r');
|
|
27
|
+
} break;
|
|
28
|
+
default: {
|
|
29
|
+
hb_buffer_append_char(&buffer, input.data[i]);
|
|
30
|
+
}
|
|
37
31
|
}
|
|
38
|
-
|
|
39
|
-
string++;
|
|
40
32
|
}
|
|
41
33
|
|
|
42
|
-
return
|
|
34
|
+
return hb_string(buffer.value);
|
|
43
35
|
}
|
|
44
36
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
while (*string != '\0') {
|
|
49
|
-
if (*string == find) { *string = replace; }
|
|
37
|
+
static hb_string_T wrap_string(hb_string_T input, char character) {
|
|
38
|
+
hb_buffer_T buffer;
|
|
50
39
|
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return original_string;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
char* escape_newlines(const char* input) {
|
|
58
|
-
char* output = calloc(strlen(input) * 2 + 1, sizeof(char));
|
|
59
|
-
char* orig_output = output;
|
|
60
|
-
|
|
61
|
-
while (*input) {
|
|
62
|
-
if (*input == '\n') {
|
|
63
|
-
*output++ = '\\';
|
|
64
|
-
*output++ = 'n';
|
|
65
|
-
} else if (*input == '\r') {
|
|
66
|
-
*output++ = '\\';
|
|
67
|
-
*output++ = 'r';
|
|
68
|
-
} else {
|
|
69
|
-
*output++ = *input;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
input++;
|
|
73
|
-
}
|
|
40
|
+
hb_buffer_init(&buffer, input.length + 2);
|
|
74
41
|
|
|
75
|
-
|
|
42
|
+
hb_buffer_append_char(&buffer, character);
|
|
43
|
+
hb_buffer_append_string(&buffer, input);
|
|
44
|
+
hb_buffer_append_char(&buffer, character);
|
|
76
45
|
|
|
77
|
-
return
|
|
46
|
+
return hb_string(buffer.value);
|
|
78
47
|
}
|
|
79
48
|
|
|
80
|
-
|
|
81
|
-
if (input == NULL) { return NULL; }
|
|
82
|
-
|
|
83
|
-
const size_t length = strlen(input);
|
|
84
|
-
char* wrapped = malloc(length + 3);
|
|
85
|
-
|
|
86
|
-
if (wrapped == NULL) { return NULL; }
|
|
87
|
-
|
|
88
|
-
wrapped[0] = character;
|
|
89
|
-
strcpy(wrapped + 1, input);
|
|
90
|
-
wrapped[length + 1] = character;
|
|
91
|
-
wrapped[length + 2] = '\0';
|
|
92
|
-
|
|
93
|
-
return wrapped;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
char* quoted_string(const char* input) {
|
|
49
|
+
hb_string_T quoted_string(hb_string_T input) {
|
|
97
50
|
return wrap_string(input, '"');
|
|
98
51
|
}
|
|
99
52
|
|
|
100
|
-
// Check if a string is blank (NULL, empty, or only contains whitespace)
|
|
101
|
-
bool string_blank(const char* input) {
|
|
102
|
-
if (input == NULL || input[0] == '\0') { return true; }
|
|
103
|
-
|
|
104
|
-
for (const char* p = input; *p != '\0'; p++) {
|
|
105
|
-
if (!isspace(*p)) { return false; }
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return true;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Check if a string is present (not blank)
|
|
112
|
-
bool string_present(const char* input) {
|
|
113
|
-
return !string_blank(input);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
53
|
char* herb_strdup(const char* s) {
|
|
117
54
|
size_t len = strlen(s) + 1;
|
|
118
55
|
char* copy = malloc(len);
|
|
@@ -121,10 +58,3 @@ char* herb_strdup(const char* s) {
|
|
|
121
58
|
|
|
122
59
|
return copy;
|
|
123
60
|
}
|
|
124
|
-
|
|
125
|
-
char* size_t_to_string(const size_t value) {
|
|
126
|
-
char* buffer = malloc(21);
|
|
127
|
-
snprintf(buffer, 21, "%zu", value);
|
|
128
|
-
|
|
129
|
-
return buffer;
|
|
130
|
-
}
|