00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef VRS_VISITOR_H
00025 #define VRS_VISITOR_H
00026
00027 #include <vrs/config.h>
00028 #include <cassert>
00029 #include <vector>
00030
00031 namespace VRS {
00032
00033
00034 class VisitorBase;
00035 class Visitable;
00036 template<class T> class Visitor;
00037
00038
00039 class VRS_CORE_API VisitorBase {
00040 public:
00041 enum VisitMode {
00042 VM_VisitChildren,
00043 VM_VisitSiblings,
00044 VM_VisitFinish
00045 };
00046
00047
00048 virtual ~VisitorBase() { }
00049
00050 virtual bool isStrict() const { return false; }
00051
00052 const std::vector<Visitable*>& pathToRoot() const { return m_pathToRoot; }
00053
00054 public:
00055
00056
00057 std::vector<Visitable*> m_pathToRoot;
00058 std::vector<Visitable*> m_childObjectList;
00059 };
00060
00061 template<class T>
00062 class Visitor {
00063 public:
00064 virtual ~Visitor() { }
00065
00066 virtual VisitorBase::VisitMode visit(T* obj, bool pushObj) = 0;
00067 };
00068
00069 class VRS_CORE_API Visitable {
00070 public:
00071 virtual ~Visitable() { }
00072
00073 virtual VisitorBase::VisitMode accept(VisitorBase& visitor) = 0;
00074
00075 protected:
00076 virtual void acceptChildren(
00077 std::vector<Visitable*>& appendChildrenHere
00078 ) const {
00079
00080 }
00081
00082 bool acceptedImpl(
00083 VisitorBase& vistor,
00084 bool pushObj,
00085 VisitorBase::VisitMode& mode
00086 ) {
00087 return true;
00088 }
00089
00090 VisitorBase::VisitMode acceptHierarchyRecursionImpl(
00091 VisitorBase& visitor,
00092 bool pushObj
00093 ) {
00094 return VisitorBase::VM_VisitChildren;
00095 }
00096 };
00097
00098 #define VRS_VISITABLE_IMPL(FATHER) \
00099 \
00100 typedef FATHER VRS_FATHER_VISITABLE; \
00101 typedef VRS::Visitor<VRS_ThisClass> VRS_VISITOR_OF_THIS; \
00102 \
00103 virtual VRS::VisitorBase::VisitMode accept(VRS::VisitorBase& visitor) { \
00104 assert(typeid(VRS_ThisClass) == typeid(*this)); \
00105 \
00106 VRS::VisitorBase::VisitMode mode1 = acceptHierarchyRecursionImpl(visitor, true); \
00107 \
00108 if(mode1 == VRS::VisitorBase::VM_VisitChildren) { \
00109 const size_t currentChildObjectSize = visitor.m_childObjectList.size(); \
00110 this->acceptChildren(visitor.m_childObjectList); \
00111 \
00112 if(currentChildObjectSize < visitor.m_childObjectList.size()) { \
00113 visitor.m_pathToRoot.push_back(this); \
00114 try { \
00115 for( \
00116 size_t i = currentChildObjectSize, iEnd = visitor.m_childObjectList.size(); \
00117 (i != iEnd) && (mode1 != VRS::VisitorBase::VM_VisitFinish); \
00118 ++i \
00119 ) { \
00120 VRS::Visitable* const child = visitor.m_childObjectList[i]; \
00121 if(child) { \
00122 mode1 = child->accept(visitor); \
00123 } \
00124 } \
00125 } catch(std::exception&) { \
00126 visitor.m_pathToRoot.pop_back(); \
00127 throw; \
00128 } \
00129 visitor.m_pathToRoot.pop_back(); \
00130 visitor.m_childObjectList.resize(currentChildObjectSize); \
00131 } \
00132 } \
00133 \
00134 const VRS::VisitorBase::VisitMode mode2 = acceptHierarchyRecursionImpl(visitor, false); \
00135 return ((mode1 >= mode2) ? mode1 : mode2); \
00136 } \
00137 \
00138 VRS::VisitorBase::VisitMode acceptHierarchyRecursionImpl(VRS::VisitorBase& visitor, bool pushObj) { \
00139 VRS::VisitorBase::VisitMode mode = VRS::VisitorBase::VM_VisitChildren; \
00140 if(!acceptedImpl(visitor, pushObj, mode) && !visitor.isStrict()) { \
00141 return VRS_FATHER_VISITABLE::acceptHierarchyRecursionImpl(visitor, pushObj); \
00142 } \
00143 return mode; \
00144 } \
00145 \
00146 bool acceptedImpl(VRS::VisitorBase& visitor, bool pushObj, VRS::VisitorBase::VisitMode& mode) { \
00147 if(VRS_VISITOR_OF_THIS* p = dynamic_cast<VRS_VISITOR_OF_THIS*>(&visitor)) { \
00148 mode = p->visit(this, pushObj); \
00149 return true; \
00150 } \
00151 return false; \
00152 }
00153
00154 #define VRS_IS_STRICT_VISITOR \
00155 virtual bool isStrict() const { return true; }
00156
00157 #define VRS_VISITABLE_BASE \
00158 VRS_VISITABLE_IMPL(VRS::Visitable)
00159
00160 #define VRS_VISITABLE \
00161 VRS_VISITABLE_IMPL(VRS_BaseClass)
00162
00163 }
00164
00165 #endif // VRS_VISITOR_H