/*
MultiNode sample code
Henry Smith (henry@enigmasoftware.ca)
MultiNode template class from which concrete classes should derive
*/
#ifndef MultiNode_H
#define MultiNode_H
#include "MultiNodeBase.h"
#include <boost/function.hpp>
////////////////////////////////////////////////////////////////////////////////
//
// Iteration orders
// (to be used as template parameters to MultiNode::iterator)
//
////////////////////////////////////////////////////////////////////////////////
// Sample tree:
//
// A
// |
// +--B
// |
// +--C
// | |
// | +--D
// |
// +--E
//
// TreeOrder (with root A iterates B, C, D, E)
struct TreeOrder
{
static MultiNodeRef Start (const MultiNodeRef& inRoot, bool inShouldIncludeRoot = false);
static MultiNodeRef Advance (const MultiNodeRef& inPosition);
private:
static MultiNodeRef NextNode (const MultiNodeRef& inCurrent);
};
// ChildOrder (with root A iterates B, C, E)
struct ChildOrder
{
static MultiNodeRef Start (const MultiNodeRef& inRoot, bool inShouldIncludeRoot = false);
static MultiNodeRef Advance (const MultiNodeRef& inPosition);
};
// TreeOrder (with root D iterates C, A)
struct ParentOrder
{
static MultiNodeRef Start (const MultiNodeRef& inRoot, bool inShouldIncludeRoot = false);
static MultiNodeRef Advance (const MultiNodeRef& inPosition);
};
enum
{
DontIncludeRoot = false,
IncludeRoot = true
};
////////////////////////////////////////////////////////////////////////////////
//
// MultiNode
// (templatize with subclass, ie. class MyData : public MultiNode<MyData>...)
//
////////////////////////////////////////////////////////////////////////////////
template <class T>
class MultiNode
: public MultiNodeBase
{
typedef MultiNodeBase Super;
public:
typedef MultiNodeRefCast<T> Ref;
public:
MultiNode () {}
virtual ~MultiNode () {}
////////////////////////////////////////////////////////////////////////////////
//
// Predicates
//
////////////////////////////////////////////////////////////////////////////////
typedef boost::function<bool (const T*)> Predicate;
// The default predicate (always returns true)
struct NullPredicate {
bool operator () (const T*) const { return true; }
};
////////////////////////////////////////////////////////////////////////////////
//
// Iterator template
//
////////////////////////////////////////////////////////////////////////////////
template <class Order, bool ShouldIncludeRoot, FamilyID Family>
struct iterator
{
public:
iterator (const Ref& inRoot)
: mFamilyScope(Family)
, mPredicate(sNullPredicate)
, mNode(Start( inRoot, ShouldIncludeRoot )) {}
// Alternate constructors for selectively overriding the template parameters
iterator (const Ref& inRoot, FamilyID inFamily, bool inShouldIncludeRoot = ShouldIncludeRoot)
: mFamilyScope(inFamily)
, mPredicate(sNullPredicate)
, mNode(Start( inRoot, inShouldIncludeRoot )) {}
iterator (const Ref& inRoot, FamilyID inFamily, Predicate inPredicate)
: mFamilyScope(inFamily)
, mPredicate(inPredicate)
, mNode(Start( inRoot, ShouldIncludeRoot )) {}
iterator (const Ref& inRoot, Predicate inPredicate)
: mFamilyScope(Family)
, mPredicate(inPredicate)
, mNode(Start( inRoot, ShouldIncludeRoot )) {}
operator T* () const { return mNode.GetPtr(); }
T* operator -> () const { return mNode.GetPtr(); }
T* operator * () const { return mNode.GetPtr(); }
iterator& operator ++ () { mNode = Advance( mNode ); return (*this); }
protected:
Ref Start (const Ref& inRoot, bool inShouldIncludeRoot);
Ref Advance (const Ref& inPosition);
private:
FamilyScope mFamilyScope; // This declaration has to be first! (we need a family to start in...)
Predicate mPredicate;
Ref mNode;
private:
static NullPredicate sNullPredicate;
};
////////////////////////////////////////////////////////////////////////////////
//
// Helpful specializations for basic iteration
//
////////////////////////////////////////////////////////////////////////////////
typedef iterator< TreeOrder, IncludeRoot, 0 > tree_iterator;
friend struct iterator< TreeOrder, IncludeRoot, 0 >;
typedef iterator< ChildOrder, DontIncludeRoot, 0 > child_iterator;
friend struct iterator< ChildOrder, DontIncludeRoot, 0 >;
typedef iterator< ParentOrder, IncludeRoot, 0 > parent_iterator;
friend struct iterator< ParentOrder, IncludeRoot, 0 >;
};
////////////////////////////////////////////////////////////////////////////////
//
// Template function definitions
//
////////////////////////////////////////////////////////////////////////////////
template <class T>
template <class O, bool S, FamilyID F>
typename MultiNode<T>::NullPredicate MultiNode<T>::iterator<O, S, F>::sNullPredicate;
template <class T>
template <class O, bool S, FamilyID F>
MultiNodeRefCast<T> MultiNode<T>::iterator<O, S, F>::Start (const Ref& inRoot, bool inShouldIncludeRoot)
{
Ref start = O::Start( inRoot, inShouldIncludeRoot );
// Skip over all nodes that DON'T match the condition (ie. only visit nodes that satisfy the condition)
while (start != NullRef && !mPredicate( start.GetPtr() )) {
start = O::Advance( start );
}
return start;
}
template <class T>
template <class O, bool S, FamilyID F>
MultiNodeRefCast<T> MultiNode<T>::iterator<O, S, F>::Advance (const Ref& inPosition)
{
Ref next = O::Advance( inPosition );
// Skip over all nodes that DON'T match the condition (ie. only visit nodes that satisfy the condition)
while (next != NullRef && !mPredicate( next.GetPtr() )) {
next = O::Advance( next );
}
return next;
}
#endif // MultiNode_H