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.

257 lines
4.7 KiB

  1. /*++
  2. Copyright (c) 1997 - 98, Microsoft Corporation
  3. Module Name:
  4. avltrie.c
  5. Abstract:
  6. Contains routines for a best matching
  7. prefix lookup using an PATRICIA trie.
  8. Author:
  9. Chaitanya Kodeboyina (chaitk) 24-Jun-1998
  10. Revision History:
  11. --*/
  12. #include "pattrie.h"
  13. DWORD
  14. WINAPI
  15. CreateTable(
  16. IN USHORT MaxBytes,
  17. OUT HANDLE *Table
  18. )
  19. {
  20. PPAT_TRIE NewTrie;
  21. ASSERT(sizeof(PAT_CONTEXT) <= sizeof(LOOKUP_CONTEXT));
  22. ASSERT(sizeof(PAT_LINKAGE) <= sizeof(DATA_ENTRY));
  23. if (MaxBytes)
  24. {
  25. if (NewTrie = AllocNZeroMemory(sizeof(PAT_TRIE)))
  26. {
  27. NewTrie->MaxKeyBytes = (MaxBytes + sizeof(ULONG) - 1) / sizeof(ULONG);
  28. #if _PROF_
  29. NewTrie->MemoryInUse = sizeof(PAT_TRIE);
  30. #endif
  31. *Table = NewTrie;
  32. return NO_ERROR;
  33. }
  34. else // if (NewTrie == NULL)
  35. {
  36. *Table = NULL;
  37. return ERROR_NOT_ENOUGH_MEMORY;
  38. }
  39. }
  40. else // (if MaxBytes == 0)
  41. {
  42. return ERROR_INVALID_PARAMETER;
  43. }
  44. }
  45. DWORD
  46. WINAPI
  47. SearchInTable(
  48. IN HANDLE Table,
  49. IN USHORT NumBits,
  50. IN PUCHAR KeyBits,
  51. OUT PLOOKUP_CONTEXT Context OPTIONAL,
  52. OUT PDATA_ENTRY *Data
  53. )
  54. {
  55. PPAT_TRIE Trie;
  56. PPAT_NODE PrevNode;
  57. PPAT_NODE CurrNode;
  58. PPAT_NODE BestNode;
  59. PAT_CHILD NextChild;
  60. ULONG Key;
  61. #if _PROF_
  62. UINT NumTravs1;
  63. UINT NumTravs2;
  64. #endif
  65. Trie = Table;
  66. #if DBG
  67. if (NumBits > Trie->MaxKeyBytes * BITS_IN_BYTE)
  68. {
  69. *Data = NULL;
  70. return ERROR_INVALID_PARAMETER;
  71. }
  72. #endif
  73. #if _PROF_
  74. NumTravs1 = 0;
  75. NumTravs2 = 0;
  76. #endif
  77. //
  78. // Go down the search trie matching the
  79. // next set of bits in key as u do so
  80. //
  81. Key = RtlUlongByteSwap(KeyBits);
  82. CurrNode = Trie->TrieRoot;
  83. PrevNode = NULL;
  84. NextChild = LCHILD;
  85. BestNode = NULL;
  86. while (CurrNode)
  87. {
  88. #if _PROF_
  89. NumTravs1++;
  90. if (CurrNode->Data)
  91. {
  92. NumTravs2++;
  93. }
  94. #endif
  95. }
  96. return NO_ERROR;
  97. }
  98. DWORD
  99. WINAPI
  100. BestMatchInTable(
  101. IN HANDLE Table,
  102. IN PUCHAR KeyBits,
  103. OUT PDATA_ENTRY *BestData
  104. )
  105. {
  106. PPAT_TRIE Trie;
  107. PPAT_NODE CurrNode;
  108. PAT_CHILD NextChild;
  109. UINT BitsLeft;
  110. ULONG Key;
  111. ULONG CurrMask;
  112. ULONG CurrBits;
  113. #if _PROF_
  114. UINT NumTravs1;
  115. UINT NumTravs2;
  116. #endif
  117. *BestData = NULL;
  118. Trie = Table;
  119. BytesLeft = Trie->MaxKeyBytes;
  120. #if _PROF_
  121. NumTravs1 = 0;
  122. NumTravs2 = 0;
  123. #endif
  124. //
  125. // Go down trie after trie until all bits done
  126. //
  127. while (BytesLeft)
  128. {
  129. //
  130. // Get the key for the next trie search
  131. //
  132. Key = RtlUlongByteSwap(*(ULONG *)KeyBits);
  133. KeyBits += sizeof(ULONG);
  134. BytesLeft -= sizeof(ULONG);
  135. //
  136. // Go down the current search trie
  137. //
  138. CurrNode = Trie->TrieRoot;
  139. BitsLeft = sizeof(ULONG) * BITS_IN_BYTE;
  140. Data = NULL;
  141. while (CurrNode)
  142. {
  143. #if _PROF_
  144. NumTravs1++;
  145. if (CurrNode->Data)
  146. {
  147. NumTravs2++;
  148. }
  149. #endif
  150. CurrMask = MaskBits(CurrNode->NumBits);
  151. CurrBits = CurrNode->KeyBits;
  152. //
  153. // Try to match bits in the current node
  154. //
  155. if ((Key & CurrMask) != CurrBits)
  156. {
  157. // Failed to match this node
  158. break;
  159. }
  160. //
  161. // Update node with best data so far
  162. //
  163. if (CurrNode->Data)
  164. {
  165. Data = CurrNode->Data;
  166. }
  167. //
  168. // Go down for more specific match
  169. //
  170. BitsLeft -= CurrNode->NumBits;
  171. Key <<= CurrNode->NumBits;
  172. NextChild = PickMostSigNBits(Key, 1);
  173. CurrNode = CurrNode->Child[NextChild];
  174. }
  175. //
  176. // Do we do a full match in this sub-trie
  177. // & do we have more sub-trees to work on
  178. //
  179. if (BitsLeft || (!IS_SUB_TRIE(Data)))
  180. {
  181. *BestData = Data;
  182. break;
  183. }
  184. Trie = GET_SUB_TRIE(*BestData);
  185. }
  186. #if _PROF_
  187. Print("Num Travs 1 = %5d, Travs 2 = %5d\n",
  188. NumTravs1,
  189. NumTravs2);
  190. #endif
  191. return BitsLeft ? ERROR_NOT_FOUND : NO_ERROR;
  192. }