Skip to content

Commit

Permalink
[mojo-stdlib] Implement compare operation for String
Browse files Browse the repository at this point in the history
Signed-off-by: zhoujing <jing.zhou@terapines.com>
  • Loading branch information
zhoujingya committed Apr 23, 2024
1 parent b176fe7 commit 2c0cae6
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 6 deletions.
72 changes: 66 additions & 6 deletions stdlib/src/builtin/string.mojo
Expand Up @@ -51,6 +51,23 @@ fn _ctlz(val: SIMD) -> __type_of(val):
return llvm_intrinsic["llvm.ctlz", __type_of(val)](val, False)


@always_inline
fn _str_compare(str1: String, str2: String) -> Int:
var min_len = len(str1) if len(str1) < len(str2) else len(str2)
var cmp = memcmp(str1._as_ptr(), str2._as_ptr(), min_len)
if cmp < 0:
return -1
elif cmp > 0:
return 1
# now check length for str1 and str2
if len(str1) == len(str2):
return 0
elif len(str1) > len(str2):
return 1
else:
return -1


# ===----------------------------------------------------------------------===#
# ord
# ===----------------------------------------------------------------------===#
Expand Down Expand Up @@ -589,13 +606,8 @@ struct String(Sized, Stringable, IntableRaising, KeyElement, Boolable):
Returns:
True if the Strings are equal and False otherwise.
"""
if len(self) != len(other):
return False

if int(self._as_ptr()) == int(other._as_ptr()):
return True

return memcmp(self._as_ptr(), other._as_ptr(), len(self)) == 0
return _str_compare(self, other) == 0

@always_inline
fn __ne__(self, other: String) -> Bool:
Expand All @@ -609,6 +621,54 @@ struct String(Sized, Stringable, IntableRaising, KeyElement, Boolable):
"""
return not (self == other)

@always_inline
fn __gt__(self, other: String) -> Bool:
"""Compares two Strings if self greater than the other.
Args:
other: The rhs of the operation.
Returns:
True if self are greater than other string.
"""
return _str_compare(self, other) == 1

@always_inline
fn __ge__(self, other: String) -> Bool:
"""Compares two Strings if self greater equal the other.
Args:
other: The rhs of the operation.
Returns:
True if self are greater equal the other string.
"""
return _str_compare(self, other) == 0 or _str_compare(self, other) == 1

@always_inline
fn __lt__(self, other: String) -> Bool:
"""Compares two Strings if self less than the other.
Args:
other: The rhs of the operation.
Returns:
True if self are less than other string.
"""
return _str_compare(self, other) == -1

@always_inline
fn __le__(self, other: String) -> Bool:
"""Compares two Strings if self less equal the other.
Args:
other: The rhs of the operation.
Returns:
True if self are less equal other string.
"""
return _str_compare(self, other) == 0 or _str_compare(self, other) == -1

@always_inline
fn __add__(self, other: String) -> String:
"""Creates a string by appending another string at the end.
Expand Down
15 changes: 15 additions & 0 deletions stdlib/test/builtin/test_string.mojo
Expand Up @@ -101,6 +101,20 @@ fn test_equality_operators() raises:
assert_not_equal(s0, "notabc")


fn test_compare_operators() raises:
assert_true(str("feefef") > str("feefe"))
assert_false(str("hello") > str("hello"))
assert_true(str("hello") >= str("hello"))
assert_false(str("hello") < str("hello"))
assert_true(str("hello") <= str("hello"))
assert_false(str("apple") > str("banana"))
assert_false(str("apple") > str("banana"))
assert_true(str("apple") > str("Banana"))
assert_false(str("apple123") > str("apple456"))
assert_false(str("appl2$") > str("banana"))
assert_false(str("") > str("a"))


fn test_add() raises:
var s1 = String("123")
var s2 = String("abc")
Expand Down Expand Up @@ -621,6 +635,7 @@ def main():
test_constructors()
test_copy()
test_equality_operators()
test_compare_operators()
test_add()
test_stringable()
test_string_join()
Expand Down

0 comments on commit 2c0cae6

Please sign in to comment.