aboutsummaryrefslogtreecommitdiff
path: root/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib')
-rw-r--r--stdlib/integers.c2
-rw-r--r--stdlib/patterns.c35
-rw-r--r--stdlib/patterns.h1
3 files changed, 37 insertions, 1 deletions
diff --git a/stdlib/integers.c b/stdlib/integers.c
index d0cc6617..4f1947d2 100644
--- a/stdlib/integers.c
+++ b/stdlib/integers.c
@@ -409,7 +409,7 @@ public const TypeInfo_t Int$info = {
return bit_array; \
} \
public to_attr Range_t KindOfInt ## $to(c_type from, c_type to) { \
- return (Range_t){Int64_to_Int(from), Int64_to_Int(to), to >= from ? (Int_t){.small=(1<<2)&1} : (Int_t){.small=(1<<2)&1}}; \
+ return (Range_t){Int64_to_Int(from), Int64_to_Int(to), to >= from ? I_small(1): I_small(-1)}; \
} \
public PUREFUNC Optional ## KindOfInt ## _t KindOfInt ## $parse(Text_t text) { \
OptionalInt_t full_int = Int$parse(text); \
diff --git a/stdlib/patterns.c b/stdlib/patterns.c
index a5ca6971..97cade4a 100644
--- a/stdlib/patterns.c
+++ b/stdlib/patterns.c
@@ -1050,6 +1050,41 @@ public Text_t Text$map(Text_t text, Pattern_t pattern, Closure_t fn)
return ret;
}
+public void Text$each(Text_t text, Pattern_t pattern, Closure_t fn)
+{
+ int32_t first_grapheme = Text$get_grapheme(pattern, 0);
+ bool find_first = (first_grapheme != '{'
+ && !uc_is_property((ucs4_t)first_grapheme, UC_PROPERTY_QUOTATION_MARK)
+ && !uc_is_property((ucs4_t)first_grapheme, UC_PROPERTY_PAIRED_PUNCTUATION));
+
+ TextIter_t text_state = {text, 0, 0};
+ void (*action)(Match_t, void*) = fn.fn;
+ for (int64_t pos = 0; pos < text.length; pos++) {
+ // Optimization: quickly skip ahead to first char in pattern:
+ if (find_first) {
+ while (pos < text.length && Text$get_grapheme_fast(&text_state, pos) != first_grapheme)
+ ++pos;
+ }
+
+ capture_t captures[MAX_BACKREFS] = {};
+ int64_t match_len = match(text, pos, pattern, 0, captures, 0);
+ if (match_len < 0) continue;
+
+ Match_t m = {
+ .text=Text$slice(text, I(pos+1), I(pos+match_len)),
+ .index=I(pos+1),
+ .captures={},
+ };
+ for (int i = 0; captures[i].occupied; i++) {
+ Text_t capture = Text$slice(text, I(captures[i].index+1), I(captures[i].index+captures[i].length));
+ Array$insert(&m.captures, &capture, I(0), sizeof(Text_t));
+ }
+
+ action(m, fn.userdata);
+ pos += (match_len - 1);
+ }
+}
+
public Text_t Text$replace_all(Text_t text, Table_t replacements, Text_t backref_pat, bool recursive)
{
if (replacements.entries.length == 0) return text;
diff --git a/stdlib/patterns.h b/stdlib/patterns.h
index bf8dee6b..2b30a3ae 100644
--- a/stdlib/patterns.h
+++ b/stdlib/patterns.h
@@ -33,6 +33,7 @@ Array_t Text$find_all(Text_t text, Pattern_t pattern);
PUREFUNC bool Text$has(Text_t text, Pattern_t pattern);
OptionalArray_t Text$matches(Text_t text, Pattern_t pattern);
Text_t Text$map(Text_t text, Pattern_t pattern, Closure_t fn);
+void Text$each(Text_t text, Pattern_t pattern, Closure_t fn);
#define Pattern$hash Text$hash
#define Pattern$compare Text$compare