LCOV - code coverage report
Current view: top level - tests - catch_tokenize_format.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 96.7 % 392 379
Test Date: 2025-07-03 19:05:49 Functions: 100.0 % 17 17
Legend: Lines: hit not hit

            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
        

Generated by: LCOV version 2.0-1

Snap C++ | List of projects | List of versions