Line data Source code
1 : // Copyright (c) 2023-2025 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 : // a few templates for an hypothetical format which allows escaping the
1949 : // introducer with a different character (backslash in our case)
1950 : //
1951 : template<typename _CharT>
1952 : class escapable_letter_traits
1953 : {
1954 : public:
1955 13 : static std::basic_string<_CharT>::size_type is_format(char const * s, snapdev::format_item<_CharT> & f)
1956 : {
1957 13 : if(s[0] == 'q'
1958 9 : || s[0] == 'z')
1959 : {
1960 10 : f.format(s[0]);
1961 10 : return 1UL;
1962 : }
1963 3 : f.add_error(snapdev::format_error_t::FORMAT_ERROR_UNKNOWN);
1964 3 : return 0;
1965 : }
1966 : };
1967 :
1968 : template<typename _CharT>
1969 : class escapable_flag_traits
1970 : {
1971 : public:
1972 : typedef _CharT char_t;
1973 :
1974 : static constexpr snapdev::format_flag_t const FORMAT_FLAG_LARGE = 0x0001; // '*'
1975 :
1976 25 : static bool is_flag(char_t c, snapdev::format_item<_CharT> & f)
1977 : {
1978 25 : if(c == 'L')
1979 : {
1980 6 : if(f.has_flags(FORMAT_FLAG_LARGE))
1981 : {
1982 0 : f.add_error(snapdev::format_error_t::FORMAT_ERROR_DUPLICATE);
1983 : }
1984 6 : f.add_flags(FORMAT_FLAG_LARGE);
1985 6 : return true;
1986 : }
1987 19 : return false;
1988 : }
1989 : };
1990 :
1991 : template<typename _CharT>
1992 : class dollar_escapable_introducer_traits
1993 : {
1994 : public:
1995 : typedef _CharT char_t;
1996 :
1997 462 : static bool is_introducer(char_t c)
1998 : {
1999 462 : return c == '$';
2000 : }
2001 :
2002 13 : static bool is_start_enclose(char_t c)
2003 : {
2004 13 : return c == '{';
2005 : }
2006 :
2007 8 : static bool is_end_enclose(char_t c)
2008 : {
2009 8 : return c == '}';
2010 : }
2011 :
2012 13 : static bool double_to_escape()
2013 : {
2014 13 : return false;
2015 : }
2016 :
2017 393 : static bool escape_character(char_t c)
2018 : {
2019 393 : return c == '\\';
2020 : }
2021 : };
2022 :
2023 :
2024 : printf_formats_t const g_shell_formats[] =
2025 : {
2026 : {
2027 : .f_format_string = "Escape Simple \\$z Variable",
2028 : .f_results = {
2029 : {
2030 : .f_string = "Escape Simple ",
2031 : },
2032 : {
2033 : .f_string = "$z Variable",
2034 : },
2035 : },
2036 : },
2037 : {
2038 : .f_format_string = "Escape Enclosed \\${Lz} Variable",
2039 : .f_results = {
2040 : {
2041 : .f_string = "Escape Enclosed "
2042 : },
2043 : {
2044 : .f_string = "${Lz} Variable",
2045 : },
2046 : },
2047 : },
2048 : {
2049 : .f_format_string = "Simple $z Code",
2050 : .f_results = {
2051 : {
2052 : .f_string = "Simple ",
2053 : },
2054 : {
2055 : .f_string = "$z",
2056 : .f_format = 'z',
2057 : },
2058 : {
2059 : .f_string = " Code",
2060 : },
2061 : },
2062 : },
2063 : {
2064 : .f_format_string = "Enclosed ${q} Variable",
2065 : .f_results = {
2066 : {
2067 : .f_string = "Enclosed ",
2068 : },
2069 : {
2070 : .f_string = "${q}",
2071 : .f_format = 'q',
2072 : },
2073 : {
2074 : .f_string = " Variable",
2075 : },
2076 : },
2077 : },
2078 : {
2079 : .f_format_string = "Large $Lz Format Code",
2080 : .f_results = {
2081 : {
2082 : .f_string = "Large ",
2083 : },
2084 : {
2085 : .f_string = "$Lz",
2086 : .f_flags = escapable_flag_traits<char>::FORMAT_FLAG_LARGE,
2087 : .f_format = 'z',
2088 : },
2089 : {
2090 : .f_string = " Format Code",
2091 : },
2092 : },
2093 : },
2094 : {
2095 : .f_format_string = "Large $35Lz Format Code",
2096 : .f_results = {
2097 : {
2098 : .f_string = "Large ",
2099 : },
2100 : {
2101 : .f_string = "$35Lz",
2102 : .f_flags = escapable_flag_traits<char>::FORMAT_FLAG_LARGE,
2103 : .f_width = 35,
2104 : .f_format = 'z',
2105 : },
2106 : {
2107 : .f_string = " Format Code",
2108 : },
2109 : },
2110 : },
2111 : {
2112 : .f_format_string = "Large $L91z Format Code",
2113 : .f_results = {
2114 : {
2115 : .f_string = "Large ",
2116 : },
2117 : {
2118 : .f_string = "$L91z",
2119 : .f_flags = escapable_flag_traits<char>::FORMAT_FLAG_LARGE,
2120 : .f_width = 91,
2121 : .f_format = 'z',
2122 : },
2123 : {
2124 : .f_string = " Format Code",
2125 : },
2126 : },
2127 : },
2128 : {
2129 : .f_format_string = "Enclose & Large ${Lq} Flag",
2130 : .f_results = {
2131 : {
2132 : .f_string = "Enclose & Large ",
2133 : },
2134 : {
2135 : .f_string = "${Lq}",
2136 : .f_flags = escapable_flag_traits<char>::FORMAT_FLAG_LARGE,
2137 : .f_format = 'q',
2138 : },
2139 : {
2140 : .f_string = " Flag",
2141 : },
2142 : },
2143 : },
2144 : {
2145 : .f_format_string = "Enclose & Large ${L28q} Flag",
2146 : .f_results = {
2147 : {
2148 : .f_string = "Enclose & Large ",
2149 : },
2150 : {
2151 : .f_string = "${L28q}",
2152 : .f_flags = escapable_flag_traits<char>::FORMAT_FLAG_LARGE,
2153 : .f_width = 28,
2154 : .f_format = 'q',
2155 : },
2156 : {
2157 : .f_string = " Flag",
2158 : },
2159 : },
2160 : },
2161 : {
2162 : .f_format_string = "Enclose & Large ${62Lq} Flag",
2163 : .f_results = {
2164 : {
2165 : .f_string = "Enclose & Large ",
2166 : },
2167 : {
2168 : .f_string = "${62Lq}",
2169 : .f_flags = escapable_flag_traits<char>::FORMAT_FLAG_LARGE,
2170 : .f_width = 62,
2171 : .f_format = 'q',
2172 : },
2173 : {
2174 : .f_string = " Flag",
2175 : },
2176 : },
2177 : },
2178 : {
2179 : .f_format_string = "Invalid $c Code ('c' not a valid format)",
2180 : .f_results = {
2181 : {
2182 : .f_string = "Invalid ",
2183 : },
2184 : {
2185 : .f_errors = { snapdev::format_error_t::FORMAT_ERROR_UNKNOWN },
2186 : .f_string = "$",
2187 : },
2188 : {
2189 : .f_string = "c Code ('c' not a valid format)",
2190 : },
2191 : },
2192 : },
2193 : {
2194 : .f_format_string = "Invalid ${a} Code ('a' not a valid format)",
2195 : .f_results = {
2196 : {
2197 : .f_string = "Invalid ",
2198 : },
2199 : {
2200 : .f_errors = { snapdev::format_error_t::FORMAT_ERROR_UNKNOWN },
2201 : .f_string = "$",
2202 : },
2203 : {
2204 : .f_string = "{a} Code ('a' not a valid format)",
2205 : },
2206 : },
2207 : },
2208 : {
2209 : .f_format_string = "Invalid ${zc} Code ('z' is known, not 'zc', we expect '}' instead of 'c')",
2210 : .f_results = {
2211 : {
2212 : .f_string = "Invalid ",
2213 : },
2214 : {
2215 : .f_errors = { snapdev::format_error_t::FORMAT_ERROR_SYNTAX },
2216 : .f_string = "$",
2217 : .f_format = 'z',
2218 : },
2219 : {
2220 : .f_string = "{zc} Code ('z' is known, not 'zc', we expect '}' instead of 'c')",
2221 : },
2222 : },
2223 : },
2224 : {
2225 : .f_format_string = "Invalid ${3.5z} Code (no precision allowed)",
2226 : .f_results = {
2227 : {
2228 : .f_string = "Invalid ",
2229 : },
2230 : {
2231 : .f_errors = { snapdev::format_error_t::FORMAT_ERROR_UNKNOWN },
2232 : .f_string = "$",
2233 : .f_width = 3,
2234 : },
2235 : {
2236 : .f_string = "{3.5z} Code (no precision allowed)",
2237 : },
2238 : },
2239 : },
2240 : {
2241 : .f_format_string = "Missing '}' at the end of the string ${8z",
2242 : .f_results = {
2243 : {
2244 : .f_string = "Missing '}' at the end of the string ",
2245 : },
2246 : {
2247 : .f_errors = { snapdev::format_error_t::FORMAT_ERROR_SYNTAX },
2248 : .f_string = "$",
2249 : .f_width = 8,
2250 : .f_format = 'z',
2251 : },
2252 : {
2253 : .f_string = "{8z",
2254 : },
2255 : },
2256 : },
2257 : };
2258 :
2259 :
2260 :
2261 :
2262 :
2263 :
2264 :
2265 :
2266 :
2267 : // a few templates for an hypothetical format: *<l|r>
2268 : //
2269 : template<typename _CharT>
2270 : class star_letter_traits
2271 : {
2272 : public:
2273 4 : static std::basic_string<_CharT>::size_type is_format(char const * s, snapdev::format_item<_CharT> & f)
2274 : {
2275 4 : if(s[0] == 'l'
2276 2 : || s[0] == 'r')
2277 : {
2278 4 : f.format(s[0]);
2279 4 : return 1UL;
2280 : }
2281 0 : f.add_error(snapdev::format_error_t::FORMAT_ERROR_UNKNOWN);
2282 0 : return 0;
2283 : }
2284 : };
2285 :
2286 : template<typename _CharT>
2287 : class star_flag_traits
2288 : {
2289 : public:
2290 : typedef _CharT char_t;
2291 :
2292 : static constexpr snapdev::format_flag_t const FORMAT_FLAG_ZERO = 0x0001; // '*'
2293 :
2294 6 : static bool is_flag(char_t c, snapdev::format_item<_CharT> & f)
2295 : {
2296 6 : if(c == 'Z')
2297 : {
2298 2 : if(f.has_flags(FORMAT_FLAG_ZERO))
2299 : {
2300 0 : f.add_error(snapdev::format_error_t::FORMAT_ERROR_DUPLICATE);
2301 : }
2302 2 : f.add_flags(FORMAT_FLAG_ZERO);
2303 2 : return true;
2304 : }
2305 4 : return false;
2306 : }
2307 : };
2308 :
2309 : printf_formats_t const g_star_formats[] =
2310 : {
2311 : {
2312 : .f_format_string = "Without brackets *l or *r variables and double star: ** for escaping",
2313 : .f_results = {
2314 : {
2315 : .f_string = "Without brackets ",
2316 : },
2317 : {
2318 : .f_string = "*l",
2319 : .f_format = 'l',
2320 : },
2321 : {
2322 : .f_string = " or ",
2323 : },
2324 : {
2325 : .f_string = "*r",
2326 : .f_format = 'r',
2327 : },
2328 : {
2329 : .f_string = " variables and double star: ",
2330 : },
2331 : {
2332 : .f_string = "*",
2333 : },
2334 : {
2335 : .f_string = " for escaping",
2336 : },
2337 : },
2338 : },
2339 : {
2340 : .f_format_string = "Enclosed *<Zr> and *<Zl> variables",
2341 : .f_results = {
2342 : {
2343 : .f_string = "Enclosed "
2344 : },
2345 : {
2346 : .f_string = "*<Zr>",
2347 : .f_flags = star_flag_traits<char>::FORMAT_FLAG_ZERO,
2348 : .f_format = 'r',
2349 : },
2350 : {
2351 : .f_string = " and ",
2352 : },
2353 : {
2354 : .f_string = "*<Zl>",
2355 : .f_flags = star_flag_traits<char>::FORMAT_FLAG_ZERO,
2356 : .f_format = 'l',
2357 : },
2358 : {
2359 : .f_string = " variables",
2360 : },
2361 : },
2362 : },
2363 : };
2364 :
2365 :
2366 :
2367 :
2368 :
2369 :
2370 :
2371 :
2372 :
2373 : // the full implementation is found in the advgetopt library
2374 : //
2375 : template<typename _CharT>
2376 : class usage_flag_traits
2377 : {
2378 : public:
2379 : typedef _CharT char_t;
2380 :
2381 : static constexpr snapdev::format_flag_t const FORMAT_FLAG_EXTENDED = 0x0001; // '*'
2382 :
2383 3 : static bool is_flag(char_t c, snapdev::format_item<_CharT> & f)
2384 : {
2385 3 : if(c == '*')
2386 : {
2387 1 : if(f.has_flags(FORMAT_FLAG_EXTENDED))
2388 : {
2389 0 : f.add_error(snapdev::format_error_t::FORMAT_ERROR_DUPLICATE);
2390 : }
2391 1 : f.add_flags(FORMAT_FLAG_EXTENDED);
2392 1 : return true;
2393 : }
2394 2 : return false;
2395 : }
2396 : };
2397 :
2398 : template<typename _CharT>
2399 : class usage_letter_traits
2400 : {
2401 : public:
2402 2 : static std::basic_string<_CharT>::size_type is_format(char const * s, snapdev::format_item<_CharT> & f)
2403 : {
2404 2 : if(s[0] == 'a'
2405 1 : || s[0] == 'd')
2406 : {
2407 2 : f.format(s[0]);
2408 2 : return 1UL;
2409 : }
2410 0 : f.add_error(snapdev::format_error_t::FORMAT_ERROR_UNKNOWN);
2411 0 : return 0;
2412 : }
2413 : };
2414 :
2415 : printf_formats_t const g_advgetopt_usage_formats[] =
2416 : {
2417 : {
2418 : .f_format_string = "Data Driven %% Tests",
2419 : .f_results = {
2420 : {
2421 : .f_string = "Data Driven ",
2422 : },
2423 : {
2424 : .f_string = "%",
2425 : },
2426 : {
2427 : .f_string = " Tests",
2428 : },
2429 : },
2430 : },
2431 : {
2432 : .f_format_string = "Simple %a Code",
2433 : .f_results = {
2434 : {
2435 : .f_string = "Simple ",
2436 : },
2437 : {
2438 : .f_string = "%a",
2439 : .f_format = 'a',
2440 : },
2441 : {
2442 : .f_string = " Code",
2443 : },
2444 : },
2445 : },
2446 : {
2447 : .f_format_string = "Extended %*d Format",
2448 : .f_results = {
2449 : {
2450 : .f_string = "Extended ",
2451 : },
2452 : {
2453 : .f_string = "%*d",
2454 : .f_flags = usage_flag_traits<char>::FORMAT_FLAG_EXTENDED,
2455 : .f_format = 'd',
2456 : },
2457 : {
2458 : .f_string = " Format",
2459 : },
2460 : },
2461 : },
2462 : };
2463 :
2464 :
2465 :
2466 : }
2467 : // no name namespace
2468 :
2469 :
2470 :
2471 :
2472 1 : CATCH_TEST_CASE("tokenize_no_numbers_template", "[tokenize_format][number]")
2473 : {
2474 1 : CATCH_START_SECTION("tokenize_no_numbers_template: verify all the no-number functions")
2475 : {
2476 : snapdev::no_number_traits<char> nn;
2477 :
2478 1 : CATCH_REQUIRE_FALSE(nn.support_numbers());
2479 :
2480 11 : for(char d = '0'; d <= '9'; ++d)
2481 : {
2482 10 : CATCH_REQUIRE_FALSE(nn.is_number_separator(d));
2483 10 : CATCH_REQUIRE_FALSE(nn.is_number_position(d));
2484 10 : CATCH_REQUIRE_FALSE(nn.is_dynamic_position(d));
2485 :
2486 10 : int const r(rand());
2487 10 : int number(r);
2488 10 : snapdev::format_item<char> item;
2489 10 : CATCH_REQUIRE_FALSE(nn.parse_number(d, number, item));
2490 10 : CATCH_REQUIRE(number == r);
2491 10 : }
2492 : }
2493 1 : CATCH_END_SECTION()
2494 1 : }
2495 :
2496 :
2497 5 : CATCH_TEST_CASE("tokenize_format_printf", "[tokenize_format][string]")
2498 : {
2499 5 : CATCH_START_SECTION("tokenize_format_printf: escape %")
2500 : {
2501 1 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2502 : char
2503 : , snapdev::printf_letter_traits<char>
2504 : , snapdev::printf_flag_traits<char>
2505 3 : , snapdev::printf_number_traits<char>>("Test %% by itself"));
2506 :
2507 1 : CATCH_REQUIRE(items.size() == 3);
2508 :
2509 1 : auto it(items.begin());
2510 :
2511 1 : CATCH_REQUIRE(it->errors().empty());
2512 1 : CATCH_REQUIRE_FALSE(it->has_errors());
2513 1 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_DUPLICATE));
2514 1 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_EOS));
2515 1 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_MISMATCH));
2516 1 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_OVERFLOW));
2517 1 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_SYNTAX));
2518 1 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_UNKNOWN));
2519 1 : CATCH_REQUIRE(it->string() == "Test ");
2520 1 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2521 33 : for(std::size_t flag(0); flag < sizeof(snapdev::format_flag_t) * CHAR_BIT; ++flag)
2522 : {
2523 32 : CATCH_REQUIRE_FALSE(it->has_flags(static_cast<snapdev::format_flag_t>(1LL << flag)));
2524 : }
2525 1 : CATCH_REQUIRE_FALSE(it->has_width());
2526 1 : CATCH_REQUIRE_FALSE(it->has_precision());
2527 1 : CATCH_REQUIRE_FALSE(it->has_position());
2528 1 : CATCH_REQUIRE_FALSE(it->is_format());
2529 :
2530 1 : ++it;
2531 1 : CATCH_REQUIRE_FALSE(it->has_errors());
2532 1 : CATCH_REQUIRE(it->string() == "%");
2533 1 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2534 1 : CATCH_REQUIRE_FALSE(it->has_width());
2535 1 : CATCH_REQUIRE_FALSE(it->has_precision());
2536 1 : CATCH_REQUIRE_FALSE(it->has_position());
2537 1 : CATCH_REQUIRE_FALSE(it->is_format());
2538 :
2539 1 : ++it;
2540 1 : CATCH_REQUIRE_FALSE(it->has_errors());
2541 1 : CATCH_REQUIRE(it->string() == " by itself");
2542 1 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2543 1 : CATCH_REQUIRE_FALSE(it->has_width());
2544 1 : CATCH_REQUIRE_FALSE(it->has_precision());
2545 1 : CATCH_REQUIRE_FALSE(it->has_position());
2546 1 : CATCH_REQUIRE_FALSE(it->is_format());
2547 1 : }
2548 5 : CATCH_END_SECTION()
2549 :
2550 5 : CATCH_START_SECTION("tokenize_format_printf: letters only")
2551 : {
2552 22 : for(char const * s(g_printf_letters); *s != '\0'; ++s)
2553 : {
2554 21 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2555 : char
2556 : , snapdev::printf_letter_traits<char>
2557 : , snapdev::printf_flag_traits<char>
2558 63 : , snapdev::printf_number_traits<char>>(std::string("Letter %") + *s + " by itself"));
2559 :
2560 21 : CATCH_REQUIRE(items.size() == 3);
2561 :
2562 21 : auto it(items.begin());
2563 :
2564 21 : CATCH_REQUIRE(it->errors().empty());
2565 21 : CATCH_REQUIRE_FALSE(it->has_errors());
2566 21 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_DUPLICATE));
2567 21 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_EOS));
2568 21 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_MISMATCH));
2569 21 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_OVERFLOW));
2570 21 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_SYNTAX));
2571 21 : CATCH_REQUIRE_FALSE(it->has_error(snapdev::format_error_t::FORMAT_ERROR_UNKNOWN));
2572 21 : CATCH_REQUIRE(it->string() == "Letter ");
2573 21 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2574 693 : for(std::size_t flag(0); flag < sizeof(snapdev::format_flag_t) * CHAR_BIT; ++flag)
2575 : {
2576 672 : CATCH_REQUIRE_FALSE(it->has_flags(static_cast<snapdev::format_flag_t>(1LL << flag)));
2577 : }
2578 21 : CATCH_REQUIRE_FALSE(it->has_width());
2579 21 : CATCH_REQUIRE_FALSE(it->has_precision());
2580 21 : CATCH_REQUIRE_FALSE(it->has_position());
2581 21 : CATCH_REQUIRE_FALSE(it->is_format());
2582 :
2583 21 : ++it;
2584 21 : CATCH_REQUIRE_FALSE(it->has_errors());
2585 63 : CATCH_REQUIRE(it->string() == std::string("%") + *s);
2586 21 : char letter(*s);
2587 21 : switch(letter)
2588 : {
2589 1 : case 'i':
2590 1 : letter = 'd';
2591 1 : break;
2592 :
2593 2 : case 'S':
2594 : case 'C':
2595 2 : CATCH_REQUIRE(it->flags() == snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG);
2596 2 : letter = letter | 0x20;
2597 2 : break;
2598 :
2599 18 : default:
2600 18 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2601 18 : break;
2602 :
2603 : }
2604 21 : CATCH_REQUIRE_FALSE(it->has_width());
2605 21 : CATCH_REQUIRE_FALSE(it->has_precision());
2606 21 : CATCH_REQUIRE_FALSE(it->has_position());
2607 21 : CATCH_REQUIRE(it->is_format());
2608 21 : CATCH_REQUIRE(it->format() == letter);
2609 :
2610 21 : ++it;
2611 21 : CATCH_REQUIRE_FALSE(it->has_errors());
2612 21 : CATCH_REQUIRE(it->string() == " by itself");
2613 21 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2614 21 : CATCH_REQUIRE_FALSE(it->has_width());
2615 21 : CATCH_REQUIRE_FALSE(it->has_precision());
2616 21 : CATCH_REQUIRE_FALSE(it->has_position());
2617 21 : CATCH_REQUIRE_FALSE(it->is_format());
2618 21 : }
2619 : }
2620 5 : CATCH_END_SECTION()
2621 :
2622 5 : CATCH_START_SECTION("tokenize_format_printf: size + format")
2623 : {
2624 24 : for(std::size_t idx(0); idx < std::size(g_printf_sizes); ++idx)
2625 : {
2626 11 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2627 : char
2628 : , snapdev::printf_letter_traits<char>
2629 : , snapdev::printf_flag_traits<char>
2630 33 : , snapdev::printf_number_traits<char>>(std::string("Sized %") + g_printf_sizes[idx].f_flag + "d format"));
2631 :
2632 11 : CATCH_REQUIRE(items.size() == 3);
2633 :
2634 11 : auto it(items.begin());
2635 :
2636 11 : CATCH_REQUIRE(it->errors().empty());
2637 11 : CATCH_REQUIRE_FALSE(it->has_errors());
2638 11 : CATCH_REQUIRE(it->string() == "Sized ");
2639 11 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2640 11 : CATCH_REQUIRE_FALSE(it->has_width());
2641 11 : CATCH_REQUIRE_FALSE(it->has_precision());
2642 11 : CATCH_REQUIRE_FALSE(it->has_position());
2643 11 : CATCH_REQUIRE_FALSE(it->is_format());
2644 :
2645 11 : ++it;
2646 11 : CATCH_REQUIRE_FALSE(it->has_errors());
2647 33 : CATCH_REQUIRE(it->string() == std::string("%") + g_printf_sizes[idx].f_flag + "d");
2648 11 : CATCH_REQUIRE(it->flags() == g_printf_sizes[idx].f_length);
2649 11 : CATCH_REQUIRE_FALSE(it->has_width());
2650 11 : CATCH_REQUIRE_FALSE(it->has_precision());
2651 11 : CATCH_REQUIRE_FALSE(it->has_position());
2652 11 : CATCH_REQUIRE(it->is_format());
2653 11 : CATCH_REQUIRE(it->format() == 'd');
2654 :
2655 11 : ++it;
2656 11 : CATCH_REQUIRE_FALSE(it->has_errors());
2657 11 : CATCH_REQUIRE(it->string() == " format");
2658 11 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2659 11 : CATCH_REQUIRE_FALSE(it->has_width());
2660 11 : CATCH_REQUIRE_FALSE(it->has_precision());
2661 11 : CATCH_REQUIRE_FALSE(it->has_position());
2662 11 : CATCH_REQUIRE_FALSE(it->is_format());
2663 11 : }
2664 : }
2665 5 : CATCH_END_SECTION()
2666 :
2667 5 : CATCH_START_SECTION("tokenize_format_printf: size defined twice")
2668 : {
2669 3 : snapdev::format_error_set_t duplicate{ snapdev::format_error_t::FORMAT_ERROR_DUPLICATE };
2670 1 : int format(rand() % (sizeof(g_printf_letters) - 1));
2671 24 : for(std::size_t i(0); i < std::size(g_printf_sizes); ++i)
2672 : {
2673 264 : for(std::size_t j(0); j < std::size(g_printf_sizes); ++j)
2674 : {
2675 121 : if(strcmp(g_printf_sizes[i].f_flag, "") == 0
2676 110 : || strcmp(g_printf_sizes[j].f_flag, "") == 0
2677 100 : || (strcmp(g_printf_sizes[i].f_flag, "h") == 0 && strcmp(g_printf_sizes[j].f_flag, "h") == 0)
2678 99 : || (strcmp(g_printf_sizes[i].f_flag, "l") == 0 && strcmp(g_printf_sizes[j].f_flag, "l") == 0))
2679 : {
2680 : // doubling these won't generate an error
2681 : // and here we are verifying duplicates
2682 : //
2683 23 : continue;
2684 : }
2685 :
2686 294 : std::string pattern("%");
2687 98 : pattern += g_printf_sizes[i].f_flag;
2688 98 : pattern += g_printf_sizes[j].f_flag;
2689 98 : pattern += g_printf_letters[format];
2690 : //std::cerr << " --- pattern [" << pattern << "]\n";
2691 :
2692 98 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2693 : char
2694 : , snapdev::printf_letter_traits<char>
2695 : , snapdev::printf_flag_traits<char>
2696 294 : , snapdev::printf_number_traits<char>>(std::string("Double sized ") + pattern + " format"));
2697 :
2698 98 : CATCH_REQUIRE(items.size() == 3);
2699 :
2700 98 : auto it(items.begin());
2701 :
2702 98 : CATCH_REQUIRE_FALSE(it->has_errors());
2703 98 : CATCH_REQUIRE(it->string() == "Double sized ");
2704 98 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2705 98 : CATCH_REQUIRE_FALSE(it->has_width());
2706 98 : CATCH_REQUIRE_FALSE(it->has_precision());
2707 98 : CATCH_REQUIRE_FALSE(it->has_position());
2708 98 : CATCH_REQUIRE_FALSE(it->is_format());
2709 :
2710 98 : ++it;
2711 98 : CATCH_REQUIRE(it->has_errors());
2712 98 : CATCH_REQUIRE(it->errors() == duplicate);
2713 98 : CATCH_REQUIRE(it->string() == pattern);
2714 98 : switch((g_printf_sizes[i].f_length << 16) | g_printf_sizes[j].f_length)
2715 : {
2716 3 : case (snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_CHAR << 16) | snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_CHAR:
2717 : case (snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_SHORT << 16) | snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_CHAR:
2718 : case (snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_CHAR << 16) | snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_SHORT:
2719 : case (snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_SHORT << 16) | snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_SHORT:
2720 3 : CATCH_REQUIRE(it->flags() == snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_CHAR);
2721 3 : break;
2722 :
2723 6 : case (snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG << 16) | snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG:
2724 : case (snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG << 16) | snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG:
2725 : case (snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG << 16) | snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG:
2726 6 : CATCH_REQUIRE(it->flags() == snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG);
2727 6 : break;
2728 :
2729 2 : case (snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG << 16) | snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG:
2730 : // "q" does not overwrite by "l"
2731 : //
2732 2 : if(strcmp(g_printf_sizes[j].f_flag, "q") == 0)
2733 : {
2734 1 : CATCH_REQUIRE(it->flags() == snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG);
2735 : }
2736 : else
2737 : {
2738 1 : CATCH_REQUIRE(it->flags() == snapdev::printf_flag_traits<char>::FORMAT_FLAG_LENGTH_LONG_LONG);
2739 : }
2740 2 : break;
2741 :
2742 87 : default:
2743 87 : CATCH_REQUIRE(it->flags() == g_printf_sizes[i].f_length);
2744 87 : break;
2745 :
2746 : }
2747 98 : CATCH_REQUIRE_FALSE(it->has_width());
2748 98 : CATCH_REQUIRE_FALSE(it->has_precision());
2749 98 : CATCH_REQUIRE_FALSE(it->has_position());
2750 98 : CATCH_REQUIRE(it->is_format());
2751 98 : switch(g_printf_letters[format])
2752 : {
2753 14 : case 'i':
2754 14 : CATCH_REQUIRE(it->format() == 'd');
2755 14 : break;
2756 :
2757 0 : case 'S':
2758 0 : CATCH_REQUIRE(it->format() == 's');
2759 0 : break;
2760 :
2761 0 : case 'C':
2762 0 : CATCH_REQUIRE(it->format() == 'c');
2763 0 : break;
2764 :
2765 84 : default:
2766 84 : CATCH_REQUIRE(it->format() == g_printf_letters[format]);
2767 :
2768 : }
2769 98 : ++it;
2770 98 : CATCH_REQUIRE_FALSE(it->has_errors());
2771 98 : CATCH_REQUIRE(it->string() == " format");
2772 98 : CATCH_REQUIRE(it->flags() == snapdev::FORMAT_FLAG_NONE);
2773 98 : CATCH_REQUIRE_FALSE(it->has_width());
2774 98 : CATCH_REQUIRE_FALSE(it->has_precision());
2775 98 : CATCH_REQUIRE_FALSE(it->has_position());
2776 98 : CATCH_REQUIRE_FALSE(it->is_format());
2777 :
2778 98 : format = (format + 1) % (sizeof(g_printf_letters) - 1);
2779 98 : }
2780 : }
2781 1 : }
2782 5 : CATCH_END_SECTION()
2783 :
2784 5 : CATCH_START_SECTION("tokenize_format_printf: data driven tests")
2785 : {
2786 74 : for(std::size_t idx(0); idx < std::size(g_printf_formats); ++idx)
2787 : {
2788 36 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2789 : char
2790 : , snapdev::printf_letter_traits<char>
2791 : , snapdev::printf_flag_traits<char>
2792 108 : , snapdev::printf_number_traits<char>>(g_printf_formats[idx].f_format_string));
2793 :
2794 36 : CATCH_REQUIRE(items.size() == g_printf_formats[idx].f_results.size());
2795 :
2796 36 : auto r(g_printf_formats[idx].f_results.begin());
2797 136 : for(auto it(items.begin()); it != items.end(); ++it, ++r)
2798 : {
2799 : //std::cerr << " +++ parsed [" << g_printf_formats[idx].f_format_string << "] compare item [" << it->string() << "]\n";
2800 : //if(it->has_errors())
2801 : //{
2802 : //for(auto const & e : it->errors())
2803 : //{
2804 : //std::cerr << " >>> error: " << static_cast<int>(e) << "\n";
2805 : //}
2806 : //}
2807 : // verify that test data match in size (we already verified
2808 : // the size, but this is better than a SEGV)
2809 : //
2810 100 : CATCH_REQUIRE(r != g_printf_formats[idx].f_results.end());
2811 :
2812 100 : CATCH_REQUIRE(it->errors() == r->f_errors);
2813 100 : CATCH_REQUIRE(it->string() == r->f_string);
2814 100 : CATCH_REQUIRE(it->flags() == r->f_flags);
2815 100 : CATCH_REQUIRE(it->width() == r->f_width);
2816 100 : CATCH_REQUIRE(it->precision() == r->f_precision);
2817 100 : CATCH_REQUIRE(it->position() == r->f_position);
2818 100 : CATCH_REQUIRE(it->format() == r->f_format);
2819 : }
2820 36 : }
2821 : }
2822 5 : CATCH_END_SECTION()
2823 5 : }
2824 :
2825 :
2826 3 : CATCH_TEST_CASE("tokenize_format_strftime", "[tokenize_format][string]")
2827 : {
2828 3 : CATCH_START_SECTION("tokenize_format_strftime: no nanoseconds support")
2829 : {
2830 1 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2831 : char
2832 : , snapdev::strftime_letter_traits<char>
2833 : , snapdev::strftime_flag_traits<char>
2834 3 : , snapdev::strftime_number_traits<char>>("%s.%N"));
2835 :
2836 1 : CATCH_REQUIRE(items.size() == 4);
2837 :
2838 1 : auto it(items.begin());
2839 :
2840 1 : CATCH_REQUIRE(it->string() == "%s");
2841 :
2842 1 : ++it;
2843 1 : CATCH_REQUIRE(it->string() == ".");
2844 :
2845 1 : ++it;
2846 1 : CATCH_REQUIRE(it->string() == "%");
2847 1 : CATCH_REQUIRE(it->has_errors());
2848 3 : CATCH_REQUIRE(it->errors() == snapdev::format_error_set_t{ snapdev::format_error_t::FORMAT_ERROR_UNKNOWN });
2849 1 : CATCH_REQUIRE(it->format() == '\0');
2850 :
2851 1 : ++it;
2852 1 : CATCH_REQUIRE(it->string() == "N");
2853 1 : }
2854 3 : CATCH_END_SECTION()
2855 :
2856 3 : CATCH_START_SECTION("tokenize_format_strftime: no nanoseconds support (extended)")
2857 : {
2858 1 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2859 : char
2860 : , snapdev::strftime_letter_traits<char>
2861 : , snapdev::strftime_flag_traits<char>
2862 3 : , snapdev::strftime_number_traits<char>>("%s.%EN"));
2863 :
2864 1 : CATCH_REQUIRE(items.size() == 4);
2865 :
2866 1 : auto it(items.begin());
2867 :
2868 1 : CATCH_REQUIRE(it->string() == "%s");
2869 :
2870 1 : ++it;
2871 1 : CATCH_REQUIRE(it->string() == ".");
2872 :
2873 1 : ++it;
2874 1 : CATCH_REQUIRE(it->string() == "%");
2875 1 : CATCH_REQUIRE(it->has_errors());
2876 3 : CATCH_REQUIRE(it->errors() == snapdev::format_error_set_t{ snapdev::format_error_t::FORMAT_ERROR_UNKNOWN });
2877 1 : CATCH_REQUIRE(it->format() == '\0');
2878 :
2879 1 : ++it;
2880 1 : CATCH_REQUIRE(it->string() == "EN");
2881 1 : }
2882 3 : CATCH_END_SECTION()
2883 :
2884 3 : CATCH_START_SECTION("tokenize_format_strftime: data driven tests")
2885 : {
2886 140 : for(std::size_t idx(0); idx < std::size(g_strftime_formats); ++idx)
2887 : {
2888 69 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2889 : char
2890 : , snapdev::strftime_letter_traits<char, true>
2891 : , snapdev::strftime_flag_traits<char>
2892 207 : , snapdev::strftime_number_traits<char>>(g_strftime_formats[idx].f_format_string));
2893 :
2894 69 : CATCH_REQUIRE(items.size() == g_strftime_formats[idx].f_results.size());
2895 :
2896 69 : auto r(g_strftime_formats[idx].f_results.begin());
2897 273 : for(auto it(items.begin()); it != items.end(); ++it, ++r)
2898 : {
2899 : //std::cerr << " +++ parsed [" << g_strftime_formats[idx].f_format_string << "] compare item [" << it->string() << "]\n";
2900 : //if(it->has_errors())
2901 : //{
2902 : //for(auto const & e : it->errors())
2903 : //{
2904 : //std::cerr << " >>> error: " << static_cast<int>(e) << "\n";
2905 : //}
2906 : //}
2907 : // verify that test data match in size (we already verified
2908 : // the size, but this is better than a SEGV)
2909 : //
2910 204 : CATCH_REQUIRE(r != g_strftime_formats[idx].f_results.end());
2911 :
2912 204 : CATCH_REQUIRE(it->errors() == r->f_errors);
2913 204 : CATCH_REQUIRE(it->string() == r->f_string);
2914 204 : CATCH_REQUIRE(it->flags() == r->f_flags);
2915 204 : CATCH_REQUIRE(it->width() == r->f_width);
2916 204 : CATCH_REQUIRE(it->precision() == r->f_precision);
2917 204 : CATCH_REQUIRE(it->position() == r->f_position);
2918 204 : CATCH_REQUIRE(it->format() == r->f_format);
2919 : }
2920 69 : }
2921 : }
2922 3 : CATCH_END_SECTION()
2923 3 : }
2924 :
2925 :
2926 : // the following tests a small subset of the advgetopt Usage: ... format
2927 : // support to verify the "no number" implementation
2928 : //
2929 1 : CATCH_TEST_CASE("tokenize_format_advgetopt", "[tokenize_format][string]")
2930 : {
2931 1 : CATCH_START_SECTION("tokenize_format_advgetopt: data driven tests")
2932 : {
2933 8 : for(std::size_t idx(0); idx < std::size(g_advgetopt_usage_formats); ++idx)
2934 : {
2935 3 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2936 : char
2937 : , usage_letter_traits<char>
2938 9 : , usage_flag_traits<char>>(g_advgetopt_usage_formats[idx].f_format_string));
2939 :
2940 3 : CATCH_REQUIRE(items.size() == g_advgetopt_usage_formats[idx].f_results.size());
2941 :
2942 3 : auto r(g_advgetopt_usage_formats[idx].f_results.begin());
2943 12 : for(auto it(items.begin()); it != items.end(); ++it, ++r)
2944 : {
2945 : //std::cerr << " +++ parsed [" << g_advgetopt_usage_formats[idx].f_format_string << "] compare item [" << it->string() << "]\n";
2946 : //if(it->has_errors())
2947 : //{
2948 : //for(auto const & e : it->errors())
2949 : //{
2950 : //std::cerr << " >>> error: " << static_cast<int>(e) << "\n";
2951 : //}
2952 : //}
2953 : // verify that test data match in size (we already verified
2954 : // the size, but this is better than a SEGV)
2955 : //
2956 9 : CATCH_REQUIRE(r != g_advgetopt_usage_formats[idx].f_results.end());
2957 :
2958 9 : CATCH_REQUIRE(it->errors() == r->f_errors);
2959 9 : CATCH_REQUIRE(it->string() == r->f_string);
2960 9 : CATCH_REQUIRE(it->flags() == r->f_flags);
2961 9 : CATCH_REQUIRE(it->width() == r->f_width);
2962 9 : CATCH_REQUIRE(it->precision() == r->f_precision);
2963 9 : CATCH_REQUIRE(it->position() == r->f_position);
2964 9 : CATCH_REQUIRE(it->format() == r->f_format);
2965 : }
2966 3 : }
2967 : }
2968 1 : CATCH_END_SECTION()
2969 1 : }
2970 :
2971 :
2972 : // the following tests a $...L type of implementation where the $ can be
2973 : // escaped by a backslash; this is to verify that the escape works as expected
2974 : //
2975 1 : CATCH_TEST_CASE("tokenize_format_shell", "[tokenize_format][string]")
2976 : {
2977 1 : CATCH_START_SECTION("tokenize_format_shell: test the ${[<number>][L]q|z} syntax (a bit like in a shell)")
2978 : {
2979 32 : for(std::size_t idx(0); idx < std::size(g_shell_formats); ++idx)
2980 : {
2981 15 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
2982 : char
2983 : , escapable_letter_traits<char>
2984 : , escapable_flag_traits<char>
2985 : , snapdev::strftime_number_traits<char>
2986 : , dollar_escapable_introducer_traits<char>
2987 45 : >(g_shell_formats[idx].f_format_string));
2988 :
2989 15 : CATCH_REQUIRE(items.size() == g_shell_formats[idx].f_results.size());
2990 :
2991 15 : auto r(g_shell_formats[idx].f_results.begin());
2992 58 : for(auto it(items.begin()); it != items.end(); ++it, ++r)
2993 : {
2994 : // verify that test data match in size (we already verified
2995 : // the size, but this is better than a SEGV)
2996 : //
2997 43 : CATCH_REQUIRE(r != g_shell_formats[idx].f_results.end());
2998 :
2999 : //std::cerr << " +++ parsed [" << g_shell_formats[idx].f_format_string << "] compare item [" << it->string() << "] == [" << r->f_string << "]\n";
3000 : //if(it->has_errors())
3001 : //{
3002 : //for(auto const & e : it->errors())
3003 : //{
3004 : //std::cerr << " >>> error: " << static_cast<int>(e) << "\n";
3005 : //}
3006 : //}
3007 43 : CATCH_REQUIRE(it->errors() == r->f_errors);
3008 43 : CATCH_REQUIRE(it->string() == r->f_string);
3009 43 : CATCH_REQUIRE(it->flags() == r->f_flags);
3010 43 : CATCH_REQUIRE(it->width() == r->f_width);
3011 43 : CATCH_REQUIRE(it->precision() == r->f_precision);
3012 43 : CATCH_REQUIRE(it->position() == r->f_position);
3013 43 : CATCH_REQUIRE(it->format() == r->f_format);
3014 : }
3015 15 : }
3016 : }
3017 1 : CATCH_END_SECTION()
3018 1 : }
3019 :
3020 :
3021 1 : CATCH_TEST_CASE("tokenize_format_star", "[tokenize_format][string]")
3022 : {
3023 1 : CATCH_START_SECTION("tokenize_format_star: test a *<l|r> syntax (with angle brackets)")
3024 : {
3025 6 : for(std::size_t idx(0); idx < std::size(g_star_formats); ++idx)
3026 : {
3027 2 : snapdev::format_item<char>::list_t items(snapdev::tokenize_format<
3028 : char
3029 : , star_letter_traits<char>
3030 : , star_flag_traits<char>
3031 : , snapdev::no_number_traits<char>
3032 : , snapdev::percent_introducer_traits<char, '*', '<', '>'>
3033 6 : >(g_star_formats[idx].f_format_string));
3034 :
3035 2 : CATCH_REQUIRE(items.size() == g_star_formats[idx].f_results.size());
3036 :
3037 2 : auto r(g_star_formats[idx].f_results.begin());
3038 14 : for(auto it(items.begin()); it != items.end(); ++it, ++r)
3039 : {
3040 : // verify that test data match in size (we already verified
3041 : // the size, but this is better than a SEGV)
3042 : //
3043 12 : CATCH_REQUIRE(r != g_star_formats[idx].f_results.end());
3044 :
3045 : //std::cerr << " +++ parsed [" << g_star_formats[idx].f_format_string << "] compare item [" << it->string() << "] == [" << r->f_string << "]\n";
3046 : //if(it->has_errors())
3047 : //{
3048 : //for(auto const & e : it->errors())
3049 : //{
3050 : //std::cerr << " >>> error: " << static_cast<int>(e) << "\n";
3051 : //}
3052 : //}
3053 12 : CATCH_REQUIRE(it->errors() == r->f_errors);
3054 12 : CATCH_REQUIRE(it->string() == r->f_string);
3055 12 : CATCH_REQUIRE(it->flags() == r->f_flags);
3056 12 : CATCH_REQUIRE(it->width() == r->f_width);
3057 12 : CATCH_REQUIRE(it->precision() == r->f_precision);
3058 12 : CATCH_REQUIRE(it->position() == r->f_position);
3059 12 : CATCH_REQUIRE(it->format() == r->f_format);
3060 : }
3061 2 : }
3062 : }
3063 1 : CATCH_END_SECTION()
3064 1 : }
3065 :
3066 :
3067 :
3068 : // vim: ts=4 sw=4 et
|