hare

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

runes.ha (1839B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 use encoding::utf8;
      5 
      6 // Returns a slice of runes for a string in O(n). The caller must free the
      7 // return value.
      8 export fn torunes(s: str) []rune = {
      9 	let sl: []rune = [];
     10 	let iter = iter(s);
     11 	for (let r => next(&iter)) {
     12 		append(sl, r)!;
     13 	};
     14 	return sl;
     15 };
     16 
     17 // Returns a string from a slice of runes. The caller must free the return value.
     18 export fn fromrunes(runes: []rune) str = {
     19 	let bytes: []u8 = [];
     20 	for (let r .. runes) {
     21 		const bs = utf8::encoderune(r)!;
     22 		append(bytes, bs...)!;
     23 	};
     24 	return fromutf8_unsafe(bytes);
     25 };
     26 
     27 // Returns a string's rune-length; the number of runes encoded in a string.
     28 export fn runelen(s: str) size = {
     29 	let it = iter(s);
     30 	let n = 0z;
     31 	for (true) {
     32 		match (next(&it)) {
     33 		case rune =>
     34 			n += 1;
     35 		case done =>
     36 			break;
     37 		};
     38 	};
     39 	return n;
     40 };
     41 
     42 @test fn fromrunes() void = {
     43 	const tests: [_](str, []rune) = [
     44 		("Harriet", ['H', 'a', 'r', 'r', 'i', 'e', 't']),
     45 		("", []),
     46 		(".", ['.']),
     47 		("\a\b\f\n\r\t\v", ['\a', '\b', '\f', '\n', '\r', '\t', '\v']),
     48 		("Hello, world!", ['H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!']),
     49 		("¡Hola Mundo!", ['¡', 'H', 'o', 'l', 'a', ' ', 'M', 'u', 'n', 'd', 'o', '!']),
     50 		("Γειά σου Κόσμε!", ['Γ', 'ε', 'ι', 'ά', ' ', 'σ', 'ο', 'υ', ' ', 'Κ', 'ό', 'σ', 'μ', 'ε', '!']),
     51 		("Привет, мир!", ['П', 'р', 'и', 'в', 'е', 'т', ',', ' ', 'м', 'и', 'р', '!']),
     52 		("こんにちは世界!", ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!']),
     53 	];
     54 
     55 	for (let (string, runes) .. tests) {
     56 		const s = fromrunes(runes);
     57 		defer free(s);
     58 		assert(s == string);
     59 
     60 		const rs = torunes(s);
     61 		defer free(rs);
     62 		assert(len(rs) == len(runes));
     63 
     64 		for (let j = 0z; j < len(rs); j += 1) {
     65 			assert(rs[j] == runes[j]);
     66 		};
     67 	};
     68 };