diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-12-21 16:32:22 -0500 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-12-21 16:32:22 -0500 |
| commit | 46b61d3ed2ae5bd5f74c9d580f5501b1226d9f4e (patch) | |
| tree | 15256a67533f176332fec7a3feb56c6b4b2e4b23 /stdlib/text.c | |
| parent | 325b367a1342826fe7174ce45cfab92091d4dbb5 (diff) | |
Add text:by_line()/:by_split()/:by_match()
Diffstat (limited to 'stdlib/text.c')
| -rw-r--r-- | stdlib/text.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/stdlib/text.c b/stdlib/text.c index 57a98e8d..65d4150a 100644 --- a/stdlib/text.c +++ b/stdlib/text.c @@ -1422,6 +1422,41 @@ public Array_t Text$lines(Text_t text) return lines; } +typedef struct { + TextIter_t state; + int64_t i; +} line_iter_state_t; + +static OptionalText_t next_line(line_iter_state_t *state) +{ + Text_t text = state->state.text; + for (int64_t i = state->i; i < text.length; i++) { + int32_t grapheme = Text$get_grapheme_fast(&state->state, i); + if (grapheme == '\r' && Text$get_grapheme_fast(&state->state, i + 1) == '\n') { // CRLF + Text_t line = Text$slice(text, I(state->i+1), I(i)); + state->i = i + 2; // skip one extra for CR + return line; + } else if (grapheme == '\n') { // newline + Text_t line = Text$slice(text, I(state->i+1), I(i)); + state->i = i + 1; + return line; + } else if (i == text.length-1 && state->i != i) { // last line + Text_t line = Text$slice(text, I(state->i+1), I(i+1)); + state->i = i + 1; + return line; + } + } + return NONE_TEXT; +} + +public Closure_t Text$by_line(Text_t text) +{ + return (Closure_t){ + .fn=(void*)next_line, + .userdata=new(line_iter_state_t, .state={text, 0, 0}, .i=0), + }; +} + PUREFUNC public bool Text$is_none(const void *t, const TypeInfo_t*) { return ((Text_t*)t)->length < 0; |
