Skip to content

Commit 2610f9a

Browse files
committed
[libc] Templatize the scanf Reader interface
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.
1 parent be0215d commit 2610f9a

20 files changed

+714
-833
lines changed

libc/src/stdio/scanf_core/CMakeLists.txt

+2-10
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
@@ -87,14 +85,8 @@ add_header_library(
8785
${use_system_file}
8886
)
8987

90-
add_object_library(
88+
add_header_library(
9189
converter
92-
SRCS
93-
converter.cpp
94-
string_converter.cpp
95-
int_converter.cpp
96-
float_converter.cpp
97-
ptr_converter.cpp
9890
HDRS
9991
converter.h
10092
converter_utils.h

libc/src/stdio/scanf_core/converter.cpp

-73
Original file line numberDiff line numberDiff line change
@@ -26,78 +26,5 @@
2626
namespace LIBC_NAMESPACE_DECL {
2727
namespace scanf_core {
2828

29-
int convert(Reader *reader, const FormatSection &to_conv) {
30-
int ret_val = 0;
31-
switch (to_conv.conv_name) {
32-
case '%':
33-
return raw_match(reader, "%");
34-
case 's':
35-
ret_val = raw_match(reader, " ");
36-
if (ret_val != READ_OK)
37-
return ret_val;
38-
return convert_string(reader, to_conv);
39-
case 'c':
40-
case '[':
41-
return convert_string(reader, to_conv);
42-
case 'd':
43-
case 'i':
44-
case 'u':
45-
case 'o':
46-
case 'x':
47-
case 'X':
48-
ret_val = raw_match(reader, " ");
49-
if (ret_val != READ_OK)
50-
return ret_val;
51-
return convert_int(reader, to_conv);
52-
#ifndef LIBC_COPT_SCANF_DISABLE_FLOAT
53-
case 'f':
54-
case 'F':
55-
case 'e':
56-
case 'E':
57-
case 'a':
58-
case 'A':
59-
case 'g':
60-
case 'G':
61-
ret_val = raw_match(reader, " ");
62-
if (ret_val != READ_OK)
63-
return ret_val;
64-
return convert_float(reader, to_conv);
65-
#endif // LIBC_COPT_SCANF_DISABLE_FLOAT
66-
case 'n':
67-
return convert_current_pos(reader, to_conv);
68-
case 'p':
69-
ret_val = raw_match(reader, " ");
70-
if (ret_val != READ_OK)
71-
return ret_val;
72-
return convert_pointer(reader, to_conv);
73-
default:
74-
return raw_match(reader, to_conv.raw_string);
75-
}
76-
return -1;
77-
}
78-
79-
// raw_string is assumed to have a positive size.
80-
int raw_match(Reader *reader, cpp::string_view raw_string) {
81-
char cur_char = reader->getc();
82-
int ret_val = READ_OK;
83-
for (size_t i = 0; i < raw_string.size(); ++i) {
84-
// Any space character matches any number of space characters.
85-
if (internal::isspace(raw_string[i])) {
86-
while (internal::isspace(cur_char)) {
87-
cur_char = reader->getc();
88-
}
89-
} else {
90-
if (raw_string[i] == cur_char) {
91-
cur_char = reader->getc();
92-
} else {
93-
ret_val = MATCHING_FAILURE;
94-
break;
95-
}
96-
}
97-
}
98-
reader->ungetc(cur_char);
99-
return ret_val;
100-
}
101-
10229
} // namespace scanf_core
10330
} // namespace LIBC_NAMESPACE_DECL

libc/src/stdio/scanf_core/converter.h

+81-2
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

+2-1
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)