Changeset 32490deb for libcfa/src


Ignore:
Timestamp:
Jan 31, 2024, 6:40:25 PM (22 months ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
496ffc17
Parents:
c75b30a (diff), e71b09a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
libcfa/src
Files:
4 edited

Legend:

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

    rc75b30a r32490deb  
    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/fstream.cfa

    rc75b30a r32490deb  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Nov 15 10:51:14 2023
    13 // Update Count     : 552
     12// Last Modified On : Sun Jan 28 09:56:08 2024
     13// Update Count     : 554
    1414//
    1515
     
    209209void ?{}( ifstream & is, void * file ) with( is ) {
    210210        file$ = file;
    211         nlOnOff$ = false;
     211        nlOnOff$ = false;                                                                       // => skip newlines when reading single characters
    212212} // ?{}
    213213
  • libcfa/src/iostream.cfa

    rc75b30a r32490deb  
    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 : Sun Jan 28 11:58:54 2024
     13// Update Count     : 1917
    1414//
    1515
     
    944944        istype & nl( istype & is ) {
    945945                fmt( is, "%*[^\n]" );                                                   // ignore characters to newline
    946                 if ( ! eof( is ) && getANL$( is ) ) fmt( is, "%*c" ); // read newline
     946                if ( ! eof( is ) ) fmt( is, "%*c" );                    // read newline
    947947                return is;
    948948        } // nl
     
    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                // read failed => no pattern match => set string to null
     1005                if ( ! flags.ignore && s != 0p && args == 0 ) s[0] = '\0';
     1006                if ( args == 1 && eof( is ) ) {                                 // data but scan ended at EOF
     1007                        clear( is );                                                            // => reset EOF => detect again on next read
     1008                } // if
     1009                return is;
     1010        }
     1011
     1012        istype & ?|?( istype & is, _Istream_Cstr f ) with( f.cstr ) {
     1013                const char * scanset;
     1014                size_t nscanset = 0;
     1015                if ( flags.delimiter ) scanset = delimiters;    // getline ?
     1016                else scanset = f.cstr.scanset;
     1017                if ( scanset ) nscanset = strlen( scanset );
     1018
     1019                char fmtstr[nscanset + 32];                                             // storage for scanset and format codes
    9881020                fmtstr[0] = '%';
    989 
    9901021                int pos = 1;
    9911022                int args;
    9921023                bool check = true;
    9931024
    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
     1025                if ( flags.ignore ) { check = false; fmtstr[1] = '*'; pos += 1; }
     1026                int rwd = wd;
     1027                if ( wd != -1 ) {                                                               // => just ignore versus ignore with width
    9971028                        // wd is buffer bytes available (for input chars + null terminator)
    9981029                        // rwd is count of input chars
    9991030                        // no maximum width necessary because text ignored => width is read width
    1000                         if ( cstr.flags.rwd ) check = false;
    1001                         else rwd = cstr.wd - 1;
     1031                        if ( flags.rwd ) check = false;
     1032                        else rwd = wd - 1;
     1033                        assert( rwd > 0 );
    10021034                        pos += sprintf( &fmtstr[pos], "%d", rwd );
    10031035                } // if
    10041036
    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 
    10611037                if ( ! scanset ) {                                                              // %s, %*s, %ws, %*ws
    1062                         // fprintf( stderr, "cstr %s\n", f.s );
     1038                        // fprintf( stderr, "cstr %s\n", s );
    10631039                        strcpy( &fmtstr[pos], "s%n" );
    10641040                        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 );
     1041                        if ( flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
     1042                        else args = fmt( is, fmtstr, s, &len );
     1043                        // fprintf( stderr, "cstr %s %d %d %d %s\n", fmtstr, args, len, wd, s );
    10681044                        if ( check && len >= rwd && ! eof( is ) ) {     // might not fit
    10691045                                char peek;
     
    10761052                        } // if
    10771053                        // FIX ME: CFA strings need to be modified to NOT change the argument for this case, then this can be removed.
    1078                         if ( rwd > 0 && args == 0 ) f.s[0]= '\0';       // read failed => no pattern match => set string to null
     1054                        if ( ! flags.ignore && args == 0 ) s[0]= '\0'; // read failed => no pattern match => set string to null
    10791055                } else {
    1080                         if ( f.flags.delimiter ) {                                      // getline
     1056                        if ( flags.delimiter ) {                                        // getline
    10811057                                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 );
     1058                                if ( delimiters[2] != '\0' ) {                  // read single character ?
     1059                                        sprintf( &fmtstr[pos], "c%%n" );
     1060                                } else {
     1061                                        sprintf( &fmtstr[pos], "[^%c]%%n", delimiters[0] );
     1062                                } // if
     1063                                if ( flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
     1064                                else args = fmt( is, fmtstr, s, &len );
    10851065                                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
     1066                                        char peek;
     1067                                        fmt( is, "%c", &peek );                         // check for delimiter
    10881068                                        if ( ! eof( is ) ) {
    1089 //                                              if ( peek != f.delimiter[0] ) {
    1090                                                 if ( len != 1 ) {
    1091 //                                                      ungetc( is, peek );
     1069                                                if ( peek != delimiters[0] ) {
     1070                                                        ungetc( is, peek );
    10921071                                                        throwResume ExceptionInst( cstring_length );
    10931072                                                } // if
     
    10971076                                // incl %[xxx],  %*[xxx],  %w[xxx],  %*w[xxx]
    10981077                                // 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 );
     1078                                sprintf( &fmtstr[pos], "[%s%s]%%n", flags.inex ? "^" : "", scanset );
     1079                                // fprintf( stderr, "incl/excl %s %d\n", fmtstr, wd );
    11011080                                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] );
     1081                                if ( flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
     1082                                else args = fmt( is, fmtstr, s, &len );
     1083                                // fprintf( stderr, "incl/excl %s \"%s\" %d %d %d %d %d %c\n", fmtstr, s, args, wd, len, eof( is ), check, s[wd] );
    11051084                                if ( check && len == rwd && ! eof( is ) ) {     // might not fit
    11061085                                        // fprintf( stderr, "overflow\n" );
     
    11101089                                        if ( ! eof( is ) ) {
    11111090                                                ungetc( is, peek );
    1112                                                 if ( f.flags.inex ^ strchr( f.scanset, peek ) != 0p ) throwResume ExceptionInst( cstring_length );
     1091                                                if ( flags.inex ^ strchr( scanset, peek ) != 0p ) throwResume ExceptionInst( cstring_length );
    11131092                                        } // if
    11141093                                } // if
    11151094                        } // if
    1116                         if ( rwd > 0 && args == 0 ) f.s[0]= '\0';       // read failed => no pattern match => set string to null
     1095                        if ( ! flags.ignore && args == 0 ) s[0]= '\0'; // read failed => no pattern match => set string to null
    11171096                } // if
    11181097                if ( args == 1 && eof( is ) ) {                                 // data but scan ended at EOF
     
    11201099                        clear( is );                                                            // => reset EOF => detect again on next read
    11211100                } // if
    1122                 return is;
    1123         } // ?|?
    1124 
    1125         istype & ?|?( istype & is, _Istream_Char f ) {
    1126                 fmt( is, "%*c" );                                                               // argument variable unused
    11271101                return is;
    11281102        } // ?|?
     
    11451119} // distribution
    11461120
     1121INPUT_FMT_IMPL( char, "c" )
    11471122INPUT_FMT_IMPL( signed char, "hhi" )
    11481123INPUT_FMT_IMPL( unsigned char, "hhi" )
  • libcfa/src/iostream.hfa

    rc75b30a r32490deb  
    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:18 2024
    13 // Update Count     : 610
     12// Last Modified On : Sun Jan 28 11:56:29 2024
     13// Update Count     : 733
    1414//
    1515
     
    196196// *********************************** integral ***********************************
    197197
    198 // See 6.7.9. 19) The initialization shall occur in initializer list order, each initializer provided for a particular
    199 // subobject overriding any previously listed initializer for the same subobject; ***all subobjects that are not
    200 // initialized explicitly shall be initialized implicitly the same as objects that have static storage duration.***
    201 
    202198#define INTEGRAL_FMT_DECL( T, CODE ) \
    203199static inline { \
    204         _Ostream_Manip(T) bin( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'b', { .all : 0 } }; } \
    205         _Ostream_Manip(T) oct( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'o', { .all : 0 } }; } \
    206         _Ostream_Manip(T) hex( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'x', { .all : 0 } }; } \
    207         _Ostream_Manip(T) wd( unsigned int w, T val ) { return (_Ostream_Manip(T))@{ val, w, 0, CODE, { .all : 0 } }; } \
    208         _Ostream_Manip(T) wd( unsigned int w, unsigned int pc, T val ) { return (_Ostream_Manip(T))@{ val, w, pc, CODE, { .flags.pc : true } }; } \
    209         _Ostream_Manip(T) & wd( unsigned int w, _Ostream_Manip(T) & fmt ) { fmt.wd = w; return fmt; } \
    210         _Ostream_Manip(T) & wd( unsigned int w, unsigned int pc, _Ostream_Manip(T) & fmt ) { fmt.wd = w; fmt.pc = pc; fmt.flags.pc = true; return fmt; } \
     200        _Ostream_Manip(T) bin( T val ) { return (_Ostream_Manip(T))@{ .val : val, .wd : 1, .pc : 0, .base : 'b', { .all : 0 } }; } \
     201        _Ostream_Manip(T) oct( T val ) { return (_Ostream_Manip(T))@{ .val : val, .wd : 1, .pc : 0, .base : 'o', { .all : 0 } }; } \
     202        _Ostream_Manip(T) hex( T val ) { return (_Ostream_Manip(T))@{ .val : val, .wd : 1, .pc : 0, .base : 'x', { .all : 0 } }; } \
     203        _Ostream_Manip(T) wd( unsigned int wd, T val ) { return (_Ostream_Manip(T))@{ .val : val, .wd : wd, .pc : 0, .base : CODE, { .all : 0 } }; } \
     204        _Ostream_Manip(T) wd( unsigned int wd, unsigned int pc, T val ) { return (_Ostream_Manip(T))@{ .val : val, .wd : wd, .pc : pc, .base : CODE, { .flags.pc : true } }; } \
     205        _Ostream_Manip(T) & wd( unsigned int wd, _Ostream_Manip(T) & fmt ) { fmt.wd = wd; return fmt; } \
     206        _Ostream_Manip(T) & wd( unsigned int wd, unsigned int pc, _Ostream_Manip(T) & fmt ) { fmt.wd = wd; fmt.pc = pc; fmt.flags.pc = true; return fmt; } \
    211207        _Ostream_Manip(T) & left( _Ostream_Manip(T) & fmt ) { fmt.flags.left = true; return fmt; } \
    212208        _Ostream_Manip(T) & upcase( _Ostream_Manip(T) & fmt ) { if ( fmt.base == 'x' || fmt.base == 'b' ) fmt.base -= 32; /* upper case */ return fmt; } \
    213209        _Ostream_Manip(T) & nobase( _Ostream_Manip(T) & fmt ) { fmt.flags.nobsdp = true; return fmt; } \
    214210        _Ostream_Manip(T) & pad0( _Ostream_Manip(T) & fmt ) { fmt.flags.pad0 = true; return fmt; } \
    215         _Ostream_Manip(T) sign( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, CODE, { .flags.sign : true } }; } \
     211        _Ostream_Manip(T) sign( T val ) { return (_Ostream_Manip(T))@{ .val : val, .wd : 1, .pc : 0, .base : CODE, { .flags.sign : true } }; } \
    216212        _Ostream_Manip(T) & sign( _Ostream_Manip(T) & fmt ) { fmt.flags.sign = true; return fmt; } \
    217213} /* distribution */ \
     
    241237#define FLOATING_POINT_FMT_DECL( T ) \
    242238static inline { \
    243         _Ostream_Manip(T) hex( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'a', { .all : 0 } }; } \
    244         _Ostream_Manip(T) sci( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'e', { .all : 0 } }; } \
    245         _Ostream_Manip(T) eng( T val ) { return (_Ostream_Manip(T))@{ val, 1, -1, 'g', { .flags.eng : true } }; } \
    246         _Ostream_Manip(T) wd( unsigned int w, T val ) { return (_Ostream_Manip(T))@{ val, w, 0, 'g', { .all : 0 } }; } \
    247         _Ostream_Manip(T) wd( unsigned int w, unsigned int pc, T val ) { return (_Ostream_Manip(T))@{ val, w, pc, 'f', { .flags.pc : true } }; } \
    248         _Ostream_Manip(T) ws( unsigned int w, unsigned int pc, T val ) { return (_Ostream_Manip(T))@{ val, w, pc, 'g', { .flags.pc : true } }; } \
    249         _Ostream_Manip(T) & wd( unsigned int w, _Ostream_Manip(T) & fmt ) { if ( fmt.flags.eng ) fmt.base = 'f'; fmt.wd = w; return fmt; } \
    250         _Ostream_Manip(T) & wd( unsigned int w, unsigned int pc, _Ostream_Manip(T) & fmt ) { if ( fmt.flags.eng ) fmt.base = 'f'; fmt.wd = w; fmt.pc = pc; fmt.flags.pc = true; return fmt; } \
    251         _Ostream_Manip(T) & ws( unsigned int w, unsigned int pc, _Ostream_Manip(T) & fmt ) { fmt.wd = w; fmt.pc = pc; fmt.flags.pc = true; return fmt; } \
     239        _Ostream_Manip(T) hex( T val ) { return (_Ostream_Manip(T))@{ .val : val, .wd : 1, .pc : 0, .base : 'a', { .all : 0 } }; } \
     240        _Ostream_Manip(T) sci( T val ) { return (_Ostream_Manip(T))@{ .val : val, .wd : 1, .pc : 0, .base : 'e', { .all : 0 } }; } \
     241        _Ostream_Manip(T) eng( T val ) { return (_Ostream_Manip(T))@{ .val : val, 1, -1, .base : 'g', { .flags.eng : true } }; } \
     242        _Ostream_Manip(T) wd( unsigned int wd, T val ) { return (_Ostream_Manip(T))@{ .val : val, .wd : wd, .pc : 0, .base : 'g', { .all : 0 } }; } \
     243        _Ostream_Manip(T) wd( unsigned int wd, unsigned int pc, T val ) { return (_Ostream_Manip(T))@{ .val : val, .wd : wd, .pc : pc, .base : 'f', { .flags.pc : true } }; } \
     244        _Ostream_Manip(T) ws( unsigned int wd, unsigned int pc, T val ) { return (_Ostream_Manip(T))@{ .val : val, .wd : wd, .pc : pc, .base : 'g', { .flags.pc : true } }; } \
     245        _Ostream_Manip(T) & wd( unsigned int wd, _Ostream_Manip(T) & fmt ) { if ( fmt.flags.eng ) fmt.base = 'f'; fmt.wd = wd; return fmt; } \
     246        _Ostream_Manip(T) & wd( unsigned int wd, unsigned int pc, _Ostream_Manip(T) & fmt ) { \
     247                if ( fmt.flags.eng ) fmt.base = 'f'; fmt.wd = wd; fmt.pc = pc; fmt.flags.pc = true; return fmt; } \
     248        _Ostream_Manip(T) & ws( unsigned int wd, unsigned int pc, _Ostream_Manip(T) & fmt ) { fmt.wd = wd; fmt.pc = pc; fmt.flags.pc = true; return fmt; } \
    252249        _Ostream_Manip(T) & left( _Ostream_Manip(T) & fmt ) { fmt.flags.left = true; return fmt; } \
    253         _Ostream_Manip(T) upcase( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'G', { .all : 0 } }; } \
     250        _Ostream_Manip(T) upcase( T val ) { return (_Ostream_Manip(T))@{ .val : val, .wd : 1, .pc : 0, .base : 'G', { .all : 0 } }; } \
    254251        _Ostream_Manip(T) & upcase( _Ostream_Manip(T) & fmt ) { fmt.base -= 32; /* upper case */ return fmt; } \
    255252        _Ostream_Manip(T) & pad0( _Ostream_Manip(T) & fmt ) { fmt.flags.pad0 = true; return fmt; } \
    256         _Ostream_Manip(T) sign( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'g', { .flags.sign : true } }; } \
     253        _Ostream_Manip(T) sign( T val ) { return (_Ostream_Manip(T))@{ .val : val, .wd : 1, .pc : 0, .base : 'g', { .flags.sign : true } }; } \
    257254        _Ostream_Manip(T) & sign( _Ostream_Manip(T) & fmt ) { fmt.flags.sign = true; return fmt; } \
    258         _Ostream_Manip(T) nodp( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'g', { .flags.nobsdp : true } }; } \
     255        _Ostream_Manip(T) nodp( T val ) { return (_Ostream_Manip(T))@{ .val : val, .wd : 1, .pc : 0, .base : 'g', { .flags.nobsdp : true } }; } \
    259256        _Ostream_Manip(T) & nodp( _Ostream_Manip(T) & fmt ) { fmt.flags.nobsdp = true; return fmt; } \
    260         _Ostream_Manip(T) unit( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'g', { .flags.nobsdp : true } }; } \
     257        _Ostream_Manip(T) unit( T val ) { return (_Ostream_Manip(T))@{ .val : val, .wd : 1, .pc : 0, .base : 'g', { .flags.nobsdp : true } }; } \
    261258        _Ostream_Manip(T) & unit( _Ostream_Manip(T) & fmt ) { fmt.flags.nobsdp = true; return fmt; } \
    262259} /* distribution */ \
     
    272269
    273270static inline {
    274         _Ostream_Manip(char) bin( char c ) { return (_Ostream_Manip(char))@{ c, 1, 0, 'b', { .all : 0 } }; }
    275         _Ostream_Manip(char) oct( char c ) { return (_Ostream_Manip(char))@{ c, 1, 0, 'o', { .all : 0 } }; }
    276         _Ostream_Manip(char) hex( char c ) { return (_Ostream_Manip(char))@{ c, 1, 0, 'x', { .all : 0 } }; }
    277         _Ostream_Manip(char) wd( unsigned int w, char c ) { return (_Ostream_Manip(char))@{ c, w, 0, 'c', { .all : 0 } }; }
    278         _Ostream_Manip(char) & wd( unsigned int w, _Ostream_Manip(char) & fmt ) { fmt.wd = w; return fmt; }
     271        _Ostream_Manip(char) bin( char c ) { return (_Ostream_Manip(char))@{ .val : c, .wd : 1, .pc : 0, .base : 'b', { .all : 0 } }; }
     272        _Ostream_Manip(char) oct( char c ) { return (_Ostream_Manip(char))@{ .val : c, .wd : 1, .pc : 0, .base : 'o', { .all : 0 } }; }
     273        _Ostream_Manip(char) hex( char c ) { return (_Ostream_Manip(char))@{ .val : c, .wd : 1, .pc : 0, .base : 'x', { .all : 0 } }; }
     274        _Ostream_Manip(char) wd( unsigned int wd, char c ) { return (_Ostream_Manip(char))@{ c, wd, 0, .base : 'c', { .all : 0 } }; }
     275        _Ostream_Manip(char) & wd( unsigned int wd, _Ostream_Manip(char) & fmt ) { fmt.wd = wd; return fmt; }
    279276        _Ostream_Manip(char) & left( _Ostream_Manip(char) & fmt ) { fmt.flags.left = true; return fmt; }
    280277        _Ostream_Manip(char) & upcase( _Ostream_Manip(char) & fmt ) { if ( fmt.base == 'x' || fmt.base == 'b' ) fmt.base -= 32; /* upper case */ return fmt; }
     
    289286
    290287static inline {
    291         _Ostream_Manip(const char *) bin( const char s[] ) { return (_Ostream_Manip(const char *))@{ s, 1, 0, 'b', { .all : 0 } }; }
    292         _Ostream_Manip(const char *) oct( const char s[] ) { return (_Ostream_Manip(const char *))@{ s, 1, 0, 'o', { .all : 0 } }; }
    293         _Ostream_Manip(const char *) hex( const char s[] ) { return (_Ostream_Manip(const char *))@{ s, 1, 0, 'x', { .all : 0 } }; }
    294         _Ostream_Manip(const char *) wd( unsigned int w, const char s[] ) { return (_Ostream_Manip(const char *))@{ s, w, 0, 's', { .all : 0 } }; }
    295         _Ostream_Manip(const char *) wd( unsigned int w, unsigned int pc, const char s[] ) { return (_Ostream_Manip(const char *))@{ s, w, pc, 's', { .flags.pc : true } }; }
    296         _Ostream_Manip(const char *) & wd( unsigned int w, _Ostream_Manip(const char *) & fmt ) { fmt.wd = w; return fmt; }
    297         _Ostream_Manip(const char *) & wd( unsigned int w, unsigned int pc, _Ostream_Manip(const char *) & fmt ) { fmt.wd = w; fmt.pc = pc; fmt.flags.pc = true; return fmt; }
     288        _Ostream_Manip(const char *) bin( const char s[] ) { return (_Ostream_Manip(const char *))@{ .val : s, .wd : 1, .pc : 0, .base : 'b', { .all : 0 } }; }
     289        _Ostream_Manip(const char *) oct( const char s[] ) { return (_Ostream_Manip(const char *))@{ .val : s, .wd : 1, .pc : 0, .base : 'o', { .all : 0 } }; }
     290        _Ostream_Manip(const char *) hex( const char s[] ) { return (_Ostream_Manip(const char *))@{ .val : s, .wd : 1, .pc : 0, .base : 'x', { .all : 0 } }; }
     291        _Ostream_Manip(const char *) wd( unsigned int wd, const char s[] ) { return (_Ostream_Manip(const char *))@{ s, wd, 0, .base : 's', { .all : 0 } }; }
     292        _Ostream_Manip(const char *) wd( unsigned int wd, unsigned int pc, const char s[] ) { return (_Ostream_Manip(const char *))@{ s, .wd : wd, .pc : pc, .base : 's', { .flags.pc : true } }; }
     293        _Ostream_Manip(const char *) & wd( unsigned int wd, _Ostream_Manip(const char *) & fmt ) { fmt.wd = wd; return fmt; }
     294        _Ostream_Manip(const char *) & wd( unsigned int wd, unsigned int pc, _Ostream_Manip(const char *) & fmt ) { fmt.wd = wd; fmt.pc = pc; fmt.flags.pc = true; return fmt; }
    298295        _Ostream_Manip(const char *) & left( _Ostream_Manip(const char *) & fmt ) { fmt.flags.left = true; return fmt; }
    299296        _Ostream_Manip(const char *) & nobase( _Ostream_Manip(const char *) & fmt ) { fmt.flags.nobsdp = true; return fmt; }
     
    385382
    386383static inline {
    387         _Istream_Cskip skip( const char scanset[] ) { return (_Istream_Cskip)@{ scanset, 0 }; }
    388         _Istream_Cskip skip( unsigned int wd ) { return (_Istream_Cskip)@{ 0p, wd }; }
     384        _Istream_Cskip skip( const char scanset[] ) { return (_Istream_Cskip)@{ .scanset : scanset, .wd : 0 }; }
     385        _Istream_Cskip skip( unsigned int wd ) { return (_Istream_Cskip)@{ .scanset : 0p, .wd : wd }; }
    389386} // distribution
    390387
     
    400397                        unsigned char ignore:1;                                         // do not change input argument
    401398                        unsigned char inex:1;                                           // include/exclude characters in scanset
    402                         unsigned char delimiter:1;                                      // delimit character
     399                        unsigned char delimiter:1;                                      // delimit character(s)
    403400                        unsigned char rwd:1;                                            // read width
    404401                } flags;
     
    406403}; // _Istream_str_base
    407404
    408 struct _Istream_Cstr {
     405struct _Istream_Cwidth {
    409406        char * s;
    410407        inline _Istream_str_base;
    411408}; // _Istream_Cstr
    412409
     410// Restrict nesting of input manipulators to those combinations that make sense.
     411
     412struct _Istream_Cstr {
     413        _Istream_Cwidth cstr;
     414}; // _Istream_Cstr
     415
    413416struct _Istream_Cquoted {
    414         _Istream_Cstr cstr;
     417        _Istream_Cwidth cstr;
    415418}; // _Istream_Cquoted
    416419
    417420static inline {
    418         // width must include room for null terminator
    419         _Istream_Cstr wdi( unsigned int wd, char s[] ) { return (_Istream_Cstr)@{ s, { {0p}, wd, {.all : 0} } }; }
    420         _Istream_Cstr wdi( unsigned int wd, unsigned int rwd, char s[] ) {
    421                 if ( wd <= rwd ) throw (cstring_length){ &cstring_length_vt };
    422                 return (_Istream_Cstr)@{ s, { {0p}, rwd, {.flags.rwd : true} } };
     421        // 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);
     422        _Istream_Cwidth wdi( unsigned int wd, char s[] ) {
     423                if ( wd <= 1 ) throw (cstring_length){ &cstring_length_vt }; // minimum 1 character and null terminator
     424                return (_Istream_Cwidth)@{ .s : s, { {.scanset : 0p}, .wd : wd, {.all : 0} } };
    423425        }
    424         _Istream_Cquoted & quoted( _Istream_Cstr & fmt, const char Ldelimiter = '"', const char Rdelimiter = '\0' ) {
    425                 fmt.delimiters[0] = Ldelimiter;  fmt.delimiters[1] = Rdelimiter;  fmt.delimiters[2] = '\0';
    426                 return (_Istream_Cquoted &)fmt;
     426        _Istream_Cwidth wdi( unsigned int wd, unsigned int rwd, char s[] ) {
     427                if ( wd <= 1 || wd <= rwd ) throw (cstring_length){ &cstring_length_vt }; // minimum 1 character, null terminator, plus subset
     428                return (_Istream_Cwidth)@{ .s : s, { {.scanset : 0p}, .wd : rwd, {.flags.rwd : true} } };
    427429        }
    428         _Istream_Cstr & getline( _Istream_Cstr & fmt, const char delimiter = '\n' ) {
    429                 fmt.delimiters[0] = delimiter; fmt.delimiters[1] = '\0'; fmt.flags.delimiter = true; fmt.flags.inex = true; return fmt;
     430        _Istream_Cquoted quoted( char & ch, const char Ldelimiter = '\'', const char Rdelimiter = '\0' ) {
     431                return (_Istream_Cquoted)@{ { .s : &ch, { {.delimiters : { Ldelimiter, Rdelimiter, '\1' }}, .wd : 1, {.flags.rwd : true} } } };
    430432        }
    431         _Istream_Cstr & incl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = false; return fmt; }
    432         _Istream_Cstr & excl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = true; return fmt; }
    433         _Istream_Cstr ignore( char s[] ) { return (_Istream_Cstr)@{ s, { {0p}, -1, {.flags.ignore : true} } }; }
    434         _Istream_Cstr & ignore( _Istream_Cstr & fmt ) { fmt.flags.ignore = true; return fmt; }
     433        _Istream_Cquoted & quoted( _Istream_Cwidth & f, const char Ldelimiter = '"', const char Rdelimiter = '\0' ) {
     434                f.delimiters[0] = Ldelimiter;  f.delimiters[1] = Rdelimiter;  f.delimiters[2] = '\0';
     435                return (_Istream_Cquoted &)f;
     436        }
     437        _Istream_Cstr & getline( _Istream_Cwidth & f, const char delimiter = '\n' ) {
     438                f.delimiters[0] = delimiter; f.delimiters[1] = '\0'; f.flags.delimiter = true; return (_Istream_Cstr &)f;
     439        }
     440        _Istream_Cstr & incl( const char scanset[], _Istream_Cwidth & f ) { f.scanset = scanset; f.flags.inex = false; return (_Istream_Cstr &)f; }
     441        _Istream_Cstr & excl( const char scanset[], _Istream_Cwidth & f ) { f.scanset = scanset; f.flags.inex = true; return (_Istream_Cstr &)f; }
     442        _Istream_Cstr ignore( const char s[] ) { return (_Istream_Cwidth)@{ .s : (char *)s, { {.scanset : 0p}, .wd : -1, {.flags.ignore : true} } }; }
     443        _Istream_Cstr & ignore( _Istream_Cwidth & f ) { f.flags.ignore = true; return (_Istream_Cstr &)f; }
     444        _Istream_Cquoted & ignore( _Istream_Cquoted & f ) { f.cstr.flags.ignore = true; return (_Istream_Cquoted &)f; }
     445        _Istream_Cstr & ignore( _Istream_Cstr & f ) { f.cstr.flags.ignore = true; return (_Istream_Cstr &)f; }
    435446} // distribution
    436447
    437448forall( istype & | basic_istream( istype ) ) {
    438         istype & ?|?( istype & is, _Istream_Cstr f );
    439449        istype & ?|?( istype & is, _Istream_Cskip f );
    440450        istype & ?|?( istype & is, _Istream_Cquoted f );
    441 } // distribution
    442 
    443 struct _Istream_Char {
    444         bool ignore;                                                                            // do not change input argument
    445 }; // _Istream_Char
    446 
    447 static inline {
    448         _Istream_Char ignore( const char ) { return (_Istream_Char)@{ true }; }
    449         _Istream_Char & ignore( _Istream_Char & fmt ) { fmt.ignore = true; return fmt; }
    450 } // distribution
    451 forall( istype & | basic_istream( istype ) ) {
    452         istype & ?|?( istype & is, _Istream_Char f );
    453 }
     451        istype & ?|?( istype & is, _Istream_Cstr f );
     452        static inline {
     453                istype & ?|?( istype & is, _Istream_Cwidth f ) { return is | *(_Istream_Cstr *)&f; }
     454        } // distribution
     455} // distribution
    454456
    455457forall( T & | sized( T ) )
     
    462464#define INPUT_FMT_DECL( T ) \
    463465static inline { \
    464         _Istream_Manip(T) ignore( const T & val ) { return (_Istream_Manip(T))@{ (T &)val, -1, true }; } \
     466        _Istream_Manip(T) wdi( unsigned int wd, T & val ) { return (_Istream_Manip(T))@{ .val : val, .wd : wd, .ignore : false }; } \
     467        _Istream_Manip(T) ignore( const T & val ) { return (_Istream_Manip(T))@{ .val : (T &)val, .wd : -1, .ignore : true }; } \
    465468        _Istream_Manip(T) & ignore( _Istream_Manip(T) & fmt ) { fmt.ignore = true; return fmt; } \
    466         _Istream_Manip(T) wdi( unsigned int wd, T & val ) { return (_Istream_Manip(T))@{ val, wd, false }; } \
    467         _Istream_Manip(T) & wdi( unsigned int wd, _Istream_Manip(T) & fmt ) { fmt.wd = wd; return fmt; } \
    468469} /* distribution */ \
    469470forall( istype & | basic_istream( istype ) ) { \
     
    471472} // ?|?
    472473
     474INPUT_FMT_DECL( char )
    473475INPUT_FMT_DECL( signed char )
    474476INPUT_FMT_DECL( unsigned char )
Note: See TracChangeset for help on using the changeset viewer.