Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
vkd3d
Manage
Activity
Members
Labels
Plan
Wiki
Bugzilla
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
wine
vkd3d
Commits
69e278e7
Commit
69e278e7
authored
7 years ago
by
Józef Kucia
Browse files
Options
Downloads
Patches
Plain Diff
include: Import red-black tree implementation from Wine.
parent
956c8b03
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
include/private/rbtree.h
+378
-0
378 additions, 0 deletions
include/private/rbtree.h
with
378 additions
and
0 deletions
include/private/rbtree.h
0 → 100644
+
378
−
0
View file @
69e278e7
/*
* Red-black search tree support
*
* Copyright 2009 Henri Verbeet
* Copyright 2009 Andrew Riedi
* Copyright 2016 Jacek Caban for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __WINE_WINE_RBTREE_H
#define __WINE_WINE_RBTREE_H
#define WINE_RB_ENTRY_VALUE(element, type, field) \
((type *)((char *)(element) - offsetof(type, field)))
struct
wine_rb_entry
{
struct
wine_rb_entry
*
parent
;
struct
wine_rb_entry
*
left
;
struct
wine_rb_entry
*
right
;
unsigned
int
flags
;
};
typedef
int
(
*
wine_rb_compare_func_t
)(
const
void
*
key
,
const
struct
wine_rb_entry
*
entry
);
struct
wine_rb_tree
{
wine_rb_compare_func_t
compare
;
struct
wine_rb_entry
*
root
;
};
typedef
void
(
wine_rb_traverse_func_t
)(
struct
wine_rb_entry
*
entry
,
void
*
context
);
#define WINE_RB_FLAG_RED 0x1
static
inline
int
wine_rb_is_red
(
struct
wine_rb_entry
*
entry
)
{
return
entry
&&
(
entry
->
flags
&
WINE_RB_FLAG_RED
);
}
static
inline
void
wine_rb_rotate_left
(
struct
wine_rb_tree
*
tree
,
struct
wine_rb_entry
*
e
)
{
struct
wine_rb_entry
*
right
=
e
->
right
;
if
(
!
e
->
parent
)
tree
->
root
=
right
;
else
if
(
e
->
parent
->
left
==
e
)
e
->
parent
->
left
=
right
;
else
e
->
parent
->
right
=
right
;
e
->
right
=
right
->
left
;
if
(
e
->
right
)
e
->
right
->
parent
=
e
;
right
->
left
=
e
;
right
->
parent
=
e
->
parent
;
e
->
parent
=
right
;
}
static
inline
void
wine_rb_rotate_right
(
struct
wine_rb_tree
*
tree
,
struct
wine_rb_entry
*
e
)
{
struct
wine_rb_entry
*
left
=
e
->
left
;
if
(
!
e
->
parent
)
tree
->
root
=
left
;
else
if
(
e
->
parent
->
left
==
e
)
e
->
parent
->
left
=
left
;
else
e
->
parent
->
right
=
left
;
e
->
left
=
left
->
right
;
if
(
e
->
left
)
e
->
left
->
parent
=
e
;
left
->
right
=
e
;
left
->
parent
=
e
->
parent
;
e
->
parent
=
left
;
}
static
inline
void
wine_rb_flip_color
(
struct
wine_rb_entry
*
entry
)
{
entry
->
flags
^=
WINE_RB_FLAG_RED
;
entry
->
left
->
flags
^=
WINE_RB_FLAG_RED
;
entry
->
right
->
flags
^=
WINE_RB_FLAG_RED
;
}
static
inline
struct
wine_rb_entry
*
wine_rb_head
(
struct
wine_rb_entry
*
iter
)
{
if
(
!
iter
)
return
NULL
;
while
(
iter
->
left
)
iter
=
iter
->
left
;
return
iter
;
}
static
inline
struct
wine_rb_entry
*
wine_rb_next
(
struct
wine_rb_entry
*
iter
)
{
if
(
iter
->
right
)
return
wine_rb_head
(
iter
->
right
);
while
(
iter
->
parent
&&
iter
->
parent
->
right
==
iter
)
iter
=
iter
->
parent
;
return
iter
->
parent
;
}
static
inline
struct
wine_rb_entry
*
wine_rb_postorder_head
(
struct
wine_rb_entry
*
iter
)
{
if
(
!
iter
)
return
NULL
;
for
(;;)
{
while
(
iter
->
left
)
iter
=
iter
->
left
;
if
(
!
iter
->
right
)
return
iter
;
iter
=
iter
->
right
;
}
}
static
inline
struct
wine_rb_entry
*
wine_rb_postorder_next
(
struct
wine_rb_entry
*
iter
)
{
if
(
!
iter
->
parent
)
return
NULL
;
if
(
iter
==
iter
->
parent
->
right
||
!
iter
->
parent
->
right
)
return
iter
->
parent
;
return
wine_rb_postorder_head
(
iter
->
parent
->
right
);
}
/* iterate through the tree */
#define WINE_RB_FOR_EACH(cursor, tree) \
for ((cursor) = wine_rb_head((tree)->root); (cursor); (cursor) = wine_rb_next(cursor))
/* iterate through the tree using a tree entry */
#define WINE_RB_FOR_EACH_ENTRY(elem, tree, type, field) \
for ((elem) = WINE_RB_ENTRY_VALUE(wine_rb_head((tree)->root), type, field); \
&(elem)->field; \
(elem) = WINE_RB_ENTRY_VALUE(wine_rb_next(&elem->field), type, field))
/* iterate through the tree using using postorder, making it safe to free the entry */
#define WINE_RB_FOR_EACH_DESTRUCTOR(cursor, cursor2, tree) \
for ((cursor) = wine_rb_postorder_head((tree)->root); \
(cursor) && (((cursor2) = wine_rb_postorder_next(cursor)) || 1); \
(cursor) = (cursor2))
/* iterate through the tree using a tree entry and postorder, making it safe to free the entry */
#define WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR(elem, elem2, tree, type, field) \
for ((elem) = WINE_RB_ENTRY_VALUE(wine_rb_postorder_head((tree)->root), type, field); \
&(elem)->field \
&& (((elem2) = WINE_RB_ENTRY_VALUE(wine_rb_postorder_next(&(elem)->field), type, field)) || 1); \
(elem) = (elem2))
static
inline
void
wine_rb_postorder
(
struct
wine_rb_tree
*
tree
,
wine_rb_traverse_func_t
*
callback
,
void
*
context
)
{
struct
wine_rb_entry
*
iter
,
*
next
;
WINE_RB_FOR_EACH_DESTRUCTOR
(
iter
,
next
,
tree
)
callback
(
iter
,
context
);
}
static
inline
void
wine_rb_init
(
struct
wine_rb_tree
*
tree
,
wine_rb_compare_func_t
compare
)
{
tree
->
compare
=
compare
;
tree
->
root
=
NULL
;
}
static
inline
void
wine_rb_for_each_entry
(
struct
wine_rb_tree
*
tree
,
wine_rb_traverse_func_t
*
callback
,
void
*
context
)
{
struct
wine_rb_entry
*
iter
;
WINE_RB_FOR_EACH
(
iter
,
tree
)
callback
(
iter
,
context
);
}
static
inline
void
wine_rb_clear
(
struct
wine_rb_tree
*
tree
,
wine_rb_traverse_func_t
*
callback
,
void
*
context
)
{
/* Note that we use postorder here because the callback will likely free the entry. */
if
(
callback
)
wine_rb_postorder
(
tree
,
callback
,
context
);
tree
->
root
=
NULL
;
}
static
inline
void
wine_rb_destroy
(
struct
wine_rb_tree
*
tree
,
wine_rb_traverse_func_t
*
callback
,
void
*
context
)
{
wine_rb_clear
(
tree
,
callback
,
context
);
}
static
inline
struct
wine_rb_entry
*
wine_rb_get
(
const
struct
wine_rb_tree
*
tree
,
const
void
*
key
)
{
struct
wine_rb_entry
*
entry
=
tree
->
root
;
while
(
entry
)
{
int
c
=
tree
->
compare
(
key
,
entry
);
if
(
!
c
)
return
entry
;
entry
=
c
<
0
?
entry
->
left
:
entry
->
right
;
}
return
NULL
;
}
static
inline
int
wine_rb_put
(
struct
wine_rb_tree
*
tree
,
const
void
*
key
,
struct
wine_rb_entry
*
entry
)
{
struct
wine_rb_entry
**
iter
=
&
tree
->
root
,
*
parent
=
tree
->
root
;
while
(
*
iter
)
{
int
c
;
parent
=
*
iter
;
c
=
tree
->
compare
(
key
,
parent
);
if
(
!
c
)
return
-
1
;
else
if
(
c
<
0
)
iter
=
&
parent
->
left
;
else
iter
=
&
parent
->
right
;
}
entry
->
flags
=
WINE_RB_FLAG_RED
;
entry
->
parent
=
parent
;
entry
->
left
=
NULL
;
entry
->
right
=
NULL
;
*
iter
=
entry
;
while
(
wine_rb_is_red
(
entry
->
parent
))
{
if
(
entry
->
parent
==
entry
->
parent
->
parent
->
left
)
{
if
(
wine_rb_is_red
(
entry
->
parent
->
parent
->
right
))
{
wine_rb_flip_color
(
entry
->
parent
->
parent
);
entry
=
entry
->
parent
->
parent
;
}
else
{
if
(
entry
==
entry
->
parent
->
right
)
{
entry
=
entry
->
parent
;
wine_rb_rotate_left
(
tree
,
entry
);
}
entry
->
parent
->
flags
&=
~
WINE_RB_FLAG_RED
;
entry
->
parent
->
parent
->
flags
|=
WINE_RB_FLAG_RED
;
wine_rb_rotate_right
(
tree
,
entry
->
parent
->
parent
);
}
}
else
{
if
(
wine_rb_is_red
(
entry
->
parent
->
parent
->
left
))
{
wine_rb_flip_color
(
entry
->
parent
->
parent
);
entry
=
entry
->
parent
->
parent
;
}
else
{
if
(
entry
==
entry
->
parent
->
left
)
{
entry
=
entry
->
parent
;
wine_rb_rotate_right
(
tree
,
entry
);
}
entry
->
parent
->
flags
&=
~
WINE_RB_FLAG_RED
;
entry
->
parent
->
parent
->
flags
|=
WINE_RB_FLAG_RED
;
wine_rb_rotate_left
(
tree
,
entry
->
parent
->
parent
);
}
}
}
tree
->
root
->
flags
&=
~
WINE_RB_FLAG_RED
;
return
0
;
}
static
inline
void
wine_rb_remove
(
struct
wine_rb_tree
*
tree
,
struct
wine_rb_entry
*
entry
)
{
struct
wine_rb_entry
*
iter
,
*
child
,
*
parent
,
*
w
;
int
need_fixup
;
if
(
entry
->
right
&&
entry
->
left
)
for
(
iter
=
entry
->
right
;
iter
->
left
;
iter
=
iter
->
left
);
else
iter
=
entry
;
child
=
iter
->
left
?
iter
->
left
:
iter
->
right
;
if
(
!
iter
->
parent
)
tree
->
root
=
child
;
else
if
(
iter
==
iter
->
parent
->
left
)
iter
->
parent
->
left
=
child
;
else
iter
->
parent
->
right
=
child
;
if
(
child
)
child
->
parent
=
iter
->
parent
;
parent
=
iter
->
parent
;
need_fixup
=
!
wine_rb_is_red
(
iter
);
if
(
entry
!=
iter
)
{
*
iter
=
*
entry
;
if
(
!
iter
->
parent
)
tree
->
root
=
iter
;
else
if
(
entry
==
iter
->
parent
->
left
)
iter
->
parent
->
left
=
iter
;
else
iter
->
parent
->
right
=
iter
;
if
(
iter
->
right
)
iter
->
right
->
parent
=
iter
;
if
(
iter
->
left
)
iter
->
left
->
parent
=
iter
;
if
(
parent
==
entry
)
parent
=
iter
;
}
if
(
need_fixup
)
{
while
(
parent
&&
!
wine_rb_is_red
(
child
))
{
if
(
child
==
parent
->
left
)
{
w
=
parent
->
right
;
if
(
wine_rb_is_red
(
w
))
{
w
->
flags
&=
~
WINE_RB_FLAG_RED
;
parent
->
flags
|=
WINE_RB_FLAG_RED
;
wine_rb_rotate_left
(
tree
,
parent
);
w
=
parent
->
right
;
}
if
(
wine_rb_is_red
(
w
->
left
)
||
wine_rb_is_red
(
w
->
right
))
{
if
(
!
wine_rb_is_red
(
w
->
right
))
{
w
->
left
->
flags
&=
~
WINE_RB_FLAG_RED
;
w
->
flags
|=
WINE_RB_FLAG_RED
;
wine_rb_rotate_right
(
tree
,
w
);
w
=
parent
->
right
;
}
w
->
flags
=
(
w
->
flags
&
~
WINE_RB_FLAG_RED
)
|
(
parent
->
flags
&
WINE_RB_FLAG_RED
);
parent
->
flags
&=
~
WINE_RB_FLAG_RED
;
if
(
w
->
right
)
w
->
right
->
flags
&=
~
WINE_RB_FLAG_RED
;
wine_rb_rotate_left
(
tree
,
parent
);
child
=
NULL
;
break
;
}
}
else
{
w
=
parent
->
left
;
if
(
wine_rb_is_red
(
w
))
{
w
->
flags
&=
~
WINE_RB_FLAG_RED
;
parent
->
flags
|=
WINE_RB_FLAG_RED
;
wine_rb_rotate_right
(
tree
,
parent
);
w
=
parent
->
left
;
}
if
(
wine_rb_is_red
(
w
->
left
)
||
wine_rb_is_red
(
w
->
right
))
{
if
(
!
wine_rb_is_red
(
w
->
left
))
{
w
->
right
->
flags
&=
~
WINE_RB_FLAG_RED
;
w
->
flags
|=
WINE_RB_FLAG_RED
;
wine_rb_rotate_left
(
tree
,
w
);
w
=
parent
->
left
;
}
w
->
flags
=
(
w
->
flags
&
~
WINE_RB_FLAG_RED
)
|
(
parent
->
flags
&
WINE_RB_FLAG_RED
);
parent
->
flags
&=
~
WINE_RB_FLAG_RED
;
if
(
w
->
left
)
w
->
left
->
flags
&=
~
WINE_RB_FLAG_RED
;
wine_rb_rotate_right
(
tree
,
parent
);
child
=
NULL
;
break
;
}
}
w
->
flags
|=
WINE_RB_FLAG_RED
;
child
=
parent
;
parent
=
child
->
parent
;
}
if
(
child
)
child
->
flags
&=
~
WINE_RB_FLAG_RED
;
}
if
(
tree
->
root
)
tree
->
root
->
flags
&=
~
WINE_RB_FLAG_RED
;
}
static
inline
void
wine_rb_remove_key
(
struct
wine_rb_tree
*
tree
,
const
void
*
key
)
{
struct
wine_rb_entry
*
entry
=
wine_rb_get
(
tree
,
key
);
if
(
entry
)
wine_rb_remove
(
tree
,
entry
);
}
#endif
/* __WINE_WINE_RBTREE_H */
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment