Changeset 7e1dbd7


Ignore:
Timestamp:
Aug 28, 2023, 7:05:05 PM (8 months ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
master
Children:
38de914, 4269d1b
Parents:
0926487
Message:

first attempt at input manipulators for strings

Location:
libcfa/src/containers
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/containers/string.cfa

    r0926487 r7e1dbd7  
    1010// Created On       : Fri Sep 03 11:00:00 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Aug 24 11:27:57 2023
    13 // Update Count     : 89
     12// Last Modified On : Mon Aug 28 19:00:45 2023
     13// Update Count     : 146
    1414//
    1515
     
    118118}
    119119
    120 void getline( ifstream & in, string & str, const char delimit = '\n' ) {
    121         // .---------------,
    122         // | | | | |...|0|0| check and guard
    123         // `---------------'
    124         enum { gwd = 256 + 2, wd = gwd - 1 };                           // guarded and unguarded width
     120static void readstr( ifstream & is, _Istream_str f, char fmtstr[], char cstr[] ) {
     121        int check = f.rwd - 1;
     122
     123        if ( ! f.flags.rwd ) cstr[check] = '\0';                        // insert sentinel
     124        int len = fmt( is, fmtstr, cstr );
     125        // fprintf( stderr, "KK %s %zd %d %c %s\n", fmtstr, len, check, cstr[check], cstr );
     126
     127        if ( ! f.flags.rwd && cstr[check] != '\0' )                     // sentinel overwritten ?
     128                throw (cstring_length){ &cstring_length_vt };
     129
     130        if ( f.flags.delimit ) {                                                        // getline ?
     131                if ( len == 0 ) cstr[0] = '\0';                                 // empty read => argument unchanged => set empty
     132                if ( ! eof( is ) ) fmt( is, "%*c" );                    // ignore delimiter
     133        } //if
     134} // readstr
     135
     136ifstream & ?|?( ifstream & is, _Istream_str f ) {
     137        // skip, same as for char *
     138        if ( ! &f.s ) {
     139                // fprintf( stderr,  "skip %s %d\n", f.scanset, f.wd );
     140                if ( f.rwd == -1 ) fmt( is, f.scanset, "" ); // no input arguments
     141                else for ( f.rwd ) fmt( is, "%*c" );
     142                return is;
     143        } // if
     144
     145        enum { gwd = 16 + 2, wd = gwd - 1 };                            // guarded and unguarded width
    125146        char cstr[gwd];                                                                         // read in chunks
    126147        bool cont = false;;
    127148
     149        if ( f.rwd == -1 ) f.rwd = wd;
     150        const char * scanset = f.scanset;;
     151        if ( f.flags.delimit ) scanset = f.delimit;                     // getline ?
     152
     153        size_t len = 0;
     154        if ( scanset ) len = strlen( scanset );
     155        char fmtstr[len + 16];
     156        int start = 1;
     157        fmtstr[0] = '%';
     158        if ( f.flags.ignore ) { fmtstr[1] = '*'; start += 1; }
     159        if ( f.rwd != -1 ) { start += sprintf( &fmtstr[start], "%d", f.rwd ); }
     160
     161        if ( ! scanset ) {
     162                // %s, %*s, %ws, %*ws
     163                fmtstr[start] = 's'; fmtstr[start + 1] = '\0';
     164                // printf( "cstr %s\n", fmtstr );
     165        } else {
     166                // incl %[xxx],  %*[xxx],  %w[xxx],  %*w[xxx]
     167                // excl %[^xxx], %*[^xxx], %w[^xxx], %*w[^xxx]
     168                fmtstr[start] = '['; start += 1;
     169                if ( f.flags.inex ) { fmtstr[start] = '^'; start += 1; }
     170                strcpy( &fmtstr[start], scanset );                              // copy includes '\0'
     171                len += start;
     172                fmtstr[len] = ']'; fmtstr[len + 1] = '\0';
     173                // printf( "incl/excl %s\n", fmtstr );
     174        } // if
     175
    128176        cstr[wd] = '\0';                                                                        // guard null terminate string
    129177        try {
    130                 in | getline( wdi( wd, cstr ), delimit );               // must have room for string terminator
    131                 if ( eof( in  ) ) return;                                               // do not change argument
     178                readstr( is, f, fmtstr, cstr );
    132179        } catch( cstring_length * ) {
    133                 cont = true;                                                                    // continue not allowed
     180                cont = true;
    134181        } finally {
    135                 str = cstr;                                                                             // ok to initialize string
     182                f.s = cstr;                                                                             // ok to initialize string
    136183        } // try
    137184        for ( ; cont; )  {                                                                      // overflow read ?
    138185                cont = false;
    139186                try {
    140                         in | getline( wdi( wd, cstr ), delimit );       // must have room for string terminator
    141                         if ( eof( in  ) ) return;
     187                        readstr( is, f, fmtstr, cstr );
    142188                } catch( cstring_length * ) {
    143189                        cont = true;                                                            // continue not allowed
    144190                } finally {
    145                         str += cstr;                                                            // build string chunk at a time
     191                        f.s += cstr;                                                            // build string chunk at a time
    146192                } // try
    147193        } // for
    148 }
     194        return is;
     195} // ?|?
     196
     197void ?|?( ifstream & in, _Istream_str f ) {
     198    (ifstream &)(in | f); ends( in );
     199}
     200
     201// void getline( ifstream & in, string & str, const char delimit = '\n' ) {
     202//      // .---------------,
     203//      // | | | | |...|0|0| check and guard
     204//      // `---------------'
     205//      enum { gwd = 128 + 2, wd = gwd - 1 };                           // guarded and unguarded width
     206//      char cstr[gwd];                                                                         // read in chunks
     207//      bool cont = false;;
     208
     209//      cstr[wd] = '\0';                                                                        // guard null terminate string
     210//      try {
     211//              in | getline( wdi( wd, cstr ), delimit );               // must have room for string terminator
     212//              if ( eof( in  ) ) return;                                               // do not change argument
     213//      } catch( cstring_length * ) {
     214//              cont = true;
     215//      } finally {
     216//              str = cstr;                                                                             // ok to initialize string
     217//      } // try
     218//      for ( ; cont; )  {                                                                      // overflow read ?
     219//              cont = false;
     220//              try {
     221//                      in | getline( wdi( wd, cstr ), delimit );       // must have room for string terminator
     222//                      if ( eof( in  ) ) return;
     223//              } catch( cstring_length * ) {
     224//                      cont = true;                                                            // continue not allowed
     225//              } finally {
     226//                      str += cstr;                                                            // build string chunk at a time
     227//              } // try
     228//      } // for
     229// }
    149230
    150231////////////////////////////////////////////////////////
  • libcfa/src/containers/string.hfa

    r0926487 r7e1dbd7  
    1010// Created On       : Fri Sep 03 11:00:00 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Aug 23 11:16:14 2023
    13 // Update Count     : 6
     12// Last Modified On : Mon Aug 28 18:32:59 2023
     13// Update Count     : 40
    1414//
    1515
     
    5757ifstream & ?|?(ifstream & in, string & s);
    5858void ?|?( ifstream & in, string & this );
     59
     60
     61struct _Istream_str {
     62        string & s;
     63        union {
     64                const char * scanset;
     65                char delimit[2];
     66        };
     67        int rwd;                                                                                        // read width
     68        union {
     69                unsigned char all;
     70                struct {
     71                        unsigned char ignore:1;                                         // do not change input argument
     72                        unsigned char inex:1;                                           // include/exclude characters in scanset
     73                        unsigned char delimit:1;                                        // delimit character
     74                        unsigned char rwd:1;                                            // read width
     75                } flags;
     76        };
     77}; // _Istream_str
     78
     79static inline {
     80        // read width does not include null terminator
     81        _Istream_str wdi( unsigned int rwd, string & s ) { return (_Istream_str)@{ s, {0p}, rwd, {.flags.rwd : true} }; }
     82        _Istream_str skip( const char scanset[] ) { return (_Istream_str)@{ *0p, {scanset}, -1, {.all : 0} }; }
     83        _Istream_str skip( unsigned int wd ) { return (_Istream_str)@{ *0p, {0p}, wd, {.all : 0} }; }
     84        _Istream_str getline( string & s, const char delimit = '\n' ) {
     85                return (_Istream_str)@{ s, {.delimit : { delimit, '\0' } }, -1, {.flags.delimit : true, .flags.inex : true} };
     86        }
     87        _Istream_str & getline( _Istream_str & fmt, const char delimit = '\n' ) {
     88                fmt.delimit[0] = delimit; fmt.delimit[1] = '\0'; fmt.flags.delimit = true; fmt.flags.inex = true; return fmt;
     89        }
     90        _Istream_str incl( const char scanset[], string & s ) { return (_Istream_str)@{ s, {scanset}, -1, {.flags.inex : false} }; }
     91        _Istream_str & incl( const char scanset[], _Istream_str & fmt ) { fmt.scanset = scanset; fmt.flags.inex = false; return fmt; }
     92        _Istream_str excl( const char scanset[], string & s ) { return (_Istream_str)@{ s, {scanset}, -1, {.flags.inex : true} }; }
     93        _Istream_str & excl( const char scanset[], _Istream_str & fmt ) { fmt.scanset = scanset; fmt.flags.inex = true; return fmt; }
     94        _Istream_str ignore( string & s ) { return (_Istream_str)@{ s, {0p}, -1, {.flags.ignore : true} }; }
     95        _Istream_str & ignore( _Istream_str & fmt ) { fmt.flags.ignore = true; return fmt; }
     96} // distribution
     97ifstream & ?|?( ifstream & is, _Istream_str f );
     98void ?|?( ifstream & is, _Istream_str t );
    5999void getline( ifstream & in, string & this, const char delimit = '\n' );
    60100
Note: See TracChangeset for help on using the changeset viewer.