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.

206 lines
8.5 KiB

  1. /*
  2. * rhizome.h
  3. *
  4. * author: John R. Douceur
  5. * date: 28 April 1997
  6. *
  7. * This header file defines structures, function prototypes, and macros for
  8. * the rhizome database. The code is object-oriented C, transliterated from
  9. * a C++ implementation.
  10. *
  11. * The rhizome is a database that stores patterns containing wildcards.
  12. * Each pattern defines a set of keys that it matches; if a pattern contains
  13. * N wildcards, then it matches 2^N keys. Since each pattern can match
  14. * multiple keys, it is possible for a given key to match multiple patterns
  15. * in the database. The rhizome requires that all patterns stored therein
  16. * have a strict hierarchical interrelationship. Two patterns may match no
  17. * common keys (in which case the patterns are said to be independent), or
  18. * one pattern may match all the keys matched by a second pattern as well as
  19. * additonal keys (in which case the second pattern is said to be more general
  20. * than the first, and the first more specific than the second). The database
  21. * will not accept two patterns which match some keys in common but each of
  22. * which also matches additional keys that the other does not.
  23. *
  24. * The database can be searched for patterns that match a given search key.
  25. * When the database is searched for a given key, the most specifically
  26. * matching pattern is found. If no patterns in the database match the key,
  27. * an appropriate indication is returned.
  28. *
  29. * Because this code is C, rather than C++, it is not possible to hide as
  30. * much of the implementation from the client code as one might wish.
  31. * Nonetheless, there is an attempt to isolate the client from some of the
  32. * implementation details through the use of macros. Below is described each
  33. * of the functions and macros necessary to use the rhizome database.
  34. *
  35. */
  36. #ifndef _INC_RHIZOME
  37. #define _INC_RHIZOME
  38. #ifdef __cplusplus
  39. extern "C" {
  40. #endif
  41. /*
  42. * There are two basic structures employed: the RhizomeNode and the Rhizome.
  43. * Ideally, these would be completely hidden from the client, but the macro
  44. * GetReferenceFromPatternHandle requires knowledge of the structure's
  45. * definition. It is strongly urged that the client not directly refer to any
  46. * of the fields of either of these structures. To support the documentation
  47. * of the accompanying rhizome.c file, these structures are annotated with
  48. * internal comments, but these can be ignored by the reader who wishes only
  49. * to understand how to write client code for the rhizome.
  50. *
  51. * The client refers to a pattern by its PatternHandle. This is typedefed to
  52. * a pointer to RhizomeNode, but this fact should be ignored by the client,
  53. * since it is an implementation detail.
  54. *
  55. */
  56. //#include <stdlib.h>
  57. //#include <malloc.h>
  58. struct _RhizomeNode
  59. {
  60. // This structure is used for both branch nodes and leaf nodes. The two
  61. // are distinguished by the value of the pivot_bit field. For branch
  62. // nodes, pivot_bit < keybits, and for leaf nodes, pivot_bit == keybits.
  63. int pivot_bit; // for branch nodes, bit of key on which to branch
  64. union
  65. {
  66. struct // data for branch node
  67. {
  68. struct _RhizomeNode *children[2]; // pointers to children in search
  69. } branch;
  70. struct // data for leaf node
  71. {
  72. void *reference; // reference value supplied by client
  73. struct _RhizomeNode *godparent; // pointer to more general pattern
  74. } leaf;
  75. } udata;
  76. char cdata[1]; // space for storing value, mask, and imask fields
  77. };
  78. typedef struct _RhizomeNode RhizomeNode;
  79. struct _Rhizome
  80. {
  81. int keybits; // number of bits in key
  82. int keybytes; // number of bytes in key, calculated from keybits
  83. RhizomeNode *root; // root of search trie
  84. };
  85. typedef struct _Rhizome Rhizome;
  86. // The client uses PatternHandle to refer to patterns stored in the database.
  87. typedef RhizomeNode *PatternHandle;
  88. /*
  89. * The client interface to the rhizome is provided by five functions and two
  90. * macros. It is expected that the client will first instantiate a database,
  91. * either on the stack or the heap, and then insert patterns with corresponding
  92. * reference information into the database. When the client then performs a
  93. * search on a key, the client wishes to know which pattern most specifically
  94. * matches the key, and it ultimately wants the reference information
  95. * associated with the most specifically matching pattern.
  96. *
  97. */
  98. // A rhizome may be allocated on the stack simply by declaring a variable of
  99. // type Rhizome. To allocate it on the heap, the following macro returns a
  100. // pointer to a new Rhizome structure. If this macro is used, a corresponding
  101. // call to free() must be made to deallocate the structure from the heap.
  102. //
  103. //#define NEW_Rhizome ((Rhizome *)malloc(sizeof(Rhizome)))
  104. #define AllocateRhizome(_r) GpcAllocMem(&(_r), sizeof(Rhizome), RhizomeTag)
  105. #define FreeRhizome(_r) GpcFreeMem((_r), RhizomeTag)
  106. // Since this is not C++, the Rhizome structure is not self-constructing;
  107. // therefore, the following constructor code must be called on the Rhizome
  108. // structure after it is allocated. The argument keybits specifies the size
  109. // (in bits) of each pattern that will be stored in the database.
  110. //
  111. void
  112. constructRhizome(
  113. Rhizome *rhizome,
  114. int keybits);
  115. // Since this is not C++, the Rhizome structure is not self-destructing;
  116. // therefore, the following destructor code must be called on the Rhizome
  117. // structure before it is deallocated. However, if the client code can be
  118. // sure, based upon its usage of the database, that all patterns have been
  119. // removed before the structure is deallocated, then this function is
  120. // unnecessary.
  121. //
  122. void
  123. destructRhizome(
  124. Rhizome *rhizome);
  125. // Once the Rhizome structure has been allocated and constructed, patterns can
  126. // be inserted into the database. Each pattern is specified by a value and a
  127. // mask. Each bit of the mask determines whether the bit position is specified
  128. // or is a wildcard: A 1 in a mask bit indicates that the value of that bit is
  129. // specified by the pattern; a 0 indicates that the value of that bit is a
  130. // wildcard. If a mask bit is 1, then the corresponding bit in the value field
  131. // indicates the specified value of that bit. Value and mask fields are passed
  132. // as arrays of bytes.
  133. //
  134. // The client also specifies a reference value, as a void pointer, that it
  135. // wishes to associate with this pattern. When the pattern is installed, the
  136. // insertRhizome function returns a pointer to a PatternHandle. From the
  137. // PatternHandle can be gotten the reference value via the macro
  138. // GetReferenceFromPatternHandle.
  139. //
  140. // If the new pattern conflicts with a pattern already installed in the
  141. // database, meaning that the two patterns match some keys in common but each
  142. // also matches additional keys that the other does not, then the new pattern
  143. // is not inserted, and a value of 0 is returned as the PatternHandle.
  144. //
  145. PatternHandle
  146. insertRhizome(
  147. Rhizome *rhizome,
  148. char *value,
  149. char *mask,
  150. void *reference,
  151. ulong *status);
  152. // This function removes a pattern from the rhizome. The pattern is specified
  153. // by the PatternHandle that was returned by the insertRhizome function. No
  154. // checks are performed to insure that this is a valid handle, so the client
  155. // must discard the handle after it has called removeRhizome.
  156. //
  157. void
  158. removeRhizome(
  159. Rhizome *rhizome,
  160. PatternHandle phandle);
  161. // This function searches the database for the pattern that most specifically
  162. // matches the given key. The key is passed as an array of bytes. When the
  163. // most specific match is found, the PatternHandle of that matching pattern is
  164. // returned. From the PatternHandle can be gotten the reference value via the
  165. // macro GetReferenceFromPatternHandle. If no pattern in the database is found
  166. // to match the key, then a value of 0 is returned as the PatternHandle.
  167. //
  168. PatternHandle
  169. searchRhizome(
  170. Rhizome *rhizome,
  171. char *key);
  172. // To get the client-supplied reference value from a PatternHandle, the
  173. // following macro should be used. The client should not make assumptions
  174. // about the details of the RhizomeNode structure, nor should it even assume
  175. // that the PatternHandle is a pointer to a RhizomeNode.
  176. //
  177. #define GetReferenceFromPatternHandle(phandle) ((PatternHandle)phandle)->udata.leaf.reference
  178. #define GetKeyPtrFromPatternHandle(_r,phandle) (((PatternHandle)phandle)->cdata)
  179. #define GetMaskPtrFromPatternHandle(_r,phandle) (((PatternHandle)phandle)->cdata + (_r)->keybytes)
  180. #define GetKeySizeBytes(_r) ((_r)->keybytes)
  181. #ifdef __cplusplus
  182. }
  183. #endif
  184. #endif /* _INC_RHIZOME */