hare

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

string.ha (3438B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 use encoding::utf8;
      5 use sort::cmp;
      6 use strings;
      7 
      8 // Converts all ASCII uppercase characters in a string to their lowercase
      9 // representation, returning a new string. The return value must be freed by the
     10 // caller.
     11 export fn strlower(s: str) str = {
     12 	let new: []u8 = alloc([], len(s))!;
     13 	return strlower_buf(s, new);
     14 };
     15 
     16 // Converts all ASCII uppercase characters in a string to their lowercase
     17 // representation, returning a new string. The new string data is stored in the
     18 // supplied buffer (overwriting any existing contents). The buffer is permitted
     19 // to exactly overlap the string. This function will abort if the buffer's
     20 // capacity is too small to fit the entire string.
     21 export fn strlower_buf(s: str, buf: []u8) str = {
     22 	let buf = buf[..0];
     23 	let it = strings::iter(s);
     24 	for (let r => strings::next(&it)) {
     25 		static append(buf, utf8::encoderune(tolower(r))!...)!;
     26 	};
     27 	return strings::fromutf8(buf)!;
     28 };
     29 
     30 // Converts all ASCII lowercase characters in a string to their uppercase
     31 // representation, returning a new string. The return value must be freed by the
     32 // caller.
     33 export fn strupper(s: str) str = {
     34 	let new: []u8 = alloc([], len(s))!;
     35 	return strupper_buf(s, new);
     36 };
     37 
     38 // Converts all ASCII lowercase characters in a string to their uppercase
     39 // representation, returning a new string. The new string data is stored in the
     40 // supplied buffer (overwriting any existing contents). The buffer is permitted
     41 // to exactly overlap the string. This function will abort if the buffer's
     42 // capacity is too small to fit the entire string.
     43 export fn strupper_buf(s: str, buf: []u8) str = {
     44 	let buf = buf[..0];
     45 	let it = strings::iter(s);
     46 	for (let r => strings::next(&it)) {
     47 		static append(buf, utf8::encoderune(toupper(r))!...)!;
     48 	};
     49 	return strings::fromutf8(buf)!;
     50 };
     51 
     52 // Compares two strings by their sort order, treating all ASCII capital letters
     53 // as their lowercase counterpart (i.e. an ASCII-case-insensitive comparison is
     54 // performed). Zero is returned if the strings are equal, a negative value if a
     55 // is less than b, or a positive value if a is greater than b.
     56 export fn strcasecmp(a: str, b: str) int = {
     57 	let abs = strings::toutf8(a);
     58 	let bbs = strings::toutf8(b);
     59 	for (let i = 0z; i < len(abs) && i < len(bbs); i += 1) {
     60 		// you know that i am called "the Cast"...
     61 		// because i *really* love to cast...
     62 		// sometimes i sit and cast all day... ha ha, but
     63 		// sometimes i get carried away!
     64 		let cmp = tolower(abs[i]: rune): u32: int - tolower(bbs[i]: rune): u32: int;
     65 		if (cmp != 0) return cmp;
     66 	};
     67 	return cmp::sizes(&len(abs), &len(bbs));
     68 };
     69 
     70 @test fn strcasecmp() void = {
     71 	let s = strupper("ABC");
     72 	defer free(s);
     73 	assert(s == "ABC");
     74 
     75 	let s = strlower("ABC");
     76 	defer free(s);
     77 	assert(s == "abc");
     78 
     79 	let s = strupper("abc");
     80 	defer free(s);
     81 	assert(s == "ABC");
     82 
     83 	let s = strlower("abc");
     84 	defer free(s);
     85 	assert(s == "abc");
     86 
     87 	let s = strupper("[[[");
     88 	defer free(s);
     89 	assert(s == "[[[");
     90 
     91 	let s = strlower("[[[");
     92 	defer free(s);
     93 	assert(s == "[[[");
     94 
     95 	let s = strupper("こ");
     96 	defer free(s);
     97 	assert(s == "こ");
     98 
     99 	let s = strlower("こ");
    100 	defer free(s);
    101 	assert(s == "こ");
    102 
    103 	assert(strcasecmp("ABC", "ABC") == 0);
    104 	assert(strcasecmp("ABC", "abc") == 0);
    105 	assert(strcasecmp("ABC", "aB") > 0);
    106 	assert(strcasecmp("ab", "Abc") < 0);
    107 	assert(strcasecmp("bcd", "ABC") > 0);
    108 	assert(strcasecmp("ABC", "[[[") > 0);
    109 };