Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
21.string.copy.cpp
Go to the documentation of this file.
1
29#include <string> // for string
30#include <cstddef> // size_t
31#include <stdexcept> // for out_of_range
32
33#include <rw_strings.h> // for StringMembers
34#include <rw_driver.h> // for rw_assert()
35#include <rw_allocator.h> // for UserAlloc
36#include <rw_char.h> // for rw_expand()
37
38
40// for convenience and brevity
41#define Copy(which) StringIds::copy_ ## which
42
43static const char* const exceptions[] = {
44 "unknown exception", "out_of_range", "length_error",
45 "bad_alloc", "exception"
46};
47
48
50// exercises:
51// copy (value_type*, size_type)
52static const StringTestCase
53ptr_size_test_cases [] = {
54
55#undef TEST
56#define TEST(str, size, res) { \
57 __LINE__, -1, size, -1, -1, -1, \
58 str, sizeof str - 1, 0, 0, \
59 res, sizeof res - 1, 0 \
60 }
61
62 // +--------------------------------------- controlled sequence
63 // | +--------------- copy() n argument
64 // | | +----------- expected result sequence
65 // | | |
66 // V V V
67 TEST ("ab", 2, "ab"),
68
69 TEST ("", 0, ""),
70 TEST ("", 10, ""),
71
72 TEST ("<U0>", 1, "<U0>"),
73 TEST ("<U0>@2", 2, "<U0>@2"),
74
75 TEST ("abc", 0, ""),
76 TEST ("abc", 1, "a"),
77 TEST ("abc", 2, "ab"),
78 TEST ("abc", 3, "abc"),
79 TEST ("abc", 5, "abc"),
80
81 TEST ("a<U0>b<U0>@2c", 10, "a<U0>b<U0>@2c"),
82 TEST ("<U0>ab<U0>@3c<U0>", 1, "<U0>"),
83 TEST ("<U0>ab<U0>@3c<U0>", 8, "<U0>ab<U0>@3c<U0>"),
84 TEST ("<U0>ab<U0>@3c<U0>", 5, "<U0>ab<U0>@2"),
85 TEST ("<U0>@2ab<U0>@2c<U0>", 6, "<U0>@2ab<U0>@2"),
86
87 TEST ("x@4096", 4096, "x@4096"),
88
89 TEST ("last", 4, "last")
90};
91
92
94// exercises:
95// copy (value_type*, size_type, size_type)
96static const StringTestCase
97ptr_size_size_test_cases [] = {
98
99#undef TEST
100#define TEST(str, size, off, res, bthrow) { \
101 __LINE__, off, size, -1, -1, -1, \
102 str, sizeof str - 1, 0, 0, \
103 res, sizeof res - 1, bthrow \
104 }
105
106 // +------------------------------------------ controlled sequence
107 // | +------------------ copy() n argument
108 // | | +-------------- copy() pos argument
109 // | | | +----------- expected result sequence
110 // | | | | +--- exception info:
111 // | | | | | 0 - no exception
112 // | | | | | 1 - out_of_range
113 // | | | | |
114 // | | | | +---------+
115 // V V V V V
116 TEST ("ab", 2, 0, "ab", 0),
117
118 TEST ("", 0, 0, "", 0),
119 TEST ("", 10, 0, "", 0),
120
121 TEST ("<U0>", 1, 0, "<U0>", 0),
122 TEST ("<U0>@2", 1, 1, "<U0>", 0),
123 TEST ("<U0>@2", 2, 0, "<U0>@2", 0),
124
125 TEST ("abc", 1, 0, "a", 0),
126 TEST ("abc", 1, 1, "b", 0),
127 TEST ("abc", 1, 2, "c", 0),
128
129 TEST ("abc", 0, 0, "", 0),
130 TEST ("abc", 2, 0, "ab", 0),
131 TEST ("abc", 2, 1, "bc", 0),
132 TEST ("abc", 3, 0, "abc", 0),
133 TEST ("abc", 10, 1, "bc", 0),
134 TEST ("abc", 3, 2, "c", 0),
135
136 TEST ("a<U0>b<U0>@2c", 10, 1, "<U0>b<U0>@2c", 0),
137 TEST ("a<U0>b<U0>@2c", 10, 0, "a<U0>b<U0>@2c", 0),
138 TEST ("a<U0>b<U0>@2c", 1, 1, "<U0>", 0),
139
140 TEST ("<U0>ab<U0>@3c<U0>", 10, 1, "ab<U0>@3c<U0>", 0),
141 TEST ("<U0>ab<U0>@3c<U0>", 5, 0, "<U0>ab<U0>@2", 0),
142 TEST ("<U0>ab<U0>@3c<U0>", 3, 3, "<U0>@3", 0),
143
144 TEST ("<U0>@2ab<U0>@2c<U0>", 6, 0, "<U0>@2ab<U0>@2", 0),
145 TEST ("<U0>@2ab<U0>@2c<U0>", 4, 1, "<U0>ab<U0>", 0),
146
147 TEST ("x@4096", 4096, 0, "x@4096", 0),
148 TEST ("x@4096", 2, 1, "xx", 0),
149 TEST ("x@4096", 4096, 4095, "x", 0),
150
151 TEST ("<U0>", 0, 2, "", 1),
152 TEST ("a", 0, 10, "", 1),
153 TEST ("x@4096", 0, 4106, "", 1),
154
155 TEST ("last", 4, 0, "last", 0)
156};
157
158
160template <class charT, class Traits, class Allocator>
162 const StringFunc &func,
163 const StringTestCase &tcase)
164{
165 typedef std::basic_string <charT, Traits, Allocator> String;
166
167 static const std::size_t BUFSIZE = 256;
168
169 static charT wstr_buf [BUFSIZE];
170 std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
171 charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
172
173 static charT wres_buf [BUFSIZE];
174 std::size_t res_len = sizeof wres_buf / sizeof *wres_buf;
175 charT* wres = rw_expand (wres_buf, tcase.res, tcase.nres, &res_len);
176
177 // construct the string object
178 const String str (wstr, str_len);
179
180 if (wstr != wstr_buf)
181 delete[] wstr;
182
183 wstr = 0;
184
185 const std::size_t min_len =
186 str_len < std::size_t (tcase.size) ? str_len : tcase.size;
187
188 std::size_t res = 0;
189
190 // create destination array and initialize it with garbage
191 charT* const s_res = new charT [min_len + 2];
192
193 const char cgb [2] = "#";
194 const charT wcgb = make_char (cgb [0], (charT*)0);
195 Traits::assign (s_res, min_len + 1, wcgb);
196 s_res [min_len + 1] = charT ();
197
198 // save the state of the string object before the call
199 // to detect wxception safety violations (changes to
200 // the state of the object after an exception)
201 const StringState str_state (rw_get_string_state (str));
202
203#ifndef _RWSTD_NO_EXCEPTIONS
204
205 // is some exception expected?
206 const char* const expected = tcase.bthrow ? exceptions [1] : 0;
207 const char* caught = 0;
208
209#else // if defined (_RWSTD_NO_EXCEPTIONS)
210
211 if (tcase.bthrow) {
212 if (wres != wres_buf)
213 delete[] wres;
214
215 return;
216 }
217
218#endif // _RWSTD_NO_EXCEPTIONS
219
220 try {
221 switch (func.which_) {
222 case Copy (ptr_size): {
223 res = str.copy (s_res, tcase.size);
224 break;
225 }
226
227 case Copy (ptr_size_size): {
228 res = str.copy (s_res, tcase.size, tcase.off);
229 break;
230 }
231 default:
232 RW_ASSERT (!"logic error: unknown copy overload");
233 return;
234 }
235
236 // verify the returned value
237 rw_assert (res == res_len, 0, tcase.line,
238 "line %d. %{$FUNCALL} == %zu, got %zu",
239 __LINE__, res_len, res);
240
241 if (res == res_len)
242 {
243 const std::size_t match = rw_match (tcase.res, s_res, res_len);
244 bool success = match == res_len;
245
246 rw_assert (success, 0, tcase.line,
247 "line %d. %{$FUNCALL} expected %{#*s}, "
248 "got %{/*.*Gs}, differ at pos %zu",
249 __LINE__, int (tcase.nres), tcase.res,
250 int (sizeof (charT)), int (res), s_res, match);
251
252 success = 1 == rw_match (cgb, s_res + min_len, 1);
253 rw_assert (success, 0, tcase.line,
254 "line %d. %{$FUNCALL} detected writing past the end of "
255 "the provided buffer", __LINE__);
256 }
257 }
258
259#ifndef _RWSTD_NO_EXCEPTIONS
260
261 catch (const std::out_of_range &ex) {
262 caught = exceptions [1];
263 rw_assert (caught == expected, 0, tcase.line,
264 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
265 "unexpectedly%{;} caught std::%s(%#s)",
266 __LINE__, 0 != expected, expected, caught, ex.what ());
267 }
268 catch (const std::exception &ex) {
269 caught = exceptions [4];
270 rw_assert (0, 0, tcase.line,
271 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
272 "unexpectedly%{;} caught std::%s(%#s)",
273 __LINE__, 0 != expected, expected, caught, ex.what ());
274 }
275 catch (...) {
276 caught = exceptions [0];
277 rw_assert (0, 0, tcase.line,
278 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
279 "unexpectedly%{;} caught %s",
280 __LINE__, 0 != expected, expected, caught);
281 }
282
283 if (caught) {
284 // verify that an exception thrown during allocation
285 // didn't cause a change in the state of the object
287 __LINE__, tcase.line, caught);
288 }
289 else if (-1 != tcase.bthrow) {
290 rw_assert (caught == expected, 0, tcase.line,
291 "line %d. %{$FUNCALL} %{?}expected %s, caught %s"
292 "%{:}unexpectedly caught %s%{;}",
293 __LINE__, 0 != expected, expected, caught, caught);
294 }
295
296#endif // _RWSTD_NO_EXCEPTIONS
297
298 if (wres != wres_buf)
299 delete[] wres;
300
301 delete[] s_res;
302}
303
304
307
308int main (int argc, char** argv)
309{
310 static const StringTest
311 tests [] = {
312
313#undef TEST
314#define TEST(which) { \
315 Copy (which), which ## _test_cases, \
316 sizeof which ## _test_cases / sizeof *which ## _test_cases \
317 }
318
319 TEST (ptr_size),
320 TEST (ptr_size_size)
321 };
322
323 const std::size_t test_count = sizeof tests / sizeof *tests;
324
325 return rw_run_string_test (argc, argv, __FILE__,
326 "lib.string.copy",
327 test_copy, tests, test_count);
328}
#define res
Definition 17.names.cpp:531
#define charT
Definition 17.names.cpp:456
#define TEST(str, size, res)
#define Copy(which)
void test_copy(std::size_t N, const InputIterator &input_iter, const OutputIterator &output_iter, const T *)
Definition 25.copy.cpp:63
std::char_traits< S > Traits
#define main
int caught
const char * str
Definition exec.cpp:170
UserChar make_char(char c, UserChar *)
Definition rw_char.h:74
_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)
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