1.\" $OpenBSD: tree.3,v 1.7 2002/06/12 01:09:20 provos Exp $ 2.\" 3.\" Copyright 2002 Niels Provos <provos@citi.umich.edu> 4.\" All rights reserved. 5.\" 6.\" Redistribution and use in source and binary forms, with or without 7.\" modification, are permitted provided that the following conditions 8.\" are met: 9.\" 1. Redistributions of source code must retain the above copyright 10.\" notice, this list of conditions and the following disclaimer. 11.\" 2. Redistributions in binary form must reproduce the above copyright 12.\" notice, this list of conditions and the following disclaimer in the 13.\" documentation and/or other materials provided with the distribution. 14.\" 3. All advertising materials mentioning features or use of this software 15.\" must display the following acknowledgement: 16.\" This product includes software developed by Niels Provos. 17.\" 4. The name of the author may not be used to endorse or promote products 18.\" derived from this software without specific prior written permission. 19.\" 20.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30.\" 31.\" $FreeBSD$ 32.\" 33.Dd September 28, 2019 34.Dt ARB 3 35.Os 36.Sh NAME 37.Nm ARB_PROTOTYPE , 38.Nm ARB_PROTOTYPE_STATIC , 39.Nm ARB_PROTOTYPE_INSERT , 40.Nm ARB_PROTOTYPE_INSERT_COLOR , 41.Nm ARB_PROTOTYPE_REMOVE , 42.Nm ARB_PROTOTYPE_REMOVE_COLOR , 43.Nm ARB_PROTOTYPE_FIND , 44.Nm ARB_PROTOTYPE_NFIND , 45.Nm ARB_PROTOTYPE_NEXT , 46.Nm ARB_PROTOTYPE_PREV , 47.Nm ARB_PROTOTYPE_MINMAX , 48.Nm ARB_PROTOTYPE_REINSERT , 49.Nm ARB_GENERATE , 50.Nm ARB_GENERATE_STATIC , 51.Nm ARB_GENERATE_INSERT , 52.Nm ARB_GENERATE_INSERT_COLOR , 53.Nm ARB_GENERATE_REMOVE , 54.Nm ARB_GENERATE_REMOVE_COLOR , 55.Nm ARB_GENERATE_FIND , 56.Nm ARB_GENERATE_NFIND , 57.Nm ARB_GENERATE_NEXT , 58.Nm ARB_GENERATE_PREV , 59.Nm ARB_GENERATE_MINMAX , 60.Nm ARB_GENERATE_REINSERT , 61.Nm ARB8_ENTRY , 62.Nm ARB16_ENTRY , 63.Nm ARB32_ENTRY , 64.Nm ARB8_HEAD , 65.Nm ARB16_HEAD , 66.Nm ARB32_HEAD , 67.Nm ARB_ALLOCSIZE , 68.Nm ARB_INITIALIZER , 69.Nm ARB_ROOT , 70.Nm ARB_EMPTY , 71.Nm ARB_FULL , 72.Nm ARB_CURNODES , 73.Nm ARB_MAXNODES , 74.Nm ARB_NEXT , 75.Nm ARB_PREV , 76.Nm ARB_MIN , 77.Nm ARB_MAX , 78.Nm ARB_FIND , 79.Nm ARB_NFIND , 80.Nm ARB_LEFT , 81.Nm ARB_LEFTIDX , 82.Nm ARB_RIGHT , 83.Nm ARB_RIGHTIDX , 84.Nm ARB_PARENT , 85.Nm ARB_PARENTIDX , 86.Nm ARB_GETFREE , 87.Nm ARB_FREEIDX , 88.Nm ARB_FOREACH , 89.Nm ARB_FOREACH_FROM , 90.Nm ARB_FOREACH_SAFE , 91.Nm ARB_FOREACH_REVERSE , 92.Nm ARB_FOREACH_REVERSE_FROM , 93.Nm ARB_FOREACH_REVERSE_SAFE , 94.Nm ARB_INIT , 95.Nm ARB_INSERT , 96.Nm ARB_REMOVE , 97.Nm ARB_REINSERT 98.Nd "array-based red-black trees" 99.Sh SYNOPSIS 100.In sys/arb.h 101.Fn ARB_PROTOTYPE NAME TYPE FIELD CMP 102.Fn ARB_PROTOTYPE_STATIC NAME TYPE FIELD CMP 103.Fn ARB_PROTOTYPE_INSERT NAME TYPE ATTR 104.Fn ARB_PROTOTYPE_INSERT_COLOR NAME TYPE ATTR 105.Fn ARB_PROTOTYPE_REMOVE NAME TYPE ATTR 106.Fn ARB_PROTOTYPE_REMOVE_COLOR NAME TYPE ATTR 107.Fn ARB_PROTOTYPE_FIND NAME TYPE ATTR 108.Fn ARB_PROTOTYPE_NFIND NAME TYPE ATTR 109.Fn ARB_PROTOTYPE_NEXT NAME TYPE ATTR 110.Fn ARB_PROTOTYPE_PREV NAME TYPE ATTR 111.Fn ARB_PROTOTYPE_MINMAX NAME TYPE ATTR 112.Fn ARB_PROTOTYPE_REINSERT NAME TYPE ATTR 113.Fn ARB_GENERATE NAME TYPE FIELD CMP 114.Fn ARB_GENERATE_STATIC NAME TYPE FIELD CMP 115.Fn ARB_GENERATE_INSERT NAME TYPE FIELD CMP ATTR 116.Fn ARB_GENERATE_INSERT_COLOR NAME TYPE FIELD ATTR 117.Fn ARB_GENERATE_REMOVE NAME TYPE FIELD ATTR 118.Fn ARB_GENERATE_REMOVE_COLOR NAME TYPE FIELD ATTR 119.Fn ARB_GENERATE_FIND NAME TYPE FIELD CMP ATTR 120.Fn ARB_GENERATE_NFIND NAME TYPE FIELD CMP ATTR 121.Fn ARB_GENERATE_NEXT NAME TYPE FIELD ATTR 122.Fn ARB_GENERATE_PREV NAME TYPE FIELD ATTR 123.Fn ARB_GENERATE_MINMAX NAME TYPE FIELD ATTR 124.Fn ARB_GENERATE_REINSERT NAME TYPE FIELD CMP ATTR 125.Fn ARB<8|16|32>_ENTRY 126.Fn ARB<8|16|32>_HEAD HEADNAME TYPE 127.Ft "size_t" 128.Fn ARB_ALLOCSIZE "ARB_HEAD *head" "int<8|16|32>_t maxnodes" "struct TYPE *elm" 129.Fn ARB_INITIALIZER "ARB_HEAD *head" "int<8|16|32>_t maxnodes" 130.Ft "struct TYPE *" 131.Fn ARB_ROOT "ARB_HEAD *head" 132.Ft "bool" 133.Fn ARB_EMPTY "ARB_HEAD *head" 134.Ft "bool" 135.Fn ARB_FULL "ARB_HEAD *head" 136.Ft "int<8|16|32>_t" 137.Fn ARB_CURNODES "ARB_HEAD *head" 138.Ft "int<8|16|32>_t" 139.Fn ARB_MAXNODES "ARB_HEAD *head" 140.Ft "struct TYPE *" 141.Fn ARB_NEXT NAME "ARB_HEAD *head" "struct TYPE *elm" 142.Ft "struct TYPE *" 143.Fn ARB_PREV NAME "ARB_HEAD *head" "struct TYPE *elm" 144.Ft "struct TYPE *" 145.Fn ARB_MIN NAME "ARB_HEAD *head" 146.Ft "struct TYPE *" 147.Fn ARB_MAX NAME "ARB_HEAD *head" 148.Ft "struct TYPE *" 149.Fn ARB_FIND NAME "ARB_HEAD *head" "struct TYPE *elm" 150.Ft "struct TYPE *" 151.Fn ARB_NFIND NAME "ARB_HEAD *head" "struct TYPE *elm" 152.Ft "struct TYPE *" 153.Fn ARB_LEFT "struct TYPE *elm" "ARB_ENTRY NAME" 154.Ft "int<8|16|32>_t" 155.Fn ARB_LEFTIDX "struct TYPE *elm" "ARB_ENTRY NAME" 156.Ft "struct TYPE *" 157.Fn ARB_RIGHT "struct TYPE *elm" "ARB_ENTRY NAME" 158.Ft "int<8|16|32>_t" 159.Fn ARB_RIGHTIDX "struct TYPE *elm" "ARB_ENTRY NAME" 160.Ft "struct TYPE *" 161.Fn ARB_PARENT "struct TYPE *elm" "ARB_ENTRY NAME" 162.Ft "int<8|16|32>_t" 163.Fn ARB_PARENTIDX "struct TYPE *elm" "ARB_ENTRY NAME" 164.Ft "struct TYPE *" 165.Fn ARB_GETFREE "ARB_HEAD *head" "FIELD" 166.Ft "int<8|16|32>_t" 167.Fn ARB_FREEIDX "ARB_HEAD *head" 168.Fn ARB_FOREACH VARNAME NAME "ARB_HEAD *head" 169.Fn ARB_FOREACH_FROM "VARNAME" "NAME" "POS_VARNAME" 170.Fn ARB_FOREACH_SAFE "VARNAME" "NAME" "ARB_HEAD *head" "TEMP_VARNAME" 171.Fn ARB_FOREACH_REVERSE VARNAME NAME "ARB_HEAD *head" 172.Fn ARB_FOREACH_REVERSE_FROM "VARNAME" "NAME" "POS_VARNAME" 173.Fn ARB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "ARB_HEAD *head" "TEMP_VARNAME" 174.Ft void 175.Fn ARB_INIT "struct TYPE *elm" "FIELD" "ARB_HEAD *head" "int<8|16|32>_t maxnodes" 176.Ft "struct TYPE *" 177.Fn ARB_INSERT NAME "ARB_HEAD *head" "struct TYPE *elm" 178.Ft "struct TYPE *" 179.Fn ARB_REMOVE NAME "ARB_HEAD *head" "struct TYPE *elm" 180.Ft "struct TYPE *" 181.Fn ARB_REINSERT NAME "ARB_HEAD *head" "struct TYPE *elm" 182.Sh DESCRIPTION 183These macros define data structures for and array-based red-black trees. 184They use a single, continuous chunk of memory, and are useful 185e.g., when the tree needs to be transferred between userspace and kernel. 186.Pp 187In the macro definitions, 188.Fa TYPE 189is the name tag of a user defined structure that must contain a field of type 190.Vt ARB_ENTRY , 191named 192.Fa ENTRYNAME . 193The argument 194.Fa HEADNAME 195is the name tag of a user defined structure that must be declared 196using the 197.Fn ARB_HEAD 198macro. 199The argument 200.Fa NAME 201has to be a unique name prefix for every tree that is defined. 202.Pp 203The function prototypes are declared with 204.Fn ARB_PROTOTYPE , 205or 206.Fn ARB_PROTOTYPE_STATIC . 207The function bodies are generated with 208.Fn ARB_GENERATE , 209or 210.Fn ARB_GENERATE_STATIC . 211See the examples below for further explanation of how these macros are used. 212.Pp 213A red-black tree is a binary search tree with the node color as an 214extra attribute. 215It fulfills a set of conditions: 216.Bl -enum -offset indent 217.It 218Every search path from the root to a leaf consists of the same number of 219black nodes. 220.It 221Each red node (except for the root) has a black parent. 222.It 223Each leaf node is black. 224.El 225.Pp 226Every operation on a red-black tree is bounded as 227.Fn O "lg n" . 228The maximum height of a red-black tree is 229.Fn 2lg "n + 1" . 230.Pp 231.Fn ARB_* 232trees require entries to be allocated as an array, and uses array 233indices to link entries together. 234The maximum number of 235.Fn ARB_* 236tree entries is therefore constrained by the minimum of array size and choice of 237signed integer data type used to store array indices. 238Use 239.Fn ARB_ALLOCSIZE 240to compute the size of memory chunk to allocate. 241.Pp 242A red-black tree is headed by a structure defined by the 243.Fn ARB_HEAD 244macro. 245A 246structure is declared with either of the following: 247.Bd -ragged -offset indent 248.Fn ARB<8|16|32>_HEAD HEADNAME TYPE 249.Va head ; 250.Ed 251.Pp 252where 253.Fa HEADNAME 254is the name of the structure to be defined, and struct 255.Fa TYPE 256is the type of the elements to be inserted into the tree. 257.Pp 258The 259.Fn ARB_HEAD 260variant includes a suffix denoting the signed integer data type size 261.Pq in bits 262used to store array indices. 263For example, 264.Fn ARB_HEAD8 265creates a red-black tree head strucutre with 8-bit signed array indices capable 266of indexing up to 128 entries. 267.Pp 268The 269.Fn ARB_ENTRY 270macro declares a structure that allows elements to be connected in the tree. 271Similarly to the 272.Fn ARB<8|16|32>_HEAD 273macro, the 274.Fn ARB_ENTRY 275variant includes a suffix denoting the signed integer data type size 276.Pq in bits 277used to store array indices. 278Entries should use the same number of bits as the tree head structure they will 279be linked into. 280.Pp 281In order to use the functions that manipulate the tree structure, 282their prototypes need to be declared with the 283.Fn ARB_PROTOTYPE 284or 285.Fn ARB_PROTOTYPE_STATIC 286macro, 287where 288.Fa NAME 289is a unique identifier for this particular tree. 290The 291.Fa TYPE 292argument is the type of the structure that is being managed 293by the tree. 294The 295.Fa FIELD 296argument is the name of the element defined by 297.Fn ARB_ENTRY . 298Individual prototypes can be declared with 299.Fn ARB_PROTOTYPE_INSERT , 300.Fn ARB_PROTOTYPE_INSERT_COLOR , 301.Fn ARB_PROTOTYPE_REMOVE , 302.Fn ARB_PROTOTYPE_REMOVE_COLOR , 303.Fn ARB_PROTOTYPE_FIND , 304.Fn ARB_PROTOTYPE_NFIND , 305.Fn ARB_PROTOTYPE_NEXT , 306.Fn ARB_PROTOTYPE_PREV , 307.Fn ARB_PROTOTYPE_MINMAX , 308and 309.Fn ARB_PROTOTYPE_REINSERT 310in case not all functions are required. 311The individual prototype macros expect 312.Fa NAME , 313.Fa TYPE , 314and 315.Fa ATTR 316arguments. 317The 318.Fa ATTR 319argument must be empty for global functions or 320.Fa static 321for static functions. 322.Pp 323The function bodies are generated with the 324.Fn ARB_GENERATE 325or 326.Fn ARB_GENERATE_STATIC 327macro. 328These macros take the same arguments as the 329.Fn ARB_PROTOTYPE 330and 331.Fn ARB_PROTOTYPE_STATIC 332macros, but should be used only once. 333As an alternative individual function bodies are generated with the 334.Fn ARB_GENERATE_INSERT , 335.Fn ARB_GENERATE_INSERT_COLOR , 336.Fn ARB_GENERATE_REMOVE , 337.Fn ARB_GENERATE_REMOVE_COLOR , 338.Fn ARB_GENERATE_FIND , 339.Fn ARB_GENERATE_NFIND , 340.Fn ARB_GENERATE_NEXT , 341.Fn ARB_GENERATE_PREV , 342.Fn ARB_GENERATE_MINMAX , 343and 344.Fn ARB_GENERATE_REINSERT 345macros. 346.Pp 347Finally, 348the 349.Fa CMP 350argument is the name of a function used to compare tree nodes 351with each other. 352The function takes two arguments of type 353.Vt "struct TYPE *" . 354If the first argument is smaller than the second, the function returns a 355value smaller than zero. 356If they are equal, the function returns zero. 357Otherwise, it should return a value greater than zero. 358The compare 359function defines the order of the tree elements. 360.Pp 361The 362.Fn ARB_INIT 363macro initializes the tree referenced by 364.Fa head , 365with the array length of 366.Fa maxnodes . 367.Pp 368The red-black tree can also be initialized statically by using the 369.Fn ARB_INITIALIZER 370macro: 371.Bd -ragged -offset indent 372.Fn ARB<8|16|32>_HEAD HEADNAME TYPE 373.Va head 374= 375.Fn ARB_INITIALIZER &head maxnodes ; 376.Ed 377.Pp 378The 379.Fn ARB_INSERT 380macro inserts the new element 381.Fa elm 382into the tree. 383.Pp 384The 385.Fn ARB_REMOVE 386macro removes the element 387.Fa elm 388from the tree pointed by 389.Fa head . 390.Pp 391The 392.Fn ARB_FIND 393and 394.Fn ARB_NFIND 395macros can be used to find a particular element in the tree. 396.Bd -literal -offset indent 397struct TYPE find, *res; 398find.key = 30; 399res = RB_FIND(NAME, head, &find); 400.Ed 401.Pp 402The 403.Fn ARB_ROOT , 404.Fn ARB_MIN , 405.Fn ARB_MAX , 406.Fn ARB_NEXT , 407and 408.Fn ARB_PREV 409macros can be used to traverse the tree: 410.Pp 411.Dl "for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np))" 412.Pp 413Or, for simplicity, one can use the 414.Fn ARB_FOREACH 415or 416.Fn ARB_FOREACH_REVERSE 417macro: 418.Bd -ragged -offset indent 419.Fn RB_FOREACH np NAME head 420.Ed 421.Pp 422The macros 423.Fn ARB_FOREACH_SAFE 424and 425.Fn ARB_FOREACH_REVERSE_SAFE 426traverse the tree referenced by head 427in a forward or reverse direction respectively, 428assigning each element in turn to np. 429However, unlike their unsafe counterparts, 430they permit both the removal of np 431as well as freeing it from within the loop safely 432without interfering with the traversal. 433.Pp 434Both 435.Fn ARB_FOREACH_FROM 436and 437.Fn ARB_FOREACH_REVERSE_FROM 438may be used to continue an interrupted traversal 439in a forward or reverse direction respectively. 440The head pointer is not required. 441The pointer to the node from where to resume the traversal 442should be passed as their last argument, 443and will be overwritten to provide safe traversal. 444.Pp 445The 446.Fn ARB_EMPTY 447macro should be used to check whether a red-black tree is empty. 448.Pp 449Given that ARB trees have an intrinsic upper bound on the number of entries, 450some ARB-specific additional macros are defined. 451The 452.Fn ARB_FULL 453macro returns a boolean indicating whether the current number of tree entries 454equals the tree's maximum. 455The 456.Fn ARB_CURNODES 457and 458.Fn ARB_MAXNODES 459macros return the current and maximum number of entries respectively. 460The 461.Fn ARB_GETFREE 462macro returns a pointer to the next free entry in the array of entries, ready to 463be linked into the tree. 464The 465.Fn ARB_INSERT 466returns 467.Dv NULL 468if the element was inserted in the tree successfully, otherwise they 469return a pointer to the element with the colliding key. 470.Pp 471Accordingly, 472.Fn ARB_REMOVE 473returns the pointer to the removed element otherwise they return 474.Dv NULL 475to indicate an error. 476.Pp 477The 478.Fn RB_REINSERT 479macro updates the position of the element 480.Fa elm 481in the tree. 482This must be called if a member of a 483.Nm tree 484is modified in a way that affects comparison, such as by modifying 485a node's key. 486This is a lower overhead alternative to removing the element 487and reinserting it again. 488.Sh SEE ALSO 489.Xr queue 3 , 490.Xr tree 3 491.Sh HISTORY 492The 493.Nm ARB 494macros first appeared in 495.Fx 13.0 . 496.Sh AUTHORS 497The 498.Nm ARB 499macros were implemented by 500.An Lawrence Stewart Aq Mt lstewart@FreeBSD.org , 501based on 502.Xr tree 3 503macros written by 504.An Niels Provos . 505