Changeset View
Changeset View
Standalone View
Standalone View
share/man/man3/tree.3
| Show First 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | |||||
| .Nm RB_FOREACH , | .Nm RB_FOREACH , | ||||
| .Nm RB_FOREACH_FROM , | .Nm RB_FOREACH_FROM , | ||||
| .Nm RB_FOREACH_SAFE , | .Nm RB_FOREACH_SAFE , | ||||
| .Nm RB_FOREACH_REVERSE , | .Nm RB_FOREACH_REVERSE , | ||||
| .Nm RB_FOREACH_REVERSE_FROM , | .Nm RB_FOREACH_REVERSE_FROM , | ||||
| .Nm RB_FOREACH_REVERSE_SAFE , | .Nm RB_FOREACH_REVERSE_SAFE , | ||||
| .Nm RB_INIT , | .Nm RB_INIT , | ||||
| .Nm RB_INSERT , | .Nm RB_INSERT , | ||||
| .Nm RB_REMOVE | .Nm RB_REMOVE , | ||||
| .Nm ARB_PROTOTYPE , | |||||
| .Nm ARB_PROTOTYPE_STATIC , | |||||
| .Nm ARB_PROTOTYPE_INSERT , | |||||
| .Nm ARB_PROTOTYPE_INSERT_COLOR , | |||||
| .Nm ARB_PROTOTYPE_REMOVE , | |||||
| .Nm ARB_PROTOTYPE_REMOVE_COLOR , | |||||
| .Nm ARB_PROTOTYPE_FIND , | |||||
| .Nm ARB_PROTOTYPE_NFIND , | |||||
| .Nm ARB_PROTOTYPE_NEXT , | |||||
| .Nm ARB_PROTOTYPE_PREV , | |||||
| .Nm ARB_PROTOTYPE_MINMAX , | |||||
| .Nm ARB_GENERATE , | |||||
| .Nm ARB_GENERATE_STATIC , | |||||
| .Nm ARB_GENERATE_INSERT , | |||||
| .Nm ARB_GENERATE_INSERT_COLOR , | |||||
| .Nm ARB_GENERATE_REMOVE , | |||||
| .Nm ARB_GENERATE_REMOVE_COLOR , | |||||
| .Nm ARB_GENERATE_FIND , | |||||
| .Nm ARB_GENERATE_NFIND , | |||||
| .Nm ARB_GENERATE_NEXT , | |||||
| .Nm ARB_GENERATE_PREV , | |||||
| .Nm ARB_GENERATE_MINMAX , | |||||
| .Nm ARB8_ENTRY , | |||||
| .Nm ARB16_ENTRY , | |||||
| .Nm ARB32_ENTRY , | |||||
| .Nm ARB8_HEAD , | |||||
| .Nm ARB16_HEAD , | |||||
| .Nm ARB32_HEAD , | |||||
| .Nm ARB_INITIALIZER , | |||||
| .Nm ARB_ROOT , | |||||
| .Nm ARB_EMPTY , | |||||
| .Nm ARB_FULL , | |||||
| .Nm ARB_CURNODES , | |||||
| .Nm ARB_MAXNODES , | |||||
| .Nm ARB_NEXT , | |||||
| .Nm ARB_PREV , | |||||
| .Nm ARB_MIN , | |||||
| .Nm ARB_MAX , | |||||
| .Nm ARB_FIND , | |||||
| .Nm ARB_NFIND , | |||||
| .Nm ARB_LEFT , | |||||
| .Nm ARB_LEFTIDX , | |||||
| .Nm ARB_RIGHT , | |||||
| .Nm ARB_RIGHTIDX , | |||||
| .Nm ARB_PARENT , | |||||
| .Nm ARB_PARENTIDX , | |||||
| .Nm ARB_GETFREE , | |||||
| .Nm ARB_FREEIDX , | |||||
| .Nm ARB_FOREACH , | |||||
| .Nm ARB_FOREACH_FROM , | |||||
| .Nm ARB_FOREACH_SAFE , | |||||
| .Nm ARB_FOREACH_REVERSE , | |||||
| .Nm ARB_FOREACH_REVERSE_FROM , | |||||
| .Nm ARB_FOREACH_REVERSE_SAFE , | |||||
| .Nm ARB_INIT , | |||||
| .Nm ARB_INSERT , | |||||
| .Nm ARB_REMOVE | |||||
| .Nd "implementations of splay and red-black trees" | .Nd "implementations of splay and red-black trees" | ||||
| .Sh SYNOPSIS | .Sh SYNOPSIS | ||||
| .In sys/tree.h | .In sys/tree.h | ||||
| .Fn SPLAY_PROTOTYPE NAME TYPE FIELD CMP | .Fn SPLAY_PROTOTYPE NAME TYPE FIELD CMP | ||||
| .Fn SPLAY_GENERATE NAME TYPE FIELD CMP | .Fn SPLAY_GENERATE NAME TYPE FIELD CMP | ||||
| .Fn SPLAY_ENTRY TYPE | .Fn SPLAY_ENTRY TYPE | ||||
| .Fn SPLAY_HEAD HEADNAME TYPE | .Fn SPLAY_HEAD HEADNAME TYPE | ||||
| .Ft "struct TYPE *" | .Ft "struct TYPE *" | ||||
| Show All 15 Lines | |||||
| .Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME" | .Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME" | ||||
| .Fn SPLAY_FOREACH VARNAME NAME "SPLAY_HEAD *head" | .Fn SPLAY_FOREACH VARNAME NAME "SPLAY_HEAD *head" | ||||
| .Ft void | .Ft void | ||||
| .Fn SPLAY_INIT "SPLAY_HEAD *head" | .Fn SPLAY_INIT "SPLAY_HEAD *head" | ||||
| .Ft "struct TYPE *" | .Ft "struct TYPE *" | ||||
| .Fn SPLAY_INSERT NAME "SPLAY_HEAD *head" "struct TYPE *elm" | .Fn SPLAY_INSERT NAME "SPLAY_HEAD *head" "struct TYPE *elm" | ||||
| .Ft "struct TYPE *" | .Ft "struct TYPE *" | ||||
| .Fn SPLAY_REMOVE NAME "SPLAY_HEAD *head" "struct TYPE *elm" | .Fn SPLAY_REMOVE NAME "SPLAY_HEAD *head" "struct TYPE *elm" | ||||
| .Fn RB_PROTOTYPE NAME TYPE FIELD CMP | .Fn (A)RB_PROTOTYPE NAME TYPE FIELD CMP | ||||
| .Fn RB_PROTOTYPE_STATIC NAME TYPE FIELD CMP | .Fn (A)RB_PROTOTYPE_STATIC NAME TYPE FIELD CMP | ||||
| .Fn RB_PROTOTYPE_INSERT NAME TYPE ATTR | .Fn (A)RB_PROTOTYPE_INSERT NAME TYPE ATTR | ||||
| .Fn RB_PROTOTYPE_INSERT_COLOR NAME TYPE ATTR | .Fn (A)RB_PROTOTYPE_INSERT_COLOR NAME TYPE ATTR | ||||
| .Fn RB_PROTOTYPE_REMOVE NAME TYPE ATTR | .Fn (A)RB_PROTOTYPE_REMOVE NAME TYPE ATTR | ||||
| .Fn RB_PROTOTYPE_REMOVE_COLOR NAME TYPE ATTR | .Fn (A)RB_PROTOTYPE_REMOVE_COLOR NAME TYPE ATTR | ||||
| .Fn RB_PROTOTYPE_FIND NAME TYPE ATTR | .Fn (A)RB_PROTOTYPE_FIND NAME TYPE ATTR | ||||
| .Fn RB_PROTOTYPE_NFIND NAME TYPE ATTR | .Fn (A)RB_PROTOTYPE_NFIND NAME TYPE ATTR | ||||
| .Fn RB_PROTOTYPE_NEXT NAME TYPE ATTR | .Fn (A)RB_PROTOTYPE_NEXT NAME TYPE ATTR | ||||
| .Fn RB_PROTOTYPE_PREV NAME TYPE ATTR | .Fn (A)RB_PROTOTYPE_PREV NAME TYPE ATTR | ||||
| .Fn RB_PROTOTYPE_MINMAX NAME TYPE ATTR | .Fn (A)RB_PROTOTYPE_MINMAX NAME TYPE ATTR | ||||
| .Fn RB_GENERATE NAME TYPE FIELD CMP | .Fn (A)RB_GENERATE NAME TYPE FIELD CMP | ||||
| .Fn RB_GENERATE_STATIC NAME TYPE FIELD CMP | .Fn (A)RB_GENERATE_STATIC NAME TYPE FIELD CMP | ||||
| .Fn RB_GENERATE_INSERT NAME TYPE FIELD CMP ATTR | .Fn (A)RB_GENERATE_INSERT NAME TYPE FIELD CMP ATTR | ||||
| .Fn RB_GENERATE_INSERT_COLOR NAME TYPE FIELD ATTR | .Fn (A)RB_GENERATE_INSERT_COLOR NAME TYPE FIELD ATTR | ||||
| .Fn RB_GENERATE_REMOVE NAME TYPE FIELD ATTR | .Fn (A)RB_GENERATE_REMOVE NAME TYPE FIELD ATTR | ||||
| .Fn RB_GENERATE_REMOVE_COLOR NAME TYPE FIELD ATTR | .Fn (A)RB_GENERATE_REMOVE_COLOR NAME TYPE FIELD ATTR | ||||
| .Fn RB_GENERATE_FIND NAME TYPE FIELD CMP ATTR | .Fn (A)RB_GENERATE_FIND NAME TYPE FIELD CMP ATTR | ||||
| .Fn RB_GENERATE_NFIND NAME TYPE FIELD CMP ATTR | .Fn (A)RB_GENERATE_NFIND NAME TYPE FIELD CMP ATTR | ||||
| .Fn RB_GENERATE_NEXT NAME TYPE FIELD ATTR | .Fn (A)RB_GENERATE_NEXT NAME TYPE FIELD ATTR | ||||
| .Fn RB_GENERATE_PREV NAME TYPE FIELD ATTR | .Fn (A)RB_GENERATE_PREV NAME TYPE FIELD ATTR | ||||
| .Fn RB_GENERATE_MINMAX NAME TYPE FIELD ATTR | .Fn (A)RB_GENERATE_MINMAX NAME TYPE FIELD ATTR | ||||
| .Fn RB_ENTRY TYPE | .Fn RB_ENTRY TYPE | ||||
| .Fn RB_HEAD HEADNAME TYPE | .Fn RB_HEAD HEADNAME TYPE | ||||
| .Fn RB_INITIALIZER "RB_HEAD *head" | .Fn RB_INITIALIZER "RB_HEAD *head" | ||||
| .Fn ARB<8|16|32>_ENTRY | |||||
| .Fn ARB<8|16|32>_HEAD HEADNAME TYPE | |||||
| .Fn ARB_INITIALIZER "ARB_HEAD *head" "int<8|16|32>_t maxnodes" | |||||
| .Ft "struct TYPE *" | .Ft "struct TYPE *" | ||||
| .Fn RB_ROOT "RB_HEAD *head" | .Fn (A)RB_ROOT "(A)RB_HEAD *head" | ||||
| .Ft "bool" | .Ft "bool" | ||||
| .Fn RB_EMPTY "RB_HEAD *head" | .Fn (A)RB_EMPTY "(A)RB_HEAD *head" | ||||
| .Ft "bool" | |||||
| .Fn ARB_FULL "ARB_HEAD *head" | |||||
| .Ft "int<8|16|32>_t" | |||||
| .Fn ARB_CURNODES "ARB_HEAD *head" | |||||
| .Ft "int<8|16|32>_t" | |||||
| .Fn ARB_MAXNODES "ARB_HEAD *head" | |||||
| .Ft "struct TYPE *" | .Ft "struct TYPE *" | ||||
| .Fn RB_NEXT NAME "RB_HEAD *head" "struct TYPE *elm" | .Fn (A)RB_NEXT NAME "(A)RB_HEAD *head" "struct TYPE *elm" | ||||
| .Ft "struct TYPE *" | .Ft "struct TYPE *" | ||||
| .Fn RB_PREV NAME "RB_HEAD *head" "struct TYPE *elm" | .Fn (A)RB_PREV NAME "(A)RB_HEAD *head" "struct TYPE *elm" | ||||
| .Ft "struct TYPE *" | .Ft "struct TYPE *" | ||||
| .Fn RB_MIN NAME "RB_HEAD *head" | .Fn (A)RB_MIN NAME "(A)RB_HEAD *head" | ||||
| .Ft "struct TYPE *" | .Ft "struct TYPE *" | ||||
| .Fn RB_MAX NAME "RB_HEAD *head" | .Fn (A)RB_MAX NAME "(A)RB_HEAD *head" | ||||
| .Ft "struct TYPE *" | .Ft "struct TYPE *" | ||||
| .Fn RB_FIND NAME "RB_HEAD *head" "struct TYPE *elm" | .Fn (A)RB_FIND NAME "(A)RB_HEAD *head" "struct TYPE *elm" | ||||
| .Ft "struct TYPE *" | .Ft "struct TYPE *" | ||||
| .Fn RB_NFIND NAME "RB_HEAD *head" "struct TYPE *elm" | .Fn (A)RB_NFIND NAME "(A)RB_HEAD *head" "struct TYPE *elm" | ||||
| .Ft "struct TYPE *" | .Ft "struct TYPE *" | ||||
| .Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME" | .Fn (A)RB_LEFT "struct TYPE *elm" "(A)RB_ENTRY NAME" | ||||
| .Ft "int<8|16|32>_t" | |||||
| .Fn ARB_LEFTIDX "struct TYPE *elm" "ARB_ENTRY NAME" | |||||
| .Ft "struct TYPE *" | .Ft "struct TYPE *" | ||||
| .Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME" | .Fn (A)RB_RIGHT "struct TYPE *elm" "(A)RB_ENTRY NAME" | ||||
| .Ft "int<8|16|32>_t" | |||||
| .Fn ARB_RIGHTIDX "struct TYPE *elm" "ARB_ENTRY NAME" | |||||
| .Ft "struct TYPE *" | .Ft "struct TYPE *" | ||||
| .Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME" | .Fn (A)RB_PARENT "struct TYPE *elm" "(A)RB_ENTRY NAME" | ||||
| .Fn RB_FOREACH VARNAME NAME "RB_HEAD *head" | .Ft "int<8|16|32>_t" | ||||
| .Fn RB_FOREACH_FROM "VARNAME" "NAME" "POS_VARNAME" | .Fn ARB_PARENTIDX "struct TYPE *elm" "ARB_ENTRY NAME" | ||||
| .Fn RB_FOREACH_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME" | .Ft "struct TYPE *" | ||||
| .Fn RB_FOREACH_REVERSE VARNAME NAME "RB_HEAD *head" | .Fn ARB_GETFREE "ARB_HEAD *head" | ||||
| .Fn RB_FOREACH_REVERSE_FROM "VARNAME" "NAME" "POS_VARNAME" | .Ft "int<8|16|32>_t" | ||||
| .Fn RB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME" | .Fn ARB_FREEIDX "ARB_HEAD *head" | ||||
| .Fn (A)RB_FOREACH VARNAME NAME "(A)RB_HEAD *head" | |||||
| .Fn (A)RB_FOREACH_FROM "VARNAME" "NAME" "POS_VARNAME" | |||||
| .Fn (A)RB_FOREACH_SAFE "VARNAME" "NAME" "(A)RB_HEAD *head" "TEMP_VARNAME" | |||||
| .Fn (A)RB_FOREACH_REVERSE VARNAME NAME "(A)RB_HEAD *head" | |||||
| .Fn (A)RB_FOREACH_REVERSE_FROM "VARNAME" "NAME" "POS_VARNAME" | |||||
| .Fn (A)RB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "(A)RB_HEAD *head" "TEMP_VARNAME" | |||||
| .Ft void | .Ft void | ||||
| .Fn RB_INIT "RB_HEAD *head" | .Fn RB_INIT "RB_HEAD *head" | ||||
| .Ft void | |||||
| .Fn ARB_INIT "ARB_HEAD *head" "int<8|16|32>_t maxnodes" | |||||
| .Ft "struct TYPE *" | .Ft "struct TYPE *" | ||||
| .Fn RB_INSERT NAME "RB_HEAD *head" "struct TYPE *elm" | .Fn (A)RB_INSERT NAME "(A)RB_HEAD *head" "struct TYPE *elm" | ||||
| .Ft "struct TYPE *" | .Ft "struct TYPE *" | ||||
| .Fn RB_REMOVE NAME "RB_HEAD *head" "struct TYPE *elm" | .Fn (A)RB_REMOVE NAME "(A)RB_HEAD *head" "struct TYPE *elm" | ||||
| .Sh DESCRIPTION | .Sh DESCRIPTION | ||||
| These macros define data structures for different types of trees: | These macros define data structures for three different types of trees: | ||||
| splay trees and red-black trees. | splay trees (macros with the | ||||
| .Dv SPLAY_ | |||||
| prefix), red-black trees (the | |||||
| .Dv RB_ | |||||
| prefix), and array-based red-black trees (the | |||||
| .Dv ARB_ | |||||
| prefix). | |||||
| The last one use a single, continuous chunk of memory, and are useful | |||||
| e.g., when the tree needs to be trasferred between userspace and kernel. | |||||
| .Pp | .Pp | ||||
| In the macro definitions, | In the macro definitions, | ||||
| .Fa TYPE | .Fa TYPE | ||||
| is the name tag of a user defined structure that must contain a field of type | is the name tag of a user defined structure that must contain a field of type | ||||
| .Vt SPLAY_ENTRY , | .Vt SPLAY_ENTRY , | ||||
| or | or | ||||
| .Vt RB_ENTRY , | .Vt Po A Pc Ns RB_ENTRY , | ||||
| named | named | ||||
| .Fa ENTRYNAME . | .Fa ENTRYNAME . | ||||
| The argument | The argument | ||||
| .Fa HEADNAME | .Fa HEADNAME | ||||
| is the name tag of a user defined structure that must be declared | is the name tag of a user defined structure that must be declared | ||||
| using the macros | using the macros | ||||
| .Fn SPLAY_HEAD , | .Fn SPLAY_HEAD , | ||||
| or | or | ||||
| .Fn RB_HEAD . | .Fn (A)RB_HEAD . | ||||
| The argument | The argument | ||||
| .Fa NAME | .Fa NAME | ||||
| has to be a unique name prefix for every tree that is defined. | has to be a unique name prefix for every tree that is defined. | ||||
| .Pp | .Pp | ||||
| The function prototypes are declared with | The function prototypes are declared with | ||||
| .Fn SPLAY_PROTOTYPE , | .Fn SPLAY_PROTOTYPE , | ||||
| .Fn RB_PROTOTYPE , | .Fn (A)RB_PROTOTYPE , | ||||
| or | or | ||||
| .Fn RB_PROTOTYPE_STATIC . | .Fn (A)RB_PROTOTYPE_STATIC . | ||||
| The function bodies are generated with | The function bodies are generated with | ||||
| .Fn SPLAY_GENERATE , | .Fn SPLAY_GENERATE , | ||||
| .Fn RB_GENERATE , | .Fn (A)RB_GENERATE , | ||||
| or | or | ||||
| .Fn RB_GENERATE_STATIC . | .Fn (A)RB_GENERATE_STATIC . | ||||
| See the examples below for further explanation of how these macros are used. | See the examples below for further explanation of how these macros are used. | ||||
| .Sh SPLAY TREES | .Sh SPLAY TREES | ||||
| A splay tree is a self-organizing data structure. | A splay tree is a self-organizing data structure. | ||||
| Every operation on the tree causes a splay to happen. | Every operation on the tree causes a splay to happen. | ||||
| The splay moves the requested | The splay moves the requested | ||||
| node to the root of the tree and partly rebalances it. | node to the root of the tree and partly rebalances it. | ||||
| .Pp | .Pp | ||||
| This has the benefit that request locality causes faster lookups as | This has the benefit that request locality causes faster lookups as | ||||
| ▲ Show 20 Lines • Show All 141 Lines • ▼ Show 20 Lines | |||||
| Each leaf node is black. | Each leaf node is black. | ||||
| .El | .El | ||||
| .Pp | .Pp | ||||
| Every operation on a red-black tree is bounded as | Every operation on a red-black tree is bounded as | ||||
| .Fn O "lg n" . | .Fn O "lg n" . | ||||
| The maximum height of a red-black tree is | The maximum height of a red-black tree is | ||||
| .Fn 2lg "n + 1" . | .Fn 2lg "n + 1" . | ||||
| .Pp | .Pp | ||||
| .Fn RB_* | |||||
| variant trees link an arbitrary number of individually allocated entries | |||||
| together using memory pointers. | |||||
| .Fn ARB_* | |||||
| variant trees require entries to be allocated as an array, and uses array | |||||
| indices to link entries together. | |||||
| The maximum number of | |||||
| .Fn ARB_* | |||||
| tree entries is therefore constrained by the minimum of array size and choice of | |||||
| signed integer data type used to store array indices. | |||||
| .Pp | |||||
| A red-black tree is headed by a structure defined by the | A red-black tree is headed by a structure defined by the | ||||
| .Fn RB_HEAD | .Fn (A)RB_HEAD | ||||
| macro. | macro. | ||||
| A | A | ||||
| structure is declared as follows: | structure is declared with either of the following: | ||||
| .Bd -ragged -offset indent | .Bd -ragged -offset indent | ||||
| .Fn RB_HEAD HEADNAME TYPE | .Fn RB_HEAD HEADNAME TYPE | ||||
| .Va head ; | .Va head ; | ||||
| .Ed | .Ed | ||||
| .Bd -ragged -offset indent | |||||
| .Fn ARB<8|16|32>_HEAD HEADNAME TYPE | |||||
| .Va head ; | |||||
| .Ed | |||||
| .Pp | .Pp | ||||
| where | where | ||||
| .Fa HEADNAME | .Fa HEADNAME | ||||
| is the name of the structure to be defined, and struct | is the name of the structure to be defined, and struct | ||||
| .Fa TYPE | .Fa TYPE | ||||
| is the type of the elements to be inserted into the tree. | is the type of the elements to be inserted into the tree. | ||||
| .Pp | .Pp | ||||
| The | The | ||||
| .Fn RB_ENTRY | .Fn ARB_HEAD | ||||
| variant includes a suffix denoting the signed integer data type size | |||||
| .Pq in bits | |||||
| used to store array indices. | |||||
| For example, | |||||
| .Fn ARB_HEAD8 | |||||
| creates a red-black tree head strucutre with 8-bit signed array indices capable | |||||
| of indexing up to 128 entries. | |||||
| .Pp | |||||
| The | |||||
| .Fn (A)RB_ENTRY | |||||
| macro declares a structure that allows elements to be connected in the tree. | macro declares a structure that allows elements to be connected in the tree. | ||||
| Similarly to the | |||||
| .Fn ARB<8|16|32>_HEAD | |||||
| macro, the | |||||
| .Fn ARB_ENTRY | |||||
| variant includes a suffix denoting the signed integer data type size | |||||
| .Pq in bits | |||||
| used to store array indices. | |||||
| Entries should use the same number of bits as the tree head structure they will | |||||
| be linked into. | |||||
| .Pp | .Pp | ||||
| In order to use the functions that manipulate the tree structure, | In order to use the functions that manipulate the tree structure, | ||||
| their prototypes need to be declared with the | their prototypes need to be declared with the | ||||
| .Fn RB_PROTOTYPE | .Fn (A)RB_PROTOTYPE | ||||
| or | or | ||||
| .Fn RB_PROTOTYPE_STATIC | .Fn (A)RB_PROTOTYPE_STATIC | ||||
| macro, | macro, | ||||
| where | where | ||||
| .Fa NAME | .Fa NAME | ||||
| is a unique identifier for this particular tree. | is a unique identifier for this particular tree. | ||||
| The | The | ||||
| .Fa TYPE | .Fa TYPE | ||||
| argument is the type of the structure that is being managed | argument is the type of the structure that is being managed | ||||
| by the tree. | by the tree. | ||||
| The | The | ||||
| .Fa FIELD | .Fa FIELD | ||||
| argument is the name of the element defined by | argument is the name of the element defined by | ||||
| .Fn RB_ENTRY . | .Fn (A)RB_ENTRY . | ||||
| Individual prototypes can be declared with | Individual prototypes can be declared with | ||||
| .Fn RB_PROTOTYPE_INSERT , | .Fn (A)RB_PROTOTYPE_INSERT , | ||||
| .Fn RB_PROTOTYPE_INSERT_COLOR , | .Fn (A)RB_PROTOTYPE_INSERT_COLOR , | ||||
| .Fn RB_PROTOTYPE_REMOVE , | .Fn (A)RB_PROTOTYPE_REMOVE , | ||||
| .Fn RB_PROTOTYPE_REMOVE_COLOR , | .Fn (A)RB_PROTOTYPE_REMOVE_COLOR , | ||||
| .Fn RB_PROTOTYPE_FIND , | .Fn (A)RB_PROTOTYPE_FIND , | ||||
| .Fn RB_PROTOTYPE_NFIND , | .Fn (A)RB_PROTOTYPE_NFIND , | ||||
| .Fn RB_PROTOTYPE_NEXT , | .Fn (A)RB_PROTOTYPE_NEXT , | ||||
| .Fn RB_PROTOTYPE_PREV , | .Fn (A)RB_PROTOTYPE_PREV , | ||||
| and | and | ||||
| .Fn RB_PROTOTYPE_MINMAX | .Fn (A)RB_PROTOTYPE_MINMAX | ||||
| in case not all functions are required. | in case not all functions are required. | ||||
| The individual prototype macros expect | The individual prototype macros expect | ||||
| .Fa NAME , | .Fa NAME , | ||||
| .Fa TYPE , | .Fa TYPE , | ||||
| and | and | ||||
| .Fa ATTR | .Fa ATTR | ||||
| arguments. | arguments. | ||||
| The | The | ||||
| .Fa ATTR | .Fa ATTR | ||||
| argument must be empty for global functions or | argument must be empty for global functions or | ||||
| .Fa static | .Fa static | ||||
| for static functions. | for static functions. | ||||
| .Pp | .Pp | ||||
| The function bodies are generated with the | The function bodies are generated with the | ||||
| .Fn RB_GENERATE | .Fn (A)RB_GENERATE | ||||
| or | or | ||||
| .Fn RB_GENERATE_STATIC | .Fn (A)RB_GENERATE_STATIC | ||||
| macro. | macro. | ||||
| These macros take the same arguments as the | These macros take the same arguments as the | ||||
| .Fn RB_PROTOTYPE | .Fn (A)RB_PROTOTYPE | ||||
| and | and | ||||
| .Fn RB_PROTOTYPE_STATIC | .Fn (A)RB_PROTOTYPE_STATIC | ||||
| macros, but should be used only once. | macros, but should be used only once. | ||||
| As an alternative individual function bodies are generated with the | As an alternative individual function bodies are generated with the | ||||
| .Fn RB_GENERATE_INSERT , | .Fn (A)RB_GENERATE_INSERT , | ||||
| .Fn RB_GENERATE_INSERT_COLOR , | .Fn (A)RB_GENERATE_INSERT_COLOR , | ||||
| .Fn RB_GENERATE_REMOVE , | .Fn (A)RB_GENERATE_REMOVE , | ||||
| .Fn RB_GENERATE_REMOVE_COLOR , | .Fn (A)RB_GENERATE_REMOVE_COLOR , | ||||
| .Fn RB_GENERATE_FIND , | .Fn (A)RB_GENERATE_FIND , | ||||
| .Fn RB_GENERATE_NFIND , | .Fn (A)RB_GENERATE_NFIND , | ||||
| .Fn RB_GENERATE_NEXT , | .Fn (A)RB_GENERATE_NEXT , | ||||
| .Fn RB_GENERATE_PREV , | .Fn (A)RB_GENERATE_PREV , | ||||
| and | and | ||||
| .Fn RB_GENERATE_MINMAX | .Fn (A)RB_GENERATE_MINMAX | ||||
| macros. | macros. | ||||
| .Pp | .Pp | ||||
| Finally, | Finally, | ||||
| the | the | ||||
| .Fa CMP | .Fa CMP | ||||
| argument is the name of a function used to compare tree nodes | argument is the name of a function used to compare tree nodes | ||||
| with each other. | with each other. | ||||
| The function takes two arguments of type | The function takes two arguments of type | ||||
| .Vt "struct TYPE *" . | .Vt "struct TYPE *" . | ||||
| If the first argument is smaller than the second, the function returns a | If the first argument is smaller than the second, the function returns a | ||||
| value smaller than zero. | value smaller than zero. | ||||
| If they are equal, the function returns zero. | If they are equal, the function returns zero. | ||||
| Otherwise, it should return a value greater than zero. | Otherwise, it should return a value greater than zero. | ||||
| The compare | The compare | ||||
| function defines the order of the tree elements. | function defines the order of the tree elements. | ||||
| .Pp | .Pp | ||||
| The | The | ||||
| .Fn RB_INIT | .Fn (A)RB_INIT | ||||
| macro initializes the tree referenced by | macro initializes the tree referenced by | ||||
| .Fa head . | .Fa head , | ||||
| with the | |||||
| .Fn ARB_INIT | |||||
| variant also taking the array length | |||||
| .Fa maxnodes . | |||||
| .Pp | .Pp | ||||
| The red-black tree can also be initialized statically by using the | The red-black tree can also be initialized statically by using the | ||||
| .Fn RB_INITIALIZER | .Fn (A)RB_INITIALIZER | ||||
| macro like this: | macro like either: | ||||
| .Bd -ragged -offset indent | .Bd -ragged -offset indent | ||||
| .Fn RB_HEAD HEADNAME TYPE | .Fn RB_HEAD HEADNAME TYPE | ||||
| .Va head | .Va head | ||||
| = | = | ||||
| .Fn RB_INITIALIZER &head ; | .Fn RB_INITIALIZER &head ; | ||||
| .Ed | .Ed | ||||
| .Bd -ragged -offset indent | |||||
| .Fn ARB<8|16|32>_HEAD HEADNAME TYPE | |||||
| .Va head | |||||
| = | |||||
| .Fn ARB_INITIALIZER &head maxnodes ; | |||||
| .Ed | |||||
| .Pp | .Pp | ||||
| The | The | ||||
| .Fn RB_INSERT | .Fn (A)RB_INSERT | ||||
| macro inserts the new element | macro inserts the new element | ||||
| .Fa elm | .Fa elm | ||||
| into the tree. | into the tree. | ||||
| .Pp | .Pp | ||||
| The | The | ||||
| .Fn RB_REMOVE | .Fn (A)RB_REMOVE | ||||
| macro removes the element | macro removes the element | ||||
| .Fa elm | .Fa elm | ||||
| from the tree pointed by | from the tree pointed by | ||||
| .Fa head . | .Fa head . | ||||
| .Pp | .Pp | ||||
| The | The | ||||
| .Fn RB_FIND | .Fn (A)RB_FIND | ||||
| and | and | ||||
| .Fn RB_NFIND | .Fn (A)RB_NFIND | ||||
| macros can be used to find a particular element in the tree. | macros can be used to find a particular element in the tree. | ||||
| .Bd -literal -offset indent | .Bd -literal -offset indent | ||||
| struct TYPE find, *res; | struct TYPE find, *res; | ||||
| find.key = 30; | find.key = 30; | ||||
| res = RB_FIND(NAME, head, &find); | res = RB_FIND(NAME, head, &find); | ||||
| .Ed | .Ed | ||||
| .Pp | .Pp | ||||
| The | The | ||||
| .Fn RB_ROOT , | .Fn (A)RB_ROOT , | ||||
| .Fn RB_MIN , | .Fn (A)RB_MIN , | ||||
| .Fn RB_MAX , | .Fn (A)RB_MAX , | ||||
| .Fn RB_NEXT , | .Fn (A)RB_NEXT , | ||||
| and | and | ||||
| .Fn RB_PREV | .Fn (A)RB_PREV | ||||
| macros can be used to traverse the tree: | macros can be used to traverse the tree: | ||||
| .Pp | .Pp | ||||
| .Dl "for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np))" | .Dl "for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np))" | ||||
| .Pp | .Pp | ||||
| Or, for simplicity, one can use the | Or, for simplicity, one can use the | ||||
| .Fn RB_FOREACH | .Fn (A)RB_FOREACH | ||||
| or | or | ||||
| .Fn RB_FOREACH_REVERSE | .Fn (A)RB_FOREACH_REVERSE | ||||
| macro: | macro: | ||||
| .Bd -ragged -offset indent | .Bd -ragged -offset indent | ||||
| .Fn RB_FOREACH np NAME head | .Fn RB_FOREACH np NAME head | ||||
| .Ed | .Ed | ||||
| .Pp | .Pp | ||||
| The macros | The macros | ||||
| .Fn RB_FOREACH_SAFE | .Fn (A)RB_FOREACH_SAFE | ||||
| and | and | ||||
| .Fn RB_FOREACH_REVERSE_SAFE | .Fn (A)RB_FOREACH_REVERSE_SAFE | ||||
| traverse the tree referenced by head | traverse the tree referenced by head | ||||
| in a forward or reverse direction respectively, | in a forward or reverse direction respectively, | ||||
| assigning each element in turn to np. | assigning each element in turn to np. | ||||
| However, unlike their unsafe counterparts, | However, unlike their unsafe counterparts, | ||||
| they permit both the removal of np | they permit both the removal of np | ||||
| as well as freeing it from within the loop safely | as well as freeing it from within the loop safely | ||||
| without interfering with the traversal. | without interfering with the traversal. | ||||
| .Pp | .Pp | ||||
| Both | Both | ||||
| .Fn RB_FOREACH_FROM | .Fn (A)RB_FOREACH_FROM | ||||
| and | and | ||||
| .Fn RB_FOREACH_REVERSE_FROM | .Fn (A)RB_FOREACH_REVERSE_FROM | ||||
| may be used to continue an interrupted traversal | may be used to continue an interrupted traversal | ||||
| in a forward or reverse direction respectively. | in a forward or reverse direction respectively. | ||||
| The head pointer is not required. | The head pointer is not required. | ||||
| The pointer to the node from where to resume the traversal | The pointer to the node from where to resume the traversal | ||||
| should be passed as their last argument, | should be passed as their last argument, | ||||
| and will be overwritten to provide safe traversal. | and will be overwritten to provide safe traversal. | ||||
| .Pp | .Pp | ||||
| The | The | ||||
| .Fn RB_EMPTY | .Fn (A)RB_EMPTY | ||||
| macro should be used to check whether a red-black tree is empty. | macro should be used to check whether a red-black tree is empty. | ||||
| .Pp | |||||
| Given that ARB trees have an intrinsic upper bound on the number of entries, | |||||
| some ARB-specific additional macros are defined. | |||||
| The | |||||
| .Fn ARB_FULL | |||||
| macro returns a boolean indicating whether the current number of tree entries | |||||
| equals the tree's maximum. | |||||
| The | |||||
| .Fn ARB_CURNODES | |||||
| and | |||||
| .Fn ARB_MAXNODES | |||||
| macros return the current and maximum number of entries respectively. | |||||
| The | |||||
| .Fn ARB_GETFREE | |||||
| macro returns a pointer to the next free entry in the array of entries, ready to | |||||
| be linked into the tree. | |||||
| .Sh EXAMPLES | .Sh EXAMPLES | ||||
| The following example demonstrates how to declare a red-black tree | The following example demonstrates how to declare a red-black tree | ||||
| holding integers. | holding integers. | ||||
| Values are inserted into it and the contents of the tree are printed | Values are inserted into it and the contents of the tree are printed | ||||
| in order. | in order. | ||||
| Lastly, the internal structure of the tree is printed. | Lastly, the internal structure of the tree is printed. | ||||
| .Bd -literal -offset 3n | .Bd -literal -offset 3n | ||||
| #include <sys/tree.h> | #include <sys/tree.h> | ||||
| ▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | |||||
| for (var = SPLAY_MIN(NAME, head); var != NULL; var = nxt) { | for (var = SPLAY_MIN(NAME, head); var != NULL; var = nxt) { | ||||
| nxt = SPLAY_NEXT(NAME, head, var); | nxt = SPLAY_NEXT(NAME, head, var); | ||||
| SPLAY_REMOVE(NAME, head, var); | SPLAY_REMOVE(NAME, head, var); | ||||
| free(var); | free(var); | ||||
| } | } | ||||
| .Ed | .Ed | ||||
| .Pp | .Pp | ||||
| Both | Both | ||||
| .Fn RB_INSERT | .Fn (A)RB_INSERT | ||||
| and | and | ||||
| .Fn SPLAY_INSERT | .Fn SPLAY_INSERT | ||||
| return | return | ||||
| .Dv NULL | .Dv NULL | ||||
| if the element was inserted in the tree successfully, otherwise they | if the element was inserted in the tree successfully, otherwise they | ||||
| return a pointer to the element with the colliding key. | return a pointer to the element with the colliding key. | ||||
| .Pp | .Pp | ||||
| Accordingly, | Accordingly, | ||||
| .Fn RB_REMOVE | .Fn (A)RB_REMOVE | ||||
| and | and | ||||
| .Fn SPLAY_REMOVE | .Fn SPLAY_REMOVE | ||||
| return the pointer to the removed element otherwise they return | return the pointer to the removed element otherwise they return | ||||
| .Dv NULL | .Dv NULL | ||||
| to indicate an error. | to indicate an error. | ||||
| .Sh SEE ALSO | .Sh SEE ALSO | ||||
| .Xr queue 3 | .Xr queue 3 | ||||
| .Sh AUTHORS | .Sh AUTHORS | ||||
| The author of the tree macros is | The author of the tree macros is | ||||
| .An Niels Provos . | .An Niels Provos . | ||||