Changeset 5764204


Ignore:
Timestamp:
Jan 25, 2024, 8:58:44 AM (11 months ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
master
Children:
68cf1d4, 8ca60e4
Parents:
64c4b4d
Message:

restrict nesting of manipulators and update manipulator test

Files:
6 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/collections/string_res.cfa

    r64c4b4d r5764204  
    1010// Created On       : Fri Sep 03 11:00:00 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jan 16 22:19:27 2024
    13 // Update Count     : 35
     12// Last Modified On : Mon Jan 22 23:12:42 2024
     13// Update Count     : 43
    1414//
    1515
     
    263263        bool cont = false;
    264264
    265         _Istream_Cstr cf = { cstr, (_Istream_str_base)f };
     265        _Istream_Cwidth cf = { cstr, (_Istream_str_base)f };
    266266        if ( ! cf.flags.rwd ) cf.wd = wd;
    267267
  • libcfa/src/iostream.cfa

    r64c4b4d r5764204  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jan  3 10:53:13 2024
    13 // Update Count     : 1898
     12// Last Modified On : Thu Jan 25 08:39:31 2024
     13// Update Count     : 1901
    1414//
    1515
     
    984984        }
    985985
    986         istype & ?|?( istype & is, _Istream_Cquoted f ) with( f ) {
    987                 char fmtstr[32];                                                                // storage scanset and format codes
     986        istype & ?|?( istype & is, _Istream_Cquoted f ) with( f.cstr ) {
     987                int args;
     988          fini: {
     989                        args = fmt( is, "%*[ \f\n\r\t\v]" );            // remove leading whitespace
     990                        if ( eof( is ) ) break fini;
     991                        char rfmt[4] = { delimiters[0], '%', 'n', '\0' };
     992                        int len = 0;                                                            // may not be set in fmt
     993                        args = fmt( is, rfmt, &len );                           // remove leading quote
     994                        if ( len == 0 || eof( is ) ) break fini;
     995
     996                        // Change the remainder of the read into a getline by reseting the closing delimiter.
     997                        if ( delimiters[1] != '\0' ) {
     998                                delimiters[0] = delimiters[1];
     999                                delimiters[1] = '\0';
     1000                        } // if
     1001                        flags.delimiter = true;
     1002                        return is | *(_Istream_Cstr *)&f;
     1003                } // fini
     1004                if ( ! flags.ignore && args == 0 ) s[0] = '\0'; // read failed => no pattern match => set string to null
     1005                if ( args == 1 && eof( is ) ) {                                 // data but scan ended at EOF
     1006                        clear( is );                                                            // => reset EOF => detect again on next read
     1007                } // if
     1008                return is;
     1009        }
     1010
     1011        istype & ?|?( istype & is, _Istream_Cstr f ) with( f.cstr ) {
     1012                const char * scanset;
     1013                size_t nscanset = 0;
     1014                if ( flags.delimiter ) scanset = delimiters;    // getline ?
     1015                else scanset = f.cstr.scanset;
     1016                if ( scanset ) nscanset = strlen( scanset );
     1017
     1018                char fmtstr[nscanset + 32];                                             // storage for scanset and format codes
    9881019                fmtstr[0] = '%';
    989 
    9901020                int pos = 1;
    9911021                int args;
    9921022                bool check = true;
    9931023
    994                 if ( cstr.flags.ignore ) { check = false; fmtstr[1] = '*'; pos += 1; }
    995                 int rwd = cstr.wd;
    996                 if ( cstr.wd != -1 ) {                                          // => just ignore versus ignore with width
     1024                if ( flags.ignore ) { check = false; fmtstr[1] = '*'; pos += 1; }
     1025                int rwd = wd;
     1026                if ( wd != -1 ) {                                                               // => just ignore versus ignore with width
    9971027                        // wd is buffer bytes available (for input chars + null terminator)
    9981028                        // rwd is count of input chars
    9991029                        // no maximum width necessary because text ignored => width is read width
    1000                         if ( cstr.flags.rwd ) check = false;
    1001                         else rwd = cstr.wd - 1;
     1030                        if ( flags.rwd ) check = false;
     1031                        else rwd = wd - 1;
     1032                        assert( rwd > 0 );
    10021033                        pos += sprintf( &fmtstr[pos], "%d", rwd );
    10031034                } // if
    10041035
    1005                 int len = 0;                                                                    // may not be set in fmt
    1006                 char enddelim;
    1007                 if ( ! cstr.flags.inex ) {                                              // => quoted getline
    1008                         args = fmt( is, "%*[ \f\n\r\t\v]" );            // remove leading whitespace
    1009                         if ( eof( is ) ) goto Eof;
    1010                         char rfmt[4] = { cstr.delimiters[0], '%', 'n', '\0' };
    1011                         args = fmt( is, rfmt, &len );                           // remove leading quote
    1012                         if ( len == 0 || eof( is ) ) goto Eof;
    1013                 } // if
    1014                 enddelim = cstr.delimiters[1] == '\0' ? cstr.delimiters[0] : cstr.delimiters[1];
    1015                 sprintf( &fmtstr[pos], "[^%c]%%n", enddelim );
    1016                 if ( cstr.flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
    1017                 else args = fmt( is, fmtstr, cstr.s, &len );
    1018                 if ( check && len == rwd && ! eof( is ) ) {             // might not fit
    1019                         char peek;
    1020                         fmt( is, "%c", &peek );                                         // check for delimiter
    1021                         if ( ! eof( is ) ) {
    1022                                 if ( peek != enddelim ) {
    1023                                         ungetc( is, peek );
    1024                                         throwResume ExceptionInst( cstring_length );
    1025                                 } // if
    1026                         } // if
    1027                 } else fmt( is, "%*c" );                                                // remove delimiter
    1028           Eof: ;
    1029                 if ( rwd > 0 && args == 0 ) cstr.s[0] = '\0';   // read failed => no pattern match => set string to null
    1030                 if ( args == 1 && eof( is ) ) {                                 // data but scan ended at EOF
    1031                         clear( is );                                                            // => reset EOF => detect again on next read
    1032                 } // if
    1033                 return is;
    1034         }
    1035 
    1036         istype & ?|?( istype & is, _Istream_Cstr f ) with( f ) {
    1037                 const char * scanset;
    1038                 size_t nscanset = 0;
    1039                 if ( flags.delimiter ) scanset = delimiters;    // getline ?
    1040                 else scanset = f.scanset;
    1041                 if ( scanset ) nscanset = strlen( scanset );
    1042 
    1043                 char fmtstr[nscanset + 32];                                             // storage for scanset and format codes
    1044                 fmtstr[0] = '%';
    1045 
    1046                 int pos = 1;
    1047                 int args;
    1048                 bool check = true;
    1049 
    1050                 if ( f.flags.ignore ) { check = false; fmtstr[1] = '*'; pos += 1; }
    1051                 int rwd = f.wd;
    1052                 if ( f.wd != -1 ) {                                                             // => just ignore versus ignore with width
    1053                         // wd is buffer bytes available (for input chars + null terminator)
    1054                         // rwd is count of input chars
    1055                         // no maximum width necessary because text ignored => width is read width
    1056                         if ( f.flags.rwd ) check = false;
    1057                         else rwd = f.wd - 1;
    1058                         pos += sprintf( &fmtstr[pos], "%d", rwd );
    1059                 } // if
    1060 
    10611036                if ( ! scanset ) {                                                              // %s, %*s, %ws, %*ws
    1062                         // fprintf( stderr, "cstr %s\n", f.s );
     1037                        // fprintf( stderr, "cstr %s\n", s );
    10631038                        strcpy( &fmtstr[pos], "s%n" );
    10641039                        int len = 0;                                                            // may not be set in fmt
    1065                         if ( f.flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
    1066                         else args = fmt( is, fmtstr, f.s, &len );
    1067                         // fprintf( stderr, "cstr %s %d %d %d %s\n", fmtstr, args, len, f.wd, f.s );
     1040                        if ( flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
     1041                        else args = fmt( is, fmtstr, s, &len );
     1042                        // fprintf( stderr, "cstr %s %d %d %d %s\n", fmtstr, args, len, wd, s );
    10681043                        if ( check && len >= rwd && ! eof( is ) ) {     // might not fit
    10691044                                char peek;
     
    10761051                        } // if
    10771052                        // FIX ME: CFA strings need to be modified to NOT change the argument for this case, then this can be removed.
    1078                         if ( ! f.flags.ignore && rwd > 0 && args == 0 ) f.s[0]= '\0';   // read failed => no pattern match => set string to null
     1053                        if ( ! flags.ignore && args == 0 ) s[0]= '\0'; // read failed => no pattern match => set string to null
    10791054                } else {
    1080                         if ( f.flags.delimiter ) {                                      // getline
     1055                        if ( flags.delimiter ) {                                        // getline
    10811056                                int len = 0;                                                    // may not be set in fmt
    1082                                 sprintf( &fmtstr[pos], "[^%c]%%n", f.delimiters[0] );
    1083                                 if ( f.flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
    1084                                 else args = fmt( is, fmtstr, f.s, &len );
     1057                                sprintf( &fmtstr[pos], "[^%c]%%n", delimiters[0] );
     1058                                if ( flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
     1059                                else args = fmt( is, fmtstr, s, &len );
    10851060                                if ( check && len == rwd && ! eof( is ) ) {     // might not fit
    1086                                         fmtstr[0] = f.delimiters[0]; fmtstr[1] = '%'; fmtstr[2] = 'n'; fmtstr[3] = '\0';
    1087                                         fmt( is, fmtstr, &len );                        // remove delimiter
     1061                                        char peek;
     1062                                        fmt( is, "%c", &peek );                         // check for delimiter
    10881063                                        if ( ! eof( is ) ) {
    1089 //                                              if ( peek != f.delimiter[0] ) {
    1090                                                 if ( len != 1 ) {
    1091 //                                                      ungetc( is, peek );
     1064                                                if ( peek != delimiters[0] ) {
     1065                                                        ungetc( is, peek );
    10921066                                                        throwResume ExceptionInst( cstring_length );
    10931067                                                } // if
     
    10971071                                // incl %[xxx],  %*[xxx],  %w[xxx],  %*w[xxx]
    10981072                                // excl %[^xxx], %*[^xxx], %w[^xxx], %*w[^xxx]
    1099                                 sprintf( &fmtstr[pos], "[%s%s]%%n", f.flags.inex ? "^" : "", scanset );
    1100                                 // fprintf( stderr, "incl/excl %s %d\n", fmtstr, f.wd );
     1073                                sprintf( &fmtstr[pos], "[%s%s]%%n", flags.inex ? "^" : "", scanset );
     1074                                // fprintf( stderr, "incl/excl %s %d\n", fmtstr, wd );
    11011075                                int len = 0;                                                    // may not be set in fmt
    1102                                 if ( f.flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
    1103                                 else args = fmt( is, fmtstr, f.s, &len );
    1104                                 // fprintf( stderr, "incl/excl %s \"%s\" %d %d %d %d %d %c\n", fmtstr, f.s, args, f.wd, len, eof( is ), check, f.s[f.wd] );
     1076                                if ( flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
     1077                                else args = fmt( is, fmtstr, s, &len );
     1078                                // fprintf( stderr, "incl/excl %s \"%s\" %d %d %d %d %d %c\n", fmtstr, s, args, wd, len, eof( is ), check, s[wd] );
    11051079                                if ( check && len == rwd && ! eof( is ) ) {     // might not fit
    11061080                                        // fprintf( stderr, "overflow\n" );
     
    11101084                                        if ( ! eof( is ) ) {
    11111085                                                ungetc( is, peek );
    1112                                                 if ( f.flags.inex ^ strchr( f.scanset, peek ) != 0p ) throwResume ExceptionInst( cstring_length );
     1086                                                if ( flags.inex ^ strchr( scanset, peek ) != 0p ) throwResume ExceptionInst( cstring_length );
    11131087                                        } // if
    11141088                                } // if
    11151089                        } // if
    1116                         if ( ! f.flags.ignore && rwd > 0 && args == 0 ) f.s[0]= '\0';   // read failed => no pattern match => set string to null
     1090                        if ( ! flags.ignore && args == 0 ) s[0]= '\0'; // read failed => no pattern match => set string to null
    11171091                } // if
    11181092                if ( args == 1 && eof( is ) ) {                                 // data but scan ended at EOF
     
    11231097        } // ?|?
    11241098
    1125         istype & ?|?( istype & is, _Istream_Char f ) {
    1126                 fmt( is, "%*c" );                                                               // argument variable unused
     1099        istype & ?|?( istype & is, _Istream_Char f ) with(f) {
     1100                if ( ignore ) {
     1101                        fmt( is, "%*c" );                                                       // argument variable unused
     1102                } else {
     1103                        int len = -1, args = fmt( is, fmt, &c, &len );
     1104                        if ( args != -1 && len == -1 ) throwResume ExceptionInst( missing_data );
     1105                } // if
    11271106                return is;
    11281107        } // ?|?
  • libcfa/src/iostream.hfa

    r64c4b4d r5764204  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jan 21 22:42:40 2024
    13 // Update Count     : 655
     12// Last Modified On : Thu Jan 25 08:39:04 2024
     13// Update Count     : 696
    1414//
    1515
     
    404404}; // _Istream_str_base
    405405
    406 struct _Istream_Cstr {
     406struct _Istream_Cwidth {
    407407        char * s;
    408408        inline _Istream_str_base;
    409409}; // _Istream_Cstr
    410410
     411// Restrict nesting of input manipulators to those combinations that make sense.
     412
     413struct _Istream_Cstr {
     414        _Istream_Cwidth cstr;
     415}; // _Istream_Cstr
     416
    411417struct _Istream_Cquoted {
    412         _Istream_Cstr cstr;
     418        _Istream_Cwidth cstr;
    413419}; // _Istream_Cquoted
    414420
    415421static inline {
    416         // width must include room for null terminator
    417         _Istream_Cstr wdi( unsigned int wd, char s[] ) { return (_Istream_Cstr)@{ .s : s, { {.scanset : 0p}, .wd : wd, {.all : 0} } }; }
    418         _Istream_Cstr wdi( unsigned int wd, unsigned int rwd, char s[] ) {
    419                 if ( wd <= rwd ) throw (cstring_length){ &cstring_length_vt };
    420                 return (_Istream_Cstr)@{ .s : s, { {.scanset : 0p}, .wd : rwd, {.flags.rwd : true} } };
     422        // width must include room for null terminator, (gcc) scanf does not allow a 0 width => wd > 1 (1 char and null) and rd > 0 (1 char);
     423        _Istream_Cwidth wdi( unsigned int wd, char s[] ) {
     424                if ( wd <= 1 ) throw (cstring_length){ &cstring_length_vt }; // minimum 1 character and null terminator
     425                return (_Istream_Cwidth)@{ .s : s, { {.scanset : 0p}, .wd : wd, {.all : 0} } };
    421426        }
    422         _Istream_Cquoted & quoted( _Istream_Cstr & fmt, const char Ldelimiter = '"', const char Rdelimiter = '\0' ) {
    423                 fmt.delimiters[0] = Ldelimiter;  fmt.delimiters[1] = Rdelimiter;  fmt.delimiters[2] = '\0';
    424                 return (_Istream_Cquoted &)fmt;
     427        _Istream_Cwidth wdi( unsigned int wd, unsigned int rwd, char s[] ) {
     428                if ( wd <= 1 || wd <= rwd ) throw (cstring_length){ &cstring_length_vt }; // minimum 1 character, null terminator, plus subset
     429                return (_Istream_Cwidth)@{ .s : s, { {.scanset : 0p}, .wd : rwd, {.flags.rwd : true} } };
    425430        }
    426         _Istream_Cstr & getline( _Istream_Cstr & fmt, const char delimiter = '\n' ) {
    427                 fmt.delimiters[0] = delimiter; fmt.delimiters[1] = '\0'; fmt.flags.delimiter = true; fmt.flags.inex = true; return fmt;
     431        _Istream_Cquoted & quoted( _Istream_Cwidth & f, const char Ldelimiter = '"', const char Rdelimiter = '\0' ) {
     432                f.delimiters[0] = Ldelimiter;  f.delimiters[1] = Rdelimiter;  f.delimiters[2] = '\0';
     433                return (_Istream_Cquoted &)f;
    428434        }
    429         _Istream_Cstr & incl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = false; return fmt; }
    430         _Istream_Cstr & excl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = true; return fmt; }
    431         _Istream_Cstr ignore( char s[] ) { return (_Istream_Cstr)@{ .s : s, { {.scanset : 0p}, .wd : -1, {.flags.ignore : true} } }; }
    432         _Istream_Cstr & ignore( _Istream_Cstr & fmt ) { fmt.flags.ignore = true; return fmt; }
     435        _Istream_Cstr & getline( _Istream_Cwidth & f, const char delimiter = '\n' ) {
     436                f.delimiters[0] = delimiter; f.delimiters[1] = '\0'; f.flags.delimiter = true; return (_Istream_Cstr &)f;
     437        }
     438        _Istream_Cstr & incl( const char scanset[], _Istream_Cwidth & f ) { f.scanset = scanset; f.flags.inex = false; return (_Istream_Cstr &)f; }
     439        _Istream_Cstr & excl( const char scanset[], _Istream_Cwidth & f ) { f.scanset = scanset; f.flags.inex = true; return (_Istream_Cstr &)f; }
     440        _Istream_Cstr ignore( char s[] ) { return (_Istream_Cwidth)@{ .s : s, { {.scanset : 0p}, .wd : -1, {.flags.ignore : true} } }; }
     441        _Istream_Cstr & ignore( _Istream_Cwidth & f ) { f.flags.ignore = true; return (_Istream_Cstr &)f; }
     442        _Istream_Cquoted & ignore( _Istream_Cquoted & f ) { f.cstr.flags.ignore = true; return (_Istream_Cquoted &)f; }
     443        _Istream_Cstr & ignore( _Istream_Cstr & f ) { f.cstr.flags.ignore = true; return (_Istream_Cstr &)f; }
    433444} // distribution
    434445
    435446forall( istype & | basic_istream( istype ) ) {
    436         istype & ?|?( istype & is, _Istream_Cstr f );
    437447        istype & ?|?( istype & is, _Istream_Cskip f );
    438448        istype & ?|?( istype & is, _Istream_Cquoted f );
     449        istype & ?|?( istype & is, _Istream_Cstr f );
     450        static inline {
     451                istype & ?|?( istype & is, _Istream_Cwidth f ) { return is | *(_Istream_Cstr *)&f; }
     452        } // distribution
    439453} // distribution
    440454
  • tests/io/.expect/manipulatorsInput.x64.txt

    r64c4b4d r5764204  
    222216 get this line
    232317 @# this line 1)-{}
    24 18 abc
    25 19 abc 
    26 20  d d
     2418 @# this line 1)-{}
     2519 abc
     2620 abc 
     2721  d d
    2728
    2829d
    29 21              ZC44%
     3022              ZC44%
     3123              ZC44%
    30321 yyyyyyyyyyyyyyyyyyyy
    31332 abcxxx
     
    454716 get this line
    464817 @# this line 1)-{}
    47 18 abc
    48 19 abc 
    49 20 d d
     4918 @# this line 1)-{}
     5019 abc
     5120 abc 
     5221 d d
    5053
    5154d
    52 21              ZC44%
     5522              ZC44%
     5623              ZC44%
    5357a
    5458a
  • tests/io/.in/manipulatorsInput.txt

    r64c4b4d r5764204  
    1212get this line
    1313@# this line 1)-{}%
     14@# this line 2)-{}%
    1415"abc"
    1516'abc  '
     
    1819d }
    1920X               ZC44%Y
     21X               ZC55%Y
    2022abc
    2123cccccb
     
    2729get this line
    2830@# this line 1)-{}%
     31@# this line 2)-{}%
    2932"abc"
    3033'abc  '
     
    3336d }
    3437X               ZC44%Y
     38X               ZC55%Y
    3539ab
    36400xff 017 15-15
  • tests/io/manipulatorsInput.cfa

    r64c4b4d r5764204  
    77// Created On       : Sat Jun  8 17:58:54 2019
    88// Last Modified By : Peter A. Buhr
    9 // Last Modified On : Wed Jan  3 11:15:04 2024
    10 // Update Count     : 103
     9// Last Modified On : Wed Jan 24 18:36:32 2024
     10// Update Count     : 104
    1111//
    1212
     
    8181                scanf( "%[^\n]\n", s );                                                 printf( "16 %s\n", s );                // |get this line\n|
    8282                scanf( "%[^%%]%%\n", s );                                               printf( "17 %s\n", s );                // |@# this line 1)-{}%\n|
     83                scanf( "%*[^%%]%%\n", s );                                              printf( "18 %s\n", s );                // |@# this line 1)-{}%\n|
    8384
    8485                scanf( "%*[ \f\n\r\t\v]" );                                             // ignore whitespace                   // ||
    85                 scanf( "\"%[^\"]\"", s );                                               printf( "18 %s\n", s );                // |"abc"|
    86                 scanf( "%*[ \f\n\r\t\v]" );                                             // ignore whitespace                   // |\n|
    87                 scanf( "'%[^']'", s );                                                  printf( "19 %s\n", s );                // |'abc  '|
    88                 scanf( "%*[ \f\n\r\t\v]" );                                             // ignore whitespace                   // |\n|
    89                 scanf( "{%[^}]}", s );                                                  printf( "20 %s\n", s );                // |{ d d\n\nd }|
    90                 scanf( "%*[ \f\n\r\t\v]" );                                             // ignore whitespace                   // |\n|
    91                 scanf( "X%[^Y]Y", s );                                                  printf( "21 %s\n", s );                // |X            ZC44%Y|
     86                scanf( "\"%[^\"]\"", s );                                               printf( "19 %s\n", s );                // |"abc"|
     87                scanf( "%*[ \f\n\r\t\v]" );                                             // ignore whitespace                   // |\n|
     88                scanf( "'%[^']'", s );                                                  printf( "20 %s\n", s );                // |'abc  '|
     89                scanf( "%*[ \f\n\r\t\v]" );                                             // ignore whitespace                   // |\n|
     90                scanf( "{%[^}]}", s );                                                  printf( "21 %s\n", s );                // |{ d d\n\nd }|
     91                scanf( "%*[ \f\n\r\t\v]" );                                             // ignore whitespace                   // |\n|
     92                scanf( "X%[^Y]Y", s );                                                  printf( "22 %s\n", s );                // |X            ZC44%Y|
     93                scanf( "%*[ \f\n\r\t\v]" );                                             // ignore whitespace                   // |\n|
     94                scanf( "X%*[^Y]Y", s );                                                 printf( "23 %s\n", s );                // |X            ZC44%Y|
    9295                scanf( "\n" );                                                                  // must start next line                // |\n|
    9396        }
     
    118121                sin | getline( wdi( sizeof(s), s ) );                   sout | "16" | s;
    119122                sin | getline( wdi( sizeof(s), s ), '%' ) | "\n"; sout | "17" | s;
    120 
    121                 sin | quoted( wdi( sizeof(s), s ) );                    sout | "18" | s;
    122                 sin | quoted( wdi( sizeof(s), s ), '\'' );              sout | "19" | s;
    123                 sin | quoted( wdi( sizeof(s), s ), '{', '}' );  sout | "20" | s;
    124                 sin | quoted( wdi( sizeof(s), s ), 'X', 'Y' );  sout | "21" | s;
     123                sin | ignore( getline( wdi( sizeof(s), s ), '%' ) ) | "\n"; sout | "18" | s;
     124
     125                sin | quoted( wdi( sizeof(s), s ) );                    sout | "19" | s;
     126                sin | quoted( wdi( sizeof(s), s ), '\'' );              sout | "20" | s;
     127                sin | quoted( wdi( sizeof(s), s ), '{', '}' );  sout | "21" | s;
     128                sin | quoted( wdi( sizeof(s), s ), 'X', 'Y' );  sout | "22" | s;
     129                sin | ignore( quoted( wdi( sizeof(s), s ), 'X', 'Y' ) ); sout | "23" | s;
    125130        }
    126131    // Keep harmonized with collections/string-istream-manip
Note: See TracChangeset for help on using the changeset viewer.