PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // ObjectGraphIterator.h 00004 // 00005 // Copyright (C) 2005 Nicolas Chapados 00006 // 00007 // Redistribution and use in source and binary forms, with or without 00008 // modification, are permitted provided that the following conditions are met: 00009 // 00010 // 1. Redistributions of source code must retain the above copyright 00011 // notice, this list of conditions and the following disclaimer. 00012 // 00013 // 2. Redistributions in binary form must reproduce the above copyright 00014 // notice, this list of conditions and the following disclaimer in the 00015 // documentation and/or other materials provided with the distribution. 00016 // 00017 // 3. The name of the authors may not be used to endorse or promote 00018 // products derived from this software without specific prior written 00019 // permission. 00020 // 00021 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00022 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00023 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00024 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00025 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00026 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00027 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00028 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00029 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 // 00032 // This file is part of the PLearn library. For more information on the PLearn 00033 // library, go to the PLearn Web site at www.plearn.org 00034 00035 /* ******************************************************* 00036 * $Id: .pyskeleton_header 544 2003-09-01 00:05:31Z plearner $ 00037 ******************************************************* */ 00038 00039 // Authors: Nicolas Chapados 00040 00044 #ifndef ObjectGraphIterator_INC 00045 #define ObjectGraphIterator_INC 00046 00047 // From C++ stdlib 00048 #include <string> 00049 #include <vector> 00050 #include <utility> 00051 00052 // From boost 00053 #include <boost/call_traits.hpp> 00054 00055 // From PLearn 00056 #include <plearn/base/OptionBase.h> 00057 00058 00059 namespace PLearn { 00060 00061 // Forward-declare 00062 class Object; 00063 00064 00065 //###################### CLASS OBJECTOPTIONSITERATOR ####################### 00066 00078 class ObjectOptionsIterator 00079 { 00080 public: 00082 ObjectOptionsIterator(); 00083 00098 ObjectOptionsIterator(const Object* root, 00099 bool ignore_nontraversable = false, 00100 bool skip_nulls = true); 00101 00102 // Default assignment, copy constructor, destructor 00103 00105 bool operator==(const ObjectOptionsIterator& rhs) const; 00106 00108 bool operator!=(const ObjectOptionsIterator& rhs) const 00109 { 00110 return ! (*this == rhs); 00111 } 00112 00115 const Object* operator*() const; 00116 00125 string getCurrentOptionName() const; 00126 00131 OptionBase::flag_t getCurrentOptionFlags() const; 00132 00133 // Go to next object or "invalid" state if end of iteration 00134 const ObjectOptionsIterator& operator++(); 00135 00138 ObjectOptionsIterator operator++(int) 00139 { 00140 ObjectOptionsIterator old(*this); 00141 ++(*this); 00142 return old; 00143 } 00144 00145 protected: 00146 bool m_invalid; 00147 bool m_ignore_nontraversable; 00148 bool m_skip_nulls; 00149 const Object* m_object; 00150 const OptionList* m_options; 00151 int m_cur_option; 00152 int m_cur_index; 00153 00154 int m_max_index; 00155 00156 }; 00157 00158 00159 //####################### CLASS OBJECTGRAPHITERATOR ######################## 00160 00184 class ObjectGraphIterator 00185 { 00186 public: 00192 enum TraversalType { 00193 BreadthOrder = 1, 00194 DepthPreOrder = 2, 00195 ReversedBreadthOrder = 64 | 1, 00196 ReversedDepthPreOrder = 64 | 2 00197 }; 00198 00201 static const int Reversed = 64; 00202 00209 static const int IgnoreNonTraversable = 128; 00210 00211 00212 public: 00214 ObjectGraphIterator(); 00215 00229 ObjectGraphIterator(const Object* root, TraversalType tt = DepthPreOrder, 00230 bool compute_optnames = false, 00231 const std::string& base_class_filter = ""); 00232 00233 // Default assignment, copy constructor, destructor 00234 00236 bool invalid() const 00237 { 00238 return m_it == m_end; 00239 } 00240 00242 bool operator==(const ObjectGraphIterator& rhs) const; 00243 00245 bool operator!=(const ObjectGraphIterator& rhs) const 00246 { 00247 return ! (*this == rhs); 00248 } 00249 00252 const Object* operator*() const 00253 { 00254 PLASSERT( !invalid() ); 00255 return m_it->first; 00256 } 00257 00262 const string& getCurrentOptionName() const 00263 { 00264 PLASSERT( !invalid() ); 00265 return m_it->second; 00266 } 00267 00269 const ObjectGraphIterator& operator++(); 00270 00273 ObjectGraphIterator operator++(int) 00274 { 00275 ObjectGraphIterator old(*this); 00276 ++(*this); 00277 return old; 00278 } 00279 00280 protected: 00283 void buildTraversalGraph(const Object* root, TraversalType tt, 00284 bool compute_optnames); 00285 00286 protected: 00287 typedef pair<const Object*, string> ObjectAndName; 00288 typedef std::vector<ObjectAndName> ObjectList; 00289 typedef bool (*ISA)(const Object*); 00290 00291 ObjectList m_object_list; 00292 ObjectList::iterator m_it; 00293 ObjectList::iterator m_end; 00294 ISA m_isa_tester; 00295 }; 00296 00297 00298 //##### Broadcast ########################################################### 00299 00317 // Zero argument, const 00318 template <class T, class U> 00319 void memfun_broadcast(const Object* o, U (T::*func)() const, 00320 ObjectGraphIterator::TraversalType tt = ObjectGraphIterator::DepthPreOrder) 00321 { 00322 ObjectGraphIterator grit(o, tt, false, T::_classname_()), grend; 00323 for ( ; grit != grend ; ++grit) 00324 if (const T* t = dynamic_cast<const T*>(*grit)) 00325 (t->*func)(); 00326 } 00327 00328 00329 // Zero argument, non-const 00330 template <class T, class U> 00331 void memfun_broadcast(Object* o, U (T::*func)(), 00332 ObjectGraphIterator::TraversalType tt = ObjectGraphIterator::DepthPreOrder) 00333 { 00334 ObjectGraphIterator grit(o, tt, false, T::_classname_()), grend; 00335 for ( ; grit != grend ; ++grit) 00336 if (T* t = const_cast<T*>(dynamic_cast<const T*>(*grit))) 00337 (t->*func)(); 00338 } 00339 00340 00341 // One argument, const 00342 template <class T, class U, class V> 00343 void memfun_broadcast(const Object* o, U (T::*func)(V) const, 00344 typename boost::call_traits<V>::param_type arg1, 00345 ObjectGraphIterator::TraversalType tt = ObjectGraphIterator::DepthPreOrder) 00346 { 00347 ObjectGraphIterator grit(o, tt, false, T::_classname_()), grend; 00348 for ( ; grit != grend ; ++grit) 00349 if (const T* t = dynamic_cast<const T*>(*grit)) 00350 (t->*func)(arg1); 00351 } 00352 00353 00354 // One argument, non-const 00355 template <class T, class U, class V> 00356 void memfun_broadcast(Object* o, U (T::*func)(V), 00357 typename boost::call_traits<V>::param_type arg1, 00358 ObjectGraphIterator::TraversalType tt = ObjectGraphIterator::DepthPreOrder) 00359 { 00360 ObjectGraphIterator grit(o, tt, false, T::_classname_()), grend; 00361 for ( ; grit != grend ; ++grit) 00362 if (T* t = const_cast<T*>(dynamic_cast<const T*>(*grit))) 00363 (t->*func)(arg1); 00364 } 00365 00366 00367 // Two arguments, const 00368 template <class T, class U, class V, class W> 00369 void memfun_broadcast(const Object* o, U (T::*func)(V,W) const, 00370 typename boost::call_traits<V>::param_type arg1, 00371 typename boost::call_traits<W>::param_type arg2, 00372 ObjectGraphIterator::TraversalType tt = ObjectGraphIterator::DepthPreOrder) 00373 { 00374 ObjectGraphIterator grit(o, tt, false, T::_classname_()), grend; 00375 for ( ; grit != grend ; ++grit) 00376 if (const T* t = dynamic_cast<const T*>(*grit)) 00377 (t->*func)(arg1,arg2); 00378 } 00379 00380 00381 // Two arguments, non-const 00382 template <class T, class U, class V, class W> 00383 void memfun_broadcast(Object* o, U (T::*func)(V,W), 00384 typename boost::call_traits<V>::param_type arg1, 00385 typename boost::call_traits<W>::param_type arg2, 00386 ObjectGraphIterator::TraversalType tt = ObjectGraphIterator::DepthPreOrder) 00387 { 00388 ObjectGraphIterator grit(o, tt, false, T::_classname_()), grend; 00389 for ( ; grit != grend ; ++grit) 00390 if (T* t = const_cast<T*>(dynamic_cast<const T*>(*grit))) 00391 (t->*func)(arg1,arg2); 00392 } 00393 00394 00395 // Three arguments, const 00396 template <class T, class U, class V, class W, class X> 00397 void memfun_broadcast(const Object* o, U (T::*func)(V,W,X) const, 00398 typename boost::call_traits<V>::param_type arg1, 00399 typename boost::call_traits<W>::param_type arg2, 00400 typename boost::call_traits<X>::param_type arg3, 00401 ObjectGraphIterator::TraversalType tt = ObjectGraphIterator::DepthPreOrder) 00402 { 00403 ObjectGraphIterator grit(o, tt, false, T::_classname_()), grend; 00404 for ( ; grit != grend ; ++grit) 00405 if (const T* t = dynamic_cast<const T*>(*grit)) 00406 (t->*func)(arg1,arg2,arg3); 00407 } 00408 00409 00410 // Three arguments, non-const 00411 template <class T, class U, class V, class W, class X> 00412 void memfun_broadcast(Object* o, U (T::*func)(V,W,X), 00413 typename boost::call_traits<V>::param_type arg1, 00414 typename boost::call_traits<W>::param_type arg2, 00415 typename boost::call_traits<X>::param_type arg3, 00416 ObjectGraphIterator::TraversalType tt = ObjectGraphIterator::DepthPreOrder) 00417 { 00418 ObjectGraphIterator grit(o, tt, false, T::_classname_()), grend; 00419 for ( ; grit != grend ; ++grit) 00420 if (T* t = const_cast<T*>(dynamic_cast<const T*>(*grit))) 00421 (t->*func)(arg1,arg2,arg3); 00422 } 00423 00424 00447 // Zero argument, const 00448 template <class T, class U, class V> 00449 void memfun_broadcast_optname(const Object* o, U (T::*func)(V) const, 00450 ObjectGraphIterator::TraversalType tt = 00451 ObjectGraphIterator::DepthPreOrder) 00452 { 00453 ObjectGraphIterator grit(o, tt, true, T::_classname_()), grend; 00454 for ( ; grit != grend ; ++grit) 00455 if (const T* t = dynamic_cast<const T*>(*grit)) 00456 (t->*func)(grit.getCurrentOptionName()); 00457 } 00458 00459 00460 // Zero argument, non-const 00461 template <class T, class U, class V> 00462 void memfun_broadcast_optname(Object* o, U (T::*func)(V), 00463 ObjectGraphIterator::TraversalType tt = 00464 ObjectGraphIterator::DepthPreOrder) 00465 { 00466 ObjectGraphIterator grit(o, tt, true, T::_classname_()), grend; 00467 for ( ; grit != grend ; ++grit) 00468 if (T* t = const_cast<T*>(dynamic_cast<const T*>(*grit))) 00469 (t->*func)(grit.getCurrentOptionName()); 00470 } 00471 00472 00473 // One argument, const 00474 template <class T, class U, class V, class W> 00475 void memfun_broadcast_optname(const Object* o, U (T::*func)(V,W) const, 00476 typename boost::call_traits<V>::param_type arg1, 00477 ObjectGraphIterator::TraversalType tt = 00478 ObjectGraphIterator::DepthPreOrder) 00479 { 00480 ObjectGraphIterator grit(o, tt, true, T::_classname_()), grend; 00481 for ( ; grit != grend ; ++grit) 00482 if (const T* t = dynamic_cast<const T*>(*grit)) 00483 (t->*func)(grit.getCurrentOptionName(), arg1); 00484 } 00485 00486 00487 // One argument, non-const 00488 template <class T, class U, class V, class W> 00489 void memfun_broadcast_optname(Object* o, U (T::*func)(V,W), 00490 typename boost::call_traits<V>::param_type arg1, 00491 ObjectGraphIterator::TraversalType tt = 00492 ObjectGraphIterator::DepthPreOrder) 00493 { 00494 ObjectGraphIterator grit(o, tt, true, T::_classname_()), grend; 00495 for ( ; grit != grend ; ++grit) 00496 if (T* t = const_cast<T*>(dynamic_cast<const T*>(*grit))) 00497 (t->*func)(grit.getCurrentOptionName(), arg1); 00498 } 00499 00500 00501 // Two arguments, const 00502 template <class T, class U, class V, class W, class X> 00503 void memfun_broadcast_optname(const Object* o, U (T::*func)(V,W,X) const, 00504 typename boost::call_traits<V>::param_type arg1, 00505 typename boost::call_traits<W>::param_type arg2, 00506 ObjectGraphIterator::TraversalType tt = 00507 ObjectGraphIterator::DepthPreOrder) 00508 { 00509 ObjectGraphIterator grit(o, tt, true, T::_classname_()), grend; 00510 for ( ; grit != grend ; ++grit) 00511 if (const T* t = dynamic_cast<const T*>(*grit)) 00512 (t->*func)(grit.getCurrentOptionName(), arg1, arg2); 00513 } 00514 00515 00516 // Two arguments, non-const 00517 template <class T, class U, class V, class W, class X> 00518 void memfun_broadcast_optname(Object* o, U (T::*func)(V,W,X), 00519 typename boost::call_traits<V>::param_type arg1, 00520 typename boost::call_traits<W>::param_type arg2, 00521 ObjectGraphIterator::TraversalType tt = 00522 ObjectGraphIterator::DepthPreOrder) 00523 { 00524 ObjectGraphIterator grit(o, tt, true, T::_classname_()), grend; 00525 for ( ; grit != grend ; ++grit) 00526 if (T* t = const_cast<T*>(dynamic_cast<const T*>(*grit))) 00527 (t->*func)(grit.getCurrentOptionName(), arg1, arg2); 00528 } 00529 00530 00543 void setoption_broadcast(const Object* o, const string& class_name, 00544 const string& option_name, const string& option_value, 00545 ObjectGraphIterator::TraversalType tt = 00546 ObjectGraphIterator::DepthPreOrder); 00547 00548 } // end of namespace PLearn 00549 00550 #endif 00551 00552 00553 /* 00554 Local Variables: 00555 mode:c++ 00556 c-basic-offset:4 00557 c-file-style:"stroustrup" 00558 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00559 indent-tabs-mode:nil 00560 fill-column:79 00561 End: 00562 */ 00563 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :