Changeset 5764204
- Timestamp:
- Jan 25, 2024, 8:58:44 AM (11 months ago)
- Branches:
- master
- Children:
- 68cf1d4, 8ca60e4
- Parents:
- 64c4b4d
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/collections/string_res.cfa
r64c4b4d r5764204 10 10 // Created On : Fri Sep 03 11:00:00 2021 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Jan 16 22:19:27202413 // Update Count : 3512 // Last Modified On : Mon Jan 22 23:12:42 2024 13 // Update Count : 43 14 14 // 15 15 … … 263 263 bool cont = false; 264 264 265 _Istream_C strcf = { cstr, (_Istream_str_base)f };265 _Istream_Cwidth cf = { cstr, (_Istream_str_base)f }; 266 266 if ( ! cf.flags.rwd ) cf.wd = wd; 267 267 -
libcfa/src/iostream.cfa
r64c4b4d r5764204 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jan 3 10:53:13202413 // Update Count : 1 89812 // Last Modified On : Thu Jan 25 08:39:31 2024 13 // Update Count : 1901 14 14 // 15 15 … … 984 984 } 985 985 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 988 1019 fmtstr[0] = '%'; 989 990 1020 int pos = 1; 991 1021 int args; 992 1022 bool check = true; 993 1023 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 width1024 if ( flags.ignore ) { check = false; fmtstr[1] = '*'; pos += 1; } 1025 int rwd = wd; 1026 if ( wd != -1 ) { // => just ignore versus ignore with width 997 1027 // wd is buffer bytes available (for input chars + null terminator) 998 1028 // rwd is count of input chars 999 1029 // 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 ); 1002 1033 pos += sprintf( &fmtstr[pos], "%d", rwd ); 1003 1034 } // if 1004 1035 1005 int len = 0; // may not be set in fmt1006 char enddelim;1007 if ( ! cstr.flags.inex ) { // => quoted getline1008 args = fmt( is, "%*[ \f\n\r\t\v]" ); // remove leading whitespace1009 if ( eof( is ) ) goto Eof;1010 char rfmt[4] = { cstr.delimiters[0], '%', 'n', '\0' };1011 args = fmt( is, rfmt, &len ); // remove leading quote1012 if ( len == 0 || eof( is ) ) goto Eof;1013 } // if1014 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 fit1019 char peek;1020 fmt( is, "%c", &peek ); // check for delimiter1021 if ( ! eof( is ) ) {1022 if ( peek != enddelim ) {1023 ungetc( is, peek );1024 throwResume ExceptionInst( cstring_length );1025 } // if1026 } // if1027 } else fmt( is, "%*c" ); // remove delimiter1028 Eof: ;1029 if ( rwd > 0 && args == 0 ) cstr.s[0] = '\0'; // read failed => no pattern match => set string to null1030 if ( args == 1 && eof( is ) ) { // data but scan ended at EOF1031 clear( is ); // => reset EOF => detect again on next read1032 } // if1033 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 codes1044 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 width1053 // wd is buffer bytes available (for input chars + null terminator)1054 // rwd is count of input chars1055 // no maximum width necessary because text ignored => width is read width1056 if ( f.flags.rwd ) check = false;1057 else rwd = f.wd - 1;1058 pos += sprintf( &fmtstr[pos], "%d", rwd );1059 } // if1060 1061 1036 if ( ! scanset ) { // %s, %*s, %ws, %*ws 1062 // fprintf( stderr, "cstr %s\n", f.s );1037 // fprintf( stderr, "cstr %s\n", s ); 1063 1038 strcpy( &fmtstr[pos], "s%n" ); 1064 1039 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 ); 1068 1043 if ( check && len >= rwd && ! eof( is ) ) { // might not fit 1069 1044 char peek; … … 1076 1051 } // if 1077 1052 // 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 null1053 if ( ! flags.ignore && args == 0 ) s[0]= '\0'; // read failed => no pattern match => set string to null 1079 1054 } else { 1080 if ( f .flags.delimiter ) { // getline1055 if ( flags.delimiter ) { // getline 1081 1056 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 ); 1085 1060 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 ); // removedelimiter1061 char peek; 1062 fmt( is, "%c", &peek ); // check for delimiter 1088 1063 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 ); 1092 1066 throwResume ExceptionInst( cstring_length ); 1093 1067 } // if … … 1097 1071 // incl %[xxx], %*[xxx], %w[xxx], %*w[xxx] 1098 1072 // 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 ); 1101 1075 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] ); 1105 1079 if ( check && len == rwd && ! eof( is ) ) { // might not fit 1106 1080 // fprintf( stderr, "overflow\n" ); … … 1110 1084 if ( ! eof( is ) ) { 1111 1085 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 ); 1113 1087 } // if 1114 1088 } // if 1115 1089 } // if 1116 if ( ! f .flags.ignore && rwd > 0 && args == 0 ) f.s[0]= '\0';// read failed => no pattern match => set string to null1090 if ( ! flags.ignore && args == 0 ) s[0]= '\0'; // read failed => no pattern match => set string to null 1117 1091 } // if 1118 1092 if ( args == 1 && eof( is ) ) { // data but scan ended at EOF … … 1123 1097 } // ?|? 1124 1098 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 1127 1106 return is; 1128 1107 } // ?|? -
libcfa/src/iostream.hfa
r64c4b4d r5764204 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Jan 21 22:42:40202413 // Update Count : 6 5512 // Last Modified On : Thu Jan 25 08:39:04 2024 13 // Update Count : 696 14 14 // 15 15 … … 404 404 }; // _Istream_str_base 405 405 406 struct _Istream_C str{406 struct _Istream_Cwidth { 407 407 char * s; 408 408 inline _Istream_str_base; 409 409 }; // _Istream_Cstr 410 410 411 // Restrict nesting of input manipulators to those combinations that make sense. 412 413 struct _Istream_Cstr { 414 _Istream_Cwidth cstr; 415 }; // _Istream_Cstr 416 411 417 struct _Istream_Cquoted { 412 _Istream_C strcstr;418 _Istream_Cwidth cstr; 413 419 }; // _Istream_Cquoted 414 420 415 421 static 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} } }; 421 426 } 422 _Istream_C quoted & 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_C quoted &)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} } }; 425 430 } 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; 428 434 } 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; } 433 444 } // distribution 434 445 435 446 forall( istype & | basic_istream( istype ) ) { 436 istype & ?|?( istype & is, _Istream_Cstr f );437 447 istype & ?|?( istype & is, _Istream_Cskip f ); 438 448 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 439 453 } // distribution 440 454 -
tests/io/.expect/manipulatorsInput.x64.txt
r64c4b4d r5764204 22 22 16 get this line 23 23 17 @# this line 1)-{} 24 18 abc 25 19 abc 26 20 d d 24 18 @# this line 1)-{} 25 19 abc 26 20 abc 27 21 d d 27 28 28 29 d 29 21 ZC44% 30 22 ZC44% 31 23 ZC44% 30 32 1 yyyyyyyyyyyyyyyyyyyy 31 33 2 abcxxx … … 45 47 16 get this line 46 48 17 @# this line 1)-{} 47 18 abc 48 19 abc 49 20 d d 49 18 @# this line 1)-{} 50 19 abc 51 20 abc 52 21 d d 50 53 51 54 d 52 21 ZC44% 55 22 ZC44% 56 23 ZC44% 53 57 a 54 58 a -
tests/io/.in/manipulatorsInput.txt
r64c4b4d r5764204 12 12 get this line 13 13 @# this line 1)-{}% 14 @# this line 2)-{}% 14 15 "abc" 15 16 'abc ' … … 18 19 d } 19 20 X ZC44%Y 21 X ZC55%Y 20 22 abc 21 23 cccccb … … 27 29 get this line 28 30 @# this line 1)-{}% 31 @# this line 2)-{}% 29 32 "abc" 30 33 'abc ' … … 33 36 d } 34 37 X ZC44%Y 38 X ZC55%Y 35 39 ab 36 40 0xff 017 15-15 -
tests/io/manipulatorsInput.cfa
r64c4b4d r5764204 7 7 // Created On : Sat Jun 8 17:58:54 2019 8 8 // Last Modified By : Peter A. Buhr 9 // Last Modified On : Wed Jan 3 11:15:04202410 // Update Count : 10 39 // Last Modified On : Wed Jan 24 18:36:32 2024 10 // Update Count : 104 11 11 // 12 12 … … 81 81 scanf( "%[^\n]\n", s ); printf( "16 %s\n", s ); // |get this line\n| 82 82 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| 83 84 84 85 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| 92 95 scanf( "\n" ); // must start next line // |\n| 93 96 } … … 118 121 sin | getline( wdi( sizeof(s), s ) ); sout | "16" | s; 119 122 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; 125 130 } 126 131 // Keep harmonized with collections/string-istream-manip
Note: See TracChangeset
for help on using the changeset viewer.