1 //===-- Unittests for the basic scanf converters --------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "src/__support/CPP/string_view.h"
10 #include "src/stdio/scanf_core/converter.h"
11 #include "src/stdio/scanf_core/core_structs.h"
12 #include "src/stdio/scanf_core/reader.h"
13 #include "src/stdio/scanf_core/string_reader.h"
15 #include "test/UnitTest/Test.h"
17 TEST(LlvmLibcScanfConverterTest
, RawMatchBasic
) {
18 const char *str
= "abcdef";
19 __llvm_libc::scanf_core::StringReader
str_reader(str
);
20 __llvm_libc::scanf_core::Reader
reader(&str_reader
);
22 // Reading "abc" should succeed.
23 ASSERT_EQ(__llvm_libc::scanf_core::raw_match(&reader
, "abc"),
24 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
25 ASSERT_EQ(reader
.chars_read(), size_t(3));
27 // Reading nothing should succeed and not advance.
28 ASSERT_EQ(__llvm_libc::scanf_core::raw_match(&reader
, ""),
29 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
30 ASSERT_EQ(reader
.chars_read(), size_t(3));
32 // Reading a space where there is none should succeed and not advance.
33 ASSERT_EQ(__llvm_libc::scanf_core::raw_match(&reader
, " "),
34 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
35 ASSERT_EQ(reader
.chars_read(), size_t(3));
37 // Reading "d" should succeed and advance by 1.
38 ASSERT_EQ(__llvm_libc::scanf_core::raw_match(&reader
, "d"),
39 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
40 ASSERT_EQ(reader
.chars_read(), size_t(4));
42 // Reading "z" should fail and not advance.
43 ASSERT_EQ(__llvm_libc::scanf_core::raw_match(&reader
, "z"),
44 static_cast<int>(__llvm_libc::scanf_core::MATCHING_FAILURE
));
45 ASSERT_EQ(reader
.chars_read(), size_t(4));
47 // Reading "efgh" should fail but advance to the end.
48 ASSERT_EQ(__llvm_libc::scanf_core::raw_match(&reader
, "efgh"),
49 static_cast<int>(__llvm_libc::scanf_core::MATCHING_FAILURE
));
50 ASSERT_EQ(reader
.chars_read(), size_t(6));
53 TEST(LlvmLibcScanfConverterTest
, RawMatchSpaces
) {
54 const char *str
= " a \t\n b cd";
55 __llvm_libc::scanf_core::StringReader
str_reader(str
);
56 __llvm_libc::scanf_core::Reader
reader(&str_reader
);
58 // Reading "a" should fail and not advance.
59 // Since there's nothing in the format string (the second argument to
60 // raw_match) to match the space in the buffer it isn't consumed.
61 ASSERT_EQ(__llvm_libc::scanf_core::raw_match(&reader
, "a"),
62 static_cast<int>(__llvm_libc::scanf_core::MATCHING_FAILURE
));
63 ASSERT_EQ(reader
.chars_read(), size_t(0));
65 // Reading " \t\n " should succeed and advance past the space.
66 // Any number of space characters in the format string match 0 or more space
67 // characters in the buffer.
68 ASSERT_EQ(__llvm_libc::scanf_core::raw_match(&reader
, " \t\n "),
69 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
70 ASSERT_EQ(reader
.chars_read(), size_t(1));
72 // Reading "ab" should fail and only advance past the a
73 // The a characters match, but the format string doesn't have anything to
74 // consume the spaces in the buffer, so it fails.
75 ASSERT_EQ(__llvm_libc::scanf_core::raw_match(&reader
, "ab"),
76 static_cast<int>(__llvm_libc::scanf_core::MATCHING_FAILURE
));
77 ASSERT_EQ(reader
.chars_read(), size_t(2));
79 // Reading " b" should succeed and advance past the b
80 // Any number of space characters in the format string matches 0 or more space
81 // characters in the buffer.
82 ASSERT_EQ(__llvm_libc::scanf_core::raw_match(&reader
, " b"),
83 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
84 ASSERT_EQ(reader
.chars_read(), size_t(7));
86 // Reading "\t" should succeed and advance past the spaces to the c
87 ASSERT_EQ(__llvm_libc::scanf_core::raw_match(&reader
, "\t"),
88 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
89 ASSERT_EQ(reader
.chars_read(), size_t(10));
91 // Reading "c d" should succeed and advance past the d.
92 // Here the space character in the format string is matching 0 space
93 // characters in the buffer.
94 ASSERT_EQ(__llvm_libc::scanf_core::raw_match(&reader
, "c d"),
95 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
96 ASSERT_EQ(reader
.chars_read(), size_t(12));
99 TEST(LlvmLibcScanfConverterTest
, StringConvSimple
) {
100 const char *str
= "abcDEF123 654LKJihg";
102 __llvm_libc::scanf_core::StringReader
str_reader(str
);
103 __llvm_libc::scanf_core::Reader
reader(&str_reader
);
105 __llvm_libc::scanf_core::FormatSection conv
;
106 conv
.has_conv
= true;
107 conv
.conv_name
= 's';
108 conv
.output_ptr
= result
;
110 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
111 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
112 ASSERT_EQ(reader
.chars_read(), size_t(9));
113 ASSERT_STREQ(result
, "abcDEF123");
115 //%s skips all spaces before beginning to read.
116 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
117 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
118 ASSERT_EQ(reader
.chars_read(), size_t(19));
119 ASSERT_STREQ(result
, "654LKJihg");
122 TEST(LlvmLibcScanfConverterTest
, StringConvNoWrite
) {
123 const char *str
= "abcDEF123 654LKJihg";
124 __llvm_libc::scanf_core::StringReader
str_reader(str
);
125 __llvm_libc::scanf_core::Reader
reader(&str_reader
);
127 __llvm_libc::scanf_core::FormatSection conv
;
128 conv
.has_conv
= true;
129 conv
.conv_name
= 's';
130 conv
.flags
= __llvm_libc::scanf_core::NO_WRITE
;
132 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
133 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
134 ASSERT_EQ(reader
.chars_read(), size_t(9));
136 //%s skips all spaces before beginning to read.
137 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
138 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
139 ASSERT_EQ(reader
.chars_read(), size_t(19));
142 TEST(LlvmLibcScanfConverterTest
, StringConvWidth
) {
143 const char *str
= "abcDEF123 654LKJihg";
145 __llvm_libc::scanf_core::StringReader
str_reader(str
);
146 __llvm_libc::scanf_core::Reader
reader(&str_reader
);
148 __llvm_libc::scanf_core::FormatSection conv
;
149 conv
.has_conv
= true;
150 conv
.conv_name
= 's';
151 conv
.max_width
= 5; // this means the result takes up 6 characters (with \0).
152 conv
.output_ptr
= result
;
154 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
155 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
156 ASSERT_EQ(reader
.chars_read(), size_t(5));
157 ASSERT_STREQ(result
, "abcDE");
159 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
160 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
161 ASSERT_EQ(reader
.chars_read(), size_t(9));
162 ASSERT_STREQ(result
, "F123");
164 //%s skips all spaces before beginning to read.
165 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
166 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
167 ASSERT_EQ(reader
.chars_read(), size_t(15));
168 ASSERT_STREQ(result
, "654LK");
170 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
171 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
172 ASSERT_EQ(reader
.chars_read(), size_t(19));
173 ASSERT_STREQ(result
, "Jihg");
176 TEST(LlvmLibcScanfConverterTest
, CharsConv
) {
177 const char *str
= "abcDEF123 654LKJihg MNOpqr&*(";
179 __llvm_libc::scanf_core::StringReader
str_reader(str
);
180 __llvm_libc::scanf_core::Reader
reader(&str_reader
);
182 __llvm_libc::scanf_core::FormatSection conv
;
183 conv
.has_conv
= true;
184 conv
.conv_name
= 'c';
185 conv
.output_ptr
= result
;
187 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
188 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
189 ASSERT_EQ(reader
.chars_read(), size_t(1));
190 ASSERT_EQ(result
[0], 'a');
192 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
193 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
194 ASSERT_EQ(reader
.chars_read(), size_t(2));
195 ASSERT_EQ(result
[0], 'b');
197 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
198 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
199 ASSERT_EQ(reader
.chars_read(), size_t(3));
200 ASSERT_EQ(result
[0], 'c');
202 // Switch from character by character to 8 at a time.
204 __llvm_libc::cpp::string_view
result_view(result
, 8);
206 //%c doesn't stop on spaces.
207 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
208 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
209 ASSERT_EQ(reader
.chars_read(), size_t(11));
210 ASSERT_EQ(result_view
, __llvm_libc::cpp::string_view("DEF123 6", 8));
212 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
213 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
214 ASSERT_EQ(reader
.chars_read(), size_t(19));
215 ASSERT_EQ(result_view
, __llvm_libc::cpp::string_view("54LKJihg", 8));
217 //%c also doesn't skip spaces at the start.
218 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
219 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
220 ASSERT_EQ(reader
.chars_read(), size_t(27));
221 ASSERT_EQ(result_view
, __llvm_libc::cpp::string_view(" MNOpqr&", 8));
223 //%c will stop on a null byte though.
224 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
225 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
226 ASSERT_EQ(reader
.chars_read(), size_t(29));
227 ASSERT_EQ(__llvm_libc::cpp::string_view(result
, 2),
228 __llvm_libc::cpp::string_view("*(", 2));
231 TEST(LlvmLibcScanfConverterTest
, ScansetConv
) {
232 const char *str
= "abcDEF[123] 654LKJihg";
234 __llvm_libc::scanf_core::StringReader
str_reader(str
);
235 __llvm_libc::scanf_core::Reader
reader(&str_reader
);
237 __llvm_libc::scanf_core::FormatSection conv
;
238 conv
.has_conv
= true;
239 conv
.conv_name
= '[';
240 conv
.output_ptr
= result
;
242 __llvm_libc::cpp::bitset
<256> bitset1
;
243 bitset1
.set_range('a', 'c');
244 bitset1
.set_range('D', 'F');
245 bitset1
.set_range('1', '6');
249 conv
.scan_set
= bitset1
;
251 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
252 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
253 ASSERT_EQ(reader
.chars_read(), size_t(11));
254 ASSERT_EQ(__llvm_libc::cpp::string_view(result
, 11),
255 __llvm_libc::cpp::string_view("abcDEF[123]", 11));
257 // The scanset conversion doesn't consume leading spaces. If it did it would
258 // return "654" here.
259 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
260 static_cast<int>(__llvm_libc::scanf_core::MATCHING_FAILURE
));
261 ASSERT_EQ(reader
.chars_read(), size_t(11));
263 // This set is everything except for a-g.
264 __llvm_libc::cpp::bitset
<256> bitset2
;
265 bitset2
.set_range('a', 'g');
267 conv
.scan_set
= bitset2
;
271 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
272 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
273 ASSERT_EQ(reader
.chars_read(), size_t(16));
274 ASSERT_EQ(__llvm_libc::cpp::string_view(result
, 5),
275 __llvm_libc::cpp::string_view(" 654L", 5));
277 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
278 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
279 ASSERT_EQ(reader
.chars_read(), size_t(20));
280 ASSERT_EQ(__llvm_libc::cpp::string_view(result
, 4),
281 __llvm_libc::cpp::string_view("KJih", 4));
283 // This set is g and '\0'.
284 __llvm_libc::cpp::bitset
<256> bitset3
;
287 conv
.scan_set
= bitset3
;
289 // Even though '\0' is in the scanset, it should still stop on it.
290 ASSERT_EQ(__llvm_libc::scanf_core::convert(&reader
, conv
),
291 static_cast<int>(__llvm_libc::scanf_core::READ_OK
));
292 ASSERT_EQ(reader
.chars_read(), size_t(21));
293 ASSERT_EQ(__llvm_libc::cpp::string_view(result
, 1),
294 __llvm_libc::cpp::string_view("g", 1));