409 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			409 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/*========================================================================
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								//      rbtree.c
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								//      Red Black tree implementation
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								//========================================================================
							 | 
						||
| 
								 | 
							
								// ####ECOSGPLCOPYRIGHTBEGIN####                                            
							 | 
						||
| 
								 | 
							
								// -------------------------------------------                              
							 | 
						||
| 
								 | 
							
								// This file is part of eCos, the Embedded Configurable Operating System.   
							 | 
						||
| 
								 | 
							
								// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// eCos is free software; you can redistribute it and/or modify it under    
							 | 
						||
| 
								 | 
							
								// the terms of the GNU General Public License as published by the Free     
							 | 
						||
| 
								 | 
							
								// Software Foundation; either version 2 or (at your option) any later      
							 | 
						||
| 
								 | 
							
								// version.                                                                 
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// eCos 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 General Public License    
							 | 
						||
| 
								 | 
							
								// for more details.                                                        
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// You should have received a copy of the GNU General Public License        
							 | 
						||
| 
								 | 
							
								// along with eCos; if not, write to the Free Software Foundation, Inc.,    
							 | 
						||
| 
								 | 
							
								// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// As a special exception, if other files instantiate templates or use      
							 | 
						||
| 
								 | 
							
								// macros or inline functions from this file, or you compile this file      
							 | 
						||
| 
								 | 
							
								// and link it with other works to produce a work based on this file,       
							 | 
						||
| 
								 | 
							
								// this file does not by itself cause the resulting work to be covered by   
							 | 
						||
| 
								 | 
							
								// the GNU General Public License. However the source code for this file    
							 | 
						||
| 
								 | 
							
								// must still be made available in accordance with section (3) of the GNU   
							 | 
						||
| 
								 | 
							
								// General Public License v2.                                               
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// This exception does not invalidate any other reasons why a work based    
							 | 
						||
| 
								 | 
							
								// on this file might be covered by the GNU General Public License.         
							 | 
						||
| 
								 | 
							
								// -------------------------------------------                              
							 | 
						||
| 
								 | 
							
								// ####ECOSGPLCOPYRIGHTEND####                                              
							 | 
						||
| 
								 | 
							
								//========================================================================
							 | 
						||
| 
								 | 
							
								//#####DESCRIPTIONBEGIN####
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Author(s):     Niels Provos/OpenBSD
							 | 
						||
| 
								 | 
							
								// Contributors:  dwmw2
							 | 
						||
| 
								 | 
							
								// Date:          2003-01-21
							 | 
						||
| 
								 | 
							
								// Purpose:       This file provides an implementation of red-black trees.
							 | 
						||
| 
								 | 
							
								// Description:   Derived from OpenBSD src/sys/sys/tree.h
							 | 
						||
| 
								 | 
							
								// Usage:         
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								//####DESCRIPTIONEND####
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								//======================================================================
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*	$OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $	*/
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
							 | 
						||
| 
								 | 
							
								 * All rights reserved.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Redistribution and use in source and binary forms, with or without
							 | 
						||
| 
								 | 
							
								 * modification, are permitted provided that the following conditions
							 | 
						||
| 
								 | 
							
								 * are met:
							 | 
						||
| 
								 | 
							
								 * 1. Redistributions of source code must retain the above copyright
							 | 
						||
| 
								 | 
							
								 *    notice, this list of conditions and the following disclaimer.
							 | 
						||
| 
								 | 
							
								 * 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.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
							 | 
						||
| 
								 | 
							
								 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
							 | 
						||
| 
								 | 
							
								 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
							 | 
						||
| 
								 | 
							
								 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
							 | 
						||
| 
								 | 
							
								 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
							 | 
						||
| 
								 | 
							
								 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
							 | 
						||
| 
								 | 
							
								 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
							 | 
						||
| 
								 | 
							
								 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
							 | 
						||
| 
								 | 
							
								 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
							 | 
						||
| 
								 | 
							
								 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Fields renamed to match Linux ones. */
							 | 
						||
| 
								 | 
							
								#include <linux/rbtree.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define RB_HEAD(head)		(head)->rb_node
							 | 
						||
| 
								 | 
							
								#define RB_LEFT(elm)		(elm)->rb_left
							 | 
						||
| 
								 | 
							
								#define RB_RIGHT(elm)		(elm)->rb_right
							 | 
						||
| 
								 | 
							
								#define RB_PARENT(elm)		(elm)->rb_parent
							 | 
						||
| 
								 | 
							
								#define RB_COLOR(elm)		(elm)->rb_color
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define RB_SET(elm, parent) do {				\
							 | 
						||
| 
								 | 
							
									RB_PARENT(elm) = parent;				\
							 | 
						||
| 
								 | 
							
									RB_LEFT(elm) = RB_RIGHT(elm) = NULL;	\
							 | 
						||
| 
								 | 
							
									RB_COLOR(elm) = RB_RED;				\
							 | 
						||
| 
								 | 
							
								} while (0)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define RB_SET_BLACKRED(black, red) do {			\
							 | 
						||
| 
								 | 
							
									RB_COLOR(black) = RB_BLACK;				\
							 | 
						||
| 
								 | 
							
									RB_COLOR(red) = RB_RED;					\
							 | 
						||
| 
								 | 
							
								} while (0)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef RB_AUGMENT
							 | 
						||
| 
								 | 
							
								#define RB_AUGMENT(x)
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define RB_ROTATE_LEFT(head, elm, tmp) do {			\
							 | 
						||
| 
								 | 
							
									(tmp) = RB_RIGHT(elm);					\
							 | 
						||
| 
								 | 
							
									if ((RB_RIGHT(elm) = RB_LEFT(tmp))) {			\
							 | 
						||
| 
								 | 
							
										RB_PARENT(RB_LEFT(tmp)) = (elm);		\
							 | 
						||
| 
								 | 
							
									}							\
							 | 
						||
| 
								 | 
							
									RB_AUGMENT(elm);					\
							 | 
						||
| 
								 | 
							
									if ((RB_PARENT(tmp) = RB_PARENT(elm))) {		\
							 | 
						||
| 
								 | 
							
										if ((elm) == RB_LEFT(RB_PARENT(elm)))		\
							 | 
						||
| 
								 | 
							
											RB_LEFT(RB_PARENT(elm)) = (tmp);	\
							 | 
						||
| 
								 | 
							
										else						\
							 | 
						||
| 
								 | 
							
											RB_RIGHT(RB_PARENT(elm)) = (tmp);	\
							 | 
						||
| 
								 | 
							
									} else							\
							 | 
						||
| 
								 | 
							
										(head)->rb_node = (tmp);			\
							 | 
						||
| 
								 | 
							
									RB_LEFT(tmp) = (elm);					\
							 | 
						||
| 
								 | 
							
									RB_PARENT(elm) = (tmp);					\
							 | 
						||
| 
								 | 
							
									RB_AUGMENT(tmp);					\
							 | 
						||
| 
								 | 
							
									if ((RB_PARENT(tmp)))					\
							 | 
						||
| 
								 | 
							
										RB_AUGMENT(RB_PARENT(tmp));			\
							 | 
						||
| 
								 | 
							
								} while (0)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define RB_ROTATE_RIGHT(head, elm, tmp) do {			\
							 | 
						||
| 
								 | 
							
									(tmp) = RB_LEFT(elm);					\
							 | 
						||
| 
								 | 
							
									if ((RB_LEFT(elm) = RB_RIGHT(tmp))) {			\
							 | 
						||
| 
								 | 
							
										RB_PARENT(RB_RIGHT(tmp)) = (elm);		\
							 | 
						||
| 
								 | 
							
									}							\
							 | 
						||
| 
								 | 
							
									RB_AUGMENT(elm);					\
							 | 
						||
| 
								 | 
							
									if ((RB_PARENT(tmp) = RB_PARENT(elm))) {		\
							 | 
						||
| 
								 | 
							
										if ((elm) == RB_LEFT(RB_PARENT(elm)))		\
							 | 
						||
| 
								 | 
							
											RB_LEFT(RB_PARENT(elm)) = (tmp);	\
							 | 
						||
| 
								 | 
							
										else						\
							 | 
						||
| 
								 | 
							
											RB_RIGHT(RB_PARENT(elm)) = (tmp);	\
							 | 
						||
| 
								 | 
							
									} else							\
							 | 
						||
| 
								 | 
							
										(head)->rb_node = (tmp);			\
							 | 
						||
| 
								 | 
							
									RB_RIGHT(tmp) = (elm);					\
							 | 
						||
| 
								 | 
							
									RB_PARENT(elm) = (tmp);					\
							 | 
						||
| 
								 | 
							
									RB_AUGMENT(tmp);					\
							 | 
						||
| 
								 | 
							
									if ((RB_PARENT(tmp)))					\
							 | 
						||
| 
								 | 
							
										RB_AUGMENT(RB_PARENT(tmp));			\
							 | 
						||
| 
								 | 
							
								} while(0)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Note args swapped to match Linux */
							 | 
						||
| 
								 | 
							
								void rb_insert_color(struct rb_node *elm, struct rb_root *head)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									struct rb_node *parent, *gparent, *tmp;
							 | 
						||
| 
								 | 
							
									while ((parent = RB_PARENT(elm)) &&
							 | 
						||
| 
								 | 
							
									    RB_COLOR(parent) == RB_RED) {
							 | 
						||
| 
								 | 
							
										gparent = RB_PARENT(parent);
							 | 
						||
| 
								 | 
							
										if (parent == RB_LEFT(gparent)) {
							 | 
						||
| 
								 | 
							
											tmp = RB_RIGHT(gparent);
							 | 
						||
| 
								 | 
							
											if (tmp && RB_COLOR(tmp) == RB_RED) {
							 | 
						||
| 
								 | 
							
												RB_COLOR(tmp) = RB_BLACK;
							 | 
						||
| 
								 | 
							
												RB_SET_BLACKRED(parent, gparent);
							 | 
						||
| 
								 | 
							
												elm = gparent;
							 | 
						||
| 
								 | 
							
												continue;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											if (RB_RIGHT(parent) == elm) {
							 | 
						||
| 
								 | 
							
												RB_ROTATE_LEFT(head, parent, tmp);
							 | 
						||
| 
								 | 
							
												tmp = parent;
							 | 
						||
| 
								 | 
							
												parent = elm;
							 | 
						||
| 
								 | 
							
												elm = tmp;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											RB_SET_BLACKRED(parent, gparent);
							 | 
						||
| 
								 | 
							
											RB_ROTATE_RIGHT(head, gparent, tmp);
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											tmp = RB_LEFT(gparent);
							 | 
						||
| 
								 | 
							
											if (tmp && RB_COLOR(tmp) == RB_RED) {
							 | 
						||
| 
								 | 
							
												RB_COLOR(tmp) = RB_BLACK;
							 | 
						||
| 
								 | 
							
												RB_SET_BLACKRED(parent, gparent);
							 | 
						||
| 
								 | 
							
												elm = gparent;
							 | 
						||
| 
								 | 
							
												continue;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											if (RB_LEFT(parent) == elm) {
							 | 
						||
| 
								 | 
							
												RB_ROTATE_RIGHT(head, parent, tmp);
							 | 
						||
| 
								 | 
							
												tmp = parent;
							 | 
						||
| 
								 | 
							
												parent = elm;
							 | 
						||
| 
								 | 
							
												elm = tmp;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											RB_SET_BLACKRED(parent, gparent);
							 | 
						||
| 
								 | 
							
											RB_ROTATE_LEFT(head, gparent, tmp);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									RB_COLOR(head->rb_node) = RB_BLACK;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void rb_remove_color(struct rb_root *head, struct rb_node *parent,
							 | 
						||
| 
								 | 
							
											    struct rb_node *elm)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									struct rb_node *tmp;
							 | 
						||
| 
								 | 
							
									while ((elm == NULL || RB_COLOR(elm) == RB_BLACK) &&
							 | 
						||
| 
								 | 
							
									    elm != RB_HEAD(head)) {
							 | 
						||
| 
								 | 
							
										if (RB_LEFT(parent) == elm) {
							 | 
						||
| 
								 | 
							
											tmp = RB_RIGHT(parent);
							 | 
						||
| 
								 | 
							
											if (RB_COLOR(tmp) == RB_RED) {
							 | 
						||
| 
								 | 
							
												RB_SET_BLACKRED(tmp, parent);
							 | 
						||
| 
								 | 
							
												RB_ROTATE_LEFT(head, parent, tmp);
							 | 
						||
| 
								 | 
							
												tmp = RB_RIGHT(parent);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											if ((RB_LEFT(tmp) == NULL ||
							 | 
						||
| 
								 | 
							
											    RB_COLOR(RB_LEFT(tmp)) == RB_BLACK) &&
							 | 
						||
| 
								 | 
							
											    (RB_RIGHT(tmp) == NULL ||
							 | 
						||
| 
								 | 
							
											    RB_COLOR(RB_RIGHT(tmp)) == RB_BLACK)) {
							 | 
						||
| 
								 | 
							
												RB_COLOR(tmp) = RB_RED;
							 | 
						||
| 
								 | 
							
												elm = parent;
							 | 
						||
| 
								 | 
							
												parent = RB_PARENT(elm);
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												if (RB_RIGHT(tmp) == NULL ||
							 | 
						||
| 
								 | 
							
												    RB_COLOR(RB_RIGHT(tmp)) == RB_BLACK) {
							 | 
						||
| 
								 | 
							
													struct rb_node *oleft;
							 | 
						||
| 
								 | 
							
													if ((oleft = RB_LEFT(tmp)))
							 | 
						||
| 
								 | 
							
														RB_COLOR(oleft) = RB_BLACK;
							 | 
						||
| 
								 | 
							
													RB_COLOR(tmp) = RB_RED;
							 | 
						||
| 
								 | 
							
													RB_ROTATE_RIGHT(head, tmp, oleft);
							 | 
						||
| 
								 | 
							
													tmp = RB_RIGHT(parent);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												RB_COLOR(tmp) = RB_COLOR(parent);
							 | 
						||
| 
								 | 
							
												RB_COLOR(parent) = RB_BLACK;
							 | 
						||
| 
								 | 
							
												if (RB_RIGHT(tmp))
							 | 
						||
| 
								 | 
							
													RB_COLOR(RB_RIGHT(tmp)) = RB_BLACK;
							 | 
						||
| 
								 | 
							
												RB_ROTATE_LEFT(head, parent, tmp);
							 | 
						||
| 
								 | 
							
												elm = RB_HEAD(head);
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											tmp = RB_LEFT(parent);
							 | 
						||
| 
								 | 
							
											if (RB_COLOR(tmp) == RB_RED) {
							 | 
						||
| 
								 | 
							
												RB_SET_BLACKRED(tmp, parent);
							 | 
						||
| 
								 | 
							
												RB_ROTATE_RIGHT(head, parent, tmp);
							 | 
						||
| 
								 | 
							
												tmp = RB_LEFT(parent);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											if ((RB_LEFT(tmp) == NULL ||
							 | 
						||
| 
								 | 
							
											    RB_COLOR(RB_LEFT(tmp)) == RB_BLACK) &&
							 | 
						||
| 
								 | 
							
											    (RB_RIGHT(tmp) == NULL ||
							 | 
						||
| 
								 | 
							
											    RB_COLOR(RB_RIGHT(tmp)) == RB_BLACK)) {
							 | 
						||
| 
								 | 
							
												RB_COLOR(tmp) = RB_RED;
							 | 
						||
| 
								 | 
							
												elm = parent;
							 | 
						||
| 
								 | 
							
												parent = RB_PARENT(elm);
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												if (RB_LEFT(tmp) == NULL ||
							 | 
						||
| 
								 | 
							
												    RB_COLOR(RB_LEFT(tmp)) == RB_BLACK) {
							 | 
						||
| 
								 | 
							
													struct rb_node *oright;
							 | 
						||
| 
								 | 
							
													if ((oright = RB_RIGHT(tmp)))
							 | 
						||
| 
								 | 
							
														RB_COLOR(oright) = RB_BLACK;
							 | 
						||
| 
								 | 
							
													RB_COLOR(tmp) = RB_RED;
							 | 
						||
| 
								 | 
							
													RB_ROTATE_LEFT(head, tmp, oright);
							 | 
						||
| 
								 | 
							
													tmp = RB_LEFT(parent);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												RB_COLOR(tmp) = RB_COLOR(parent);
							 | 
						||
| 
								 | 
							
												RB_COLOR(parent) = RB_BLACK;
							 | 
						||
| 
								 | 
							
												if (RB_LEFT(tmp))
							 | 
						||
| 
								 | 
							
													RB_COLOR(RB_LEFT(tmp)) = RB_BLACK;
							 | 
						||
| 
								 | 
							
												RB_ROTATE_RIGHT(head, parent, tmp);
							 | 
						||
| 
								 | 
							
												elm = RB_HEAD(head);
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if (elm)
							 | 
						||
| 
								 | 
							
										RB_COLOR(elm) = RB_BLACK;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Note name changed. Guess why :) */
							 | 
						||
| 
								 | 
							
								void rb_erase(struct rb_node *elm, struct rb_root *head)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									struct rb_node *child, *parent, *old = elm;
							 | 
						||
| 
								 | 
							
									int color;
							 | 
						||
| 
								 | 
							
									if (RB_LEFT(elm) == NULL)
							 | 
						||
| 
								 | 
							
										child = RB_RIGHT(elm);
							 | 
						||
| 
								 | 
							
									else if (RB_RIGHT(elm) == NULL)
							 | 
						||
| 
								 | 
							
										child = RB_LEFT(elm);
							 | 
						||
| 
								 | 
							
									else {
							 | 
						||
| 
								 | 
							
										struct rb_node *left;
							 | 
						||
| 
								 | 
							
										elm = RB_RIGHT(elm);
							 | 
						||
| 
								 | 
							
										while ((left = RB_LEFT(elm)))
							 | 
						||
| 
								 | 
							
											elm = left;
							 | 
						||
| 
								 | 
							
										child = RB_RIGHT(elm);
							 | 
						||
| 
								 | 
							
										parent = RB_PARENT(elm);
							 | 
						||
| 
								 | 
							
										color = RB_COLOR(elm);
							 | 
						||
| 
								 | 
							
										if (child)
							 | 
						||
| 
								 | 
							
											RB_PARENT(child) = parent;
							 | 
						||
| 
								 | 
							
										if (parent) {
							 | 
						||
| 
								 | 
							
											if (RB_LEFT(parent) == elm)
							 | 
						||
| 
								 | 
							
												RB_LEFT(parent) = child;
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
												RB_RIGHT(parent) = child;
							 | 
						||
| 
								 | 
							
											RB_AUGMENT(parent);
							 | 
						||
| 
								 | 
							
										} else
							 | 
						||
| 
								 | 
							
											RB_HEAD(head) = child;
							 | 
						||
| 
								 | 
							
										if (RB_PARENT(elm) == old)
							 | 
						||
| 
								 | 
							
											parent = elm;
							 | 
						||
| 
								 | 
							
										*(elm) = *(old);
							 | 
						||
| 
								 | 
							
										if (RB_PARENT(old)) {
							 | 
						||
| 
								 | 
							
											if (RB_LEFT(RB_PARENT(old)) == old)
							 | 
						||
| 
								 | 
							
												RB_LEFT(RB_PARENT(old)) = elm;
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
												RB_RIGHT(RB_PARENT(old)) = elm;
							 | 
						||
| 
								 | 
							
											RB_AUGMENT(RB_PARENT(old));
							 | 
						||
| 
								 | 
							
										} else
							 | 
						||
| 
								 | 
							
											RB_HEAD(head) = elm;
							 | 
						||
| 
								 | 
							
										RB_PARENT(RB_LEFT(old)) = elm;
							 | 
						||
| 
								 | 
							
										if (RB_RIGHT(old))
							 | 
						||
| 
								 | 
							
											RB_PARENT(RB_RIGHT(old)) = elm;
							 | 
						||
| 
								 | 
							
										if (parent) {
							 | 
						||
| 
								 | 
							
											left = parent;
							 | 
						||
| 
								 | 
							
											do {
							 | 
						||
| 
								 | 
							
												RB_AUGMENT(left);
							 | 
						||
| 
								 | 
							
											} while ((left = RB_PARENT(left)));
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										goto color;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									parent = RB_PARENT(elm);
							 | 
						||
| 
								 | 
							
									color = RB_COLOR(elm);
							 | 
						||
| 
								 | 
							
									if (child)
							 | 
						||
| 
								 | 
							
										RB_PARENT(child) = parent;
							 | 
						||
| 
								 | 
							
									if (parent) {
							 | 
						||
| 
								 | 
							
										if (RB_LEFT(parent) == elm)
							 | 
						||
| 
								 | 
							
											RB_LEFT(parent) = child;
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
											RB_RIGHT(parent) = child;
							 | 
						||
| 
								 | 
							
										RB_AUGMENT(parent);
							 | 
						||
| 
								 | 
							
									} else
							 | 
						||
| 
								 | 
							
										RB_HEAD(head) = child;
							 | 
						||
| 
								 | 
							
								color:
							 | 
						||
| 
								 | 
							
									if (color == RB_BLACK)
							 | 
						||
| 
								 | 
							
										rb_remove_color(head, parent, child);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct rb_node *rb_next(struct rb_node *elm)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (RB_RIGHT(elm)) {
							 | 
						||
| 
								 | 
							
										elm = RB_RIGHT(elm);
							 | 
						||
| 
								 | 
							
										while (RB_LEFT(elm))
							 | 
						||
| 
								 | 
							
											elm = RB_LEFT(elm);
							 | 
						||
| 
								 | 
							
									} else {
							 | 
						||
| 
								 | 
							
										if (RB_PARENT(elm) &&
							 | 
						||
| 
								 | 
							
										    (elm == RB_LEFT(RB_PARENT(elm))))
							 | 
						||
| 
								 | 
							
											elm = RB_PARENT(elm);
							 | 
						||
| 
								 | 
							
										else {
							 | 
						||
| 
								 | 
							
											while (RB_PARENT(elm) &&
							 | 
						||
| 
								 | 
							
											    (elm == RB_RIGHT(RB_PARENT(elm))))
							 | 
						||
| 
								 | 
							
												elm = RB_PARENT(elm);
							 | 
						||
| 
								 | 
							
											elm = RB_PARENT(elm);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return (elm);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct rb_node *rb_prev(struct rb_node *elm)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (RB_LEFT(elm)) {
							 | 
						||
| 
								 | 
							
										elm = RB_LEFT(elm);
							 | 
						||
| 
								 | 
							
										while (RB_RIGHT(elm))
							 | 
						||
| 
								 | 
							
											elm = RB_RIGHT(elm);
							 | 
						||
| 
								 | 
							
									} else {
							 | 
						||
| 
								 | 
							
										if (RB_PARENT(elm) &&
							 | 
						||
| 
								 | 
							
										    (elm == RB_RIGHT(RB_PARENT(elm))))
							 | 
						||
| 
								 | 
							
											elm = RB_PARENT(elm);
							 | 
						||
| 
								 | 
							
										else {
							 | 
						||
| 
								 | 
							
											while (RB_PARENT(elm) &&
							 | 
						||
| 
								 | 
							
											    (elm == RB_LEFT(RB_PARENT(elm))))
							 | 
						||
| 
								 | 
							
												elm = RB_PARENT(elm);
							 | 
						||
| 
								 | 
							
											elm = RB_PARENT(elm);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return (elm);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* These ones are lifted from Linux -- but that's OK because I
							 | 
						||
| 
								 | 
							
								   wrote them. dwmw2. */
							 | 
						||
| 
								 | 
							
								struct rb_node *rb_first(struct rb_root *root)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								        struct rb_node  *n;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        n = root->rb_node;
							 | 
						||
| 
								 | 
							
								        if (!n)
							 | 
						||
| 
								 | 
							
								                return 0;
							 | 
						||
| 
								 | 
							
								        while (n->rb_left)
							 | 
						||
| 
								 | 
							
								                n = n->rb_left;
							 | 
						||
| 
								 | 
							
								        return n;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void rb_replace_node(struct rb_node *victim, struct rb_node *new,
							 | 
						||
| 
								 | 
							
								                     struct rb_root *root)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								        struct rb_node *parent = victim->rb_parent;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* Set the surrounding nodes to point to the replacement */
							 | 
						||
| 
								 | 
							
								        if (parent) {
							 | 
						||
| 
								 | 
							
								                if (victim == parent->rb_left)
							 | 
						||
| 
								 | 
							
								                        parent->rb_left = new;
							 | 
						||
| 
								 | 
							
								                else
							 | 
						||
| 
								 | 
							
								                        parent->rb_right = new;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								                root->rb_node = new;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (victim->rb_left)
							 | 
						||
| 
								 | 
							
								                victim->rb_left->rb_parent = new;
							 | 
						||
| 
								 | 
							
								        if (victim->rb_right)
							 | 
						||
| 
								 | 
							
								                victim->rb_right->rb_parent = new;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* Copy the pointers/colour from the victim to the replacement */
							 | 
						||
| 
								 | 
							
								        *new = *victim;
							 | 
						||
| 
								 | 
							
								}
							 |