Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
21.string.append.cpp
Go to the documentation of this file.
1
27#include <string> // for string
28#include <stdexcept> // for out_of_range, length_error
29#include <cstddef> // for size_t
30
31#include <rw_strings.h> // for StringMembers
32#include <rw_alg_test.h> // for InputIter
33#include <rw_driver.h> // for rw_test()
34#include <rw_allocator.h> // for UserAlloc
35#include <rw_char.h> // for rw_expand()
36#include <rw_new.h> // for bad_alloc, replacement operator new
37
38
40// for convenience and brevity
41#define Append(sig) StringIds::append_ ## sig
42#define PushBack(sig) StringIds::push_back_ ## sig
43
44static const char* const exceptions[] = {
45 "unknown exception", "out_of_range", "length_error",
46 "bad_alloc", "exception"
47};
48
49
51// exercises:
52// append (const value_type*)
53static const StringTestCase
54cptr_test_cases [] = {
55
56#undef TEST
57#define TEST(str, arg, res, bthrow) { \
58 __LINE__, -1, -1, -1, -1, -1, \
59 str, sizeof str - 1, \
60 arg, sizeof arg - 1, res, sizeof res - 1, bthrow \
61 }
62
63 // +------------------------------------------ controlled sequence
64 // | +----------------------- sequence to be appended
65 // | | +---------- expected result sequence
66 // | | | +- exception info
67 // | | | | 0 - no exception
68 // | | | | 1 - out_of_range
69 // | | | | 2 - length_error
70 // | | | | -1 - avoid exc. safety
71 // | | | |
72 // | | | +--------------+
73 // V V V V
74 TEST ("ab", "c", "abc", 0),
75
76 TEST ("", "", "", 0),
77 TEST ("", "<U0>", "", 0),
78 TEST ("", "abc", "abc", 0),
79
80 TEST ("<U0>", "", "<U0>", 0),
81 TEST ("<U0>", "a", "<U0>a", 0),
82 TEST ("<U0>", "<U0>@2", "<U0>", 0),
83
84 TEST ("ab", "cd", "abcd", 0),
85 TEST ("bcd", "a", "bcda", 0),
86 TEST ("cde", "ab", "cdeab", 0),
87 TEST ("abc", "", "abc", 0),
88 TEST ("ab", "c<U0>e", "abc", 0),
89
90 TEST ("<U0>@2ab", "cdefghij", "<U0>@2abcdefghij", 0),
91 TEST ("a<U0>@2b", "cdefghij", "a<U0>@2bcdefghij", 0),
92 TEST ("ab<U0>@2", "cdefghij", "ab<U0>@2cdefghij", 0),
93 TEST ("a<U0>b<U0>@2c", "e<U0>", "a<U0>b<U0>@2ce", 0),
94 TEST ("<U0>ab<U0>@2c", "e<U0>", "<U0>ab<U0>@2ce", 0),
95 TEST ("abcdefghij", "abcdefghij", "abcdefghijabcdefghij", 0),
96
97 TEST ("", "x@4096", "x@4096", 0),
98 TEST ("x@4096", "", "x@4096", 0),
99 TEST ("x@4096", "x@4096", "x@8192", 0),
100
101 TEST ("x@10", "x@118", "x@128", 0),
102 TEST ("x@128", "x@79", "x@207", 0),
103 TEST ("x@207", "x@127", "x@334", 0),
104 TEST ("x@334", "x@206", "x@540", 0),
105 TEST ("x@540", "x@333", "x@873", 0),
106 TEST ("x@539", "x@873", "x@1412", 0),
107 TEST ("x@872", "x@1412", "x@2284", 0),
108 TEST ("x@1411", "x@2284", "x@3695", 0),
109 TEST ("x@1412", "x@2284", "x@3696", 0),
110
111 TEST ("", 0, "", 0),
112 TEST ("abc", 0, "abcabc", 0),
113 TEST ("a<U0>@2bc", 0, "a<U0>@2bca", 0),
114 TEST ("<U0>@2abc", 0, "<U0>@2abc", 0),
115 TEST ("abc<U0>@2", 0, "abc<U0>@2abc", 0),
116
117 TEST ("last", "test", "lasttest", 0)
118};
119
120
122// exercises:
123// append (const basic_string&)
124static const StringTestCase
125cstr_test_cases [] = {
126
127#undef TEST
128#define TEST(s, arg, res, bthrow) { \
129 __LINE__, -1, -1, -1, -1, -1, \
130 s, sizeof s - 1, \
131 arg, sizeof arg - 1, res, sizeof res - 1, bthrow \
132 }
133
134 // +------------------------------------------ controlled sequence
135 // | +----------------------- sequence to be appended
136 // | | +---------- expected result sequence
137 // | | | +- exception info
138 // | | | | 0 - no exception
139 // | | | | 1 - out_of_range
140 // | | | | 2 - length_error
141 // | | | | -1 - avoid exc. safety
142 // | | | |
143 // | | | +--------------+
144 // V V V V
145 TEST ("ab", "c", "abc", 0),
146
147 TEST ("", "", "", 0),
148 TEST ("", "<U0>", "<U0>", 0),
149 TEST ("", "abc", "abc", 0),
150
151 TEST ("<U0>", "", "<U0>", 0),
152 TEST ("<U0>", "a", "<U0>a", 0),
153 TEST ("<U0>", "<U0>@2", "<U0>@3", 0),
154
155 TEST ("ab", "cd", "abcd", 0),
156 TEST ("bcd", "a", "bcda", 0),
157 TEST ("cde", "ab", "cdeab", 0),
158 TEST ("abc", "", "abc", 0),
159 TEST ("ab", "c<U0>e", "abc<U0>e", 0),
160
161 TEST ("<U0>@2ab", "cdefghij", "<U0>@2abcdefghij", 0),
162 TEST ("a<U0>@2b", "cdefghij", "a<U0>@2bcdefghij", 0),
163 TEST ("ab<U0>@2", "cdefghij", "ab<U0>@2cdefghij", 0),
164 TEST ("a<U0>b<U0>@2c", "e<U0>", "a<U0>b<U0>@2ce<U0>", 0),
165 TEST ("<U0>ab<U0>@2c", "e<U0>", "<U0>ab<U0>@2ce<U0>", 0),
166 TEST ("ab<U0>@2c<U0>", "<U0>e", "ab<U0>@2c<U0>@2e", 0),
167 TEST ("abcdefghij", "abcdefghij", "abcdefghijabcdefghij", 0),
168
169 TEST ("", "x@4096", "x@4096", 0),
170 TEST ("x@4096", "", "x@4096", 0),
171 TEST ("x@4096", "x@4096", "x@8192", 0),
172
173 TEST ("x@10", "x@118", "x@128", 0),
174 TEST ("x@128", "x@79", "x@207", 0),
175 TEST ("x@207", "x@127", "x@334", 0),
176 TEST ("x@334", "x@206", "x@540", 0),
177 TEST ("x@540", "x@333", "x@873", 0),
178 TEST ("x@539", "x@873", "x@1412", 0),
179 TEST ("x@872", "x@1412", "x@2284", 0),
180 TEST ("x@1411", "x@2284", "x@3695", 0),
181 TEST ("x@1412", "x@2284", "x@3696", 0),
182
183 TEST ("", 0, "", 0),
184 TEST ("abc", 0, "abcabc", 0),
185 TEST ("a<U0>@2bc", 0, "a<U0>@2bca<U0>@2bc", 0),
186 TEST ("<U0>@2abc", 0, "<U0>@2abc<U0>@2abc", 0),
187 TEST ("abc<U0>@2", 0, "abc<U0>@2abc<U0>@2", 0),
188
189 TEST ("last", "test", "lasttest", 0)
190};
191
192
194// exercises:
195// append (const value_type*, size_type)
196static const StringTestCase
197cptr_size_test_cases [] = {
198
199#undef TEST
200#define TEST(str, arg, size, res, bthrow) { \
201 __LINE__, -1, size, -1, -1, -1, \
202 str, sizeof str - 1, \
203 arg, sizeof arg - 1, res, sizeof res - 1, bthrow \
204 }
205
206 // +------------------------------------------ controlled sequence
207 // | +------------------------- sequence to be appended
208 // | | +------------ append() n argument
209 // | | | +--------- expected result sequence
210 // | | | | +---- exception info
211 // | | | | | 0 - no exception
212 // | | | | | 1 - out_of_range
213 // | | | | | 2 - length_error
214 // | | | | | -1 - avoid exc. safety
215 // | | | | |
216 // | | | | +------------+
217 // V V V V V
218 TEST ("ab", "c", 1, "abc", 0),
219
220 TEST ("", "", 0, "", 0),
221 TEST ("", "abc", 1, "a", 0),
222 TEST ("", "<U0>", 1, "<U0>", 0),
223
224 TEST ("<U0>", "", 0, "<U0>", 0),
225 TEST ("<U0>", "a", 0, "<U0>", 0),
226 TEST ("<U0>", "a", 1, "<U0>a", 0),
227 TEST ("<U0>", "<U0>@2", 1, "<U0>@2", 0),
228 TEST ("<U0>", "<U0>@2", 2, "<U0>@3", 0),
229
230 TEST ("cde", "ab", 2, "cdeab", 0),
231 TEST ("cde", "ab", 1, "cdea", 0),
232
233 TEST ("<U0>e<U0>", "a<U0>b<U0>@2c", 0, "<U0>e<U0>", 0),
234 TEST ("<U0>e<U0>", "<U0>ab<U0>@2c", 3, "<U0>e<U0>@2ab", 0),
235
236 TEST ("a<U0>b<U0>@2c", "<U0>e<U0>", 3, "a<U0>b<U0>@2c<U0>e<U0>", 0),
237 TEST ("a<U0>b<U0>@2c", "<U0>@2e<U0>", 2, "a<U0>b<U0>@2c<U0>@2", 0),
238 TEST ("<U0>ab<U0>@2c", "<U0>e<U0>", 1, "<U0>ab<U0>@2c<U0>", 0),
239 TEST ("a<U0>bc<U0>@2", "<U0>e", 2, "a<U0>bc<U0>@3e", 0),
240
241 TEST ("x@10", "x@118", 118, "x@128", 0),
242 TEST ("x@128", "x@79", 79, "x@207", 0),
243 TEST ("x@207", "x@127", 127, "x@334", 0),
244 TEST ("x@207", "x@207", 127, "x@334", 0),
245 TEST ("x@334", "x@206", 206, "x@540", 0),
246 TEST ("x@540", "x@333", 333, "x@873", 0),
247 TEST ("x@539", "x@873", 873, "x@1412", 0),
248 TEST ("x@873", "x@540", 539, "x@1412", 0),
249 TEST ("x@872", "x@1412", 1412, "x@2284", 0),
250 TEST ("x@1411", "x@2284", 2284, "x@3695", 0),
251 TEST ("x@1411", "x@3695", 2284, "x@3695", 0),
252 TEST ("x@1412", "x@2284", 2284, "x@3696", 0),
253
254 TEST ("", 0, 0, "", 0),
255 TEST ("abc", 0, 0, "abc", 0),
256 TEST ("abc", 0, 1, "abca", 0),
257 TEST ("abc", 0, 2, "abcab", 0),
258 TEST ("a<U0>bc", 0, 2, "a<U0>bca<U0>", 0),
259 TEST ("<U0>abc<U0>@2", 0, 1, "<U0>abc<U0>@3", 0),
260 TEST ("a<U0>bc<U0>@2", 0, 3, "a<U0>bc<U0>@2a<U0>b", 0),
261 TEST ("a@4096", 0, 1111, "a@5207", 0),
262 TEST ("b@4096", 0, 2222, "b@6318", 0),
263
264 TEST ("", "x@4096", 4096, "x@4096", 0),
265 TEST ("x@4096", "", 0, "x@4096", 0),
266
267 TEST ("last", "test", 4, "lasttest", 0)
268};
269
270
272// exercises:
273// append (const basic_string&, size_type, size_type)
274// append (InputIterator, InputIterator)
275static const StringTestCase
276range_test_cases [] = {
277
278// range_test_cases serves a double duty
279#define cstr_size_size_test_cases range_test_cases
280
281#undef TEST
282#define TEST(str, arg, off, size, res, bthrow) { \
283 __LINE__, -1, -1, off, size, -1, \
284 str, sizeof str - 1, \
285 arg, sizeof arg - 1, res, sizeof res - 1, bthrow \
286 }
287
288 // +------------------------------------------ controlled sequence
289 // | +------------------------- sequence to be appended
290 // | | +------------ append() pos argument
291 // | | | +--------- append() n argument
292 // | | | | +------ expected result sequence
293 // | | | | | +--- exception info
294 // | | | | | | 0 - no exception
295 // | | | | | | 1 - out_of_range
296 // | | | | | | 2 - length_error
297 // | | | | | | -1 - exc. safety
298 // | | | | | |
299 // | | | | | +----------------+
300 // V V V V V V
301 TEST ("ab", "c", 0, 1, "abc", 0),
302
303 TEST ("", "", 0, 0, "", 0),
304 TEST ("", "abc", 1, 1, "b", 0),
305 TEST ("", "<U0>", 0, 1, "<U0>", 0),
306
307 TEST ("<U0>", "", 0, 0, "<U0>", 0),
308
309 TEST ("abc", "", 0, 0, "abc", 0),
310
311 TEST ("<U0>", "a", 0, 1, "<U0>a", 0),
312 TEST ("<U0>", "<U0>@2", 1, 1, "<U0>@2", 0),
313 TEST ("<U0>", "<U0>@2", 0, 2, "<U0>@3", 0),
314 TEST ("<U0>", "<U0>@2", 1, 5, "<U0>@2", 0),
315
316 TEST ("cde", "ab", 0, 2, "cdeab", 0),
317 TEST ("cde", "ab", 0, 1, "cdea", 0),
318 TEST ("cde", "ab", 1, 5, "cdeb", 0),
319
320 TEST ("ab", "c<U0>e", 0, 3, "abc<U0>e", 0),
321 TEST ("ab", "c<U0>e", 1, 2, "ab<U0>e", 0),
322 TEST ("ab", "c<U0>e", 0, 2, "abc<U0>", 0),
323
324 TEST ("<U0>e<U0>", "<U0>ab<U0>@2c", 0, 9, "<U0>e<U0>@2ab<U0>@2c", 0),
325 TEST ("<U0>e<U0>", "<U0>ab<U0>@2c", 0, 3, "<U0>e<U0>@2ab", 0),
326 TEST ("a<U0>b<U0>@2c", "<U0>e<U0>", 0, 3, "a<U0>b<U0>@2c<U0>e<U0>", 0),
327 TEST ("a<U0>b<U0>@2c", "<U0>@2e<U0>", 0, 2, "a<U0>b<U0>@2c<U0>@2", 0),
328 TEST ("<U0>ab<U0>@2c", "<U0>e<U0>", 2, 1, "<U0>ab<U0>@2c<U0>", 0),
329 TEST ("a<U0>bc<U0>@2", "<U0>e", 0, 2, "a<U0>bc<U0>@3e", 0),
330
331 TEST ("", 0, 0, 0, "", 0),
332 TEST ("abc", 0, 1, 0, "abc", 0),
333 TEST ("abc", 0, 1, 1, "abcb", 0),
334 TEST ("abc", 0, 0, 2, "abcab", 0),
335 TEST ("a<U0>bc<U0>@2", 0, 4, 2, "a<U0>bc<U0>@3<U0>", 0),
336 TEST ("a<U0>bc<U0>@2", 0, 1, 3, "a<U0>bc<U0>@3bc", 0),
337 TEST ("a<U0>bc<U0>@2", 0, 3, 9, "a<U0>bc<U0>@2c<U0>@2", 0),
338 TEST ("abcdef", 0, 1, 2, "abcdefbc", 0),
339
340 TEST ("a@1000", "b@1000", 0, 999, "a@1000b@999", 0),
341 TEST ("a@1000", "b@1001", 0, 1000, "a@1000b@1000", 0),
342 TEST ("a@1000", "b@1002", 0, 102, "a@1000b@102", 0),
343 TEST ("", "x@4096", 0, 4096, "x@4096", 0),
344 TEST ("x@4096", "", 0, 0, "x@4096", 0),
345 TEST ("x@4096", "a@4096", 100, 10, "x@4096a@10", 0),
346
347 TEST ("x@10", "x@118", 0, 118, "x@128", 0),
348 TEST ("x@128", "x@129", 50, 79, "x@207", 0),
349 TEST ("x@207", "x@127", 0, 127, "x@334", 0),
350 TEST ("x@207", "x@207", 10, 127, "x@334", 0),
351 TEST ("x@334", "x@208", 2, 206, "x@540", 0),
352 TEST ("x@540", "x@336", 3, 333, "x@873", 0),
353 TEST ("x@539", "x@873", 0, 873, "x@1412", 0),
354 TEST ("x@873", "x@540", 1, 539, "x@1412", 0),
355 TEST ("x@872", "x@1412", 0, 1412, "x@2284", 0),
356 TEST ("x@1411", "x@2288", 4, 2284, "x@3695", 0),
357 TEST ("x@1411", "x@3695", 128, 2284, "x@3695", 0),
358 TEST ("x@1412", "x@2284", 0, 2284, "x@3696", 0),
359
360 TEST ("", "<U0>", 2, 0, "", 1),
361 TEST ("", "a", 2, 0, "", 1),
362 TEST ("", "x@4096", 4106, 0, "", 1),
363
364 TEST ("last", "test", 0, 4, "lasttest", 0)
365};
366
367
369// exercises:
370// append (value_type, size_type)
371static const StringTestCase
372size_val_test_cases [] = {
373
374#undef TEST
375#define TEST(str, size, val, res, bthrow) { \
376 __LINE__, -1, size, -1, -1, val, \
377 str, sizeof str - 1, \
378 0, 0, res, sizeof res - 1, bthrow \
379 }
380
381 // +------------------------------------------ controlled sequence
382 // | +------------------------- append() count argument
383 // | | +--------------------- character to be appended
384 // | | | +----------------- expected result sequence
385 // | | | | +--------- exception info
386 // | | | | | 0 - no exception
387 // | | | | | 1 - out_of_range
388 // | | | | | 2 - length_error
389 // | | | | | -1 - exc. safety
390 // | | | | |
391 // | | | | +-----------+
392 // V V V V V
393 TEST ("ab", 1, 'c', "abc", 0),
394
395 TEST ("", 0, ' ', "", 0),
396 TEST ("", 1, 'b', "b", 0),
397 TEST ("", 3, 'b', "bbb", 0),
398
399 TEST ("<U0>", 0, ' ', "<U0>", 0),
400 TEST ("", 2, '\0', "<U0>@2", 0),
401
402 TEST ("<U0>", 1, 'a', "<U0>a", 0),
403 TEST ("<U0>", 1, '\0', "<U0>@2", 0),
404 TEST ("<U0>", 2, '\0', "<U0>@3", 0),
405 TEST ("<U0>", 0, '\0', "<U0>", 0),
406
407 TEST ("cde", 1, 'a', "cdea", 0),
408 TEST ("cde", 2, 'a', "cdeaa", 0),
409 TEST ("cde", 3, 'a', "cdeaaa", 0),
410
411 TEST ("ab", 2, '\0', "ab<U0>@2", 0),
412 TEST ("ab", 1, '\0', "ab<U0>", 0),
413 TEST ("ab", 2, '\0', "ab<U0>@2", 0),
414
415 TEST ("a<U0>b<U0>@2c", 2, '\0', "a<U0>b<U0>@2c<U0>@2", 0),
416 TEST ("a<U0>b<U0>@2c", 1, '\0', "a<U0>b<U0>@2c<U0>", 0),
417 TEST ("<U0>ab<U0>@2c", 3, '\0', "<U0>ab<U0>@2c<U0>@3", 0),
418 TEST ("a<U0>bc<U0>@2", 2, 'a', "a<U0>bc<U0>@2aa", 0),
419
420 TEST ("", 4096, 'x', "x@4096", 0),
421 TEST ("x@4096", 0, 'x', "x@4096", 0),
422
423 TEST ("x@127", 1, 'x', "x@128", 0),
424 TEST ("x@200", 7, 'x', "x@207", 0),
425 TEST ("x@331", 3, 'x', "x@334", 0),
426 TEST ("x@539", 1, 'x', "x@540", 0),
427 TEST ("x@539", 873, 'x', "x@1412", 0),
428 TEST ("x@873", 1411, 'x', "x@2284", 0),
429 TEST ("x@3694", 1, 'x', "x@3695", 0),
430 TEST ("x@540", 1, 'x', "x@541", 0),
431
432 TEST ("last", 4, 't', "lasttttt", 0)
433};
434
435
437// exercises:
438// push_back (value_type)
439static const StringTestCase
440push_back_val_test_cases [] = {
441
442#undef TEST
443#define TEST(str, val, res, bthrow) { \
444 __LINE__, -1, -1, -1, -1, val, \
445 str, sizeof str - 1, \
446 0, 0, res, sizeof res - 1, bthrow \
447 }
448
449 // +---------------------------------------- controlled sequence
450 // | +---------------------- character to be appended
451 // | | +----------------- expected result sequence
452 // | | | +--------- exception info
453 // | | | | 0 - no exception
454 // | | | | -1 - exc. safety
455 // | | | |
456 // | | | +------------+
457 // V V V V
458 TEST ("ab", 'c', "abc", 0),
459
460 TEST ("", 'a', "a", 0),
461 TEST ("", '\0', "<U0>", 0),
462 TEST ("<U0>", 'a', "<U0>a", 0),
463 TEST ("<U0>", '\0', "<U0>@2", 0),
464
465 TEST ("a<U0>b<U0>@2c", '\0', "a<U0>b<U0>@2c<U0>", 0),
466 TEST ("a<U0>bc<U0>@2", 'a', "a<U0>bc<U0>@2a", 0),
467 TEST ("<U0>abc<U0>@2", 'a', "<U0>abc<U0>@2a", 0),
468
469 TEST ("x@4095", 'x', "x@4096", 0),
470
471 TEST ("x@127", 'x', "x@128", 0),
472 TEST ("x@206", 'x', "x@207", 0),
473 TEST ("x@333", 'x', "x@334", 0),
474 TEST ("x@539", 'x', "x@540", 0),
475 TEST ("x@1411", 'x', "x@1412", 0),
476 TEST ("x@2283", 'x', "x@2284", 0),
477 TEST ("x@3694", 'x', "x@3695", 0),
478 TEST ("x@540", 'x', "x@541", 0),
479
480 TEST ("last", 't', "lastt", 0)
481};
482
483
485// invokes specializations of the member function template
486// on the required iterator categories
487template <class String, class Iterator>
488struct AppendRange: RangeBase<String> {
489
490 typedef typename String::iterator StringIter;
491 typedef typename String::value_type StringChar;
492
494
495 virtual String&
497 const StringTestCaseData<StringChar>& tdata) const {
498
499 const StringTestCase &tcase = tdata.tcase_;
500
501 const String &cstr = str;
502
503 // when (0 == tcase.arg) exercise self-referential modification
504 // (i.e., replacing a range of elements with a subrange of its
505 // own elements)
506 const StringChar* const beg =
507 (tcase.arg ? tdata.arg_ : cstr.data ()) + tdata.off2_;
508
509 const StringChar* const end = beg + tdata.ext2_;
510
511 const Iterator first (beg, beg, end);
512 const Iterator last (end, beg, end);
513
514 return str.append (first, last);
515 }
516};
517
518
520// invokes possible overloads of the member function template
521// on common RandomAccessIterator types
522template <class String, class Iterator>
524{
525 typedef typename String::iterator StringIter;
526 typedef typename String::value_type StringChar;
527
529
530 virtual String&
532 const StringTestCaseData<StringChar>& tdata) const {
533
534 const StringTestCase &tcase = tdata.tcase_;
535
536 bool reverse_iter = StringIds::ReverseIterator == tdata.func_.iter_id_
538
539 const std::size_t srclen_ = tcase.arg ? tdata.arglen_ : str.size ();
540
541 const std::size_t off =
542 reverse_iter ? srclen_ - tdata.off2_ - tdata.ext2_ : tdata.off2_;
543 const std::size_t ext = tdata.ext2_;
544
545 if (0 == tcase.arg) {
546 // exercise self-referential modification (i.e., replacing
547 // a range of elements with a subrange of its own elements)
548
549 const Iterator first (this->begin (str, (Iterator*)0) + off);
550 const Iterator last (first + ext);
551
552 return str.append (first, last);
553 }
554
555 String str_arg (tdata.arg_, tdata.arglen_);
556
557 const Iterator first (this->begin (str_arg, (Iterator*)0) + off);
558 const Iterator last (first + ext);
559
560 return str.append (first, last);
561 }
562};
563
564
566template <class charT, class Traits, class Allocator>
568 std::basic_string <charT, Traits, Allocator> > &rng,
569 const StringTestCaseData<charT> &tdata)
570{
571 typedef std::basic_string <charT, Traits, Allocator> String;
572 typedef typename String::size_type SizeT;
573 typedef typename String::iterator StringIter;
574 typedef typename UserTraits<charT>::MemFun TraitsFunc;
575
576 const StringFunc &func = tdata.func_;
577 const StringTestCase &tcase = tdata.tcase_;
578
579 // construct the string object to be modified
580 // and the (possibly unused) argument string
581 /* const */ String str (tdata.str_, tdata.strlen_);
582 const String arg (tdata.arg_, tdata.arglen_);
583
584 // save the state of the string object before the call
585 // to detect wxception safety violations (changes to
586 // the state of the object after an exception)
587 const StringState str_state (rw_get_string_state (str));
588
589 const charT* const ptr_arg = tcase.arg ? arg.c_str () : str.c_str ();
590 const String& str_arg = tcase.arg ? arg : str;
591 const charT val_arg = (make_char (char (tcase.val), (charT*)0));
592
593 std::size_t total_length_calls = 0;
594 std::size_t n_length_calls = 0;
595 std::size_t* const rg_calls = rw_get_call_counters ((Traits*)0, (charT*)0);
596
597 if (rg_calls)
598 total_length_calls = rg_calls [TraitsFunc::length];
599
600 rwt_free_store* const pst = rwt_get_free_store (0);
601 SharedAlloc* const pal = SharedAlloc::instance ();
602
603 // iterate for`throw_after' starting at the next call to operator new,
604 // forcing each call to throw an exception, until the function finally
605 // succeeds (i.e, no exception is thrown)
606 std::size_t throw_count;
607 for (throw_count = 0; ; ++throw_count) {
608
609 // (name of) expected and caught exception
610 const char* expected = 0;
611 const char* caught = 0;
612
613#ifndef _RWSTD_NO_EXCEPTIONS
614
615 if (1 == tcase.bthrow && Append (cstr_size_size) == func.which_)
616 expected = exceptions [1]; // out_of_range
617 else if (2 == tcase.bthrow)
618 expected = exceptions [2]; // length_error
619 else if (0 == tcase.bthrow) {
620 // by default excercise the exception safety of the function
621 // by iteratively inducing an exception at each call to operator
622 // new or Allocator::allocate() until the call succeeds
623 expected = exceptions [3]; // bad_alloc
624 *pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_count + 1;
625 pal->throw_at_calls_ [pal->m_allocate] =
626 pal->throw_at_calls_ [pal->m_allocate] + throw_count + 1;
627 }
628 else {
629 // exceptions disabled for this test case
630 }
631
632#else // if defined (_RWSTD_NO_EXCEPTIONS)
633
634 if (tcase.bthrow)
635 return;
636
637#endif // _RWSTD_NO_EXCEPTIONS
638
639 // pointer to the returned reference
640 const String* ret_ptr = 0;
641
642 // start checking for memory leaks
643 rw_check_leaks (str.get_allocator ());
644
645 try {
646
647 switch (func.which_) {
648
649 case Append (cptr):
650 ret_ptr = &str.append (ptr_arg);
651 if (rg_calls)
652 n_length_calls = rg_calls [TraitsFunc::length];
653 break;
654
655 case Append (cstr):
656 ret_ptr = &str.append (str_arg);
657 break;
658
659 case Append (cptr_size):
660 ret_ptr = &str.append (ptr_arg, tcase.size);
661 break;
662
663 case Append (cstr_size_size):
664 ret_ptr = &str.append (str_arg,
665 SizeT (tcase.off2), SizeT (tcase.size2));
666 break;
667
668 case Append (size_val):
669 ret_ptr = &str.append (tcase.size, val_arg);
670 break;
671
672 case Append (range):
673 ret_ptr = &rng (str, tdata);
674 break;
675
676 case PushBack (val):
677 str.push_back (val_arg);
678 ret_ptr = &str;
679 break;
680
681 default:
682 RW_ASSERT (!"logic error: unknown append overload");
683 }
684
685 // verify that the reference returned from the function
686 // refers to the modified string object (i.e., *this
687 // within the function)
688 const std::ptrdiff_t ret_off = ret_ptr - &str;
689
690 // verify the returned value
691 rw_assert (0 == ret_off, 0, tcase.line,
692 "line %d. %{$FUNCALL} returned invalid reference, "
693 "offset is %td", __LINE__, ret_off);
694
695 // for convenience
696 static const int cwidth = sizeof (charT);
697
698 // verify that strings are of equal length
699 rw_assert (tdata.reslen_ == str.size (), 0, tcase.line,
700 "line %d. %{$FUNCALL} expected %{/*.*Gs}, "
701 "length %zu, got %{/*.*Gs}, length %zu",
702 __LINE__, cwidth, int (tdata.reslen_), tdata.res_,
703 tdata.reslen_, cwidth,
704 int (str.size ()), str.c_str (), str.size ());
705
706 if (tdata.reslen_ == str.size ()) {
707 // if the result length matches the expected length
708 // (and only then), also verify that the modified
709 // string matches the expected result
710 const std::size_t match =
711 rw_match (tcase.res, str.c_str (), str.size ());
712
713 rw_assert (match == tdata.reslen_, 0, tcase.line,
714 "line %d. %{$FUNCALL} expected %{/*.*Gs}, "
715 "got %{/*.*Gs}, difference at offset %zu",
716 __LINE__, cwidth, int (tdata.reslen_), tdata.res_,
717 cwidth, int (str.size ()), str.c_str (), match);
718 }
719
720 // verify that Traits::length was used
721 if (Append (cptr) == func.which_ && rg_calls) {
722 rw_assert (n_length_calls - total_length_calls > 0,
723 0, tcase.line, "line %d. %{$FUNCALL} doesn't "
724 "use traits::length()", __LINE__);
725 }
726 }
727
728#ifndef _RWSTD_NO_EXCEPTIONS
729
730 catch (const std::out_of_range &ex) {
731 caught = exceptions [1];
732 rw_assert (caught == expected, 0, tcase.line,
733 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
734 "unexpectedly%{;} caught std::%s(%#s)",
735 __LINE__, 0 != expected, expected, caught, ex.what ());
736 }
737 catch (const std::length_error &ex) {
738 caught = exceptions [2];
739 rw_assert (caught == expected, 0, tcase.line,
740 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
741 "unexpectedly%{;} caught std::%s(%#s)",
742 __LINE__, 0 != expected, expected, caught, ex.what ());
743 }
744 catch (const std::bad_alloc &ex) {
745 caught = exceptions [3];
746 rw_assert (0 == tcase.bthrow, 0, tcase.line,
747 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
748 "unexpectedly%{;} caught std::%s(%#s)",
749 __LINE__, 0 != expected, expected, caught, ex.what ());
750 }
751 catch (const std::exception &ex) {
752 caught = exceptions [4];
753 rw_assert (0, 0, tcase.line,
754 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
755 "unexpectedly%{;} caught std::%s(%#s)",
756 __LINE__, 0 != expected, expected, caught, ex.what ());
757 }
758 catch (...) {
759 caught = exceptions [0];
760 rw_assert (0, 0, tcase.line,
761 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
762 "unexpectedly%{;} caught %s",
763 __LINE__, 0 != expected, expected, caught);
764 }
765
766#endif // _RWSTD_NO_EXCEPTIONS
767
768 // FIXME: verify the number of blocks the function call
769 // is expected to allocate and detect any memory leaks
770 rw_check_leaks (str.get_allocator (), tcase.line,
771 std::size_t (-1), std::size_t (-1));
772
773 if (caught) {
774 // verify that an exception thrown during allocation
775 // didn't cause a change in the state of the object
777 __LINE__, tcase.line, caught);
778
779 if (0 == tcase.bthrow) {
780 // allow this call to operator new to succeed and try
781 // to make the next one to fail during the next call
782 // to the same function again
783 continue;
784 }
785 }
786 else if (0 < tcase.bthrow) {
787 rw_assert (caught == expected, 0, tcase.line,
788 "line %d. %{$FUNCALL} %{?}expected %s, caught %s"
789 "%{:}unexpectedly caught %s%{;}",
790 __LINE__, 0 != expected, expected, caught, caught);
791 }
792
793 break;
794 }
795
796#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
797
798 // verify that if exceptions are enabled and when capacity changes
799 // at least one exception is thrown
800 const std::size_t expect_throws = str_state.capacity_ < str.capacity ();
801
802#else // if defined (_RWSTD_NO_REPLACEABLE_NEW_DELETE)
803
804 const std::size_t expect_throws =
805 (StringIds::UserAlloc == func.alloc_id_)
806 ? str_state.capacity_ < str.capacity (): 0;
807
808#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
809
810 // verify number of exceptions thrown
811 // for range version the allocation may take place several times
812 if (Append (range) != func.which_)
813 rw_assert (expect_throws == throw_count, 0, tcase.line,
814 "line %d: %{$FUNCALL}: expected exactly 1 %s exception "
815 "while changing capacity from %zu to %zu, got %zu",
816 __LINE__, exceptions [3],
817 str_state.capacity_, str.capacity (), throw_count);
818 else
819 rw_assert (expect_throws <= throw_count, 0, tcase.line,
820 "line %d: %{$FUNCALL}: expected at least 1 %s exception "
821 "while changing capacity from %zu to %zu, got %zu",
822 __LINE__, exceptions [3],
823 str_state.capacity_, str.capacity (), throw_count);
824
825 // disable bad_alloc exceptions
826 *pst->throw_at_calls_ [0] = 0;
827 pal->throw_at_calls_ [pal->m_allocate] = 0;
828}
829
830
832template <class charT, class Traits, class Allocator>
834 const StringTestCaseData<charT> &tdata)
835{
836 typedef std::basic_string<charT, Traits, Allocator> String;
837
838 if (tdata.func_.which_ == Append (range)) {
839
840 switch (tdata.func_.iter_id_) {
841
842 // exercise possible overloads of the member function template
843 // on common RandomAccessIterator types
844#undef TEST
845#define TEST(Iterator) do { \
846 typedef typename String::Iterator Iter; \
847 static const \
848 AppendRangeOverload<String, Iter> rng; \
849 test_append ((charT*)0, (Traits*)0, (Allocator*)0, rng, tdata); \
850 } while (0)
851
852 case StringIds::Pointer: TEST (pointer); break;
853 case StringIds::ConstPointer: TEST (const_pointer); break;
854 case StringIds::Iterator: TEST (iterator); break;
855 case StringIds::ConstIterator: TEST (const_iterator); break;
856
857 case StringIds::ReverseIterator: TEST (reverse_iterator); break;
858 case StringIds::ConstReverseIterator: TEST (const_reverse_iterator);
859 break;
860
861 // exercise specializations of the member function template
862 // on the required iterator categories
863
864#undef TEST
865#define TEST(Iterator) do { \
866 typedef Iterator<charT> Iter; \
867 static const \
868 AppendRange<String, Iter> rng; \
869 test_append ((charT*)0, (Traits*)0, (Allocator*)0, rng, tdata); \
870 } while (0)
871
872 case StringIds::Input: TEST (InputIter); break;
873 case StringIds::Forward: TEST (ConstFwdIter); break;
874 case StringIds::Bidir: TEST (ConstBidirIter); break;
876
877 default:
878 rw_error (0, 0, __LINE__, "bad iterator id");
879 }
880 }
881 else {
882 // exercise ordinary overloads of the member function
883 static const RangeBase<String > rng;
884 test_append ((charT*)0, (Traits*)0, (Allocator*)0, rng, tdata);
885 }
886}
887
888
891
892int main (int argc, char** argv)
893{
894 static const StringTest
895 tests [] = {
896
897#undef TEST
898#define TEST(sig) { \
899 Append (sig), sig ## _test_cases, \
900 sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
901 }
902
903 TEST (cptr),
904 TEST (cstr),
905 TEST (cptr_size),
906 TEST (cstr_size_size),
907 TEST (size_val),
908 TEST (range),
909
910 {
911 StringIds::push_back_val, push_back_val_test_cases,
912 sizeof push_back_val_test_cases / sizeof *push_back_val_test_cases
913 }
914 };
915
916 const std::size_t test_count = sizeof tests / sizeof *tests;
917
918 const int status =
919 rw_run_string_test (argc, argv, __FILE__,
920 "lib.string.append",
921 test_append_func_array, tests, test_count);
922
923 return status;
924}
#define last
Definition 17.names.cpp:487
#define off
Definition 17.names.cpp:507
#define charT
Definition 17.names.cpp:456
#define val
Definition 17.names.cpp:570
void test_append(charT *, Traits *, Allocator *, const RangeBase< std::basic_string< charT, Traits, Allocator > > &rng, const StringTestCaseData< charT > &tdata)
#define TEST(str, arg, res, bthrow)
#define PushBack(sig)
#define Append(sig)
#define range_test_cases
std::char_traits< S > Traits
const int end
#define main
int caught
const StringTestCase & tcase_
Definition rw_strings.h:692
const charT *const arg_
Definition rw_strings.h:688
const charT *const res_
Definition rw_strings.h:689
const StringFunc & func_
Definition rw_strings.h:691
const charT *const str_
Definition rw_strings.h:687
const char * str
Definition exec.cpp:170
_TEST_EXPORT void rw_check_leaks(const SharedAlloc *=0, int=0, _RWSTD_SIZE_T=0, _RWSTD_SIZE_T=_RWSTD_SIZE_MAX)
UserChar make_char(char c, UserChar *)
Definition rw_char.h:74
_RWSTD_SIZE_T * rw_get_call_counters(std::char_traits< charT > *, charT *)
Definition rw_char.h:495
_TEST_EXPORT _RWSTD_SIZE_T rw_match(const char *, const char *, _RWSTD_SIZE_T=_RWSTD_SIZE_MAX)
_TEST_EXPORT int rw_assert(int, const char *, int, const char *,...)
Definition driver.cpp:1630
_TEST_EXPORT int rw_error(int, const char *, int, const char *,...)
Definition driver.cpp:1613
_TEST_EXPORT rwt_free_store * rwt_get_free_store(rwt_free_store *)
Definition new.cpp:597
StringState rw_get_string_state(const String &str)
Definition rw_strings.h:752
_TEST_EXPORT int rw_run_string_test(int, char **, const char *, const char *, StringTestFunc *, const StringTest *, _RWSTD_SIZE_T)
#define DEFINE_STRING_TEST_FUNCTIONS(fname)
Definition rw_strings.h:909
#define RW_ASSERT(expr)
String::value_type StringChar
String::iterator StringIter
virtual String & operator()(String &str, const StringTestCaseData< StringChar > &tdata) const
String::iterator StringIter
virtual String & operator()(String &str, const StringTestCaseData< StringChar > &tdata) const
String::value_type StringChar
static StringPtr begin(String &str, StringPtr *)
Definition rw_strings.h:781
static SharedAlloc * instance(SharedAlloc *=0)
_RWSTD_SIZE_T throw_at_calls_[n_funs]
StringIds::OverloadId which_
Definition rw_strings.h:577
StringIds::IteratorId iter_id_
Definition rw_strings.h:576
_RWSTD_SIZE_T capacity_
Definition rw_strings.h:741
int assert_equal(const StringState &, int, int, const char *) const
const char * arg
Definition rw_strings.h:599
const char * res
Definition rw_strings.h:602
_RWSTD_SIZE_T * throw_at_calls_[2]
Definition rw_new.h:83
_RWSTD_SIZE_T new_calls_[2]
Definition rw_new.h:47
int arg
Definition locale.cpp:2806