[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