[libc-commits] [libc] 631a6e0 - [libc][wchar] implement wcslen (#124150)
via libc-commits
libc-commits at lists.llvm.org
Thu Jan 23 13:33:09 PST 2025
Author: Nick Desaulniers
Date: 2025-01-23T13:33:04-08:00
New Revision: 631a6e0004e57ca85569b99ea411418627925697
URL: https://github.com/llvm/llvm-project/commit/631a6e0004e57ca85569b99ea411418627925697
DIFF: https://github.com/llvm/llvm-project/commit/631a6e0004e57ca85569b99ea411418627925697.diff
LOG: [libc][wchar] implement wcslen (#124150)
Update string_utils' string_length to work with char* or wchar_t*, so that it
may be reusable when implementing wmemchr, wcspbrk, wcsrchr, wcsstr.
Link: #121183
Link: #124027
Co-authored-by: Nick Desaulniers <ndesaulniers at google.com>
---------
Co-authored-by: Tristan Ross <tristan.ross at midstall.com>
Added:
libc/src/wchar/wcslen.cpp
libc/src/wchar/wcslen.h
libc/test/src/wchar/wcslen_test.cpp
Modified:
libc/config/gpu/amdgpu/entrypoints.txt
libc/config/gpu/nvptx/entrypoints.txt
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/riscv/entrypoints.txt
libc/config/linux/x86_64/entrypoints.txt
libc/include/wchar.yaml
libc/src/string/CMakeLists.txt
libc/src/string/string_utils.h
libc/src/wchar/CMakeLists.txt
libc/test/src/wchar/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/config/gpu/amdgpu/entrypoints.txt b/libc/config/gpu/amdgpu/entrypoints.txt
index 7a1982808dfeb7..756b2cdc7496ec 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -261,6 +261,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.time.nanosleep
# wchar.h entrypoints
+ libc.src.wchar.wcslen
libc.src.wchar.wctob
# locale.h entrypoints
diff --git a/libc/config/gpu/nvptx/entrypoints.txt b/libc/config/gpu/nvptx/entrypoints.txt
index 059dc9b20d6dd2..6b25dae158cc94 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -261,6 +261,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.time.nanosleep
# wchar.h entrypoints
+ libc.src.wchar.wcslen
libc.src.wchar.wctob
# locale.h entrypoints
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 6e5ecba6200a4b..09eb51a3f8fc62 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -350,6 +350,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.unistd.write
# wchar.h entrypoints
+ libc.src.wchar.wcslen
libc.src.wchar.wctob
# sys/uio.h entrypoints
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 36339126b1f22f..14a05a2f3fbf2a 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -346,6 +346,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.unistd.write
# wchar.h entrypoints
+ libc.src.wchar.wcslen
libc.src.wchar.wctob
)
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 6662175c530217..366e4d34294d15 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -349,8 +349,9 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.unistd.write
# wchar.h entrypoints
- libc.src.wchar.wctob
libc.src.wchar.btowc
+ libc.src.wchar.wcslen
+ libc.src.wchar.wctob
# sys/uio.h entrypoints
libc.src.sys.uio.writev
diff --git a/libc/include/wchar.yaml b/libc/include/wchar.yaml
index 159237c7b4ff7c..0ac9aa29f0a181 100644
--- a/libc/include/wchar.yaml
+++ b/libc/include/wchar.yaml
@@ -9,6 +9,12 @@ types:
enums: []
objects: []
functions:
+ - name: wcslen
+ standards:
+ - stdc
+ return_type: size_t
+ arguments:
+ - type: const wchar_t *
- name: wctob
standards:
- stdc
diff --git a/libc/src/string/CMakeLists.txt b/libc/src/string/CMakeLists.txt
index e3faa543e630cc..2c607bf8ea8953 100644
--- a/libc/src/string/CMakeLists.txt
+++ b/libc/src/string/CMakeLists.txt
@@ -17,9 +17,11 @@ add_header_library(
DEPENDS
.memory_utils.inline_bzero
.memory_utils.inline_memcpy
+ libc.hdr.types.size_t
libc.include.stdlib
- libc.src.__support.common
libc.src.__support.CPP.bitset
+ libc.src.__support.CPP.type_traits
+ libc.src.__support.common
${string_config_options}
)
diff --git a/libc/src/string/string_utils.h b/libc/src/string/string_utils.h
index fc617bd18e8f64..583d35014d3986 100644
--- a/libc/src/string/string_utils.h
+++ b/libc/src/string/string_utils.h
@@ -14,12 +14,13 @@
#ifndef LLVM_LIBC_SRC_STRING_STRING_UTILS_H
#define LLVM_LIBC_SRC_STRING_STRING_UTILS_H
+#include "hdr/types/size_t.h"
#include "src/__support/CPP/bitset.h"
+#include "src/__support/CPP/type_traits.h" // cpp::is_same_v
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
#include "src/string/memory_utils/inline_bzero.h"
#include "src/string/memory_utils/inline_memcpy.h"
-#include <stddef.h> // For size_t
namespace LIBC_NAMESPACE_DECL {
namespace internal {
@@ -79,24 +80,21 @@ LIBC_INLINE size_t string_length_wide_read(const char *src) {
return char_ptr - src;
}
-LIBC_INLINE size_t string_length_byte_read(const char *src) {
- size_t length;
- for (length = 0; *src; ++src, ++length)
- ;
- return length;
-}
-
// Returns the length of a string, denoted by the first occurrence
// of a null terminator.
-LIBC_INLINE size_t string_length(const char *src) {
+template <typename T> LIBC_INLINE size_t string_length(const T *src) {
#ifdef LIBC_COPT_STRING_UNSAFE_WIDE_READ
// Unsigned int is the default size for most processors, and on x86-64 it
// performs better than larger sizes when the src pointer can't be assumed to
// be aligned to a word boundary, so it's the size we use for reading the
// string a block at a time.
- return string_length_wide_read<unsigned int>(src);
+ if constexpr (cpp::is_same_v<T, char>)
+ return string_length_wide_read<unsigned int>(src);
#else
- return string_length_byte_read(src);
+ size_t length;
+ for (length = 0; *src; ++src, ++length)
+ ;
+ return length;
#endif
}
diff --git a/libc/src/wchar/CMakeLists.txt b/libc/src/wchar/CMakeLists.txt
index d4c98ea527a8f9..703db75b5b194b 100644
--- a/libc/src/wchar/CMakeLists.txt
+++ b/libc/src/wchar/CMakeLists.txt
@@ -1,3 +1,14 @@
+add_entrypoint_object(
+ wcslen
+ SRCS
+ wcslen.cpp
+ HDRS
+ wcslen.h
+ DEPENDS
+ libc.hdr.types.size_t
+ libc.hdr.types.wchar_t
+ libc.src.string.string_utils
+)
add_entrypoint_object(
wctob
diff --git a/libc/src/wchar/wcslen.cpp b/libc/src/wchar/wcslen.cpp
new file mode 100644
index 00000000000000..5889e27f9729eb
--- /dev/null
+++ b/libc/src/wchar/wcslen.cpp
@@ -0,0 +1,23 @@
+//===-- Implementation of wcslen ------------------------------------------===//
+//
+// 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/wchar/wcslen.h"
+
+#include "hdr/types/size_t.h"
+#include "hdr/types/wchar_t.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/string/string_utils.h" // string_length_trivial
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(size_t, wcslen, (const wchar_t *src)) {
+ return internal::string_length(src);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/wchar/wcslen.h b/libc/src/wchar/wcslen.h
new file mode 100644
index 00000000000000..8b2e7f50b007e9
--- /dev/null
+++ b/libc/src/wchar/wcslen.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for wcslen ----------------------------------===//
+//
+// 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_WCHAR_WCSLEN_H
+#define LLVM_LIBC_SRC_WCHAR_WCSLEN_H
+
+#include "hdr/types/size_t.h"
+#include "hdr/types/wchar_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+size_t wcslen(const wchar_t *src);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_WCHAR_WCSLEN_H
diff --git a/libc/test/src/wchar/CMakeLists.txt b/libc/test/src/wchar/CMakeLists.txt
index 3cc404b9c86fc5..d41e328fc9d90c 100644
--- a/libc/test/src/wchar/CMakeLists.txt
+++ b/libc/test/src/wchar/CMakeLists.txt
@@ -1,5 +1,17 @@
add_custom_target(libc_wchar_unittests)
+add_libc_test(
+ wcslen_test
+ SUITE
+ libc_wchar_unittests
+ SRCS
+ wcslen_test.cpp
+ DEPENDS
+ libc.hdr.types.size_t
+ libc.hdr.types.wchar_t
+ libc.src.wchar.wcslen
+)
+
add_libc_test(
btowc_test
SUITE
diff --git a/libc/test/src/wchar/wcslen_test.cpp b/libc/test/src/wchar/wcslen_test.cpp
new file mode 100644
index 00000000000000..9cf446564c07ed
--- /dev/null
+++ b/libc/test/src/wchar/wcslen_test.cpp
@@ -0,0 +1,20 @@
+//===-- Unittests for wcslen ----------------------------------------------===//
+//
+// 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 "hdr/types/size_t.h"
+#include "hdr/types/wchar_t.h"
+#include "src/wchar/wcslen.h"
+#include "test/UnitTest/Test.h"
+
+TEST(LlvmLibcWCSLenTest, EmptyString) {
+ ASSERT_EQ(size_t{0}, LIBC_NAMESPACE::wcslen(L""));
+}
+
+TEST(LlvmLibcWCSLenTest, AnyString) {
+ ASSERT_EQ(size_t{12}, LIBC_NAMESPACE::wcslen(L"Hello World!"));
+}
More information about the libc-commits
mailing list