commit c7b0a929f568b1feb8d43df4498dd9b32f98187c
parent 70d771de6bccb1866cf3936b8fd7e9cba42e616b
Author: Bor Grošelj Simić <bgs@turminal.net>
Date: Fri, 22 Apr 2022 02:15:23 +0200
compare strings byte-by-byte
and rename strings::strcmp to strings::compare
Signed-off-by: Bor Grošelj Simić <bgs@turminal.net>
Diffstat:
9 files changed, 31 insertions(+), 46 deletions(-)
diff --git a/cmd/haredoc/sort.ha b/cmd/haredoc/sort.ha
@@ -98,7 +98,7 @@ fn decl_cmp(a: const *void, b: const *void) int = {
return -1;
};
const id_a = decl_ident(a), id_b = decl_ident(b);
- return strings::strcmp(id_a[len(id_a) - 1], id_b[len(id_b) - 1]);
+ return strings::compare(id_a[len(id_a) - 1], id_b[len(id_b) - 1]);
};
fn decl_ident(decl: ast::decl) ast::ident = {
diff --git a/fnmatch/fnmatch.ha b/fnmatch/fnmatch.ha
@@ -335,7 +335,7 @@ fn match_ctype(it: *strings::iterator, c: rune) (bool | errors::invalid) = {
type funcmap = (str, *fn(c: rune) bool);
fn cmp(a: const *void, b: const *void) int =
- strings::strcmp((a: *funcmap).0, *(b: const *str));
+ strings::compare((a: *funcmap).0, *(b: const *str));
fn ctype_name_to_func(name: str) nullable *fn(c: rune) bool = {
const map: [_]funcmap = [
diff --git a/glob/glob.ha b/glob/glob.ha
@@ -261,7 +261,7 @@ fn strstack_sort(ss: *strstack, pos: size) void = {
};
fn bufcmp(a: const *void, b: const *void) int =
- strings::strcmp(
+ strings::compare(
strio::string(b: *strio::stream),
strio::string(a: *strio::stream),
);
diff --git a/hare/types/store.ha b/hare/types/store.ha
@@ -516,7 +516,7 @@ fn tuple_from_ast(
fn field_cmp(a: const *void, b: const *void) int = {
const a = a: const *struct_field, b = b: *const struct_field;
- return strings::strcmp(a.name, b.name);
+ return strings::compare(a.name, b.name);
};
fn type_finish(t: *_type) void = {
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -1125,7 +1125,7 @@ strings() {
utf8.ha \
index.ha \
trim.ha \
- strcmp.ha \
+ compare.ha \
pad.ha \
replace.ha
gen_ssa strings bytes encoding::utf8 types
diff --git a/sort/types.ha b/sort/types.ha
@@ -10,7 +10,7 @@ export type cmpfunc = fn(a: const *void, b: const *void) int;
fn scmp(a: const *void, b: const *void) int = {
const a = a: const *str, b = b: const *str;
- return strings::strcmp(*a, *b);
+ return strings::compare(*a, *b);
};
fn icmp(a: const *void, b: const *void) int = {
diff --git a/stdlib.mk b/stdlib.mk
@@ -1727,7 +1727,7 @@ stdlib_strings_any_srcs= \
$(STDLIB)/strings/utf8.ha \
$(STDLIB)/strings/index.ha \
$(STDLIB)/strings/trim.ha \
- $(STDLIB)/strings/strcmp.ha \
+ $(STDLIB)/strings/compare.ha \
$(STDLIB)/strings/pad.ha \
$(STDLIB)/strings/replace.ha
@@ -3766,7 +3766,7 @@ testlib_strings_any_srcs= \
$(STDLIB)/strings/utf8.ha \
$(STDLIB)/strings/index.ha \
$(STDLIB)/strings/trim.ha \
- $(STDLIB)/strings/strcmp.ha \
+ $(STDLIB)/strings/compare.ha \
$(STDLIB)/strings/pad.ha \
$(STDLIB)/strings/replace.ha
diff --git a/strings/compare.ha b/strings/compare.ha
@@ -0,0 +1,23 @@
+// Compares two strings by their Unicode codepoint sort order. 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 compare(a: str, b: str) int = {
+ let a = toutf8(a), b = toutf8(b);
+ let ln = if (len(a) < len(b)) (len(a), -1) else (len(b), 1);
+ for (let i = 0z; i < ln.0; i += 1) {
+ if (a[i] != b[i]) {
+ return a[i]: int - b[i]: int;
+ };
+ };
+ return if (len(a) == len(b)) 0 else ln.1;
+};
+
+
+@test fn compare() void = {
+ assert(compare("ABC", "ABC") == 0);
+ assert(compare("ABC", "AB") > 0);
+ assert(compare("AB", "ABC") < 0);
+ assert(compare("BCD", "ABC") > 0);
+ assert(compare("ABC", "こんにちは") < 0);
+ assert(compare("ABC", "abc") < 0);
+};
diff --git a/strings/strcmp.ha b/strings/strcmp.ha
@@ -1,38 +0,0 @@
-// Compares two strings by their Unicode codepoint sort order. 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 strcmp(a: str, b: str) int = {
- let a = iter(a), b = iter(b);
- for (true) {
- let ra = match (next(&a)) {
- case void =>
- match (next(&b)) {
- case void =>
- return 0;
- case rune =>
- return -1;
- };
- case let r: rune =>
- yield r;
- };
- let rb = match (next(&b)) {
- case void =>
- return 1;
- case let r: rune =>
- yield r;
- };
- if (ra != rb) {
- return ra: u32: int - rb: u32: int;
- };
- };
- abort("unreachable");
-};
-
-@test fn strcmp() void = {
- assert(strcmp("ABC", "ABC") == 0);
- assert(strcmp("ABC", "AB") > 0);
- assert(strcmp("AB", "ABC") < 0);
- assert(strcmp("BCD", "ABC") > 0);
- assert(strcmp("ABC", "こんにちは") < 0);
- assert(strcmp("ABC", "abc") < 0);
-};