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