source: tests/collections/string-istream-manip.cfa @ dc80280

Last change on this file since dc80280 was 37ceccb, checked in by Michael Brooks <mlbrooks@…>, 13 months ago

Change string-read semantics so that reading nothing leaves the original value unmodified.

Logically revert #8cffa4f21, and apply the change onto work done since.

At cstring layer, libcfa change is a simplification, and test suite change is merely a different expectation.

At var-len-string layer, libcfa change is a patch to enable detecting the nothing-read case,
and test sute change (shows the different expectation but also) puts a similar patch into its "stop trying if nothing read" loop exits.

  • Property mode set to 100644
File size: 7.6 KB
Line 
1
2#include <fstream.hfa>
3#include <collections/string.hfa>
4#include <collections/string_res.hfa>
5#include <stdio.h>
6
7// No-op manipulators.
8// Temporary hack while there are two code paths in the string implementation.
9// (One for reading plain strings, the other for reading via a manipulator.)
10// The test cases that use plainjane(-) are exercising the via-manipulator code path,
11// just with trivial manipulation.
12static _Istream_Sstr plainjane( string     & s )  { return (_Istream_Sstr)@{  s, {{0p}, -1, {.flags.rwd : false}} }; }
13static _Istream_Rstr plainjane( string_res & s )  { return (_Istream_Rstr)@{ &s, {{0p}, -1, {.flags.rwd : false}} }; }
14
15static void forceStringHeapFreeSpaceTo(int desiredSize) {
16    for (1_000_000) {
17        string x = "a";
18        (void)x;
19      if (desiredSize == DEBUG_string_bytes_avail_until_gc(DEBUG_string_heap())) return;
20    }
21    sout | "Unable to force size" | desiredSize | "in 1,000,000 tries";
22}
23
24int main() {
25    // These "pre" cases deal with issues analogous to the "pre" cases of io/manipulatorsInput.
26    // The acceptance criterion is simpler but driving the cases is harder.
27    // The tests just read strings and echo what they read; acceptance of simple echoing assures
28    // no spurious splitting merging.
29    // The lengths of the strings are chosen to match white-box knowledge of when the string layer
30    // has tor drive the cstring layer through a second iteration:
31    //  - for no-manip, lengths are near the room at end of string heap
32    //    (chosen target size of 9 showed the original bug on preS2, aligned with the other cases)
33    //  - for manip, lengths are near the auxiliary buffer size of 128
34    // Only first case repeats for string_res; rest run only from the passthru string layer.
35    // Similarly, the manipulator breadth isn't checked at the cstring layer either.
36    {
37        // S: string, no manipulator
38        void echoTillX(const char * casename) {
39            string s;
40            // loop assumes behaviour not tested until main-case #15:
41            // on reading nothing, the prior string value is left alone
42            do {
43                s = "";
44                forceStringHeapFreeSpaceTo(9);
45                sin | s;
46                sout | casename | s;
47            } while ( size(s) > 0 && s[size(s)-1] != 'x' );
48        }
49        echoTillX("preS1");
50        echoTillX("preS2");
51        echoTillX("preS3");
52        echoTillX("preS4");
53    }
54    {
55        // SMN: string, manipulator for no-op
56        void echoTillX(const char * casename) {
57            string s;
58            do {
59                s = "";
60                sin | plainjane( s );
61                sout | casename | s;
62            } while ( size(s) > 0 && s[size(s)-1] != 'x' );
63        }
64        echoTillX("preSMN1");
65        echoTillX("preSMN2");
66        echoTillX("preSMN3");
67        echoTillX("preSMN4");
68    }
69    {
70        // RMN: string_res, manipulator for no-op
71        void echoTillX(const char * casename) {
72            string_res s;
73            do {
74                s = "";
75                sin | plainjane( s );
76                sout | casename | s;
77            } while ( size(s) > 0 && s[size(s)-1] != 'x' );
78        }
79        echoTillX("preRMN1");
80        echoTillX("preRMN2");
81        echoTillX("preRMN3");
82        echoTillX("preRMN4");
83    }
84    {
85        // SMI: string, manipulator `incl`
86        void echoTillX(const char * casename) {
87            string s;
88            do {
89                s = "";
90                sin | skip("-\n");
91                sin | incl( ".:|# x", s );
92                sout | casename | " \"" | s | "\"";
93            } while ( size(s) > 0 && s[size(s)-1] != 'x' );
94        }
95        echoTillX("preSMI1");
96        echoTillX("preSMI2");
97        echoTillX("preSMI3");
98        echoTillX("preSMI4");
99    }
100    {
101        // SME: string, manipulator `excl`
102        void echoTillX(const char * casename) {
103            string s;
104            do {
105                s = "";
106                sin | skip("-\n");
107                sin | excl( "-\n", s );
108                sout | casename | " \"" | s | "\"";
109            } while ( size(s) > 0 && s[size(s)-1] != 'x' );
110        }
111        echoTillX("preSME1");
112        echoTillX("preSME2");
113        echoTillX("preSME3");
114        echoTillX("preSME4");
115    }
116    sin | skip("-\n");
117    {
118        // SMG: string, manipulator `getline`
119        void echoTillX(const char * casename) {
120            string s;
121            do {
122                s = "";
123                sin | getline( s );
124                sout | casename | s;
125            } while ( size(s) > 0 && s[size(s)-1] != 'x' );
126        }
127        echoTillX("preSMG1");
128        echoTillX("preSMG2");
129        echoTillX("preSMG3");
130        echoTillX("preSMG4");
131    }
132    {
133        // SMD: string, manipulator (`getline` with custom) delimiter
134        void echoTillX(const char * casename) {
135            string s;
136            do {
137                s = "";
138                sin | getline( s, '@' );
139                sout | casename | s;
140            } while ( size(s) > 0 && s[size(s)-1] != 'x' );
141            sin | skip(" \n");
142        }
143        echoTillX("preSMD1");
144        echoTillX("preSMD2");
145        echoTillX("preSMD3");
146        echoTillX("preSMD4");
147    }
148
149    /* Keep harmonized with io/manipulatorsInput */
150    {
151        string s = "yyyyyyyyyyyyyyyyyyyy";
152        char sk[] = "abc";
153        sin | "abc " | skip( sk ) | skip( 5 );          sout | "1" | s;
154        sin | s;                                        sout | "2" | s;
155        sin | ignore( s );                              sout | "3" | s;
156        sin | wdi( 8, s );                              sout | "4" | s;
157        sin | ignore( wdi( 8, s ) );                    sout | "5" | s;
158
159        sin | incl( "abc", s );                         sout | "6" | s;
160        sin | excl( "abc", s );                         sout | "7" | s;
161        sin | ignore( incl( "abc", s ) );               sout | "8" | s;
162        sin | ignore( excl( "abc", s ) );               sout | "9" | s;
163        sin | incl( "abc", wdi( 8, s ) );               sout | "10" | s;
164        sin | excl( "abc", wdi( 8, s ) );               sout | "11" | s;
165        sin | ignore( incl( "abc", wdi( 8, s ) ) );     sout | "12" | s;
166        sin | ignore( excl( "abc", wdi( 8, s ) ) );     sout | "13" | s;
167
168                s = "q";
169                sin | incl( "abc", s );                         sout | "14" | s;
170                s = "q";
171                sin | excl( "u", s );                           sout | "15" | s;
172                sin | skip( "u" );
173                sin | "\n";
174        }
175    // Full repeat on string_res layer assures the full manipulator vocabulary is supported there.
176    {
177        string_res s = "yyyyyyyyyyyyyyyyyyyy";
178        char sk[] = "abc";
179        sin | "abc " | skip( sk ) | skip( 5 );          sout | "1" | s;
180        sin | s;                                        sout | "2" | s;
181        sin | ignore( s );                              sout | "3" | s;
182        sin | wdi( 8, s );                              sout | "4" | s;
183        sin | ignore( wdi( 8, s ) );                    sout | "5" | s;
184
185        sin | incl( "abc", s );                         sout | "6" | s;
186        sin | excl( "abc", s );                         sout | "7" | s;
187        sin | ignore( incl( "abc", s ) );               sout | "8" | s;
188        sin | ignore( excl( "abc", s ) );               sout | "9" | s;
189        sin | incl( "abc", wdi( 8, s ) );               sout | "10" | s;
190        sin | excl( "abc", wdi( 8, s ) );               sout | "11" | s;
191        sin | ignore( incl( "abc", wdi( 8, s ) ) );     sout | "12" | s;
192        sin | ignore( excl( "abc", wdi( 8, s ) ) );     sout | "13" | s;
193
194                s = "q";
195                sin | incl( "abc", s );                         sout | "14" | s;
196                s = "q";
197                sin | excl( "u", s );                           sout | "15" | s;
198                sin | skip( "u" );
199                sin | "\n";
200    }
201}
Note: See TracBrowser for help on using the repository browser.