-
Notifications
You must be signed in to change notification settings - Fork 13k
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] Templatize the scanf Reader interface #131037
Conversation
@llvm/pr-subscribers-libc Author: Petr Hosek (petrhosek) ChangesThis allows specializing the implementation for different targets without including unnecessary logic and is similar to #111559 which did the same for printf Writer interface. Patch is 76.96 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/131037.diff 32 Files Affected:
diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index 2c226ef176c08..8b51942d30fe8 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -123,18 +123,22 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.inttypes.strtoumax
# stdio.h entrypoints
+ libc.src.stdio.asprintf
libc.src.stdio.getchar
libc.src.stdio.printf
libc.src.stdio.putchar
libc.src.stdio.puts
libc.src.stdio.remove
+ libc.src.stdio.scanf
libc.src.stdio.snprintf
libc.src.stdio.sprintf
- libc.src.stdio.asprintf
+ libc.src.stdio.sscanf
+ libc.src.stdio.vasprintf
libc.src.stdio.vprintf
+ libc.src.stdio.vscanf
libc.src.stdio.vsnprintf
libc.src.stdio.vsprintf
- libc.src.stdio.vasprintf
+ libc.src.stdio.vsscanf
# stdbit.h entrypoints
libc.src.stdbit.stdc_bit_ceil_uc
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index d7a01bdf90b3f..511d9d22f1450 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -123,18 +123,22 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.inttypes.strtoumax
# stdio.h entrypoints
+ libc.src.stdio.asprintf
libc.src.stdio.getchar
libc.src.stdio.printf
libc.src.stdio.putchar
libc.src.stdio.puts
libc.src.stdio.remove
+ libc.src.stdio.scanf
libc.src.stdio.snprintf
libc.src.stdio.sprintf
- libc.src.stdio.asprintf
+ libc.src.stdio.sscanf
+ libc.src.stdio.vasprintf
libc.src.stdio.vprintf
+ libc.src.stdio.vscanf
libc.src.stdio.vsnprintf
libc.src.stdio.vsprintf
- libc.src.stdio.vasprintf
+ libc.src.stdio.vsscanf
# stdbit.h entrypoints
libc.src.stdbit.stdc_bit_ceil_uc
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index ae00803dd0def..bbefb75ee16b5 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -119,18 +119,22 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.inttypes.strtoumax
# stdio.h entrypoints
+ libc.src.stdio.asprintf
libc.src.stdio.getchar
libc.src.stdio.printf
libc.src.stdio.putchar
libc.src.stdio.puts
libc.src.stdio.remove
+ libc.src.stdio.scanf
libc.src.stdio.snprintf
libc.src.stdio.sprintf
- libc.src.stdio.asprintf
+ libc.src.stdio.sscanf
+ libc.src.stdio.vasprintf
libc.src.stdio.vprintf
+ libc.src.stdio.vscanf
libc.src.stdio.vsnprintf
libc.src.stdio.vsprintf
- libc.src.stdio.vasprintf
+ libc.src.stdio.vsscanf
# stdbit.h entrypoints
libc.src.stdbit.stdc_bit_ceil_uc
diff --git a/libc/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt
index b9bc904471df9..23c103c1d6465 100644
--- a/libc/src/stdio/CMakeLists.txt
+++ b/libc/src/stdio/CMakeLists.txt
@@ -95,20 +95,6 @@ add_entrypoint_object(
libc.src.__support.File.platform_file
)
-list(APPEND scanf_deps
- libc.src.__support.arg_list
- libc.src.stdio.scanf_core.vfscanf_internal
- libc.hdr.types.FILE
-)
-
-if(LLVM_LIBC_FULL_BUILD AND NOT LIBC_TARGET_OS_IS_GPU)
- list(APPEND scanf_deps
- libc.src.__support.File.file
- libc.src.__support.File.platform_file
- libc.src.__support.File.platform_stdin
- )
-endif()
-
add_entrypoint_object(
sscanf
SRCS
@@ -133,46 +119,6 @@ add_entrypoint_object(
libc.src.stdio.scanf_core.scanf_main
)
-add_entrypoint_object(
- fscanf
- SRCS
- fscanf.cpp
- HDRS
- fscanf.h
- DEPENDS
- ${scanf_deps}
-)
-
-add_entrypoint_object(
- vfscanf
- SRCS
- vfscanf.cpp
- HDRS
- vfscanf.h
- DEPENDS
- ${scanf_deps}
-)
-
-add_entrypoint_object(
- scanf
- SRCS
- scanf.cpp
- HDRS
- scanf.h
- DEPENDS
- ${scanf_deps}
-)
-
-add_entrypoint_object(
- vscanf
- SRCS
- vscanf.cpp
- HDRS
- vscanf.h
- DEPENDS
- ${scanf_deps}
-)
-
add_entrypoint_object(
sprintf
SRCS
@@ -295,8 +241,12 @@ add_stdio_entrypoint_object(getchar)
add_stdio_entrypoint_object(getchar_unlocked)
add_stdio_entrypoint_object(fgets)
add_stdio_entrypoint_object(ungetc)
+add_stdio_entrypoint_object(scanf)
+add_stdio_entrypoint_object(fscanf)
add_stdio_entrypoint_object(stdin)
add_stdio_entrypoint_object(stdout)
add_stdio_entrypoint_object(stderr)
add_stdio_entrypoint_object(vprintf)
add_stdio_entrypoint_object(vfprintf)
+add_stdio_entrypoint_object(vscanf)
+add_stdio_entrypoint_object(vfscanf)
diff --git a/libc/src/stdio/baremetal/CMakeLists.txt b/libc/src/stdio/baremetal/CMakeLists.txt
index c5cf4a8e0e5b5..4abe8bc66b25b 100644
--- a/libc/src/stdio/baremetal/CMakeLists.txt
+++ b/libc/src/stdio/baremetal/CMakeLists.txt
@@ -55,6 +55,19 @@ add_entrypoint_object(
libc.src.__support.CPP.string_view
)
+add_entrypoint_object(
+ scanf
+ SRCS
+ scanf.cpp
+ HDRS
+ ../scanf.h
+ DEPENDS
+ libc.src.stdio.scanf_core.scanf_main
+ libc.src.stdio.scanf_core.reader
+ libc.src.__support.arg_list
+ libc.src.__support.OSUtil.osutil
+)
+
add_entrypoint_object(
vprintf
SRCS
@@ -67,3 +80,16 @@ add_entrypoint_object(
libc.src.__support.arg_list
libc.src.__support.OSUtil.osutil
)
+
+add_entrypoint_object(
+ vscanf
+ SRCS
+ vscanf.cpp
+ HDRS
+ ../vscanf.h
+ DEPENDS
+ libc.src.stdio.scanf_core.scanf_main
+ libc.src.stdio.scanf_core.reader
+ libc.src.__support.arg_list
+ libc.src.__support.OSUtil.osutil
+)
diff --git a/libc/src/stdio/baremetal/scanf.cpp b/libc/src/stdio/baremetal/scanf.cpp
new file mode 100644
index 0000000000000..1b0bf3e3afd54
--- /dev/null
+++ b/libc/src/stdio/baremetal/scanf.cpp
@@ -0,0 +1,52 @@
+//===-- Implementation of scanf ---------------------------------*- 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/stdio/scanf.h"
+
+#include "hdr/stdio_macros.h"
+#include "src/__support/OSUtil/io.h"
+#include "src/__support/arg_list.h"
+#include "src/__support/macros/config.h"
+#include "src/stdio/scanf_core/reader.h"
+#include "src/stdio/scanf_core/scanf_main.h"
+
+#include <stdarg.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace {
+
+struct StreamBuffer : scanf_core::ReadBuffer<StreamBuffer> {
+ LIBC_INLINE char getc() {
+ char buf[1];
+ read_from_stdin(buf, sizeof(buf));
+ return buf[0];
+ }
+ LIBC_INLINE void ungetc(int) {}
+};
+
+} // namespace
+
+LLVM_LIBC_FUNCTION(int, scanf, (const char *__restrict format, ...)) {
+ va_list vlist;
+ va_start(vlist, format);
+ internal::ArgList args(vlist); // This holder class allows for easier copying
+ // and pointer semantics, as well as handling
+ // destruction automatically.
+ va_end(vlist);
+
+ StreamBuffer buffer;
+ scanf_core::Reader<StreamBuffer> reader(&buffer);
+
+ int retval = scanf_core::scanf_main(&reader, format, args);
+ // This is done to avoid including stdio.h in the internals. On most systems
+ // EOF is -1, so this will be transformed into just "return retval".
+ return (retval == -1) ? EOF : retval;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/baremetal/vscanf.cpp b/libc/src/stdio/baremetal/vscanf.cpp
new file mode 100644
index 0000000000000..e0119d6146d89
--- /dev/null
+++ b/libc/src/stdio/baremetal/vscanf.cpp
@@ -0,0 +1,51 @@
+//===-- Implementation of vscanf --------------------------------*- 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/stdio/vscanf.h"
+
+#include "hdr/stdio_macros.h"
+#include "src/__support/OSUtil/io.h"
+#include "src/__support/arg_list.h"
+#include "src/__support/macros/config.h"
+#include "src/stdio/scanf_core/reader.h"
+#include "src/stdio/scanf_core/scanf_main.h"
+
+#include <stdarg.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace {
+
+struct StreamBuffer : scanf_core::ReadBuffer<StreamBuffer> {
+ LIBC_INLINE char getc() {
+ char buf[1];
+ read_from_stdin(buf, sizeof(buf));
+ return buf[0];
+ }
+ LIBC_INLINE void ungetc(int) {}
+};
+
+} // namespace
+
+LLVM_LIBC_FUNCTION(int, vscanf,
+ (const char *__restrict format, va_list vlist)) {
+ internal::ArgList args(vlist); // This holder class allows for easier copying
+ // and pointer semantics, as well as handling
+ // destruction automatically.
+ va_end(vlist);
+
+ StreamBuffer buffer;
+ scanf_core::Reader<StreamBuffer> reader(&buffer);
+
+ int retval = scanf_core::scanf_main(&reader, format, args);
+ // This is done to avoid including stdio.h in the internals. On most systems
+ // EOF is -1, so this will be transformed into just "return retval".
+ return (retval == -1) ? EOF : retval;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/generic/CMakeLists.txt b/libc/src/stdio/generic/CMakeLists.txt
index bf301a6b0cb3c..9f568c5ab8d3a 100644
--- a/libc/src/stdio/generic/CMakeLists.txt
+++ b/libc/src/stdio/generic/CMakeLists.txt
@@ -425,6 +425,60 @@ add_entrypoint_object(
${fprintf_deps}
)
+list(APPEND scanf_deps
+ libc.src.__support.arg_list
+ libc.src.stdio.scanf_core.vfscanf_internal
+ libc.hdr.types.FILE
+)
+
+if(LLVM_LIBC_FULL_BUILD AND NOT LIBC_TARGET_OS_IS_GPU)
+ list(APPEND scanf_deps
+ libc.src.__support.File.file
+ libc.src.__support.File.platform_file
+ libc.src.__support.File.platform_stdin
+ )
+endif()
+
+add_entrypoint_object(
+ fscanf
+ SRCS
+ fscanf.cpp
+ HDRS
+ ../fscanf.h
+ DEPENDS
+ ${scanf_deps}
+)
+
+add_entrypoint_object(
+ vfscanf
+ SRCS
+ vfscanf.cpp
+ HDRS
+ ../vfscanf.h
+ DEPENDS
+ ${scanf_deps}
+)
+
+add_entrypoint_object(
+ scanf
+ SRCS
+ scanf.cpp
+ HDRS
+ ../scanf.h
+ DEPENDS
+ ${scanf_deps}
+)
+
+add_entrypoint_object(
+ vscanf
+ SRCS
+ vscanf.cpp
+ HDRS
+ ../vscanf.h
+ DEPENDS
+ ${scanf_deps}
+)
+
add_entrypoint_object(
fgets
SRCS
diff --git a/libc/src/stdio/fscanf.cpp b/libc/src/stdio/generic/fscanf.cpp
similarity index 100%
rename from libc/src/stdio/fscanf.cpp
rename to libc/src/stdio/generic/fscanf.cpp
diff --git a/libc/src/stdio/scanf.cpp b/libc/src/stdio/generic/scanf.cpp
similarity index 100%
rename from libc/src/stdio/scanf.cpp
rename to libc/src/stdio/generic/scanf.cpp
diff --git a/libc/src/stdio/vfscanf.cpp b/libc/src/stdio/generic/vfscanf.cpp
similarity index 100%
rename from libc/src/stdio/vfscanf.cpp
rename to libc/src/stdio/generic/vfscanf.cpp
diff --git a/libc/src/stdio/vscanf.cpp b/libc/src/stdio/generic/vscanf.cpp
similarity index 100%
rename from libc/src/stdio/vscanf.cpp
rename to libc/src/stdio/generic/vscanf.cpp
diff --git a/libc/src/stdio/scanf_core/CMakeLists.txt b/libc/src/stdio/scanf_core/CMakeLists.txt
index 014413ccaa8da..3de1e6a6eea37 100644
--- a/libc/src/stdio/scanf_core/CMakeLists.txt
+++ b/libc/src/stdio/scanf_core/CMakeLists.txt
@@ -16,6 +16,8 @@ if(LIBC_TARGET_OS_IS_GPU)
libc.src.stdio.ungetc
libc.src.stdio.ferror
)
+elseif(LIBC_TARGET_OS_IS_BAREMETAL)
+ # There's no FILE* for baremetal.
elseif(LLVM_LIBC_FULL_BUILD)
list(APPEND file_deps
libc.src.__support.File.file
@@ -54,17 +56,8 @@ add_header_library(
libc.src.__support.CPP.string_view
)
-if(NOT(TARGET libc.src.__support.File.file) AND LLVM_LIBC_FULL_BUILD AND
- (NOT LIBC_TARGET_OS_IS_GPU))
- # Not all platforms have a file implementation. If file is unvailable, and a
- # full build is requested, then we must skip all file based scanf sections.
- return()
-endif()
-
-add_object_library(
+add_header_library(
scanf_main
- SRCS
- scanf_main.cpp
HDRS
scanf_main.h
DEPENDS
@@ -87,14 +80,8 @@ add_header_library(
${use_system_file}
)
-add_object_library(
+add_header_library(
converter
- SRCS
- converter.cpp
- string_converter.cpp
- int_converter.cpp
- float_converter.cpp
- ptr_converter.cpp
HDRS
converter.h
converter_utils.h
diff --git a/libc/src/stdio/scanf_core/converter.cpp b/libc/src/stdio/scanf_core/converter.cpp
index b1ee8cd1e74bb..fb234ce7864cf 100644
--- a/libc/src/stdio/scanf_core/converter.cpp
+++ b/libc/src/stdio/scanf_core/converter.cpp
@@ -26,78 +26,5 @@
namespace LIBC_NAMESPACE_DECL {
namespace scanf_core {
-int convert(Reader *reader, const FormatSection &to_conv) {
- int ret_val = 0;
- switch (to_conv.conv_name) {
- case '%':
- return raw_match(reader, "%");
- case 's':
- ret_val = raw_match(reader, " ");
- if (ret_val != READ_OK)
- return ret_val;
- return convert_string(reader, to_conv);
- case 'c':
- case '[':
- return convert_string(reader, to_conv);
- case 'd':
- case 'i':
- case 'u':
- case 'o':
- case 'x':
- case 'X':
- ret_val = raw_match(reader, " ");
- if (ret_val != READ_OK)
- return ret_val;
- return convert_int(reader, to_conv);
-#ifndef LIBC_COPT_SCANF_DISABLE_FLOAT
- case 'f':
- case 'F':
- case 'e':
- case 'E':
- case 'a':
- case 'A':
- case 'g':
- case 'G':
- ret_val = raw_match(reader, " ");
- if (ret_val != READ_OK)
- return ret_val;
- return convert_float(reader, to_conv);
-#endif // LIBC_COPT_SCANF_DISABLE_FLOAT
- case 'n':
- return convert_current_pos(reader, to_conv);
- case 'p':
- ret_val = raw_match(reader, " ");
- if (ret_val != READ_OK)
- return ret_val;
- return convert_pointer(reader, to_conv);
- default:
- return raw_match(reader, to_conv.raw_string);
- }
- return -1;
-}
-
-// raw_string is assumed to have a positive size.
-int raw_match(Reader *reader, cpp::string_view raw_string) {
- char cur_char = reader->getc();
- int ret_val = READ_OK;
- for (size_t i = 0; i < raw_string.size(); ++i) {
- // Any space character matches any number of space characters.
- if (internal::isspace(raw_string[i])) {
- while (internal::isspace(cur_char)) {
- cur_char = reader->getc();
- }
- } else {
- if (raw_string[i] == cur_char) {
- cur_char = reader->getc();
- } else {
- ret_val = MATCHING_FAILURE;
- break;
- }
- }
- }
- reader->ungetc(cur_char);
- return ret_val;
-}
-
} // namespace scanf_core
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/scanf_core/converter.h b/libc/src/stdio/scanf_core/converter.h
index 3f514eeb75bdf..3df43e9de1e25 100644
--- a/libc/src/stdio/scanf_core/converter.h
+++ b/libc/src/stdio/scanf_core/converter.h
@@ -10,10 +10,19 @@
#define LLVM_LIBC_SRC_STDIO_SCANF_CORE_CONVERTER_H
#include "src/__support/CPP/string_view.h"
+#include "src/__support/ctype_utils.h"
#include "src/__support/macros/config.h"
#include "src/stdio/scanf_core/core_structs.h"
#include "src/stdio/scanf_core/reader.h"
+#ifndef LIBC_COPT_SCANF_DISABLE_FLOAT
+#include "src/stdio/scanf_core/float_converter.h"
+#endif // LIBC_COPT_SCANF_DISABLE_FLOAT
+#include "src/stdio/scanf_core/current_pos_converter.h"
+#include "src/stdio/scanf_core/int_converter.h"
+#include "src/stdio/scanf_core/ptr_converter.h"
+#include "src/stdio/scanf_core/string_converter.h"
+
#include <stddef.h>
namespace LIBC_NAMESPACE_DECL {
@@ -22,11 +31,81 @@ namespace scanf_core {
// convert will call a conversion function to convert the FormatSection into
// its string representation, and then that will write the result to the
// reader.
-int convert(Reader *reader, const FormatSection &to_conv);
+template <typename T>
+int convert(Reader<T> *reader, const FormatSection &to_conv) {
+ int ret_val = 0;
+ switch (to_conv.conv_name) {
+ case '%':
+ return raw_match(reader, "%");
+ case 's':
+ ret_val = raw_match(reader, " ");
+ if (ret_val != READ_OK)
+ return ret_val;
+ return convert_string(reader, to_conv);
+ case 'c':
+ case '[':
+ return convert_string(reader, to_conv);
+ case 'd':
+ case 'i':
+ case 'u':
+ case 'o':
+ case 'x':
+ case 'X':
+ ret_val = raw_match(reader, " ");
+ if (ret_val != READ_OK)
+ return ret_val;
+ return convert_int(reader, to_conv);
+#ifndef LIBC_COPT_SCANF_DISABLE_FLOAT
+ case 'f':
+ case 'F':
+ case 'e':
+ case 'E':
+ case 'a':
+ case 'A':
+ case 'g':
+ case 'G':
+ ret_val = raw_match(reader, " ");
+ if (ret_val != READ_OK)
+ return ret_val;
+ return convert_float(reader, to_conv);
+#endif // LIBC_COPT_SCANF_DISABLE_FLOAT
+ case 'n':
+ return convert_current_pos(reader, to_conv);
+ case 'p':
+ ret_val = raw_match(reader, " ");
+ if (ret_val != READ_OK)
+ return ret_val;
+ return convert_pointer(reader, to_conv);
+ default:
+ return raw_match(reader, to_conv.raw_string);
+ }
+ return -1;
+}
// raw_match takes a raw string and matches it to the characters obtained from
// the reader.
-int raw_match(Reader *reader, cpp::string_view raw_string);
+template <typename T>
+int raw_match(Reader<T> *reader, cpp::string_view raw_string) {
+ char cur_char = reader->getc();
+ int ret_val = READ_OK;
+ for (size_t i = 0; i < raw_string.size(); ++i) {
+ // Any space character matches any number of space characters.
+ if (internal::isspace(raw_string[i])) {
+ while (internal::isspace(cur_char)) {
+ cur_char = reader->getc();
+ }
+ } else {
+ if (raw_string[i] == cur_char) {
+ cur_char = reader->getc();
+ } else {
+ ret_val = MATCHING_FAILURE;
+ break;
+ }
+ }
+ }
+ reader->ungetc(cur_char);
+ return ret_val;
+}
} // namespace scanf_core
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/scanf_core/current_pos_converter.h b/libc/src/stdio/scanf_core/current_pos_converter.h
index 8af1cc0ca0c27..8708490c82d3e 100644
--- a/libc/src/stdio/scanf_core/current_pos_converter.h
+++ b/libc/src/stdio/scanf_core/current_pos_converter.h
@@ -19,7 +19,8 @@
namespace LIBC_NAMESPACE_DECL {
namespace scanf_core {
-LIBC_INLINE int convert_current_pos(Reader *reader,
+template <typename T>
+LIBC_INLINE int convert_current_pos(Reader<T> *reader,
const FormatSection &to_conv) {
write_int_with_length(reader->chars_read(), to_conv);
return READ_OK;
diff --git a/libc/src/stdio/scanf_core/float_converter.cpp b/libc/src/stdio/scanf_core/float_converter.cpp
deleted file mode 100644
index 9c714d0727214..0000000000000
--- a/libc/src/stdio/scanf_core/float_converter.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-//===-- Int type specifier converters for scanf -----------------*- 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/stdio/scanf_core/float_converter.h"
-
-#include "src/__support/CPP/limits.h"
-#include "src/__support/char_vector.h"
-#include "src/__support/ctype_utils.h"
-#include "src/__support/macros/config.h"
-#include "src/stdio/scanf_core/converter_utils.h"
-#include "src/stdio/scanf_core/core_structs.h"
-#include "src/stdio/scanf_core/reader.h"
-
-#include <stddef.h>
-
-namespace LIBC_NAMESPACE_DECL {
-namespace scanf_core {
-
-// All of the floating point conversions are the same for scanf, every name will
-// accept every style.
-int convert_float(Reader *reader, const FormatSection &to_conv) {
- // %a/A/e/E/f/F/g/G "Matches an optionally signed floating-point number,
- // infinity, or NaN, whose format is the same as expected for the subject
- // sequence of the strtod function. The corresponding argument shall be a
- // pointer to floating."
-
- CharVector out_str = CharVector();
- bool is_number = false;
-
- size_t max_width = cpp::numeric_limits<size_t>::max();
- if (to_conv.max_width > 0) {
- max_width = to_conv.max_width;
- }
-
- char cur_char = reader->getc();
- // Handle the sign.
- if (cur_char == '+' || cur_char == '-') {
- if (!...
[truncated]
|
This PR currently also includes support for |
@michaelrj-google Do you have any opinion on keeping |
This allows specializing the implementation for different targets without including unnecessary logic and is similar to llvm#111559 which did the same for printf Writer interface.
5c75b13
to
2610f9a
Compare
This uses the templatized scanf Reader interface introduced in llvm#131037.
I moved the baremetal implementation of |
@@ -26,78 +26,5 @@ | |||
namespace LIBC_NAMESPACE_DECL { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this file can be deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
libc/src/stdio/scanf_core/reader.h
Outdated
class Reader { | ||
ReadBuffer *rb; | ||
void *input_stream = nullptr; | ||
// TODO: We should be able to fold ReadBuffer into Reader. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about this:
template <typename Derived> class Reader {
size_t cur_chars_read = 0;
public:
// This returns the next character from the input and advances it by one
// character. When it hits the end of the string or file it returns '\0' to
// signal to stop parsing.
LIBC_INLINE char getc() {
++cur_chars_read;
return static_cast<Derived *>(this)->getc();
}
// This moves the input back by one character, placing c into the buffer if
// this is a file reader, else c is ignored.
LIBC_INLINE void ungetc(char c) {
--cur_chars_read;
static_cast<Derived *>(this)->ungetc(c);
}
LIBC_INLINE size_t chars_read() { return cur_chars_read; }
};
class StringReader : public Reader<StringReader> {
const char *buffer;
[[maybe_unused]] size_t buff_len;
size_t buff_cur = 0;
public:
LIBC_INLINE StringReader(const char *buffer, size_t buff_len)
: buffer(buffer), buff_len(buff_len) {}
LIBC_INLINE char getc() {
char output = buffer[buff_cur];
++buff_cur;
return output;
}
LIBC_INLINE void ungetc(int) {
if (buff_cur > 0) {
// While technically c should be written back to the buffer, in scanf we
// always write the character that was already there. Additionally, the
// buffer is most likely to contain a string that isn't part of a file,
// which may not be writable.
--buff_cur;
}
}
};
I'm fine with merging them in this way since the subclass already needs to track state, so making it fully static wouldn't work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
class StreamBuffer : public ReadBuffer<StreamBuffer> { | ||
::FILE *stream; | ||
|
||
public: | ||
LIBC_INLINE StreamBuffer(::FILE *stream) : stream(stream) {} | ||
|
||
LIBC_INLINE char getc() { | ||
return static_cast<char>(internal::getc(static_cast<FILE *>(stream))); | ||
} | ||
LIBC_INLINE void ungetc(int c) { | ||
internal::ungetc(c, static_cast<FILE *>(stream)); | ||
} | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to also add a dynamic dispatch reader that stores a union of StringReader
and StreamReader
so to make that simpler I'd like to move each reader subclass into its own file.
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/10/builds/1542 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/73/builds/14781 Here is the relevant piece of the build log for the reference
|
This uses the templatized scanf Reader interface introduced in #131037.
This allows specializing the implementation for different targets without including unnecessary logic and is similar to #111559 which did the same for printf Writer interface.