This revision removes dependencies that exist between different string functions. This allows for the libc user to use a specific function X of this library without also depending on Y and Z.
Reviewed By: sivachandra
Differential Revision: https://reviews.llvm.org/D87421
strcat.h
DEPENDS
.strcpy
- .strlen
- libc.include.string
+ .string_utils
)
add_entrypoint_object(
strcpy.h
DEPENDS
.memcpy
- .strlen
- libc.include.string
+ .string_utils
)
add_entrypoint_object(
memchr.cpp
HDRS
memchr.h
+ DEPENDS
+ .string_utils
)
add_entrypoint_object(
HDRS
strnlen.h
DEPENDS
- .memchr
+ .string_utils
)
add_entrypoint_object(
//===----------------------------------------------------------------------===//
#include "src/string/memchr.h"
+#include "src/string/string_utils.h"
+
#include "src/__support/common.h"
#include <stddef.h>
// 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);
- const unsigned char ch = c;
- for (; n && *str != ch; --n, ++str)
- ;
- return n ? const_cast<unsigned char *>(str) : nullptr;
+ return internal::find_first_character(
+ reinterpret_cast<const unsigned char *>(src), c, n);
}
} // namespace __llvm_libc
#include "src/string/strcat.h"
#include "src/string/strcpy.h"
-#include "src/string/strlen.h"
+#include "src/string/string_utils.h"
#include "src/__support/common.h"
char *LLVM_LIBC_ENTRYPOINT(strcat)(char *__restrict dest,
const char *__restrict src) {
- __llvm_libc::strcpy(dest + __llvm_libc::strlen(dest), src);
+ __llvm_libc::strcpy(dest + internal::string_length(dest), src);
return dest;
}
//===----------------------------------------------------------------------===//
#include "src/string/strcpy.h"
-#include "src/string/strlen.h"
#include "src/string/memcpy.h"
+#include "src/string/string_utils.h"
#include "src/__support/common.h"
char *LLVM_LIBC_ENTRYPOINT(strcpy)(char *__restrict dest,
const char *__restrict src) {
return reinterpret_cast<char *>(
- __llvm_libc::memcpy(dest, src, __llvm_libc::strlen(src) + 1));
+ __llvm_libc::memcpy(dest, src, internal::string_length(src) + 1));
}
} // namespace __llvm_libc
namespace __llvm_libc {
namespace internal {
+// Returns the length of a string, denoted by the first occurrence
+// of a null terminator.
+static inline size_t string_length(const char *src) {
+ size_t length;
+ for (length = 0; *src; ++src, ++length)
+ ;
+ return length;
+}
+
+// Returns the first occurrence of 'ch' within the first 'n' characters of
+// 'src'. If 'ch' is not found, returns nullptr.
+static inline void *find_first_character(const unsigned char *src,
+ unsigned char ch, size_t n) {
+ for (; n && *src != ch; --n, ++src)
+ ;
+ return n ? const_cast<unsigned char *>(src) : nullptr;
+}
+
// Returns the maximum length span that contains only characters not found in
// 'segment'. If no characters are found, returns the length of 'src'.
static inline size_t complementary_span(const char *src, const char *segment) {
//===----------------------------------------------------------------------===//
#include "src/string/strlen.h"
+#include "src/string/string_utils.h"
#include "src/__support/common.h"
// TODO: investigate the performance of this function.
// There might be potential for compiler optimization.
size_t LLVM_LIBC_ENTRYPOINT(strlen)(const char *src) {
- const char *end = src;
- while (*end != '\0')
- ++end;
- return end - src;
+ return internal::string_length(src);
}
} // namespace __llvm_libc
//===----------------------------------------------------------------------===//
#include "src/string/strnlen.h"
+#include "src/string/string_utils.h"
#include "src/__support/common.h"
-#include "src/string/memchr.h"
#include <stddef.h>
namespace __llvm_libc {
size_t LLVM_LIBC_ENTRYPOINT(strnlen)(const char *src, size_t n) {
- const char *temp =
- reinterpret_cast<char *>(__llvm_libc::memchr(src, '\0', n));
- return temp ? temp - src : n;
+ const void *temp = internal::find_first_character(
+ reinterpret_cast<const unsigned char *>(src), '\0', n);
+ return temp ? reinterpret_cast<const char *>(temp) - src : n;
}
} // namespace __llvm_libc