From 05e1612c4345353680752bad23eb52eba3ab51a3 Mon Sep 17 00:00:00 2001 From: cgyurgyik Date: Fri, 19 Jun 2020 16:05:26 -0400 Subject: [PATCH] [libc] This adds the strcmp (string compare) implementation. Reviewed-by: sivachandra Differential Revision: https://reviews.llvm.org/D82134 --- libc/config/linux/x86_64/entrypoints.txt | 1 + libc/src/string/CMakeLists.txt | 10 ++++ libc/src/string/strcmp.cpp | 23 ++++++++ libc/src/string/strcmp.h | 18 ++++++ libc/test/src/string/CMakeLists.txt | 10 ++++ libc/test/src/string/strcmp_test.cpp | 97 ++++++++++++++++++++++++++++++++ 6 files changed, 159 insertions(+) create mode 100644 libc/src/string/strcmp.cpp create mode 100644 libc/src/string/strcmp.h create mode 100644 libc/test/src/string/strcmp_test.cpp diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 656ccdd..a783663 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -26,6 +26,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strcpy libc.src.string.strcat libc.src.string.strlen + libc.src.string.strcmp # sys/mman.h entrypoints libc.src.sys.mman.mmap diff --git a/libc/src/string/CMakeLists.txt b/libc/src/string/CMakeLists.txt index dee547b..51456e8 100644 --- a/libc/src/string/CMakeLists.txt +++ b/libc/src/string/CMakeLists.txt @@ -34,6 +34,16 @@ add_entrypoint_object( libc.include.string ) +add_entrypoint_object( + strcmp + SRCS + strcmp.cpp + HDRS + strcmp.h + DEPENDS + libc.include.string +) + # Helper to define a function with multiple implementations # - Computes flags to satisfy required/rejected features and arch, # - Declares an entry point, diff --git a/libc/src/string/strcmp.cpp b/libc/src/string/strcmp.cpp new file mode 100644 index 0000000..4ef7a77 --- /dev/null +++ b/libc/src/string/strcmp.cpp @@ -0,0 +1,23 @@ +//===-- Implementation of strcmp ------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/string/strcmp.h" + +#include "src/__support/common.h" + +namespace __llvm_libc { + +// TODO: Look at benefits for comparing words at a time. +int LLVM_LIBC_ENTRYPOINT(strcmp)(const char *left, const char *right) { + for (; *left && *left == *right; ++left, ++right) + ; + return *reinterpret_cast(left) - + *reinterpret_cast(right); +} + +} // namespace __llvm_libc diff --git a/libc/src/string/strcmp.h b/libc/src/string/strcmp.h new file mode 100644 index 0000000..a45f2d5 --- /dev/null +++ b/libc/src/string/strcmp.h @@ -0,0 +1,18 @@ +//===-- Implementation header for strcmp ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_STRING_STRCMP_H +#define LLVM_LIBC_SRC_STRING_STRCMP_H + +namespace __llvm_libc { + +int strcmp(const char *left, const char *right); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STRING_STRCMP_H diff --git a/libc/test/src/string/CMakeLists.txt b/libc/test/src/string/CMakeLists.txt index abe0652..992cebe 100644 --- a/libc/test/src/string/CMakeLists.txt +++ b/libc/test/src/string/CMakeLists.txt @@ -32,6 +32,16 @@ add_libc_unittest( libc.src.string.strlen ) +add_libc_unittest( + strcmp_test + SUITE + libc_string_unittests + SRCS + strcmp_test.cpp + DEPENDS + libc.src.string.strcmp +) + # Tests all implementations that can run on the host. function(add_libc_multi_impl_test name) get_property(fq_implementations GLOBAL PROPERTY ${name}_implementations) diff --git a/libc/test/src/string/strcmp_test.cpp b/libc/test/src/string/strcmp_test.cpp new file mode 100644 index 0000000..18e20a2 --- /dev/null +++ b/libc/test/src/string/strcmp_test.cpp @@ -0,0 +1,97 @@ +//===-- Unittests for strcmp ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/string/strcmp.h" +#include "utils/UnitTest/Test.h" + +TEST(StrCmpTest, EmptyStringsShouldReturnZero) { + const char *s1 = ""; + const char *s2 = ""; + int result = __llvm_libc::strcmp(s1, s2); + ASSERT_EQ(result, 0); + + // Verify operands reversed. + result = __llvm_libc::strcmp(s2, s1); + ASSERT_EQ(result, 0); +} + +TEST(StrCmpTest, EmptyStringShouldNotEqualNonEmptyString) { + const char *empty = ""; + const char *s2 = "abc"; + int result = __llvm_libc::strcmp(empty, s2); + // This should be '\0' - 'a' = -97 + ASSERT_EQ(result, -97); + + // Similar case if empty string is second argument. + const char *s3 = "123"; + result = __llvm_libc::strcmp(s3, empty); + // This should be '1' - '\0' = 49 + ASSERT_EQ(result, 49); +} + +TEST(StrCmpTest, EqualStringsShouldReturnZero) { + const char *s1 = "abc"; + const char *s2 = "abc"; + int result = __llvm_libc::strcmp(s1, s2); + ASSERT_EQ(result, 0); + + // Verify operands reversed. + result = __llvm_libc::strcmp(s2, s1); + ASSERT_EQ(result, 0); +} + +TEST(StrCmpTest, ShouldReturnResultOfFirstDifference) { + const char *s1 = "___B42__"; + const char *s2 = "___C55__"; + int result = __llvm_libc::strcmp(s1, s2); + // This should return 'B' - 'C' = -1. + ASSERT_EQ(result, -1); + + // Verify operands reversed. + result = __llvm_libc::strcmp(s2, s1); + // This should return 'C' - 'B' = 1. + ASSERT_EQ(result, 1); +} + +TEST(StrCmpTest, CapitalizedLetterShouldNotBeEqual) { + const char *s1 = "abcd"; + const char *s2 = "abCd"; + int result = __llvm_libc::strcmp(s1, s2); + // 'c' - 'C' = 32. + ASSERT_EQ(result, 32); + + // Verify operands reversed. + result = __llvm_libc::strcmp(s2, s1); + // 'C' - 'c' = -32. + ASSERT_EQ(result, -32); +} + +TEST(StrCmpTest, UnequalLengthStringsShouldNotReturnZero) { + const char *s1 = "abc"; + const char *s2 = "abcd"; + int result = __llvm_libc::strcmp(s1, s2); + // '\0' - 'd' = -100. + ASSERT_EQ(result, -100); + + // Verify operands reversed. + result = __llvm_libc::strcmp(s2, s1); + // 'd' - '\0' = 100. + ASSERT_EQ(result, 100); +} + +TEST(StrCmpTest, StringArgumentSwapChangesSign) { + const char *a = "a"; + const char *b = "b"; + int result = __llvm_libc::strcmp(b, a); + // 'b' - 'a' = 1. + ASSERT_EQ(result, 1); + + result = __llvm_libc::strcmp(a, b); + // 'a' - 'b' = -1. + ASSERT_EQ(result, -1); +} -- 2.7.4