Skip to content

Commit a653934

Browse files
sribee8Sriya Pratipati
andauthored
[libc] Reland wchar string conversion mb to wc (#151048)
Added crash on nullptr to mbstowcs --------- Co-authored-by: Sriya Pratipati <[email protected]>
1 parent 335dbba commit a653934

File tree

15 files changed

+972
-9
lines changed

15 files changed

+972
-9
lines changed

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,6 +1273,9 @@ if(LLVM_LIBC_FULL_BUILD)
12731273
libc.src.wchar.mbsinit
12741274
libc.src.wchar.mbrtowc
12751275
libc.src.wchar.mbtowc
1276+
libc.src.wchar.mbstowcs
1277+
libc.src.wchar.mbsrtowcs
1278+
libc.src.wchar.mbsnrtowcs
12761279
libc.src.wchar.wcrtomb
12771280
libc.src.wchar.wctomb
12781281
libc.src.wchar.wcstombs

libc/include/wchar.yaml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,33 @@ functions:
5353
- type: wchar_t *__restrict
5454
- type: const char *__restrict
5555
- type: size_t
56+
- name: mbsnrtowcs
57+
standards:
58+
- stdc
59+
return_type: size_t
60+
arguments:
61+
- type: wchar_t *__restrict
62+
- type: const char **__restrict
63+
- type: size_t
64+
- type: size_t
65+
- type: mbstate_t *__restrict
66+
- name: mbsrtowcs
67+
standards:
68+
- stdc
69+
return_type: size_t
70+
arguments:
71+
- type: wchar_t *__restrict
72+
- type: const char **__restrict
73+
- type: size_t
74+
- type: mbstate_t *__restrict
75+
- name: mbstowcs
76+
standards:
77+
- stdc
78+
return_type: size_t
79+
arguments:
80+
- type: wchar_t *__restrict
81+
- type: const char *__restrict
82+
- type: size_t
5683
- name: mbsinit
5784
standards:
5885
- stdc

libc/src/__support/wchar/CMakeLists.txt

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,31 @@ add_object_library(
6060
SRCS
6161
mbrtowc.cpp
6262
DEPENDS
63-
libc.hdr.errno_macros
64-
libc.hdr.types.wchar_t
65-
libc.hdr.types.size_t
66-
libc.src.__support.common
67-
libc.src.__support.error_or
68-
libc.src.__support.macros.config
69-
.character_converter
70-
.mbstate
63+
libc.hdr.errno_macros
64+
libc.hdr.types.wchar_t
65+
libc.hdr.types.size_t
66+
libc.src.__support.common
67+
libc.src.__support.error_or
68+
libc.src.__support.macros.config
69+
.character_converter
70+
.mbstate
71+
)
72+
73+
add_header_library(
74+
mbsnrtowcs
75+
HDRS
76+
mbsnrtowcs.h
77+
DEPENDS
78+
libc.hdr.errno_macros
79+
libc.hdr.types.wchar_t
80+
libc.hdr.types.size_t
81+
libc.src.__support.common
82+
libc.src.__support.error_or
83+
libc.src.__support.macros.config
84+
libc.src.__support.macros.null_check
85+
.character_converter
86+
.mbstate
87+
.string_converter
7188
)
7289

7390
add_header_library(

libc/src/__support/wchar/mbsnrtowcs.h

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//===-- Implementation for mbsnrtowcs function ------------------*- 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___SUPPORT_WCHAR_MBSNRTOWCS_H
10+
#define LLVM_LIBC_SRC___SUPPORT_WCHAR_MBSNRTOWCS_H
11+
12+
#include "hdr/errno_macros.h"
13+
#include "hdr/types/size_t.h"
14+
#include "hdr/types/wchar_t.h"
15+
#include "src/__support/common.h"
16+
#include "src/__support/error_or.h"
17+
#include "src/__support/macros/config.h"
18+
#include "src/__support/macros/null_check.h"
19+
#include "src/__support/wchar/character_converter.h"
20+
#include "src/__support/wchar/mbstate.h"
21+
#include "src/__support/wchar/string_converter.h"
22+
23+
namespace LIBC_NAMESPACE_DECL {
24+
namespace internal {
25+
26+
LIBC_INLINE static ErrorOr<size_t> mbsnrtowcs(wchar_t *__restrict dst,
27+
const char **__restrict src,
28+
size_t nmc, size_t len,
29+
mbstate *__restrict ps) {
30+
LIBC_CRASH_ON_NULLPTR(src);
31+
// Checking if mbstate is valid
32+
CharacterConverter char_conv(ps);
33+
if (!char_conv.isValidState())
34+
return Error(EINVAL);
35+
36+
StringConverter<char8_t> str_conv(reinterpret_cast<const char8_t *>(*src), ps,
37+
len, nmc);
38+
size_t dst_idx = 0;
39+
ErrorOr<char32_t> converted = str_conv.popUTF32();
40+
while (converted.has_value()) {
41+
if (dst != nullptr)
42+
dst[dst_idx] = converted.value();
43+
// null terminator should not be counted in return value
44+
if (converted.value() == L'\0') {
45+
if (dst != nullptr)
46+
*src = nullptr;
47+
return dst_idx;
48+
}
49+
dst_idx++;
50+
converted = str_conv.popUTF32();
51+
}
52+
53+
if (converted.error() == -1) { // if we hit conversion limit
54+
if (dst != nullptr)
55+
*src += str_conv.getSourceIndex();
56+
return dst_idx;
57+
}
58+
59+
return Error(converted.error());
60+
}
61+
62+
} // namespace internal
63+
64+
} // namespace LIBC_NAMESPACE_DECL
65+
66+
#endif // LLVM_LIBC_SRC___SUPPORT_WCHAR_MBSNRTOWCS_H

libc/src/wchar/CMakeLists.txt

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,55 @@ add_entrypoint_object(
184184
libc.src.__support.wchar.mbstate
185185
)
186186

187+
add_entrypoint_object(
188+
mbstowcs
189+
SRCS
190+
mbstowcs.cpp
191+
HDRS
192+
mbstowcs.h
193+
DEPENDS
194+
libc.hdr.types.size_t
195+
libc.hdr.types.wchar_t
196+
libc.src.__support.common
197+
libc.src.__support.macros.config
198+
libc.src.__support.macros.null_check
199+
libc.src.__support.libc_errno
200+
libc.src.__support.wchar.mbstate
201+
libc.src.__support.wchar.mbsnrtowcs
202+
)
203+
204+
add_entrypoint_object(
205+
mbsrtowcs
206+
SRCS
207+
mbsrtowcs.cpp
208+
HDRS
209+
mbsrtowcs.h
210+
DEPENDS
211+
libc.hdr.types.size_t
212+
libc.hdr.types.wchar_t
213+
libc.src.__support.common
214+
libc.src.__support.macros.config
215+
libc.src.__support.libc_errno
216+
libc.src.__support.wchar.mbstate
217+
libc.src.__support.wchar.mbsnrtowcs
218+
)
219+
220+
add_entrypoint_object(
221+
mbsnrtowcs
222+
SRCS
223+
mbsnrtowcs.cpp
224+
HDRS
225+
mbsnrtowcs.h
226+
DEPENDS
227+
libc.hdr.types.size_t
228+
libc.hdr.types.wchar_t
229+
libc.src.__support.common
230+
libc.src.__support.macros.config
231+
libc.src.__support.libc_errno
232+
libc.src.__support.wchar.mbstate
233+
libc.src.__support.wchar.mbsnrtowcs
234+
)
235+
187236
add_entrypoint_object(
188237
wcstombs
189238
SRCS

libc/src/wchar/mbsnrtowcs.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//===-- Implementation of mbsnrtowcs --------------------------------------===//
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/mbsnrtowcs.h"
10+
11+
#include "hdr/types/size_t.h"
12+
#include "hdr/types/wchar_t.h"
13+
#include "src/__support/common.h"
14+
#include "src/__support/libc_errno.h"
15+
#include "src/__support/macros/config.h"
16+
#include "src/__support/wchar/mbsnrtowcs.h"
17+
#include "src/__support/wchar/mbstate.h"
18+
19+
namespace LIBC_NAMESPACE_DECL {
20+
21+
LLVM_LIBC_FUNCTION(size_t, mbsnrtowcs,
22+
(wchar_t *__restrict dst, const char **__restrict src,
23+
size_t nmc, size_t len, mbstate_t *__restrict ps)) {
24+
static internal::mbstate internal_mbstate;
25+
// If destination is null, ignore len
26+
len = dst == nullptr ? SIZE_MAX : len;
27+
auto ret = internal::mbsnrtowcs(
28+
dst, src, nmc, len,
29+
ps == nullptr ? &internal_mbstate
30+
: reinterpret_cast<internal::mbstate *>(ps));
31+
if (!ret.has_value()) {
32+
// Encoding failure
33+
libc_errno = ret.error();
34+
return -1;
35+
}
36+
return ret.value();
37+
}
38+
39+
} // namespace LIBC_NAMESPACE_DECL

libc/src/wchar/mbsnrtowcs.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//===-- Implementation header for mbsnrtowcs ------------------------------===//
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_MBSNRTOWCS_H
10+
#define LLVM_LIBC_SRC_WCHAR_MBSNRTOWCS_H
11+
12+
#include "hdr/types/mbstate_t.h"
13+
#include "hdr/types/size_t.h"
14+
#include "hdr/types/wchar_t.h"
15+
#include "src/__support/macros/config.h"
16+
17+
namespace LIBC_NAMESPACE_DECL {
18+
19+
size_t mbsnrtowcs(wchar_t *__restrict dst, const char **__restrict src,
20+
size_t nmc, size_t len, mbstate_t *__restrict ps);
21+
22+
} // namespace LIBC_NAMESPACE_DECL
23+
24+
#endif // LLVM_LIBC_SRC_WCHAR_MBSNRTOWCS_H

libc/src/wchar/mbsrtowcs.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//===-- Implementation of mbsrtowcs ---------------------------------------===//
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/mbsrtowcs.h"
10+
11+
#include "hdr/types/size_t.h"
12+
#include "hdr/types/wchar_t.h"
13+
#include "src/__support/common.h"
14+
#include "src/__support/libc_errno.h"
15+
#include "src/__support/macros/config.h"
16+
#include "src/__support/wchar/mbsnrtowcs.h"
17+
#include "src/__support/wchar/mbstate.h"
18+
19+
namespace LIBC_NAMESPACE_DECL {
20+
21+
LLVM_LIBC_FUNCTION(size_t, mbsrtowcs,
22+
(wchar_t *__restrict dst, const char **__restrict src,
23+
size_t len, mbstate_t *__restrict ps)) {
24+
static internal::mbstate internal_mbstate;
25+
// If destination is null, ignore len
26+
len = dst == nullptr ? SIZE_MAX : len;
27+
auto ret = internal::mbsnrtowcs(
28+
dst, src, SIZE_MAX, len,
29+
ps == nullptr ? &internal_mbstate
30+
: reinterpret_cast<internal::mbstate *>(ps));
31+
if (!ret.has_value()) {
32+
// Encoding failure
33+
libc_errno = ret.error();
34+
return -1;
35+
}
36+
return ret.value();
37+
}
38+
39+
} // namespace LIBC_NAMESPACE_DECL

libc/src/wchar/mbsrtowcs.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//===-- Implementation header for mbsrtowcs -------------------------------===//
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_MBSRTOWCS_H
10+
#define LLVM_LIBC_SRC_WCHAR_MBSRTOWCS_H
11+
12+
#include "hdr/types/mbstate_t.h"
13+
#include "hdr/types/size_t.h"
14+
#include "hdr/types/wchar_t.h"
15+
#include "src/__support/macros/config.h"
16+
17+
namespace LIBC_NAMESPACE_DECL {
18+
19+
size_t mbsrtowcs(wchar_t *__restrict dst, const char **__restrict src,
20+
size_t len, mbstate_t *__restrict ps);
21+
22+
} // namespace LIBC_NAMESPACE_DECL
23+
24+
#endif // LLVM_LIBC_SRC_WCHAR_MBSRTOWCS_H

libc/src/wchar/mbstowcs.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===-- Implementation of mbstowcs ----------------------------------------===//
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/mbstowcs.h"
10+
11+
#include "hdr/types/size_t.h"
12+
#include "hdr/types/wchar_t.h"
13+
#include "src/__support/common.h"
14+
#include "src/__support/libc_errno.h"
15+
#include "src/__support/macros/config.h"
16+
#include "src/__support/macros/null_check.h"
17+
#include "src/__support/wchar/mbsnrtowcs.h"
18+
#include "src/__support/wchar/mbstate.h"
19+
20+
namespace LIBC_NAMESPACE_DECL {
21+
22+
LLVM_LIBC_FUNCTION(size_t, mbstowcs,
23+
(wchar_t *__restrict pwcs, const char *__restrict s,
24+
size_t n)) {
25+
LIBC_CRASH_ON_NULLPTR(s);
26+
// If destination is null, ignore n
27+
n = pwcs == nullptr ? SIZE_MAX : n;
28+
static internal::mbstate internal_mbstate;
29+
const char *temp = s;
30+
auto ret = internal::mbsnrtowcs(pwcs, &temp, SIZE_MAX, n, &internal_mbstate);
31+
32+
if (!ret.has_value()) {
33+
// Encoding failure
34+
libc_errno = ret.error();
35+
return -1;
36+
}
37+
return ret.value();
38+
}
39+
40+
} // namespace LIBC_NAMESPACE_DECL

0 commit comments

Comments
 (0)