mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 23:51:56 +00:00
[libc] Add strchr implementation. Fixes bug in memchr.
Summary: [libc] Adds strchr implementation with unit tests. Fixes signed character bug in memchr. Reviewers: sivachandra, PaulkaToast Reviewed By: sivachandra Subscribers: mgorny, tschuett, ecnelises, libc-commits Tags: #libc-project Differential Revision: https://reviews.llvm.org/D83353
This commit is contained in:
parent
90b1a710ae
commit
a4f0c58c6e
@ -10,6 +10,7 @@ set(TARGET_LIBC_ENTRYPOINTS
|
||||
libc.src.string.strcat
|
||||
libc.src.string.strlen
|
||||
libc.src.string.memchr
|
||||
libc.src.string.strchr
|
||||
)
|
||||
|
||||
set(TARGET_LIBM_ENTRYPOINTS
|
||||
|
@ -28,6 +28,7 @@ set(TARGET_LIBC_ENTRYPOINTS
|
||||
libc.src.string.strlen
|
||||
libc.src.string.strcmp
|
||||
libc.src.string.memchr
|
||||
libc.src.string.strchr
|
||||
|
||||
# sys/mman.h entrypoints
|
||||
libc.src.sys.mman.mmap
|
||||
|
@ -52,6 +52,15 @@ add_entrypoint_object(
|
||||
memchr.h
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
strchr
|
||||
SRCS
|
||||
strchr.cpp
|
||||
HDRS
|
||||
strchr.h
|
||||
DEPENDS
|
||||
.strlen
|
||||
)
|
||||
|
||||
# Helper to define a function with multiple implementations
|
||||
# - Computes flags to satisfy required/rejected features and arch,
|
||||
|
@ -15,7 +15,8 @@ namespace __llvm_libc {
|
||||
// TODO: Look at performance benefits of comparing words.
|
||||
void *LLVM_LIBC_ENTRYPOINT(memchr)(const void *src, int c, size_t n) {
|
||||
const unsigned char *str = reinterpret_cast<const unsigned char *>(src);
|
||||
for (; n && *str != c; --n, ++str)
|
||||
const unsigned char ch = c;
|
||||
for (; n && *str != ch; --n, ++str)
|
||||
;
|
||||
return n ? const_cast<unsigned char *>(str) : nullptr;
|
||||
}
|
||||
|
26
libc/src/string/strchr.cpp
Normal file
26
libc/src/string/strchr.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
//===-- Implementation of strchr ------------------------------------------===//
|
||||
//
|
||||
// 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/strchr.h"
|
||||
#include "src/string/strlen.h"
|
||||
|
||||
#include "src/__support/common.h"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
// TODO: Look at performance benefits of comparing words.
|
||||
char *LLVM_LIBC_ENTRYPOINT(strchr)(const char *src, int c) {
|
||||
unsigned char *str =
|
||||
const_cast<unsigned char *>(reinterpret_cast<const unsigned char *>(src));
|
||||
const unsigned char ch = c;
|
||||
for (; *str && *str != ch; ++str)
|
||||
;
|
||||
return *str == ch ? reinterpret_cast<char *>(str) : nullptr;
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
18
libc/src/string/strchr.h
Normal file
18
libc/src/string/strchr.h
Normal file
@ -0,0 +1,18 @@
|
||||
//===-- Implementation header for strchr ------------------------*- 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_STRCHR_H
|
||||
#define LLVM_LIBC_SRC_STRING_STRCHR_H
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
char *strchr(const char *src, int c);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STRING_STRCHR_H
|
@ -52,6 +52,16 @@ add_libc_unittest(
|
||||
libc.src.string.memchr
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
strchr_test
|
||||
SUITE
|
||||
libc_string_unittests
|
||||
SRCS
|
||||
strchr_test.cpp
|
||||
DEPENDS
|
||||
libc.src.string.strchr
|
||||
)
|
||||
|
||||
# Tests all implementations that can run on the host.
|
||||
function(add_libc_multi_impl_test name)
|
||||
get_property(fq_implementations GLOBAL PROPERTY ${name}_implementations)
|
||||
|
@ -111,3 +111,12 @@ TEST(MemChrTest, SingleRepeatedCharacterShouldReturnFirst) {
|
||||
// Should return original string since X is first character.
|
||||
ASSERT_STREQ(call_memchr(dups, 'X', size), dups);
|
||||
}
|
||||
|
||||
TEST(MemChrTest, SignedCharacterFound) {
|
||||
char c = -1;
|
||||
const size_t size = 1;
|
||||
char src[size] = {c};
|
||||
const char *actual = call_memchr(src, c, size);
|
||||
// Should find the first character 'c'.
|
||||
ASSERT_EQ(actual[0], c);
|
||||
}
|
||||
|
87
libc/test/src/string/strchr_test.cpp
Normal file
87
libc/test/src/string/strchr_test.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
//===-- Unittests for strchr ----------------------------------------------===//
|
||||
//
|
||||
// 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/strchr.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
TEST(StrChrTest, FindsFirstCharacter) {
|
||||
const char *src = "abcde";
|
||||
const char *src_copy = src;
|
||||
|
||||
// Should return original string since 'a' is the first character.
|
||||
ASSERT_STREQ(__llvm_libc::strchr(src, 'a'), "abcde");
|
||||
// Source string should not change.
|
||||
ASSERT_STREQ(src, src_copy);
|
||||
}
|
||||
|
||||
TEST(StrChrTest, FindsMiddleCharacter) {
|
||||
const char *src = "abcde";
|
||||
const char *src_copy = src;
|
||||
|
||||
// Should return characters after (and including) 'c'.
|
||||
ASSERT_STREQ(__llvm_libc::strchr(src, 'c'), "cde");
|
||||
// Source string should not change.
|
||||
ASSERT_STREQ(src, src_copy);
|
||||
}
|
||||
|
||||
TEST(StrChrTest, FindsLastCharacterThatIsNotNullTerminator) {
|
||||
const char *src = "abcde";
|
||||
const char *src_copy = src;
|
||||
|
||||
// Should return 'e' and null-terminator.
|
||||
ASSERT_STREQ(__llvm_libc::strchr(src, 'e'), "e");
|
||||
// Source string should not change.
|
||||
ASSERT_STREQ(src, src_copy);
|
||||
}
|
||||
|
||||
TEST(StrChrTest, FindsNullTerminator) {
|
||||
const char *src = "abcde";
|
||||
const char *src_copy = src;
|
||||
|
||||
// Should return null terminator.
|
||||
ASSERT_STREQ(__llvm_libc::strchr(src, '\0'), "");
|
||||
// Source string should not change.
|
||||
ASSERT_STREQ(src, src_copy);
|
||||
}
|
||||
|
||||
TEST(StrChrTest, CharacterNotWithinStringShouldReturnNullptr) {
|
||||
// Since 'z' is not within the string, should return nullptr.
|
||||
ASSERT_STREQ(__llvm_libc::strchr("123?", 'z'), nullptr);
|
||||
}
|
||||
|
||||
TEST(StrChrTest, TheSourceShouldNotChange) {
|
||||
const char *src = "abcde";
|
||||
const char *src_copy = src;
|
||||
// When the character is found, the source string should not change.
|
||||
__llvm_libc::strchr(src, 'd');
|
||||
ASSERT_STREQ(src, src_copy);
|
||||
// Same case for when the character is not found.
|
||||
__llvm_libc::strchr(src, 'z');
|
||||
ASSERT_STREQ(src, src_copy);
|
||||
// Same case for when looking for nullptr.
|
||||
__llvm_libc::strchr(src, '\0');
|
||||
ASSERT_STREQ(src, src_copy);
|
||||
}
|
||||
|
||||
TEST(StrChrTest, ShouldFindFirstOfDuplicates) {
|
||||
// '1' is duplicated in the string, but it should find the first copy.
|
||||
ASSERT_STREQ(__llvm_libc::strchr("abc1def1ghi", '1'), "1def1ghi");
|
||||
|
||||
const char *dups = "XXXXX";
|
||||
// Should return original string since 'X' is the first character.
|
||||
ASSERT_STREQ(__llvm_libc::strchr(dups, 'X'), dups);
|
||||
}
|
||||
|
||||
TEST(StrChrTest, EmptyStringShouldOnlyMatchNullTerminator) {
|
||||
// Null terminator should match.
|
||||
ASSERT_STREQ(__llvm_libc::strchr("", '\0'), "");
|
||||
// All other characters should not match.
|
||||
ASSERT_STREQ(__llvm_libc::strchr("", 'Z'), nullptr);
|
||||
ASSERT_STREQ(__llvm_libc::strchr("", '3'), nullptr);
|
||||
ASSERT_STREQ(__llvm_libc::strchr("", '*'), nullptr);
|
||||
}
|
Loading…
Reference in New Issue
Block a user