diff --git a/libc/src/__support/CPP/functional.h b/libc/src/__support/CPP/functional.h --- a/libc/src/__support/CPP/functional.h +++ b/libc/src/__support/CPP/functional.h @@ -24,6 +24,10 @@ constexpr R operator()(Args... params) { return func(params...); } }; +template struct minus { + constexpr T operator()(const T &lhs, const T &rhs) const { return lhs - rhs; } +}; + } // namespace cpp } // namespace __llvm_libc diff --git a/libc/src/string/CMakeLists.txt b/libc/src/string/CMakeLists.txt --- a/libc/src/string/CMakeLists.txt +++ b/libc/src/string/CMakeLists.txt @@ -111,6 +111,9 @@ strcmp.cpp HDRS strcmp.h + DEPENDS + .memory_utils.strcmp_implementation + libc.src.__support.CPP.functional ) add_entrypoint_object( @@ -226,6 +229,9 @@ strncmp.cpp HDRS strncmp.h + DEPENDS + .memory_utils.strcmp_implementation + libc.src.__support.CPP.functional ) add_entrypoint_object( diff --git a/libc/src/string/memory_utils/CMakeLists.txt b/libc/src/string/memory_utils/CMakeLists.txt --- a/libc/src/string/memory_utils/CMakeLists.txt +++ b/libc/src/string/memory_utils/CMakeLists.txt @@ -60,3 +60,9 @@ DEPS .memset_implementation ) + +add_header_library( + strcmp_implementation + HDRS + strcmp_implementations.h +) diff --git a/libc/src/string/memory_utils/strcmp_implementations.h b/libc/src/string/memory_utils/strcmp_implementations.h new file mode 100644 --- /dev/null +++ b/libc/src/string/memory_utils/strcmp_implementations.h @@ -0,0 +1,44 @@ +//===-- str{,case}cmp implementation ----------------------------*- 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_MEMORY_UTILS_STRCMP_IMPLEMENTATIONS_H +#define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_STRCMP_IMPLEMENTATIONS_H + +#include + +namespace __llvm_libc { + +template +constexpr static int strcmp_implementation(const char *left, const char *right, + Comp &&comp) { + // TODO: Look at benefits for comparing words at a time. + for (; *left && !comp(*left, *right); ++left, ++right) + ; + return comp(*reinterpret_cast(left), + *reinterpret_cast(right)); +} + +template +constexpr static int strncmp_implementation(const char *left, const char *right, + size_t n, Comp &&comp) { + if (n == 0) + return 0; + + // TODO: Look at benefits for comparing words at a time. + for (; n > 1; --n, ++left, ++right) { + char lc = *left; + if (!comp(lc, '\0') || comp(lc, *right)) + break; + } + return comp(*reinterpret_cast(left), + *reinterpret_cast(right)); +} + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STRING_MEMORY_UTILS_STRCMP_IMPLEMENTATIONS_H diff --git a/libc/src/string/strcmp.cpp b/libc/src/string/strcmp.cpp --- a/libc/src/string/strcmp.cpp +++ b/libc/src/string/strcmp.cpp @@ -8,16 +8,14 @@ #include "src/string/strcmp.h" +#include "src/__support/CPP/functional.h" #include "src/__support/common.h" +#include "src/string/memory_utils/strcmp_implementations.h" namespace __llvm_libc { -// TODO: Look at benefits for comparing words at a time. LLVM_LIBC_FUNCTION(int, strcmp, (const char *left, const char *right)) { - for (; *left && *left == *right; ++left, ++right) - ; - return *reinterpret_cast(left) - - *reinterpret_cast(right); + return strcmp_implementation(left, right, cpp::minus{}); } } // namespace __llvm_libc diff --git a/libc/src/string/strncmp.cpp b/libc/src/string/strncmp.cpp --- a/libc/src/string/strncmp.cpp +++ b/libc/src/string/strncmp.cpp @@ -8,25 +8,17 @@ #include "src/string/strncmp.h" +#include "src/__support/CPP/functional.h" #include "src/__support/common.h" +#include "src/string/memory_utils/strcmp_implementations.h" + #include namespace __llvm_libc { -// TODO: Look at benefits for comparing words at a time. LLVM_LIBC_FUNCTION(int, strncmp, (const char *left, const char *right, size_t n)) { - - if (n == 0) - return 0; - - for (; n > 1; --n, ++left, ++right) { - char lc = *left; - if (lc == '\0' || lc != *right) - break; - } - return *reinterpret_cast(left) - - *reinterpret_cast(right); + return strncmp_implementation(left, right, n, cpp::minus{}); } } // namespace __llvm_libc diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -1089,6 +1089,7 @@ "src/string/memory_utils/memcpy_implementations.h", "src/string/memory_utils/memmove_implementations.h", "src/string/memory_utils/memset_implementations.h", + "src/string/memory_utils/strcmp_implementations.h", ], deps = [ ":__support_common", @@ -1270,6 +1271,8 @@ hdrs = ["src/string/strcmp.h"], deps = [ ":__support_common", + ":__support_cpp_functional", + ":string_memory_utils", ":string_utils", ], )