forked from OSchip/llvm-project
[libc] Adds strrchr implementation.
Reviewed By: sivachandra Differential Revision: https://reviews.llvm.org/D84875
This commit is contained in:
parent
09746fbfb9
commit
e8a2af28af
|
@ -20,6 +20,7 @@ set(TARGET_LIBC_ENTRYPOINTS
|
|||
libc.src.string.strcpy
|
||||
libc.src.string.strlen
|
||||
libc.src.string.strnlen
|
||||
libc.src.string.strrchr
|
||||
libc.src.string.strstr
|
||||
)
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ set(TARGET_LIBC_ENTRYPOINTS
|
|||
libc.src.string.strcpy
|
||||
libc.src.string.strlen
|
||||
libc.src.string.strnlen
|
||||
libc.src.string.strrchr
|
||||
libc.src.string.strstr
|
||||
|
||||
# sys/mman.h entrypoints
|
||||
|
|
|
@ -86,6 +86,14 @@ add_entrypoint_object(
|
|||
memrchr.h
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
strrchr
|
||||
SRCS
|
||||
strrchr.cpp
|
||||
HDRS
|
||||
strrchr.h
|
||||
)
|
||||
|
||||
# Helper to define a function with multiple implementations
|
||||
# - Computes flags to satisfy required/rejected features and arch,
|
||||
# - Declares an entry point,
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
//===-- Implementation of strrchr------------------------------------------===//
|
||||
//
|
||||
// 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/strrchr.h"
|
||||
|
||||
#include "src/__support/common.h"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
char *LLVM_LIBC_ENTRYPOINT(strrchr)(const char *src, int c) {
|
||||
unsigned char *str =
|
||||
const_cast<unsigned char *>(reinterpret_cast<const unsigned char *>(src));
|
||||
const unsigned char ch = c;
|
||||
|
||||
unsigned char *last_occurrence = nullptr;
|
||||
do {
|
||||
if (*str == ch)
|
||||
last_occurrence = str;
|
||||
} while (*str++);
|
||||
return reinterpret_cast<char *>(last_occurrence);
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,18 @@
|
|||
//===-- Implementation header for strrchr -----------------------*- 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_STRRCHR_H
|
||||
#define LLVM_LIBC_SRC_STRING_STRRCHR_H
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
char *strrchr(const char *src, int c);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STRING_STRRCHR_H
|
|
@ -92,6 +92,16 @@ add_libc_unittest(
|
|||
libc.src.string.memrchr
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
strrchr_test
|
||||
SUITE
|
||||
libc_string_unittests
|
||||
SRCS
|
||||
strrchr_test.cpp
|
||||
DEPENDS
|
||||
libc.src.string.strrchr
|
||||
)
|
||||
|
||||
# Tests all implementations that can run on the host.
|
||||
function(add_libc_multi_impl_test name)
|
||||
get_property(fq_implementations GLOBAL PROPERTY ${name}_implementations)
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
//===-- Unittests for strrchr ---------------------------------------------===//
|
||||
//
|
||||
// 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/strrchr.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
TEST(StrRChrTest, FindsFirstCharacter) {
|
||||
const char *src = "abcde";
|
||||
const char *src_copy = src;
|
||||
|
||||
// Should return original string since 'a' is the first character.
|
||||
ASSERT_STREQ(__llvm_libc::strrchr(src, 'a'), "abcde");
|
||||
// Source string should not change.
|
||||
ASSERT_STREQ(src, src_copy);
|
||||
}
|
||||
|
||||
TEST(StrRChrTest, FindsMiddleCharacter) {
|
||||
const char *src = "abcde";
|
||||
const char *src_copy = src;
|
||||
|
||||
// Should return characters after (and including) 'c'.
|
||||
ASSERT_STREQ(__llvm_libc::strrchr(src, 'c'), "cde");
|
||||
// Source string should not change.
|
||||
ASSERT_STREQ(src, src_copy);
|
||||
}
|
||||
|
||||
TEST(StrRChrTest, FindsLastCharacterThatIsNotNullTerminator) {
|
||||
const char *src = "abcde";
|
||||
const char *src_copy = src;
|
||||
|
||||
// Should return 'e' and null-terminator.
|
||||
ASSERT_STREQ(__llvm_libc::strrchr(src, 'e'), "e");
|
||||
// Source string should not change.
|
||||
ASSERT_STREQ(src, src_copy);
|
||||
}
|
||||
|
||||
TEST(StrRChrTest, FindsNullTerminator) {
|
||||
const char *src = "abcde";
|
||||
const char *src_copy = src;
|
||||
|
||||
// Should return null terminator.
|
||||
ASSERT_STREQ(__llvm_libc::strrchr(src, '\0'), "");
|
||||
// Source string should not change.
|
||||
ASSERT_STREQ(src, src_copy);
|
||||
}
|
||||
|
||||
TEST(StrRChrTest, FindsLastNullTerminator) {
|
||||
const char src[5] = {'a', '\0', 'b', '\0', 'c'};
|
||||
// 'b' is behind a null terminator, so should not be found.
|
||||
ASSERT_STREQ(__llvm_libc::strrchr(src, 'b'), nullptr);
|
||||
// Same goes for 'c'.
|
||||
ASSERT_STREQ(__llvm_libc::strrchr(src, 'c'), nullptr);
|
||||
}
|
||||
|
||||
TEST(StrRChrTest, CharacterNotWithinStringShouldReturnNullptr) {
|
||||
// Since 'z' is not within the string, should return nullptr.
|
||||
ASSERT_STREQ(__llvm_libc::strrchr("123?", 'z'), nullptr);
|
||||
}
|
||||
|
||||
TEST(StrRChrTest, ShouldFindLastOfDuplicates) {
|
||||
// '1' is duplicated in the string, but it should find the last copy.
|
||||
ASSERT_STREQ(__llvm_libc::strrchr("abc1def1ghi", '1'), "1ghi");
|
||||
|
||||
const char *dups = "XXXXX";
|
||||
// Should return the last occurrence of 'X'.
|
||||
ASSERT_STREQ(__llvm_libc::strrchr(dups, 'X'), "X");
|
||||
}
|
||||
|
||||
TEST(StrRChrTest, EmptyStringShouldOnlyMatchNullTerminator) {
|
||||
// Null terminator should match.
|
||||
ASSERT_STREQ(__llvm_libc::strrchr("", '\0'), "");
|
||||
// All other characters should not match.
|
||||
ASSERT_STREQ(__llvm_libc::strrchr("", 'A'), nullptr);
|
||||
ASSERT_STREQ(__llvm_libc::strrchr("", '2'), nullptr);
|
||||
ASSERT_STREQ(__llvm_libc::strrchr("", '*'), nullptr);
|
||||
}
|
Loading…
Reference in New Issue