|
Sierra Toolkit Version of the Day
|
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