Update contrib.
1 /***********************************************************************************
5 * Mark of the Unicorn, Inc.
7 * Permission to use, copy, modify, distribute and sell this software
8 * and its documentation for any purpose is hereby granted without fee,
9 * provided that the above copyright notice appear in all copies and
10 * that both that copyright notice and this permission notice appear
11 * in supporting documentation. Mark of the Unicorn makes no
12 * representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied warranty.
15 ***********************************************************************************/
16 #ifndef test_insert_H_
17 #define test_insert_H_
20 # if defined (EH_NEW_HEADERS)
30 #include "random_number.h"
32 #include "ThrowCompare.h"
34 // A classification system for containers, for verification
35 struct container_tag {};
36 struct sequence_container_tag {};
37 struct associative_container_tag {};
40 struct multiset_tag {};
42 struct multimap_tag {};
44 template <class C, class Iter>
45 size_t CountNewItems( const C&, const Iter& firstNew,
46 const Iter& lastNew, sequence_container_tag )
49 #if 0 //def __SUNPRO_CC
50 EH_DISTANCE( firstNew, lastNew, dist );
52 EH_DISTANCE( Iter(firstNew), Iter(lastNew), dist );
57 template <class C, class Iter>
58 size_t CountNewItems( const C& c, const Iter& firstNew,
59 const Iter& lastNew, multimap_tag )
61 return CountNewItems( c, firstNew, lastNew, sequence_container_tag() );
64 template <class C, class Iter>
65 size_t CountNewItems( const C& c, const Iter& firstNew,
66 const Iter& lastNew, multiset_tag )
68 return CountNewItems( c, firstNew, lastNew, sequence_container_tag() );
72 template <class C, class Iter, class KeyOfValue>
74 size_t CountUniqueItems_Aux( const C& original, const Iter& firstNew,
76 size_t CountUniqueItems_Aux( const C& original, Iter firstNew,
78 Iter lastNew, const KeyOfValue& keyOfValue )
80 typedef typename C::key_type key;
81 typedef typename C::const_iterator const_iter;
82 typedef EH_STD::vector<key> key_list;
83 typedef typename key_list::iterator key_iterator;
87 EH_DISTANCE( firstNew, lastNew, dist );
89 EH_DISTANCE( Iter(firstNew), Iter(lastNew), dist );
92 for ( Iter x = firstNew; x != lastNew; ++x )
93 keys.push_back( keyOfValue(*x) );
95 EH_STD::sort( keys.begin(), keys.end() );
96 key_iterator last = EH_STD::unique( keys.begin(), keys.end() );
99 for ( key_iterator tmp = keys.begin(); tmp != last; ++tmp )
101 if ( const_iter(original.find( *tmp )) == const_iter(original.end()) )
107 #if ! defined (__SGI_STL)
112 const T& operator()( const T& x ) const { return x; }
114 # if ! defined (__KCC)
115 template <class _Pair>
116 struct select1st : public unary_function<_Pair, typename _Pair::first_type> {
117 const typename _Pair::first_type& operator()(const _Pair& __x) const {
125 template <class C, class Iter>
126 size_t CountUniqueItems( const C& original, const Iter& firstNew,
127 const Iter& lastNew, set_tag )
129 typedef typename C::value_type value_type;
130 return CountUniqueItems_Aux( original, firstNew, lastNew,
131 EH_STD::identity<value_type>() );
134 template <class C, class Iter>
135 size_t CountUniqueItems( const C& original, const Iter& firstNew,
136 const Iter& lastNew, map_tag )
138 #ifdef EH_MULTI_CONST_TEMPLATE_ARG_BUG
139 return CountUniqueItems_Aux( original, firstNew, lastNew,
140 EH_SELECT1ST_HINT<C::value_type, C::key_type>() );
142 typedef typename C::value_type value_type;
143 return CountUniqueItems_Aux( original, firstNew, lastNew,
144 EH_STD::select1st<value_type>() );
148 template <class C, class Iter>
149 size_t CountNewItems( const C& original, const Iter& firstNew,
150 const Iter& lastNew, map_tag )
152 return CountUniqueItems( original, firstNew, lastNew,
153 container_category( original ) );
156 template <class C, class Iter>
157 size_t CountNewItems( const C& original, const Iter& firstNew,
158 const Iter& lastNew, set_tag )
160 return CountUniqueItems( original, firstNew, lastNew,
161 container_category( original ) );
164 template <class C, class SrcIter>
165 inline void VerifyInsertion( const C& original, const C& result,
166 const SrcIter& firstNew, const SrcIter& lastNew,
167 size_t, associative_container_tag )
169 typedef typename C::const_iterator DstIter;
170 DstIter first1 = original.begin();
171 DstIter first2 = result.begin();
173 DstIter* from_orig = new DstIter[original.size()];
174 DstIter* last_from_orig = from_orig;
176 // fbp : for hashed containers, the following is needed :
177 while ( first2 != result.end() )
179 EH_STD::pair<DstIter, DstIter> p = EH_STD::mismatch( first1, original.end(), first2 );
180 if ( p.second != result.end() )
182 SrcIter srcItem = EH_STD::find( SrcIter(firstNew), SrcIter(lastNew), *p.second );
184 if (srcItem == lastNew)
186 // not found in input range, probably re-ordered from the orig
188 tmp = EH_STD::find( from_orig, last_from_orig, p.first );
190 // if already here, exclude
191 if (tmp != last_from_orig)
193 EH_STD::copy(tmp+1, last_from_orig, tmp);
198 // register re-ordered element
200 dstItem = EH_STD::find( first1, original.end(), *p.first );
201 EH_ASSERT( dstItem != original.end() );
202 *last_from_orig = dstItem;
217 template <class C, class SrcIter>
218 inline void VerifyInsertion(
219 const C& original, const C& result, const SrcIter& firstNew,
220 const SrcIter& lastNew, size_t, set_tag )
222 VerifyInsertion( original, result, firstNew, lastNew,
223 size_t(0), associative_container_tag() );
226 template <class C, class SrcIter>
227 inline void VerifyInsertion(const C& original, const C& result,
228 const SrcIter& firstNew, const SrcIter& lastNew,
229 size_t, multiset_tag )
231 VerifyInsertion( original, result, firstNew, lastNew,
232 size_t(0), associative_container_tag() );
235 template <class C, class SrcIter>
236 inline void VerifyInsertion(
237 const C& original, const C& result, const SrcIter& firstNew,
238 const SrcIter& lastNew, size_t, map_tag )
240 VerifyInsertion( original, result, firstNew, lastNew,
241 size_t(0), associative_container_tag() );
244 template <class C, class SrcIter>
245 inline void VerifyInsertion(
246 const C& original, const C& result, const SrcIter& firstNew,
247 const SrcIter& lastNew, size_t, multimap_tag )
249 VerifyInsertion( original, result, firstNew, lastNew,
250 size_t(0), associative_container_tag() );
253 template <class C, class SrcIter>
254 void VerifyInsertion(
256 const C& original, const C& result, SrcIter firstNew,
257 SrcIter lastNew, size_t insPos, sequence_container_tag )
259 const C& original, const C& result, const SrcIter& firstNew,
260 const SrcIter& lastNew, size_t insPos, sequence_container_tag )
263 typename C::const_iterator p1 = original.begin();
264 typename C::const_iterator p2 = result.begin();
265 SrcIter tmp(firstNew);
267 for ( size_t n = 0; n < insPos; n++, ++p1, ++p2)
268 EH_ASSERT( *p1 == *p2 );
270 for (; tmp != lastNew; ++p2, ++tmp ) {
271 EH_ASSERT(p2 != result.end());
272 EH_ASSERT(*p2 == *tmp);
275 for (; p2 != result.end(); ++p1, ++p2 )
276 EH_ASSERT( *p1 == *p2 );
277 EH_ASSERT( p1 == original.end() );
280 template <class C, class SrcIter>
281 inline void VerifyInsertion( const C& original, const C& result,
282 const SrcIter& firstNew,
283 const SrcIter& lastNew, size_t insPos )
285 EH_ASSERT( result.size() == original.size() +
286 CountNewItems( original, firstNew, lastNew,
287 container_category(original) ) );
288 VerifyInsertion( original, result, firstNew, lastNew, insPos,
289 container_category(original) );
292 template <class C, class Value>
293 void VerifyInsertN( const C& original, const C& result, size_t insCnt,
294 const Value& val, size_t insPos )
296 typename C::const_iterator p1 = original.begin();
297 typename C::const_iterator p2 = result.begin();
298 (void)val; //*TY 02/06/2000 - to suppress unused variable warning under nondebug build
300 for ( size_t n = 0; n < insPos; n++ )
301 EH_ASSERT( *p1++ == *p2++ );
303 while ( insCnt-- > 0 )
305 EH_ASSERT(p2 != result.end());
306 EH_ASSERT(*p2 == val );
310 while ( p2 != result.end() ) {
311 EH_ASSERT( *p1 == *p2 );
314 EH_ASSERT( p1 == original.end() );
318 void prepare_insert_n( C&, size_t ) {}
320 // Metrowerks 1.8 compiler requires that specializations appear first (!!)
321 // or it won't call them. Fixed in 1.9, though.
322 inline void MakeRandomValue(bool& b) { b = bool(random_number(2) != 0); }
325 inline void MakeRandomValue(T&) {}
328 struct test_insert_one
330 test_insert_one( const C& orig, int pos =-1 )
331 : original( orig ), fPos( random_number( orig.size() ))
333 MakeRandomValue( fInsVal );
338 gTestController.SetCurrentTestName("single insertion at begin()");
340 gTestController.SetCurrentTestName("single insertion at end()");
343 gTestController.SetCurrentTestName("single insertion at random position");
346 void operator()( C& c ) const
348 prepare_insert_n( c, (size_t)1 );
349 typename C::iterator pos = c.begin();
350 EH_STD::advance( pos, size_t(fPos) );
351 c.insert( pos, fInsVal );
353 // Prevent simulated failures during verification
354 gTestController.CancelFailureCountdown();
355 // Success. Check results.
356 VerifyInsertion( original, c, &fInsVal, 1+&fInsVal, fPos );
359 typename C::value_type fInsVal;
367 test_insert_n( const C& orig, size_t insCnt, int pos =-1 )
368 : original( orig ), fPos( random_number( orig.size() )), fInsCnt(insCnt)
370 MakeRandomValue( fInsVal );
375 gTestController.SetCurrentTestName("n-ary insertion at begin()");
377 gTestController.SetCurrentTestName("n-ary insertion at end()");
380 gTestController.SetCurrentTestName("n-ary insertion at random position");
383 void operator()( C& c ) const
385 prepare_insert_n( c, fInsCnt );
386 typename C::iterator pos = c.begin();
387 EH_STD::advance( pos, fPos );
388 c.insert( pos, fInsCnt, fInsVal );
390 // Prevent simulated failures during verification
391 gTestController.CancelFailureCountdown();
392 // Success. Check results.
393 VerifyInsertN( original, c, fInsCnt, fInsVal, fPos );
396 typename C::value_type fInsVal;
403 struct test_insert_value
405 test_insert_value( const C& orig )
408 MakeRandomValue( fInsVal );
409 gTestController.SetCurrentTestName("insertion of random value");
412 void operator()( C& c ) const
416 // Prevent simulated failures during verification
417 gTestController.CancelFailureCountdown();
418 // Success. Check results.
419 VerifyInsertion( original, c, &fInsVal, 1+&fInsVal, size_t(0) );
422 typename C::value_type fInsVal;
427 struct test_insert_noresize
429 test_insert_noresize( const C& orig )
432 MakeRandomValue( fInsVal );
433 gTestController.SetCurrentTestName("insertion of random value without resize");
436 void operator()( C& c ) const
438 c.insert_noresize( fInsVal );
440 // Prevent simulated failures during verification
441 gTestController.CancelFailureCountdown();
442 // Success. Check results.
443 VerifyInsertion( original, c, &fInsVal, 1+&fInsVal, size_t(0) );
446 typename C::value_type fInsVal;
450 template <class C, class Position, class Iter>
451 void do_insert_range( C& c_inst, Position offset,
452 Iter first, Iter last, sequence_container_tag )
454 typedef typename C::iterator CIter;
455 CIter pos = c_inst.begin();
456 EH_STD::advance( pos, offset );
457 c_inst.insert( pos, first, last );
460 template <class C, class Position, class Iter>
461 void do_insert_range( C& c, Position,
462 Iter first, Iter last, associative_container_tag )
464 c.insert( first, last );
467 template <class C, class Position, class Iter>
468 void do_insert_range( C& c, Position, Iter first, Iter last, multiset_tag )
470 c.insert( first, last );
473 template <class C, class Position, class Iter>
474 void do_insert_range( C& c, Position, Iter first, Iter last, multimap_tag )
476 c.insert( first, last );
479 template <class C, class Position, class Iter>
480 void do_insert_range( C& c, Position, Iter first, Iter last, set_tag )
482 c.insert( first, last );
485 template <class C, class Position, class Iter>
486 void do_insert_range( C& c, Position, Iter first, Iter last, map_tag )
488 c.insert( first, last );
492 template <class C, class Iter>
493 void prepare_insert_range( C&, size_t, Iter, Iter) {}
496 template <class C, class Iter>
497 struct test_insert_range
499 test_insert_range( const C& orig, Iter first, Iter last, int pos=-1 )
503 fPos( random_number( orig.size() ))
505 gTestController.SetCurrentTestName("range insertion");
510 gTestController.SetCurrentTestName("range insertion at begin()");
512 gTestController.SetCurrentTestName("range insertion at end()");
515 gTestController.SetCurrentTestName("range insertion at random position");
518 void operator()( C& c ) const
520 // prepare_insert_range( c, fPos, fFirst, fLast );
521 do_insert_range( c, fPos, fFirst, fLast, container_category(c) );
523 // Prevent simulated failures during verification
524 gTestController.CancelFailureCountdown();
525 // Success. Check results.
526 VerifyInsertion( original, c, fFirst, fLast, fPos );
534 template <class C, class Iter>
535 test_insert_range<C, Iter> insert_range_tester( const C& orig, const Iter& first, const Iter& last )
537 return test_insert_range<C, Iter>( orig, first, last );
540 template <class C, class Iter>
541 test_insert_range<C, Iter> insert_range_at_begin_tester( const C& orig, const Iter& first, const Iter& last )
543 return test_insert_range<C, Iter>( orig, first, last , 0);
546 template <class C, class Iter>
547 test_insert_range<C, Iter> insert_range_at_end_tester( const C& orig, const Iter& first, const Iter& last )
549 return test_insert_range<C, Iter>( orig, first, last , (int)orig.size());
552 #endif // test_insert_H_