1//===-- Unittests for the scanf Parser -----------------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#include "src/__support/CPP/bit.h"
10#include "src/__support/CPP/bitset.h"
11#include "src/__support/CPP/string_view.h"
12#include "src/__support/arg_list.h"
13#include "src/stdio/scanf_core/parser.h"
14
15#include <stdarg.h>
16
17#include "test/UnitTest/ScanfMatcher.h"
18#include "test/UnitTest/Test.h"
19
20using LIBC_NAMESPACE::cpp::string_view;
21using LIBC_NAMESPACE::internal::ArgList;
22
23void init(const char *__restrict str, ...) {
24 va_list vlist;
25 va_start(vlist, str);
26 ArgList v(vlist);
27 va_end(vlist);
28
29 LIBC_NAMESPACE::scanf_core::Parser<ArgList> parser(str, v);
30}
31
32void evaluate(LIBC_NAMESPACE::scanf_core::FormatSection *format_arr,
33 const char *__restrict str, ...) {
34 va_list vlist;
35 va_start(vlist, str);
36 LIBC_NAMESPACE::internal::ArgList v(vlist);
37 va_end(vlist);
38
39 LIBC_NAMESPACE::scanf_core::Parser<ArgList> parser(str, v);
40
41 for (auto cur_section = parser.get_next_section();
42 !cur_section.raw_string.empty();
43 cur_section = parser.get_next_section()) {
44 *format_arr = cur_section;
45 ++format_arr;
46 }
47}
48
49TEST(LlvmLibcScanfParserTest, Constructor) { init(str: "test", 1, 2); }
50
51TEST(LlvmLibcScanfParserTest, EvalRaw) {
52 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
53 const char *str = "test";
54 evaluate(format_arr, str);
55
56 LIBC_NAMESPACE::scanf_core::FormatSection expected;
57 expected.has_conv = false;
58
59 expected.raw_string = str;
60
61 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
62 // TODO: add checks that the format_arr after the last one has length 0
63}
64
65TEST(LlvmLibcScanfParserTest, EvalSimple) {
66 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
67 const char *str = "test %% test";
68 evaluate(format_arr, str);
69
70 LIBC_NAMESPACE::scanf_core::FormatSection expected0, expected1, expected2;
71 expected0.has_conv = false;
72
73 expected0.raw_string = {str, 5};
74
75 ASSERT_SFORMAT_EQ(expected0, format_arr[0]);
76
77 expected1.has_conv = true;
78
79 expected1.raw_string = {str + 5, 2};
80 expected1.conv_name = '%';
81
82 ASSERT_SFORMAT_EQ(expected1, format_arr[1]);
83
84 expected2.has_conv = false;
85
86 expected2.raw_string = {str + 7, 5};
87
88 ASSERT_SFORMAT_EQ(expected2, format_arr[2]);
89}
90
91TEST(LlvmLibcScanfParserTest, EvalOneArg) {
92 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
93 const char *str = "%d";
94 int arg1 = 12345;
95 evaluate(format_arr, str, &arg1);
96
97 LIBC_NAMESPACE::scanf_core::FormatSection expected;
98 expected.has_conv = true;
99
100 expected.raw_string = str;
101 expected.output_ptr = &arg1;
102 expected.conv_name = 'd';
103
104 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
105}
106
107TEST(LlvmLibcScanfParserTest, EvalBadArg) {
108 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
109 const char *str = "%\0abc";
110 int arg1 = 12345;
111 evaluate(format_arr, str, &arg1);
112
113 LIBC_NAMESPACE::scanf_core::FormatSection expected;
114 expected.has_conv = false;
115 expected.raw_string = {str, 1};
116
117 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
118}
119
120TEST(LlvmLibcScanfParserTest, EvalOneArgWithFlag) {
121 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
122 const char *str = "%*d";
123 // Since NO_WRITE is set, the argument shouldn't be used, but I've included
124 // one anyways because in the case that it doesn't work it's better for it to
125 // have a real argument to check against.
126 int arg1 = 12345;
127 evaluate(format_arr, str, &arg1);
128
129 LIBC_NAMESPACE::scanf_core::FormatSection expected;
130 expected.has_conv = true;
131
132 expected.raw_string = str;
133 expected.flags = LIBC_NAMESPACE::scanf_core::FormatFlags::NO_WRITE;
134 expected.conv_name = 'd';
135
136 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
137
138 // If NO_WRITE is set, then the equality check ignores the pointer since it's
139 // irrelevant, but in this case I want to make sure that it hasn't been set
140 // and check it separately.
141 ASSERT_EQ(expected.output_ptr, format_arr[0].output_ptr);
142}
143
144TEST(LlvmLibcScanfParserTest, EvalOneArgWithWidth) {
145 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
146 const char *str = "%12d";
147 int arg1 = 12345;
148 evaluate(format_arr, str, &arg1);
149
150 LIBC_NAMESPACE::scanf_core::FormatSection expected;
151 expected.has_conv = true;
152
153 expected.raw_string = str;
154 expected.max_width = 12;
155 expected.output_ptr = &arg1;
156 expected.conv_name = 'd';
157
158 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
159}
160
161TEST(LlvmLibcScanfParserTest, EvalOneArgWithShortLengthModifier) {
162 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
163 const char *str = "%hd";
164 int arg1 = 12345;
165 evaluate(format_arr, str, &arg1);
166
167 LIBC_NAMESPACE::scanf_core::FormatSection expected;
168 expected.has_conv = true;
169
170 expected.raw_string = str;
171 expected.length_modifier = LIBC_NAMESPACE::scanf_core::LengthModifier::h;
172 expected.output_ptr = &arg1;
173 expected.conv_name = 'd';
174
175 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
176}
177
178TEST(LlvmLibcScanfParserTest, EvalOneArgWithLongLengthModifier) {
179 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
180 const char *str = "%lld";
181 long long arg1 = 12345;
182 evaluate(format_arr, str, &arg1);
183
184 LIBC_NAMESPACE::scanf_core::FormatSection expected;
185 expected.has_conv = true;
186
187 expected.raw_string = str;
188 expected.length_modifier = LIBC_NAMESPACE::scanf_core::LengthModifier::ll;
189 expected.output_ptr = &arg1;
190 expected.conv_name = 'd';
191
192 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
193}
194
195TEST(LlvmLibcScanfParserTest, EvalOneArgWithAllOptions) {
196 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
197 const char *str = "%*56jd";
198 intmax_t arg1 = 12345;
199 evaluate(format_arr, str, &arg1);
200
201 LIBC_NAMESPACE::scanf_core::FormatSection expected;
202 expected.has_conv = true;
203
204 expected.raw_string = str;
205 expected.flags = LIBC_NAMESPACE::scanf_core::FormatFlags::NO_WRITE;
206 expected.max_width = 56;
207 expected.length_modifier = LIBC_NAMESPACE::scanf_core::LengthModifier::j;
208 expected.conv_name = 'd';
209
210 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
211}
212
213TEST(LlvmLibcScanfParserTest, EvalSimpleBracketArg) {
214 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
215 const char *str = "%[abc]";
216 char arg1 = 'a';
217 evaluate(format_arr, str, &arg1);
218
219 LIBC_NAMESPACE::scanf_core::FormatSection expected;
220 expected.has_conv = true;
221
222 expected.raw_string = str;
223 expected.conv_name = '[';
224 expected.output_ptr = &arg1;
225
226 LIBC_NAMESPACE::cpp::bitset<256> scan_set;
227
228 scan_set.set('a');
229 scan_set.set('b');
230 scan_set.set('c');
231
232 expected.scan_set = scan_set;
233
234 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
235}
236
237TEST(LlvmLibcScanfParserTest, EvalBracketArgRange) {
238 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
239 const char *str = "%[A-D]";
240 char arg1 = 'a';
241 evaluate(format_arr, str, &arg1);
242
243 LIBC_NAMESPACE::scanf_core::FormatSection expected;
244 expected.has_conv = true;
245
246 expected.raw_string = str;
247 expected.conv_name = '[';
248 expected.output_ptr = &arg1;
249
250 LIBC_NAMESPACE::cpp::bitset<256> scan_set;
251
252 scan_set.set('A');
253 scan_set.set('B');
254 scan_set.set('C');
255 scan_set.set('D');
256
257 expected.scan_set = scan_set;
258
259 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
260}
261
262TEST(LlvmLibcScanfParserTest, EvalBracketArgTwoRanges) {
263 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
264 const char *str = "%[A-De-g]";
265 char arg1 = 'a';
266 evaluate(format_arr, str, &arg1);
267
268 LIBC_NAMESPACE::scanf_core::FormatSection expected;
269 expected.has_conv = true;
270
271 expected.raw_string = str;
272 expected.conv_name = '[';
273 expected.output_ptr = &arg1;
274
275 LIBC_NAMESPACE::cpp::bitset<256> scan_set;
276
277 scan_set.set('A');
278 scan_set.set('B');
279 scan_set.set('C');
280 scan_set.set('D');
281 scan_set.set_range(Start: 'e', End: 'g');
282
283 expected.scan_set = scan_set;
284
285 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
286}
287
288TEST(LlvmLibcScanfParserTest, EvalBracketArgJustHyphen) {
289 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
290 const char *str = "%[-]";
291 char arg1 = 'a';
292 evaluate(format_arr, str, &arg1);
293
294 LIBC_NAMESPACE::scanf_core::FormatSection expected;
295 expected.has_conv = true;
296
297 expected.raw_string = str;
298 expected.conv_name = '[';
299 expected.output_ptr = &arg1;
300
301 LIBC_NAMESPACE::cpp::bitset<256> scan_set;
302
303 scan_set.set('-');
304
305 expected.scan_set = scan_set;
306
307 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
308}
309
310TEST(LlvmLibcScanfParserTest, EvalBracketArgLeftHyphen) {
311 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
312 const char *str = "%[-A]";
313 char arg1 = 'a';
314 evaluate(format_arr, str, &arg1);
315
316 LIBC_NAMESPACE::scanf_core::FormatSection expected;
317 expected.has_conv = true;
318
319 expected.raw_string = str;
320 expected.conv_name = '[';
321 expected.output_ptr = &arg1;
322
323 LIBC_NAMESPACE::cpp::bitset<256> scan_set;
324
325 scan_set.set('-');
326 scan_set.set('A');
327
328 expected.scan_set = scan_set;
329
330 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
331}
332
333TEST(LlvmLibcScanfParserTest, EvalBracketArgRightHyphen) {
334 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
335 const char *str = "%[Z-]";
336 char arg1 = 'a';
337 evaluate(format_arr, str, &arg1);
338
339 LIBC_NAMESPACE::scanf_core::FormatSection expected;
340 expected.has_conv = true;
341
342 expected.raw_string = str;
343 expected.conv_name = '[';
344 expected.output_ptr = &arg1;
345
346 LIBC_NAMESPACE::cpp::bitset<256> scan_set;
347
348 scan_set.set('-');
349 scan_set.set('Z');
350
351 expected.scan_set = scan_set;
352
353 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
354}
355
356TEST(LlvmLibcScanfParserTest, EvalBracketArgInvertSimple) {
357 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
358 const char *str = "%[^abc]";
359 char arg1 = 'a';
360 evaluate(format_arr, str, &arg1);
361
362 LIBC_NAMESPACE::scanf_core::FormatSection expected;
363 expected.has_conv = true;
364
365 expected.raw_string = str;
366 expected.conv_name = '[';
367 expected.output_ptr = &arg1;
368
369 LIBC_NAMESPACE::cpp::bitset<256> scan_set;
370
371 scan_set.set('a');
372 scan_set.set('b');
373 scan_set.set('c');
374 scan_set.flip();
375
376 expected.scan_set = scan_set;
377
378 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
379}
380
381TEST(LlvmLibcScanfParserTest, EvalBracketArgInvertRange) {
382 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
383 const char *str = "%[^0-9]";
384 char arg1 = 'a';
385 evaluate(format_arr, str, &arg1);
386
387 LIBC_NAMESPACE::scanf_core::FormatSection expected;
388 expected.has_conv = true;
389
390 expected.raw_string = str;
391 expected.conv_name = '[';
392 expected.output_ptr = &arg1;
393
394 LIBC_NAMESPACE::cpp::bitset<256> scan_set;
395
396 scan_set.set_range(Start: '0', End: '9');
397 scan_set.flip();
398
399 expected.scan_set = scan_set;
400
401 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
402}
403
404TEST(LlvmLibcScanfParserTest, EvalBracketArgRightBracket) {
405 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
406 const char *str = "%[]]";
407 char arg1 = 'a';
408 evaluate(format_arr, str, &arg1);
409
410 LIBC_NAMESPACE::scanf_core::FormatSection expected;
411 expected.has_conv = true;
412
413 expected.raw_string = str;
414 expected.conv_name = '[';
415 expected.output_ptr = &arg1;
416
417 LIBC_NAMESPACE::cpp::bitset<256> scan_set;
418
419 scan_set.set(']');
420
421 expected.scan_set = scan_set;
422
423 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
424}
425
426TEST(LlvmLibcScanfParserTest, EvalBracketArgRightBracketRange) {
427 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
428 const char *str = "%[]-a]";
429 char arg1 = 'a';
430 evaluate(format_arr, str, &arg1);
431
432 LIBC_NAMESPACE::scanf_core::FormatSection expected;
433 expected.has_conv = true;
434
435 expected.raw_string = str;
436 expected.conv_name = '[';
437 expected.output_ptr = &arg1;
438
439 LIBC_NAMESPACE::cpp::bitset<256> scan_set;
440
441 scan_set.set_range(Start: ']', End: 'a');
442
443 expected.scan_set = scan_set;
444
445 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
446}
447
448TEST(LlvmLibcScanfParserTest, EvalBracketArgRightBracketInvert) {
449 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
450 const char *str = "%[^]]";
451 char arg1 = 'a';
452 evaluate(format_arr, str, &arg1);
453
454 LIBC_NAMESPACE::scanf_core::FormatSection expected;
455 expected.has_conv = true;
456
457 expected.raw_string = str;
458 expected.conv_name = '[';
459 expected.output_ptr = &arg1;
460
461 LIBC_NAMESPACE::cpp::bitset<256> scan_set;
462
463 scan_set.set(']');
464 scan_set.flip();
465
466 expected.scan_set = scan_set;
467
468 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
469}
470
471TEST(LlvmLibcScanfParserTest, EvalBracketArgRightBracketInvertRange) {
472 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
473 const char *str = "%[^]-^]";
474 char arg1 = 'a';
475 evaluate(format_arr, str, &arg1);
476
477 LIBC_NAMESPACE::scanf_core::FormatSection expected;
478 expected.has_conv = true;
479
480 expected.raw_string = str;
481 expected.conv_name = '[';
482 expected.output_ptr = &arg1;
483
484 LIBC_NAMESPACE::cpp::bitset<256> scan_set;
485
486 scan_set.set_range(Start: ']', End: '^');
487 scan_set.flip();
488
489 expected.scan_set = scan_set;
490
491 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
492}
493
494// This is not part of the standard, but the hyphen's effect is always
495// implementation defined, and I have defined it such that it will capture the
496// correct range regardless of the order of the characters.
497TEST(LlvmLibcScanfParserTest, EvalBracketArgBackwardsRange) {
498 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
499 const char *str = "%[9-0]";
500 char arg1 = 'a';
501 evaluate(format_arr, str, &arg1);
502
503 LIBC_NAMESPACE::scanf_core::FormatSection expected;
504 expected.has_conv = true;
505
506 expected.raw_string = str;
507 expected.conv_name = '[';
508 expected.output_ptr = &arg1;
509
510 LIBC_NAMESPACE::cpp::bitset<256> scan_set;
511
512 scan_set.set_range(Start: '0', End: '9');
513
514 expected.scan_set = scan_set;
515
516 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
517}
518
519TEST(LlvmLibcScanfParserTest, EvalThreeArgs) {
520 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
521 const char *str = "%d%f%s";
522 int arg1 = 12345;
523 double arg2 = 123.45;
524 const char *arg3 = "12345";
525 evaluate(format_arr, str, &arg1, &arg2, &arg3);
526
527 LIBC_NAMESPACE::scanf_core::FormatSection expected0, expected1, expected2;
528 expected0.has_conv = true;
529
530 expected0.raw_string = {str, 2};
531 expected0.output_ptr = &arg1;
532 expected0.conv_name = 'd';
533
534 ASSERT_SFORMAT_EQ(expected0, format_arr[0]);
535
536 expected1.has_conv = true;
537
538 expected1.raw_string = {str + 2, 2};
539 expected1.output_ptr = &arg2;
540 expected1.conv_name = 'f';
541
542 ASSERT_SFORMAT_EQ(expected1, format_arr[1]);
543
544 expected2.has_conv = true;
545
546 expected2.raw_string = {str + 4, 2};
547 expected2.output_ptr = &arg3;
548 expected2.conv_name = 's';
549
550 ASSERT_SFORMAT_EQ(expected2, format_arr[2]);
551}
552
553#ifndef LIBC_COPT_SCANF_DISABLE_INDEX_MODE
554
555TEST(LlvmLibcScanfParserTest, IndexModeOneArg) {
556 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
557 const char *str = "%1$d";
558 int arg1 = 12345;
559 evaluate(format_arr, str, &arg1);
560
561 LIBC_NAMESPACE::scanf_core::FormatSection expected;
562 expected.has_conv = true;
563
564 expected.raw_string = {str, 4};
565 expected.output_ptr = &arg1;
566 expected.conv_name = 'd';
567
568 ASSERT_SFORMAT_EQ(expected, format_arr[0]);
569}
570
571TEST(LlvmLibcScanfParserTest, IndexModeThreeArgsSequential) {
572 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
573 const char *str = "%1$d%2$f%3$s";
574 int arg1 = 12345;
575 double arg2 = 123.45;
576 const char *arg3 = "12345";
577 evaluate(format_arr, str, &arg1, &arg2, &arg3);
578
579 LIBC_NAMESPACE::scanf_core::FormatSection expected0, expected1, expected2;
580 expected0.has_conv = true;
581
582 expected0.raw_string = {str, 4};
583 expected0.output_ptr = &arg1;
584 expected0.conv_name = 'd';
585
586 ASSERT_SFORMAT_EQ(expected0, format_arr[0]);
587
588 expected1.has_conv = true;
589
590 expected1.raw_string = {str + 4, 4};
591 expected1.output_ptr = &arg2;
592 expected1.conv_name = 'f';
593
594 ASSERT_SFORMAT_EQ(expected1, format_arr[1]);
595
596 expected2.has_conv = true;
597
598 expected2.raw_string = {str + 8, 4};
599 expected2.output_ptr = &arg3;
600 expected2.conv_name = 's';
601
602 ASSERT_SFORMAT_EQ(expected2, format_arr[2]);
603}
604
605TEST(LlvmLibcScanfParserTest, IndexModeThreeArgsReverse) {
606 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
607 const char *str = "%3$d%2$f%1$s";
608 int arg1 = 12345;
609 double arg2 = 123.45;
610 const char *arg3 = "12345";
611 evaluate(format_arr, str, &arg3, &arg2, &arg1);
612
613 LIBC_NAMESPACE::scanf_core::FormatSection expected0, expected1, expected2;
614 expected0.has_conv = true;
615
616 expected0.raw_string = {str, 4};
617 expected0.output_ptr = &arg1;
618 expected0.conv_name = 'd';
619
620 ASSERT_SFORMAT_EQ(expected0, format_arr[0]);
621
622 expected1.has_conv = true;
623
624 expected1.raw_string = {str + 4, 4};
625 expected1.output_ptr = &arg2;
626 expected1.conv_name = 'f';
627
628 ASSERT_SFORMAT_EQ(expected1, format_arr[1]);
629
630 expected2.has_conv = true;
631
632 expected2.raw_string = {str + 8, 4};
633 expected2.output_ptr = &arg3;
634 expected2.conv_name = 's';
635
636 ASSERT_SFORMAT_EQ(expected2, format_arr[2]);
637}
638
639TEST(LlvmLibcScanfParserTest, IndexModeTenArgsRandom) {
640 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[10];
641 const char *str = "%6$d%3$d%7$d%2$d%8$d%1$d%4$d%9$d%5$d%10$d";
642 uintptr_t args[10] = {6, 4, 2, 7, 9, 1, 3, 5, 8, 10};
643 evaluate(format_arr, str, args[0], args[1], args[2], args[3], args[4],
644 args[5], args[6], args[7], args[8], args[9]);
645
646 for (size_t i = 0; i < 10; ++i) {
647 LIBC_NAMESPACE::scanf_core::FormatSection expected;
648 expected.has_conv = true;
649
650 expected.raw_string = {str + (4 * i),
651 static_cast<size_t>(4 + (i >= 9 ? 1 : 0))};
652 expected.output_ptr = reinterpret_cast<void *>(i + 1);
653 expected.conv_name = 'd';
654 EXPECT_SFORMAT_EQ(expected, format_arr[i]);
655 }
656}
657
658TEST(LlvmLibcScanfParserTest, IndexModeComplexParsing) {
659 LIBC_NAMESPACE::scanf_core::FormatSection format_arr[11];
660 const char *str = "normal text %3$llu %% %2$*f %4$d %1$1c%5$[123]";
661 char arg1 = '1';
662 double arg2 = 123.45;
663 unsigned long long arg3 = 12345;
664 int arg4 = 10;
665 char arg5 = 'A';
666 evaluate(format_arr, str, &arg1, &arg2, &arg3, &arg4, &arg5);
667
668 LIBC_NAMESPACE::scanf_core::FormatSection expected0, expected1, expected2,
669 expected3, expected4, expected5, expected6, expected7, expected8,
670 expected9, expected10;
671
672 expected0.has_conv = false;
673
674 // "normal text "
675 expected0.raw_string = {str, 12};
676
677 EXPECT_SFORMAT_EQ(expected0, format_arr[0]);
678
679 expected1.has_conv = true;
680 // "%3$llu"
681 expected1.raw_string = {str + 12, 6};
682 expected1.length_modifier = LIBC_NAMESPACE::scanf_core::LengthModifier::ll;
683 expected1.output_ptr = &arg3;
684 expected1.conv_name = 'u';
685
686 EXPECT_SFORMAT_EQ(expected1, format_arr[1]);
687
688 expected2.has_conv = false;
689 // " "
690 expected2.raw_string = {str + 18, 1};
691
692 EXPECT_SFORMAT_EQ(expected2, format_arr[2]);
693
694 expected3.has_conv = true;
695 // "%%"
696 expected3.raw_string = {str + 19, 2};
697 expected3.conv_name = '%';
698
699 EXPECT_SFORMAT_EQ(expected3, format_arr[3]);
700
701 expected4.has_conv = false;
702 // " "
703 expected4.raw_string = {str + 21, 1};
704
705 EXPECT_SFORMAT_EQ(expected4, format_arr[4]);
706
707 expected5.has_conv = true;
708 // "%2$*f"
709 expected5.raw_string = {str + 22, 5};
710 expected5.flags = LIBC_NAMESPACE::scanf_core::FormatFlags::NO_WRITE;
711 expected5.conv_name = 'f';
712
713 EXPECT_SFORMAT_EQ(expected5, format_arr[5]);
714
715 expected6.has_conv = false;
716 // " "
717 expected6.raw_string = {str + 27, 1};
718
719 EXPECT_SFORMAT_EQ(expected6, format_arr[6]);
720
721 expected7.has_conv = true;
722
723 // "%4$d"
724 expected7.raw_string = {str + 28, 4};
725 expected7.output_ptr = &arg4;
726 expected7.conv_name = 'd';
727
728 EXPECT_SFORMAT_EQ(expected7, format_arr[7]);
729
730 expected8.has_conv = false;
731 // " "
732 expected8.raw_string = {str + 32, 1};
733
734 EXPECT_SFORMAT_EQ(expected8, format_arr[8]);
735
736 expected9.has_conv = true;
737 // "%1$1c"
738 expected9.raw_string = {str + 33, 5};
739 expected9.max_width = 1;
740 expected9.output_ptr = &arg1;
741 expected9.conv_name = 'c';
742
743 EXPECT_SFORMAT_EQ(expected9, format_arr[9]);
744
745 expected10.has_conv = true;
746 // "%5$[123]"
747 expected10.raw_string = {str + 38, 8};
748 expected10.output_ptr = &arg5;
749 expected10.conv_name = '[';
750
751 LIBC_NAMESPACE::cpp::bitset<256> scan_set;
752
753 scan_set.set_range(Start: '1', End: '3');
754
755 expected10.scan_set = scan_set;
756
757 EXPECT_SFORMAT_EQ(expected10, format_arr[10]);
758}
759
760#endif // LIBC_COPT_SCANF_DISABLE_INDEX_MODE
761

source code of libc/test/src/stdio/scanf_core/parser_test.cpp