diff options
Diffstat (limited to 'libc')
-rw-r--r-- | libc/config/baremetal/entrypoints.txt | 2 | ||||
-rw-r--r-- | libc/config/darwin/arm/entrypoints.txt | 2 | ||||
-rw-r--r-- | libc/config/gpu/entrypoints.txt | 2 | ||||
-rw-r--r-- | libc/config/linux/aarch64/entrypoints.txt | 2 | ||||
-rw-r--r-- | libc/config/linux/arm/entrypoints.txt | 2 | ||||
-rw-r--r-- | libc/config/linux/x86_64/entrypoints.txt | 2 | ||||
-rw-r--r-- | libc/config/windows/entrypoints.txt | 2 | ||||
-rw-r--r-- | libc/spec/bsd_ext.td | 20 | ||||
-rw-r--r-- | libc/src/__support/ctype_utils.h | 6 | ||||
-rw-r--r-- | libc/src/ctype/tolower.cpp | 6 | ||||
-rw-r--r-- | libc/src/string/CMakeLists.txt | 22 | ||||
-rw-r--r-- | libc/src/string/strcasecmp.cpp | 25 | ||||
-rw-r--r-- | libc/src/string/strcasecmp.h | 18 | ||||
-rw-r--r-- | libc/src/string/strncasecmp.cpp | 26 | ||||
-rw-r--r-- | libc/src/string/strncasecmp.h | 20 | ||||
-rw-r--r-- | libc/test/src/string/CMakeLists.txt | 20 | ||||
-rw-r--r-- | libc/test/src/string/strcasecmp_test.cpp | 46 | ||||
-rw-r--r-- | libc/test/src/string/strcmp_test.cpp | 11 | ||||
-rw-r--r-- | libc/test/src/string/strncasecmp_test.cpp | 48 | ||||
-rw-r--r-- | libc/test/src/string/strncmp_test.cpp | 11 |
20 files changed, 288 insertions, 5 deletions
diff --git a/libc/config/baremetal/entrypoints.txt b/libc/config/baremetal/entrypoints.txt index 6efa4484b8ab..db645c06fe26 100644 --- a/libc/config/baremetal/entrypoints.txt +++ b/libc/config/baremetal/entrypoints.txt @@ -31,6 +31,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.memset libc.src.string.stpcpy libc.src.string.stpncpy + libc.src.string.strcasecmp libc.src.string.strcat libc.src.string.strchr libc.src.string.strcmp @@ -39,6 +40,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strlcat libc.src.string.strlcpy libc.src.string.strlen + libc.src.string.strncasecmp libc.src.string.strncat libc.src.string.strncmp libc.src.string.strncpy diff --git a/libc/config/darwin/arm/entrypoints.txt b/libc/config/darwin/arm/entrypoints.txt index 4a9af696f728..cf2931963cfa 100644 --- a/libc/config/darwin/arm/entrypoints.txt +++ b/libc/config/darwin/arm/entrypoints.txt @@ -31,6 +31,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.memset libc.src.string.stpcpy libc.src.string.stpncpy + libc.src.string.strcasecmp libc.src.string.strcat libc.src.string.strchr libc.src.string.strcmp @@ -39,6 +40,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strlcat libc.src.string.strlcpy libc.src.string.strlen + libc.src.string.strncasecmp libc.src.string.strncat libc.src.string.strncmp libc.src.string.strncpy diff --git a/libc/config/gpu/entrypoints.txt b/libc/config/gpu/entrypoints.txt index 8b058df246c6..57b314f3d231 100644 --- a/libc/config/gpu/entrypoints.txt +++ b/libc/config/gpu/entrypoints.txt @@ -30,6 +30,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.memset libc.src.string.stpcpy libc.src.string.stpncpy + libc.src.string.strcasecmp libc.src.string.strcat libc.src.string.strchr libc.src.string.strcmp @@ -38,6 +39,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strlcat libc.src.string.strlcpy libc.src.string.strlen + libc.src.string.strncasecmp libc.src.string.strncat libc.src.string.strncmp libc.src.string.strncpy diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 14e0cc934bb2..7223975eb835 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -40,6 +40,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.memset libc.src.string.stpcpy libc.src.string.stpncpy + libc.src.string.strcasecmp libc.src.string.strcat libc.src.string.strchr libc.src.string.strcmp @@ -51,6 +52,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strlcat libc.src.string.strlcpy libc.src.string.strlen + libc.src.string.strncasecmp libc.src.string.strncat libc.src.string.strncmp libc.src.string.strncpy diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt index 725365231af5..f4228f120146 100644 --- a/libc/config/linux/arm/entrypoints.txt +++ b/libc/config/linux/arm/entrypoints.txt @@ -31,6 +31,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.memset libc.src.string.stpcpy libc.src.string.stpncpy + libc.src.string.strcasecmp libc.src.string.strcat libc.src.string.strchr libc.src.string.strcmp @@ -39,6 +40,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strlcat libc.src.string.strlcpy libc.src.string.strlen + libc.src.string.strncasecmp libc.src.string.strncat libc.src.string.strncmp libc.src.string.strncpy diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 138c574cf489..2c1c938c5fff 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -40,6 +40,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.memset libc.src.string.stpcpy libc.src.string.stpncpy + libc.src.string.strcasecmp libc.src.string.strcat libc.src.string.strchr libc.src.string.strcmp @@ -52,6 +53,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strlcat libc.src.string.strlcpy libc.src.string.strlen + libc.src.string.strncasecmp libc.src.string.strncat libc.src.string.strncmp libc.src.string.strncpy diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt index 61f28fae5bbc..01c33f9d68d4 100644 --- a/libc/config/windows/entrypoints.txt +++ b/libc/config/windows/entrypoints.txt @@ -31,6 +31,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.memset libc.src.string.stpcpy libc.src.string.stpncpy + libc.src.string.strcasecmp libc.src.string.strcat libc.src.string.strchr libc.src.string.strcmp @@ -39,6 +40,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strlcat libc.src.string.strlcpy libc.src.string.strlen + libc.src.string.strncasecmp libc.src.string.strncat libc.src.string.strncmp libc.src.string.strncpy diff --git a/libc/spec/bsd_ext.td b/libc/spec/bsd_ext.td index 5779ab79c4f1..9ee07ce4e182 100644 --- a/libc/spec/bsd_ext.td +++ b/libc/spec/bsd_ext.td @@ -18,6 +18,25 @@ def BsdExtensions : StandardSpec<"BSDExtensions"> { ] >; + HeaderSpec Strings = HeaderSpec< + "strings.h", + [], // Macros + [], // Types + [], // Enumerations + [ + FunctionSpec< + "strcasecmp", + RetValSpec<IntType>, + [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>] + >, + FunctionSpec< + "strncasecmp", + RetValSpec<IntType>, + [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>, ArgSpec<SizeTType>] + >, + ] + >; + HeaderSpec SysWait = HeaderSpec< "sys/wait.h", [], // Macros @@ -34,6 +53,7 @@ def BsdExtensions : StandardSpec<"BSDExtensions"> { let Headers = [ String, + Strings, SysWait, ]; } diff --git a/libc/src/__support/ctype_utils.h b/libc/src/__support/ctype_utils.h index f3f4b366d91d..f67398122443 100644 --- a/libc/src/__support/ctype_utils.h +++ b/libc/src/__support/ctype_utils.h @@ -36,6 +36,12 @@ static constexpr bool isspace(unsigned ch) { return ch == ' ' || (ch - '\t') < 5; } +static constexpr int tolower(int ch) { + if (isupper(ch)) + return ch + ('a' - 'A'); + return ch; +} + } // namespace internal } // namespace __llvm_libc diff --git a/libc/src/ctype/tolower.cpp b/libc/src/ctype/tolower.cpp index 8fbb5aaded48..2c4b851a615e 100644 --- a/libc/src/ctype/tolower.cpp +++ b/libc/src/ctype/tolower.cpp @@ -15,10 +15,6 @@ namespace __llvm_libc { // TODO: Currently restricted to default locale. // These should be extended using locale information. -LLVM_LIBC_FUNCTION(int, tolower, (int c)) { - if (internal::isupper(c)) - return c + ('a' - 'A'); - return c; -} +LLVM_LIBC_FUNCTION(int, tolower, (int c)) { return internal::tolower(c); } } // namespace __llvm_libc diff --git a/libc/src/string/CMakeLists.txt b/libc/src/string/CMakeLists.txt index cdce0bc69ec3..ec61735f4154 100644 --- a/libc/src/string/CMakeLists.txt +++ b/libc/src/string/CMakeLists.txt @@ -116,6 +116,17 @@ add_entrypoint_object( ) add_entrypoint_object( + strcasecmp + SRCS + strcasecmp.cpp + HDRS + strcasecmp.h + DEPENDS + .memory_utils.strcmp_implementation + libc.src.__support.ctype_utils +) + +add_entrypoint_object( strcoll SRCS strcoll.cpp @@ -233,6 +244,17 @@ add_entrypoint_object( ) add_entrypoint_object( + strncasecmp + SRCS + strncasecmp.cpp + HDRS + strncasecmp.h + DEPENDS + .memory_utils.strcmp_implementation + libc.src.__support.ctype_utils +) + +add_entrypoint_object( strncpy SRCS strncpy.cpp diff --git a/libc/src/string/strcasecmp.cpp b/libc/src/string/strcasecmp.cpp new file mode 100644 index 000000000000..d7a080aec949 --- /dev/null +++ b/libc/src/string/strcasecmp.cpp @@ -0,0 +1,25 @@ +//===-- Implementation of strcasecmp --------------------------------------===// +// +// 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/strcasecmp.h" + +#include "src/__support/common.h" +#include "src/__support/ctype_utils.h" +#include "src/string/memory_utils/strcmp_implementations.h" + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(int, strcasecmp, (const char *left, const char *right)) { + auto case_cmp = [](char a, char b) { + return __llvm_libc::internal::tolower(a) - + __llvm_libc::internal::tolower(b); + }; + return strcmp_implementation(left, right, case_cmp); +} + +} // namespace __llvm_libc diff --git a/libc/src/string/strcasecmp.h b/libc/src/string/strcasecmp.h new file mode 100644 index 000000000000..ce0a4e5b613c --- /dev/null +++ b/libc/src/string/strcasecmp.h @@ -0,0 +1,18 @@ +//===-- Implementation header for strcasecmp --------------------*- 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_STRCASECMP_H +#define LLVM_LIBC_SRC_STRING_STRCASECMP_H + +namespace __llvm_libc { + +int strcasecmp(const char *left, const char *right); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STRING_STRCASECMP_H diff --git a/libc/src/string/strncasecmp.cpp b/libc/src/string/strncasecmp.cpp new file mode 100644 index 000000000000..0fb2f81b17fe --- /dev/null +++ b/libc/src/string/strncasecmp.cpp @@ -0,0 +1,26 @@ +//===-- Implementation of strncasecmp -------------------------------------===// +// +// 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/strncasecmp.h" + +#include "src/__support/common.h" +#include "src/__support/ctype_utils.h" +#include "src/string/memory_utils/strcmp_implementations.h" + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(int, strncasecmp, + (const char *left, const char *right, size_t n)) { + auto case_cmp = [](char a, char b) { + return __llvm_libc::internal::tolower(a) - + __llvm_libc::internal::tolower(b); + }; + return strncmp_implementation(left, right, n, case_cmp); +} + +} // namespace __llvm_libc diff --git a/libc/src/string/strncasecmp.h b/libc/src/string/strncasecmp.h new file mode 100644 index 000000000000..5ef2dcd4cd12 --- /dev/null +++ b/libc/src/string/strncasecmp.h @@ -0,0 +1,20 @@ +//===-- Implementation header for strcasecmp --------------------*- 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_STRCASECMP_H +#define LLVM_LIBC_SRC_STRING_STRCASECMP_H + +#include <stddef.h> + +namespace __llvm_libc { + +int strncasecmp(const char *left, const char *right, size_t n); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STRING_STRCASECMP_H diff --git a/libc/test/src/string/CMakeLists.txt b/libc/test/src/string/CMakeLists.txt index b5de08b2fbb0..99dfabbd93a3 100644 --- a/libc/test/src/string/CMakeLists.txt +++ b/libc/test/src/string/CMakeLists.txt @@ -105,6 +105,16 @@ add_libc_unittest( ) add_libc_unittest( + strcasecmp_test + SUITE + libc_string_unittests + SRCS + strcasecmp_test.cpp + DEPENDS + libc.src.string.strcasecmp +) + +add_libc_unittest( strcoll_test SUITE libc_string_unittests @@ -219,6 +229,16 @@ add_libc_unittest( ) add_libc_unittest( + strncasecmp_test + SUITE + libc_string_unittests + SRCS + strncasecmp_test.cpp + DEPENDS + libc.src.string.strncasecmp +) + +add_libc_unittest( strncpy_test SUITE libc_string_unittests diff --git a/libc/test/src/string/strcasecmp_test.cpp b/libc/test/src/string/strcasecmp_test.cpp new file mode 100644 index 000000000000..a8200104d22c --- /dev/null +++ b/libc/test/src/string/strcasecmp_test.cpp @@ -0,0 +1,46 @@ +//===-- Unittests for strcasecmp ------------------------------------------===// +// +// 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/strcasecmp.h" +#include "utils/UnitTest/Test.h" + +TEST(LlvmLibcStrCaseCmpTest, EmptyStringsShouldReturnZero) { + const char *s1 = ""; + const char *s2 = ""; + int result = __llvm_libc::strcasecmp(s1, s2); + ASSERT_EQ(result, 0); + + // Verify operands reversed. + result = __llvm_libc::strcasecmp(s2, s1); + ASSERT_EQ(result, 0); +} + +TEST(LlvmLibcStrCaseCmpTest, EmptyStringShouldNotEqualNonEmptyString) { + const char *empty = ""; + const char *s2 = "abc"; + int result = __llvm_libc::strcasecmp(empty, s2); + // This should be '\0' - 'a' = -97 + ASSERT_LT(result, 0); + + // Similar case if empty string is second argument. + const char *s3 = "123"; + result = __llvm_libc::strcasecmp(s3, empty); + // This should be '1' - '\0' = 49 + ASSERT_GT(result, 0); +} + +TEST(LlvmLibcStrCaseCmpTest, Case) { + const char *s1 = "aB"; + const char *s2 = "ab"; + int result = __llvm_libc::strcasecmp(s1, s2); + ASSERT_EQ(result, 0); + + // Verify operands reversed. + result = __llvm_libc::strcasecmp(s2, s1); + ASSERT_EQ(result, 0); +} diff --git a/libc/test/src/string/strcmp_test.cpp b/libc/test/src/string/strcmp_test.cpp index f80cdfa3d44d..9f707dbf1581 100644 --- a/libc/test/src/string/strcmp_test.cpp +++ b/libc/test/src/string/strcmp_test.cpp @@ -95,3 +95,14 @@ TEST(LlvmLibcStrCmpTest, StringArgumentSwapChangesSign) { // 'a' - 'b' = -1. ASSERT_EQ(result, -1); } + +TEST(LlvmLibcStrCmpTest, Case) { + const char *s1 = "aB"; + const char *s2 = "ab"; + int result = __llvm_libc::strcmp(s1, s2); + ASSERT_LT(result, 0); + + // Verify operands reversed. + result = __llvm_libc::strcmp(s2, s1); + ASSERT_GT(result, 0); +} diff --git a/libc/test/src/string/strncasecmp_test.cpp b/libc/test/src/string/strncasecmp_test.cpp new file mode 100644 index 000000000000..0188c7fca74e --- /dev/null +++ b/libc/test/src/string/strncasecmp_test.cpp @@ -0,0 +1,48 @@ +//===-- Unittests for strncasecmp -----------------------------------------===// +// +// 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/strncasecmp.h" +#include "utils/UnitTest/Test.h" + +TEST(LlvmLibcStrNCaseCmpTest, + EmptyStringsShouldReturnZeroWithSufficientLength) { + const char *s1 = ""; + const char *s2 = ""; + int result = __llvm_libc::strncasecmp(s1, s2, 1); + ASSERT_EQ(result, 0); + + // Verify operands reversed. + result = __llvm_libc::strncasecmp(s2, s1, 1); + ASSERT_EQ(result, 0); +} + +TEST(LlvmLibcStrNCaseCmpTest, + EmptyStringShouldNotEqualNonEmptyStringWithSufficientLength) { + const char *empty = ""; + const char *s2 = "abc"; + int result = __llvm_libc::strncasecmp(empty, s2, 3); + // This should be '\0' - 'a' = -97 + ASSERT_LT(result, 0); + + // Similar case if empty string is second argument. + const char *s3 = "123"; + result = __llvm_libc::strncasecmp(s3, empty, 3); + // This should be '1' - '\0' = 49 + ASSERT_GT(result, 0); +} + +TEST(LlvmLibcStrNCaseCmpTest, Case) { + const char *s1 = "aB"; + const char *s2 = "ab"; + int result = __llvm_libc::strncasecmp(s1, s2, 2); + ASSERT_EQ(result, 0); + + // Verify operands reversed. + result = __llvm_libc::strncasecmp(s2, s1, 2); + ASSERT_EQ(result, 0); +} diff --git a/libc/test/src/string/strncmp_test.cpp b/libc/test/src/string/strncmp_test.cpp index 8855e0f59db0..52add6b516e8 100644 --- a/libc/test/src/string/strncmp_test.cpp +++ b/libc/test/src/string/strncmp_test.cpp @@ -156,3 +156,14 @@ TEST(LlvmLibcStrNCmpTest, StringComparisonEndsOnNullByteEvenWithLongerLength) { result = __llvm_libc::strncmp(s2, s1, 7); ASSERT_EQ(result, 0); } + +TEST(LlvmLibcStrNCmpTest, Case) { + const char *s1 = "aB"; + const char *s2 = "ab"; + int result = __llvm_libc::strncmp(s1, s2, 2); + ASSERT_LT(result, 0); + + // Verify operands reversed. + result = __llvm_libc::strncmp(s2, s1, 2); + ASSERT_GT(result, 0); +} |