Skip to content

Commit 2db0289

Browse files
authored
[libc] Implemented wctomb (#145554)
Implemented wctomb by calling internal wcrtomb function Added tests
1 parent 0c359d7 commit 2db0289

File tree

7 files changed

+162
-0
lines changed

7 files changed

+162
-0
lines changed

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,7 @@ if(LLVM_LIBC_FULL_BUILD)
12511251
libc.src.wchar.mbrtowc
12521252
libc.src.wchar.mbtowc
12531253
libc.src.wchar.wcrtomb
1254+
libc.src.wchar.wctomb
12541255
)
12551256
endif()
12561257

libc/include/wchar.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,13 @@ functions:
175175
- type: char *__restrict
176176
- type: wchar_t
177177
- type: mbstate_t *__restrict
178+
- name: wctomb
179+
standards:
180+
- stdc
181+
return_type: int
182+
arguments:
183+
- type: char *
184+
- type: wchar_t
178185
- name: wcscpy
179186
standards:
180187
- stdc

libc/src/wchar/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,19 @@ add_entrypoint_object(
4848
libc.src.__support.wchar.mbstate
4949
)
5050

51+
add_entrypoint_object(
52+
wctomb
53+
SRCS
54+
wctomb.cpp
55+
HDRS
56+
wctomb.h
57+
DEPENDS
58+
libc.hdr.types.wchar_t
59+
libc.src.__support.wchar.wcrtomb
60+
libc.src.__support.wchar.mbstate
61+
libc.src.__support.libc_errno
62+
)
63+
5164
add_entrypoint_object(
5265
mbrtowc
5366
SRCS

libc/src/wchar/wctomb.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===-- Implementation of wctomb ------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/wchar/wctomb.h"
10+
11+
#include "hdr/types/wchar_t.h"
12+
#include "src/__support/common.h"
13+
#include "src/__support/libc_errno.h"
14+
#include "src/__support/macros/config.h"
15+
#include "src/__support/wchar/mbstate.h"
16+
#include "src/__support/wchar/wcrtomb.h"
17+
18+
namespace LIBC_NAMESPACE_DECL {
19+
20+
LLVM_LIBC_FUNCTION(int, wctomb, (char *s, wchar_t wc)) {
21+
static internal::mbstate internal_mbstate;
22+
if (s == nullptr)
23+
return 0;
24+
25+
auto result = internal::wcrtomb(s, wc, &internal_mbstate);
26+
27+
if (!result.has_value()) { // invalid wide character
28+
libc_errno = EILSEQ;
29+
return -1;
30+
}
31+
32+
return static_cast<int>(result.value());
33+
}
34+
35+
} // namespace LIBC_NAMESPACE_DECL

libc/src/wchar/wctomb.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===-- Implementation header for wctomb ------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_WCHAR_WCTOMB_H
10+
#define LLVM_LIBC_SRC_WCHAR_WCTOMB_H
11+
12+
#include "hdr/types/mbstate_t.h"
13+
#include "hdr/types/wchar_t.h"
14+
#include "src/__support/macros/config.h"
15+
16+
namespace LIBC_NAMESPACE_DECL {
17+
18+
int wctomb(char *s, wchar_t wc);
19+
20+
} // namespace LIBC_NAMESPACE_DECL
21+
22+
#endif // LLVM_LIBC_SRC_WCHAR_WCTOMB_H

libc/test/src/wchar/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,17 @@ add_libc_test(
7474
libc.src.__support.libc_errno
7575
)
7676

77+
add_libc_test(
78+
wctomb_test
79+
SUITE
80+
libc_wchar_unittests
81+
SRCS
82+
wctomb_test.cpp
83+
DEPENDS
84+
libc.src.wchar.wctomb
85+
libc.hdr.types.wchar_t
86+
)
87+
7788
add_libc_test(
7889
wmemset_test
7990
SUITE

libc/test/src/wchar/wctomb_test.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//===-- Unittests for wctomb ----------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "hdr/types/wchar_t.h"
10+
#include "src/__support/libc_errno.h"
11+
#include "src/wchar/wctomb.h"
12+
#include "test/UnitTest/ErrnoCheckingTest.h"
13+
#include "test/UnitTest/Test.h"
14+
15+
using LlvmLibcWCToMBTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
16+
17+
TEST(LlvmLibcWCToMBTest, OneByte) {
18+
wchar_t wc = L'U';
19+
char mb[4];
20+
int cnt = LIBC_NAMESPACE::wctomb(mb, wc);
21+
ASSERT_EQ(cnt, 1);
22+
ASSERT_EQ(mb[0], 'U');
23+
}
24+
25+
TEST(LlvmLibcWCToMBTest, TwoByte) {
26+
// testing utf32: 0xff -> utf8: 0xc3 0xbf
27+
wchar_t wc = 0xff;
28+
char mb[4];
29+
int cnt = LIBC_NAMESPACE::wctomb(mb, wc);
30+
ASSERT_EQ(cnt, 2);
31+
ASSERT_EQ(mb[0], static_cast<char>(0xc3));
32+
ASSERT_EQ(mb[1], static_cast<char>(0xbf));
33+
}
34+
35+
TEST(LlvmLibcWCToMBTest, ThreeByte) {
36+
// testing utf32: 0xac15 -> utf8: 0xea 0xb0 0x95
37+
wchar_t wc = 0xac15;
38+
char mb[4];
39+
int cnt = LIBC_NAMESPACE::wctomb(mb, wc);
40+
ASSERT_EQ(cnt, 3);
41+
ASSERT_EQ(mb[0], static_cast<char>(0xea));
42+
ASSERT_EQ(mb[1], static_cast<char>(0xb0));
43+
ASSERT_EQ(mb[2], static_cast<char>(0x95));
44+
}
45+
46+
TEST(LlvmLibcWCToMBTest, FourByte) {
47+
// testing utf32: 0x1f921 -> utf8: 0xf0 0x9f 0xa4 0xa1
48+
wchar_t wc = 0x1f921;
49+
char mb[4];
50+
int cnt = LIBC_NAMESPACE::wctomb(mb, wc);
51+
ASSERT_EQ(cnt, 4);
52+
ASSERT_EQ(mb[0], static_cast<char>(0xf0));
53+
ASSERT_EQ(mb[1], static_cast<char>(0x9f));
54+
ASSERT_EQ(mb[2], static_cast<char>(0xa4));
55+
ASSERT_EQ(mb[3], static_cast<char>(0xa1));
56+
}
57+
58+
TEST(LlvmLibcWCToMBTest, NullString) {
59+
wchar_t wc = L'A';
60+
61+
int cnt = LIBC_NAMESPACE::wctomb(nullptr, wc);
62+
63+
// no state-dependent encoding
64+
ASSERT_EQ(cnt, 0);
65+
}
66+
67+
TEST(LlvmLibcWCToMBTest, InvalidWchar) {
68+
wchar_t wc = 0x12ffff;
69+
char mb[4];
70+
int cnt = LIBC_NAMESPACE::wctomb(mb, wc);
71+
ASSERT_EQ(cnt, -1);
72+
ASSERT_ERRNO_EQ(EILSEQ);
73+
}

0 commit comments

Comments
 (0)