Skip to content

Commit 71af52f

Browse files
authored
C: Add trim, blank and simplify hb_string_T operations (#1314)
Follow up on #687 and #1313
1 parent fa219d0 commit 71af52f

File tree

8 files changed

+66
-99
lines changed

8 files changed

+66
-99
lines changed

src/analyze/conditional_elements.c

Lines changed: 8 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#include "../include/element_source.h"
44
#include "../include/errors.h"
55
#include "../include/token_struct.h"
6-
#include "../include/util.h"
76
#include "../include/util/hb_allocator.h"
87
#include "../include/util/hb_array.h"
98
#include "../include/util/hb_string.h"
@@ -37,38 +36,19 @@ static hb_string_T extract_condition_from_erb_content(AST_NODE_T* erb_node, bool
3736

3837
if (!content_token || hb_string_is_empty(content_token->value)) { return HB_STRING_NULL; }
3938

40-
const char* data = content_token->value.data;
41-
size_t remaining = content_token->value.length;
42-
43-
while (remaining > 0 && is_whitespace(*data)) {
44-
data++;
45-
remaining--;
46-
}
39+
hb_string_T value = hb_string_trim_start(content_token->value);
4740

4841
if (*is_if) {
49-
if (remaining >= 3 && strncmp(data, "if", 2) == 0 && is_whitespace(data[2])) {
50-
data += 3;
51-
remaining -= 3;
52-
}
42+
if (hb_string_starts_with(value, hb_string("if "))) { value = hb_string_slice(value, 3); }
5343
} else {
54-
if (remaining >= 7 && strncmp(data, "unless", 6) == 0 && is_whitespace(data[6])) {
55-
data += 7;
56-
remaining -= 7;
57-
}
44+
if (hb_string_starts_with(value, hb_string("unless "))) { value = hb_string_slice(value, 7); }
5845
}
5946

60-
while (remaining > 0 && is_whitespace(*data)) {
61-
data++;
62-
remaining--;
63-
}
64-
if (remaining == 0) { return HB_STRING_NULL; }
47+
value = hb_string_trim(value);
6548

66-
while (remaining > 0 && is_whitespace(data[remaining - 1])) {
67-
remaining--;
68-
}
69-
if (remaining == 0) { return HB_STRING_NULL; }
49+
if (hb_string_is_empty(value)) { return HB_STRING_NULL; }
7050

71-
return (hb_string_T) { .data = (char*) data, .length = (uint32_t) remaining };
51+
return value;
7252
}
7353

7454
static bool is_simple_erb_conditional(AST_NODE_T* node) {
@@ -107,18 +87,7 @@ static bool contains_single_open_tag(hb_array_T* statements, AST_HTML_OPEN_TAG_N
10787

10888
if (child->type == AST_HTML_TEXT_NODE) {
10989
AST_HTML_TEXT_NODE_T* text = (AST_HTML_TEXT_NODE_T*) child;
110-
bool whitespace_only = true;
111-
112-
if (!hb_string_is_empty(text->content)) {
113-
for (size_t ci = 0; ci < text->content.length; ci++) {
114-
if (!is_whitespace(text->content.data[ci])) {
115-
whitespace_only = false;
116-
break;
117-
}
118-
}
119-
}
120-
121-
if (whitespace_only) { continue; }
90+
if (hb_string_is_blank(text->content)) { continue; }
12291

12392
return false;
12493
}
@@ -156,18 +125,7 @@ static bool contains_single_close_tag(hb_array_T* statements, AST_HTML_CLOSE_TAG
156125

157126
if (child->type == AST_HTML_TEXT_NODE) {
158127
AST_HTML_TEXT_NODE_T* text = (AST_HTML_TEXT_NODE_T*) child;
159-
bool whitespace_only = true;
160-
161-
if (!hb_string_is_empty(text->content)) {
162-
for (size_t ci = 0; ci < text->content.length; ci++) {
163-
if (!is_whitespace(text->content.data[ci])) {
164-
whitespace_only = false;
165-
break;
166-
}
167-
}
168-
}
169-
170-
if (whitespace_only) { continue; }
128+
if (hb_string_is_blank(text->content)) { continue; }
171129

172130
return false;
173131
}

src/analyze/conditional_open_tags.c

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#include "../include/element_source.h"
44
#include "../include/errors.h"
55
#include "../include/token_struct.h"
6-
#include "../include/util.h"
76
#include "../include/util/hb_allocator.h"
87
#include "../include/util/hb_array.h"
98
#include "../include/util/hb_string.h"
@@ -87,18 +86,7 @@ static single_open_tag_result_T get_single_open_tag_from_statements(hb_array_T*
8786

8887
if (node->type == AST_HTML_TEXT_NODE) {
8988
AST_HTML_TEXT_NODE_T* text = (AST_HTML_TEXT_NODE_T*) node;
90-
bool whitespace_only = true;
91-
92-
if (!hb_string_is_empty(text->content)) {
93-
for (size_t ci = 0; ci < text->content.length; ci++) {
94-
if (!is_whitespace(text->content.data[ci])) {
95-
whitespace_only = false;
96-
break;
97-
}
98-
}
99-
}
100-
101-
if (whitespace_only) { continue; }
89+
if (hb_string_is_blank(text->content)) { continue; }
10290

10391
if (result.tag) {
10492
hb_string_T tag_name = get_open_tag_name(result.tag);

src/extract.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,10 @@ void herb_extract_ruby_to_buffer_with_options(
9999
bool is_inline_comment = false;
100100

101101
if (!extract_options.comments && !is_comment_tag && !hb_string_is_empty(token->value)) {
102-
const char* content = token->value.data;
103-
104-
while (*content == ' ' || *content == '\t') {
105-
content++;
106-
}
102+
hb_string_T trimmed = hb_string_trim_start(token->value);
107103

108-
if (*content == '#' && token->location.start.line == token->location.end.line) {
104+
if (!hb_string_is_empty(trimmed) && trimmed.data[0] == '#'
105+
&& token->location.start.line == token->location.end.line) {
109106
is_comment_tag = true;
110107
is_inline_comment = true;
111108
}

src/include/util.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77

88
int is_newline(int character);
99
int is_whitespace(int character);
10-
const char* skip_whitespace(const char* pointer);
11-
1210
hb_string_T escape_newlines(hb_string_T input);
1311
hb_string_T quoted_string(hb_string_T input);
1412
char* herb_strdup(const char* s);

src/include/util/hb_string.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ bool hb_string_is_empty(hb_string_T string);
2626

2727
hb_string_T hb_string_truncate(hb_string_T string, uint32_t max_length);
2828
hb_string_T hb_string_range(hb_string_T string, uint32_t from, uint32_t to);
29+
hb_string_T hb_string_trim_start(hb_string_T string);
30+
hb_string_T hb_string_trim_end(hb_string_T string);
31+
hb_string_T hb_string_trim(hb_string_T string);
32+
bool hb_string_is_blank(hb_string_T string);
2933
hb_string_T hb_string_copy(hb_string_T string, hb_allocator_T* allocator);
3034

3135
char* hb_string_to_c_string_using_malloc(hb_string_T string);

src/parser.c

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -336,9 +336,8 @@ static AST_HTML_ATTRIBUTE_NAME_NODE_T* parser_parse_html_attribute_name(parser_T
336336
TOKEN_EOF
337337
)) {
338338
if (token_is(parser, TOKEN_ERB_START)) {
339-
const char* tag = parser->current_token->value.data;
340-
size_t tag_length = parser->current_token->value.length;
341-
bool is_output_tag = (tag_length >= 3 && tag[2] == '=');
339+
hb_string_T tag = parser->current_token->value;
340+
bool is_output_tag = (tag.length >= 3 && tag.data[2] == '=');
342341

343342
if (!is_output_tag) {
344343
bool is_control_flow = parser_lookahead_erb_is_control_flow(parser);
@@ -921,14 +920,14 @@ static bool parser_lookahead_erb_is_attribute(lexer_T* lexer) {
921920
} while (true);
922921
}
923922

924-
static bool starts_with_keyword(const char* pointer, size_t remaining, const char* keyword) {
925-
size_t length = strlen(keyword);
926-
if (remaining < length) { return false; }
927-
if (strncmp(pointer, keyword, length) != 0) { return false; }
923+
static bool starts_with_keyword(hb_string_T string, const char* keyword) {
924+
hb_string_T prefix = hb_string(keyword);
925+
if (string.length < prefix.length) { return false; }
926+
if (strncmp(string.data, prefix.data, prefix.length) != 0) { return false; }
928927

929-
if (remaining == length) { return true; }
928+
if (string.length == prefix.length) { return true; }
930929

931-
return is_whitespace(pointer[length]);
930+
return is_whitespace(string.data[prefix.length]);
932931
}
933932

934933
// TODO: ideally we could avoid basing this off of strings, and use the step in analyze.c
@@ -942,18 +941,12 @@ static bool parser_lookahead_erb_is_control_flow(parser_T* parser) {
942941
return false;
943942
}
944943

945-
const char* data = content->value.data;
946-
size_t remaining = content->value.length;
944+
hb_string_T trimmed = hb_string_trim_start(content->value);
947945

948-
while (remaining > 0 && is_whitespace(*data)) {
949-
data++;
950-
remaining--;
951-
}
952-
953-
bool is_control_flow = starts_with_keyword(data, remaining, "end") || starts_with_keyword(data, remaining, "else")
954-
|| starts_with_keyword(data, remaining, "elsif") || starts_with_keyword(data, remaining, "in")
955-
|| starts_with_keyword(data, remaining, "when") || starts_with_keyword(data, remaining, "rescue")
956-
|| starts_with_keyword(data, remaining, "ensure");
946+
bool is_control_flow = starts_with_keyword(trimmed, "end") || starts_with_keyword(trimmed, "else")
947+
|| starts_with_keyword(trimmed, "elsif") || starts_with_keyword(trimmed, "in")
948+
|| starts_with_keyword(trimmed, "when") || starts_with_keyword(trimmed, "rescue")
949+
|| starts_with_keyword(trimmed, "ensure");
957950

958951
token_free(content, parser->allocator);
959952

src/util.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,6 @@ int is_whitespace(int character) {
1414
return character == ' ' || character == '\t' || character == '\n' || character == '\r';
1515
}
1616

17-
const char* skip_whitespace(const char* pointer) {
18-
while (is_whitespace(*pointer)) {
19-
pointer++;
20-
}
21-
22-
return pointer;
23-
}
24-
2517
hb_string_T escape_newlines(hb_string_T input) {
2618
hb_buffer_T buffer;
2719

src/util/hb_string.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "../include/util/hb_string.h"
22
#include "../include/macros.h"
3+
#include "../include/util.h"
34

45
#include <stdlib.h>
56
#include <string.h>
@@ -68,6 +69,42 @@ hb_string_T hb_string_range(hb_string_T string, uint32_t from, uint32_t to) {
6869
return hb_string_truncate(hb_string_slice(string, from), to - from);
6970
}
7071

72+
hb_string_T hb_string_trim_start(hb_string_T string) {
73+
if (hb_string_is_empty(string)) { return string; }
74+
75+
uint32_t offset = 0;
76+
while (offset < string.length && is_whitespace(string.data[offset])) {
77+
offset++;
78+
}
79+
80+
return hb_string_slice(string, offset);
81+
}
82+
83+
hb_string_T hb_string_trim_end(hb_string_T string) {
84+
if (hb_string_is_empty(string)) { return string; }
85+
86+
uint32_t length = string.length;
87+
while (length > 0 && is_whitespace(string.data[length - 1])) {
88+
length--;
89+
}
90+
91+
return hb_string_truncate(string, length);
92+
}
93+
94+
hb_string_T hb_string_trim(hb_string_T string) {
95+
return hb_string_trim_end(hb_string_trim_start(string));
96+
}
97+
98+
bool hb_string_is_blank(hb_string_T string) {
99+
if (hb_string_is_empty(string)) { return true; }
100+
101+
for (uint32_t i = 0; i < string.length; i++) {
102+
if (!is_whitespace(string.data[i])) { return false; }
103+
}
104+
105+
return true;
106+
}
107+
71108
hb_string_T hb_string_copy(hb_string_T string, hb_allocator_T* allocator) {
72109
if (hb_string_is_null(string)) { return HB_STRING_NULL; }
73110
if (hb_string_is_empty(string)) { return HB_STRING_EMPTY; }

0 commit comments

Comments
 (0)