Skip to content

Commit 83e9697

Browse files
authored
[libc] Implement strfromd() and strfroml() (llvm#86113)
Follow up to llvm#85438. Implements the functions `strfromd()` and `strfroml()` introduced in C23, and unifies the testing framework for `strfrom*()` functions.
1 parent 721f149 commit 83e9697

File tree

13 files changed

+650
-97
lines changed

13 files changed

+650
-97
lines changed

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,9 @@ set(TARGET_LIBC_ENTRYPOINTS
180180
libc.src.stdlib.qsort_r
181181
libc.src.stdlib.rand
182182
libc.src.stdlib.srand
183+
libc.src.stdlib.strfromd
183184
libc.src.stdlib.strfromf
185+
libc.src.stdlib.strfroml
184186
libc.src.stdlib.strtod
185187
libc.src.stdlib.strtof
186188
libc.src.stdlib.strtol

libc/spec/stdc.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,8 @@ def StdC : StandardSpec<"stdc"> {
962962
FunctionSpec<"srand", RetValSpec<VoidType>, [ArgSpec<UnsignedIntType>]>,
963963

964964
FunctionSpec<"strfromf", RetValSpec<IntType>, [ArgSpec<CharRestrictedPtr>, ArgSpec<SizeTType>, ArgSpec<ConstCharRestrictedPtr>, ArgSpec<FloatType>]>,
965+
FunctionSpec<"strfromd", RetValSpec<IntType>, [ArgSpec<CharRestrictedPtr>, ArgSpec<SizeTType>, ArgSpec<ConstCharRestrictedPtr>, ArgSpec<DoubleType>]>,
966+
FunctionSpec<"strfroml", RetValSpec<IntType>, [ArgSpec<CharRestrictedPtr>, ArgSpec<SizeTType>, ArgSpec<ConstCharRestrictedPtr>, ArgSpec<LongDoubleType>]>,
965967

966968
FunctionSpec<"strtof", RetValSpec<FloatType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>,
967969
FunctionSpec<"strtod", RetValSpec<DoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>,

libc/src/stdlib/CMakeLists.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,26 @@ add_entrypoint_object(
6262
.str_from_util
6363
)
6464

65+
add_entrypoint_object(
66+
strfromd
67+
SRCS
68+
strfromd.cpp
69+
HDRS
70+
strfromd.h
71+
DEPENDS
72+
.str_from_util
73+
)
74+
75+
add_entrypoint_object(
76+
strfroml
77+
SRCS
78+
strfroml.cpp
79+
HDRS
80+
strfroml.h
81+
DEPENDS
82+
.str_from_util
83+
)
84+
6585
add_header_library(
6686
str_from_util
6787
HDRS

libc/src/stdlib/strfromd.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//===-- Implementation of strfromd ------------------------------*- 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+
#include "src/stdlib/strfromd.h"
10+
#include "src/stdlib/str_from_util.h"
11+
12+
#include <stdarg.h>
13+
#include <stddef.h>
14+
15+
namespace LIBC_NAMESPACE {
16+
17+
LLVM_LIBC_FUNCTION(int, strfromd,
18+
(char *__restrict s, size_t n, const char *__restrict format,
19+
double fp)) {
20+
LIBC_ASSERT(s != nullptr);
21+
22+
printf_core::FormatSection section =
23+
internal::parse_format_string(format, fp);
24+
printf_core::WriteBuffer wb(s, (n > 0 ? n - 1 : 0));
25+
printf_core::Writer writer(&wb);
26+
27+
int result = 0;
28+
if (section.has_conv)
29+
result = internal::strfromfloat_convert<double>(&writer, section);
30+
else
31+
result = writer.write(section.raw_string);
32+
33+
if (result < 0)
34+
return result;
35+
36+
if (n > 0)
37+
wb.buff[wb.buff_cur] = '\0';
38+
39+
return writer.get_chars_written();
40+
}
41+
42+
} // namespace LIBC_NAMESPACE

libc/src/stdlib/strfromd.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- Implementation header for strfromd ------------------------*- 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_STDLIB_STRFROMD_H
10+
#define LLVM_LIBC_SRC_STDLIB_STRFROMD_H
11+
12+
#include <stddef.h>
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
int strfromd(char *__restrict s, size_t n, const char *__restrict format,
17+
double fp);
18+
19+
} // namespace LIBC_NAMESPACE
20+
21+
#endif // LLVM_LIBC_SRC_STDLIB_STRFROMD_H

libc/src/stdlib/strfromf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ int strfromf(char *__restrict s, size_t n, const char *__restrict format,
1818

1919
} // namespace LIBC_NAMESPACE
2020

21-
#endif // LLVM_LIBC_SRC_STDLIB_STRTOF_H
21+
#endif // LLVM_LIBC_SRC_STDLIB_STRFROMF_H

libc/src/stdlib/strfroml.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//===-- Implementation of strfroml ------------------------------*- 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+
#include "src/stdlib/strfroml.h"
10+
#include "src/stdlib/str_from_util.h"
11+
12+
#include <stdarg.h>
13+
#include <stddef.h>
14+
15+
namespace LIBC_NAMESPACE {
16+
17+
LLVM_LIBC_FUNCTION(int, strfroml,
18+
(char *__restrict s, size_t n, const char *__restrict format,
19+
long double fp)) {
20+
LIBC_ASSERT(s != nullptr);
21+
22+
printf_core::FormatSection section =
23+
internal::parse_format_string(format, fp);
24+
25+
// To ensure that the conversion function actually uses long double,
26+
// the length modifier has to be set to LenghtModifier::L
27+
section.length_modifier = printf_core::LengthModifier::L;
28+
29+
printf_core::WriteBuffer wb(s, (n > 0 ? n - 1 : 0));
30+
printf_core::Writer writer(&wb);
31+
32+
int result = 0;
33+
if (section.has_conv)
34+
result = internal::strfromfloat_convert<long double>(&writer, section);
35+
else
36+
result = writer.write(section.raw_string);
37+
38+
if (result < 0)
39+
return result;
40+
41+
if (n > 0)
42+
wb.buff[wb.buff_cur] = '\0';
43+
44+
return writer.get_chars_written();
45+
}
46+
47+
} // namespace LIBC_NAMESPACE

libc/src/stdlib/strfroml.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- Implementation header for strfroml ------------------------*- 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_STDLIB_STRFROML_H
10+
#define LLVM_LIBC_SRC_STDLIB_STRFROML_H
11+
12+
#include <stddef.h>
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
int strfroml(char *__restrict s, size_t n, const char *__restrict format,
17+
long double fp);
18+
19+
} // namespace LIBC_NAMESPACE
20+
21+
#endif // LLVM_LIBC_SRC_STDLIB_STRFROML_H

libc/test/src/stdlib/CMakeLists.txt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,16 +168,47 @@ add_libc_test(
168168
.strtol_test_support
169169
)
170170

171+
add_header_library(
172+
strfrom_test_support
173+
HDRS
174+
StrfromTest.h
175+
DEPENDS
176+
libc.src.__support.CPP.type_traits
177+
)
178+
171179
add_libc_test(
172180
strfromf_test
173181
SUITE
174182
libc-stdlib-tests
175183
SRCS
176184
strfromf_test.cpp
177185
DEPENDS
186+
.strfrom_test_support
178187
libc.src.stdlib.strfromf
179188
)
180189

190+
add_libc_test(
191+
strfromd_test
192+
SUITE
193+
libc-stdlib-tests
194+
SRCS
195+
strfromd_test.cpp
196+
DEPENDS
197+
.strfrom_test_support
198+
libc.src.stdlib.strfromd
199+
)
200+
201+
add_libc_test(
202+
strfroml_test
203+
SUITE
204+
libc-stdlib-tests
205+
SRCS
206+
strfroml_test.cpp
207+
DEPENDS
208+
.strfrom_test_support
209+
libc.src.stdlib.strfroml
210+
)
211+
181212
add_libc_test(
182213
abs_test
183214
SUITE

0 commit comments

Comments
 (0)