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:
* 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>
.\" * All rights reserved.
@ -11,11 +11,6 @@
.\" * 2. Redistributions in binary form must reproduce the above copyright
.\" * notice, this list of conditions and the following disclaimer in the
.\" * 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
.\" * 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
.\" * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.Dd $Mdocdate$
.Dd $Mdocdate: January 28 2009 $
.Dt TREE 3
.Os
.Sh NAME
@ -50,20 +45,25 @@
.Nm SPLAY_INSERT ,
.Nm SPLAY_REMOVE ,
.Nm RB_PROTOTYPE ,
.Nm RB_PROTOTYPE_STATIC ,
.Nm RB_GENERATE ,
.Nm RB_GENERATE_STATIC ,
.Nm RB_ENTRY ,
.Nm RB_HEAD ,
.Nm RB_INITIALIZER ,
.Nm RB_ROOT ,
.Nm RB_EMPTY ,
.Nm RB_NEXT ,
.Nm RB_PREV ,
.Nm RB_MIN ,
.Nm RB_MAX ,
.Nm RB_FIND ,
.Nm RB_NFIND ,
.Nm RB_LEFT ,
.Nm RB_RIGHT ,
.Nm RB_PARENT ,
.Nm RB_FOREACH ,
.Nm RB_FOREACH_REVERSE ,
.Nm RB_INIT ,
.Nm RB_INSERT ,
.Nm RB_REMOVE
@ -78,7 +78,7 @@
.Ft "struct TYPE *"
.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head"
.Fn SPLAY_ROOT "SPLAY_HEAD *head"
.Ft "bool"
.Ft "int"
.Fn SPLAY_EMPTY "SPLAY_HEAD *head"
.Ft "struct TYPE *"
.Fn SPLAY_NEXT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm"
@ -101,29 +101,36 @@
.Fn SPLAY_REMOVE "NAME" "SPLAY_HEAD *head" "struct TYPE *elm"
.Pp
.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_STATIC "NAME" "TYPE" "FIELD" "CMP"
.Fn RB_ENTRY "TYPE"
.Fn RB_HEAD "HEADNAME" "TYPE"
.Fn RB_INITIALIZER "RB_HEAD *head"
.Ft "struct TYPE *"
.Fn RB_ROOT "RB_HEAD *head"
.Ft "bool"
.Ft "int"
.Fn RB_EMPTY "RB_HEAD *head"
.Ft "struct TYPE *"
.Fn RB_NEXT "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
.Fn RB_PREV "NAME" "RB_HEAD *head" "struct TYPE *elm"
.Ft "struct TYPE *"
.Fn RB_MIN "NAME" "RB_HEAD *head"
.Ft "struct TYPE *"
.Fn RB_MAX "NAME" "RB_HEAD *head"
.Ft "struct TYPE *"
.Fn RB_FIND "NAME" "RB_HEAD *head" "struct TYPE *elm"
.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"
.Ft "struct TYPE *"
.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME"
.Ft "struct TYPE *"
.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME"
.Fn RB_FOREACH "VARNAME" "NAME" "RB_HEAD *head"
.Fn RB_FOREACH_REVERSE "VARNAME" "NAME" "RB_HEAD *head"
.Ft void
.Fn RB_INIT "RB_HEAD *head"
.Ft "struct TYPE *"
@ -136,12 +143,12 @@ splay trees and red-black trees.
.Pp
In the macro definitions,
.Fa TYPE
is the name tag of a user defined structure that must contain a field of type
.Li SPLAY_ENTRY ,
is the name tag of a user defined structure that must contain a field named
.Fa FIELD ,
of type
.Li SPLAY_ENTRY
or
.Li RB_ENTRY ,
named
.Fa ENTRYNAME .
.Li RB_ENTRY .
The argument
.Fa HEADNAME
is the name tag of a user defined structure that must be declared
@ -153,14 +160,16 @@ The argument
.Fa NAME
has to be a unique name prefix for every tree that is defined.
.Pp
The function prototypes are declared with either
.Li SPLAY_PROTOTYPE
The function prototypes are declared with
.Li SPLAY_PROTOTYPE ,
.Li RB_PROTOTYPE ,
or
.Li RB_PROTOTYPE .
The function bodies are generated with either
.Li SPLAY_GENERATE
.Li RB_PROTOTYPE_STATIC .
The function bodies are generated with
.Li SPLAY_GENERATE ,
.Li RB_GENERATE ,
or
.Li RB_GENERATE .
.Li RB_GENERATE_STATIC .
See the examples below for further explanation of how these macros are used.
.Sh SPLAY TREES
A splay tree is a self-organizing data structure.
@ -222,7 +231,7 @@ macro, but should be used only once.
Finally,
the
.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.
The function takes two arguments of 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,
their prototypes need to be declared with the
.Fn RB_PROTOTYPE
macro,
or
.Fn RB_PROTOTYPE_STATIC
macros,
where
.Fa NAME
is a unique identifier for this particular tree.
@ -343,15 +354,19 @@ argument is the name of the element defined by
.Pp
The function bodies are generated with the
.Fn RB_GENERATE
macro.
It takes the same arguments as the
or
.Fn RB_GENERATE_STATIC
macros.
These macros take the same arguments as the
.Fn RB_PROTOTYPE
macro, but should be used only once.
and
.Fn RB_PROTOTYPE_STATIC
macros, but should be used only once.
.Pp
Finally,
the
.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.
The function takes two arguments of type
.Fa "struct TYPE *" .
@ -378,6 +393,11 @@ The
macro inserts the new element
.Fa elm
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
The
.Fn RB_REMOVE
@ -388,7 +408,14 @@ from the tree pointed by
.Pp
The
.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
struct TYPE find, *res;
find.key = 30;
@ -399,8 +426,9 @@ The
.Fn RB_ROOT ,
.Fn RB_MIN ,
.Fn RB_MAX ,
.Fn RB_NEXT ,
and
.Fn RB_NEXT
.Fn RB_PREV
macros can be used to traverse the tree:
.Bd -literal -offset indent
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
Or, for simplicity, one can use the
.Fn RB_FOREACH
macro:
or
.Fn RB_FOREACH_REVERSE
macros:
.Bd -literal -offset indent
RB_FOREACH(np, NAME, &head)
.Ed
@ -436,7 +466,7 @@ struct node {
int
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);

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>
* All rights reserved.
@ -374,20 +374,30 @@ struct { \
/* Generates prototypes and inline functions */
#define RB_PROTOTYPE(name, type, field, cmp) \
void name##_RB_INSERT_COLOR(struct name *, struct type *); \
void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
struct type *name##_RB_REMOVE(struct name *, struct type *); \
struct type *name##_RB_INSERT(struct name *, struct type *); \
struct type *name##_RB_FIND(struct name *, struct type *); \
struct type *name##_RB_NEXT(struct type *); \
struct type *name##_RB_MINMAX(struct name *, int); \
RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
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.
* Moves node close to the key of elm to top
*/
#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) \
{ \
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; \
} \
\
void \
attr void \
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
{ \
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; \
} \
\
struct type * \
attr struct type * \
name##_RB_REMOVE(struct name *head, struct type *elm) \
{ \
struct type *child, *parent, *old = elm; \
@ -575,7 +585,7 @@ color: \
} \
\
/* Inserts a node into the RB tree */ \
struct type * \
attr struct type * \
name##_RB_INSERT(struct name *head, struct type *elm) \
{ \
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 */ \
struct type * \
attr struct type * \
name##_RB_FIND(struct name *head, struct type *elm) \
{ \
struct type *tmp = RB_ROOT(head); \
@ -623,7 +633,29 @@ name##_RB_FIND(struct name *head, struct type *elm) \
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) \
{ \
if (RB_RIGHT(elm, field)) { \
@ -644,7 +676,29 @@ name##_RB_NEXT(struct type *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) \
{ \
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_REMOVE(name, x, y) name##_RB_REMOVE(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_PREV(name, x, y) name##_RB_PREV(y)
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
#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) = 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_ */