00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef test_insert_H_
00017 #define test_insert_H_
00018
00019 # include "Prefix.h"
00020 # if defined (EH_NEW_HEADERS)
00021 # include <utility>
00022 # include <vector>
00023 # include <cassert>
00024 # include <climits>
00025 # else
00026 # include <vector.h>
00027 # include <assert.h>
00028 # include <limits.h>
00029 # endif
00030 #include "random_number.h"
00031 #include "nc_alloc.h"
00032 #include "ThrowCompare.h"
00033
00034
00035 struct container_tag {};
00036 struct sequence_container_tag {};
00037 struct associative_container_tag {};
00038
00039 struct set_tag {};
00040 struct multiset_tag {};
00041 struct map_tag {};
00042 struct multimap_tag {};
00043
00044 template <class C, class Iter>
00045 EH_STD::size_t CountNewItems( const C&, const Iter& firstNew,
00046 const Iter& lastNew, sequence_container_tag )
00047 {
00048 EH_STD::size_t dist = 0;
00049 #if 0 //def __SUNPRO_CC
00050 EH_DISTANCE( firstNew, lastNew, dist );
00051 #else
00052 EH_DISTANCE( Iter(firstNew), Iter(lastNew), dist );
00053 #endif
00054 return dist;
00055 }
00056
00057 template <class C, class Iter>
00058 EH_STD::size_t CountNewItems( const C& c, const Iter& firstNew,
00059 const Iter& lastNew, multimap_tag )
00060 {
00061 return CountNewItems( c, firstNew, lastNew, sequence_container_tag() );
00062 }
00063
00064 template <class C, class Iter>
00065 EH_STD::size_t CountNewItems( const C& c, const Iter& firstNew,
00066 const Iter& lastNew, multiset_tag )
00067 {
00068 return CountNewItems( c, firstNew, lastNew, sequence_container_tag() );
00069 }
00070
00071
00072 template <class C, class Iter, class KeyOfValue>
00073 #ifdef __BORLANDC__
00074 EH_STD::size_t CountUniqueItems_Aux( const C& original, const Iter& firstNew,
00075 #else
00076 EH_STD::size_t CountUniqueItems_Aux( const C& original, Iter firstNew,
00077 #endif
00078 Iter lastNew, const KeyOfValue& keyOfValue )
00079 {
00080 typedef typename C::key_type key;
00081 typedef typename C::const_iterator const_iter;
00082 typedef EH_STD::vector<key> key_list;
00083 typedef typename key_list::iterator key_iterator;
00084 key_list keys;
00085 EH_STD::size_t dist = 0;
00086 #ifdef __SUNPRO_CC
00087 EH_DISTANCE( firstNew, lastNew, dist );
00088 #else
00089 EH_DISTANCE( Iter(firstNew), Iter(lastNew), dist );
00090 #endif
00091 keys.reserve( dist );
00092 for ( Iter x = firstNew; x != lastNew; ++x )
00093 keys.push_back( keyOfValue(*x) );
00094
00095 EH_STD::sort( keys.begin(), keys.end() );
00096 key_iterator last = EH_STD::unique( keys.begin(), keys.end() );
00097
00098 EH_STD::size_t cnt = 0;
00099 for ( key_iterator tmp = keys.begin(); tmp != last; ++tmp )
00100 {
00101 if ( const_iter(original.find( *tmp )) == const_iter(original.end()) )
00102 ++cnt;
00103 }
00104 return cnt;
00105 }
00106
00107 #if ! defined (__SGI_STL)
00108 EH_BEGIN_NAMESPACE
00109 template <class T>
00110 struct identity
00111 {
00112 const T& operator()( const T& x ) const { return x; }
00113 };
00114 # if ! defined (__KCC)
00115 template <class _Pair>
00116 struct select1st : public unary_function<_Pair, typename _Pair::first_type> {
00117 const typename _Pair::first_type& operator()(const _Pair& __x) const {
00118 return __x.first;
00119 }
00120 };
00121 # endif
00122 EH_END_NAMESPACE
00123 #endif
00124
00125 template <class C, class Iter>
00126 EH_STD::size_t CountUniqueItems( const C& original, const Iter& firstNew,
00127 const Iter& lastNew, set_tag )
00128 {
00129 typedef typename C::value_type value_type;
00130 return CountUniqueItems_Aux( original, firstNew, lastNew,
00131 EH_STD::identity<value_type>() );
00132 }
00133
00134 template <class C, class Iter>
00135 EH_STD::size_t CountUniqueItems( const C& original, const Iter& firstNew,
00136 const Iter& lastNew, map_tag )
00137 {
00138 #ifdef EH_MULTI_CONST_TEMPLATE_ARG_BUG
00139 return CountUniqueItems_Aux( original, firstNew, lastNew,
00140 EH_SELECT1ST_HINT<C::value_type, C::key_type>() );
00141 #else
00142 typedef typename C::value_type value_type;
00143 return CountUniqueItems_Aux( original, firstNew, lastNew,
00144 EH_STD::select1st<value_type>() );
00145 #endif
00146 }
00147
00148 template <class C, class Iter>
00149 EH_STD::size_t CountNewItems( const C& original, const Iter& firstNew,
00150 const Iter& lastNew, map_tag )
00151 {
00152 return CountUniqueItems( original, firstNew, lastNew,
00153 container_category( original ) );
00154 }
00155
00156 template <class C, class Iter>
00157 EH_STD::size_t CountNewItems( const C& original, const Iter& firstNew,
00158 const Iter& lastNew, set_tag )
00159 {
00160 return CountUniqueItems( original, firstNew, lastNew,
00161 container_category( original ) );
00162 }
00163
00164 template <class C, class SrcIter>
00165 inline void VerifyInsertion( const C& original, const C& result,
00166 const SrcIter& firstNew, const SrcIter& lastNew,
00167 EH_STD::size_t, associative_container_tag )
00168 {
00169 typedef typename C::const_iterator DstIter;
00170 DstIter first1 = original.begin();
00171 DstIter first2 = result.begin();
00172
00173 DstIter* from_orig = new DstIter[original.size()];
00174 DstIter* last_from_orig = from_orig;
00175
00176
00177 while ( first2 != result.end() )
00178 {
00179 EH_STD::pair<DstIter, DstIter> p = EH_STD::mismatch( first1, original.end(), first2 );
00180 if ( p.second != result.end() )
00181 {
00182 SrcIter srcItem = EH_STD::find( SrcIter(firstNew), SrcIter(lastNew), *p.second );
00183
00184 if (srcItem == lastNew)
00185 {
00186
00187 DstIter* tmp;
00188 tmp = EH_STD::find( from_orig, last_from_orig, p.first );
00189
00190
00191 if (tmp != last_from_orig)
00192 {
00193 EH_STD::copy(tmp+1, last_from_orig, tmp);
00194 last_from_orig--;
00195 }
00196 else
00197 {
00198
00199 DstIter dstItem;
00200 dstItem = EH_STD::find( first1, original.end(), *p.first );
00201 EH_ASSERT( dstItem != original.end() );
00202 *last_from_orig = dstItem;
00203 last_from_orig++;
00204 ++p.first;
00205 }
00206 }
00207 ++p.second;
00208 }
00209 first1 = p.first;
00210 first2 = p.second;
00211 }
00212
00213 delete [] from_orig;
00214 }
00215
00216
00217 template <class C, class SrcIter>
00218 inline void VerifyInsertion(
00219 const C& original, const C& result, const SrcIter& firstNew,
00220 const SrcIter& lastNew, EH_STD::size_t, set_tag )
00221 {
00222 VerifyInsertion( original, result, firstNew, lastNew,
00223 EH_STD::size_t(0), associative_container_tag() );
00224 }
00225
00226 template <class C, class SrcIter>
00227 inline void VerifyInsertion(const C& original, const C& result,
00228 const SrcIter& firstNew, const SrcIter& lastNew,
00229 EH_STD::size_t, multiset_tag )
00230 {
00231 VerifyInsertion( original, result, firstNew, lastNew,
00232 EH_STD::size_t(0), associative_container_tag() );
00233 }
00234
00235 template <class C, class SrcIter>
00236 inline void VerifyInsertion(
00237 const C& original, const C& result, const SrcIter& firstNew,
00238 const SrcIter& lastNew, EH_STD::size_t, map_tag )
00239 {
00240 VerifyInsertion( original, result, firstNew, lastNew,
00241 EH_STD::size_t(0), associative_container_tag() );
00242 }
00243
00244 template <class C, class SrcIter>
00245 inline void VerifyInsertion(
00246 const C& original, const C& result, const SrcIter& firstNew,
00247 const SrcIter& lastNew, EH_STD::size_t, multimap_tag )
00248 {
00249 VerifyInsertion( original, result, firstNew, lastNew,
00250 EH_STD::size_t(0), associative_container_tag() );
00251 }
00252
00253 template <class C, class SrcIter>
00254 void VerifyInsertion(
00255 # if defined (_MSC_VER) && !defined (__SYMBIAN32__)
00256 const C& original, const C& result, SrcIter firstNew,
00257 SrcIter lastNew, EH_STD::size_t insPos, sequence_container_tag )
00258 # else
00259 const C& original, const C& result, const SrcIter& firstNew,
00260 const SrcIter& lastNew, EH_STD::size_t insPos, sequence_container_tag )
00261 # endif
00262 {
00263 typename C::const_iterator p1 = original.begin();
00264 typename C::const_iterator p2 = result.begin();
00265 SrcIter tmp(firstNew);
00266
00267 for ( EH_STD::size_t n = 0; n < insPos; n++, ++p1, ++p2)
00268 EH_ASSERT( *p1 == *p2 );
00269
00270 for (; tmp != lastNew; ++p2, ++tmp ) {
00271 EH_ASSERT(p2 != result.end());
00272 EH_ASSERT(*p2 == *tmp);
00273 }
00274
00275 for (; p2 != result.end(); ++p1, ++p2 )
00276 EH_ASSERT( *p1 == *p2 );
00277 EH_ASSERT( p1 == original.end() );
00278 }
00279
00280 template <class C, class SrcIter>
00281 inline void VerifyInsertion( const C& original, const C& result,
00282 const SrcIter& firstNew,
00283 const SrcIter& lastNew, EH_STD::size_t insPos )
00284 {
00285 EH_ASSERT( result.size() == original.size() +
00286 CountNewItems( original, firstNew, lastNew,
00287 container_category(original) ) );
00288 VerifyInsertion( original, result, firstNew, lastNew, insPos,
00289 container_category(original) );
00290 }
00291
00292 template <class C, class Value>
00293 void VerifyInsertN( const C& original, const C& result, EH_STD::size_t insCnt,
00294 const Value& val, EH_STD::size_t insPos )
00295 {
00296 typename C::const_iterator p1 = original.begin();
00297 typename C::const_iterator p2 = result.begin();
00298 (void)val;
00299
00300 for ( EH_STD::size_t n = 0; n < insPos; n++ )
00301 EH_ASSERT( *p1++ == *p2++ );
00302
00303 while ( insCnt-- > 0 )
00304 {
00305 EH_ASSERT(p2 != result.end());
00306 EH_ASSERT(*p2 == val );
00307 ++p2;
00308 }
00309
00310 while ( p2 != result.end() ) {
00311 EH_ASSERT( *p1 == *p2 );
00312 ++p1; ++p2;
00313 }
00314 EH_ASSERT( p1 == original.end() );
00315 }
00316
00317 template <class C>
00318 void prepare_insert_n( C&, EH_STD::size_t ) {}
00319
00320
00321
00322 inline void MakeRandomValue(bool& b) { b = bool(random_number(2)); }
00323
00324 template<class T>
00325 inline void MakeRandomValue(T&) {}
00326
00327 template <class C>
00328 struct test_insert_one
00329 {
00330 test_insert_one( const C& orig, int pos =-1 )
00331 : original( orig ), fPos( random_number( orig.size() ))
00332 {
00333 MakeRandomValue( fInsVal );
00334 if ( pos != -1 )
00335 {
00336 fPos = EH_STD::size_t(pos);
00337 if ( pos == 0 )
00338 gTestController.SetCurrentTestName("single insertion at begin()");
00339 else
00340 gTestController.SetCurrentTestName("single insertion at end()");
00341 }
00342 else
00343 gTestController.SetCurrentTestName("single insertion at random position");
00344 }
00345
00346 void operator()( C& c ) const
00347 {
00348 prepare_insert_n( c, (EH_STD::size_t)1 );
00349 typename C::iterator pos = c.begin();
00350 EH_STD::advance( pos, EH_STD::size_t(fPos) );
00351 c.insert( pos, fInsVal );
00352
00353
00354 gTestController.CancelFailureCountdown();
00355
00356 VerifyInsertion( original, c, &fInsVal, 1+&fInsVal, fPos );
00357 }
00358 private:
00359 typename C::value_type fInsVal;
00360 const C& original;
00361 EH_STD::size_t fPos;
00362 };
00363
00364 template <class C>
00365 struct test_insert_n
00366 {
00367 test_insert_n( const C& orig, EH_STD::size_t insCnt, int pos =-1 )
00368 : original( orig ), fPos( random_number( orig.size() )), fInsCnt(insCnt)
00369 {
00370 MakeRandomValue( fInsVal );
00371 if (pos!=-1)
00372 {
00373 fPos=EH_STD::size_t(pos);
00374 if (pos==0)
00375 gTestController.SetCurrentTestName("n-ary insertion at begin()");
00376 else
00377 gTestController.SetCurrentTestName("n-ary insertion at end()");
00378 }
00379 else
00380 gTestController.SetCurrentTestName("n-ary insertion at random position");
00381 }
00382
00383 void operator()( C& c ) const
00384 {
00385 prepare_insert_n( c, fInsCnt );
00386 typename C::iterator pos = c.begin();
00387 EH_STD::advance( pos, fPos );
00388 c.insert( pos, fInsCnt, fInsVal );
00389
00390
00391 gTestController.CancelFailureCountdown();
00392
00393 VerifyInsertN( original, c, fInsCnt, fInsVal, fPos );
00394 }
00395 private:
00396 typename C::value_type fInsVal;
00397 const C& original;
00398 EH_STD::size_t fPos;
00399 EH_STD::size_t fInsCnt;
00400 };
00401
00402 template <class C>
00403 struct test_insert_value
00404 {
00405 test_insert_value( const C& orig )
00406 : original( orig )
00407 {
00408 MakeRandomValue( fInsVal );
00409 gTestController.SetCurrentTestName("insertion or random value");
00410 }
00411
00412 void operator()( C& c ) const
00413 {
00414 c.insert( fInsVal );
00415
00416
00417 gTestController.CancelFailureCountdown();
00418
00419 VerifyInsertion( original, c, &fInsVal, 1+&fInsVal, EH_STD::size_t(0) );
00420 }
00421 private:
00422 typename C::value_type fInsVal;
00423 const C& original;
00424 };
00425
00426 template <class C>
00427 struct test_insert_noresize
00428 {
00429 test_insert_noresize( const C& orig )
00430 : original( orig )
00431 {
00432 MakeRandomValue( fInsVal );
00433 gTestController.SetCurrentTestName("insertion of random value without resize");
00434 }
00435
00436 void operator()( C& c ) const
00437 {
00438 c.insert_noresize( fInsVal );
00439
00440
00441 gTestController.CancelFailureCountdown();
00442
00443 VerifyInsertion( original, c, &fInsVal, 1+&fInsVal, EH_STD::size_t(0) );
00444 }
00445 private:
00446 typename C::value_type fInsVal;
00447 const C& original;
00448 };
00449
00450 template <class C, class Position, class Iter>
00451 void do_insert_range( C& c_inst, Position offset,
00452 Iter first, Iter last, sequence_container_tag )
00453 {
00454 typedef typename C::iterator CIter;
00455 CIter pos = c_inst.begin();
00456 EH_STD::advance( pos, offset );
00457 c_inst.insert( pos, first, last );
00458 }
00459
00460 template <class C, class Position, class Iter>
00461 void do_insert_range( C& c, Position,
00462 Iter first, Iter last, associative_container_tag )
00463 {
00464 c.insert( first, last );
00465 }
00466
00467 template <class C, class Position, class Iter>
00468 void do_insert_range( C& c, Position, Iter first, Iter last, multiset_tag )
00469 {
00470 c.insert( first, last );
00471 }
00472
00473 template <class C, class Position, class Iter>
00474 void do_insert_range( C& c, Position, Iter first, Iter last, multimap_tag )
00475 {
00476 c.insert( first, last );
00477 }
00478
00479 template <class C, class Position, class Iter>
00480 void do_insert_range( C& c, Position, Iter first, Iter last, set_tag )
00481 {
00482 c.insert( first, last );
00483 }
00484
00485 template <class C, class Position, class Iter>
00486 void do_insert_range( C& c, Position, Iter first, Iter last, map_tag )
00487 {
00488 c.insert( first, last );
00489 }
00490
00491
00492
00493
00494
00495
00496 template <class C, class Iter>
00497 struct test_insert_range
00498 {
00499 test_insert_range( const C& orig, Iter first, Iter last, int pos=-1 )
00500 : fFirst( first ),
00501 fLast( last ),
00502 original( orig ),
00503 fPos( random_number( orig.size() ))
00504 {
00505 gTestController.SetCurrentTestName("range insertion");
00506 if ( pos != -1 )
00507 {
00508 fPos = EH_STD::size_t(pos);
00509 if ( pos == 0 )
00510 gTestController.SetCurrentTestName("range insertion at begin()");
00511 else
00512 gTestController.SetCurrentTestName("range insertion at end()");
00513 }
00514 else
00515 gTestController.SetCurrentTestName("range insertion at random position");
00516 }
00517
00518 void operator()( C& c ) const
00519 {
00520
00521 do_insert_range( c, fPos, fFirst, fLast, container_category(c) );
00522
00523
00524 gTestController.CancelFailureCountdown();
00525
00526 VerifyInsertion( original, c, fFirst, fLast, fPos );
00527 }
00528 private:
00529 Iter fFirst, fLast;
00530 const C& original;
00531 size_t fPos;
00532 };
00533
00534 template <class C, class Iter>
00535 test_insert_range<C, Iter> insert_range_tester( const C& orig, const Iter& first, const Iter& last )
00536 {
00537 return test_insert_range<C, Iter>( orig, first, last );
00538 }
00539
00540 template <class C, class Iter>
00541 test_insert_range<C, Iter> insert_range_at_begin_tester( const C& orig, const Iter& first, const Iter& last )
00542 {
00543 return test_insert_range<C, Iter>( orig, first, last , 0);
00544 }
00545
00546 template <class C, class Iter>
00547 test_insert_range<C, Iter> insert_range_at_end_tester( const C& orig, const Iter& first, const Iter& last )
00548 {
00549 return test_insert_range<C, Iter>( orig, first, last , (int)orig.size());
00550 }
00551 #endif // test_insert_H_