aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgingerBill <gingerBill@users.noreply.github.com>2020-02-23 10:08:50 +0000
committerGitHub <noreply@github.com>2020-02-23 10:08:50 +0000
commit49ecd73406e92c2cc0846188f4dfaf1ec687d1f2 (patch)
tree793511c5c0bccd3696a1da145ec5396d153755d8
parent0b7711684bae15ac5bfe3ac78230e9d6e9057673 (diff)
parent1f0c1943daa21a4c06c21c8d3b8f704bb7f191f8 (diff)
Merge pull request #562 from Tetralux/string-compare
Fix #552: Fix strings.compare for empty strings and different-length strings.
-rw-r--r--core/mem/mem.odin12
-rw-r--r--core/strings/strings.odin2
2 files changed, 13 insertions, 1 deletions
diff --git a/core/mem/mem.odin b/core/mem/mem.odin
index 144ba07a8..6dd4e9c27 100644
--- a/core/mem/mem.odin
+++ b/core/mem/mem.odin
@@ -45,8 +45,18 @@ copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> rawpt
return runtime.mem_copy_non_overlapping(dst, src, len);
}
compare :: inline proc "contextless" (a, b: []byte) -> int {
- return compare_byte_ptrs(&a[0], &b[0], min(len(a), len(b)));
+ // NOTE(tetra): no-abc is okay here because if the slices are empty, `&a[0]` is just nil+0 == nil, which
+ // compare_byte_ptrs handles fine when the passed length is also zero.
+ res := #no_bounds_check compare_byte_ptrs(&a[0], &b[0], min(len(a), len(b)));
+ if res == 0 && len(a) != len(b) {
+ return len(a) <= len(b) ? -1 : +1;
+ } else if len(a) == 0 && len(b) == 0 {
+ return 0;
+ } else {
+ return res;
+ }
}
+
compare_byte_ptrs :: proc "contextless" (a, b: ^byte, n: int) -> int #no_bounds_check {
x := slice_ptr(a, n);
y := slice_ptr(b, n);
diff --git a/core/strings/strings.odin b/core/strings/strings.odin
index 6e004993a..a477b9e13 100644
--- a/core/strings/strings.odin
+++ b/core/strings/strings.odin
@@ -52,6 +52,8 @@ unsafe_string_to_cstring :: proc(str: string) -> cstring {
return cstring(d.data);
}
+// Compares two strings, returning a value representing which one comes first lexiographically.
+// -1 for `a`; 1 for `b`, or 0 if they are equal.
compare :: proc(lhs, rhs: string) -> int {
return mem.compare(transmute([]byte)lhs, transmute([]byte)rhs);
}