[libc] This adds the strcmp (string compare) implementation.

Reviewed-by: sivachandra
Differential Revision: https://reviews.llvm.org/D82134
This commit is contained in:
cgyurgyik 2020-06-19 16:05:26 -04:00
parent af4f2eb476
commit 05e1612c43
6 changed files with 159 additions and 0 deletions

View File

@ -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

View File

@ -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,

View File

@ -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<const unsigned char *>(left) -
*reinterpret_cast<const unsigned char *>(right);
}
} // namespace __llvm_libc

18
libc/src/string/strcmp.h Normal file
View File

@ -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

View File

@ -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)

View File

@ -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);
}