|
1 /************************************************************************ |
|
2 * |
|
3 * alg_test.cpp - definitions of class X members |
|
4 * |
|
5 * $Id: alg_test.cpp 349035 2005-11-25 23:17:58Z sebor $ |
|
6 * |
|
7 ************************************************************************ |
|
8 * |
|
9 * Copyright (c) 1994-2005 Quovadx, Inc., acting through its Rogue Wave |
|
10 * Software division. Licensed under the Apache License, Version 2.0 (the |
|
11 * "License"); you may not use this file except in compliance with the |
|
12 * License. You may obtain a copy of the License at |
|
13 * http://www.apache.org/licenses/LICENSE-2.0. Unless required by |
|
14 * applicable law or agreed to in writing, software distributed under |
|
15 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
|
16 * CONDITIONS OF ANY KIND, either express or implied. See the License |
|
17 * for the specific language governing permissions and limitations under |
|
18 * the License. |
|
19 * |
|
20 **************************************************************************/ |
|
21 |
|
22 // expand _TEST_EXPORT macros |
|
23 #define _RWSTD_TEST_SRC |
|
24 |
|
25 #include <stddef.h> // for size_t |
|
26 #include <stdlib.h> // for rand() |
|
27 #include <string.h> // for strlen() |
|
28 #include <ctype.h> // for toupper() |
|
29 |
|
30 #include <alg_test.h> |
|
31 |
|
32 |
|
33 #ifdef _RWSTDDEBUG |
|
34 // use own assertion mechanism for better diagnostic output |
|
35 # undef assert |
|
36 # define assert(expr) _RWSTD_ASSERT(expr) |
|
37 #else |
|
38 # include <assert.h> // for assert() |
|
39 #endif // _RWSTDDEBUG |
|
40 |
|
41 |
|
42 /* static */ size_t X::count_; |
|
43 /* static */ int X::id_gen_; // generates unique non-zero ids |
|
44 /* static */ int (*X::_gen_)() ; // extern "C++" int (*)() |
|
45 |
|
46 /* static */ size_t X::n_total_def_ctor_; |
|
47 /* static */ size_t X::n_total_copy_ctor_; |
|
48 /* static */ size_t X::n_total_dtor_; |
|
49 /* static */ size_t X::_n_total_op_assign_ ; |
|
50 /* static */ size_t X::_n_total_op_eq_; |
|
51 /* static */ size_t X::n_total_op_lt_; |
|
52 |
|
53 // default values of pointers |
|
54 /* static */ size_t* X::def_ctor_throw_ptr_ = &X::def_ctor_throw_count_; |
|
55 /* static */ size_t* X::copy_ctor_throw_ptr_ = &X::copy_ctor_throw_count_; |
|
56 /* static */ size_t* X::dtor_throw_ptr_ = &X::dtor_throw_count_; |
|
57 /* static */ size_t* X::op_assign_throw_ptr_ = &X::op_assign_throw_count_; |
|
58 /* static */ size_t* X::op_eq_throw_ptr_ = &X::op_eq_throw_count_; |
|
59 /* static */ size_t* X::op_lt_throw_ptr_ = &X::op_lt_throw_count_; |
|
60 |
|
61 // exception throwing initially disabled |
|
62 /* static */ size_t X::def_ctor_throw_count_ = size_t (-1); |
|
63 /* static */ size_t X::copy_ctor_throw_count_ = size_t (-1); |
|
64 /* static */ size_t X::dtor_throw_count_ = size_t (-1); |
|
65 /* static */ size_t X::op_assign_throw_count_ = size_t (-1); |
|
66 /* static */ size_t X::op_eq_throw_count_ = size_t (-1); |
|
67 /* static */ size_t X::op_lt_throw_count_ = size_t (-1); |
|
68 |
|
69 |
|
70 X::X () |
|
71 : id_ (++id_gen_), origin_ (id_), src_id_ (id_), val_ (0), |
|
72 n_copy_ctor_ (0), n_op_assign_ (0), n_op_eq_ (0), n_op_lt_ (0) |
|
73 { |
|
74 // increment the total number of invocations of the default ctor |
|
75 // (do so even if the function throws an exception below) |
|
76 ++n_total_def_ctor_; |
|
77 |
|
78 #ifndef _RWSTD_NO_EXCEPTIONS |
|
79 |
|
80 if (def_ctor_throw_ptr_ && n_total_def_ctor_ == *def_ctor_throw_ptr_) { |
|
81 DefCtor ex; |
|
82 ex.id_ = id_; |
|
83 throw ex; |
|
84 } |
|
85 |
|
86 #endif // _RWSTD_NO_EXCEPTIONS |
|
87 |
|
88 // initialize the object's value |
|
89 if (_gen_) |
|
90 val_ = _gen_ (); |
|
91 |
|
92 // increment the number of successfully constructed objects |
|
93 ++count_; |
|
94 } |
|
95 |
|
96 |
|
97 X::X (const X &rhs) |
|
98 : id_ (++id_gen_), origin_ (rhs.origin_), src_id_ (rhs.id_), |
|
99 val_ (rhs.val_), |
|
100 n_copy_ctor_ (0), n_op_assign_ (0), n_op_eq_ (0), n_op_lt_ (0) |
|
101 { |
|
102 // verify id validity |
|
103 assert (rhs.id_ && rhs.id_ < id_gen_); |
|
104 |
|
105 // increment the number of times `rhs' has been copied |
|
106 // (do so even if the function throws an exception below) |
|
107 ++_RWSTD_CONST_CAST (X*, &rhs)->n_copy_ctor_; |
|
108 |
|
109 // increment the total number of invocations of the copy ctor |
|
110 // (do so even if the function throws an exception below) |
|
111 ++n_total_copy_ctor_; |
|
112 |
|
113 #ifndef _RWSTD_NO_EXCEPTIONS |
|
114 |
|
115 // throw an exception if the number of calls |
|
116 // to the copy ctor reaches the given value |
|
117 if (copy_ctor_throw_ptr_ && n_total_copy_ctor_ == *copy_ctor_throw_ptr_) { |
|
118 CopyCtor ex; |
|
119 ex.id_ = id_; |
|
120 throw ex; |
|
121 } |
|
122 |
|
123 #endif // _RWSTD_NO_EXCEPTIONS |
|
124 |
|
125 // increment the number of successfully constructed objects |
|
126 ++count_; |
|
127 } |
|
128 |
|
129 |
|
130 X::~X () |
|
131 { |
|
132 // verify id validity |
|
133 assert (id_ && id_ <= id_gen_); |
|
134 |
|
135 // increment the total number of invocations of the dtor |
|
136 // (do so even if the function throws an exception below) |
|
137 ++n_total_dtor_; |
|
138 |
|
139 #ifndef _RWSTD_NO_EXCEPTIONS |
|
140 |
|
141 // throw an exception if the number of calls |
|
142 // to the class dtor reaches the given value |
|
143 if (dtor_throw_ptr_ && n_total_dtor_ == *dtor_throw_ptr_) { |
|
144 Dtor ex; |
|
145 ex.id_ = id_; |
|
146 throw ex; |
|
147 } |
|
148 |
|
149 #endif // _RWSTD_NO_EXCEPTIONS |
|
150 |
|
151 // decrement the number of objects in existence |
|
152 --count_; |
|
153 |
|
154 // invalidate id |
|
155 _RWSTD_CONST_CAST (int&, this->id_) = 0; |
|
156 } |
|
157 |
|
158 |
|
159 X& |
|
160 X::operator= (const X &rhs) |
|
161 { |
|
162 // verify id validity and uniqueness |
|
163 assert (id_ && id_ <= id_gen_); |
|
164 assert (rhs.id_ && rhs.id_ <= id_gen_); |
|
165 assert (this == &rhs || id_ != rhs.id_); |
|
166 |
|
167 // increment the total number of invocations of the operator |
|
168 // (do so even if the function throws an exception below) |
|
169 ++n_total_op_assign_; |
|
170 |
|
171 // increment the number of times the object has been assigned to |
|
172 // (do so even if the function throws an exception below) |
|
173 ++n_op_assign_; |
|
174 |
|
175 #ifndef _RWSTD_NO_EXCEPTIONS |
|
176 |
|
177 // throw an exception if the number of calls to |
|
178 // the assignment operator reaches the given value |
|
179 |
|
180 if (op_assign_throw_ptr_ && n_total_op_assign_ == *op_assign_throw_ptr_) { |
|
181 OpAssign ex; |
|
182 ex.id_ = id_; |
|
183 throw ex; |
|
184 } |
|
185 |
|
186 #endif // _RWSTD_NO_EXCEPTIONS |
|
187 |
|
188 // overwrite value and source id only when the operation |
|
189 // is successful (i.e., only when it doesn't throw) |
|
190 |
|
191 origin_ = rhs.origin_; |
|
192 src_id_ = rhs.id_; |
|
193 val_ = rhs.val_; |
|
194 |
|
195 return *this; |
|
196 } |
|
197 |
|
198 |
|
199 bool |
|
200 X::operator== (const X &rhs) const |
|
201 { |
|
202 // verify id validity and uniqueness |
|
203 assert (id_ && id_ <= id_gen_); |
|
204 assert (rhs.id_ && rhs.id_ <= id_gen_); |
|
205 assert (this == &rhs || id_ != rhs.id_); |
|
206 |
|
207 // increment the number of times each distinct object |
|
208 // has been used as the argument to operator== |
|
209 // (do so even if the function throws an exception below) |
|
210 ++_RWSTD_CONST_CAST (X*, this)->n_op_eq_; |
|
211 |
|
212 if (this != &rhs) |
|
213 ++_RWSTD_CONST_CAST (X*, &rhs)->n_op_eq_; |
|
214 |
|
215 // increment the total number of invocations of the operator |
|
216 // (do so even if the function throws an exception below) |
|
217 ++n_total_op_eq_; |
|
218 |
|
219 #ifndef _RWSTD_NO_EXCEPTIONS |
|
220 |
|
221 // throw an exception if the number of calls |
|
222 // to operator== reaches the given value |
|
223 |
|
224 if (op_eq_throw_ptr_ && n_total_op_eq_ == *op_eq_throw_ptr_) { |
|
225 OpEq ex; |
|
226 ex.id_ = id_; |
|
227 throw ex; |
|
228 } |
|
229 |
|
230 #endif // _RWSTD_NO_EXCEPTIONS |
|
231 |
|
232 return val_ == rhs.val_; |
|
233 } |
|
234 |
|
235 |
|
236 bool |
|
237 X::operator< (const X &rhs) const |
|
238 { |
|
239 // verify id validity and uniqueness |
|
240 assert (id_ && id_ <= id_gen_); |
|
241 assert (rhs.id_ && rhs.id_ <= id_gen_); |
|
242 assert (this == &rhs || id_ != rhs.id_); |
|
243 |
|
244 // increment the number of times each distinct object |
|
245 // has been used as the argument to operator< |
|
246 // (do so even if the function throws an exception below) |
|
247 ++_RWSTD_CONST_CAST (X*, this)->n_op_lt_; |
|
248 |
|
249 if (this != &rhs) |
|
250 ++_RWSTD_CONST_CAST (X*, &rhs)->n_op_lt_; |
|
251 |
|
252 // increment the total number of invocations of the operator |
|
253 // (do so even if the function throws an exception below) |
|
254 ++n_total_op_lt_; |
|
255 |
|
256 #ifndef _RWSTD_NO_EXCEPTIONS |
|
257 |
|
258 // throw an exception if the number of calls |
|
259 // to operator== reaches the given value |
|
260 |
|
261 if (op_lt_throw_ptr_ && n_total_op_lt_ == *op_lt_throw_ptr_) { |
|
262 OpLt ex; |
|
263 ex.id_ = id_; |
|
264 throw ex; |
|
265 } |
|
266 |
|
267 #endif // _RWSTD_NO_EXCEPTIONS |
|
268 |
|
269 return val_ < rhs.val_; |
|
270 } |
|
271 |
|
272 |
|
273 bool X:: |
|
274 is_count (size_t n_copy_ctor, |
|
275 size_t n_op_assign, |
|
276 size_t n_op_eq, |
|
277 size_t n_op_lt) const |
|
278 { |
|
279 // verify id validity |
|
280 assert (id_ && id_ <= id_gen_); |
|
281 |
|
282 return (size_t (-1) == n_copy_ctor || n_copy_ctor_ == n_copy_ctor) |
|
283 && (size_t (-1) == n_op_assign || n_op_assign_ == n_op_assign) |
|
284 && (size_t (-1) == n_op_eq || n_op_eq_ == n_op_eq) |
|
285 && (size_t (-1) == n_op_lt || n_op_lt_ == n_op_lt); |
|
286 } |
|
287 |
|
288 |
|
289 /* static */ bool X:: |
|
290 is_total (size_t cnt, |
|
291 size_t n_def_ctor, |
|
292 size_t n_copy_ctor, |
|
293 size_t n_op_assign, |
|
294 size_t n_op_eq, |
|
295 size_t n_op_lt) |
|
296 { |
|
297 return (size_t (-1) == cnt || count_ == cnt) |
|
298 && (size_t (-1) == n_def_ctor || n_total_def_ctor_ == n_def_ctor) |
|
299 && (size_t (-1) == n_copy_ctor || n_total_copy_ctor_ == n_copy_ctor) |
|
300 && (size_t (-1) == n_op_assign || n_total_op_assign_ == n_op_assign) |
|
301 && (size_t (-1) == n_op_eq || n_total_op_eq_ == n_op_eq) |
|
302 && (size_t (-1) == n_op_lt || n_total_op_lt_ == n_op_lt); |
|
303 } |
|
304 |
|
305 |
|
306 /* static void |
|
307 X::reset_totals () |
|
308 { |
|
309 n_total_def_ctor_ = |
|
310 n_total_copy_ctor_ = |
|
311 n_total_dtor_ = |
|
312 n_total_op_assign_ = |
|
313 n_total_op_eq_ = |
|
314 n_total_op_lt_ = 0; |
|
315 }*/ |
|
316 |
|
317 |
|
318 typedef unsigned char UChar; |
|
319 |
|
320 // used to initialize an array of objects of type X |
|
321 static const char *xinit_begin; |
|
322 |
|
323 static int xinit () |
|
324 { |
|
325 if (xinit_begin) |
|
326 return UChar (*xinit_begin++); |
|
327 |
|
328 return 0; |
|
329 } |
|
330 |
|
331 |
|
332 /* static */ X* |
|
333 X::from_char (const char *str, size_t len /* = -1 */) |
|
334 { |
|
335 // handle null pointers |
|
336 if (!str) |
|
337 return 0; |
|
338 |
|
339 // compute the length of the character array if not specified |
|
340 if (size_t (-1) == len) |
|
341 len = strlen (str); |
|
342 |
|
343 // set the global pointer to point to the beginning of `str' |
|
344 xinit_begin = str; |
|
345 |
|
346 // save the previous pointer to the initializer function |
|
347 int (*gen_save)() = X::_gen_; |
|
348 |
|
349 // set the generating function |
|
350 X::_gen_ = xinit; |
|
351 |
|
352 X *array = 0; |
|
353 |
|
354 _TRY { |
|
355 // allocate and construct `len' elements, initializing |
|
356 // each from the character array `str' (via `xinit') |
|
357 array = new X [len]; |
|
358 } |
|
359 _CATCH (...) { |
|
360 |
|
361 // restore the original initializer function and rethrow |
|
362 X::_gen_ = gen_save; |
|
363 |
|
364 _RETHROW; |
|
365 } |
|
366 |
|
367 // restore the original initializer function |
|
368 X::_gen_ = gen_save; |
|
369 |
|
370 return array; |
|
371 } |
|
372 |
|
373 _TEST_EXPORT |
|
374 /* static */ int |
|
375 X::compare (const X *x, const char *str, size_t len /* = -1 */) |
|
376 { |
|
377 if (!str) |
|
378 return x == 0; |
|
379 |
|
380 if (size_t (-1) == len) |
|
381 len = strlen (str); |
|
382 |
|
383 for (size_t i = 0; i != len; ++i) { |
|
384 |
|
385 const int val = UChar (str [i]); |
|
386 |
|
387 if (val != x [i].val_) |
|
388 return x [i].val_ - val; |
|
389 } |
|
390 |
|
391 return 0; |
|
392 } |
|
393 |
|
394 _TEST_EXPORT |
|
395 /* static */ int |
|
396 X::compare (const char *str, const X *x, size_t len /* = -1 */) |
|
397 { |
|
398 return -X::compare (x, str, len); |
|
399 } |
|
400 |
|
401 _TEST_EXPORT |
|
402 /* static */ int |
|
403 X::compare (const X *x, const X *y, size_t count) |
|
404 { |
|
405 for (size_t i = 0; i != count; ++i) { |
|
406 if (x [i].val_ != y [i].val_) |
|
407 return x [i].val_ - y [i].val_; |
|
408 } |
|
409 |
|
410 return 0; |
|
411 } |
|
412 |
|
413 |
|
414 /* static */ size_t UnaryPredicate::n_total_op_fcall_; |
|
415 |
|
416 _TEST_EXPORT |
|
417 UnaryPredicate:: |
|
418 UnaryPredicate () |
|
419 { |
|
420 // no-op |
|
421 } |
|
422 |
|
423 _TEST_EXPORT |
|
424 UnaryPredicate:: |
|
425 UnaryPredicate (const UnaryPredicate&) |
|
426 { |
|
427 // no-op |
|
428 } |
|
429 |
|
430 _TEST_EXPORT |
|
431 UnaryPredicate& UnaryPredicate:: |
|
432 operator= (const UnaryPredicate&) |
|
433 { |
|
434 return *this; |
|
435 } |
|
436 |
|
437 _TEST_EXPORT |
|
438 /* virtual */ UnaryPredicate::~UnaryPredicate () |
|
439 { |
|
440 // no-op |
|
441 } |
|
442 |
|
443 _TEST_EXPORT |
|
444 /* virtual */ bool UnaryPredicate:: |
|
445 operator()(const X&) const |
|
446 { |
|
447 ++n_total_op_fcall_; |
|
448 |
|
449 return true; |
|
450 } |
|
451 |
|
452 |
|
453 /* static */ size_t BinaryPredicate::n_total_op_fcall_; |
|
454 |
|
455 _TEST_EXPORT |
|
456 BinaryPredicate:: |
|
457 BinaryPredicate (bool ignore_case) |
|
458 : ignore_case_ (ignore_case) |
|
459 { |
|
460 // no-op |
|
461 } |
|
462 |
|
463 |
|
464 BinaryPredicate:: |
|
465 BinaryPredicate (const BinaryPredicate &rhs) |
|
466 : ignore_case_ (rhs.ignore_case_) |
|
467 { |
|
468 // no-op |
|
469 } |
|
470 |
|
471 |
|
472 _TEST_EXPORT BinaryPredicate& BinaryPredicate:: |
|
473 operator= (const BinaryPredicate &rhs) |
|
474 { |
|
475 ignore_case_ = rhs.ignore_case_; |
|
476 return *this; |
|
477 } |
|
478 |
|
479 |
|
480 _TEST_EXPORT /* virtual */ BinaryPredicate::~BinaryPredicate () |
|
481 { |
|
482 // no-op |
|
483 } |
|
484 |
|
485 |
|
486 _TEST_EXPORT /* virtual */ bool BinaryPredicate:: |
|
487 operator()(const X &lhs, const X &rhs) const |
|
488 { |
|
489 ++n_total_op_fcall_; |
|
490 |
|
491 if (lhs == rhs) |
|
492 return true; |
|
493 |
|
494 if (ignore_case_) { |
|
495 |
|
496 const int lval = lhs.val_; |
|
497 const int rval = rhs.val_; |
|
498 |
|
499 if ( lval < 0 || lval > int (_RWSTD_UCHAR_MAX) |
|
500 || rval < 0 || rval > int (_RWSTD_UCHAR_MAX)) |
|
501 return false; |
|
502 |
|
503 const int lup = toupper (lval); |
|
504 const int rup = toupper (rval); |
|
505 |
|
506 return _RWSTD_EOF != lup && lup == rup; |
|
507 } |
|
508 |
|
509 return false; |
|
510 } |
|
511 |
|
512 |
|
513 // generate a unique sequential number starting from 0 |
|
514 _TEST_EXPORT int gen_seq () |
|
515 { |
|
516 static int val; |
|
517 |
|
518 return ++val; |
|
519 } |
|
520 |
|
521 |
|
522 // generate numbers in the sequence 0, 0, 1, 1, 2, 2, 3, 3, etc... |
|
523 _TEST_EXPORT int gen_seq_2lists () |
|
524 { |
|
525 static int vals [2]; |
|
526 |
|
527 return vals [0] += ++vals [1] % 2; |
|
528 } |
|
529 |
|
530 |
|
531 // generate a sequence of subsequences (i.e., 0, 1, 2, 3, 4, 0, 1, 2, etc...) |
|
532 _TEST_EXPORT int gen_subseq () |
|
533 { |
|
534 static int val; |
|
535 |
|
536 return val++ % 5; |
|
537 } |
|
538 |
|
539 |
|
540 // wrapper around a (possibly) extern "C" int rand() |
|
541 // extern "C++" |
|
542 _TEST_EXPORT int gen_rnd () |
|
543 { |
|
544 return rand (); |
|
545 } |
|
546 //defination of fun |
|
547 _TEST_EXPORT _RWSTD_SIZE_T* Getn_total_op_assign_() |
|
548 { |
|
549 return &X::_n_total_op_assign_; |
|
550 } |
|
551 |
|
552 _TEST_EXPORT _RWSTD_SIZE_T* Getn_total_op_eq_() |
|
553 { |
|
554 return &X::_n_total_op_eq_; |
|
555 } |
|
556 _TEST_EXPORT fptr_gen_* Get_gen_() |
|
557 { |
|
558 return &(X::_gen_) ; |
|
559 } |