Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
21.string.erase.cpp
Go to the documentation of this file.
1
29#include <string> // for string
30#include <cstddef> // for ptrdiff_t, size_t
31#include <stdexcept> // for out_of_range
32
33#include <rw_strings.h> // for StringMembers
34#include <rw_driver.h> // for rw_test()
35#include <rw_allocator.h> // for UserAlloc
36#include <rw_char.h> // for rw_expand()
37#include <rw_new.h> // for bad_alloc, replacement operator new
38
39
41// for convenience and brevity
42#define Erase(sig) StringIds::erase_ ## sig
43
44static const char* const exceptions[] = {
45 "unknown exception", "out_of_range", "length_error",
46 "bad_alloc", "exception"
47};
48
49
51// used to exercise
52// erase ()
53static const StringTestCase
54void_test_cases [] = {
55
56#undef TEST
57#define TEST(str, res) { \
58 __LINE__, -1, -1, -1, -1, -1, str, sizeof str - 1, \
59 0, 0, res, sizeof res - 1, 0 }
60
61 // +--------------------------------- controlled sequence
62 // | +--------------- expected result sequence
63 // | |
64 // V V
65 TEST ("a", ""),
66
67 TEST ("", ""),
68 TEST ("<U0>", ""),
69 TEST ("abc", ""),
70 TEST ("t<U0> s", ""),
71 TEST ("<U0>ab<U0>@2c", ""),
72 TEST ("a<U0>b<U0>@2c", ""),
73 TEST ("a<U0>bc<U0>@2", ""),
74
75 TEST ("x@4096", ""),
76 TEST ("last", "")
77};
78
79
80
82// used to exercise
83// erase (size_type)
84static const StringTestCase
85size_test_cases [] = {
86
87#undef TEST
88#define TEST(str, off, res, bthrow) { \
89 __LINE__, off, -1, -1, -1, -1, str, sizeof str - 1, \
90 0, 0, res, sizeof res - 1, bthrow }
91
92 // +-------------------------------------- controlled sequence
93 // | +------------------ erase() pos argument
94 // | | +------------- expected result sequence
95 // | | | +--- exception info
96 // | | | | 0 - no exception
97 // | | | | 1 - out_of_range
98 // | | | |
99 // V V V V
100 TEST ("", 0, "", 0),
101 TEST ("<U0>", 0, "", 0),
102 TEST ("<U0>", 1, "<U0>", 0),
103 TEST ("<U0>@2", 1, "<U0>", 0),
104
105 TEST ("a", 0, "", 0),
106 TEST ("a", 1, "a", 0),
107
108 TEST ("abc", 0, "", 0),
109 TEST ("abc", 1, "a", 0),
110 TEST ("abc", 2, "ab", 0),
111 TEST ("abc", 3, "abc", 0),
112
113 TEST ("t<U0> s", 0, "", 0),
114 TEST ("t<U0> s", 1, "t", 0),
115 TEST ("t<U0> s", 2, "t<U0>", 0),
116 TEST ("t<U0> s", 3, "t<U0> ", 0),
117 TEST ("t<U0> s", 4, "t<U0> s", 0),
118
119 TEST ("a<U0>@3b", 2, "a<U0>", 0),
120 TEST ("a<U0>@3b", 1, "a", 0),
121 TEST ("a<U0>@3b", 0, "", 0),
122 TEST ("a<U0>b<U0>@2c", 0, "", 0),
123 TEST ("a<U0>b<U0>@2c", 4, "a<U0>b<U0>", 0),
124 TEST ("<U0>ab<U0>@2c", 2, "<U0>a", 0),
125 TEST ("ab<U0>c<U0>@2", 5, "ab<U0>c<U0>", 0),
126
127 TEST ("a", 3, "a", 1),
128 TEST ("t<U0> s", 5, "t<U0> s", 1),
129 TEST ("ab<U0>c<U0>@2", 10, "ab<U0>c<U0>@2", 1),
130 TEST ("x@4096", 4106, "x@4096", 1),
131
132 TEST ("x@4096", 0, "", 0),
133 TEST ("x@4096", 1, "x", 0),
134 TEST ("x@4096", 4, "xxxx", 0),
135 TEST ("x@4096", 4096, "x@4096", 0),
136 TEST ("x@2048y@2048", 2048, "x@2048", 0),
137
138 TEST ("last test", 4, "last", 0)
139};
140
141
142
144// used to exercise
145// erase (size_type, size_type)
146// erase (iterator, iterator)
147static const StringTestCase
148size_size_test_cases [] = {
149
150// size_size_test_cases serves a double duty
151#define iter_iter_test_cases size_size_test_cases
152
153#undef TEST
154#define TEST(str, off, size, res, bthrow) { \
155 __LINE__, off, size, -1, -1, -1, str, sizeof str - 1, \
156 0, 0, res, sizeof res - 1, bthrow }
157
158 // +----------------------------------------- controlled sequence
159 // | +--------------------- erase() pos argument
160 // | | +----------- erase() n argument
161 // | | | +------- expected result sequence
162 // | | | | +--- exception info
163 // | | | | | 0 - no exception
164 // | | | | | 1 - out_of_range
165 // | | | | |
166 // | | | | +-------+
167 // V V V V V
168 TEST ("", 0, 0, "", 0),
169 TEST ("<U0>", 0, 1, "", 0),
170 TEST ("<U0>", 0, 0, "<U0>", 0),
171 TEST ("<U0>", 1, 1, "<U0>", 0),
172 TEST ("<U0>@2", 1, 1, "<U0>", 0),
173 TEST ("<U0>@2", 0, 1, "<U0>", 0),
174
175 TEST ("a", 0, 1, "", 0),
176 TEST ("a", 0, 0, "a", 0),
177 TEST ("a", 1, 1, "a", 0),
178
179 TEST ("abc", 0, 3, "", 0),
180 TEST ("abc", 0, 2, "c", 0),
181 TEST ("abc", 1, 2, "a", 0),
182 TEST ("abc", 1, 1, "ac", 0),
183 TEST ("abc", 2, 1, "ab", 0),
184 TEST ("abc", 3, 0, "abc", 0),
185
186 TEST ("t<U0> s", 0, 3, "s", 0),
187 TEST ("t<U0> s", 0, 4, "", 0),
188 TEST ("t<U0> s", 0, 1, "<U0> s", 0),
189 TEST ("t<U0> s", 1, 3, "t", 0),
190 TEST ("t<U0> s", 1, 2, "ts", 0),
191 TEST ("t<U0> s", 2, 2, "t<U0>", 0),
192 TEST ("t<U0> s", 2, 1, "t<U0>s", 0),
193 TEST ("t<U0> s", 3, 2, "t<U0> ", 0),
194 TEST ("t<U0> s", 4, 0, "t<U0> s", 0),
195
196 TEST ("a<U0>@3b", 2, 0, "a<U0>@3b", 0),
197 TEST ("a<U0>@3b", 2, 3, "a<U0>", 0),
198 TEST ("a<U0>@3b", 2, 2, "a<U0>b", 0),
199 TEST ("a<U0>@3b", 1, 4, "a", 0),
200 TEST ("a<U0>@3b", 0, 5, "", 0),
201 TEST ("a<U0>@3b", 0, 2, "<U0>@2b", 0),
202 TEST ("a<U0>b<U0>@2c", 0, 6, "", 0),
203 TEST ("a<U0>b<U0>@2c", 4, 2, "a<U0>b<U0>", 0),
204 TEST ("a<U0>b<U0>@2c", 4, 1, "a<U0>b<U0>c", 0),
205 TEST ("<U0>ab<U0>@2c", 2, 5, "<U0>a", 0),
206 TEST ("<U0>ab<U0>@2c", 0, 4, "<U0>c", 0),
207 TEST ("ab<U0>c<U0>@2", 5, 1, "ab<U0>c<U0>", 0),
208
209 TEST ("a", 0, 3, "", 0),
210 TEST ("t<U0> s", 0, 9, "", 0),
211 TEST ("ab<U0>c<U0>@2", 0, 10, "", 0),
212 TEST ("x@4096", 0, 4105, "", 0),
213
214 TEST ("a", 3, 1, "a", 1),
215 TEST ("t<U0> s", 5, 1, "t<U0> s", 1),
216 TEST ("ab<U0>c<U0>@2", 10, 1, "ab<U0>c<U0>@2", 1),
217 TEST ("x@4096", 4106, 1, "x@4096", 1),
218
219 TEST ("x@4096", 0, 4096, "", 0),
220 TEST ("x@4096", 1, 4095, "x", 0),
221 TEST ("x@4096", 4, 4092, "xxxx", 0),
222 TEST ("x@4096", 4, 4090, "xxxxxx", 0),
223 TEST ("x@4096", 4096, 4096, "x@4096", 0),
224 TEST ("x@2048y@2048", 1, 4094, "xy", 0),
225
226 TEST ("last test", 4, 1, "lasttest", 0)
227};
228
229
230
232// used to exercise
233// erase (iterator)
234static const StringTestCase
235iter_test_cases [] = {
236
237#undef TEST
238#define TEST(str, off, res) { \
239 __LINE__, off, -1, -1, -1, -1, str, sizeof str - 1, \
240 0, 0, res, sizeof res - 1, 0 }
241
242 // +-------------------------------------- controlled sequence
243 // | +------------------ iterator offset
244 // | | +------------- expected result sequence
245 // | | |
246 // V V V
247 TEST ("a", 0, ""),
248
249 TEST ("<U0>", 0, ""),
250 TEST ("<U0>@2", 0, "<U0>"),
251 TEST ("<U0>@2", 1, "<U0>"),
252
253 TEST ("abc", 0, "bc"),
254 TEST ("abc", 1, "ac"),
255 TEST ("abc", 2, "ab"),
256
257 TEST ("t<U0> s", 0, "<U0> s"),
258 TEST ("t<U0> s", 1, "t s"),
259 TEST ("t<U0> s", 2, "t<U0>s"),
260 TEST ("t<U0> s", 3, "t<U0> "),
261
262 TEST ("a<U0>@3b", 4, "a<U0>@3"),
263 TEST ("a<U0>@3b", 2, "a<U0>@2b"),
264 TEST ("a<U0>@3b", 1, "a<U0>@2b"),
265 TEST ("a<U0>@3b", 0, "<U0>@3b"),
266 TEST ("a<U0>b<U0>@2c", 4, "a<U0>b<U0>c"),
267 TEST ("<U0>ab<U0>@2c", 0, "ab<U0>@2c"),
268 TEST ("<U0>ab<U0>@2c", 2, "<U0>a<U0>@2c"),
269 TEST ("ab<U0>c<U0>@2", 5, "ab<U0>c<U0>"),
270
271 TEST ("x@4096y", 4096, "x@4096"),
272 TEST ("x@4096", 4088, "x@4095"),
273 TEST ("ax@4096", 0, "x@4096"),
274 TEST ("x@4096", 9, "x@4095"),
275
276 TEST ("last test", 4, "lasttest")
277};
278
279
280// exercises basic_string::erase, 21.3.5.5
281
282template <class charT, class Traits, class Allocator>
284 const StringFunc &func,
285 const StringTestCase &tcase)
286{
287 typedef std::basic_string <charT, Traits, Allocator> String;
288 typedef typename String::iterator StringIter;
289 typedef typename String::const_iterator ConstStringIter;
290
291 const bool use_iters =
293
294 if (use_iters && tcase.bthrow)
295 return;
296
297 static const std::size_t BUFSIZE = 256;
298
299 static charT wstr_buf [BUFSIZE];
300 std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
301 charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
302
303 static charT wres_buf [BUFSIZE];
304 std::size_t res_len = sizeof wres_buf / sizeof *wres_buf;
305 charT* wres = rw_expand (wres_buf, tcase.res, tcase.nres, &res_len);
306
307 static char nres_buf [BUFSIZE];
308 char* nres = 0;
309 if (use_iters) {
310 std::size_t nreslen = sizeof nres_buf / sizeof *nres_buf;
311 nres = rw_expand (nres_buf, tcase.res, tcase.nres, &nreslen);
312 }
313
314 // construct the string object to be modified
315 // and the (possibly unused) argument string
316 String str (wstr, str_len);
317
318 if (wstr != wstr_buf)
319 delete[] wstr;
320
321 wstr = 0;
322
323 // save the state of the string object before the call
324 // to detect wxception safety violations (changes to
325 // the state of the object after an exception)
326 const StringState str_state (rw_get_string_state (str));
327
328 StringIter res_iter = str.begin ();
329
330 // compute the offset and the extent (the number of elements)
331 // of the first range into the string object being modified
332 const std::size_t size1 = str_len;
333 const std::size_t off1 =
334 std::size_t (tcase.off) < size1 ? std::size_t (tcase.off) : size1;
335 const std::size_t ext1 =
336 off1 + tcase.size < size1 ? tcase.size : size1 - off1;
337
338 // create a pair of iterators into the string object being
339 // modified (used only by the iterator overloads)
340 const StringIter it_first (str.begin () + off1);
341 const StringIter it_last (it_first + ext1);
342
343#ifndef _RWSTD_NO_EXCEPTIONS
344
345 // is some exception expected ?
346 const char* expected = 0;
347 if (1 == tcase.bthrow)
348 expected = exceptions [1];
349
350 const char* caught = 0;
351
352#else // if defined (_RWSTD_NO_EXCEPTIONS)
353
354 if (tcase.bthrow) {
355 if (wres != wres_buf)
356 delete[] wres;
357
358 return;
359 }
360
361#endif // _RWSTD_NO_EXCEPTIONS
362
363 // pointer to the returned reference
364 const String* ret_ptr = 0;
365
366 typedef typename String::size_type size_type;
367
368 try {
369 switch (func.which_) {
370
371 case Erase (void):
372 ret_ptr = &str.erase ();
373 break;
374
375 case Erase (size):
376 ret_ptr = &str.erase (size_type (tcase.off));
377 break;
378
379 case Erase (size_size):
380 ret_ptr = &str.erase (size_type (tcase.off),
381 size_type (tcase.size));
382 break;
383
384 case Erase (iter):
385 res_iter = str.erase (it_first);
386 break;
387
388 case Erase (iter_iter):
389 res_iter = str.erase (it_first, it_last);
390 break;
391
392 default:
393 RW_ASSERT (!"test logic error: unknown erase overload");
394 return;
395 }
396
397 // verify the returned value
398 if (use_iters) {
399 const ConstStringIter begin = str.begin ();
400 const ConstStringIter end = str.end ();
401
402 const bool success = begin <= res_iter && res_iter <= end;
403 rw_assert (success, 0, tcase.line,
404 "line %d. %{$FUNCALL} returned invalid iterator, "
405 "difference with begin is %td",
406 __LINE__, res_iter - begin);
407
408 if (std::size_t (tcase.off) >= res_len) {
409 rw_assert (res_iter == end, 0, tcase.line,
410 "line %d. %{$FUNCALL} != end()", __LINE__);
411 }
412 else {
413 const std::size_t match =
414 rw_match (nres + tcase.off, &(*res_iter), 1);
415
416 rw_assert (1 == match, 0, tcase.line,
417 "line %d. %{$FUNCALL} == %{#c}, got %{#c}",
418 __LINE__, nres[tcase.off], *res_iter);
419 }
420 }
421 else {
422 // verify that the reference returned from the function
423 // refers to the modified string object (i.e., *this
424 // within the function)
425 const std::ptrdiff_t ret_off = ret_ptr - &str;
426
427 // verify the returned value
428 rw_assert (0 == ret_off, 0, tcase.line,
429 "line %d. %{$FUNCALL} returned invalid reference, "
430 "offset is %td", __LINE__, ret_off);
431 }
432
433 // verfiy that strings length are equal
434 rw_assert (res_len == str.size (), 0, tcase.line,
435 "line %d. %{$FUNCALL} expected %{#*s} with length "
436 "%zu, got %{/*.*Gs} with length %zu",
437 __LINE__, int (tcase.nres), tcase.res,
438 res_len, int (sizeof (charT)),
439 int (str.size ()), str.c_str (), str.size ());
440
441 if (res_len == str.size ()) {
442 // if the result length matches the expected length
443 // (and only then), also verify that the modified
444 // string matches the expected result
445 const std::size_t match =
446 rw_match (tcase.res, str.c_str(), str.size ());
447
448 rw_assert (match == res_len, 0, tcase.line,
449 "line %d. %{$FUNCALL} expected %{#*s}, "
450 "got %{/*.*Gs}, difference at offset %zu",
451 __LINE__, int (tcase.nres), tcase.res,
452 int (sizeof (charT)), int (str.size ()),
453 str.c_str (), match);
454 }
455 }
456
457#ifndef _RWSTD_NO_EXCEPTIONS
458
459 catch (const std::out_of_range &ex) {
460 caught = exceptions [1];
461 rw_assert (caught == expected, 0, tcase.line,
462 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
463 "unexpectedly%{;} caught std::%s(%#s)",
464 __LINE__, 0 != expected, expected, caught, ex.what ());
465 }
466 catch (const std::exception &ex) {
467 caught = exceptions [4];
468 rw_assert (0, 0, tcase.line,
469 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
470 "unexpectedly%{;} caught std::%s(%#s)",
471 __LINE__, 0 != expected, expected, caught, ex.what ());
472 }
473 catch (...) {
474 caught = exceptions [0];
475 rw_assert (0, 0, tcase.line,
476 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
477 "unexpectedly%{;} caught %s",
478 __LINE__, 0 != expected, expected, caught);
479 }
480
481#endif // _RWSTD_NO_EXCEPTIONS
482
483 if (caught) {
484 // verify that an exception thrown during allocation
485 // didn't cause a change in the state of the object
487 __LINE__, tcase.line, caught);
488 }
489
490 if (nres != nres_buf)
491 delete[] nres;
492
493 if (wres != wres_buf)
494 delete[] wres;
495}
496
497
500
501int main (int argc, char** argv)
502{
503 static const StringTest
504 tests [] = {
505
506#undef TEST
507#define TEST(sig) { \
508 Erase (sig), sig ## _test_cases, \
509 sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
510 }
511
512 TEST (void),
513 TEST (size),
514 TEST (size_size),
515 TEST (iter),
516 TEST (iter_iter)
517 };
518
519 const std::size_t test_count = sizeof tests / sizeof *tests;
520
521 return rw_run_string_test (argc, argv, __FILE__,
522 "lib.string.erase",
523 test_erase, tests, test_count);
524}
#define charT
Definition 17.names.cpp:456
#define TEST(str, res)
#define Erase(sig)
void test_erase()
std::char_traits< S > Traits
const int end
#define main
int caught
const char * str
Definition exec.cpp:170
_TEST_EXPORT char * rw_expand(char *, const char *, _RWSTD_SIZE_T=_RWSTD_SIZE_MAX, _RWSTD_SIZE_T *=0)
_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
StringState rw_get_string_state(const String &str)
Definition rw_strings.h:752
#define DEFINE_STRING_TEST_DISPATCH(fname)
Definition rw_strings.h:885
_TEST_EXPORT int rw_run_string_test(int, char **, const char *, const char *, StringTestFunc *, const StringTest *, _RWSTD_SIZE_T)
#define RW_ASSERT(expr)
static ArgId arg_type(OverloadId id, int argno)
Definition rw_strings.h:559
int assert_equal(const StringState &, int, int, const char *) const
_RWSTD_SIZE_T str_len
Definition rw_strings.h:597
const char * str
Definition rw_strings.h:596
_RWSTD_SIZE_T nres
Definition rw_strings.h:603
const char * res
Definition rw_strings.h:602