Skip to content

Commit 1fbfef9

Browse files
authored
[libc] Templatize the scanf Reader interface (#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.
1 parent 4781941 commit 1fbfef9

23 files changed

+732
-880
lines changed

libc/src/stdio/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ add_entrypoint_object(
117117
sscanf.h
118118
DEPENDS
119119
libc.src.__support.arg_list
120-
libc.src.stdio.scanf_core.reader
121120
libc.src.stdio.scanf_core.scanf_main
121+
libc.src.stdio.scanf_core.string_reader
122122
)
123123

124124
add_entrypoint_object(
@@ -129,8 +129,8 @@ add_entrypoint_object(
129129
vsscanf.h
130130
DEPENDS
131131
libc.src.__support.arg_list
132-
libc.src.stdio.scanf_core.reader
133132
libc.src.stdio.scanf_core.scanf_main
133+
libc.src.stdio.scanf_core.string_reader
134134
)
135135

136136
add_entrypoint_object(

libc/src/stdio/scanf_core/CMakeLists.txt

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,8 @@ if(NOT(TARGET libc.src.__support.File.file) AND LLVM_LIBC_FULL_BUILD AND
6161
return()
6262
endif()
6363

64-
add_object_library(
64+
add_header_library(
6565
scanf_main
66-
SRCS
67-
scanf_main.cpp
6866
HDRS
6967
scanf_main.h
7068
DEPENDS
@@ -83,18 +81,19 @@ add_header_library(
8381
reader.h
8482
DEPENDS
8583
libc.src.__support.macros.attributes
86-
${file_deps}
87-
${use_system_file}
8884
)
8985

90-
add_object_library(
86+
add_header_library(
87+
string_reader
88+
HDRS
89+
string_reader.h
90+
DEPENDS
91+
.reader
92+
libc.src.__support.macros.attributes
93+
)
94+
95+
add_header_library(
9196
converter
92-
SRCS
93-
converter.cpp
94-
string_converter.cpp
95-
int_converter.cpp
96-
float_converter.cpp
97-
ptr_converter.cpp
9897
HDRS
9998
converter.h
10099
converter_utils.h

libc/src/stdio/scanf_core/converter.cpp

Lines changed: 0 additions & 103 deletions
This file was deleted.

libc/src/stdio/scanf_core/converter.h

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,19 @@
1010
#define LLVM_LIBC_SRC_STDIO_SCANF_CORE_CONVERTER_H
1111

1212
#include "src/__support/CPP/string_view.h"
13+
#include "src/__support/ctype_utils.h"
1314
#include "src/__support/macros/config.h"
1415
#include "src/stdio/scanf_core/core_structs.h"
1516
#include "src/stdio/scanf_core/reader.h"
1617

18+
#ifndef LIBC_COPT_SCANF_DISABLE_FLOAT
19+
#include "src/stdio/scanf_core/float_converter.h"
20+
#endif // LIBC_COPT_SCANF_DISABLE_FLOAT
21+
#include "src/stdio/scanf_core/current_pos_converter.h"
22+
#include "src/stdio/scanf_core/int_converter.h"
23+
#include "src/stdio/scanf_core/ptr_converter.h"
24+
#include "src/stdio/scanf_core/string_converter.h"
25+
1726
#include <stddef.h>
1827

1928
namespace LIBC_NAMESPACE_DECL {
@@ -22,11 +31,81 @@ namespace scanf_core {
2231
// convert will call a conversion function to convert the FormatSection into
2332
// its string representation, and then that will write the result to the
2433
// reader.
25-
int convert(Reader *reader, const FormatSection &to_conv);
34+
template <typename T>
35+
int convert(Reader<T> *reader, const FormatSection &to_conv) {
36+
int ret_val = 0;
37+
switch (to_conv.conv_name) {
38+
case '%':
39+
return raw_match(reader, "%");
40+
case 's':
41+
ret_val = raw_match(reader, " ");
42+
if (ret_val != READ_OK)
43+
return ret_val;
44+
return convert_string(reader, to_conv);
45+
case 'c':
46+
case '[':
47+
return convert_string(reader, to_conv);
48+
case 'd':
49+
case 'i':
50+
case 'u':
51+
case 'o':
52+
case 'x':
53+
case 'X':
54+
ret_val = raw_match(reader, " ");
55+
if (ret_val != READ_OK)
56+
return ret_val;
57+
return convert_int(reader, to_conv);
58+
#ifndef LIBC_COPT_SCANF_DISABLE_FLOAT
59+
case 'f':
60+
case 'F':
61+
case 'e':
62+
case 'E':
63+
case 'a':
64+
case 'A':
65+
case 'g':
66+
case 'G':
67+
ret_val = raw_match(reader, " ");
68+
if (ret_val != READ_OK)
69+
return ret_val;
70+
return convert_float(reader, to_conv);
71+
#endif // LIBC_COPT_SCANF_DISABLE_FLOAT
72+
case 'n':
73+
return convert_current_pos(reader, to_conv);
74+
case 'p':
75+
ret_val = raw_match(reader, " ");
76+
if (ret_val != READ_OK)
77+
return ret_val;
78+
return convert_pointer(reader, to_conv);
79+
default:
80+
return raw_match(reader, to_conv.raw_string);
81+
}
82+
return -1;
83+
}
2684

2785
// raw_match takes a raw string and matches it to the characters obtained from
2886
// the reader.
29-
int raw_match(Reader *reader, cpp::string_view raw_string);
87+
template <typename T>
88+
int raw_match(Reader<T> *reader, cpp::string_view raw_string) {
89+
char cur_char = reader->getc();
90+
int ret_val = READ_OK;
91+
for (size_t i = 0; i < raw_string.size(); ++i) {
92+
// Any space character matches any number of space characters.
93+
if (internal::isspace(raw_string[i])) {
94+
while (internal::isspace(cur_char)) {
95+
cur_char = reader->getc();
96+
}
97+
} else {
98+
if (raw_string[i] == cur_char) {
99+
cur_char = reader->getc();
100+
} else {
101+
ret_val = MATCHING_FAILURE;
102+
break;
103+
}
104+
}
105+
}
106+
reader->ungetc(cur_char);
107+
return ret_val;
108+
}
30109

31110
} // namespace scanf_core
32111
} // namespace LIBC_NAMESPACE_DECL

libc/src/stdio/scanf_core/current_pos_converter.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
namespace LIBC_NAMESPACE_DECL {
2020
namespace scanf_core {
2121

22-
LIBC_INLINE int convert_current_pos(Reader *reader,
22+
template <typename T>
23+
LIBC_INLINE int convert_current_pos(Reader<T> *reader,
2324
const FormatSection &to_conv) {
2425
write_int_with_length(reader->chars_read(), to_conv);
2526
return READ_OK;

0 commit comments

Comments
 (0)