source: trunk/include/k/kAvlTmpl/kAvlEnum.h@ 8

Last change on this file since 8 was 7, checked in by bird, 18 years ago

kAVL: Implemented locking, root node and a direct cache.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 6.4 KB
Line 
1/* $Id: kAvlEnum.h 7 2008-02-04 02:08:02Z bird $ */
2/** @file
3 * kAvlTmpl - Templated AVL Trees, Node Enumeration.
4 */
5
6/*
7 * Copyright (c) 1999-2007 knut st. osmundsen <bird-src-spam@anduin.net>
8 *
9 * This file is part of kStuff.
10 *
11 * kStuff is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * kStuff is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with kStuff; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 *
26 * As a special exception, since this is a source file and not a header
27 * file, you are granted permission to #include this file as you wish
28 * without this in itself causing the resulting program or whatever to be
29 * covered by the LGPL license. This exception does not however invalidate
30 * any other reasons why the resulting program/whatever should not be
31 * covered the LGPL or GPL.
32 */
33
34/*******************************************************************************
35* Structures and Typedefs *
36*******************************************************************************/
37/**
38 * Enumeration control data.
39 *
40 * This is initialized by BeginEnum and used by GetNext to figure out what
41 * to do next.
42 */
43typedef struct KAVL_TYPE(,ENUMDATA)
44{
45 KBOOL fFromLeft;
46 KI8 cEntries;
47 KU8 achFlags[KAVL_MAX_STACK];
48 KAVLNODE * aEntries[KAVL_MAX_STACK];
49} KAVL_TYPE(,ENUMDATA), *KAVL_TYPE(P,ENUMDATA);
50
51
52/**
53 * Ends an enumeration.
54 *
55 * The purpose of this function is to unlock the tree should the
56 * AVL implementation include locking. It's good practice to call
57 * it anyway even if the tree doesn't do any locking.
58 *
59 * @param pEnumData Pointer to enumeration control data.
60 */
61KAVL_DECL(void) KAVL_FN(EndEnum)(KAVL_TYPE(,ENUMDATA) *pEnumData)
62{
63 KAVLROOT pRoot = pEnumData->pRoot;
64 pEnumData->pRoot = NULL;
65 if (pRoot)
66 KAVL_READ_UNLOCK(pEnumData->pRoot);
67}
68
69
70/**
71 * Get the next node in the tree enumeration.
72 *
73 * The current implementation of this function willl not walk the mpList
74 * chain like the DoWithAll function does. This may be changed later.
75 *
76 * @returns Pointer to the next node in the tree.
77 * NULL is returned when the end of the tree has been reached,
78 * it is not necessary to call EndEnum in this case.
79 * @param pEnumData Pointer to enumeration control data.
80 */
81KAVL_DECL(KAVLNODE *) KAVL_FN(GetNext)(KAVL_TYPE(,ENUMDATA) *pEnumData)
82{
83 if (pEnumData->fFromLeft)
84 { /* from left */
85 while (pEnumData->cEntries > 0)
86 {
87 KAVLNODE *pNode = pEnumData->aEntries[pEnumData->cEntries - 1];
88
89 /* left */
90 if (pEnumData->achFlags[pEnumData->cEntries - 1] == 0)
91 {
92 pEnumData->achFlags[pEnumData->cEntries - 1]++;
93 if (pNode->mpLeft != KAVL_NULL)
94 {
95 pEnumData->achFlags[pEnumData->cEntries] = 0; /* 0 left, 1 center, 2 right */
96 pEnumData->aEntries[pEnumData->cEntries++] = KAVL_GET_POINTER(&pNode->mpLeft);
97 continue;
98 }
99 }
100
101 /* center */
102 if (pEnumData->achFlags[pEnumData->cEntries - 1] == 1)
103 {
104 pEnumData->achFlags[pEnumData->cEntries - 1]++;
105 return pNode;
106 }
107
108 /* right */
109 pEnumData->cEntries--;
110 if (pNode->mpRight != KAVL_NULL)
111 {
112 pEnumData->achFlags[pEnumData->cEntries] = 0;
113 pEnumData->aEntries[pEnumData->cEntries++] = KAVL_GET_POINTER(&pNode->mpRight);
114 }
115 } /* while */
116 }
117 else
118 { /* from right */
119 while (pEnumData->cEntries > 0)
120 {
121 KAVLNODE *pNode = pEnumData->aEntries[pEnumData->cEntries - 1];
122
123 /* right */
124 if (pEnumData->achFlags[pEnumData->cEntries - 1] == 0)
125 {
126 pEnumData->achFlags[pEnumData->cEntries - 1]++;
127 if (pNode->mpRight != KAVL_NULL)
128 {
129 pEnumData->achFlags[pEnumData->cEntries] = 0; /* 0 right, 1 center, 2 left */
130 pEnumData->aEntries[pEnumData->cEntries++] = KAVL_GET_POINTER(&pNode->mpRight);
131 continue;
132 }
133 }
134
135 /* center */
136 if (pEnumData->achFlags[pEnumData->cEntries - 1] == 1)
137 {
138 pEnumData->achFlags[pEnumData->cEntries - 1]++;
139 return pNode;
140 }
141
142 /* left */
143 pEnumData->cEntries--;
144 if (pNode->mpLeft != KAVL_NULL)
145 {
146 pEnumData->achFlags[pEnumData->cEntries] = 0;
147 pEnumData->aEntries[pEnumData->cEntries++] = KAVL_GET_POINTER(&pNode->mpLeft);
148 }
149 } /* while */
150 }
151
152 /*
153 * Call EndEnum.
154 */
155 KAVL_FN(EndEnum)(pEnumData);
156 return NULL;
157}
158
159
160/**
161 * Starts an enumeration of all nodes in the given AVL tree.
162 *
163 * The current implementation of this function will not walk the mpList
164 * chain like the DoWithAll function does. This may be changed later.
165 *
166 * @returns Pointer to the first node in the enumeration.
167 * If NULL is returned the tree is empty calling EndEnum isn't
168 * strictly necessary (although it will do no harm).
169 * @param pRoot Pointer to the AVL-tree root structure.
170 * @param pEnumData Pointer to enumeration control data.
171 * @param fFromLeft K_TRUE: Left to right.
172 * K_FALSE: Right to left.
173 */
174KAVL_DECL(KAVLNODE *) KAVL_FN(BeginEnum)(KAVLROOT *pRoot, KAVL_TYPE(,ENUMDATA) *pEnumData, KBOOL fFromLeft)
175{
176 KAVL_READ_LOCK(pRoot);
177 pEnumData->pRoot = pRoot;
178 if (pRoot->mpRoot != KAVL_NULL)
179 {
180 pEnumData->fFromLeft = fFromLeft;
181 pEnumData->cEntries = 1;
182 pEnumData->aEntries[0] = KAVL_GET_POINTER(pRoot->mpRoot);
183 pEnumData->achFlags[0] = 0;
184 }
185 else
186 pEnumData->cEntries = 0;
187
188 return KAVL_FN(GetNext)(pEnumData);
189}
190
Note: See TracBrowser for help on using the repository browser.