source: tests/collections/string-overwrite.cfa@ 4be0117

Last change on this file since 4be0117 was e8b3717, checked in by Michael Brooks <mlbrooks@…>, 20 months ago

Modify substring interface from start-end to start-len, and add a missing test.

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