aboutsummaryrefslogtreecommitdiff
path: root/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib')
-rw-r--r--stdlib/text.c52
-rw-r--r--stdlib/text.h1
2 files changed, 53 insertions, 0 deletions
diff --git a/stdlib/text.c b/stdlib/text.c
index 44179fa7..69e54ff6 100644
--- a/stdlib/text.c
+++ b/stdlib/text.c
@@ -563,6 +563,58 @@ public Text_t Text$slice(Text_t text, Int_t first_int, Int_t last_int)
}
}
+public Text_t Text$cluster(Text_t text, Int_t index_int)
+{
+ int64_t index = Int_to_Int64(index_int, false);
+ if (index == 0) fail("Invalid index: 0");
+
+ if (index < 0) index = text.length + index + 1;
+
+ if (index > text.length || index < 1)
+ fail("Invalid index: %ld is beyond the length of the text (length = %ld)",
+ Int_to_Int64(index_int, false), text.length);
+
+ switch (text.tag) {
+ case TEXT_SHORT_ASCII: {
+ return (Text_t) {
+ .tag=TEXT_SHORT_ASCII,
+ .length=1,
+ .short_ascii={text.short_ascii[index-1]},
+ };
+ }
+ case TEXT_ASCII: {
+ return (Text_t) {
+ .tag=TEXT_SHORT_ASCII,
+ .length=1,
+ .short_ascii={text.ascii[index-1]},
+ };
+ }
+ case TEXT_SHORT_GRAPHEMES: {
+ return (Text_t) {
+ .tag=TEXT_SHORT_GRAPHEMES,
+ .length=1,
+ .short_graphemes={text.short_graphemes[index-1]},
+ };
+ }
+ case TEXT_GRAPHEMES: {
+ return (Text_t) {
+ .tag=TEXT_SHORT_GRAPHEMES,
+ .length=1,
+ .short_graphemes={text.graphemes[index-1]},
+ };
+ }
+ case TEXT_SUBTEXT: {
+ Text_t *subtext = text.subtexts;
+ while (index > subtext[0].length) {
+ index -= subtext[0].length;
+ ++subtext;
+ }
+ return Text$cluster(*subtext, I(index));
+ }
+ default: errx(1, "Invalid tag");
+ }
+}
+
Text_t text_from_u32(ucs4_t *codepoints, int64_t num_codepoints, bool normalize)
{
// Normalization is apparently guaranteed to never exceed 3x in the input length
diff --git a/stdlib/text.h b/stdlib/text.h
index 45aa00ca..4f23834f 100644
--- a/stdlib/text.h
+++ b/stdlib/text.h
@@ -28,6 +28,7 @@ Text_t Text$_concat(int n, Text_t items[n]);
#define Text$concat(...) Text$_concat(sizeof((Text_t[]){__VA_ARGS__})/sizeof(Text_t), (Text_t[]){__VA_ARGS__})
#define Texts(...) Text$concat(__VA_ARGS__)
Text_t Text$slice(Text_t text, Int_t first_int, Int_t last_int);
+Text_t Text$cluster(Text_t text, Int_t index_int);
OptionalText_t Text$from_str(const char *str);
OptionalText_t Text$from_strn(const char *str, size_t len);
PUREFUNC uint64_t Text$hash(Text_t *text);