Sierra Toolkit Version of the Day
CSet.cpp
00001 /*------------------------------------------------------------------------*/
00002 /*                 Copyright 2010 Sandia Corporation.                     */
00003 /*  Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive   */
00004 /*  license for use of this work by or on behalf of the U.S. Government.  */
00005 /*  Export of this program may require a license from the                 */
00006 /*  United States Government.                                             */
00007 /*------------------------------------------------------------------------*/
00008 
00009 #include <algorithm>
00010 #include <stdexcept>
00011 #include <iostream>
00012 #include <sstream>
00013 #include <assert.h>
00014 
00015 #include <stk_util/util/CSet.hpp>
00016 
00017 namespace stk {
00018 
00019 namespace {
00020 
00021 typedef void (* DeleteFunction )( void * );
00022 
00023 typedef std::pair< const std::type_info * , DeleteFunction > Manager ;
00024 
00025 // Comparison for sorted vector
00026 
00027 struct less_cset {
00028   bool operator()( const Manager        & lhs ,
00029                    const std::type_info & rhs ) const ;
00030   bool operator()( const std::type_info & lhs ,
00031                    const Manager        & rhs ) const ;
00032 };
00033 
00034 // On some systems, namely AIX, std::type_info::before(...)
00035 // has a bug where it returns true instead of false for equality.
00036 // Thus we pay a small price on all systems to specifically
00037 // test for and eliminate equality.
00038 
00039 bool less_cset::operator()( const Manager        & lhs ,
00040                             const std::type_info & rhs ) const
00041 { return lhs.first->before( rhs ) && * lhs.first != rhs ; }
00042 
00043 bool less_cset::operator()( const std::type_info & lhs ,
00044                             const Manager        & rhs ) const
00045 { return lhs.before( *rhs.first ) && lhs != *rhs.first ; }
00046 
00047 
00048 std::vector< Manager >::const_iterator
00049 lower_bound( const std::vector< Manager > & v , const std::type_info & t )
00050 {
00051   std::vector< Manager >::const_iterator i = v.begin();
00052   std::vector< Manager >::const_iterator j = v.end();
00053 
00054   return std::lower_bound( i , j , t , less_cset() );
00055 }
00056 
00057 std::vector< Manager >::iterator
00058 lower_bound( std::vector< Manager > & v , const std::type_info & t )
00059 {
00060   std::vector< Manager >::iterator i = v.begin();
00061   std::vector< Manager >::iterator j = v.end();
00062 
00063   return std::lower_bound( i , j , t , less_cset() );
00064 }
00065 
00066 }
00067 
00068 //----------------------------------------------------------------------
00069 
00070 const void * CSet::p_get( const std::type_info & t ) const
00071 {
00072   const void * result = NULL ;
00073 
00074   const std::vector< Manager >::const_iterator im = lower_bound(m_manager,t);
00075 
00076   if ( im < m_manager.end() && t == * im->first ) {
00077     const size_t offset = im - m_manager.begin();
00078     result = m_value[ offset ];
00079   }
00080 
00081   return result ;
00082 }
00083 
00084 const void *
00085 CSet::p_insert( const Manager & m , const void * v )
00086 {
00087   std::vector< Manager >::iterator im = lower_bound( m_manager , * m.first );
00088 
00089   const size_t offset = im - m_manager.begin();
00090 
00091   assert(m_value.size() == m_manager.size());
00092   std::vector<const void *>::iterator iv = m_value.begin();
00093   std::advance( iv , offset );
00094 
00095   if ( im == m_manager.end() || * m.first != * im->first ) {
00096     im = m_manager.insert( im , m );
00097     iv = m_value  .insert( iv , v );
00098   }
00099 
00100   assert(iv != m_value.end());
00101   return *iv ;
00102 }
00103 
00104 bool CSet::p_remove( const std::type_info & t , const void * v )
00105 {
00106   bool result = false;
00107   const std::vector< Manager >::iterator im = lower_bound( m_manager , t );
00108 
00109   if (im != m_manager.end()) {
00110     const size_t offset = im - m_manager.begin();
00111 
00112     if (offset <= m_value.size()) {
00113       std::vector<const void *>::iterator iv = m_value.begin();
00114       std::advance( iv , offset );
00115 
00116       result = t == * im->first && v == * iv ;
00117 
00118       if ( result ) {
00119   m_manager.erase( im );
00120   m_value  .erase( iv );
00121       }
00122     }
00123   }
00124   return result ;
00125 }
00126 
00127 //----------------------------------------------------------------------
00128 
00129 CSet::~CSet()
00130 {
00131   try {
00132     const size_t n = m_manager.size();
00133     for ( size_t i = 0 ; i < n ; ++i ) {
00134       try {
00135         if ( m_manager[i].second ) {
00136           (*m_manager[i].second)( const_cast<void*>( m_value[i] ) );
00137         }
00138       } catch(...) {}
00139     }
00140   } catch(...) {}
00141 }
00142 
00143 CSet::CSet() : m_manager(), m_value() {}
00144 
00145 } // namespace stk
00146 
00147 //----------------------------------------------------------------------
00148 //----------------------------------------------------------------------
00149 
00150 
00151 #ifdef UNIT_TEST
00152 
00153 namespace stk {
00154 namespace unit_test {
00155 
00156 class A {
00157 public:
00158   virtual const char * name() const = 0 ;
00159   virtual ~A();
00160 };
00161 
00162 class B {
00163 public:
00164   virtual const char * name() const = 0 ;
00165   virtual ~B();
00166 };
00167 
00168 void DoNotDelete( A * a )
00169 { std::cout << "DoNotDelete(" << a->name() << ")" << std::endl ; }
00170 
00171 void DoDelete( A * a )
00172 {
00173   std::cout << "DoDelete(" << a->name() << ")" << std::endl ;
00174   delete a ;
00175 }
00176 
00177 void DoNotDelete( B * b )
00178 { std::cout << "DoNotDelete(" << b->name() << ")" << std::endl ; }
00179 
00180 void DoDelete( B * b )
00181 {
00182   std::cout << "DoDelete(" << b->name() << ")" << std::endl ;
00183   delete b ;
00184 }
00185 
00186 class U : public A {
00187 public:
00188   const char * name() const ;
00189   ~U() {}
00190 };
00191 
00192 class V : public B {
00193 public:
00194   const char * name() const ;
00195   ~V() {}
00196 };
00197 
00198 class W : public B {
00199 public:
00200   const char * name() const ;
00201   ~W() {}
00202 };
00203 
00204 class X : public A , public B {
00205 public:
00206   const char * name() const ;
00207   ~X() {}
00208 };
00209 
00210 class Y : public A , public B {
00211 public:
00212   const char * name() const ;
00213   ~Y() {}
00214 };
00215 
00216 class Z {
00217 public:
00218   const char * name() const ;
00219   ~Z() {}
00220 };
00221 
00222 //----------------------------------------------------------------------
00223 
00224 int cset()
00225 {
00226   const A * sa ;
00227   const B * sb ;
00228   bool flag ;
00229 
00230   U * u = new U();
00231   V * v = new V();
00232   W * w = new W();
00233   X * x = new X();
00234   Y * y = new Y();
00235 
00236   {
00237     CSet cs ;
00238 
00239     sa = cs.insert<A>(u,true);
00240     std::cout << "cs.insert<A>(u,true)->name() = " << sa->name() << std::endl ;
00241 
00242     sb = cs.insert<B>(v,true);
00243     std::cout << "cs.insert<B>(v,true)->name() = " << sb->name() << std::endl ;
00244 
00245     // Should not replace:
00246     sb = cs.insert<B>(w,true);
00247     std::cout << "cs.insert<B>(w,true)->name() = " << sb->name() << std::endl ;
00248 
00249     flag = cs.remove<A>( u );
00250     std::cout << "s.remove<A>(u) = " << flag << std::endl ;
00251 
00252     flag = cs.remove<B>( v );
00253     std::cout << "s.remove<B>(v) = " << flag << std::endl ;
00254 
00255     sa = cs.insert<A>(x);
00256     sb = cs.insert<B>(x);
00257     std::cout << "s.insert<A>(x)->name() = " << sa->name() << std::endl ;
00258     std::cout << "s.insert<B>(x)->name() = " << sb->name() << std::endl ;
00259 
00260     sa = cs.insert<A>(y);
00261     sb = cs.insert<B>(y);
00262     std::cout << "s.insert<A>(y)->name() = " << sa->name() << std::endl ;
00263     std::cout << "s.insert<B>(y)->name() = " << sb->name() << std::endl ;
00264   }
00265 
00266   delete x ; x = NULL ;
00267   delete y ; y = NULL ;
00268   delete w ; w = NULL ;
00269   delete v ; v = NULL ;
00270   delete u ; u = NULL ;
00271 
00272   return 0 ;
00273 }
00274 
00275 //----------------------------------------------------------------------
00276 
00277 A::~A() {}
00278 B::~B() {}
00279 
00280 const char * U::name() const
00281 {
00282   static const char n[] = "U" ;
00283   return n ;
00284 }
00285 
00286 const char * V::name() const
00287 {
00288   static const char n[] = "V" ;
00289   return n ;
00290 }
00291 
00292 const char * W::name() const
00293 {
00294   static const char n[] = "W" ;
00295   return n ;
00296 }
00297 
00298 const char * X::name() const
00299 {
00300   static const char n[] = "X" ;
00301   return n ;
00302 }
00303 
00304 const char * Y::name() const
00305 {
00306   static const char n[] = "Y" ;
00307   return n ;
00308 }
00309 
00310 const char * Z::name() const
00311 {
00312   static const char n[] = "Z" ;
00313   return n ;
00314 }
00315 
00316 }
00317 }
00318 
00319 int main()
00320 {
00321   return phdmesh::unit_test::cset();
00322 }
00323 
00324 #endif
00325 
00326 
00327 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends