Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentest_insert.h
Go to the documentation of this file.
00001 /*********************************************************************************** 00002 test_insert.h 00003 00004 * Copyright (c) 1997 00005 * Mark of the Unicorn, Inc. 00006 * 00007 * Permission to use, copy, modify, distribute and sell this software 00008 * and its documentation for any purpose is hereby granted without fee, 00009 * provided that the above copyright notice appear in all copies and 00010 * that both that copyright notice and this permission notice appear 00011 * in supporting documentation. Mark of the Unicorn makes no 00012 * representations about the suitability of this software for any 00013 * purpose. It is provided "as is" without express or implied warranty. 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 // A classification system for containers, for verification 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 size_t CountNewItems( const C&, const Iter& firstNew, 00046 const Iter& lastNew, sequence_container_tag ) 00047 { 00048 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 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 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 size_t CountUniqueItems_Aux( const C& original, const Iter& firstNew, 00075 #else 00076 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 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 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 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 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 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 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 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 // fbp : for hashed containers, the following is needed : 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 // not found in input range, probably re-ordered from the orig 00187 DstIter* tmp; 00188 tmp = EH_STD::find( from_orig, last_from_orig, p.first ); 00189 00190 // if already here, exclude 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 // register re-ordered element 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 // VC++ 00217 template <class C, class SrcIter> 00218 inline void VerifyInsertion( 00219 const C& original, const C& result, const SrcIter& firstNew, 00220 const SrcIter& lastNew, size_t, set_tag ) 00221 { 00222 VerifyInsertion( original, result, firstNew, lastNew, 00223 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 size_t, multiset_tag ) 00230 { 00231 VerifyInsertion( original, result, firstNew, lastNew, 00232 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, size_t, map_tag ) 00239 { 00240 VerifyInsertion( original, result, firstNew, lastNew, 00241 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, size_t, multimap_tag ) 00248 { 00249 VerifyInsertion( original, result, firstNew, lastNew, 00250 size_t(0), associative_container_tag() ); 00251 } 00252 00253 template <class C, class SrcIter> 00254 void VerifyInsertion( 00255 # ifdef _MSC_VER 00256 const C& original, const C& result, SrcIter firstNew, 00257 SrcIter lastNew, size_t insPos, sequence_container_tag ) 00258 # else 00259 const C& original, const C& result, const SrcIter& firstNew, 00260 const SrcIter& lastNew, 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 ( 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, 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, size_t insCnt, 00294 const Value& val, size_t insPos ) 00295 { 00296 typename C::const_iterator p1 = original.begin(); 00297 typename C::const_iterator p2 = result.begin(); 00298 (void)val; //*TY 02/06/2000 - to suppress unused variable warning under nondebug build 00299 00300 for ( 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&, size_t ) {} 00319 00320 // Metrowerks 1.8 compiler requires that specializations appear first (!!) 00321 // or it won't call them. Fixed in 1.9, though. 00322 inline void MakeRandomValue(bool& b) { b = bool(random_number(2) != 0); } 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 = 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, (size_t)1 ); 00349 typename C::iterator pos = c.begin(); 00350 EH_STD::advance( pos, size_t(fPos) ); 00351 c.insert( pos, fInsVal ); 00352 00353 // Prevent simulated failures during verification 00354 gTestController.CancelFailureCountdown(); 00355 // Success. Check results. 00356 VerifyInsertion( original, c, &fInsVal, 1+&fInsVal, fPos ); 00357 } 00358 private: 00359 typename C::value_type fInsVal; 00360 const C& original; 00361 size_t fPos; 00362 }; 00363 00364 template <class C> 00365 struct test_insert_n 00366 { 00367 test_insert_n( const C& orig, 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=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 // Prevent simulated failures during verification 00391 gTestController.CancelFailureCountdown(); 00392 // Success. Check results. 00393 VerifyInsertN( original, c, fInsCnt, fInsVal, fPos ); 00394 } 00395 private: 00396 typename C::value_type fInsVal; 00397 const C& original; 00398 size_t fPos; 00399 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 of random value"); 00410 } 00411 00412 void operator()( C& c ) const 00413 { 00414 c.insert( fInsVal ); 00415 00416 // Prevent simulated failures during verification 00417 gTestController.CancelFailureCountdown(); 00418 // Success. Check results. 00419 VerifyInsertion( original, c, &fInsVal, 1+&fInsVal, 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 // Prevent simulated failures during verification 00441 gTestController.CancelFailureCountdown(); 00442 // Success. Check results. 00443 VerifyInsertion( original, c, &fInsVal, 1+&fInsVal, 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 template <class C, class Iter> 00493 void prepare_insert_range( C&, size_t, Iter, Iter) {} 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 = 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 // prepare_insert_range( c, fPos, fFirst, fLast ); 00521 do_insert_range( c, fPos, fFirst, fLast, container_category(c) ); 00522 00523 // Prevent simulated failures during verification 00524 gTestController.CancelFailureCountdown(); 00525 // Success. Check results. 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 00552 #endif // test_insert_H_ Generated on Sun May 27 2012 04:35:15 for ReactOS by
1.7.6.1
|