hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 5101d99b1600acebd796c730bb4ef2d3ff627fb3
parent 991b9323d6c52e02b96f54a16b7032e39560e53b
Author: Byron Torres <b@torresjrjr.com>
Date:   Mon, 23 May 2022 11:33:00 +0100

strings: add fromrunes()

Signed-off-by: Byron Torres <b@torresjrjr.com>

Diffstat:
Mscripts/gen-stdlib | 1+
Mstdlib.mk | 2++
Mstrings/iter.ha | 15---------------
Astrings/runes.ha | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 69 insertions(+), 15 deletions(-)

diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -1210,6 +1210,7 @@ strings() { cstrings.ha \ dup.ha \ iter.ha \ + runes.ha \ sub.ha \ suffix.ha \ tokenize.ha \ diff --git a/stdlib.mk b/stdlib.mk @@ -1825,6 +1825,7 @@ stdlib_strings_any_srcs = \ $(STDLIB)/strings/cstrings.ha \ $(STDLIB)/strings/dup.ha \ $(STDLIB)/strings/iter.ha \ + $(STDLIB)/strings/runes.ha \ $(STDLIB)/strings/sub.ha \ $(STDLIB)/strings/suffix.ha \ $(STDLIB)/strings/tokenize.ha \ @@ -3976,6 +3977,7 @@ testlib_strings_any_srcs = \ $(STDLIB)/strings/cstrings.ha \ $(STDLIB)/strings/dup.ha \ $(STDLIB)/strings/iter.ha \ + $(STDLIB)/strings/runes.ha \ $(STDLIB)/strings/sub.ha \ $(STDLIB)/strings/suffix.ha \ $(STDLIB)/strings/tokenize.ha \ diff --git a/strings/iter.ha b/strings/iter.ha @@ -145,18 +145,3 @@ export fn iterstr(iter: *iterator) str = { assert(next(&s) is void); assert(prev(&s) as rune == 'に'); }; - -// Returns a slice of runes for a string in O(n). The caller must free the -// return value. -export fn runes(s: str) []rune = { - let sl: []rune = alloc([], len(s)); - let iter = iter(s); - for (true) { - match (next(&iter)) { - case void => break; - case let r: rune => - append(sl, r); - }; - }; - return sl; -}; diff --git a/strings/runes.ha b/strings/runes.ha @@ -0,0 +1,66 @@ +// License: MPL-2.0 +// (c) 2022 Byron Torres <b@torresjrjr.com> +use encoding::utf8; + +// Returns a slice of runes for a string in O(n). The caller must free the +// return value. +export fn runes(s: str) []rune = { + let sl: []rune = alloc([], len(s)); + let iter = iter(s); + for (true) { + match (next(&iter)) { + case void => break; + case let r: rune => + append(sl, r); + }; + }; + return sl; +}; + +// Returns a string from a slice of runes. The caller must free the return value. +export fn fromrunes(rs: []rune) str = { + let bytes: []u8 = []; + for (let i = 0z; i < len(rs); i += 1) { + const bs = encoding::utf8::encoderune(rs[i]); + append(bytes, bs...); + }; + return fromutf8(bytes); +}; + +@test fn fromrunes() void = { + const rs = ['H', 'a', 'r', 'r', 'i', 'e', 't']; + const s = fromrunes(rs); defer free(s); + assert(s == "Harriet", "strings::fromrunes() error (Harriet)"); + + const rs: []rune = []; + const s = fromrunes(rs); defer free(s); + assert(s == "", "strings::fromrunes() error (empty)"); + + const rs = ['.']; + const s = fromrunes(rs); defer free(s); + assert(s == ".", "strings::fromrunes() error (period)"); + + const rs = ['\a', '\b', '\f', '\n', '\r', '\t', '\v']; + const s = fromrunes(rs); defer free(s); + assert(s == "\a\b\f\n\r\t\v", "strings::fromrunes() error (control chars)"); + + const rs = ['H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!']; + const s = fromrunes(rs); defer free(s); + assert(s == "Hello, world!", "strings::fromrunes() error (English)"); + + const rs = ['¡', 'H', 'o', 'l', 'a', ' ', 'M', 'u', 'n', 'd', 'o', '!']; + const s = fromrunes(rs); defer free(s); + assert(s == "¡Hola Mundo!", "strings::fromrunes() error (Spanish)"); + + const rs = ['Γ', 'ε', 'ι', 'ά', ' ', 'σ', 'ο', 'υ', ' ', 'Κ', 'ό', 'σ', 'μ', 'ε', '!']; + const s = fromrunes(rs); defer free(s); + assert(s == "Γειά σου Κόσμε!", "strings::fromrunes() error (Greek)"); + + const rs = ['П', 'р', 'и', 'в', 'е', 'т', ',', ' ', 'м', 'и', 'р', '!']; + const s = fromrunes(rs); defer free(s); + assert(s == "Привет, мир!", "strings::fromrunes() error (Russian)"); + + const rs = ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!']; + const s = fromrunes(rs); defer free(s); + assert(s == "こんにちは世界!", "strings::fromrunes() error (Japanese)"); +};