Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc] Implement strfromd() and strfroml() #86113

Merged
merged 1 commit into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,9 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.stdlib.qsort_r
libc.src.stdlib.rand
libc.src.stdlib.srand
libc.src.stdlib.strfromd
libc.src.stdlib.strfromf
libc.src.stdlib.strfroml
libc.src.stdlib.strtod
libc.src.stdlib.strtof
libc.src.stdlib.strtol
Expand Down
2 changes: 2 additions & 0 deletions libc/spec/stdc.td
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,8 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"srand", RetValSpec<VoidType>, [ArgSpec<UnsignedIntType>]>,

FunctionSpec<"strfromf", RetValSpec<IntType>, [ArgSpec<CharRestrictedPtr>, ArgSpec<SizeTType>, ArgSpec<ConstCharRestrictedPtr>, ArgSpec<FloatType>]>,
FunctionSpec<"strfromd", RetValSpec<IntType>, [ArgSpec<CharRestrictedPtr>, ArgSpec<SizeTType>, ArgSpec<ConstCharRestrictedPtr>, ArgSpec<DoubleType>]>,
FunctionSpec<"strfroml", RetValSpec<IntType>, [ArgSpec<CharRestrictedPtr>, ArgSpec<SizeTType>, ArgSpec<ConstCharRestrictedPtr>, ArgSpec<LongDoubleType>]>,

FunctionSpec<"strtof", RetValSpec<FloatType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>,
FunctionSpec<"strtod", RetValSpec<DoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>,
Expand Down
20 changes: 20 additions & 0 deletions libc/src/stdlib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,26 @@ add_entrypoint_object(
.str_from_util
)

add_entrypoint_object(
strfromd
SRCS
strfromd.cpp
HDRS
strfromd.h
DEPENDS
.str_from_util
)

add_entrypoint_object(
strfroml
SRCS
strfroml.cpp
HDRS
strfroml.h
DEPENDS
.str_from_util
)

add_header_library(
str_from_util
HDRS
Expand Down
42 changes: 42 additions & 0 deletions libc/src/stdlib/strfromd.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//===-- Implementation of strfromd ------------------------------*- C++ -*-===//
//
// 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/stdlib/strfromd.h"
#include "src/stdlib/str_from_util.h"

#include <stdarg.h>
#include <stddef.h>

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(int, strfromd,
(char *__restrict s, size_t n, const char *__restrict format,
double fp)) {
LIBC_ASSERT(s != nullptr);

printf_core::FormatSection section =
internal::parse_format_string(format, fp);
printf_core::WriteBuffer wb(s, (n > 0 ? n - 1 : 0));
printf_core::Writer writer(&wb);

int result = 0;
if (section.has_conv)
result = internal::strfromfloat_convert<double>(&writer, section);
else
result = writer.write(section.raw_string);

if (result < 0)
return result;

if (n > 0)
wb.buff[wb.buff_cur] = '\0';

return writer.get_chars_written();
}

} // namespace LIBC_NAMESPACE
21 changes: 21 additions & 0 deletions libc/src/stdlib/strfromd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for strfromd ------------------------*- C++--===//
//
// 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_STDLIB_STRFROMD_H
#define LLVM_LIBC_SRC_STDLIB_STRFROMD_H

#include <stddef.h>

namespace LIBC_NAMESPACE {

int strfromd(char *__restrict s, size_t n, const char *__restrict format,
double fp);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_STDLIB_STRFROMD_H
2 changes: 1 addition & 1 deletion libc/src/stdlib/strfromf.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ int strfromf(char *__restrict s, size_t n, const char *__restrict format,

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_STDLIB_STRTOF_H
#endif // LLVM_LIBC_SRC_STDLIB_STRFROMF_H
47 changes: 47 additions & 0 deletions libc/src/stdlib/strfroml.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//===-- Implementation of strfroml ------------------------------*- C++ -*-===//
//
// 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/stdlib/strfroml.h"
#include "src/stdlib/str_from_util.h"

#include <stdarg.h>
#include <stddef.h>

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(int, strfroml,
(char *__restrict s, size_t n, const char *__restrict format,
long double fp)) {
LIBC_ASSERT(s != nullptr);

printf_core::FormatSection section =
internal::parse_format_string(format, fp);

// To ensure that the conversion function actually uses long double,
// the length modifier has to be set to LenghtModifier::L
section.length_modifier = printf_core::LengthModifier::L;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Add a comment here to mark that this is different from the others.


printf_core::WriteBuffer wb(s, (n > 0 ? n - 1 : 0));
printf_core::Writer writer(&wb);

int result = 0;
if (section.has_conv)
result = internal::strfromfloat_convert<long double>(&writer, section);
else
result = writer.write(section.raw_string);

if (result < 0)
return result;

if (n > 0)
wb.buff[wb.buff_cur] = '\0';

return writer.get_chars_written();
}

} // namespace LIBC_NAMESPACE
21 changes: 21 additions & 0 deletions libc/src/stdlib/strfroml.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for strfroml ------------------------*- C++--===//
//
// 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_STDLIB_STRFROML_H
#define LLVM_LIBC_SRC_STDLIB_STRFROML_H

#include <stddef.h>

namespace LIBC_NAMESPACE {

int strfroml(char *__restrict s, size_t n, const char *__restrict format,
long double fp);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_STDLIB_STRFROML_H
31 changes: 31 additions & 0 deletions libc/test/src/stdlib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -168,16 +168,47 @@ add_libc_test(
.strtol_test_support
)

add_header_library(
strfrom_test_support
HDRS
StrfromTest.h
DEPENDS
libc.src.__support.CPP.type_traits
)

add_libc_test(
strfromf_test
SUITE
libc-stdlib-tests
SRCS
strfromf_test.cpp
DEPENDS
.strfrom_test_support
libc.src.stdlib.strfromf
)

add_libc_test(
strfromd_test
SUITE
libc-stdlib-tests
SRCS
strfromd_test.cpp
DEPENDS
.strfrom_test_support
libc.src.stdlib.strfromd
)

add_libc_test(
strfroml_test
SUITE
libc-stdlib-tests
SRCS
strfroml_test.cpp
DEPENDS
.strfrom_test_support
libc.src.stdlib.strfroml
)

add_libc_test(
abs_test
SUITE
Expand Down