diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -21,6 +21,7 @@ # string.h entrypoints libc.src.string.bzero libc.src.string.memchr + libc.src.string.memcmp libc.src.string.memcpy libc.src.string.memset libc.src.string.memrchr diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -38,6 +38,7 @@ # string.h entrypoints libc.src.string.bzero libc.src.string.memchr + libc.src.string.memcmp libc.src.string.memcpy libc.src.string.memrchr libc.src.string.memset 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 @@ -58,6 +58,14 @@ .string_utils ) +add_entrypoint_object( + memcmp + SRCS + memcmp.cpp + HDRS + memcmp.h +) + add_entrypoint_object( strchr SRCS diff --git a/libc/src/string/memcmp.h b/libc/src/string/memcmp.h new file mode 100644 --- /dev/null +++ b/libc/src/string/memcmp.h @@ -0,0 +1,20 @@ +//===-- Implementation header for memcmp ------------------------*- 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_MEMCMP_H +#define LLVM_LIBC_SRC_STRING_MEMCMP_H + +#include // size_t + +namespace __llvm_libc { + +int memcmp(const void *lhs, const void *rhs, size_t count); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STRING_MEMCMP_H diff --git a/libc/src/string/memcmp.cpp b/libc/src/string/memcmp.cpp new file mode 100644 --- /dev/null +++ b/libc/src/string/memcmp.cpp @@ -0,0 +1,27 @@ +//===-- Implementation of memcmp ------------------------------------------===// +// +// 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/memcmp.h" +#include "src/__support/common.h" +#include // size_t + +namespace __llvm_libc { + +// TODO: It is a simple implementation, an optimized version is preparing. +int LLVM_LIBC_ENTRYPOINT(memcmp)(const void *lhs, const void *rhs, + size_t count) { + const unsigned char *_lhs = reinterpret_cast(lhs); + const unsigned char *_rhs = reinterpret_cast(rhs); + for (size_t i = 0; i < count; ++i) + if (_lhs[i] != _rhs[i]) + return _lhs[i] - _rhs[i]; + // count is 0 or _lhs and _rhs are the same. + return 0; +} + +} // namespace __llvm_libc diff --git a/libc/test/src/string/CMakeLists.txt b/libc/test/src/string/CMakeLists.txt --- a/libc/test/src/string/CMakeLists.txt +++ b/libc/test/src/string/CMakeLists.txt @@ -52,6 +52,16 @@ libc.src.string.memchr ) +add_libc_unittest( + memcmp_test + SUITE + libc_string_unittests + SRCS + memcmp_test.cpp + DEPENDS + libc.src.string.memcmp +) + add_libc_unittest( strchr_test SUITE diff --git a/libc/test/src/string/memcmp_test.cpp b/libc/test/src/string/memcmp_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/string/memcmp_test.cpp @@ -0,0 +1,34 @@ +//===-- Unittests for memcmp ----------------------------------------------===// +// +// 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/memcmp.h" +#include "utils/UnitTest/Test.h" + +TEST(MemcmpTest, CmpZeroByte) { + const char *lhs = "ab"; + const char *rhs = "bc"; + EXPECT_EQ(__llvm_libc::memcmp(lhs, rhs, 0), 0); +} + +TEST(MemcmpTest, LhsRhsAreTheSame) { + const char *lhs = "ab"; + const char *rhs = "ab"; + EXPECT_EQ(__llvm_libc::memcmp(lhs, rhs, 2), 0); +} + +TEST(MemcmpTest, LhsBeforeRhsLexically) { + const char *lhs = "ab"; + const char *rhs = "ac"; + EXPECT_EQ(__llvm_libc::memcmp(lhs, rhs, 2), -1); +} + +TEST(MemcmpTest, LhsAfterRhsLexically) { + const char *lhs = "ac"; + const char *rhs = "ab"; + EXPECT_EQ(__llvm_libc::memcmp(lhs, rhs, 2), 1); +}