1
0
mirror of https://gitlab.xiph.org/xiph/ezstream.git synced 2024-12-04 14:46:31 -05:00

Update tree macros. The manual now actually has an acceptable license.

git-svn-id: https://svn.xiph.org/trunk/ezstream@15767 0101bb08-14d6-0310-b084-bc0e0c8e3800
This commit is contained in:
moritz 2009-03-15 10:55:58 +00:00
parent 86cf28410f
commit 26142cade4
3 changed files with 146 additions and 47 deletions

8
NEWS
View File

@ -1,3 +1,11 @@
Changes in 0.5.4, released on XXXX-XX-XX:
* sys/compat/tree.*:
- [MISC] Update tree macros to a newer version. The manual, shipped for
reference, now has a more friendly 2-clause BSD license.
Changes in 0.5.3, released on 2007-12-01: Changes in 0.5.3, released on 2007-12-01:
* src/ezstream.c: * src/ezstream.c:

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: tree.3,v 1.13 2007/05/31 19:19:48 jmc Exp $ .\" $OpenBSD: tree.3,v 1.20 2009/01/28 12:22:48 stsp Exp $
.\"/* .\"/*
.\" * Copyright 2002 Niels Provos <provos@citi.umich.edu> .\" * Copyright 2002 Niels Provos <provos@citi.umich.edu>
.\" * All rights reserved. .\" * All rights reserved.
@ -11,11 +11,6 @@
.\" * 2. Redistributions in binary form must reproduce the above copyright .\" * 2. Redistributions in binary form must reproduce the above copyright
.\" * notice, this list of conditions and the following disclaimer in the .\" * notice, this list of conditions and the following disclaimer in the
.\" * documentation and/or other materials provided with the distribution. .\" * documentation and/or other materials provided with the distribution.
.\" * 3. All advertising materials mentioning features or use of this software
.\" * must display the following acknowledgement:
.\" * This product includes software developed by Niels Provos.
.\" * 4. The name of the author may not be used to endorse or promote products
.\" * derived from this software without specific prior written permission.
.\" * .\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@ -28,7 +23,7 @@
.\" * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" */ .\" */
.Dd $Mdocdate$ .Dd $Mdocdate: January 28 2009 $
.Dt TREE 3 .Dt TREE 3
.Os .Os
.Sh NAME .Sh NAME
@ -50,20 +45,25 @@
.Nm SPLAY_INSERT , .Nm SPLAY_INSERT ,
.Nm SPLAY_REMOVE , .Nm SPLAY_REMOVE ,
.Nm RB_PROTOTYPE , .Nm RB_PROTOTYPE ,
.Nm RB_PROTOTYPE_STATIC ,
.Nm RB_GENERATE , .Nm RB_GENERATE ,
.Nm RB_GENERATE_STATIC ,
.Nm RB_ENTRY , .Nm RB_ENTRY ,
.Nm RB_HEAD , .Nm RB_HEAD ,
.Nm RB_INITIALIZER , .Nm RB_INITIALIZER ,
.Nm RB_ROOT , .Nm RB_ROOT ,
.Nm RB_EMPTY , .Nm RB_EMPTY ,
.Nm RB_NEXT , .Nm RB_NEXT ,
.Nm RB_PREV ,
.Nm RB_MIN , .Nm RB_MIN ,
.Nm RB_MAX , .Nm RB_MAX ,
.Nm RB_FIND , .Nm RB_FIND ,
.Nm RB_NFIND ,
.Nm RB_LEFT , .Nm RB_LEFT ,
.Nm RB_RIGHT , .Nm RB_RIGHT ,
.Nm RB_PARENT , .Nm RB_PARENT ,
.Nm RB_FOREACH , .Nm RB_FOREACH ,
.Nm RB_FOREACH_REVERSE ,
.Nm RB_INIT , .Nm RB_INIT ,
.Nm RB_INSERT , .Nm RB_INSERT ,
.Nm RB_REMOVE .Nm RB_REMOVE
@ -78,7 +78,7 @@
.Ft "struct TYPE *" .Ft "struct TYPE *"
.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head" .Fn SPLAY_INITIALIZER "SPLAY_HEAD *head"
.Fn SPLAY_ROOT "SPLAY_HEAD *head" .Fn SPLAY_ROOT "SPLAY_HEAD *head"
.Ft "bool" .Ft "int"
.Fn SPLAY_EMPTY "SPLAY_HEAD *head" .Fn SPLAY_EMPTY "SPLAY_HEAD *head"
.Ft "struct TYPE *" .Ft "struct TYPE *"
.Fn SPLAY_NEXT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" .Fn SPLAY_NEXT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm"
@ -101,29 +101,36 @@
.Fn SPLAY_REMOVE "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" .Fn SPLAY_REMOVE "NAME" "SPLAY_HEAD *head" "struct TYPE *elm"
.Pp .Pp
.Fn RB_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP" .Fn RB_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP"
.Fn RB_PROTOTYPE_STATIC "NAME" "TYPE" "FIELD" "CMP"
.Fn RB_GENERATE "NAME" "TYPE" "FIELD" "CMP" .Fn RB_GENERATE "NAME" "TYPE" "FIELD" "CMP"
.Fn RB_GENERATE_STATIC "NAME" "TYPE" "FIELD" "CMP"
.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"
.Ft "struct TYPE *" .Ft "struct TYPE *"
.Fn RB_ROOT "RB_HEAD *head" .Fn RB_ROOT "RB_HEAD *head"
.Ft "bool" .Ft "int"
.Fn RB_EMPTY "RB_HEAD *head" .Fn RB_EMPTY "RB_HEAD *head"
.Ft "struct TYPE *" .Ft "struct TYPE *"
.Fn RB_NEXT "NAME" "RB_HEAD *head" "struct TYPE *elm" .Fn RB_NEXT "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *" .Ft "struct TYPE *"
.Fn RB_PREV "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
.Fn RB_MIN "NAME" "RB_HEAD *head" .Fn RB_MIN "NAME" "RB_HEAD *head"
.Ft "struct TYPE *" .Ft "struct TYPE *"
.Fn RB_MAX "NAME" "RB_HEAD *head" .Fn RB_MAX "NAME" "RB_HEAD *head"
.Ft "struct TYPE *" .Ft "struct TYPE *"
.Fn RB_FIND "NAME" "RB_HEAD *head" "struct TYPE *elm" .Fn RB_FIND "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *" .Ft "struct TYPE *"
.Fn RB_NFIND "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME" .Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME"
.Ft "struct TYPE *" .Ft "struct TYPE *"
.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME" .Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME"
.Ft "struct TYPE *" .Ft "struct TYPE *"
.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME" .Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME"
.Fn RB_FOREACH "VARNAME" "NAME" "RB_HEAD *head" .Fn RB_FOREACH "VARNAME" "NAME" "RB_HEAD *head"
.Fn RB_FOREACH_REVERSE "VARNAME" "NAME" "RB_HEAD *head"
.Ft void .Ft void
.Fn RB_INIT "RB_HEAD *head" .Fn RB_INIT "RB_HEAD *head"
.Ft "struct TYPE *" .Ft "struct TYPE *"
@ -136,12 +143,12 @@ splay trees and red-black trees.
.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 named
.Li SPLAY_ENTRY , .Fa FIELD ,
of type
.Li SPLAY_ENTRY
or or
.Li RB_ENTRY , .Li RB_ENTRY .
named
.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
@ -153,14 +160,16 @@ 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 either The function prototypes are declared with
.Li SPLAY_PROTOTYPE .Li SPLAY_PROTOTYPE ,
.Li RB_PROTOTYPE ,
or or
.Li RB_PROTOTYPE . .Li RB_PROTOTYPE_STATIC .
The function bodies are generated with either The function bodies are generated with
.Li SPLAY_GENERATE .Li SPLAY_GENERATE ,
.Li RB_GENERATE ,
or or
.Li RB_GENERATE . .Li 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.
@ -222,7 +231,7 @@ macro, but should be used only once.
Finally, Finally,
the the
.Fa CMP .Fa CMP
argument is the name of a function used to compare trees noded argument is the name of a function used to compare trees' nodes
with each other. with each other.
The function takes two arguments of type The function takes two arguments of type
.Fa "struct TYPE *" . .Fa "struct TYPE *" .
@ -328,7 +337,9 @@ macro declares a structure that allows elements to be connected in the tree.
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 RB_PROTOTYPE
macro, or
.Fn RB_PROTOTYPE_STATIC
macros,
where where
.Fa NAME .Fa NAME
is a unique identifier for this particular tree. is a unique identifier for this particular tree.
@ -343,15 +354,19 @@ argument is the name of the element defined by
.Pp .Pp
The function bodies are generated with the The function bodies are generated with the
.Fn RB_GENERATE .Fn RB_GENERATE
macro. or
It takes the same arguments as the .Fn RB_GENERATE_STATIC
macros.
These macros take the same arguments as the
.Fn RB_PROTOTYPE .Fn RB_PROTOTYPE
macro, but should be used only once. and
.Fn RB_PROTOTYPE_STATIC
macros, but should be used only once.
.Pp .Pp
Finally, Finally,
the the
.Fa CMP .Fa CMP
argument is the name of a function used to compare trees noded argument is the name of a function used to compare trees' nodes
with each other. with each other.
The function takes two arguments of type The function takes two arguments of type
.Fa "struct TYPE *" . .Fa "struct TYPE *" .
@ -378,6 +393,11 @@ The
macro inserts the new element macro inserts the new element
.Fa elm .Fa elm
into the tree. into the tree.
Upon success,
.Va NULL
is returned.
If a matching element already exists in the tree, the insertion is
aborted, and a pointer to the existing element is returned.
.Pp .Pp
The The
.Fn RB_REMOVE .Fn RB_REMOVE
@ -388,7 +408,14 @@ from the tree pointed by
.Pp .Pp
The The
.Fn RB_FIND .Fn RB_FIND
macro can be used to find a particular element in the tree. and
.Fn RB_NFIND
macros can be used to find a particular element in the tree.
.Fn RB_FIND
finds the node with the same key as
.Fa elm .
.Fn RB_NFIND
finds the first node greater than or equal to the search key.
.Bd -literal -offset indent .Bd -literal -offset indent
struct TYPE find, *res; struct TYPE find, *res;
find.key = 30; find.key = 30;
@ -399,8 +426,9 @@ The
.Fn RB_ROOT , .Fn RB_ROOT ,
.Fn RB_MIN , .Fn RB_MIN ,
.Fn RB_MAX , .Fn RB_MAX ,
.Fn RB_NEXT ,
and and
.Fn RB_NEXT .Fn RB_PREV
macros can be used to traverse the tree: macros can be used to traverse the tree:
.Bd -literal -offset indent .Bd -literal -offset indent
for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np)) for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np))
@ -408,7 +436,9 @@ 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 RB_FOREACH
macro: or
.Fn RB_FOREACH_REVERSE
macros:
.Bd -literal -offset indent .Bd -literal -offset indent
RB_FOREACH(np, NAME, &head) RB_FOREACH(np, NAME, &head)
.Ed .Ed
@ -436,7 +466,7 @@ struct node {
int int
intcmp(struct node *e1, struct node *e2) intcmp(struct node *e1, struct node *e2)
{ {
return (e1->i - e2->i); return (e1->i < e2->i ? -1 : e1->i > e2->i);
} }
RB_HEAD(inttree, node) head = RB_INITIALIZER(&head); RB_HEAD(inttree, node) head = RB_INITIALIZER(&head);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tree.h,v 1.9 2004/11/24 18:10:42 tdeval Exp $ */ /* $OpenBSD: tree.h,v 1.11 2008/05/11 22:19:09 millert Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved. * All rights reserved.
@ -374,20 +374,30 @@ struct { \
/* Generates prototypes and inline functions */ /* Generates prototypes and inline functions */
#define RB_PROTOTYPE(name, type, field, cmp) \ #define RB_PROTOTYPE(name, type, field, cmp) \
void name##_RB_INSERT_COLOR(struct name *, struct type *); \ RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ #define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
struct type *name##_RB_REMOVE(struct name *, struct type *); \ RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
struct type *name##_RB_INSERT(struct name *, struct type *); \ #define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
struct type *name##_RB_FIND(struct name *, struct type *); \ attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \
struct type *name##_RB_NEXT(struct type *); \ attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
struct type *name##_RB_MINMAX(struct name *, int); \ attr struct type *name##_RB_REMOVE(struct name *, struct type *); \
attr struct type *name##_RB_INSERT(struct name *, struct type *); \
attr struct type *name##_RB_FIND(struct name *, struct type *); \
attr struct type *name##_RB_NFIND(struct name *, struct type *); \
attr struct type *name##_RB_NEXT(struct type *); \
attr struct type *name##_RB_PREV(struct type *); \
attr struct type *name##_RB_MINMAX(struct name *, int); \
\ \
/* Main rb operation. /* Main rb operation.
* Moves node close to the key of elm to top * Moves node close to the key of elm to top
*/ */
#define RB_GENERATE(name, type, field, cmp) \ #define RB_GENERATE(name, type, field, cmp) \
void \ RB_GENERATE_INTERNAL(name, type, field, cmp,)
#define RB_GENERATE_STATIC(name, type, field, cmp) \
RB_GENERATE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
attr void \
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
{ \ { \
struct type *parent, *gparent, *tmp; \ struct type *parent, *gparent, *tmp; \
@ -431,7 +441,7 @@ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
RB_COLOR(head->rbh_root, field) = RB_BLACK; \ RB_COLOR(head->rbh_root, field) = RB_BLACK; \
} \ } \
\ \
void \ attr void \
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
{ \ { \
struct type *tmp; \ struct type *tmp; \
@ -507,7 +517,7 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
RB_COLOR(elm, field) = RB_BLACK; \ RB_COLOR(elm, field) = RB_BLACK; \
} \ } \
\ \
struct type * \ attr struct type * \
name##_RB_REMOVE(struct name *head, struct type *elm) \ name##_RB_REMOVE(struct name *head, struct type *elm) \
{ \ { \
struct type *child, *parent, *old = elm; \ struct type *child, *parent, *old = elm; \
@ -575,7 +585,7 @@ color: \
} \ } \
\ \
/* Inserts a node into the RB tree */ \ /* Inserts a node into the RB tree */ \
struct type * \ attr struct type * \
name##_RB_INSERT(struct name *head, struct type *elm) \ name##_RB_INSERT(struct name *head, struct type *elm) \
{ \ { \
struct type *tmp; \ struct type *tmp; \
@ -606,7 +616,7 @@ name##_RB_INSERT(struct name *head, struct type *elm) \
} \ } \
\ \
/* Finds the node with the same key as elm */ \ /* Finds the node with the same key as elm */ \
struct type * \ attr struct type * \
name##_RB_FIND(struct name *head, struct type *elm) \ name##_RB_FIND(struct name *head, struct type *elm) \
{ \ { \
struct type *tmp = RB_ROOT(head); \ struct type *tmp = RB_ROOT(head); \
@ -623,7 +633,29 @@ name##_RB_FIND(struct name *head, struct type *elm) \
return (NULL); \ return (NULL); \
} \ } \
\ \
struct type * \ /* Finds the first node greater than or equal to the search key */ \
attr struct type * \
name##_RB_NFIND(struct name *head, struct type *elm) \
{ \
struct type *tmp = RB_ROOT(head); \
struct type *res = NULL; \
int comp; \
while (tmp) { \
comp = cmp(elm, tmp); \
if (comp < 0) { \
res = tmp; \
tmp = RB_LEFT(tmp, field); \
} \
else if (comp > 0) \
tmp = RB_RIGHT(tmp, field); \
else \
return (tmp); \
} \
return (res); \
} \
\
/* ARGSUSED */ \
attr struct type * \
name##_RB_NEXT(struct type *elm) \ name##_RB_NEXT(struct type *elm) \
{ \ { \
if (RB_RIGHT(elm, field)) { \ if (RB_RIGHT(elm, field)) { \
@ -644,7 +676,29 @@ name##_RB_NEXT(struct type *elm) \
return (elm); \ return (elm); \
} \ } \
\ \
struct type * \ /* ARGSUSED */ \
attr struct type * \
name##_RB_PREV(struct type *elm) \
{ \
if (RB_LEFT(elm, field)) { \
elm = RB_LEFT(elm, field); \
while (RB_RIGHT(elm, field)) \
elm = RB_RIGHT(elm, field); \
} else { \
if (RB_PARENT(elm, field) && \
(elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
elm = RB_PARENT(elm, field); \
else { \
while (RB_PARENT(elm, field) && \
(elm == RB_LEFT(RB_PARENT(elm, field), field)))\
elm = RB_PARENT(elm, field); \
elm = RB_PARENT(elm, field); \
} \
} \
return (elm); \
} \
\
attr struct type * \
name##_RB_MINMAX(struct name *head, int val) \ name##_RB_MINMAX(struct name *head, int val) \
{ \ { \
struct type *tmp = RB_ROOT(head); \ struct type *tmp = RB_ROOT(head); \
@ -665,7 +719,9 @@ name##_RB_MINMAX(struct name *head, int val) \
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) #define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) #define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
#define RB_FIND(name, x, y) name##_RB_FIND(x, y) #define RB_FIND(name, x, y) name##_RB_FIND(x, y)
#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
#define RB_NEXT(name, x, y) name##_RB_NEXT(y) #define RB_NEXT(name, x, y) name##_RB_NEXT(y)
#define RB_PREV(name, x, y) name##_RB_PREV(y)
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) #define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) #define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
@ -674,4 +730,9 @@ name##_RB_MINMAX(struct name *head, int val) \
(x) != NULL; \ (x) != NULL; \
(x) = name##_RB_NEXT(x)) (x) = name##_RB_NEXT(x))
#define RB_FOREACH_REVERSE(x, name, head) \
for ((x) = RB_MAX(name, head); \
(x) != NULL; \
(x) = name##_RB_PREV(x))
#endif /* _SYS_TREE_H_ */ #endif /* _SYS_TREE_H_ */