summaryrefslogtreecommitdiffstats
path: root/svx/source/inc/treevisitor.hxx
blob: ac66dcb2d1c68ad2aeb5bc1e30cfc731a3a06b9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/*************************************************************************
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2008 by Sun Microsystems, Inc.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: code,v $
*
* $Revision: 1.3 $
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org.  If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
************************************************************************/

#ifndef SVX_TREE_VISITOR_HXX
#define SVX_TREE_VISITOR_HXX

#include <stack>

template< class ELEMENT, class NODEINFO, class PROCESSOR >
class TreeVisitor
{
public:
    TreeVisitor( NODEINFO _nodeInfo )
        :m_visitedRoot( false )
        ,m_root()
        ,m_current()
        ,m_nodeInfo( _nodeInfo )
    {
    }

    void    process( const ELEMENT& _root, PROCESSOR& _processor )
    {
        m_root = _root;
        m_visitedRoot = false;

        while ( do_step() )
            _processor.process( m_current );
    }

private:
    bool    do_step();

private:
    bool            m_visitedRoot;
    ELEMENT         m_root;
    ELEMENT         m_current;
    const NODEINFO  m_nodeInfo;

    ::std::stack< size_t >  m_pathToCurrent;
    ::std::stack< ELEMENT > m_currentAncestors;
};

template< class ELEMENT, class NODEINFO, class PROCESSOR >
bool TreeVisitor< ELEMENT, NODEINFO, PROCESSOR >::do_step()
{
    if ( !m_visitedRoot )
    {
        m_current = m_root;
        m_visitedRoot = true;
        return true;
    }

    // can we step down from the current node?
    size_t childCount = m_nodeInfo.childCount( m_current );
    if ( childCount )
    {
        m_currentAncestors.push( m_current );
        m_current = m_nodeInfo.getChild( m_current, 0 );
        m_pathToCurrent.push( 0 );
        return true;
    }

    // is there a right sibling of the current node?
    while ( !m_pathToCurrent.empty() )
    {
        const ELEMENT& currentParent = m_currentAncestors.top();
        childCount = m_nodeInfo.childCount( currentParent );

        size_t currentChildPos = m_pathToCurrent.top();
        if ( ++currentChildPos < childCount )
        {
            // yes there is
            m_pathToCurrent.top() = currentChildPos;
            m_current = m_nodeInfo.getChild( currentParent, currentChildPos );
            return true;
        }

        // no there isn't => step up
        m_currentAncestors.pop();
        m_pathToCurrent.pop();
    }

    return false;
}

#endif // SVX_TREE_VISITOR_HXX