[libc-commits] [libc] [libc] Implement wcs to mbs family of functions (PR #149421)
via libc-commits
libc-commits at lists.llvm.org
Fri Jul 18 08:38:40 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: Uzair Nawaz (uzairnawaz)
<details>
<summary>Changes</summary>
Implemented internal wcs to mbs internal function + tests
Impelemented wcs to mbs public functions
---
Patch is 35.83 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/149421.diff
18 Files Affected:
- (modified) libc/config/linux/x86_64/entrypoints.txt (+3)
- (modified) libc/include/wchar.yaml (+28)
- (modified) libc/src/__support/wchar/CMakeLists.txt (+19)
- (added) libc/src/__support/wchar/wcsnrtombs.cpp (+56)
- (added) libc/src/__support/wchar/wcsnrtombs.h (+27)
- (modified) libc/src/wchar/CMakeLists.txt (+41)
- (added) libc/src/wchar/wcsnrtombs.cpp (+39)
- (added) libc/src/wchar/wcsnrtombs.h (+23)
- (added) libc/src/wchar/wcsrtombs.cpp (+39)
- (added) libc/src/wchar/wcsrtombs.h (+23)
- (added) libc/src/wchar/wcstombs.cpp (+37)
- (added) libc/src/wchar/wcstombs.h (+22)
- (modified) libc/test/src/__support/wchar/CMakeLists.txt (+17)
- (added) libc/test/src/__support/wchar/wcsnrtombs_test.cpp (+190)
- (modified) libc/test/src/wchar/CMakeLists.txt (+40)
- (added) libc/test/src/wchar/wcsnrtombs_test.cpp (+156)
- (added) libc/test/src/wchar/wcsrtombs_test.cpp (+113)
- (added) libc/test/src/wchar/wcstombs_test.cpp (+85)
``````````diff
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 9223911f04a93..a067e73e80d13 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1263,6 +1263,9 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.wchar.mbtowc
libc.src.wchar.wcrtomb
libc.src.wchar.wctomb
+ libc.src.wchar.wcstombs
+ libc.src.wchar.wcsrtombs
+ libc.src.wchar.wcsnrtombs
)
endif()
diff --git a/libc/include/wchar.yaml b/libc/include/wchar.yaml
index 123d3440aeec3..8c72e1963a425 100644
--- a/libc/include/wchar.yaml
+++ b/libc/include/wchar.yaml
@@ -274,3 +274,31 @@ functions:
- type: const wchar_t *__restrict
- type: wchar_t **__restrict
- type: int
+ - name: wcstombs
+ standards:
+ - stdc
+ return_type: size_t
+ arguments:
+ - type: char *__restrict
+ - type: const wchar_t *__restrict
+ - type: size_t
+ - name: wcsrtombs
+ standards:
+ - stdc
+ return_type: size_t
+ arguments:
+ - type: char *__restrict
+ - type: const wchar_t **__restrict
+ - type: size_t
+ - type: mbstate_t
+ - name: wcsnrtombs
+ standards:
+ - stdc
+ return_type: size_t
+ arguments:
+ - type: char *__restrict
+ - type: const wchar_t **__restrict
+ - type: size_t
+ - type: size_t
+ - type: mbstate_t
+
diff --git a/libc/src/__support/wchar/CMakeLists.txt b/libc/src/__support/wchar/CMakeLists.txt
index 802441d37fe92..b9efe5888d955 100644
--- a/libc/src/__support/wchar/CMakeLists.txt
+++ b/libc/src/__support/wchar/CMakeLists.txt
@@ -68,3 +68,22 @@ add_object_library(
.character_converter
.mbstate
)
+
+add_object_library(
+ wcsnrtombs
+ HDRS
+ wcsnrtombs.h
+ SRCS
+ wcsnrtombs.cpp
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.types.char8_t
+ libc.hdr.types.char32_t
+ libc.hdr.types.size_t
+ libc.hdr.types.wchar_t
+ libc.src.__support.error_or
+ libc.src.__support.common
+ .string_converter
+ .character_converter
+ .mbstate
+)
diff --git a/libc/src/__support/wchar/wcsnrtombs.cpp b/libc/src/__support/wchar/wcsnrtombs.cpp
new file mode 100644
index 0000000000000..b7add66214b5a
--- /dev/null
+++ b/libc/src/__support/wchar/wcsnrtombs.cpp
@@ -0,0 +1,56 @@
+//===-- Implementation of wcsnrtombs --------------------------------------===//
+//
+// 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/__support/wchar/wcsnrtombs.h"
+
+#include "hdr/types/char32_t.h"
+#include "hdr/types/size_t.h"
+#include "hdr/types/wchar_t.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/wchar/mbstate.h"
+#include "src/__support/wchar/string_converter.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace internal {
+
+ErrorOr<size_t> wcsnrtombs(char *__restrict s, const wchar_t **__restrict pwcs,
+ size_t nwc, size_t len, mbstate *ps) {
+ CharacterConverter cr(ps);
+ if (!cr.isValidState())
+ return Error(EINVAL);
+
+ if (s == nullptr)
+ len = SIZE_MAX;
+
+ StringConverter<char32_t> str_conv(reinterpret_cast<const char32_t *>(*pwcs),
+ ps, len, nwc);
+ size_t dst_idx = 0;
+ ErrorOr<char8_t> converted = str_conv.popUTF8();
+ while (converted.has_value()) {
+ if (s != nullptr)
+ s[dst_idx] = converted.value();
+
+ if (converted.value() == '\0') {
+ *pwcs = nullptr;
+ return dst_idx;
+ }
+
+ dst_idx++;
+ converted = str_conv.popUTF8();
+ }
+
+ *pwcs += str_conv.getSourceIndex();
+ if (converted.error() == -1) // if we hit conversion limit
+ return dst_idx;
+
+ return Error(converted.error());
+}
+} // namespace internal
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/wchar/wcsnrtombs.h b/libc/src/__support/wchar/wcsnrtombs.h
new file mode 100644
index 0000000000000..f5ba910940692
--- /dev/null
+++ b/libc/src/__support/wchar/wcsnrtombs.h
@@ -0,0 +1,27 @@
+//===-- Implementation header for wcsnrtombs ------------------------------===//
+//
+// 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__SUPPORT_WCHAR_WCSNRTOMBS_H
+#define LLVM_LIBC_SRC__SUPPORT_WCHAR_WCSNRTOMBS_H
+
+#include "hdr/types/size_t.h"
+#include "hdr/types/wchar_t.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/wchar/mbstate.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace internal {
+
+ErrorOr<size_t> wcsnrtombs(char *__restrict s, const wchar_t **__restrict pwcs,
+ size_t nwc, size_t len, mbstate *ps);
+
+} // namespace internal
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC__SUPPORT_WCHAR_WCSNRTOMBS_H
diff --git a/libc/src/wchar/CMakeLists.txt b/libc/src/wchar/CMakeLists.txt
index 7ace1a6ca66ba..05c91d459bb95 100644
--- a/libc/src/wchar/CMakeLists.txt
+++ b/libc/src/wchar/CMakeLists.txt
@@ -159,6 +159,47 @@ add_entrypoint_object(
libc.src.__support.wchar.mbstate
)
+add_entrypoint_object(
+ wcstombs
+ SRCS
+ wcstombs.cpp
+ HDRS
+ wcstombs.h
+ DEPENDS
+ libc.hdr.types.wchar_t
+ libc.src.__support.wchar.mbstate
+ libc.src.__support.wchar.wcsnrtombs
+ libc.src.__support.libc_errno
+)
+
+add_entrypoint_object(
+ wcsrtombs
+ SRCS
+ wcsrtombs.cpp
+ HDRS
+ wcsrtombs.h
+ DEPENDS
+ libc.hdr.types.wchar_t
+ libc.hdr.types.mbstate_t
+ libc.src.__support.wchar.mbstate
+ libc.src.__support.wchar.wcsnrtombs
+ libc.src.__support.libc_errno
+)
+
+add_entrypoint_object(
+ wcsnrtombs
+ SRCS
+ wcsnrtombs.cpp
+ HDRS
+ wcsnrtombs.h
+ DEPENDS
+ libc.hdr.types.wchar_t
+ libc.hdr.types.mbstate_t
+ libc.src.__support.wchar.mbstate
+ libc.src.__support.wchar.wcsnrtombs
+ libc.src.__support.libc_errno
+)
+
add_entrypoint_object(
wmemset
SRCS
diff --git a/libc/src/wchar/wcsnrtombs.cpp b/libc/src/wchar/wcsnrtombs.cpp
new file mode 100644
index 0000000000000..fd4724150e927
--- /dev/null
+++ b/libc/src/wchar/wcsnrtombs.cpp
@@ -0,0 +1,39 @@
+//===-- Implementation of wcsnrtombs --------------------------------------===//
+//
+// 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/wcsnrtombs.h"
+
+#include "hdr/types/char32_t.h"
+#include "hdr/types/mbstate_t.h"
+#include "hdr/types/size_t.h"
+#include "hdr/types/wchar_t.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/wchar/mbstate.h"
+#include "src/__support/wchar/wcsnrtombs.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(size_t, wcsnrtombs,
+ (char *__restrict s, const wchar_t **__restrict pwcs,
+ size_t nwc, size_t len, mbstate_t *ps)) {
+ static internal::mbstate internal_mbstate;
+ auto result = internal::wcsnrtombs(
+ s, pwcs, nwc, len,
+ ps == nullptr ? &internal_mbstate
+ : reinterpret_cast<internal::mbstate *>(ps));
+ if (!result.has_value()) {
+ libc_errno = result.error();
+ return -1;
+ }
+
+ return result.value();
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/wchar/wcsnrtombs.h b/libc/src/wchar/wcsnrtombs.h
new file mode 100644
index 0000000000000..793d383660f1b
--- /dev/null
+++ b/libc/src/wchar/wcsnrtombs.h
@@ -0,0 +1,23 @@
+//===-- Implementation header for wcsnrtombs -------------------------------===//
+//
+// 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_WCSNRTOMBS_H
+#define LLVM_LIBC_SRC_WCHAR_WCSNRTOMBS_H
+
+#include "hdr/types/mbstate_t.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 wcsnrtombs(char *__restrict s, const wchar_t **__restrict pwcs, size_t nwc, size_t len, mbstate_t* ps);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_WCHAR_WCSNRTOMBS_H
diff --git a/libc/src/wchar/wcsrtombs.cpp b/libc/src/wchar/wcsrtombs.cpp
new file mode 100644
index 0000000000000..b4632a4a436ba
--- /dev/null
+++ b/libc/src/wchar/wcsrtombs.cpp
@@ -0,0 +1,39 @@
+//===-- Implementation of wcsrtombs ---------------------------------------===//
+//
+// 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/wcsrtombs.h"
+
+#include "hdr/types/char32_t.h"
+#include "hdr/types/mbstate_t.h"
+#include "hdr/types/size_t.h"
+#include "hdr/types/wchar_t.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/wchar/mbstate.h"
+#include "src/__support/wchar/wcsnrtombs.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(size_t, wcsrtombs,
+ (char *__restrict s, const wchar_t **__restrict pwcs,
+ size_t n, mbstate_t *ps)) {
+ static internal::mbstate internal_mbstate;
+ auto result = internal::wcsnrtombs(
+ s, pwcs, SIZE_MAX, n,
+ ps == nullptr ? &internal_mbstate
+ : reinterpret_cast<internal::mbstate *>(ps));
+ if (!result.has_value()) {
+ libc_errno = result.error();
+ return -1;
+ }
+
+ return result.value();
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/wchar/wcsrtombs.h b/libc/src/wchar/wcsrtombs.h
new file mode 100644
index 0000000000000..af69fccdb296a
--- /dev/null
+++ b/libc/src/wchar/wcsrtombs.h
@@ -0,0 +1,23 @@
+//===-- Implementation header for wcsrtombs --------------------------------===//
+//
+// 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_WCSRTOMBS_H
+#define LLVM_LIBC_SRC_WCHAR_WCSRTOMBS_H
+
+#include "hdr/types/mbstate_t.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 wcsrtombs(char *__restrict s, const wchar_t **__restrict pwcs, size_t n, mbstate_t* ps);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_WCHAR_WCSRTOMBS_H
diff --git a/libc/src/wchar/wcstombs.cpp b/libc/src/wchar/wcstombs.cpp
new file mode 100644
index 0000000000000..28e2425d645e7
--- /dev/null
+++ b/libc/src/wchar/wcstombs.cpp
@@ -0,0 +1,37 @@
+//===-- Implementation of wcstombs ----------------------------------------===//
+//
+// 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/wcstombs.h"
+
+#include "hdr/types/char32_t.h"
+#include "hdr/types/size_t.h"
+#include "hdr/types/wchar_t.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/wchar/mbstate.h"
+#include "src/__support/wchar/wcsnrtombs.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(size_t, wcstombs,
+ (char *__restrict s, const wchar_t *__restrict wcs,
+ size_t n)) {
+ static internal::mbstate internal_mbstate;
+ const wchar_t *wcs_ptr_copy = wcs;
+ auto result =
+ internal::wcsnrtombs(s, &wcs_ptr_copy, SIZE_MAX, n, &internal_mbstate);
+ if (!result.has_value()) {
+ libc_errno = result.error();
+ return -1;
+ }
+
+ return result.value();
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/wchar/wcstombs.h b/libc/src/wchar/wcstombs.h
new file mode 100644
index 0000000000000..cd0008a168d90
--- /dev/null
+++ b/libc/src/wchar/wcstombs.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for wcstombs --------------------------------===//
+//
+// 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_WCSTOMBS_H
+#define LLVM_LIBC_SRC_WCHAR_WCSTOMBS_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 wcstombs(char *__restrict s, const wchar_t *__restrict pwcs, size_t n);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_WCHAR_WCSTOMBS_H
diff --git a/libc/test/src/__support/wchar/CMakeLists.txt b/libc/test/src/__support/wchar/CMakeLists.txt
index f0727451736f9..c112c83dbe9af 100644
--- a/libc/test/src/__support/wchar/CMakeLists.txt
+++ b/libc/test/src/__support/wchar/CMakeLists.txt
@@ -34,3 +34,20 @@ add_libc_test(
libc.hdr.errno_macros
libc.hdr.types.char32_t
)
+
+add_libc_test(
+ wcsnrtombs_test
+ SUITE
+ libc-support-tests
+ SRCS
+ wcsnrtombs_test.cpp
+ DEPENDS
+ libc.src.__support.wchar.string_converter
+ libc.src.__support.wchar.character_converter
+ libc.src.__support.wchar.mbstate
+ libc.src.__support.error_or
+ libc.src.__support.wchar.wcsnrtombs
+ libc.hdr.errno_macros
+ libc.hdr.types.char32_t
+ libc.hdr.types.char8_t
+)
diff --git a/libc/test/src/__support/wchar/wcsnrtombs_test.cpp b/libc/test/src/__support/wchar/wcsnrtombs_test.cpp
new file mode 100644
index 0000000000000..710fc4b568ac0
--- /dev/null
+++ b/libc/test/src/__support/wchar/wcsnrtombs_test.cpp
@@ -0,0 +1,190 @@
+//===-- Unittests for wcsnrtombs ------------------------------------------===//
+//
+// 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/errno_macros.h"
+#include "hdr/types/size_t.h"
+#include "hdr/types/wchar_t.h"
+#include "src/__support/error_or.h"
+#include "src/__support/wchar/mbstate.h"
+#include "src/__support/wchar/wcsnrtombs.h"
+#include "test/UnitTest/Test.h"
+
+TEST(LlvmLibcWcsnrtombs, AllMultibyteLengths) {
+ LIBC_NAMESPACE::internal::mbstate state;
+
+ /// clown emoji, sigma symbol, y with diaeresis, letter A
+ const wchar_t src[] = {static_cast<wchar_t>(0x1f921),
+ static_cast<wchar_t>(0x2211),
+ static_cast<wchar_t>(0xff), static_cast<wchar_t>(0x41),
+ static_cast<wchar_t>(0x0)};
+ const wchar_t *cur = src;
+ char mbs[11];
+
+ auto res = LIBC_NAMESPACE::internal::wcsnrtombs(mbs, &cur, 5, 11, &state);
+ ASSERT_TRUE(res.has_value());
+ ASSERT_EQ(res.value(), static_cast<size_t>(10));
+ ASSERT_EQ(cur, nullptr);
+ ASSERT_EQ(mbs[0], '\xF0'); // clown begin
+ ASSERT_EQ(mbs[1], '\x9F');
+ ASSERT_EQ(mbs[2], '\xA4');
+ ASSERT_EQ(mbs[3], '\xA1');
+ ASSERT_EQ(mbs[4], '\xE2'); // sigma begin
+ ASSERT_EQ(mbs[5], '\x88');
+ ASSERT_EQ(mbs[6], '\x91');
+ ASSERT_EQ(mbs[7], '\xC3'); // y diaeresis begin
+ ASSERT_EQ(mbs[8], '\xBF');
+ ASSERT_EQ(mbs[9], '\x41'); // A begin
+ ASSERT_EQ(mbs[10], '\0'); // null terminator
+}
+
+TEST(LlvmLibcWcsnrtombs, DestLimit) {
+ LIBC_NAMESPACE::internal::mbstate state1;
+
+ /// clown emoji, sigma symbol, y with diaeresis, letter A
+ const wchar_t src[] = {static_cast<wchar_t>(0x1f921),
+ static_cast<wchar_t>(0x2211),
+ static_cast<wchar_t>(0xff), static_cast<wchar_t>(0x41),
+ static_cast<wchar_t>(0x0)};
+ const wchar_t *cur = src;
+
+ char mbs[11];
+ for (int i = 0; i < 11; ++i)
+ mbs[i] = '\x01'; // dummy initial values
+
+ auto res = LIBC_NAMESPACE::internal::wcsnrtombs(mbs, &cur, 5, 4, &state1);
+ ASSERT_TRUE(res.has_value());
+ ASSERT_EQ(res.value(), static_cast<size_t>(4));
+ ASSERT_EQ(cur, src + 1);
+ ASSERT_EQ(mbs[0], '\xF0');
+ ASSERT_EQ(mbs[1], '\x9F');
+ ASSERT_EQ(mbs[2], '\xA4');
+ ASSERT_EQ(mbs[3], '\xA1');
+ ASSERT_EQ(mbs[4], '\x01'); // didn't write more than 4 bytes
+
+ for (int i = 0; i < 11; ++i)
+ mbs[i] = '\x01'; // dummy initial values
+ LIBC_NAMESPACE::internal::mbstate state2;
+
+ // not enough bytes to convert the second character, so only converts one
+ cur = src;
+ res = LIBC_NAMESPACE::internal::wcsnrtombs(mbs, &cur, 5, 6, &state2);
+ ASSERT_TRUE(res.has_value());
+ ASSERT_EQ(res.value(), static_cast<size_t>(4));
+ ASSERT_EQ(cur, src + 1);
+ ASSERT_EQ(mbs[0], '\xF0');
+ ASSERT_EQ(mbs[1], '\x9F');
+ ASSERT_EQ(mbs[2], '\xA4');
+ ASSERT_EQ(mbs[3], '\xA1');
+ ASSERT_EQ(mbs[4], '\x01');
+}
+
+TEST(LlvmLibcWcsnrtombs, SrcLimit) {
+ LIBC_NAMESPACE::internal::mbstate state;
+
+ /// clown emoji, sigma symbol, y with diaeresis, letter A
+ const wchar_t src[] = {static_cast<wchar_t>(0x1f921),
+ static_cast<wchar_t>(0x2211),
+ static_cast<wchar_t>(0xff), static_cast<wchar_t>(0x41),
+ static_cast<wchar_t>(0x0)};
+ const wchar_t *cur = src;
+
+ char mbs[11];
+ for (int i = 0; i < 11; ++i)
+ mbs[i] = '\x01'; // dummy initial values
+
+ auto res = LIBC_NAMESPACE::internal::wcsnrtombs(mbs, &cur, 2, 11, &state);
+ ASSERT_TRUE(res.has_value());
+ ASSERT_EQ(res.value(), static_cast<size_t>(7));
+ ASSERT_EQ(cur, src + 2);
+ ASSERT_EQ(mbs[0], '\xF0'); // clown begin
+ ASSERT_EQ(mbs[1], '\x9F');
+ ASSERT_EQ(mbs[2], '\xA4');
+ ASSERT_EQ(mbs[3], '\xA1');
+ ASSERT_EQ(mbs[4], '\xE2'); // sigma begin
+ ASSERT_EQ(mbs[5], '\x88');
+ ASSERT_EQ(mbs[6], '\x91');
+ ASSERT_EQ(mbs[7], '\x01');
+
+ res = LIBC_NAMESPACE::internal::wcsnrtombs(mbs + res.value(), &cur, 100, 11, &state);
+ ASSERT_TRUE(res.has_value());
+ ASSERT_EQ(res.value(), static_cast<size_t>(3));
+ ASSERT_EQ(cur, nullptr);
+ ASSERT_EQ(mbs[0], '\xF0'); // clown begin
+ ASSERT_EQ(mbs[1], '\x9F');
+ ASSERT_EQ(mbs[2], '\xA4');
+ ASSERT_EQ(mbs[3], '\xA1');
+ ASSERT_EQ(mbs[4], '\xE2'); // sigma begin
+ ASSERT_EQ(mbs[5], '\x88');
+ ASSERT_EQ(mbs[6], '\x91');
+ ASSERT_EQ(mbs[7], '\xC3'); // y diaeresis begin
+ ASSERT_EQ(mbs[8], '\xBF');
+ ASSERT_EQ(mbs[9], '\x41'); // A begin
+ ASSERT_EQ(mbs[10], '\0'); // null terminator
+}
+
+TEST(LlvmLibcWcsnrtombs, NullDest) {
+ LIBC_NAMESPACE::internal::mbstate state1;
+
+ const wchar_t src[] = {static_cast<wchar_t>(0x1f921),
+ static_cast<wchar_t>(0x2211),
+ static_cast<wchar_t>(0xff), static_cast<wchar_t>(0x41),
+ static_cast<wchar_t>(0x0)};
+ const wchar_t *cur = src;
+
+ // n parameter ignored when dest is null
+ auto res = LIBC_NAMESPACE::internal::wcsnrtombs(nullptr, &cur, 5, 1, &state1);
+ ASSERT_TRUE(res.has_value());
+ ASSERT_EQ(res.value(), static_cast<size_t>(10));
+ ASSERT_EQ(cur, nullptr);
+
+ LIBC_NAMESPACE::internal::mbstate state2;
+ cur = src;
+ res = LIBC_NAMESPACE::internal::wcsnrtombs(nullptr, &cur, 5, 100, &state2);
+ ASSERT_TRUE(res.has_value());
+ ASSERT_EQ(res.value(), static_cast<size_t>(10));
+ ASSERT_EQ(cur, nullptr);
+}
+
+TEST(LlvmLib...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/149421
More information about the libc-commits
mailing list