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.

426 lines
8.5 KiB

  1. /*++
  2. Copyright (c) 1997 - 98, Microsoft Corporation
  3. Module Name:
  4. avltrie.h
  5. Abstract:
  6. Contains interface for a best matching
  7. prefix lookup using an AVL trie.
  8. Author:
  9. Chaitanya Kodeboyina (chaitk) 24-Jun-1998
  10. Revision History:
  11. --*/
  12. #ifndef __ROUTING_AVLLOOKUP_H__
  13. #define __ROUTING_AVLLOOKUP_H__
  14. #include "lookup.h"
  15. #define Print printf
  16. #define BITS_IN_BYTE (UINT) 8
  17. //
  18. // Balance factor at an AVL node
  19. //
  20. #define LEFT -1
  21. #define EVEN 0
  22. #define RIGHT +1
  23. #define INVALID 100
  24. typedef INT AVL_BALANCE, *PAVL_BALANCE;
  25. //
  26. // A node in the AVL trie
  27. //
  28. typedef struct _AVL_NODE *PAVL_NODE;
  29. // Disable warnings for unnamed structs
  30. #pragma warning(disable : 4201)
  31. typedef struct _AVL_NODE
  32. {
  33. PAVL_NODE Prefix; // Node with the next best prefix
  34. PAVL_NODE Parent; // Parent of this AVL trie node
  35. struct
  36. {
  37. PAVL_NODE LChild;
  38. union
  39. {
  40. PAVL_NODE Child[1]; // Child[-1] = Left, Child[1] = Right
  41. PVOID Data; // Opaque Pointer to data in the node
  42. };
  43. PAVL_NODE RChild;
  44. };
  45. AVL_BALANCE Balance; // Balance factor at this node
  46. USHORT NumBits; // Actual number of bits in key
  47. UCHAR KeyBits[1]; // Value of key bits to compare
  48. }
  49. AVL_NODE;
  50. #pragma warning(default : 4201)
  51. //
  52. // AVL trie with prefix matching
  53. //
  54. typedef struct _AVL_TRIE
  55. {
  56. PAVL_NODE TrieRoot; // Pointer to the AVL trie
  57. UINT MaxKeyBytes; // Max num of bytes in key
  58. UINT NumNodes; // Number of nodes in trie
  59. #if PROF
  60. ULONG MemoryInUse; // Total memory in use now
  61. UINT NumAllocs; // Num of total allocations
  62. UINT NumFrees; // Num of total free allocs
  63. UINT NumInsertions; // Num of total insertions
  64. UINT NumDeletions; // Num of total deletions
  65. UINT NumSingleRots; // Num of single rotations
  66. UINT NumDoubleRots; // Num of double rotations
  67. #endif
  68. }
  69. AVL_TRIE, *PAVL_TRIE;
  70. //
  71. // Lookup context for an AVL trie
  72. //
  73. typedef struct _AVL_CONTEXT
  74. {
  75. PVOID BestNode; // Node with best the matching prefix
  76. PVOID InsPoint; // Node to which new node is attached
  77. AVL_BALANCE InsChild; // Node should attached as this child
  78. }
  79. AVL_CONTEXT, *PAVL_CONTEXT;
  80. //
  81. // Linkage Info Kept in Data
  82. //
  83. typedef struct _AVL_LINKAGE
  84. {
  85. PAVL_NODE NodePtr; // Back pointer to the owning node
  86. }
  87. AVL_LINKAGE, *PAVL_LINKAGE;
  88. #define SET_NODEPTR_INTO_DATA(Data, Node) ((PAVL_LINKAGE)Data)->NodePtr = Node
  89. #define GET_NODEPTR_FROM_DATA(Data) ((PAVL_LINKAGE)Data)->NodePtr
  90. //
  91. // Key Compare/Copy inlines
  92. //
  93. INT
  94. __inline
  95. CompareFullKeys(
  96. IN PUCHAR Key1,
  97. IN PUCHAR Key2,
  98. IN UINT NumBytes
  99. )
  100. {
  101. UINT Count;
  102. #if _OPT_
  103. ULONG Temp1;
  104. ULONG Temp2;
  105. if (NumBytes == sizeof(ULONG))
  106. {
  107. Temp1 = RtlUlongByteSwap(*(ULONG *)Key1);
  108. Temp2 = RtlUlongByteSwap(*(ULONG *)Key2);
  109. if (Temp1 > Temp2)
  110. {
  111. return +1;
  112. }
  113. if (Temp1 < Temp2)
  114. {
  115. return -1;
  116. }
  117. return 0;
  118. }
  119. #endif
  120. Count = NumBytes;
  121. if (!Count)
  122. {
  123. return 0;
  124. }
  125. Count--;
  126. while (Count && (*Key1 == *Key2))
  127. {
  128. Key1++;
  129. Key2++;
  130. Count--;
  131. }
  132. return *Key1 - *Key2;
  133. }
  134. INT
  135. __inline
  136. ComparePartialKeys(
  137. IN PUCHAR Key1,
  138. IN PUCHAR Key2,
  139. IN USHORT NumBits
  140. )
  141. {
  142. UINT Count;
  143. #if _OPT_
  144. ULONG Temp1;
  145. ULONG Temp2;
  146. if (NumBits <= sizeof(ULONG) * BITS_IN_BYTE)
  147. {
  148. Count = sizeof(ULONG) * BITS_IN_BYTE - NumBits;
  149. Temp1 = RtlUlongByteSwap(*(ULONG *)Key1) >> Count;
  150. Temp2 = RtlUlongByteSwap(*(ULONG *)Key2) >> Count;
  151. if (Temp1 > Temp2)
  152. {
  153. return +1;
  154. }
  155. if (Temp1 < Temp2)
  156. {
  157. return -1;
  158. }
  159. return 0;
  160. }
  161. #endif
  162. Count = NumBits / BITS_IN_BYTE;
  163. while (Count && *Key1 == *Key2)
  164. {
  165. Key1++;
  166. Key2++;
  167. Count--;
  168. }
  169. if (Count)
  170. {
  171. return (*Key1 - *Key2);
  172. }
  173. Count = NumBits % BITS_IN_BYTE;
  174. if (Count)
  175. {
  176. Count = BITS_IN_BYTE - Count;
  177. return (*Key1 >> Count) - (*Key2 >> Count);
  178. }
  179. return 0;
  180. }
  181. VOID
  182. __inline
  183. CopyFullKeys(
  184. OUT PUCHAR KeyDst,
  185. IN PUCHAR KeySrc,
  186. IN UINT NumBytes
  187. )
  188. {
  189. UINT Count = NumBytes;
  190. while (Count--)
  191. {
  192. *KeyDst++ = *KeySrc++;
  193. }
  194. return;
  195. }
  196. VOID
  197. __inline
  198. CopyPartialKeys(
  199. OUT PUCHAR KeyDst,
  200. IN PUCHAR KeySrc,
  201. IN USHORT NumBits
  202. )
  203. {
  204. UINT Count = (NumBits + BITS_IN_BYTE - 1) / BITS_IN_BYTE;
  205. while (Count--)
  206. {
  207. *KeyDst++ = *KeySrc++;
  208. }
  209. return;
  210. }
  211. //
  212. // Node Creation and Deletion inlines
  213. //
  214. PAVL_NODE
  215. __inline
  216. CreateTrieNode(
  217. IN PAVL_TRIE Trie,
  218. IN USHORT NumBits,
  219. IN PUCHAR KeyBits,
  220. IN PAVL_NODE Prefix,
  221. IN PLOOKUP_LINKAGE Data
  222. )
  223. {
  224. PAVL_NODE NewNode;
  225. UINT NumBytes;
  226. NumBytes = FIELD_OFFSET(AVL_NODE, KeyBits) + Trie->MaxKeyBytes;
  227. NewNode = AllocNZeroMemory(NumBytes);
  228. if (NewNode)
  229. {
  230. NewNode->Prefix = Prefix;
  231. NewNode->Data = Data;
  232. SET_NODEPTR_INTO_DATA(Data, NewNode);
  233. NewNode->Balance = EVEN;
  234. NewNode->NumBits = NumBits;
  235. CopyPartialKeys(NewNode->KeyBits,
  236. KeyBits,
  237. NumBits);
  238. Trie->NumNodes++;
  239. #if PROF
  240. Trie->NumAllocs++;
  241. Trie->MemoryInUse += NumBytes;
  242. #endif
  243. }
  244. return NewNode;
  245. }
  246. VOID
  247. __inline
  248. DestroyTrieNode(
  249. IN PAVL_TRIE Trie,
  250. IN PAVL_NODE Node
  251. )
  252. {
  253. UINT NumBytes;
  254. SET_NODEPTR_INTO_DATA(Node->Data, NULL);
  255. NumBytes = FIELD_OFFSET(AVL_NODE, KeyBits) + Trie->MaxKeyBytes;
  256. Trie->NumNodes--;
  257. #if PROF
  258. Trie->NumFrees++;
  259. Trie->MemoryInUse -= NumBytes;
  260. #endif
  261. FreeMemory(Node);
  262. }
  263. //
  264. // Helper Prototypes
  265. //
  266. VOID
  267. BalanceAfterInsert(
  268. IN PAVL_TRIE Trie,
  269. IN PAVL_NODE Node,
  270. IN AVL_BALANCE Longer
  271. );
  272. VOID
  273. BalanceAfterDelete(
  274. IN PAVL_TRIE Trie,
  275. IN PAVL_NODE Node,
  276. IN AVL_BALANCE Shorter
  277. );
  278. VOID
  279. SingleRotate(
  280. IN PAVL_TRIE Trie,
  281. IN PAVL_NODE UnbalNode,
  282. IN AVL_BALANCE Direction,
  283. OUT PAVL_NODE *BalancedNode
  284. );
  285. VOID
  286. DoubleRotate(
  287. IN PAVL_TRIE Trie,
  288. IN PAVL_NODE UnbalNode,
  289. IN AVL_BALANCE Direction,
  290. OUT PAVL_NODE *BalancedNode
  291. );
  292. VOID
  293. SwapWithSuccessor(
  294. IN PAVL_TRIE Trie,
  295. IN OUT PAVL_CONTEXT Context
  296. );
  297. VOID
  298. AdjustPrefixes(
  299. IN PAVL_TRIE Trie,
  300. IN PAVL_NODE OldNode,
  301. IN PAVL_NODE NewNode,
  302. IN PAVL_NODE TheNode,
  303. IN PLOOKUP_CONTEXT Context
  304. );
  305. DWORD
  306. CheckSubTrie(
  307. IN PAVL_NODE Node,
  308. OUT PUSHORT Depth
  309. );
  310. DWORD
  311. CheckTrieNode(
  312. IN PAVL_NODE Node,
  313. IN USHORT LDepth,
  314. IN USHORT RDepth
  315. );
  316. VOID
  317. DumpSubTrie(
  318. IN PAVL_NODE Node
  319. );
  320. VOID
  321. DumpTrieNode(
  322. IN PAVL_NODE Node
  323. );
  324. #endif //__ROUTING_AVLLOOKUP_H__