Line data Source code
1 : // Copyright (c) 2023-2024 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/snapdev
4 : // contact@m2osw.com
5 : //
6 : // This program is free software: you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation, either version 3 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License
17 : // along with this program. If not, see <https://www.gnu.org/licenses/>.
18 :
19 : /** \file
20 : * \brief Verify that the tokenize_format functions & traits work.
21 : *
22 : * This file implements tests for the tokenize_format functions and
23 : * traits for printf(3) and strftime(3).
24 : */
25 :
26 : // self
27 : //
28 : #include <snapdev/tokenize_format.h>
29 :
30 : #include "catch_main.h"
31 :
32 :
33 : // last include
34 : //
35 : #include <snapdev/poison.h>
36 :
37 :
38 : namespace
39 : {
40 :
41 :
42 :
43 : constexpr char const * const g_printf_letters = "diouxXeEfFgGaAcsCSpnm";
44 :
45 :
46 : struct printf_size_t
47 : {
48 : char const * const f_flag = nullptr;
49 : snapdev::format_flag_t const f_length = snapdev::FORMAT_FLAG_NONE;
50 : };
51 :
52 : constexpr printf_size_t const g_printf_sizes[] = {
53 : {
54 : "",
55 : snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_INT,
56 : },
57 : {
58 : "hh",
59 : snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_CHAR,
60 : },
61 : {
62 : "h",
63 : snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_SHORT,
64 : },
65 : {
66 : "l",
67 : snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG,
68 : },
69 : {
70 : "ll",
71 : snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG,
72 : },
73 : {
74 : "q",
75 : snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG,
76 : },
77 : {
78 : "L",
79 : snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_DOUBLE,
80 : },
81 : {
82 : "j",
83 : snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_INTMAX_T,
84 : },
85 : {
86 : "z",
87 : snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_SIZE_T,
88 : },
89 : {
90 : "Z",
91 : snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_SIZE_T,
92 : },
93 : {
94 : "t",
95 : snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_PTRDFF_T,
96 : },
97 : };
98 :
99 :
100 :
101 : struct printf_result_t
102 : {
103 : snapdev::format_error_set_t f_errors = {};
104 : char const * const f_string = nullptr;
105 : snapdev::format_flag_t const f_flags = snapdev::FORMAT_FLAG_NONE;
106 : int f_width = snapdev::format_item<char>::NUMBER_UNDEFINED;
107 : int f_precision = snapdev::format_item<char>::NUMBER_UNDEFINED;
108 : int f_position = snapdev::format_item<char>::NUMBER_UNDEFINED;
109 : char f_format = '\0';
110 : };
111 :
112 : struct printf_formats_t
113 : {
114 : char const * const f_format_string = nullptr;
115 : std::list<printf_result_t> f_results = {};
116 : };
117 :
118 : printf_formats_t const g_printf_formats[] =
119 : {
120 : {
121 : .f_format_string = "Data Driven %% Tests",
122 : .f_results = {
123 : {
124 : .f_string = "Data Driven ",
125 : },
126 : {
127 : .f_string = "%",
128 : },
129 : {
130 : .f_string = " Tests",
131 : },
132 : },
133 : },
134 : {
135 : .f_format_string = "Position %32$i Only",
136 : .f_results = {
137 : {
138 : .f_string = "Position ",
139 : },
140 : {
141 : .f_string = "%32$i", // for now this keeps the original...
142 : .f_position = 32,
143 : .f_format = 'd',
144 : },
145 : {
146 : .f_string = " Only",
147 : },
148 : },
149 : },
150 : {
151 : .f_format_string = "Width %72d Only",
152 : .f_results = {
153 : {
154 : .f_string = "Width ",
155 : },
156 : {
157 : .f_string = "%72d",
158 : .f_width = 72,
159 : .f_format = 'd',
160 : },
161 : {
162 : .f_string = " Only",
163 : },
164 : },
165 : },
166 : {
167 : .f_format_string = "Precision %l.l23x Only",
168 : .f_results = {
169 : {
170 : .f_string = "Precision ",
171 : },
172 : {
173 : .f_string = "%l.l23x",
174 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG,
175 : .f_precision = 23,
176 : .f_format = 'x',
177 : },
178 : {
179 : .f_string = " Only",
180 : },
181 : },
182 : },
183 : {
184 : .f_format_string = "Width/Precision/Position %4$72.41lX Mix",
185 : .f_results = {
186 : {
187 : .f_string = "Width/Precision/Position ",
188 : },
189 : {
190 : .f_string = "%4$72.41lX",
191 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG,
192 : .f_width = 72,
193 : .f_precision = 41,
194 : .f_position = 4,
195 : .f_format = 'X',
196 : },
197 : {
198 : .f_string = " Mix",
199 : },
200 : },
201 : },
202 : {
203 : .f_format_string = "Width/Precision %*.h*u Dynamic",
204 : .f_results = {
205 : {
206 : .f_string = "Width/Precision ",
207 : },
208 : {
209 : .f_string = "%*.h*u",
210 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_SHORT,
211 : .f_width = 0,
212 : .f_precision = 0,
213 : .f_format = 'u',
214 : },
215 : {
216 : .f_string = " Dynamic",
217 : },
218 : },
219 : },
220 : {
221 : .f_format_string = "Position/Width/Precision %h*3$.*5$h1$o Ultra Dynamic",
222 : .f_results = {
223 : {
224 : .f_string = "Position/Width/Precision ",
225 : },
226 : {
227 : .f_string = "%h*3$.*5$h1$o",
228 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_CHAR,
229 : .f_width = -3,
230 : .f_precision = -5,
231 : .f_position = 1,
232 : .f_format = 'o',
233 : },
234 : {
235 : .f_string = " Ultra Dynamic",
236 : },
237 : },
238 : },
239 : {
240 : .f_format_string = "Space Sign %7$ q*8$.*2$f Flag",
241 : .f_results = {
242 : {
243 : .f_string = "Space Sign ",
244 : },
245 : {
246 : .f_string = "%7$ q*8$.*2$f",
247 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG
248 : | snapdev::printf_flag_traits<char>::FORMAT_FLAG_SPACE_SIGN,
249 : .f_width = -8,
250 : .f_precision = -2,
251 : .f_position = 7,
252 : .f_format = 'f',
253 : },
254 : {
255 : .f_string = " Flag",
256 : },
257 : },
258 : },
259 : {
260 : .f_format_string = "Left Adjusted %10000$-q*8$.*2$f Flag",
261 : .f_results = {
262 : {
263 : .f_string = "Left Adjusted ",
264 : },
265 : {
266 : .f_string = "%10000$-q*8$.*2$f",
267 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG
268 : | snapdev::printf_flag_traits<char>::FORMAT_FLAG_LEFT_ADJUSTED,
269 : .f_width = -8,
270 : .f_precision = -2,
271 : .f_position = 10000,
272 : .f_format = 'f',
273 : },
274 : {
275 : .f_string = " Flag",
276 : },
277 : },
278 : },
279 : {
280 : .f_format_string = "Alternate Form %1$#*10000$.*5$C Flag",
281 : .f_results = {
282 : {
283 : .f_string = "Alternate Form ",
284 : },
285 : {
286 : .f_string = "%1$#*10000$.*5$C",
287 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG
288 : | snapdev::printf_flag_traits<char>::FORMAT_FLAG_ALTERNATE_FORM,
289 : .f_width = -10000,
290 : .f_precision = -5,
291 : .f_position = 1,
292 : .f_format = 'c',
293 : },
294 : {
295 : .f_string = " Flag",
296 : },
297 : },
298 : },
299 : {
300 : .f_format_string = "Show Sign %1$301.*10000$+S Flag",
301 : .f_results = {
302 : {
303 : .f_string = "Show Sign ",
304 : },
305 : {
306 : .f_string = "%1$301.*10000$+S",
307 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG
308 : | snapdev::printf_flag_traits<char>::FORMAT_FLAG_SHOW_SIGN,
309 : .f_width = 301,
310 : .f_precision = -10000,
311 : .f_position = 1,
312 : .f_format = 's',
313 : },
314 : {
315 : .f_string = " Flag",
316 : },
317 : },
318 : },
319 : {
320 : .f_format_string = "Grouping %'1$301.*31$S Flag",
321 : .f_results = {
322 : {
323 : .f_string = "Grouping ",
324 : },
325 : {
326 : .f_string = "%'1$301.*31$S",
327 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG
328 : | snapdev::printf_flag_traits<char>::FORMAT_FLAG_GROUPING,
329 : .f_width = 301,
330 : .f_precision = -31,
331 : .f_position = 1,
332 : .f_format = 's',
333 : },
334 : {
335 : .f_string = " Flag",
336 : },
337 : },
338 : },
339 : {
340 : .f_format_string = "Alternate Digits %2$307.I*41$zG Flag",
341 : .f_results = {
342 : {
343 : .f_string = "Alternate Digits ",
344 : },
345 : {
346 : .f_string = "%2$307.I*41$zG",
347 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_SIZE_T
348 : | snapdev::printf_flag_traits<char>::FORMAT_FLAG_ALTERNATE_DIGITS,
349 : .f_width = 307,
350 : .f_precision = -41,
351 : .f_position = 2,
352 : .f_format = 'G',
353 : },
354 : {
355 : .f_string = " Flag",
356 : },
357 : },
358 : },
359 : {
360 : .f_format_string = "Error %--e Duplicate",
361 : .f_results = {
362 : {
363 : .f_string = "Error ",
364 : },
365 : {
366 : .f_errors = {
367 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
368 : },
369 : .f_string = "%--e",
370 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LEFT_ADJUSTED,
371 : .f_format = 'e',
372 : },
373 : {
374 : .f_string = " Duplicate",
375 : },
376 : },
377 : },
378 : {
379 : .f_format_string = "Error % E Duplicate",
380 : .f_results = {
381 : {
382 : .f_string = "Error ",
383 : },
384 : {
385 : .f_errors = {
386 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
387 : },
388 : .f_string = "% E",
389 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_SPACE_SIGN,
390 : .f_format = 'E',
391 : },
392 : {
393 : .f_string = " Duplicate",
394 : },
395 : },
396 : },
397 : {
398 : .f_format_string = "Error %##G Duplicate",
399 : .f_results = {
400 : {
401 : .f_string = "Error ",
402 : },
403 : {
404 : .f_errors = {
405 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
406 : },
407 : .f_string = "%##G",
408 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_ALTERNATE_FORM,
409 : .f_format = 'G',
410 : },
411 : {
412 : .f_string = " Duplicate",
413 : },
414 : },
415 : },
416 : {
417 : .f_format_string = "Error %++f Duplicate",
418 : .f_results = {
419 : {
420 : .f_string = "Error ",
421 : },
422 : {
423 : .f_errors = {
424 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
425 : },
426 : .f_string = "%++f",
427 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_SHOW_SIGN,
428 : .f_format = 'f',
429 : },
430 : {
431 : .f_string = " Duplicate",
432 : },
433 : },
434 : },
435 : {
436 : .f_format_string = "Error %''F Duplicate",
437 : .f_results = {
438 : {
439 : .f_string = "Error ",
440 : },
441 : {
442 : .f_errors = {
443 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
444 : },
445 : .f_string = "%''F",
446 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_GROUPING,
447 : .f_format = 'F',
448 : },
449 : {
450 : .f_string = " Duplicate",
451 : },
452 : },
453 : },
454 : {
455 : .f_format_string = "Error %IIA Duplicate",
456 : .f_results = {
457 : {
458 : .f_string = "Error ",
459 : },
460 : {
461 : .f_errors = {
462 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
463 : },
464 : .f_string = "%IIA",
465 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_ALTERNATE_DIGITS,
466 : .f_format = 'A',
467 : },
468 : {
469 : .f_string = " Duplicate",
470 : },
471 : },
472 : },
473 : {
474 : .f_format_string = "Unknown Format %h*Y Error",
475 : .f_results = {
476 : {
477 : .f_string = "Unknown Format ",
478 : },
479 : {
480 : .f_errors = {
481 : snapdev::format_error_t::FORMAT_ERROR_UNKNOWN,
482 : },
483 : .f_string = "%",
484 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_SHORT,
485 : .f_width = 0,
486 : },
487 : {
488 : .f_string = "h*Y Error",
489 : },
490 : },
491 : },
492 : {
493 : .f_format_string = "Duplicated Width %h*h4p Error",
494 : .f_results = {
495 : {
496 : .f_string = "Duplicated Width ",
497 : },
498 : {
499 : .f_errors = {
500 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
501 : },
502 : .f_string = "%h*h4p",
503 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_CHAR,
504 : .f_width = 4,
505 : .f_format = 'p',
506 : },
507 : {
508 : .f_string = " Error",
509 : },
510 : },
511 : },
512 : {
513 : .f_format_string = "Duplicated Width %l4l*n Error",
514 : .f_results = {
515 : {
516 : .f_string = "Duplicated Width ",
517 : },
518 : {
519 : .f_errors = {
520 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
521 : },
522 : .f_string = "%l4l*n",
523 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG,
524 : .f_width = 0,
525 : .f_format = 'n',
526 : },
527 : {
528 : .f_string = " Error",
529 : },
530 : },
531 : },
532 : {
533 : .f_format_string = "Mismatch Widths %*4hhp Error",
534 : .f_results = {
535 : {
536 : .f_string = "Mismatch Widths ",
537 : },
538 : {
539 : .f_errors = {
540 : snapdev::format_error_t::FORMAT_ERROR_MISMATCH,
541 : },
542 : .f_string = "%*4hhp",
543 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_CHAR,
544 : .f_width = 4,
545 : .f_format = 'p',
546 : },
547 : {
548 : .f_string = " Error",
549 : },
550 : },
551 : },
552 : {
553 : .f_format_string = "Lone $ %L$m Error",
554 : .f_results = {
555 : {
556 : .f_string = "Lone $ ",
557 : },
558 : {
559 : .f_errors = {
560 : snapdev::format_error_t::FORMAT_ERROR_SYNTAX,
561 : },
562 : .f_string = "%",
563 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_DOUBLE,
564 : },
565 : {
566 : .f_string = "L$m Error",
567 : },
568 : },
569 : },
570 : {
571 : .f_format_string = "Duplicated Width %.h*h4p Error",
572 : .f_results = {
573 : {
574 : .f_string = "Duplicated Width ",
575 : },
576 : {
577 : .f_errors = {
578 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
579 : },
580 : .f_string = "%.h*h4p",
581 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_CHAR,
582 : .f_precision = 4,
583 : .f_format = 'p',
584 : },
585 : {
586 : .f_string = " Error",
587 : },
588 : },
589 : },
590 : {
591 : .f_format_string = "Duplicated Width %.l4l*n Error",
592 : .f_results = {
593 : {
594 : .f_string = "Duplicated Width ",
595 : },
596 : {
597 : .f_errors = {
598 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
599 : },
600 : .f_string = "%.l4l*n",
601 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG,
602 : .f_precision = 0,
603 : .f_format = 'n',
604 : },
605 : {
606 : .f_string = " Error",
607 : },
608 : },
609 : },
610 : {
611 : .f_format_string = "Mismatch Widths %.*4hhp Error",
612 : .f_results = {
613 : {
614 : .f_string = "Mismatch Widths ",
615 : },
616 : {
617 : .f_errors = {
618 : snapdev::format_error_t::FORMAT_ERROR_MISMATCH,
619 : },
620 : .f_string = "%.*4hhp",
621 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_CHAR,
622 : .f_precision = 4,
623 : .f_format = 'p',
624 : },
625 : {
626 : .f_string = " Error",
627 : },
628 : },
629 : },
630 : {
631 : .f_format_string = "Two Positions %4$1$Zp Error",
632 : .f_results = {
633 : {
634 : .f_string = "Two Positions ",
635 : },
636 : {
637 : .f_errors = {
638 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
639 : },
640 : .f_string = "%4$1$Zp",
641 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_SIZE_T,
642 : .f_position = 1,
643 : .f_format = 'p',
644 : },
645 : {
646 : .f_string = " Error",
647 : },
648 : },
649 : },
650 : {
651 : .f_format_string = "End Of String %z*",
652 : .f_results = {
653 : {
654 : .f_string = "End Of String ",
655 : },
656 : {
657 : .f_errors = {
658 : snapdev::format_error_t::FORMAT_ERROR_EOS,
659 : },
660 : .f_string = "%z*",
661 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_SIZE_T,
662 : .f_width = 0,
663 : },
664 : },
665 : },
666 : {
667 : .f_format_string = "End Of String %.z*",
668 : .f_results = {
669 : {
670 : .f_string = "End Of String ",
671 : },
672 : {
673 : .f_errors = {
674 : snapdev::format_error_t::FORMAT_ERROR_EOS,
675 : },
676 : .f_string = "%.z*",
677 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_SIZE_T,
678 : .f_precision = 0,
679 : },
680 : },
681 : },
682 : {
683 : .f_format_string = "End Of String %1..5zp",
684 : .f_results = {
685 : {
686 : .f_string = "End Of String ",
687 : },
688 : {
689 : .f_errors = {
690 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
691 : },
692 : .f_string = "%1..5zp",
693 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_SIZE_T,
694 : .f_width = 1,
695 : .f_precision = 5,
696 : .f_format = 'p',
697 : },
698 : },
699 : },
700 : {
701 : .f_format_string = "End Of String %10001Lp",
702 : .f_results = {
703 : {
704 : .f_string = "End Of String ",
705 : },
706 : {
707 : .f_errors = {
708 : snapdev::format_error_t::FORMAT_ERROR_OVERFLOW,
709 : },
710 : .f_string = "%10001Lp",
711 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_DOUBLE,
712 : .f_width = 10000,
713 : .f_format = 'p',
714 : },
715 : },
716 : },
717 : {
718 : .f_format_string = "End Of String %1j*a",
719 : .f_results = {
720 : {
721 : .f_string = "End Of String ",
722 : },
723 : {
724 : .f_errors = {
725 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
726 : },
727 : .f_string = "%1j*a",
728 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_INTMAX_T,
729 : .f_width = 0,
730 : .f_format = 'a',
731 : },
732 : },
733 : },
734 : {
735 : .f_format_string = "End Of String %.1j*a",
736 : .f_results = {
737 : {
738 : .f_string = "End Of String ",
739 : },
740 : {
741 : .f_errors = {
742 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
743 : },
744 : .f_string = "%.1j*a",
745 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_INTMAX_T,
746 : .f_precision = 0,
747 : .f_format = 'a',
748 : },
749 : },
750 : },
751 : {
752 : .f_format_string = "End Of String %1j*3$A",
753 : .f_results = {
754 : {
755 : .f_string = "End Of String ",
756 : },
757 : {
758 : .f_errors = {
759 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
760 : },
761 : .f_string = "%1j*3$A",
762 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_INTMAX_T,
763 : .f_width = -3,
764 : .f_format = 'A',
765 : },
766 : },
767 : },
768 : {
769 : .f_format_string = "End Of String %.1j*3$A",
770 : .f_results = {
771 : {
772 : .f_string = "End Of String ",
773 : },
774 : {
775 : .f_errors = {
776 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
777 : },
778 : .f_string = "%.1j*3$A",
779 : .f_flags = snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_INTMAX_T,
780 : .f_precision = -3,
781 : .f_format = 'A',
782 : },
783 : },
784 : },
785 : };
786 :
787 :
788 : printf_formats_t const g_strftime_formats[] =
789 : {
790 : {
791 : .f_format_string = "Data Driven %% Tests",
792 : .f_results = {
793 : {
794 : .f_string = "Data Driven ",
795 : },
796 : {
797 : .f_string = "%",
798 : },
799 : {
800 : .f_string = " Tests",
801 : },
802 : },
803 : },
804 : {
805 : .f_format_string = "Simple %a Code",
806 : .f_results = {
807 : {
808 : .f_string = "Simple ",
809 : },
810 : {
811 : .f_string = "%a",
812 : .f_format = 'a',
813 : },
814 : {
815 : .f_string = " Code",
816 : },
817 : },
818 : },
819 : {
820 : .f_format_string = "Week Day %_A and Space Pad",
821 : .f_results = {
822 : {
823 : .f_string = "Week Day ",
824 : },
825 : {
826 : .f_string = "%_A",
827 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_PAD_WITH_SPACES,
828 : .f_format = 'A',
829 : },
830 : {
831 : .f_string = " and Space Pad",
832 : },
833 : },
834 : },
835 : {
836 : .f_format_string = "Abbr Month %-b without pad",
837 : .f_results = {
838 : {
839 : .f_string = "Abbr Month ",
840 : },
841 : {
842 : .f_string = "%-b",
843 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_NO_PAD,
844 : .f_format = 'b',
845 : },
846 : {
847 : .f_string = " without pad",
848 : },
849 : },
850 : },
851 : {
852 : .f_format_string = "Month %0B Zero Pad",
853 : .f_results = {
854 : {
855 : .f_string = "Month ",
856 : },
857 : {
858 : .f_string = "%0B",
859 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_PAD_WITH_ZEROES,
860 : .f_format = 'B',
861 : },
862 : {
863 : .f_string = " Zero Pad",
864 : },
865 : },
866 : },
867 : {
868 : .f_format_string = "Default Date %^c Uppercase",
869 : .f_results = {
870 : {
871 : .f_string = "Default Date ",
872 : },
873 : {
874 : .f_string = "%^c",
875 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_UPPERCASE,
876 : .f_format = 'c',
877 : },
878 : {
879 : .f_string = " Uppercase",
880 : },
881 : },
882 : },
883 : {
884 : .f_format_string = "Century %#C Swap Case",
885 : .f_results = {
886 : {
887 : .f_string = "Century ",
888 : },
889 : {
890 : .f_string = "%#C",
891 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_SWAP_CASE,
892 : .f_format = 'C',
893 : },
894 : {
895 : .f_string = " Swap Case",
896 : },
897 : },
898 : },
899 : {
900 : .f_format_string = "Day %Od Alternate",
901 : .f_results = {
902 : {
903 : .f_string = "Day ",
904 : },
905 : {
906 : .f_string = "%Od",
907 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_MODIFIER,
908 : .f_format = 'd',
909 : },
910 : {
911 : .f_string = " Alternate",
912 : },
913 : },
914 : },
915 : {
916 : .f_format_string = "Date %_^D Pad/Upper",
917 : .f_results = {
918 : {
919 : .f_string = "Date ",
920 : },
921 : {
922 : .f_string = "%_^D",
923 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_PAD_WITH_SPACES
924 : | snapdev::strftime_flag_traits<char>::FORMAT_FLAG_UPPERCASE,
925 : .f_format = 'D',
926 : },
927 : {
928 : .f_string = " Pad/Upper",
929 : },
930 : },
931 : },
932 : {
933 : .f_format_string = "Alternate Form %-#Oe Flag",
934 : .f_results = {
935 : {
936 : .f_string = "Alternate Form ",
937 : },
938 : {
939 : .f_string = "%-#Oe",
940 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_NO_PAD
941 : | snapdev::strftime_flag_traits<char>::FORMAT_FLAG_SWAP_CASE
942 : | snapdev::strftime_flag_traits<char>::FORMAT_FLAG_MODIFIER,
943 : .f_format = 'e',
944 : },
945 : {
946 : .f_string = " Flag",
947 : },
948 : },
949 : },
950 : {
951 : .f_format_string = "ISO 8601 %^0F Date",
952 : .f_results = {
953 : {
954 : .f_string = "ISO 8601 ",
955 : },
956 : {
957 : .f_string = "%^0F",
958 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_PAD_WITH_ZEROES
959 : | snapdev::strftime_flag_traits<char>::FORMAT_FLAG_UPPERCASE,
960 : .f_format = 'F',
961 : },
962 : {
963 : .f_string = " Date",
964 : },
965 : },
966 : },
967 : {
968 : .f_format_string = "Year %G Based on Week",
969 : .f_results = {
970 : {
971 : .f_string = "Year ",
972 : },
973 : {
974 : .f_string = "%G",
975 : .f_format = 'G',
976 : },
977 : {
978 : .f_string = " Based on Week",
979 : },
980 : },
981 : },
982 : {
983 : .f_format_string = "Small %g Year",
984 : .f_results = {
985 : {
986 : .f_string = "Small ",
987 : },
988 : {
989 : .f_string = "%g",
990 : .f_format = 'g',
991 : },
992 : {
993 : .f_string = " Year",
994 : },
995 : },
996 : },
997 : {
998 : .f_format_string = "Switch to b %--h and Duplicate",
999 : .f_results = {
1000 : {
1001 : .f_string = "Switch to b ",
1002 : },
1003 : {
1004 : .f_errors = {
1005 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
1006 : },
1007 : .f_string = "%--h",
1008 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_NO_PAD,
1009 : .f_format = 'b',
1010 : },
1011 : {
1012 : .f_string = " and Duplicate",
1013 : },
1014 : },
1015 : },
1016 : {
1017 : .f_format_string = "Hour %__H and Duplicate",
1018 : .f_results = {
1019 : {
1020 : .f_string = "Hour ",
1021 : },
1022 : {
1023 : .f_errors = {
1024 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
1025 : },
1026 : .f_string = "%__H",
1027 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_PAD_WITH_SPACES,
1028 : .f_format = 'H',
1029 : },
1030 : {
1031 : .f_string = " and Duplicate",
1032 : },
1033 : },
1034 : },
1035 : {
1036 : .f_format_string = "12h %##I and Duplicate",
1037 : .f_results = {
1038 : {
1039 : .f_string = "12h ",
1040 : },
1041 : {
1042 : .f_errors = {
1043 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
1044 : },
1045 : .f_string = "%##I",
1046 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_SWAP_CASE,
1047 : .f_format = 'I',
1048 : },
1049 : {
1050 : .f_string = " and Duplicate",
1051 : },
1052 : },
1053 : },
1054 : {
1055 : .f_format_string = "Year Day %00j and Duplicate",
1056 : .f_results = {
1057 : {
1058 : .f_string = "Year Day ",
1059 : },
1060 : {
1061 : .f_errors = {
1062 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
1063 : },
1064 : .f_string = "%00j",
1065 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_PAD_WITH_ZEROES,
1066 : .f_format = 'j',
1067 : },
1068 : {
1069 : .f_string = " and Duplicate",
1070 : },
1071 : },
1072 : },
1073 : {
1074 : .f_format_string = "24h %^^k and Duplicate",
1075 : .f_results = {
1076 : {
1077 : .f_string = "24h ",
1078 : },
1079 : {
1080 : .f_errors = {
1081 : snapdev::format_error_t::FORMAT_ERROR_DUPLICATE,
1082 : },
1083 : .f_string = "%^^k",
1084 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_UPPERCASE,
1085 : .f_format = 'k',
1086 : },
1087 : {
1088 : .f_string = " and Duplicate",
1089 : },
1090 : },
1091 : },
1092 : {
1093 : .f_format_string = "12h %_0l and Mismatch",
1094 : .f_results = {
1095 : {
1096 : .f_string = "12h ",
1097 : },
1098 : {
1099 : .f_errors = {
1100 : snapdev::format_error_t::FORMAT_ERROR_MISMATCH,
1101 : },
1102 : .f_string = "%_0l",
1103 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_PAD_WITH_SPACES
1104 : | snapdev::strftime_flag_traits<char>::FORMAT_FLAG_PAD_WITH_ZEROES,
1105 : .f_format = 'l',
1106 : },
1107 : {
1108 : .f_string = " and Mismatch",
1109 : },
1110 : },
1111 : },
1112 : {
1113 : .f_format_string = "Month %0_m Mismatch",
1114 : .f_results = {
1115 : {
1116 : .f_string = "Month ",
1117 : },
1118 : {
1119 : .f_errors = {
1120 : snapdev::format_error_t::FORMAT_ERROR_MISMATCH,
1121 : },
1122 : .f_string = "%0_m",
1123 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_PAD_WITH_SPACES
1124 : | snapdev::strftime_flag_traits<char>::FORMAT_FLAG_PAD_WITH_ZEROES,
1125 : .f_format = 'm',
1126 : },
1127 : {
1128 : .f_string = " Mismatch",
1129 : },
1130 : },
1131 : },
1132 : {
1133 : .f_format_string = "Minutes %_-M and Mismatch",
1134 : .f_results = {
1135 : {
1136 : .f_string = "Minutes ",
1137 : },
1138 : {
1139 : .f_errors = {
1140 : snapdev::format_error_t::FORMAT_ERROR_MISMATCH,
1141 : },
1142 : .f_string = "%_-M",
1143 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_NO_PAD
1144 : | snapdev::strftime_flag_traits<char>::FORMAT_FLAG_PAD_WITH_SPACES,
1145 : .f_format = 'M',
1146 : },
1147 : {
1148 : .f_string = " and Mismatch",
1149 : },
1150 : },
1151 : },
1152 : {
1153 : .f_format_string = "Newline %-_n and Mismatch",
1154 : .f_results = {
1155 : {
1156 : .f_string = "Newline ",
1157 : },
1158 : {
1159 : .f_errors = {
1160 : snapdev::format_error_t::FORMAT_ERROR_MISMATCH,
1161 : },
1162 : .f_string = "%-_n",
1163 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_NO_PAD
1164 : | snapdev::strftime_flag_traits<char>::FORMAT_FLAG_PAD_WITH_SPACES,
1165 : .f_format = 'n',
1166 : },
1167 : {
1168 : .f_string = " and Mismatch",
1169 : },
1170 : },
1171 : },
1172 : {
1173 : .f_format_string = "Nanoseconds %-N (for us)",
1174 : .f_results = {
1175 : {
1176 : .f_string = "Nanoseconds ",
1177 : },
1178 : {
1179 : .f_string = "%-N",
1180 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_NO_PAD,
1181 : .f_format = 'N',
1182 : },
1183 : {
1184 : .f_string = " (for us)",
1185 : },
1186 : },
1187 : },
1188 : {
1189 : .f_format_string = "AM/PM %-0p Mismatch",
1190 : .f_results = {
1191 : {
1192 : .f_string = "AM/PM ",
1193 : },
1194 : {
1195 : .f_errors = {
1196 : snapdev::format_error_t::FORMAT_ERROR_MISMATCH,
1197 : },
1198 : .f_string = "%-0p",
1199 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_NO_PAD
1200 : | snapdev::strftime_flag_traits<char>::FORMAT_FLAG_PAD_WITH_ZEROES,
1201 : .f_format = 'p',
1202 : },
1203 : {
1204 : .f_string = " Mismatch",
1205 : },
1206 : },
1207 : },
1208 : {
1209 : .f_format_string = "am/pm %0-P and Mismatch",
1210 : .f_results = {
1211 : {
1212 : .f_string = "am/pm ",
1213 : },
1214 : {
1215 : .f_errors = {
1216 : snapdev::format_error_t::FORMAT_ERROR_MISMATCH,
1217 : },
1218 : .f_string = "%0-P",
1219 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_NO_PAD
1220 : | snapdev::strftime_flag_traits<char>::FORMAT_FLAG_PAD_WITH_ZEROES,
1221 : .f_format = 'P',
1222 : },
1223 : {
1224 : .f_string = " and Mismatch",
1225 : },
1226 : },
1227 : },
1228 : {
1229 : .f_format_string = "Time %^#r Upper/Flip",
1230 : .f_results = {
1231 : {
1232 : .f_string = "Time ",
1233 : },
1234 : {
1235 : .f_string = "%^#r",
1236 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_UPPERCASE
1237 : | snapdev::strftime_flag_traits<char>::FORMAT_FLAG_SWAP_CASE,
1238 : .f_format = 'r',
1239 : },
1240 : {
1241 : .f_string = " Upper/Flip",
1242 : },
1243 : },
1244 : },
1245 : {
1246 : .f_format_string = "Time %#^r Flip/Upper",
1247 : .f_results = {
1248 : {
1249 : .f_string = "Time ",
1250 : },
1251 : {
1252 : .f_string = "%#^r",
1253 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_UPPERCASE
1254 : | snapdev::strftime_flag_traits<char>::FORMAT_FLAG_SWAP_CASE,
1255 : .f_format = 'r',
1256 : },
1257 : {
1258 : .f_string = " Flip/Upper",
1259 : },
1260 : },
1261 : },
1262 : {
1263 : .f_format_string = "Basic Time %R",
1264 : .f_results = {
1265 : {
1266 : .f_string = "Basic Time ",
1267 : },
1268 : {
1269 : .f_string = "%R",
1270 : .f_format = 'R',
1271 : },
1272 : },
1273 : },
1274 : {
1275 : .f_format_string = "Seconds %s.%EN Nanoseconds",
1276 : .f_results = {
1277 : {
1278 : .f_string = "Seconds ",
1279 : },
1280 : {
1281 : .f_string = "%s",
1282 : .f_format = 's',
1283 : },
1284 : {
1285 : .f_string = ".",
1286 : },
1287 : {
1288 : .f_string = "%EN",
1289 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_EXTENDED,
1290 : .f_format = 'N',
1291 : },
1292 : {
1293 : .f_string = " Nanoseconds",
1294 : },
1295 : },
1296 : },
1297 : {
1298 : .f_format_string = "2-digit seconds %02S no error",
1299 : .f_results = {
1300 : {
1301 : .f_string = "2-digit seconds ",
1302 : },
1303 : {
1304 : .f_string = "%02S",
1305 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_PAD_WITH_ZEROES,
1306 : .f_width = 2,
1307 : .f_format = 'S',
1308 : },
1309 : {
1310 : .f_string = " no error",
1311 : },
1312 : },
1313 : },
1314 : {
1315 : .f_format_string = "Tab %t Char",
1316 : .f_results = {
1317 : {
1318 : .f_string = "Tab ",
1319 : },
1320 : {
1321 : .f_string = "%t",
1322 : .f_format = 't',
1323 : },
1324 : {
1325 : .f_string = " Char",
1326 : },
1327 : },
1328 : },
1329 : {
1330 : .f_format_string = "End Of String %_#^",
1331 : .f_results = {
1332 : {
1333 : .f_string = "End Of String ",
1334 : },
1335 : {
1336 : .f_errors = {
1337 : snapdev::format_error_t::FORMAT_ERROR_EOS,
1338 : },
1339 : .f_string = "%_#^",
1340 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_PAD_WITH_SPACES
1341 : | snapdev::strftime_flag_traits<char>::FORMAT_FLAG_UPPERCASE
1342 : | snapdev::strftime_flag_traits<char>::FORMAT_FLAG_SWAP_CASE,
1343 : },
1344 : },
1345 : },
1346 : {
1347 : .f_format_string = "Time %^5T and EOS %",
1348 : .f_results = {
1349 : {
1350 : .f_string = "Time ",
1351 : },
1352 : {
1353 : .f_string = "%^5T",
1354 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_UPPERCASE,
1355 : .f_width = 5,
1356 : .f_format = 'T',
1357 : },
1358 : {
1359 : .f_string = " and EOS ",
1360 : },
1361 : {
1362 : .f_errors = {
1363 : snapdev::format_error_t::FORMAT_ERROR_EOS,
1364 : },
1365 : .f_string = "%",
1366 : },
1367 : },
1368 : },
1369 : {
1370 : .f_format_string = "%0u Start Of String",
1371 : .f_results = {
1372 : {
1373 : .f_string = "%0u",
1374 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_PAD_WITH_ZEROES,
1375 : .f_format = 'u',
1376 : },
1377 : {
1378 : .f_string = " Start Of String",
1379 : },
1380 : },
1381 : },
1382 : {
1383 : .f_format_string = "%U%10V%w",
1384 : .f_results = {
1385 : {
1386 : .f_string = "%U",
1387 : .f_format = 'U',
1388 : },
1389 : {
1390 : .f_string = "%10V",
1391 : .f_width = 10,
1392 : .f_format = 'V',
1393 : },
1394 : {
1395 : .f_string = "%w",
1396 : .f_format = 'w',
1397 : },
1398 : },
1399 : },
1400 : {
1401 : .f_format_string = "without%Wspaces",
1402 : .f_results = {
1403 : {
1404 : .f_string = "without",
1405 : },
1406 : {
1407 : .f_string = "%W",
1408 : .f_format = 'W',
1409 : },
1410 : {
1411 : .f_string = "spaces",
1412 : },
1413 : },
1414 : },
1415 : {
1416 : .f_format_string = "Unknown %q Error",
1417 : .f_results = {
1418 : {
1419 : .f_string = "Unknown ",
1420 : },
1421 : {
1422 : .f_errors = {
1423 : snapdev::format_error_t::FORMAT_ERROR_UNKNOWN,
1424 : },
1425 : .f_string = "%",
1426 : },
1427 : {
1428 : .f_string = "q Error",
1429 : },
1430 : },
1431 : },
1432 : {
1433 : .f_format_string = "No %3.4z Separator",
1434 : .f_results = {
1435 : {
1436 : .f_string = "No ",
1437 : },
1438 : {
1439 : .f_errors = {
1440 : snapdev::format_error_t::FORMAT_ERROR_UNKNOWN,
1441 : },
1442 : .f_string = "%",
1443 : .f_width = 3,
1444 : },
1445 : {
1446 : .f_string = "3.4z Separator",
1447 : },
1448 : },
1449 : },
1450 : {
1451 : .f_format_string = "Date %x Only",
1452 : .f_results = {
1453 : {
1454 : .f_string = "Date ",
1455 : },
1456 : {
1457 : .f_string = "%x",
1458 : .f_format = 'x',
1459 : },
1460 : {
1461 : .f_string = " Only",
1462 : },
1463 : },
1464 : },
1465 : {
1466 : .f_format_string = "Time %X Only",
1467 : .f_results = {
1468 : {
1469 : .f_string = "Time ",
1470 : },
1471 : {
1472 : .f_string = "%X",
1473 : .f_format = 'X',
1474 : },
1475 : {
1476 : .f_string = " Only",
1477 : },
1478 : },
1479 : },
1480 : {
1481 : .f_format_string = "Year %y without century",
1482 : .f_results = {
1483 : {
1484 : .f_string = "Year ",
1485 : },
1486 : {
1487 : .f_string = "%y",
1488 : .f_format = 'y',
1489 : },
1490 : {
1491 : .f_string = " without century",
1492 : },
1493 : },
1494 : },
1495 : {
1496 : .f_format_string = "Full %Y year",
1497 : .f_results = {
1498 : {
1499 : .f_string = "Full ",
1500 : },
1501 : {
1502 : .f_string = "%Y",
1503 : .f_format = 'Y',
1504 : },
1505 : {
1506 : .f_string = " year",
1507 : },
1508 : },
1509 : },
1510 : {
1511 : .f_format_string = "Zone %z (numeric)",
1512 : .f_results = {
1513 : {
1514 : .f_string = "Zone ",
1515 : },
1516 : {
1517 : .f_string = "%z",
1518 : .f_format = 'z',
1519 : },
1520 : {
1521 : .f_string = " (numeric)",
1522 : },
1523 : },
1524 : },
1525 : {
1526 : .f_format_string = "Zone %Z (abbr)",
1527 : .f_results = {
1528 : {
1529 : .f_string = "Zone ",
1530 : },
1531 : {
1532 : .f_string = "%Z",
1533 : .f_format = 'Z',
1534 : },
1535 : {
1536 : .f_string = " (abbr)",
1537 : },
1538 : },
1539 : },
1540 : {
1541 : .f_format_string = "date(1) %+ format",
1542 : .f_results = {
1543 : {
1544 : .f_string = "date(1) ",
1545 : },
1546 : {
1547 : .f_string = "%+",
1548 : .f_format = '+',
1549 : },
1550 : {
1551 : .f_string = " format",
1552 : },
1553 : },
1554 : },
1555 : {
1556 : .f_format_string = "extended %Ec format",
1557 : .f_results = {
1558 : {
1559 : .f_string = "extended ",
1560 : },
1561 : {
1562 : .f_string = "%Ec",
1563 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_EXTENDED,
1564 : .f_format = 'c',
1565 : },
1566 : {
1567 : .f_string = " format",
1568 : },
1569 : },
1570 : },
1571 : {
1572 : .f_format_string = "extended %EC format",
1573 : .f_results = {
1574 : {
1575 : .f_string = "extended ",
1576 : },
1577 : {
1578 : .f_string = "%EC",
1579 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_EXTENDED,
1580 : .f_format = 'C',
1581 : },
1582 : {
1583 : .f_string = " format",
1584 : },
1585 : },
1586 : },
1587 : {
1588 : .f_format_string = "extended %Ex format",
1589 : .f_results = {
1590 : {
1591 : .f_string = "extended ",
1592 : },
1593 : {
1594 : .f_string = "%Ex",
1595 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_EXTENDED,
1596 : .f_format = 'x',
1597 : },
1598 : {
1599 : .f_string = " format",
1600 : },
1601 : },
1602 : },
1603 : {
1604 : .f_format_string = "extended %EX format",
1605 : .f_results = {
1606 : {
1607 : .f_string = "extended ",
1608 : },
1609 : {
1610 : .f_string = "%EX",
1611 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_EXTENDED,
1612 : .f_format = 'X',
1613 : },
1614 : {
1615 : .f_string = " format",
1616 : },
1617 : },
1618 : },
1619 : {
1620 : .f_format_string = "extended %Ey format",
1621 : .f_results = {
1622 : {
1623 : .f_string = "extended ",
1624 : },
1625 : {
1626 : .f_string = "%Ey",
1627 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_EXTENDED,
1628 : .f_format = 'y',
1629 : },
1630 : {
1631 : .f_string = " format",
1632 : },
1633 : },
1634 : },
1635 : {
1636 : .f_format_string = "extended %EY format",
1637 : .f_results = {
1638 : {
1639 : .f_string = "extended ",
1640 : },
1641 : {
1642 : .f_string = "%EY",
1643 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_EXTENDED,
1644 : .f_format = 'Y',
1645 : },
1646 : {
1647 : .f_string = " format",
1648 : },
1649 : },
1650 : },
1651 : {
1652 : .f_format_string = "modified %Od format",
1653 : .f_results = {
1654 : {
1655 : .f_string = "modified ",
1656 : },
1657 : {
1658 : .f_string = "%Od",
1659 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_MODIFIER,
1660 : .f_format = 'd',
1661 : },
1662 : {
1663 : .f_string = " format",
1664 : },
1665 : },
1666 : },
1667 : {
1668 : .f_format_string = "modified %Oe format",
1669 : .f_results = {
1670 : {
1671 : .f_string = "modified ",
1672 : },
1673 : {
1674 : .f_string = "%Oe",
1675 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_MODIFIER,
1676 : .f_format = 'e',
1677 : },
1678 : {
1679 : .f_string = " format",
1680 : },
1681 : },
1682 : },
1683 : {
1684 : .f_format_string = "modified %OH format",
1685 : .f_results = {
1686 : {
1687 : .f_string = "modified ",
1688 : },
1689 : {
1690 : .f_string = "%OH",
1691 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_MODIFIER,
1692 : .f_format = 'H',
1693 : },
1694 : {
1695 : .f_string = " format",
1696 : },
1697 : },
1698 : },
1699 : {
1700 : .f_format_string = "modified %OI format",
1701 : .f_results = {
1702 : {
1703 : .f_string = "modified ",
1704 : },
1705 : {
1706 : .f_string = "%OI",
1707 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_MODIFIER,
1708 : .f_format = 'I',
1709 : },
1710 : {
1711 : .f_string = " format",
1712 : },
1713 : },
1714 : },
1715 : {
1716 : .f_format_string = "modified %Om format",
1717 : .f_results = {
1718 : {
1719 : .f_string = "modified ",
1720 : },
1721 : {
1722 : .f_string = "%Om",
1723 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_MODIFIER,
1724 : .f_format = 'm',
1725 : },
1726 : {
1727 : .f_string = " format",
1728 : },
1729 : },
1730 : },
1731 : {
1732 : .f_format_string = "modified %OM format",
1733 : .f_results = {
1734 : {
1735 : .f_string = "modified ",
1736 : },
1737 : {
1738 : .f_string = "%OM",
1739 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_MODIFIER,
1740 : .f_format = 'M',
1741 : },
1742 : {
1743 : .f_string = " format",
1744 : },
1745 : },
1746 : },
1747 : {
1748 : .f_format_string = "modified %OS format",
1749 : .f_results = {
1750 : {
1751 : .f_string = "modified ",
1752 : },
1753 : {
1754 : .f_string = "%OS",
1755 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_MODIFIER,
1756 : .f_format = 'S',
1757 : },
1758 : {
1759 : .f_string = " format",
1760 : },
1761 : },
1762 : },
1763 : {
1764 : .f_format_string = "modified %Ou format",
1765 : .f_results = {
1766 : {
1767 : .f_string = "modified ",
1768 : },
1769 : {
1770 : .f_string = "%Ou",
1771 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_MODIFIER,
1772 : .f_format = 'u',
1773 : },
1774 : {
1775 : .f_string = " format",
1776 : },
1777 : },
1778 : },
1779 : {
1780 : .f_format_string = "modified %OU format",
1781 : .f_results = {
1782 : {
1783 : .f_string = "modified ",
1784 : },
1785 : {
1786 : .f_string = "%OU",
1787 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_MODIFIER,
1788 : .f_format = 'U',
1789 : },
1790 : {
1791 : .f_string = " format",
1792 : },
1793 : },
1794 : },
1795 : {
1796 : .f_format_string = "modified %OV format",
1797 : .f_results = {
1798 : {
1799 : .f_string = "modified ",
1800 : },
1801 : {
1802 : .f_string = "%OV",
1803 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_MODIFIER,
1804 : .f_format = 'V',
1805 : },
1806 : {
1807 : .f_string = " format",
1808 : },
1809 : },
1810 : },
1811 : {
1812 : .f_format_string = "modified %Ow format",
1813 : .f_results = {
1814 : {
1815 : .f_string = "modified ",
1816 : },
1817 : {
1818 : .f_string = "%Ow",
1819 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_MODIFIER,
1820 : .f_format = 'w',
1821 : },
1822 : {
1823 : .f_string = " format",
1824 : },
1825 : },
1826 : },
1827 : {
1828 : .f_format_string = "modified %OW format",
1829 : .f_results = {
1830 : {
1831 : .f_string = "modified ",
1832 : },
1833 : {
1834 : .f_string = "%OW",
1835 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_MODIFIER,
1836 : .f_format = 'W',
1837 : },
1838 : {
1839 : .f_string = " format",
1840 : },
1841 : },
1842 : },
1843 : {
1844 : .f_format_string = "modified %Oy format",
1845 : .f_results = {
1846 : {
1847 : .f_string = "modified ",
1848 : },
1849 : {
1850 : .f_string = "%Oy",
1851 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_MODIFIER,
1852 : .f_format = 'y',
1853 : },
1854 : {
1855 : .f_string = " format",
1856 : },
1857 : },
1858 : },
1859 : {
1860 : .f_format_string = "extended %Ef unknown",
1861 : .f_results = {
1862 : {
1863 : .f_string = "extended ",
1864 : },
1865 : {
1866 : .f_errors = {
1867 : snapdev::format_error_t::FORMAT_ERROR_UNKNOWN,
1868 : },
1869 : .f_string = "%",
1870 : },
1871 : {
1872 : .f_string = "Ef unknown",
1873 : },
1874 : },
1875 : },
1876 : {
1877 : .f_format_string = "modified %Of unknown",
1878 : .f_results = {
1879 : {
1880 : .f_string = "modified ",
1881 : },
1882 : {
1883 : .f_errors = {
1884 : snapdev::format_error_t::FORMAT_ERROR_UNKNOWN,
1885 : },
1886 : .f_string = "%",
1887 : },
1888 : {
1889 : .f_string = "Of unknown",
1890 : },
1891 : },
1892 : },
1893 : {
1894 : .f_format_string = "Overflow at end %10001Ey",
1895 : .f_results = {
1896 : {
1897 : .f_string = "Overflow at end ",
1898 : },
1899 : {
1900 : .f_errors = {
1901 : snapdev::format_error_t::FORMAT_ERROR_OVERFLOW,
1902 : },
1903 : .f_string = "%10001Ey",
1904 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_EXTENDED,
1905 : .f_width = 10000,
1906 : .f_format = 'y',
1907 : },
1908 : },
1909 : },
1910 : {
1911 : .f_format_string = "Overflow at end %99999Ey",
1912 : .f_results = {
1913 : {
1914 : .f_string = "Overflow at end ",
1915 : },
1916 : {
1917 : .f_errors = {
1918 : snapdev::format_error_t::FORMAT_ERROR_OVERFLOW,
1919 : },
1920 : .f_string = "%99999Ey",
1921 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_EXTENDED,
1922 : .f_width = 10000,
1923 : .f_format = 'y',
1924 : },
1925 : },
1926 : },
1927 : {
1928 : .f_format_string = "Overflow at end %3472830Ey",
1929 : .f_results = {
1930 : {
1931 : .f_string = "Overflow at end ",
1932 : },
1933 : {
1934 : .f_errors = {
1935 : snapdev::format_error_t::FORMAT_ERROR_OVERFLOW,
1936 : },
1937 : .f_string = "%3472830Ey",
1938 : .f_flags = snapdev::strftime_flag_traits<char>::FORMAT_FLAG_EXTENDED,
1939 : .f_width = 10000,
1940 : .f_format = 'y',
1941 : },
1942 : },
1943 : },
1944 : };
1945 :
1946 :
1947 :
1948 : // the full implementation is found in the advgetopt library
1949 : //
1950 : template<typename _CharT>
1951 : class usage_flag_traits
1952 : {
1953 : public:
1954 : typedef _CharT char_t;
1955 :
1956 : static constexpr snapdev::format_flag_t const FORMAT_FLAG_EXTENDED = 0x0001; // '*'
1957 :
1958 3 : static bool is_flag(char_t c, snapdev::format_item<_CharT> & f)
1959 : {
1960 3 : if(c == '*')
1961 : {
1962 1 : if(f.has_flags(FORMAT_FLAG_EXTENDED))
1963 : {
1964 0 : f.add_error(snapdev::format_error_t::FORMAT_ERROR_DUPLICATE);
1965 : }
1966 1 : f.add_flags(FORMAT_FLAG_EXTENDED);
1967 1 : return true;
1968 : }
1969 2 : return false;
1970 : }
1971 : };
1972 :
1973 : template<typename _CharT>
1974 : class usage_letter_traits
1975 : {
1976 : public:
1977 2 : static std::basic_string<_CharT>::size_type is_format(char const * s, snapdev::format_item<_CharT> & f)
1978 : {
1979 2 : if(s[0] == 'a'
1980 1 : || s[0] == 'd')
1981 : {
1982 2 : f.format(s[0]);
1983 2 : return 1UL;
1984 : }
1985 0 : f.add_error(snapdev::format_error_t::FORMAT_ERROR_UNKNOWN);
1986 0 : return 0;
1987 : }
1988 : };
1989 :
1990 :
1991 : printf_formats_t const g_usage_formats[] =
1992 : {
1993 : {
1994 : .f_format_string = "Data Driven %% Tests",
1995 : .f_results = {
1996 : {
1997 : .f_string = "Data Driven ",
1998 : },
1999 : {
2000 : .f_string = "%",
2001 : },
2002 : {
2003 : .f_string = " Tests",
2004 : },
2005 : },
2006 : },
2007 : {
2008 : .f_format_string = "Simple %a Code",
2009 : .f_results = {
2010 : {
2011 : .f_string = "Simple ",
2012 : },
2013 : {
2014 : .f_string = "%a",
2015 : .f_format = 'a',
2016 : },
2017 : {
2018 : .f_string = " Code",
2019 : },
2020 : },
2021 : },
2022 : {
2023 : .f_format_string = "Extended %*d Format",
2024 : .f_results = {
2025 : {
2026 : .f_string = "Extended ",
2027 : },
2028 : {
2029 : .f_string = "%*d",
2030 : .f_flags = usage_flag_traits<char>::FORMAT_FLAG_EXTENDED,
2031 : .f_format = 'd',
2032 : },
2033 : {
2034 : .f_string = " Format",
2035 : },
2036 : },
2037 : },
2038 : };
2039 :
2040 :
2041 :
2042 : }
2043 : // no name namespace
2044 :
2045 :
2046 :
2047 5 : CATCH_TEST_CASE("tokenize_format_printf", "[string]")
2048 : {
2049 5 : CATCH_START_SECTION("tokenize_format_printf: escape %")
2050 : {
2051 1 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2052 : char
2053 : , snapdev::printf_letter_traits<char>
2054 : , snapdev::printf_flag_traits<char>
2055 3 : , snapdev::printf_number_traits<char>>("Test %% by itself"));
2056 :
2057 1 : CATCH_REQUIRE(items.size() == 3);
2058 :
2059 1 : auto it(items.begin());
2060 :
2061 1 : CATCH_REQUIRE(it->errors().empty());
2062 1 : CATCH_REQUIRE_FALSE(it->has_errors());
2063 1 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_DUPLICATE));
2064 1 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_EOS));
2065 1 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_MISMATCH));
2066 1 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_OVERFLOW));
2067 1 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_SYNTAX));
2068 1 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_UNKNOWN));
2069 1 : CATCH_REQUIRE(it->string() == "Test ");
2070 1 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2071 33 : for(std::size_t flag(0); flag < sizeof(snapdev::format_flag_t) * CHAR_BIT; ++flag)
2072 : {
2073 32 : CATCH_REQUIRE_FALSE(it->has_flags(static_cast<snapdev::format_flag_t>(1LL << flag)));
2074 : }
2075 1 : CATCH_REQUIRE_FALSE(it->has_width());
2076 1 : CATCH_REQUIRE_FALSE(it->has_precision());
2077 1 : CATCH_REQUIRE_FALSE(it->has_position());
2078 1 : CATCH_REQUIRE_FALSE(it->is_format());
2079 :
2080 1 : ++it;
2081 1 : CATCH_REQUIRE_FALSE(it->has_errors());
2082 1 : CATCH_REQUIRE(it->string() == "%");
2083 1 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2084 1 : CATCH_REQUIRE_FALSE(it->has_width());
2085 1 : CATCH_REQUIRE_FALSE(it->has_precision());
2086 1 : CATCH_REQUIRE_FALSE(it->has_position());
2087 1 : CATCH_REQUIRE_FALSE(it->is_format());
2088 :
2089 1 : ++it;
2090 1 : CATCH_REQUIRE_FALSE(it->has_errors());
2091 1 : CATCH_REQUIRE(it->string() == " by itself");
2092 1 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2093 1 : CATCH_REQUIRE_FALSE(it->has_width());
2094 1 : CATCH_REQUIRE_FALSE(it->has_precision());
2095 1 : CATCH_REQUIRE_FALSE(it->has_position());
2096 1 : CATCH_REQUIRE_FALSE(it->is_format());
2097 1 : }
2098 5 : CATCH_END_SECTION()
2099 :
2100 5 : CATCH_START_SECTION("tokenize_format_printf: letters only")
2101 : {
2102 22 : for(char const * s(g_printf_letters); *s != '\0'; ++s)
2103 : {
2104 21 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2105 : char
2106 : , snapdev::printf_letter_traits<char>
2107 : , snapdev::printf_flag_traits<char>
2108 105 : , snapdev::printf_number_traits<char>>(std::string("Letter %") + *s + " by itself"));
2109 :
2110 21 : CATCH_REQUIRE(items.size() == 3);
2111 :
2112 21 : auto it(items.begin());
2113 :
2114 21 : CATCH_REQUIRE(it->errors().empty());
2115 21 : CATCH_REQUIRE_FALSE(it->has_errors());
2116 21 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_DUPLICATE));
2117 21 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_EOS));
2118 21 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_MISMATCH));
2119 21 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_OVERFLOW));
2120 21 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_SYNTAX));
2121 21 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_UNKNOWN));
2122 21 : CATCH_REQUIRE(it->string() == "Letter ");
2123 21 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2124 693 : for(std::size_t flag(0); flag < sizeof(snapdev::format_flag_t) * CHAR_BIT; ++flag)
2125 : {
2126 672 : CATCH_REQUIRE_FALSE(it->has_flags(static_cast<snapdev::format_flag_t>(1LL << flag)));
2127 : }
2128 21 : CATCH_REQUIRE_FALSE(it->has_width());
2129 21 : CATCH_REQUIRE_FALSE(it->has_precision());
2130 21 : CATCH_REQUIRE_FALSE(it->has_position());
2131 21 : CATCH_REQUIRE_FALSE(it->is_format());
2132 :
2133 21 : ++it;
2134 21 : CATCH_REQUIRE_FALSE(it->has_errors());
2135 21 : CATCH_REQUIRE(it->string() == std::string("%") + *s);
2136 21 : char letter(*s);
2137 21 : switch(letter)
2138 : {
2139 1 : case 'i':
2140 1 : letter = 'd';
2141 1 : break;
2142 :
2143 2 : case 'S':
2144 : case 'C':
2145 2 : CATCH_REQUIRE(it->flags() == snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG);
2146 2 : letter = letter | 0x20;
2147 2 : break;
2148 :
2149 18 : default:
2150 18 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2151 18 : break;
2152 :
2153 : }
2154 21 : CATCH_REQUIRE_FALSE(it->has_width());
2155 21 : CATCH_REQUIRE_FALSE(it->has_precision());
2156 21 : CATCH_REQUIRE_FALSE(it->has_position());
2157 21 : CATCH_REQUIRE(it->is_format());
2158 21 : CATCH_REQUIRE(it->format() == letter);
2159 :
2160 21 : ++it;
2161 21 : CATCH_REQUIRE_FALSE(it->has_errors());
2162 21 : CATCH_REQUIRE(it->string() == " by itself");
2163 21 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2164 21 : CATCH_REQUIRE_FALSE(it->has_width());
2165 21 : CATCH_REQUIRE_FALSE(it->has_precision());
2166 21 : CATCH_REQUIRE_FALSE(it->has_position());
2167 21 : CATCH_REQUIRE_FALSE(it->is_format());
2168 21 : }
2169 : }
2170 5 : CATCH_END_SECTION()
2171 :
2172 5 : CATCH_START_SECTION("tokenize_format_printf: size + format")
2173 : {
2174 12 : for(std::size_t idx(0); idx < std::size(g_printf_sizes); ++idx)
2175 : {
2176 11 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2177 : char
2178 : , snapdev::printf_letter_traits<char>
2179 : , snapdev::printf_flag_traits<char>
2180 55 : , snapdev::printf_number_traits<char>>(std::string("Sized %") + g_printf_sizes[idx].f_flag + "d format"));
2181 :
2182 11 : CATCH_REQUIRE(items.size() == 3);
2183 :
2184 11 : auto it(items.begin());
2185 :
2186 11 : CATCH_REQUIRE(it->errors().empty());
2187 11 : CATCH_REQUIRE_FALSE(it->has_errors());
2188 11 : CATCH_REQUIRE(it->string() == "Sized ");
2189 11 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2190 11 : CATCH_REQUIRE_FALSE(it->has_width());
2191 11 : CATCH_REQUIRE_FALSE(it->has_precision());
2192 11 : CATCH_REQUIRE_FALSE(it->has_position());
2193 11 : CATCH_REQUIRE_FALSE(it->is_format());
2194 :
2195 11 : ++it;
2196 11 : CATCH_REQUIRE_FALSE(it->has_errors());
2197 11 : CATCH_REQUIRE(it->string() == std::string("%") + g_printf_sizes[idx].f_flag + "d");
2198 11 : CATCH_REQUIRE(it->flags() == g_printf_sizes[idx].f_length);
2199 11 : CATCH_REQUIRE_FALSE(it->has_width());
2200 11 : CATCH_REQUIRE_FALSE(it->has_precision());
2201 11 : CATCH_REQUIRE_FALSE(it->has_position());
2202 11 : CATCH_REQUIRE(it->is_format());
2203 11 : CATCH_REQUIRE(it->format() == 'd');
2204 :
2205 11 : ++it;
2206 11 : CATCH_REQUIRE_FALSE(it->has_errors());
2207 11 : CATCH_REQUIRE(it->string() == " format");
2208 11 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2209 11 : CATCH_REQUIRE_FALSE(it->has_width());
2210 11 : CATCH_REQUIRE_FALSE(it->has_precision());
2211 11 : CATCH_REQUIRE_FALSE(it->has_position());
2212 11 : CATCH_REQUIRE_FALSE(it->is_format());
2213 11 : }
2214 : }
2215 5 : CATCH_END_SECTION()
2216 :
2217 5 : CATCH_START_SECTION("tokenize_format_printf: size defined twice")
2218 : {
2219 2 : snapdev::format_error_set_t duplicate{ snapdev::format_error_t::FORMAT_ERROR_DUPLICATE };
2220 1 : int format(rand() % (sizeof(g_printf_letters) - 1));
2221 12 : for(std::size_t i(0); i < std::size(g_printf_sizes); ++i)
2222 : {
2223 132 : for(std::size_t j(0); j < std::size(g_printf_sizes); ++j)
2224 : {
2225 121 : if(strcmp(g_printf_sizes[i].f_flag, "") == 0
2226 110 : || strcmp(g_printf_sizes[j].f_flag, "") == 0
2227 100 : || (strcmp(g_printf_sizes[i].f_flag, "h") == 0 && strcmp(g_printf_sizes[j].f_flag, "h") == 0)
2228 99 : || (strcmp(g_printf_sizes[i].f_flag, "l") == 0 && strcmp(g_printf_sizes[j].f_flag, "l") == 0))
2229 : {
2230 : // doubling these won't generate an error
2231 : // and here we are verifying duplicates
2232 : //
2233 23 : continue;
2234 : }
2235 :
2236 196 : std::string pattern("%");
2237 98 : pattern += g_printf_sizes[i].f_flag;
2238 98 : pattern += g_printf_sizes[j].f_flag;
2239 98 : pattern += g_printf_letters[format];
2240 : //std::cerr << " --- pattern [" << pattern << "]\n";
2241 :
2242 98 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2243 : char
2244 : , snapdev::printf_letter_traits<char>
2245 : , snapdev::printf_flag_traits<char>
2246 490 : , snapdev::printf_number_traits<char>>(std::string("Double sized ") + pattern + " format"));
2247 :
2248 98 : CATCH_REQUIRE(items.size() == 3);
2249 :
2250 98 : auto it(items.begin());
2251 :
2252 98 : CATCH_REQUIRE_FALSE(it->has_errors());
2253 98 : CATCH_REQUIRE(it->string() == "Double sized ");
2254 98 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2255 98 : CATCH_REQUIRE_FALSE(it->has_width());
2256 98 : CATCH_REQUIRE_FALSE(it->has_precision());
2257 98 : CATCH_REQUIRE_FALSE(it->has_position());
2258 98 : CATCH_REQUIRE_FALSE(it->is_format());
2259 :
2260 98 : ++it;
2261 98 : CATCH_REQUIRE(it->has_errors());
2262 98 : CATCH_REQUIRE(it->errors() == duplicate);
2263 98 : CATCH_REQUIRE(it->string() == pattern);
2264 98 : switch((g_printf_sizes[i].f_length << 16) | g_printf_sizes[j].f_length)
2265 : {
2266 3 : case (snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_CHAR << 16) | snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_CHAR:
2267 : case (snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_SHORT << 16) | snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_CHAR:
2268 : case (snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_CHAR << 16) | snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_SHORT:
2269 : case (snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_SHORT << 16) | snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_SHORT:
2270 3 : CATCH_REQUIRE(it->flags() == snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_CHAR);
2271 3 : break;
2272 :
2273 6 : case (snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG << 16) | snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG:
2274 : case (snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG << 16) | snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG:
2275 : case (snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG << 16) | snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG:
2276 6 : CATCH_REQUIRE(it->flags() == snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG);
2277 6 : break;
2278 :
2279 2 : case (snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG << 16) | snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG:
2280 : // "q" does not overwrite by "l"
2281 : //
2282 2 : if(strcmp(g_printf_sizes[j].f_flag, "q") == 0)
2283 : {
2284 1 : CATCH_REQUIRE(it->flags() == snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG);
2285 : }
2286 : else
2287 : {
2288 1 : CATCH_REQUIRE(it->flags() == snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG);
2289 : }
2290 2 : break;
2291 :
2292 87 : default:
2293 87 : CATCH_REQUIRE(it->flags() == g_printf_sizes[i].f_length);
2294 87 : break;
2295 :
2296 : }
2297 98 : CATCH_REQUIRE_FALSE(it->has_width());
2298 98 : CATCH_REQUIRE_FALSE(it->has_precision());
2299 98 : CATCH_REQUIRE_FALSE(it->has_position());
2300 98 : CATCH_REQUIRE(it->is_format());
2301 98 : switch(g_printf_letters[format])
2302 : {
2303 14 : case 'i':
2304 14 : CATCH_REQUIRE(it->format() == 'd');
2305 14 : break;
2306 :
2307 0 : case 'S':
2308 0 : CATCH_REQUIRE(it->format() == 's');
2309 0 : break;
2310 :
2311 0 : case 'C':
2312 0 : CATCH_REQUIRE(it->format() == 'c');
2313 0 : break;
2314 :
2315 84 : default:
2316 84 : CATCH_REQUIRE(it->format() == g_printf_letters[format]);
2317 :
2318 : }
2319 98 : ++it;
2320 98 : CATCH_REQUIRE_FALSE(it->has_errors());
2321 98 : CATCH_REQUIRE(it->string() == " format");
2322 98 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2323 98 : CATCH_REQUIRE_FALSE(it->has_width());
2324 98 : CATCH_REQUIRE_FALSE(it->has_precision());
2325 98 : CATCH_REQUIRE_FALSE(it->has_position());
2326 98 : CATCH_REQUIRE_FALSE(it->is_format());
2327 :
2328 98 : format = (format + 1) % (sizeof(g_printf_letters) - 1);
2329 98 : }
2330 : }
2331 1 : }
2332 5 : CATCH_END_SECTION()
2333 :
2334 5 : CATCH_START_SECTION("tokenize_format_printf: data driven tests")
2335 : {
2336 37 : for(std::size_t idx(0); idx < std::size(g_printf_formats); ++idx)
2337 : {
2338 36 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2339 : char
2340 : , snapdev::printf_letter_traits<char>
2341 : , snapdev::printf_flag_traits<char>
2342 108 : , snapdev::printf_number_traits<char>>(g_printf_formats[idx].f_format_string));
2343 :
2344 36 : CATCH_REQUIRE(items.size() == g_printf_formats[idx].f_results.size());
2345 :
2346 36 : auto r(g_printf_formats[idx].f_results.begin());
2347 136 : for(auto it(items.begin()); it != items.end(); ++it, ++r)
2348 : {
2349 : //std::cerr << " +++ parsed [" << g_printf_formats[idx].f_format_string << "] compare item [" << it->string() << "]\n";
2350 : //if(it->has_errors())
2351 : //{
2352 : //for(auto const & e : it->errors())
2353 : //{
2354 : //std::cerr << " >>> error: " << static_cast<int>(e) << "\n";
2355 : //}
2356 : //}
2357 : // verify that test data match in size (we already verified
2358 : // the size, but this is better than a SEGV)
2359 : //
2360 100 : CATCH_REQUIRE(r != g_printf_formats[idx].f_results.end());
2361 :
2362 100 : CATCH_REQUIRE(it->errors() == r->f_errors);
2363 100 : CATCH_REQUIRE(it->string() == r->f_string);
2364 100 : CATCH_REQUIRE(it->flags() == r->f_flags);
2365 100 : CATCH_REQUIRE(it->width() == r->f_width);
2366 100 : CATCH_REQUIRE(it->precision() == r->f_precision);
2367 100 : CATCH_REQUIRE(it->position() == r->f_position);
2368 100 : CATCH_REQUIRE(it->format() == r->f_format);
2369 : }
2370 36 : }
2371 : }
2372 5 : CATCH_END_SECTION()
2373 5 : }
2374 :
2375 :
2376 3 : CATCH_TEST_CASE("tokenize_format_strftime", "[string]")
2377 : {
2378 3 : CATCH_START_SECTION("tokenize_format_strftime: no nanoseconds support")
2379 : {
2380 1 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2381 : char
2382 : , snapdev::strftime_letter_traits<char>
2383 : , snapdev::strftime_flag_traits<char>
2384 3 : , snapdev::strftime_number_traits<char>>("%s.%N"));
2385 :
2386 1 : CATCH_REQUIRE(items.size() == 4);
2387 :
2388 1 : auto it(items.begin());
2389 :
2390 1 : CATCH_REQUIRE(it->string() == "%s");
2391 :
2392 1 : ++it;
2393 1 : CATCH_REQUIRE(it->string() == ".");
2394 :
2395 1 : ++it;
2396 1 : CATCH_REQUIRE(it->string() == "%");
2397 1 : CATCH_REQUIRE(it->has_errors());
2398 1 : CATCH_REQUIRE(it->errors() == snapdev::format_error_set_t{ snapdev::format_error_t::FORMAT_ERROR_UNKNOWN });
2399 1 : CATCH_REQUIRE(it->format() == '\0');
2400 :
2401 1 : ++it;
2402 1 : CATCH_REQUIRE(it->string() == "N");
2403 1 : }
2404 3 : CATCH_END_SECTION()
2405 :
2406 3 : CATCH_START_SECTION("tokenize_format_strftime: no nanoseconds support (extended)")
2407 : {
2408 1 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2409 : char
2410 : , snapdev::strftime_letter_traits<char>
2411 : , snapdev::strftime_flag_traits<char>
2412 3 : , snapdev::strftime_number_traits<char>>("%s.%EN"));
2413 :
2414 1 : CATCH_REQUIRE(items.size() == 4);
2415 :
2416 1 : auto it(items.begin());
2417 :
2418 1 : CATCH_REQUIRE(it->string() == "%s");
2419 :
2420 1 : ++it;
2421 1 : CATCH_REQUIRE(it->string() == ".");
2422 :
2423 1 : ++it;
2424 1 : CATCH_REQUIRE(it->string() == "%");
2425 1 : CATCH_REQUIRE(it->has_errors());
2426 1 : CATCH_REQUIRE(it->errors() == snapdev::format_error_set_t{ snapdev::format_error_t::FORMAT_ERROR_UNKNOWN });
2427 1 : CATCH_REQUIRE(it->format() == '\0');
2428 :
2429 1 : ++it;
2430 1 : CATCH_REQUIRE(it->string() == "EN");
2431 1 : }
2432 3 : CATCH_END_SECTION()
2433 :
2434 3 : CATCH_START_SECTION("tokenize_format_strftime: data driven tests")
2435 : {
2436 70 : for(std::size_t idx(0); idx < std::size(g_strftime_formats); ++idx)
2437 : {
2438 69 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2439 : char
2440 : , snapdev::strftime_letter_traits<char, true>
2441 : , snapdev::strftime_flag_traits<char>
2442 207 : , snapdev::strftime_number_traits<char>>(g_strftime_formats[idx].f_format_string));
2443 :
2444 69 : CATCH_REQUIRE(items.size() == g_strftime_formats[idx].f_results.size());
2445 :
2446 69 : auto r(g_strftime_formats[idx].f_results.begin());
2447 273 : for(auto it(items.begin()); it != items.end(); ++it, ++r)
2448 : {
2449 : //std::cerr << " +++ parsed [" << g_strftime_formats[idx].f_format_string << "] compare item [" << it->string() << "]\n";
2450 : //if(it->has_errors())
2451 : //{
2452 : //for(auto const & e : it->errors())
2453 : //{
2454 : //std::cerr << " >>> error: " << static_cast<int>(e) << "\n";
2455 : //}
2456 : //}
2457 : // verify that test data match in size (we already verified
2458 : // the size, but this is better than a SEGV)
2459 : //
2460 204 : CATCH_REQUIRE(r != g_strftime_formats[idx].f_results.end());
2461 :
2462 204 : CATCH_REQUIRE(it->errors() == r->f_errors);
2463 204 : CATCH_REQUIRE(it->string() == r->f_string);
2464 204 : CATCH_REQUIRE(it->flags() == r->f_flags);
2465 204 : CATCH_REQUIRE(it->width() == r->f_width);
2466 204 : CATCH_REQUIRE(it->precision() == r->f_precision);
2467 204 : CATCH_REQUIRE(it->position() == r->f_position);
2468 204 : CATCH_REQUIRE(it->format() == r->f_format);
2469 : }
2470 69 : }
2471 : }
2472 3 : CATCH_END_SECTION()
2473 3 : }
2474 :
2475 :
2476 : // the following tests a small subset of the advgetopt Usage: ... format
2477 : // support to verify the "no number" implementation
2478 : //
2479 1 : CATCH_TEST_CASE("tokenize_format_advgetopt", "[string]")
2480 : {
2481 1 : CATCH_START_SECTION("tokenize_format_advgetopt: data driven tests")
2482 : {
2483 4 : for(std::size_t idx(0); idx < std::size(g_usage_formats); ++idx)
2484 : {
2485 3 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2486 : char
2487 : , usage_letter_traits<char>
2488 9 : , usage_flag_traits<char>>(g_usage_formats[idx].f_format_string));
2489 :
2490 3 : CATCH_REQUIRE(items.size() == g_usage_formats[idx].f_results.size());
2491 :
2492 3 : auto r(g_usage_formats[idx].f_results.begin());
2493 12 : for(auto it(items.begin()); it != items.end(); ++it, ++r)
2494 : {
2495 : //std::cerr << " +++ parsed [" << g_usage_formats[idx].f_format_string << "] compare item [" << it->string() << "]\n";
2496 : //if(it->has_errors())
2497 : //{
2498 : //for(auto const & e : it->errors())
2499 : //{
2500 : //std::cerr << " >>> error: " << static_cast<int>(e) << "\n";
2501 : //}
2502 : //}
2503 : // verify that test data match in size (we already verified
2504 : // the size, but this is better than a SEGV)
2505 : //
2506 9 : CATCH_REQUIRE(r != g_usage_formats[idx].f_results.end());
2507 :
2508 9 : CATCH_REQUIRE(it->errors() == r->f_errors);
2509 9 : CATCH_REQUIRE(it->string() == r->f_string);
2510 9 : CATCH_REQUIRE(it->flags() == r->f_flags);
2511 9 : CATCH_REQUIRE(it->width() == r->f_width);
2512 9 : CATCH_REQUIRE(it->precision() == r->f_precision);
2513 9 : CATCH_REQUIRE(it->position() == r->f_position);
2514 9 : CATCH_REQUIRE(it->format() == r->f_format);
2515 : }
2516 3 : }
2517 : }
2518 1 : CATCH_END_SECTION()
2519 1 : }
2520 :
2521 :
2522 :
2523 : // vim: ts=4 sw=4 et
|