diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-11-09 16:55:44 -0500 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-11-09 16:55:44 -0500 |
| commit | 06d3ec138003e412d8a2adde71969f01a25fe96a (patch) | |
| tree | d1a737d43bb477ea214d1446999c66225aee4deb /stdlib | |
| parent | 898bee15817573b5ab865a1dae7e52da310affa8 (diff) | |
Bugfix for fixed-size integer ranges
Diffstat (limited to 'stdlib')
| -rw-r--r-- | stdlib/integers.c | 2 | ||||
| -rw-r--r-- | stdlib/patterns.c | 35 | ||||
| -rw-r--r-- | stdlib/patterns.h | 1 |
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 |
