2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
5 * UniConf low-level tree storage abstraction.
7 #include "unihashtree.h"
11 UniHashTreeBase::UniHashTreeBase(UniHashTreeBase
*parent
,
12 const UniConfKey
&key
) :
23 UniHashTreeBase::~UniHashTreeBase()
27 Container
*oldchildren
= xchildren
;
33 // This happens only after the children are deleted by our
34 // subclass. This ensures that we do not confuse them
35 // about their parentage as their destructors are invoked
36 // The xchildren vector is destroyed by the subclass!
38 xparent
->unlink(this);
42 void UniHashTreeBase::_setparent(UniHashTreeBase
*parent
)
44 if (xparent
== parent
)
47 xparent
->unlink(this);
54 UniHashTreeBase
*UniHashTreeBase::_root() const
56 const UniHashTreeBase
*node
= this;
59 return const_cast<UniHashTreeBase
*>(node
);
63 UniConfKey
UniHashTreeBase::_fullkey(const UniHashTreeBase
*ancestor
) const
68 const UniHashTreeBase
*node
= this;
69 while (node
!= ancestor
)
71 result
.prepend(node
->key());
73 assert(node
!= NULL
||
74 ! "ancestor was not a node in the tree");
79 const UniHashTreeBase
*node
= this;
82 result
.prepend(node
->key());
90 UniHashTreeBase
*UniHashTreeBase::_find(const UniConfKey
&key
) const
92 const UniHashTreeBase
*node
= this;
93 UniConfKey::Iter
it(key
);
97 node
= node
->_findchild(it());
101 return const_cast<UniHashTreeBase
*>(node
);
105 UniHashTreeBase
*UniHashTreeBase::_findchild(const UniConfKey
&key
) const
108 return const_cast<UniHashTreeBase
*>(this);
110 return xchildren
? (*xchildren
)[key
] : NULL
;
114 bool UniHashTreeBase::haschildren() const
116 return xchildren
&& !xchildren
->isempty();
120 void UniHashTreeBase::link(UniHashTreeBase
*node
)
123 xchildren
= new Container();
125 xchildren
->add(node
);
129 void UniHashTreeBase::unlink(UniHashTreeBase
*node
)
134 xchildren
->remove(node
);
135 if (xchildren
->count() == 0)
143 static int keysorter(const UniHashTreeBase
*a
, const UniHashTreeBase
*b
)
145 return a
->key().compareto(b
->key());
148 void UniHashTreeBase::_recursive_unsorted_visit(
149 const UniHashTreeBase
*a
,
150 const UniHashTreeBaseVisitor
&visitor
, void *userdata
,
151 bool preorder
, bool postorder
)
154 visitor(a
, userdata
);
155 Container::Iter
i(*const_cast<Container
*>(a
->xchildren
));
156 for (i
.rewind(); i
.next();)
157 _recursive_unsorted_visit(i
.ptr(), visitor
, userdata
,
158 preorder
, postorder
);
160 visitor(a
, userdata
);
163 bool UniHashTreeBase::_recursivecompare(
164 const UniHashTreeBase
*a
, const UniHashTreeBase
*b
,
165 const UniHashTreeBaseComparator
&comparator
)
169 // don't bother comparing subtree if this returns false
170 // apenwarr 2004/04/26: some people seem to call recursivecompare and
171 // have their comparator function get called for *all* keys, because
172 // it has side effects. Gross, but whatever. If that's the case, then
173 // short-circuiting here is a bad idea.
174 if (!comparator(a
, b
))
177 // begin iteration sequence
178 Container::Sorter
*ait
= NULL
, *bit
= NULL
;
181 ait
= new Container::Sorter(*const_cast<Container
*>(a
->xchildren
),
184 a
= ait
->next() ? ait
->ptr() : NULL
;
188 bit
= new Container::Sorter(*const_cast<Container
*>(b
->xchildren
),
191 b
= bit
->next() ? bit
->ptr() : NULL
;
195 while (a
!= NULL
&& b
!= NULL
)
197 int order
= a
->key().compareto(b
->key());
201 _recursivecompare(a
, NULL
, comparator
);
202 a
= ait
->next() ? ait
->ptr() : NULL
;
207 _recursivecompare(NULL
, b
, comparator
);
208 b
= bit
->next() ? bit
->ptr() : NULL
;
210 else // keys are equal
212 if (!_recursivecompare(a
, b
, comparator
))
214 a
= ait
->next() ? ait
->ptr() : NULL
;
215 b
= bit
->next() ? bit
->ptr() : NULL
;
219 // finish up if one side is bigger than the other
223 _recursivecompare(a
, NULL
, comparator
);
224 a
= ait
->next() ? ait
->ptr() : NULL
;
229 _recursivecompare(NULL
, b
, comparator
);
230 b
= bit
->next() ? bit
->ptr() : NULL
;