Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenavltable.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Runtime Library 00003 * LICENSE: BSD - See COPYING.ARM in the top level directory 00004 * FILE: lib/rtl/avltable.c 00005 * PURPOSE: AVL Tree Generic Table Implementation 00006 * PROGRAMMERS: ReactOS Portable Systems Group 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 00011 #include <rtl.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* Include RTL version of AVL support */ 00016 #include "rtlavl.h" 00017 #include "avlsupp.c" 00018 00019 /* AVL FUNCTIONS *************************************************************/ 00020 00021 /* 00022 * @implemented 00023 */ 00024 VOID 00025 NTAPI 00026 RtlInitializeGenericTableAvl(IN OUT PRTL_AVL_TABLE Table, 00027 IN PRTL_AVL_COMPARE_ROUTINE CompareRoutine, 00028 IN PRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine, 00029 IN PRTL_AVL_FREE_ROUTINE FreeRoutine, 00030 IN PVOID TableContext) 00031 { 00032 /* Setup the table */ 00033 RtlZeroMemory(Table, sizeof(RTL_AVL_TABLE)); 00034 Table->BalancedRoot.Parent = &Table->BalancedRoot; 00035 Table->CompareRoutine = CompareRoutine; 00036 Table->AllocateRoutine = AllocateRoutine; 00037 Table->FreeRoutine = FreeRoutine; 00038 Table->TableContext = TableContext; 00039 } 00040 00041 /* 00042 * @implemented 00043 */ 00044 PVOID 00045 NTAPI 00046 RtlInsertElementGenericTableFullAvl(IN PRTL_AVL_TABLE Table, 00047 IN PVOID Buffer, 00048 IN ULONG BufferSize, 00049 OUT PBOOLEAN NewElement OPTIONAL, 00050 IN OUT PVOID NodeOrParent, 00051 IN OUT TABLE_SEARCH_RESULT SearchResult) 00052 { 00053 PRTL_BALANCED_LINKS NewNode; 00054 PVOID UserData; 00055 00056 /* Check if the entry wasn't already found */ 00057 if (SearchResult != TableFoundNode) 00058 { 00059 /* We're doing an allocation, sanity check */ 00060 ASSERT(Table->NumberGenericTableElements != (MAXULONG - 1)); 00061 00062 /* Allocate a node */ 00063 NewNode = Table->AllocateRoutine(Table, 00064 BufferSize + 00065 FIELD_OFFSET(TABLE_ENTRY_HEADER, 00066 UserData)); 00067 if (!NewNode) 00068 { 00069 /* No memory or other allocation error, fail */ 00070 if (NewElement) *NewElement = FALSE; 00071 return NULL; 00072 } 00073 00074 /* Data to return to user */ 00075 UserData = &((PTABLE_ENTRY_HEADER)NewNode)->UserData; 00076 00077 /* Insert the node in the tree */ 00078 RtlZeroMemory(NewNode, sizeof(RTL_BALANCED_LINKS)); 00079 RtlpInsertAvlTreeNode(Table, NewNode, NodeOrParent, SearchResult); 00080 00081 /* Copy user buffer */ 00082 RtlCopyMemory(UserData, Buffer, BufferSize); 00083 } 00084 else 00085 { 00086 /* Return the node we already found */ 00087 NewNode = NodeOrParent; 00088 UserData = &((PTABLE_ENTRY_HEADER)NewNode)->UserData; 00089 } 00090 00091 /* Return status */ 00092 if (NewElement) *NewElement = (SearchResult != TableFoundNode); 00093 00094 /* Return pointer to user data */ 00095 return UserData; 00096 } 00097 00098 /* 00099 * @implemented 00100 */ 00101 PVOID 00102 NTAPI 00103 RtlInsertElementGenericTableAvl(IN PRTL_AVL_TABLE Table, 00104 IN PVOID Buffer, 00105 IN ULONG BufferSize, 00106 OUT PBOOLEAN NewElement OPTIONAL) 00107 { 00108 PRTL_BALANCED_LINKS NodeOrParent = NULL; 00109 TABLE_SEARCH_RESULT Result; 00110 00111 /* Get the balanced links and table search result immediately */ 00112 Result = RtlpFindAvlTableNodeOrParent(Table, Buffer, &NodeOrParent); 00113 00114 /* Now call the routine to do the full insert */ 00115 return RtlInsertElementGenericTableFullAvl(Table, 00116 Buffer, 00117 BufferSize, 00118 NewElement, 00119 NodeOrParent, 00120 Result); 00121 } 00122 00123 /* 00124 * @implemented 00125 */ 00126 BOOLEAN 00127 NTAPI 00128 RtlIsGenericTableEmptyAvl(IN PRTL_AVL_TABLE Table) 00129 { 00130 /* If there's no elements, the table is empty */ 00131 return Table->NumberGenericTableElements == 0; 00132 } 00133 00134 /* 00135 * @implemented 00136 */ 00137 ULONG 00138 NTAPI 00139 RtlNumberGenericTableElementsAvl(IN PRTL_AVL_TABLE Table) 00140 { 00141 /* Return the element count */ 00142 return Table->NumberGenericTableElements; 00143 } 00144 00145 /* 00146 * @implemented 00147 */ 00148 PVOID 00149 NTAPI 00150 RtlLookupElementGenericTableFullAvl(IN PRTL_AVL_TABLE Table, 00151 IN PVOID Buffer, 00152 IN OUT PVOID *NodeOrParent, 00153 IN OUT TABLE_SEARCH_RESULT *SearchResult) 00154 { 00155 /* Find the node */ 00156 *SearchResult = RtlpFindAvlTableNodeOrParent(Table, 00157 Buffer, 00158 (PRTL_BALANCED_LINKS*)NodeOrParent); 00159 if (*SearchResult != TableFoundNode) return NULL; 00160 00161 /* Node found, return the user data */ 00162 return &((PTABLE_ENTRY_HEADER)*NodeOrParent)->UserData; 00163 } 00164 00165 /* 00166 * @implemented 00167 */ 00168 PVOID 00169 NTAPI 00170 RtlLookupElementGenericTableAvl(IN PRTL_AVL_TABLE Table, 00171 IN PVOID Buffer) 00172 { 00173 PRTL_BALANCED_LINKS NodeOrParent; 00174 TABLE_SEARCH_RESULT Lookup; 00175 00176 /* Call the full function */ 00177 return RtlLookupElementGenericTableFullAvl(Table, 00178 Buffer, 00179 (PVOID*)&NodeOrParent, 00180 &Lookup); 00181 } 00182 00183 /* 00184 * @implemented 00185 */ 00186 PVOID 00187 NTAPI 00188 RtlEnumerateGenericTableAvl(IN PRTL_AVL_TABLE Table, 00189 IN BOOLEAN Restart) 00190 { 00191 /* Reset the restart key if needed */ 00192 if (Restart) Table->RestartKey = NULL; 00193 00194 /* Call the full function */ 00195 return RtlEnumerateGenericTableWithoutSplayingAvl(Table, 00196 (PVOID*)&Table->RestartKey); 00197 } 00198 00199 /* 00200 * @implemented 00201 */ 00202 PVOID 00203 NTAPI 00204 RtlLookupFirstMatchingElementGenericTableAvl(IN PRTL_AVL_TABLE Table, 00205 IN PVOID Buffer, 00206 OUT PVOID *RestartKey) 00207 { 00208 PRTL_BALANCED_LINKS Node, PreviousNode; 00209 TABLE_SEARCH_RESULT SearchResult; 00210 RTL_GENERIC_COMPARE_RESULTS Result = GenericEqual; 00211 00212 /* Assume failure */ 00213 *RestartKey = NULL; 00214 00215 /* Find the node */ 00216 SearchResult = RtlpFindAvlTableNodeOrParent(Table, Buffer, &Node); 00217 if (SearchResult != TableFoundNode) return NULL; 00218 00219 /* Scan each predecessor until a match is found */ 00220 PreviousNode = Node; 00221 while (Result == GenericEqual) 00222 { 00223 /* Save the node */ 00224 Node = PreviousNode; 00225 00226 /* Get the predecessor */ 00227 PreviousNode = RtlRealPredecessorAvl(Node); 00228 if ((!PreviousNode) || (RtlParentAvl(PreviousNode) == PreviousNode)) break; 00229 00230 /* Check if this node matches */ 00231 Result = RtlpAvlCompareRoutine(Table, 00232 Buffer, 00233 &((PTABLE_ENTRY_HEADER)PreviousNode)-> 00234 UserData); 00235 } 00236 00237 /* Save the node as the restart key, and return its data */ 00238 *RestartKey = Node; 00239 return &((PTABLE_ENTRY_HEADER)Node)->UserData; 00240 } 00241 00242 /* 00243 * @unimplemented 00244 */ 00245 PVOID 00246 NTAPI 00247 RtlEnumerateGenericTableWithoutSplayingAvl(IN PRTL_AVL_TABLE Table, 00248 IN OUT PVOID *RestartKey) 00249 { 00250 PRTL_BALANCED_LINKS CurrentNode; 00251 00252 /* Skip an empty tree */ 00253 if (RtlIsGenericTableEmptyAvl(Table)) return NULL; 00254 00255 /* Check if we have a starting point */ 00256 if (!*RestartKey) 00257 { 00258 /* We'll have to find it, keep going until the leftmost child */ 00259 for (CurrentNode = RtlRightChildAvl(&Table->BalancedRoot); 00260 RtlLeftChildAvl(CurrentNode); 00261 CurrentNode = RtlLeftChildAvl(CurrentNode)); 00262 00263 /* Found it */ 00264 *RestartKey = CurrentNode; 00265 } 00266 else 00267 { 00268 /* We already had a child, keep going by getting its successor */ 00269 CurrentNode = RtlRealSuccessorAvl(*RestartKey); 00270 00271 /* If there was one, update the restart key */ 00272 if (CurrentNode) *RestartKey = CurrentNode; 00273 } 00274 00275 /* Return the node's data if it was found, otherwise return NULL */ 00276 if (CurrentNode) return &((PTABLE_ENTRY_HEADER)CurrentNode)->UserData; 00277 return NULL; 00278 } 00279 00280 /* 00281 * @unimplemented 00282 */ 00283 PVOID 00284 NTAPI 00285 RtlGetElementGenericTableAvl(IN PRTL_AVL_TABLE Table, 00286 IN ULONG I) 00287 { 00288 UNIMPLEMENTED; 00289 return NULL; 00290 } 00291 00292 /* 00293 * @implemented 00294 */ 00295 BOOLEAN 00296 NTAPI 00297 RtlDeleteElementGenericTableAvl(IN PRTL_AVL_TABLE Table, 00298 IN PVOID Buffer) 00299 { 00300 PRTL_BALANCED_LINKS Node; 00301 TABLE_SEARCH_RESULT SearchResult; 00302 00303 /* Find the node */ 00304 SearchResult = RtlpFindAvlTableNodeOrParent(Table, Buffer, &Node); 00305 if (SearchResult != TableFoundNode) return FALSE; 00306 00307 /* If this node was the key, update it */ 00308 if (Node == Table->RestartKey) Table->RestartKey = RtlRealPredecessorAvl(Node); 00309 00310 /* Do the delete */ 00311 Table->DeleteCount++; 00312 RtlpDeleteAvlTreeNode(Table, Node); 00313 Table->NumberGenericTableElements--; 00314 00315 /* Reset accounting */ 00316 Table->WhichOrderedElement = 0; 00317 Table->OrderedPointer = NULL; 00318 00319 /* Free the node's data */ 00320 Table->FreeRoutine(Table, Node); 00321 00322 /* It's done */ 00323 return TRUE; 00324 } 00325 00326 /* EOF */ Generated on Sat May 26 2012 04:35:20 for ReactOS by
1.7.6.1
|