os/ossrv/genericopenlibs/cppstdlib/stl/test/eh/test_insert.h
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /***********************************************************************************
     2   test_insert.h
     3 
     4  * Copyright (c) 1997
     5  * Mark of the Unicorn, Inc.
     6  *
     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.
    14 
    15 ***********************************************************************************/
    16 #ifndef test_insert_H_
    17 #define test_insert_H_
    18 
    19 # include "Prefix.h"
    20 # if defined (EH_NEW_HEADERS)
    21 #  include <utility>
    22 #  include <vector>
    23 #  include <cassert>
    24 #  include <climits>
    25 # else
    26 #  include <vector.h>
    27 #  include <assert.h>
    28 #  include <limits.h>
    29 # endif
    30 #include "random_number.h"
    31 #include "nc_alloc.h"
    32 #include "ThrowCompare.h"
    33 
    34 // A classification system for containers, for verification
    35 struct container_tag {};
    36 struct sequence_container_tag  {};
    37 struct associative_container_tag  {};
    38 
    39 struct set_tag  {};
    40 struct multiset_tag  {};
    41 struct map_tag {};
    42 struct multimap_tag {};
    43 
    44 template <class C, class Iter>
    45 size_t CountNewItems( const C&, const Iter& firstNew,
    46                       const Iter& lastNew, sequence_container_tag )
    47 {
    48     size_t dist = 0;
    49 #if 0 //def __SUNPRO_CC
    50     EH_DISTANCE( firstNew, lastNew, dist );
    51 #else
    52     EH_DISTANCE( Iter(firstNew), Iter(lastNew), dist );
    53 #endif
    54     return dist;
    55 }
    56 
    57 template <class C, class Iter>
    58 size_t CountNewItems( const C& c, const Iter& firstNew,
    59                       const Iter& lastNew, multimap_tag )
    60 {
    61     return CountNewItems( c, firstNew, lastNew, sequence_container_tag() );
    62 }
    63 
    64 template <class C, class Iter>
    65 size_t CountNewItems( const C& c, const Iter& firstNew,
    66                       const Iter& lastNew, multiset_tag )
    67 {
    68     return CountNewItems( c, firstNew, lastNew, sequence_container_tag() );
    69 }
    70 
    71 
    72 template <class C, class Iter, class KeyOfValue>
    73 #ifdef __BORLANDC__
    74 size_t CountUniqueItems_Aux( const C& original, const Iter& firstNew,
    75 #else
    76 size_t CountUniqueItems_Aux( const C& original, Iter firstNew,
    77 #endif
    78                              Iter lastNew, const KeyOfValue& keyOfValue )
    79 {
    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;
    84   key_list keys;
    85   size_t dist = 0;
    86 #ifdef __SUNPRO_CC
    87   EH_DISTANCE( firstNew, lastNew, dist );
    88 #else
    89   EH_DISTANCE( Iter(firstNew), Iter(lastNew), dist );
    90 #endif
    91   keys.reserve( dist );
    92   for ( Iter x = firstNew; x != lastNew; ++x )
    93     keys.push_back( keyOfValue(*x) );
    94 
    95   EH_STD::sort( keys.begin(), keys.end() );
    96   key_iterator last = EH_STD::unique( keys.begin(), keys.end() );
    97 
    98     size_t cnt = 0;
    99     for ( key_iterator tmp = keys.begin(); tmp != last; ++tmp )
   100     {
   101         if ( const_iter(original.find( *tmp )) == const_iter(original.end()) )
   102             ++cnt;
   103     }
   104     return cnt;
   105 }
   106 
   107 #if ! defined (__SGI_STL)
   108 EH_BEGIN_NAMESPACE
   109 template <class T>
   110 struct identity
   111 {
   112   const T& operator()( const T& x ) const { return x; }
   113 };
   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 {
   118     return __x.first;
   119   }
   120 };
   121 # endif
   122 EH_END_NAMESPACE
   123 #endif
   124 
   125 template <class C, class Iter>
   126 size_t CountUniqueItems( const C& original, const Iter& firstNew,
   127                          const Iter& lastNew, set_tag )
   128 {
   129     typedef typename C::value_type value_type;
   130     return CountUniqueItems_Aux( original, firstNew, lastNew,
   131                                  EH_STD::identity<value_type>() );
   132 }
   133 
   134 template <class C, class Iter>
   135 size_t CountUniqueItems( const C& original, const Iter& firstNew,
   136                          const Iter& lastNew, map_tag )
   137 {
   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>() );
   141 #else
   142     typedef typename C::value_type value_type;
   143     return CountUniqueItems_Aux( original, firstNew, lastNew,
   144                                  EH_STD::select1st<value_type>() );
   145 #endif
   146 }
   147 
   148 template <class C, class Iter>
   149 size_t CountNewItems( const C& original, const Iter& firstNew,
   150                       const Iter& lastNew, map_tag )
   151 {
   152     return CountUniqueItems( original, firstNew, lastNew,
   153                              container_category( original ) );
   154 }
   155 
   156 template <class C, class Iter>
   157 size_t CountNewItems( const C& original, const Iter& firstNew,
   158                       const Iter& lastNew, set_tag )
   159 {
   160     return CountUniqueItems( original, firstNew, lastNew,
   161                              container_category( original ) );
   162 }
   163 
   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 )
   168 {
   169     typedef typename C::const_iterator DstIter;
   170     DstIter first1 = original.begin();
   171     DstIter first2 = result.begin();
   172 
   173     DstIter* from_orig = new DstIter[original.size()];
   174     DstIter* last_from_orig = from_orig;
   175 
   176     // fbp : for hashed containers, the following is needed :
   177     while ( first2 != result.end() )
   178     {
   179         EH_STD::pair<DstIter, DstIter> p = EH_STD::mismatch( first1, original.end(), first2 );
   180         if ( p.second != result.end() )
   181         {
   182             SrcIter srcItem = EH_STD::find( SrcIter(firstNew), SrcIter(lastNew), *p.second );
   183 
   184             if (srcItem == lastNew)
   185             {
   186                 // not found in input range, probably re-ordered from the orig
   187                 DstIter* tmp;
   188                 tmp = EH_STD::find( from_orig, last_from_orig, p.first );
   189 
   190                 // if already here, exclude
   191                 if (tmp != last_from_orig)
   192                 {
   193                     EH_STD::copy(tmp+1, last_from_orig, tmp);
   194                     last_from_orig--;
   195                 }
   196                 else
   197                 {
   198                     // register re-ordered element
   199                     DstIter dstItem;
   200                     dstItem = EH_STD::find( first1, original.end(), *p.first );
   201                     EH_ASSERT( dstItem != original.end() );
   202                     *last_from_orig = dstItem;
   203                     last_from_orig++;
   204                     ++p.first;
   205                 }
   206             }
   207             ++p.second;
   208         }
   209         first1 = p.first;
   210         first2 = p.second;
   211     }
   212 
   213     delete [] from_orig;
   214 }
   215 
   216 // VC++
   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 )
   221 {
   222     VerifyInsertion( original, result, firstNew, lastNew,
   223                      size_t(0), associative_container_tag() );
   224 }
   225 
   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 )
   230 {
   231     VerifyInsertion( original, result, firstNew, lastNew,
   232                      size_t(0), associative_container_tag() );
   233 }
   234 
   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 )
   239 {
   240     VerifyInsertion( original, result, firstNew, lastNew,
   241                      size_t(0), associative_container_tag() );
   242 }
   243 
   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 )
   248 {
   249     VerifyInsertion( original, result, firstNew, lastNew,
   250                      size_t(0), associative_container_tag() );
   251 }
   252 
   253 template <class C, class SrcIter>
   254 void VerifyInsertion(
   255 # ifdef _MSC_VER
   256     const C& original, const C& result, SrcIter firstNew,
   257     SrcIter lastNew, size_t insPos, sequence_container_tag )
   258 # else
   259     const C& original, const C& result, const SrcIter& firstNew,
   260     const SrcIter& lastNew, size_t insPos, sequence_container_tag )
   261 # endif
   262 {
   263     typename C::const_iterator p1 = original.begin();
   264     typename C::const_iterator p2 = result.begin();
   265     SrcIter tmp(firstNew);
   266 
   267     for ( size_t n = 0; n < insPos; n++, ++p1, ++p2)
   268         EH_ASSERT( *p1 == *p2 );
   269 
   270     for (; tmp != lastNew; ++p2, ++tmp ) {
   271         EH_ASSERT(p2 != result.end());
   272         EH_ASSERT(*p2 == *tmp);
   273     }
   274 
   275     for (;  p2 != result.end(); ++p1, ++p2 )
   276         EH_ASSERT( *p1 == *p2 );
   277     EH_ASSERT( p1 == original.end() );
   278 }
   279 
   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 )
   284 {
   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) );
   290 }
   291 
   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 )
   295 {
   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
   299 
   300     for ( size_t n = 0; n < insPos; n++ )
   301         EH_ASSERT( *p1++ == *p2++ );
   302 
   303     while ( insCnt-- > 0 )
   304     {
   305         EH_ASSERT(p2 != result.end());
   306         EH_ASSERT(*p2 == val );
   307         ++p2;
   308     }
   309 
   310     while ( p2 != result.end() ) {
   311         EH_ASSERT( *p1 == *p2 );
   312         ++p1; ++p2;
   313     }
   314     EH_ASSERT( p1 == original.end() );
   315 }
   316 
   317 template <class C>
   318 void prepare_insert_n( C&, size_t ) {}
   319 
   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); }
   323 
   324 template<class T>
   325 inline void MakeRandomValue(T&) {}
   326 
   327 template <class C>
   328 struct test_insert_one
   329 {
   330     test_insert_one( const C& orig, int pos =-1 )
   331         : original( orig ), fPos( random_number( orig.size() ))
   332     {
   333         MakeRandomValue( fInsVal );
   334         if ( pos != -1 )
   335         {
   336             fPos = size_t(pos);
   337             if ( pos == 0 )
   338                 gTestController.SetCurrentTestName("single insertion at begin()");
   339             else
   340                 gTestController.SetCurrentTestName("single insertion at end()");
   341         }
   342         else
   343             gTestController.SetCurrentTestName("single insertion at random position");
   344     }
   345 
   346     void operator()( C& c ) const
   347     {
   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 );
   352 
   353         // Prevent simulated failures during verification
   354         gTestController.CancelFailureCountdown();
   355         // Success. Check results.
   356         VerifyInsertion( original, c, &fInsVal, 1+&fInsVal, fPos );
   357     }
   358 private:
   359     typename C::value_type fInsVal;
   360     const C& original;
   361     size_t fPos;
   362 };
   363 
   364 template <class C>
   365 struct test_insert_n
   366 {
   367     test_insert_n( const C& orig, size_t insCnt, int pos =-1 )
   368         : original( orig ), fPos( random_number( orig.size() )), fInsCnt(insCnt)
   369     {
   370         MakeRandomValue( fInsVal );
   371         if (pos!=-1)
   372         {
   373             fPos=size_t(pos);
   374             if (pos==0)
   375                 gTestController.SetCurrentTestName("n-ary insertion at begin()");
   376             else
   377                 gTestController.SetCurrentTestName("n-ary insertion at end()");
   378         }
   379         else
   380             gTestController.SetCurrentTestName("n-ary insertion at random position");
   381     }
   382 
   383     void operator()( C& c ) const
   384     {
   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 );
   389 
   390         // Prevent simulated failures during verification
   391         gTestController.CancelFailureCountdown();
   392         // Success. Check results.
   393         VerifyInsertN( original, c, fInsCnt, fInsVal, fPos );
   394     }
   395 private:
   396     typename C::value_type fInsVal;
   397     const C& original;
   398     size_t fPos;
   399     size_t fInsCnt;
   400 };
   401 
   402 template <class C>
   403 struct test_insert_value
   404 {
   405     test_insert_value( const C& orig )
   406         : original( orig )
   407     {
   408         MakeRandomValue( fInsVal );
   409         gTestController.SetCurrentTestName("insertion of random value");
   410     }
   411 
   412     void operator()( C& c ) const
   413     {
   414         c.insert( fInsVal );
   415 
   416         // Prevent simulated failures during verification
   417         gTestController.CancelFailureCountdown();
   418         // Success. Check results.
   419         VerifyInsertion( original, c, &fInsVal, 1+&fInsVal, size_t(0) );
   420     }
   421 private:
   422     typename C::value_type fInsVal;
   423     const C& original;
   424 };
   425 
   426 template <class C>
   427 struct test_insert_noresize
   428 {
   429     test_insert_noresize( const C& orig )
   430         : original( orig )
   431     {
   432         MakeRandomValue( fInsVal );
   433         gTestController.SetCurrentTestName("insertion of random value without resize");
   434     }
   435 
   436     void operator()( C& c ) const
   437     {
   438         c.insert_noresize( fInsVal );
   439 
   440         // Prevent simulated failures during verification
   441         gTestController.CancelFailureCountdown();
   442         // Success. Check results.
   443         VerifyInsertion( original, c, &fInsVal, 1+&fInsVal, size_t(0) );
   444     }
   445 private:
   446     typename C::value_type fInsVal;
   447     const C& original;
   448 };
   449 
   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 )
   453 {
   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 );
   458 }
   459 
   460 template <class C, class Position, class Iter>
   461 void do_insert_range( C& c, Position,
   462                       Iter first, Iter last, associative_container_tag )
   463 {
   464     c.insert( first, last );
   465 }
   466 
   467 template <class C, class Position, class Iter>
   468 void do_insert_range( C& c, Position, Iter first, Iter last, multiset_tag )
   469 {
   470     c.insert( first, last );
   471 }
   472 
   473 template <class C, class Position, class Iter>
   474 void do_insert_range( C& c, Position, Iter first, Iter last, multimap_tag )
   475 {
   476     c.insert( first, last );
   477 }
   478 
   479 template <class C, class Position, class Iter>
   480 void do_insert_range( C& c, Position, Iter first, Iter last, set_tag )
   481 {
   482     c.insert( first, last );
   483 }
   484 
   485 template <class C, class Position, class Iter>
   486 void do_insert_range( C& c, Position, Iter first, Iter last, map_tag )
   487 {
   488     c.insert( first, last );
   489 }
   490 
   491 /*
   492 template <class C, class Iter>
   493 void prepare_insert_range( C&, size_t, Iter, Iter) {}
   494 */
   495 
   496 template <class C, class Iter>
   497 struct test_insert_range
   498 {
   499     test_insert_range( const C& orig, Iter first, Iter last, int pos=-1 )
   500         : fFirst( first ),
   501           fLast( last ),
   502           original( orig ),
   503           fPos( random_number( orig.size() ))
   504     {
   505         gTestController.SetCurrentTestName("range insertion");
   506         if ( pos != -1 )
   507         {
   508             fPos = size_t(pos);
   509             if ( pos == 0 )
   510                 gTestController.SetCurrentTestName("range insertion at begin()");
   511             else
   512                 gTestController.SetCurrentTestName("range insertion at end()");
   513         }
   514         else
   515             gTestController.SetCurrentTestName("range insertion at random position");
   516     }
   517 
   518     void operator()( C& c ) const
   519     {
   520 //        prepare_insert_range( c, fPos, fFirst, fLast );
   521         do_insert_range( c, fPos, fFirst, fLast, container_category(c) );
   522 
   523         // Prevent simulated failures during verification
   524         gTestController.CancelFailureCountdown();
   525         // Success. Check results.
   526         VerifyInsertion( original, c, fFirst, fLast, fPos );
   527     }
   528 private:
   529     Iter fFirst, fLast;
   530     const C& original;
   531     size_t fPos;
   532 };
   533 
   534 template <class C, class Iter>
   535 test_insert_range<C, Iter> insert_range_tester( const C& orig, const Iter& first, const Iter& last )
   536 {
   537     return test_insert_range<C, Iter>( orig, first, last );
   538 }
   539 
   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 )
   542 {
   543   return test_insert_range<C, Iter>( orig, first, last , 0);
   544 }
   545 
   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 )
   548 {
   549   return test_insert_range<C, Iter>( orig, first, last , (int)orig.size());
   550 }
   551 
   552 #endif // test_insert_H_