From 1f0c1943daa21a4c06c21c8d3b8f704bb7f191f8 Mon Sep 17 00:00:00 2001 From: Tetralux Date: Wed, 12 Feb 2020 10:26:38 +0000 Subject: [PATCH] Fix #552. - Fix comparisons involving one or more empty string. - Fix comparisons against two strings of different lengths. --- core/mem/mem.odin | 12 +++++++++++- core/strings/strings.odin | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) 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); }