Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/newlib
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2021-10-05 16:43:34 +0300
committerSebastian Huber <sebastian.huber@embedded-brains.de>2021-10-05 18:21:18 +0300
commit5f7f27c81736c11c35c119cc5f18231eb8aaecec (patch)
tree0e7bbf1f046e58d034918a5e909a30c668e344e1 /newlib
parentee30f991c38851f1bfbbf72d19c5c6ee1b97f32a (diff)
sys/tree.h: Add parent rotations
Add specialized rotations RB_PARENT_ROTATE_LEFT() and RB_PARENT_ROTATE_RIGHT() which may be used if the parent node exists and the direction of the child is known. The specialized rotations are derived from RB_ROTATE_LEFT() and RB_ROTATE_RIGHT() where the RB_SWAP_CHILD() was replaced by a simple assignment.
Diffstat (limited to 'newlib')
-rw-r--r--newlib/libc/include/sys/tree.h43
1 files changed, 39 insertions, 4 deletions
diff --git a/newlib/libc/include/sys/tree.h b/newlib/libc/include/sys/tree.h
index 180809e9b..f6190f7f4 100644
--- a/newlib/libc/include/sys/tree.h
+++ b/newlib/libc/include/sys/tree.h
@@ -381,6 +381,37 @@ struct { \
RB_AUGMENT(elm); \
} while (/*CONSTCOND*/ 0)
+/*
+ * The RB_PARENT_ROTATE_LEFT() and RB_PARENT_ROTATE_RIGHT() rotations are
+ * specialized versions of RB_ROTATE_LEFT() and RB_ROTATE_RIGHT() which may be
+ * used if the parent node exists and the direction of the child element is
+ * known.
+ */
+
+#define RB_PARENT_ROTATE_LEFT(parent, left, tmp, field) do { \
+ (tmp) = RB_RIGHT(left, field); \
+ if ((RB_RIGHT(left, field) = RB_LEFT(tmp, field)) != NULL) { \
+ RB_SET_PARENT(RB_RIGHT(left, field), left, field); \
+ } \
+ RB_SET_PARENT(tmp, parent, field); \
+ RB_LEFT(parent, field) = (tmp); \
+ RB_LEFT(tmp, field) = (left); \
+ RB_SET_PARENT(left, tmp, field); \
+ RB_AUGMENT(left); \
+} while (/*CONSTCOND*/ 0)
+
+#define RB_PARENT_ROTATE_RIGHT(parent, right, tmp, field) do { \
+ (tmp) = RB_LEFT(right, field); \
+ if ((RB_LEFT(right, field) = RB_RIGHT(tmp, field)) != NULL) { \
+ RB_SET_PARENT(RB_LEFT(right, field), right, field); \
+ } \
+ RB_SET_PARENT(tmp, parent, field); \
+ RB_RIGHT(parent, field) = (tmp); \
+ RB_RIGHT(tmp, field) = (right); \
+ RB_SET_PARENT(right, tmp, field); \
+ RB_AUGMENT(right); \
+} while (/*CONSTCOND*/ 0)
+
/* Generates prototypes and inline functions */
#define RB_PROTOTYPE(name, type, field, cmp) \
RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
@@ -454,7 +485,8 @@ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
continue; \
} \
if (RB_RIGHT(parent, field) == elm) { \
- RB_ROTATE_LEFT(head, parent, tmp, field);\
+ RB_PARENT_ROTATE_LEFT(gparent, parent, \
+ tmp, field); \
tmp = parent; \
parent = elm; \
elm = tmp; \
@@ -470,7 +502,8 @@ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
continue; \
} \
if (RB_LEFT(parent, field) == elm) { \
- RB_ROTATE_RIGHT(head, parent, tmp, field);\
+ RB_PARENT_ROTATE_RIGHT(gparent, parent, \
+ tmp, field); \
tmp = parent; \
parent = elm; \
elm = tmp; \
@@ -500,7 +533,8 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent) \
RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK; \
else if (RB_ISRED(RB_LEFT(tmp, field), field)) { \
struct type *oleft; \
- RB_ROTATE_RIGHT(head, tmp, oleft, field); \
+ RB_PARENT_ROTATE_RIGHT(parent, tmp, \
+ oleft, field); \
RB_COLOR(oleft, field) = RB_BLACK; \
tmp = oleft; \
} else { \
@@ -525,7 +559,8 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent) \
RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK; \
else if (RB_ISRED(RB_RIGHT(tmp, field), field)) { \
struct type *oright; \
- RB_ROTATE_LEFT(head, tmp, oright, field); \
+ RB_PARENT_ROTATE_LEFT(parent, tmp, \
+ oright, field); \
RB_COLOR(oright, field) = RB_BLACK; \
tmp = oright; \
} else { \