source: tests/collections/string-overwrite.cfa@ b28ce93

Last change on this file since b28ce93 was 3f631d6, checked in by Michael Brooks <mlbrooks@…>, 5 months ago

Switch string io to be generic upon iostream, rather than specific upon fstream.

No direct test added because we currently lack a second implementation of the abstract streams.

Benefit is removing polymorphism-induced noise from cost calculations, in upcoming string-overload reorganizations.

The change in tests 'collections/string-operator*' shows cases where we stopped picking string for the wrong reason. (If we should be picking string for a better reason, that's just ahead.)

  • Property mode set to 100644
File size: 9.1 KB
Line 
1#include <string.hfa>
2#include <string_sharectx.hfa>
3#include <fstream.hfa>
4
5/*
6
7Modify a subrange of a string, while a witness is watching another subrange of the same string.
8
9Cases are the relative positions and overlaps of the modifier vs the witness.
10MS = modifier start
11ME = modifier end
12ML = modifier length
13WS = witness start
14WE = witness end
15WL = witness length
16
17The test does:
18 starts with the entire string being, initially, the alphabet; prints this entire alphabet
19 sets up modifier and witness as ranges within it, and prints a visualization of those ranges
20 does the main modification
21 prints the result of the main modification, which is always an unsurprising consequence of the modifier range, but shows little about what happened to the witness, particularly if the witness is/became empty
22 modifies the witness to be "?"
23 prints the result of this second modification, which implies what the witness included after the main modification
24
25Deriving the concrete list of cases....
26
27By definition of a string, MS <= ME and WS <= WE.
28This API's convention has Start positions being inclusive and end positions being exclusive.
29
30 v Case number in output
31With 1 equivalence class:
32MS = ME = WS = WE 1
33
34With 2 equivalence classes:
35 < = =
36MS rest 2
37WS rest 3
38
39 = < =
40MS ME WS WE 4
41WS WE MS ME 5
42MS WS ME WE 6
43
44 = = <
45 rest ME 7
46 rest WE 8
47
48With 3 equivalence classes
49 < < =
50MS ME WS WE 9
51 WS ME WE 10
52+2 11, 12
53
54 < = <
55MS WS ME WE 13
56 WE ME 14
57+2 15, 16
58
59 = < <
60MS WS WE ME 17
61 ME WS WE 18
62+2 19, 20
63
64With 4 equivalence classes
65 < < <
66MS ME WS WE 21
67 WS ME WE 22
68 WE ME 23
69+3 24, 25, 26
70
71
72
73*/
74
75
76void showOneReplacement(string & s, int ms, int ml, int ws, int wl, const char* replaceWith) {
77
78 int me = ms + ml;
79 int we = ws + wl;
80
81 assert( ms >= 0 && ms <= me && me <= len(s) );
82 assert( ws >= 0 && ws <= we && we <= len(s) );
83
84 string mod = s(ms, ml)`share;
85 string wit = s(ws, wl)`share;
86
87 string modOld = mod;
88 string witOld = wit;
89
90 // s, before the mode
91 sout | s;
92
93 // visualize the pair of ranges
94 sout | nlOff;
95 for ( i; len(s) ) {
96 if( i < ms || i > me ) {
97 sout | ' ';
98 } else if ( i < me ) {
99 sout | '-';
100 } else {
101 assert ( i == me );
102 sout | '!';
103 }
104 } sout | nl;
105 for ( i; len(s) ) {
106 if( i < ws || i > we ) {
107 sout | ' ';
108 } else if ( i < we ) {
109 sout | '-';
110 } else {
111 assert ( i == we );
112 sout | '?';
113 }
114 }
115 sout | nl;
116 sout | nlOn;
117
118 mod = replaceWith; // main replacement
119 sout | s | "( wit = " | wit | "witlen = " | len(wit) | " )";
120 wit = "?"; // witness-revelaing replacement
121 sout | s;
122}
123
124void runReplaceCases() {
125 char * alphabetTemplate = "abcdefghijklmnopqrstuvwxyz";
126 struct { int ms; int ml; int ws; int wl; char *replaceWith; char *label; } cases[] = {
127 { 12, 2, 10, 10, "xxxxx", "warmup" },
128 { 10, 0, 10, 0, "=====", "1" },
129 { 10, 0, 10, 0, "==" , "" },
130 { 10, 0, 10, 0, "=" , "" },
131 { 10, 0, 10, 0, "" , "" },
132 { 10, 2, 12, 0, "=====", "2" },
133 { 10, 2, 12, 0, "==" , "" },
134 { 10, 2, 12, 0, "=" , "" },
135 { 10, 2, 12, 0, "" , "" },
136 { 12, 0, 10, 2, "=====", "3" },
137 { 12, 0, 10, 2, "==" , "" },
138 { 12, 0, 10, 2, "=" , "" },
139 { 12, 0, 10, 2, "" , "" },
140 { 10, 0, 12, 0, "=====", "4" },
141 { 10, 0, 12, 0, "==" , "" },
142 { 10, 0, 12, 0, "=" , "" },
143 { 10, 0, 12, 0, "" , "" },
144 { 12, 0, 10, 0, "=====", "5" },
145 { 12, 0, 10, 0, "==" , "" },
146 { 12, 0, 10, 0, "=" , "" },
147 { 12, 0, 10, 0, "" , "" },
148 { 10, 2, 10, 2, "=====", "6" },
149 { 10, 2, 10, 2, "==" , "" },
150 { 10, 2, 10, 2, "=" , "" },
151 { 10, 2, 10, 2, "" , "" },
152 { 10, 2, 10, 0, "=====", "7" },
153 { 10, 2, 10, 0, "==" , "" },
154 { 10, 2, 10, 0, "=" , "" },
155 { 10, 2, 10, 0, "" , "" },
156 { 10, 0, 10, 2, "=====", "8" },
157 { 10, 0, 10, 2, "==" , "" },
158 { 10, 0, 10, 2, "=" , "" },
159 { 10, 0, 10, 2, "" , "" },
160 { 10, 2, 14, 0, "=====", "9" },
161 { 10, 2, 14, 0, "==" , "" },
162 { 10, 2, 14, 0, "=" , "" },
163 { 10, 2, 14, 0, "" , "" },
164 { 10, 4, 12, 2, "=====", "10" },
165 { 10, 4, 12, 2, "==" , "" },
166 { 10, 4, 12, 2, "=" , "" }, // FORMERLY unrunnable bug: tries to print seemingly infinite string
167 { 10, 4, 12, 2, "" , "" }, // ditto
168 { 14, 0, 10, 2, "=====", "11" },
169 { 14, 0, 10, 2, "==" , "" },
170 { 14, 0, 10, 2, "=" , "" },
171 { 14, 0, 10, 2, "" , "" },
172 { 12, 2, 10, 4, "=====", "12" }, // correctness observation: watching klmn while mn |-> xxx gives klxxx because the mn is inside what I'm watching
173 { 12, 2, 10, 4, "==" , "" },
174 { 12, 2, 10, 4, "=" , "" },
175 { 12, 2, 10, 4, "" , "" },
176 { 10, 2, 12, 2, "=====", "13" },
177 { 10, 2, 12, 2, "==" , "" },
178 { 10, 2, 12, 2, "=" , "" },
179 { 10, 2, 12, 2, "" , "" },
180 { 10, 4, 12, 0, "=====", "14" },
181 { 10, 4, 12, 0, "==" , "" },
182 { 10, 4, 12, 0, "=" , "" },
183 { 10, 4, 12, 0, "" , "" },
184 { 12, 2, 10, 2, "=====", "15" },
185 { 12, 2, 10, 2, "==" , "" },
186 { 12, 2, 10, 2, "=" , "" },
187 { 12, 2, 10, 2, "" , "" },
188 { 12, 0, 10, 4, "=====", "16" },
189 { 12, 0, 10, 4, "==" , "" },
190 { 12, 0, 10, 4, "=" , "" },
191 { 12, 0, 10, 4, "" , "" },
192 { 10, 4, 10, 2, "=====", "17" },
193 { 10, 4, 10, 2, "==" , "" },
194 { 10, 4, 10, 2, "=" , "" },
195 { 10, 4, 10, 2, "" , "" },
196 { 10, 0, 12, 2, "=====", "18" },
197 { 10, 0, 12, 2, "==" , "" },
198 { 10, 0, 12, 2, "=" , "" },
199 { 10, 0, 12, 2, "" , "" },
200 { 10, 2, 10, 4, "=====", "19" },
201 { 10, 2, 10, 4, "==" , "" },
202 { 10, 2, 10, 4, "=" , "" },
203 { 10, 2, 10, 4, "" , "" },
204 { 12, 2, 10, 0, "=====", "20" },
205 { 12, 2, 10, 0, "==" , "" },
206 { 12, 2, 10, 0, "=" , "" },
207 { 12, 2, 10, 0, "" , "" },
208 { 10, 2, 14, 2, "=====", "21" },
209 { 10, 2, 14, 2, "==" , "" },
210 { 10, 2, 14, 2, "=" , "" },
211 { 10, 2, 14, 2, "" , "" },
212 { 10, 4, 12, 4, "=====", "22" },
213 { 10, 4, 12, 4, "==" , "" },
214 { 10, 4, 12, 4, "=" , "" },
215 { 10, 4, 12, 4, "" , "" },
216 { 10, 6, 12, 2, "=====", "23" },
217 { 10, 6, 12, 2, "==" , "" },
218 { 10, 6, 12, 2, "=" , "" },
219 { 10, 6, 12, 2, "" , "" },
220 { 14, 2, 10, 2, "=====", "24" },
221 { 14, 2, 10, 2, "==" , "" },
222 { 14, 2, 10, 2, "=" , "" },
223 { 14, 2, 10, 2, "" , "" },
224 { 12, 4, 10, 4, "=====", "25" },
225 { 12, 4, 10, 4, "==" , "" },
226 { 12, 4, 10, 4, "=" , "" },
227 { 12, 4, 10, 4, "" , "" },
228 { 12, 2, 10, 6, "=====", "26" },
229 { 12, 2, 10, 6, "==" , "" },
230 { 12, 2, 10, 6, "=" , "" },
231 { 12, 2, 10, 6, "" , "" },
232 };
233 for ( i; sizeof(cases)/sizeof(cases[0]) ) {
234 sout | "------------------------------------------------------------------------" | cases[i].label;
235 string replaceIn = alphabetTemplate;
236 showOneReplacement( replaceIn, cases[i].ms, cases[i].ml, cases[i].ws, cases[i].wl, cases[i].replaceWith );
237 }
238}
239
240
241int main() {
242
243 #ifdef STRING_SHARING_OFF
244 string_sharectx c = { NO_SHARING };
245 #endif
246
247
248 // 0 1 2
249 // 01234567890123456789012345
250 string s = "abcdefghijklmnopqrstuvwxyz";
251
252 s(5,5) = "qqqqq"; // start=5, end=10, len=5
253
254 sout | s;
255
256
257 s(5,0) = "-----"; // start=5, end=5, len=0
258
259 sout | s;
260
261 runReplaceCases();
262}
Note: See TracBrowser for help on using the repository browser.