aboutsummaryrefslogtreecommitdiff
path: root/stdlib/text.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-12-21 16:32:22 -0500
committerBruce Hill <bruce@bruce-hill.com>2024-12-21 16:32:22 -0500
commit46b61d3ed2ae5bd5f74c9d580f5501b1226d9f4e (patch)
tree15256a67533f176332fec7a3feb56c6b4b2e4b23 /stdlib/text.c
parent325b367a1342826fe7174ce45cfab92091d4dbb5 (diff)
Add text:by_line()/:by_split()/:by_match()
Diffstat (limited to 'stdlib/text.c')
-rw-r--r--stdlib/text.c35
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;