ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

avltable.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.