aboutsummaryrefslogtreecommitdiff
path: root/builtins
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-09-02 23:47:16 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-09-02 23:47:16 -0400
commit5aa5a5e99b322586eed9997a14b3d616540bef07 (patch)
treec8eede952aa9ff49cea8f981d48e0b5faad291b2 /builtins
parent5d6fa135b1eadbceac04e5456fabb7e53feedc10 (diff)
Fix some stuff around Text:find() and text indexing
Diffstat (limited to 'builtins')
-rw-r--r--builtins/functions.c2
-rw-r--r--builtins/text.c25
2 files changed, 17 insertions, 10 deletions
diff --git a/builtins/functions.c b/builtins/functions.c
index 06636cba..4aa699a5 100644
--- a/builtins/functions.c
+++ b/builtins/functions.c
@@ -218,7 +218,7 @@ public void end_test(void *expr, const TypeInfo *type, const char *expected, con
Text_t expr_plain = USE_COLOR ? generic_as_text(expr, false, type) : expr_text;
bool success = Text$equal(&expr_plain, &expected_text);
if (!success) {
- Int_t colon = Text$find(expected_text, Text$from_str(":"), I_small(0), NULL);
+ Int_t colon = Text$find(expected_text, Text$from_str(":"), I_small(1), NULL);
if (colon.small != I_small(0).small) {
Text_t with_type = Text$concat(expr_plain, Text$from_str(" : "), type_name);
success = Text$equal(&with_type, &expected_text);
diff --git a/builtins/text.c b/builtins/text.c
index 2f3fbb46..32eefd32 100644
--- a/builtins/text.c
+++ b/builtins/text.c
@@ -1291,16 +1291,23 @@ int64_t match(Text_t text, Text_t pattern, int64_t text_index, int64_t pattern_i
public Int_t Text$find(Text_t text, Text_t pattern, Int_t from_index, int64_t *match_length)
{
- int32_t first = get_grapheme(pattern, 0);
- bool find_first = (first != '['
- && !uc_is_property(first, UC_PROPERTY_QUOTATION_MARK)
- && !uc_is_property(first, UC_PROPERTY_PAIRED_PUNCTUATION));
+ int64_t first = Int_to_Int64(from_index, false);
+ if (first == 0) fail("Invalid index: 0");
+ if (first < 0) first = text.length + first + 1;
+ if (first > text.length || first < 1)
+ return I_small(0);
+
+ int32_t first_grapheme = get_grapheme(pattern, 0);
+ bool find_first = (first_grapheme != '['
+ && !uc_is_property(first_grapheme, UC_PROPERTY_QUOTATION_MARK)
+ && !uc_is_property(first_grapheme, UC_PROPERTY_PAIRED_PUNCTUATION));
iteration_state_t text_state = {0, 0};
- for (int64_t i = Int_to_Int64(from_index, false)-1; i < text.length; i++) {
+
+ for (int64_t i = first-1; i < text.length; i++) {
// Optimization: quickly skip ahead to first char in pattern:
if (find_first) {
- while (i < text.length && _next_grapheme(text, &text_state, i) != first)
+ while (i < text.length && _next_grapheme(text, &text_state, i) != first_grapheme)
++i;
}
@@ -1416,7 +1423,7 @@ public array_t Text$find_all(Text_t text, Text_t pattern)
if (I_is_zero(found)) break;
Text_t match = Text$slice(text, found, Int$plus(found, Int64_to_Int(len-1)));
Array$insert(&matches, &match, I_small(0), sizeof(Text_t));
- i = Int$plus(found, Int64_to_Int(len));
+ i = Int$plus(found, Int64_to_Int(len <= 0 ? 1 : len));
}
return matches;
@@ -1437,7 +1444,7 @@ public Text_t Text$replace(Text_t text, Text_t pattern, Text_t replacement)
} else {
ret = concat2(ret, replacement);
}
- i = Int$plus(found, Int64_to_Int(len));
+ i = Int$plus(found, Int64_to_Int(len <= 0 ? 1 : len));
}
if (Int_to_Int64(i, false) <= text.length) {
Text_t last_slice = Text$slice(text, i, Int64_to_Int(text.length));
@@ -1463,7 +1470,7 @@ public array_t Text$split(Text_t text, Text_t pattern)
if (I_is_zero(found)) break;
Text_t chunk = Text$slice(text, i, Int$minus(found, I_small(1)));
Array$insert(&chunks, &chunk, I_small(0), sizeof(Text_t));
- i = Int$plus(found, Int64_to_Int(len));
+ i = Int$plus(found, Int64_to_Int(len <= 0 ? 1 : len));
}
Text_t last_chunk = Text$slice(text, i, Int64_to_Int(text.length));