Source code of Windows XP (NT5)
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
/*++
Copyright (c) 1997 - 98, Microsoft Corporation
Module Name:
avltrie.c
Abstract:
Contains routines for a best matching prefix lookup using an PATRICIA trie.
Author:
Chaitanya Kodeboyina (chaitk) 24-Jun-1998
Revision History:
--*/
#include "pattrie.h"
DWORD WINAPI CreateTable( IN USHORT MaxBytes, OUT HANDLE *Table ) { PPAT_TRIE NewTrie;
ASSERT(sizeof(PAT_CONTEXT) <= sizeof(LOOKUP_CONTEXT));
ASSERT(sizeof(PAT_LINKAGE) <= sizeof(DATA_ENTRY));
if (MaxBytes) { if (NewTrie = AllocNZeroMemory(sizeof(PAT_TRIE))) { NewTrie->MaxKeyBytes = (MaxBytes + sizeof(ULONG) - 1) / sizeof(ULONG);
#if _PROF_
NewTrie->MemoryInUse = sizeof(PAT_TRIE); #endif
*Table = NewTrie;
return NO_ERROR; } else // if (NewTrie == NULL)
{ *Table = NULL; return ERROR_NOT_ENOUGH_MEMORY; } } else // (if MaxBytes == 0)
{ return ERROR_INVALID_PARAMETER; } }
DWORD WINAPI SearchInTable( IN HANDLE Table, IN USHORT NumBits, IN PUCHAR KeyBits, OUT PLOOKUP_CONTEXT Context OPTIONAL, OUT PDATA_ENTRY *Data ) { PPAT_TRIE Trie; PPAT_NODE PrevNode; PPAT_NODE CurrNode; PPAT_NODE BestNode; PAT_CHILD NextChild; ULONG Key; #if _PROF_
UINT NumTravs1; UINT NumTravs2; #endif
Trie = Table;
#if DBG
if (NumBits > Trie->MaxKeyBytes * BITS_IN_BYTE) { *Data = NULL;
return ERROR_INVALID_PARAMETER; } #endif
#if _PROF_
NumTravs1 = 0; NumTravs2 = 0; #endif
//
// Go down the search trie matching the
// next set of bits in key as u do so
//
Key = RtlUlongByteSwap(KeyBits);
CurrNode = Trie->TrieRoot; PrevNode = NULL;
NextChild = LCHILD;
BestNode = NULL;
while (CurrNode) { #if _PROF_
NumTravs1++;
if (CurrNode->Data) { NumTravs2++; } #endif
}
return NO_ERROR; }
DWORD WINAPI BestMatchInTable( IN HANDLE Table, IN PUCHAR KeyBits, OUT PDATA_ENTRY *BestData ) { PPAT_TRIE Trie; PPAT_NODE CurrNode; PAT_CHILD NextChild; UINT BitsLeft; ULONG Key; ULONG CurrMask; ULONG CurrBits; #if _PROF_
UINT NumTravs1; UINT NumTravs2; #endif
*BestData = NULL;
Trie = Table;
BytesLeft = Trie->MaxKeyBytes;
#if _PROF_
NumTravs1 = 0; NumTravs2 = 0; #endif
//
// Go down trie after trie until all bits done
//
while (BytesLeft) { //
// Get the key for the next trie search
//
Key = RtlUlongByteSwap(*(ULONG *)KeyBits);
KeyBits += sizeof(ULONG);
BytesLeft -= sizeof(ULONG);
//
// Go down the current search trie
//
CurrNode = Trie->TrieRoot;
BitsLeft = sizeof(ULONG) * BITS_IN_BYTE;
Data = NULL;
while (CurrNode) { #if _PROF_
NumTravs1++;
if (CurrNode->Data) { NumTravs2++; } #endif
CurrMask = MaskBits(CurrNode->NumBits);
CurrBits = CurrNode->KeyBits;
//
// Try to match bits in the current node
//
if ((Key & CurrMask) != CurrBits) { // Failed to match this node
break; }
//
// Update node with best data so far
//
if (CurrNode->Data) { Data = CurrNode->Data; }
//
// Go down for more specific match
//
BitsLeft -= CurrNode->NumBits;
Key <<= CurrNode->NumBits;
NextChild = PickMostSigNBits(Key, 1);
CurrNode = CurrNode->Child[NextChild]; }
//
// Do we do a full match in this sub-trie
// & do we have more sub-trees to work on
//
if (BitsLeft || (!IS_SUB_TRIE(Data))) { *BestData = Data; break; }
Trie = GET_SUB_TRIE(*BestData); }
#if _PROF_
Print("Num Travs 1 = %5d, Travs 2 = %5d\n", NumTravs1, NumTravs2); #endif
return BitsLeft ? ERROR_NOT_FOUND : NO_ERROR; }
|