test_insert.h

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 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     // 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, 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;              //*TY 02/06/2000 - to suppress unused variable warning under nondebug build
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 // 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)); }
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         // 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     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         // 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     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         // Prevent simulated failures during verification
00417         gTestController.CancelFailureCountdown();
00418         // Success. Check results.
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         // Prevent simulated failures during verification
00441         gTestController.CancelFailureCountdown();
00442         // Success. Check results.
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 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 = 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 //        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 #endif // test_insert_H_

Generated on Mon Jun 5 10:20:48 2006 for Intelligence.kdevelop by  doxygen 1.4.6