source: tests/io/manipulatorsInput.cfa @ 0860d9c

Last change on this file since 0860d9c was 0860d9c, checked in by Michael Brooks <mlbrooks@…>, 9 months ago

Fix read-to-variable-length-string cases when internal buffer fills.

Also fix read-to-cstring ability to give no-exception cases when an entire buffer fills.

The added test cases run, and fail, when run against prior libcfa.
Doing so illustrates a CFA-string-level bug.
Doing so illustrates a C-string-level changed semantics.

At the CFA-string level, the bug was, when reading strings of just the right length,
what should be two reads ("abc" then "def") gets mashed into one ("abcdef").
These cases are clearly bugs because a test program that just echoes chuncks of delimeted input would do so inaccurately.
They're just hard to drive because the relevant chunk lengths are implementation-dependent, and sometimes big.

At the C-string level, the semantic change concerns when to throw the cstring_length exception.
By this change, make the original semantics,
"An exception means the maximum number of characters was read," into
"An exception means that if the buffer were larger, then more characters would have been read."

The added test cases cover the respective stop conditions for manipulator state "%s", include, exclude, getline, and getline/delimiter.

  • Property mode set to 100644
File size: 6.8 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
3//
4// manipulatorsInput.cfa --
5//
6// Author           : Peter A. Buhr
7// Created On       : Sat Jun  8 17:58:54 2019
8// Last Modified By : Peter A. Buhr
9// Last Modified On : Sat Sep  2 14:27:46 2023
10// Update Count     : 65
11//
12
13#include <fstream.hfa>
14#include <stdio.h>                                      // scanf
15
16int main() {
17        {
18                // Upfront checks to ensure buffer safety.  Once these pass, the simpler `wdi(sizeof(s),s)`
19                // usage, as in the scanf alignment cases below, is justified.
20                struct {
21                        char buf[8];
22                        char canary;
23                } data;
24                static_assert( sizeof(data.buf) == 8 );
25                static_assert( &data.buf[8] == &data.canary );  // canary comes right after buf
26
27                void rep(const char* casename) {
28                        data.canary = 42;
29                        bool caught = false;
30                        try {
31                                sin | wdi( sizeof(data.buf), data.buf );
32                        } catch (cstring_length*) {
33                                caught = true;
34                        }
35                        printf( "%s \"%s\"", casename, data.buf );
36                        if ( caught ) {
37                                printf(", exception occurred");
38                        }
39                        if ( data.canary == 42 ) {
40                                printf(", canary ok");
41                        } else {
42                                printf(", canary overwritten to %d", data.canary);
43                        }
44                        printf("\n");
45                }
46
47                rep("pre1");    // 123456     |  123456
48                rep("pre2");    // 1234567    |  1234567
49                rep("pre3a");   // 12345678   |  1234567
50                rep("pre3b");   //            |  8
51                rep("pre4a");   // 123456789  |  1234567
52                rep("pre4b");   //            |  89
53
54                scanf("\n");  // next test does not start with %s so does not tolerate leading whitespace
55        }
56        {
57                char s[] = "yyyyyyyyyyyyyyyyyyyy";
58                const char sk_fmt[] = "%*[abc]";
59                scanf( "abc " ); scanf( sk_fmt ); for ( 5 ) scanf( "%*c" ); printf( "1 %s\n", s );
60                scanf( "%s", s );                                                               printf( "2 %s\n", s );
61                scanf( "%*s" );                                                                 printf( "3 %s\n", s );
62                scanf( "%8s", s );                                                              printf( "4 %s\n", s );
63                scanf( "%*8s" );                                                                printf( "5 %s\n", s );
64
65                scanf( "%[abc]", s );                                                   printf( "6 %s\n", s );
66                scanf( "%[^abc]", s );                                                  printf( "7 %s\n", s );
67                scanf( "%*[abc]" );                                                             printf( "8 %s\n", s );
68                scanf( "%*[^abc]" );                                                    printf( "9 %s\n", s );
69                scanf( "%8[abc]", s );                                                  printf( "10 %s\n", s );
70                scanf( "%8[^abc]", s );                                                 printf( "11 %s\n", s );
71                scanf( "%*8[abc]" );                                                    printf( "12 %s\n", s );
72                scanf( "%*8[^abc]" );                                                   printf( "13 %s\n", s );
73
74                int rc;
75                s[0] = 'q'; s[1] = '\0'; rc = 99;
76                rc = scanf( "%[abc]", s );                                              printf( "14 rc=%d, %s\n", rc, s );
77                s[0] = 'q'; s[1] = '\0'; rc = 99;
78                rc = scanf( "%[^u]", s );                                               printf( "15 rc=%d, %s\n", rc, s );
79                scanf( "%*[u]" );
80                scanf("\n");
81        }
82        {
83                char s[] = "yyyyyyyyyyyyyyyyyyyy";
84                char sk[] = "abc";
85                sin | "abc " | skip( sk ) | skip( 5 );                  sout | "1" | s;
86                sin | wdi( sizeof(s), s );                                              sout | "2" | s;
87                sin | ignore( s );                                                              sout | "3" | s;
88                sin | wdi( sizeof(s), 8, s );                                   sout | "4" | s;
89                sin | ignore( wdi( sizeof(s), 8, s ) );                 sout | "5" | s;
90
91                sin | incl( "abc", wdi( sizeof(s), s ) );               sout | "6" | s;
92                sin | excl( "abc", wdi( sizeof(s), s ) );               sout | "7" | s;
93                sin | ignore( incl( "abc", wdi( sizeof(s), s ) ) ); sout | "8" | s;
94                sin | ignore( excl( "abc", wdi( sizeof(s), s ) ) ); sout | "9" | s;
95                sin | incl( "abc", wdi( sizeof(s), 8, s ) );    sout | "10" | s;
96                sin | excl( "abc", wdi( sizeof(s), 8, s ) );    sout | "11" | s;
97                sin | ignore( incl( "abc", wdi( sizeof(s), 8, s ) ) ); sout | "12" | s;
98                sin | ignore( excl( "abc", wdi( sizeof(s), 8, s ) ) ); sout | "13" | s;
99
100                s[0] = 'q'; s[1] = '\0';
101                sin | incl( "abc", wdi( sizeof(s), s ) );               sout | "14" | s;
102                s[0] = 'q'; s[1] = '\0';
103                sin | excl( "u", wdi( sizeof(s), s ) );                 sout | "15" | s;
104                sin | skip( "u" );
105                sin | "\n";
106        }
107    /* Keep harmonized with collections/string-istream-manip */
108        {
109                char c;
110                sin | c;                                                                                sout | c;
111                sin | ignore( c );                                                              sout | c;
112
113                signed char sc;
114                sin | sc;                                                                               sout | sc;
115                sin | wdi( 3, sc );                                                             sout | sc;
116                sin | ignore( sc );                                                             sout | sc;
117                sin | ignore( wdi( 3, sc ) );                                   sout | sc;
118
119                unsigned char usc;
120                sin | usc;                                                                              sout | usc;
121                sin | wdi( 3, usc );                                                    sout | usc;
122                sin | ignore( usc );                                                    sout | usc;
123                sin | ignore( wdi( 3, usc ) );                                  sout | usc;
124
125                signed short int ssi;
126                sin | ssi;                                                                              sout | ssi;
127                sin | wdi( 3, ssi );                                                    sout | ssi;
128                sin | ignore( ssi );                                                    sout | ssi;
129                sin | ignore( wdi( 3, ssi ) );                                  sout | ssi;
130
131                unsigned short int usi;
132                sin | usi;                                                                              sout | usi;
133                sin | wdi( 3, usi );                                                    sout | usi;
134                sin | ignore( usi );                                                    sout | usi;
135                sin | ignore( wdi( 3, usi ) );                                  sout | usi;
136
137                signed int si;
138                sin | si;                                                                               sout | si;
139                sin | wdi( 3, si );                                                             sout | si;
140                sin | ignore( si );                                                             sout | si;
141                sin | ignore( wdi( 3, si ) );                                   sout | si;
142
143                unsigned int ui;
144                sin | ui;                                                                               sout | ui;
145                sin | wdi( 3, ui );                                                             sout | ui;
146                sin | ignore( ui );                                                             sout | ui;
147                sin | ignore( wdi( 3, ui ) );                                   sout | ui;
148
149                signed long int sli;
150                sin | sli;                                                                              sout | sli;
151                sin | wdi( 3, sli );                                                    sout | sli;
152                sin | ignore( sli );                                                    sout | sli;
153                sin | ignore( wdi( 3, sli ) );                                  sout | sli;
154
155                unsigned long int uli;
156                sin | uli;                                                                              sout | uli;
157                sin | wdi( 3, uli );                                                    sout | uli;
158                sin | ignore( uli );                                                    sout | uli;
159                sin | ignore( wdi( 3, uli ) );                                  sout | uli;
160
161                signed long long int slli;
162                sin | slli;                                                                             sout | slli;
163                sin | wdi( 3, slli );                                                   sout | slli;
164                sin | ignore( slli );                                                   sout | slli;
165                sin | ignore( wdi( 3, slli ) );                                 sout | slli;
166
167                unsigned long long int ulli;
168                sin | ulli;                                                                             sout | ulli;
169                sin | wdi( 3, ulli );                                                   sout | ulli;
170                sin | ignore( ulli );                                                   sout | ulli;
171                sin | ignore( wdi( 3, ulli ) );                                 sout | ulli;
172
173                float f;
174                sin | f;                                                                                sout | f;
175                sin | wdi( 8, f );                                                              sout | f;
176                sin | ignore( f );                                                              sout | f;
177                sin | ignore( wdi( 8, f ) );                                    sout | f;
178
179                double d;
180                sin | d;                                                                                sout | d;
181                sin | wdi( 8, d );                                                              sout | d;
182                sin | ignore( d );                                                              sout | d;
183                sin | ignore( wdi( 8, d ) );                                    sout | d;
184
185                long double ld;
186                sin | ld;                                                                               sout | ld;
187                sin | wdi( 8, ld );                                                             sout | ld;
188                sin | ignore( ld );                                                             sout | ld;
189                sin | ignore( wdi( 8, ld ) );                                   sout | ld;
190
191                float _Complex fc;
192                sin | fc;                                                                               sout | fc;
193                sin | wdi( 8, fc );                                                             sout | fc;
194                sin | ignore( fc );                                                             sout | fc;
195                sin | ignore( wdi( 8, fc ) );                                   sout | fc;
196
197                double _Complex dc;
198                sin | dc;                                                                               sout | dc;
199                sin | wdi( 8, dc );                                                             sout | dc;
200                sin | ignore( dc );                                                             sout | dc;
201                sin | ignore( wdi( 8, dc ) );                                   sout | dc;
202
203                long double _Complex ldc;
204                sin | ldc;                                                                              sout | ldc;
205                sin | wdi( 8, ldc );                                                    sout | ldc;
206                sin | ignore( ldc );                                                    sout | ldc;
207                sin | ignore( wdi( 8, ldc ) );                                  sout | ldc;
208        }
209        #if defined( __SIZEOF_INT128__ )
210        {
211                int128 val;
212                for ( 15 ) {
213                        sin | val;
214                        sout | val;
215                }
216        }
217        #endif // __SIZEOF_INT128__
218} // main
219
220// Local Variables: //
221// tab-width: 4 //
222// compile-command: "cfa -Wall -Wextra manipulatorsInput.cfa" //
223// End: //
Note: See TracBrowser for help on using the repository browser.