96 lines
2.8 KiB
C++
96 lines
2.8 KiB
C++
|
/******************************************************************************/
|
||
|
/* VARIOUS ALGORITHMS *********************************************************/
|
||
|
/******************************************************************************/
|
||
|
|
||
|
#ifndef _H_EBCL_ALGORITHMS
|
||
|
#define _H_EBCL_ALGORITHMS
|
||
|
#include <ebcl/Types.hh>
|
||
|
#include <ebcl/Arrays.hh>
|
||
|
namespace ebcl {
|
||
|
|
||
|
|
||
|
/*= VISITOR ==================================================================*/
|
||
|
|
||
|
|
||
|
/* Helper for the visitor algorithm. Provides the various types used internally
|
||
|
* as well as means to create and dereference values for the stack.
|
||
|
*
|
||
|
* The template's default implementation are not functional. It is specialised
|
||
|
* later for references and non-references.
|
||
|
*/
|
||
|
template<
|
||
|
typename T_Ref ,
|
||
|
bool IsRef = std::is_reference< T_Ref >::value
|
||
|
> struct T_VisitorHelper_
|
||
|
{
|
||
|
using T_Opt = void; // Optional value type
|
||
|
using T_StackRef = void; // Stack reference type
|
||
|
|
||
|
static T_StackRef mkext( T_Ref ) noexcept; // Create stack reference
|
||
|
static T_Ref deref( T_StackRef ) noexcept; // Dereference stack entry
|
||
|
};
|
||
|
|
||
|
|
||
|
template<
|
||
|
// Node type
|
||
|
typename T_Node ,
|
||
|
// Node reference type; by default, use values for arithmetic types and
|
||
|
// pointers, and references for other types
|
||
|
typename R_Node = std::conditional_t<
|
||
|
std::is_arithmetic< T_Node >::value || std::is_pointer< T_Node >::value ,
|
||
|
T_Node , T_Node& >
|
||
|
> class T_Visitor
|
||
|
{
|
||
|
private:
|
||
|
using Helper_ = T_VisitorHelper_< R_Node >;
|
||
|
|
||
|
public:
|
||
|
// Optional value
|
||
|
using T_OptNode = typename Helper_::T_Opt;
|
||
|
|
||
|
// Node browser. Returns the Nth child of the specified node, or null
|
||
|
// if there are no children left.
|
||
|
using F_NodeBrowser = std::function< T_OptNode( R_Node , uint32_t ) >;
|
||
|
|
||
|
// Node action. Second parameter indicates whether the action is
|
||
|
// being called before (false) or after (true) visiting the children.
|
||
|
using F_NodeAction = std::function< bool( R_Node , bool ) >;
|
||
|
|
||
|
private:
|
||
|
using T_StackRef_ = typename Helper_::T_StackRef;
|
||
|
|
||
|
// State of a stack entry
|
||
|
enum E_State_ {
|
||
|
BEFORE , // Must enter the node
|
||
|
CHILDREN , // Going through children
|
||
|
AFTER // Must exit the node
|
||
|
};
|
||
|
struct T_NodeRef_ {
|
||
|
T_StackRef_ node;
|
||
|
uint32_t child;
|
||
|
E_State_ state{ BEFORE };
|
||
|
|
||
|
explicit T_NodeRef_( R_Node node ) noexcept
|
||
|
: node( Helper_::mkext( node ) ) , child( 0 ) {}
|
||
|
explicit T_NodeRef_( R_Node node , uint32_t child ) noexcept
|
||
|
: node( Helper_::mkext( node ) ) , child( child ) {}
|
||
|
};
|
||
|
|
||
|
F_NodeBrowser nodeBrowser_;
|
||
|
T_AutoArray< T_NodeRef_ , 8 > stack_;
|
||
|
|
||
|
public:
|
||
|
T_Visitor( ) = delete;
|
||
|
T_Visitor( T_Visitor const& ) = default;
|
||
|
T_Visitor( T_Visitor&& ) noexcept = default;
|
||
|
|
||
|
explicit T_Visitor( F_NodeBrowser browser ) noexcept;
|
||
|
|
||
|
void visit( R_Node root , F_NodeAction action );
|
||
|
};
|
||
|
|
||
|
|
||
|
} // namespace
|
||
|
#endif // _H_EBCL_ALGORITHMS
|
||
|
#include <ebcl/inline/Algorithms.hh>
|