Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/iostream.cfa

    re0dc038 r37ceccb  
     1
    12//
    23// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     
    1011// Created On       : Wed May 27 17:56:53 2015
    1112// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Oct 17 20:57:05 2023
    13 // Update Count     : 1795
     13// Last Modified On : Sun Oct  8 12:10:21 2023
     14// Update Count     : 1564
    1415//
    1516
     
    965966                        char fmtstr[ sizeof("%*[]") + nscanset ];
    966967                        int pos = 0;
    967                         strcpy( &fmtstr[pos], "%*[" );  pos += 3;
     968                        fmtstr[pos] = '%';                  pos += 1;
     969                        fmtstr[pos] = '*';                  pos += 1;
     970                        fmtstr[pos] = '[';                  pos += 1;
    968971                        strcpy( &fmtstr[pos], f.scanset );  pos += nscanset;
    969                         strcpy( &fmtstr[pos], "]" );
    970                         fmt( is, fmtstr, "" );                                          // skip scanset
    971                 } else {
    972                         char ch;
    973 //                      fprintf( stderr, "skip " );
    974                         for ( f.wd ) {                                                          // skip N characters
    975                           if ( eof( is ) ) break;
    976                                 fmt( is, "%c", &ch );
    977 //                              fprintf( stderr, "`%c' ", ch );
    978                         } // for
    979                 } // if
     972                        fmtstr[pos] = ']';                  pos += 1;
     973                        fmtstr[pos] = '\0';
     974                        fmt( is, fmtstr, (void*)0 );  // last arg is dummy: suppress gcc warning
     975                }
     976                else for ( f.wd ) fmt( is, "%*c" );
    980977                return is;
    981978        }
     
    983980
    984981        istype & ?|?( istype & is, _Istream_Cstr f ) {
    985                 const char * scanset;
    986                 size_t nscanset = 0;
     982                const char * scanset = f.scanset;
    987983                if ( f.flags.delimiter ) scanset = f.delimiter; // getline ?
    988                 else scanset = f.scanset;
    989                 if ( scanset ) nscanset = strlen( scanset );
    990 
    991                 char fmtstr[nscanset + 32];                                             // storage for scanset and format codes
     984
     985                size_t len = 0;
     986                if ( scanset ) len = strlen( scanset );
     987                char fmtstr[len + 16];
     988                int start = 1;
    992989                fmtstr[0] = '%';
    993 
    994                 int pos = 1;
    995                 int args;
    996                 bool check = true;
    997 
    998                 if ( f.flags.ignore ) { check = false; fmtstr[1] = '*'; pos += 1; }
    999                 int rwd = f.wd;
    1000                 if ( f.wd != -1 ) {                                                             // => just ignore versus ignore with width
     990                if ( f.flags.ignore ) { fmtstr[1] = '*'; start += 1; }
     991                // no maximum width necessary because text ignored => width is read width
     992                if ( f.wd != -1 ) {
    1001993                        // wd is buffer bytes available (for input chars + null terminator)
    1002994                        // rwd is count of input chars
    1003                         // no maximum width necessary because text ignored => width is read width
    1004                         if ( f.flags.rwd ) check = false;
    1005                         else rwd = f.wd - 1;
    1006                         pos += sprintf( &fmtstr[pos], "%d", rwd );
     995                        int rwd;
     996                        if (f.flags.rwd) {
     997                                verify (f.wd >= 0);
     998                                rwd = f.wd;
     999                        } else {
     1000                                verify (f.wd >= 1);
     1001                                rwd = f.wd - 1;
     1002                        } // if
     1003                        start += sprintf( &fmtstr[start], "%d", rwd );
     1004                }
     1005
     1006                if ( ! scanset ) {
     1007                        // %s, %*s, %ws, %*ws
     1008                        fmtstr[start] = 's'; fmtstr[start + 1] = '\0';
     1009                        // printf( "cstr %s\n", fmtstr );
     1010                } else {
     1011                        // incl %[xxx],  %*[xxx],  %w[xxx],  %*w[xxx]
     1012                        // excl %[^xxx], %*[^xxx], %w[^xxx], %*w[^xxx]
     1013                        fmtstr[start] = '['; start += 1;
     1014                        if ( f.flags.inex ) { fmtstr[start] = '^'; start += 1; }
     1015                        strcpy( &fmtstr[start], scanset );                      // copy includes '\0'
     1016                        len += start;
     1017                        fmtstr[len] = ']'; fmtstr[len + 1] = '\0';
     1018                        // printf( "incl/excl %s\n", fmtstr );
    10071019                } // if
    10081020
    1009                 if ( ! scanset ) {                                                              // %s, %*s, %ws, %*ws
    1010 //                      fprintf( stderr, "cstr %s\n", f.s );
    1011                         strcpy( &fmtstr[pos], "s%n" );
    1012                         int len = 0;                                                            // may not be set in fmt
    1013                         if ( f.flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
    1014                         else args = fmt( is, fmtstr, f.s, &len );
    1015 //                      fprintf( stderr, "cstr %s %d %d %d %s\n", fmtstr, args, len, f.wd, f.s );
    1016                         if ( check && len >= rwd && ! eof( is ) ) {     // might not fit
     1021                int check = f.wd - 2;
     1022                if (! f.flags.ignore ) {
     1023                        if ( ! f.flags.rwd ) f.s[check] = '\0';         // insert sentinel
     1024                }
     1025                len = fmt( is, fmtstr, f.s );
     1026                //fprintf( stderr, "KK %s %zd %d %c %s\n", fmtstr, len, check, f.s[check], f.s );
     1027
     1028                if ( ! f.flags.ignore && ! f.flags.rwd && f.s[check] != '\0' ) { // sentinel overwritten ?
     1029                        // buffer filled, but would we have kept going?
     1030                        if ( ! eof( is ) ) {
    10171031                                char peek;
    1018                                 fmt( is, "%c", &peek );                                 // check for whitespace terminator
    1019 //                              fprintf( stderr, "peek %d '%c'\n", args, peek );
    1020                                 if ( ! eof( is ) ) {
    1021                                         ungetc( is, peek );
    1022                                         if ( ! isspace( peek ) ) throw ExceptionInst( cstring_length );
    1023                                 } // if
    1024                         } // if
    1025                 } else {
    1026                         if ( f.flags.delimiter ) {                                      // getline
    1027 //                              fprintf( stderr, "getline\n" );
    1028                                 sprintf( &fmtstr[pos], "[%s%s]%%n", f.flags.inex ? "^" : "", scanset );
    1029 //                              fprintf( stderr, "getline %s %d\n", fmtstr, f.wd );
    1030                                 int len = 0;                                                    // may not be set in fmt
    1031                                 if ( f.flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
    1032                                 else args = fmt( is, fmtstr, f.s, &len );
    1033 //                              fprintf( stderr, "getline %s %d %d %d\n", fmtstr, args, f.wd, eof( is ) );
    1034                                 if ( check && len == rwd && ! eof( is ) ) {     // might not fit
    1035                                         char peek;
    1036                                         fmt( is, "%c", &peek );                         // check for delimiter
    1037 //                                      fprintf( stderr, "peek %d '%c'\n", args, peek );
    1038                                         if ( ! eof( is ) ) {
    1039                                                 if ( peek != f.delimiter[0] ) {
    1040                                                         ungetc( is, peek );
    1041                                                         throw ExceptionInst( cstring_length );
    1042                                                 } // if
    1043                                         } // if
    1044                                 } else fmt( is, "%*c" );                                //  remove delimiter
    1045                         } else {
    1046                                 // incl %[xxx],  %*[xxx],  %w[xxx],  %*w[xxx]
    1047                                 // excl %[^xxx], %*[^xxx], %w[^xxx], %*w[^xxx]
    1048                                 sprintf( &fmtstr[pos], "[%s%s]%%n", f.flags.inex ? "^" : "", scanset );
    1049 //                              fprintf( stderr, "incl/excl %s %d\n", fmtstr, f.wd );
    1050                                 int len = 0;                                                    // may not be set in fmt
    1051                                 if ( f.flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
    1052                                 else args = fmt( is, fmtstr, f.s, &len );
    1053 //                              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] );
    1054                                 if ( check && len == rwd && ! eof( is ) ) {     // might not fit
    1055 //                                      fprintf( stderr, "overflow\n" );
    1056                                         char peek;
    1057                                         fmt( is, "%c", &peek );                         // check for whitespace terminator
    1058 //                                      fprintf( stderr, "peek %d '%c'\n", args, peek );
    1059                                         if ( ! eof( is ) ) {
    1060                                                 ungetc( is, peek );
    1061                                                 if ( f.flags.inex ^ strchr( f.scanset, peek ) != 0p ) throw ExceptionInst( cstring_length );
    1062                                         } // if
    1063                                 } // if
     1032                                fmt( is, "%c", &peek );
     1033                                ungetc( is, peek );
     1034                                bool hasMore;
     1035                                if (f.flags.delimiter) { // getline
     1036                                        hasMore = (peek != f.delimiter[0]);
     1037                                } else if (f.scanset) { // incl/excl
     1038                                        bool peekMatch = strchr(f.scanset, peek) != 0p;
     1039                                        hasMore = f.flags.inex ? (!peekMatch) : (peekMatch);
     1040                                } else { // %s
     1041                                        hasMore = !isspace(peek);
     1042                                }
     1043                                if (hasMore) throw (cstring_length){ &cstring_length_vt };
    10641044                        } // if
    10651045                } // if
    1066                 if ( args == 1 && eof( is ) ) {                                 // data but scan ended at EOF
    1067 //                      fprintf( stderr, "clear\n" );
    1068                         clear( is );                                                            // => reset EOF => detect again on next read
    1069                 } // if
     1046
     1047                if ( f.flags.delimiter ) {                                              // getline ?
     1048                        if ( len == 0 ) f.s[0] = '\0';                          // empty read => argument unchanged => set empty
     1049                        if ( ! eof( is ) ) {                                            // ignore delimiter, may not be present because of width
     1050                                char delimiter;
     1051                                fmt( is, "%c", &delimiter );
     1052                                if ( delimiter != f.delimiter[0] ) ungetc( is, delimiter );
     1053                        } // if
     1054                } //if
    10701055                return is;
    10711056        } // ?|?
Note: See TracChangeset for help on using the changeset viewer.