⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rbt.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 5 页
字号:
						rotate_right(sibling, rootp);						sibling = RIGHT(parent);					}					COLOR(sibling) = COLOR(parent);					MAKE_BLACK(parent);					MAKE_BLACK(RIGHT(sibling));					rotate_left(parent, rootp);					child = *rootp;				}			} else {				/*				 * Child is parent's right child.				 * Everything is doen the same as above,				 * except mirrored.				 */				sibling = LEFT(parent);				if (IS_RED(sibling)) {					MAKE_BLACK(sibling);					MAKE_RED(parent);					rotate_right(parent, rootp);					sibling = LEFT(parent);				}				if (IS_BLACK(LEFT(sibling)) &&				    IS_BLACK(RIGHT(sibling))) {					MAKE_RED(sibling);					child = parent;				} else {					if (IS_BLACK(LEFT(sibling))) {						MAKE_BLACK(RIGHT(sibling));						MAKE_RED(sibling);						rotate_left(sibling, rootp);						sibling = LEFT(parent);					}					COLOR(sibling) = COLOR(parent);					MAKE_BLACK(parent);					MAKE_BLACK(LEFT(sibling));					rotate_right(parent, rootp);					child = *rootp;				}			}			parent = PARENT(child);		}		if (IS_RED(child))			MAKE_BLACK(child);	}}/* * This should only be used on the root of a tree, because no color fixup * is done at all. * * NOTE: No root pointer maintenance is done, because the function is only * used for two cases: * + deleting everything DOWN from a node that is itself being deleted, and * + deleting the entire tree of trees from dns_rbt_destroy. * In each case, the root pointer is no longer relevant, so there * is no need for a root parameter to this function. * * If the function is ever intended to be used to delete something where * a pointer needs to be told that this tree no longer exists, * this function would need to adjusted accordingly. */static voiddns_rbt_deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node) {	REQUIRE(VALID_RBT(rbt));	if (node == NULL)		return;	if (LEFT(node) != NULL)		dns_rbt_deletetree(rbt, LEFT(node));	if (RIGHT(node) != NULL)		dns_rbt_deletetree(rbt, RIGHT(node));	if (DOWN(node) != NULL)		dns_rbt_deletetree(rbt, DOWN(node));	if (DATA(node) != NULL && rbt->data_deleter != NULL)		rbt->data_deleter(DATA(node), rbt->deleter_arg);	unhash_node(rbt, node);	isc_mem_put(rbt->mctx, node, NODE_SIZE(node));	rbt->nodecount--;}static voiddns_rbt_indent(int depth) {	int i;	for (i = 0; i < depth; i++)		putchar('\t');}static voiddns_rbt_printnodename(dns_rbtnode_t *node) {	isc_buffer_t target;	isc_region_t r;	dns_name_t name;	char buffer[1024];	dns_offsets_t offsets;	r.length = NAMELEN(node);	r.base = NAME(node);	dns_name_init(&name, offsets);	dns_name_fromregion(&name, &r);	isc_buffer_init(&target, buffer, 255);	/*	 * ISC_FALSE means absolute names have the final dot added.	 */	dns_name_totext(&name, ISC_FALSE, &target);	printf("%.*s", (int)target.used, (char *)target.base);}static voiddns_rbt_printtree(dns_rbtnode_t *root, dns_rbtnode_t *parent, int depth) {	dns_rbt_indent(depth);	if (root != NULL) {		dns_rbt_printnodename(root);		printf(" (%s", IS_RED(root) ? "RED" : "black");		if (parent) {			printf(" from ");			dns_rbt_printnodename(parent);		}		if ((! IS_ROOT(root) && PARENT(root) != parent) ||		    (  IS_ROOT(root) && depth > 0 &&		       DOWN(PARENT(root)) != root)) {			printf(" (BAD parent pointer! -> ");			if (PARENT(root) != NULL)				dns_rbt_printnodename(PARENT(root));			else				printf("NULL");			printf(")");		}		printf(")\n");		depth++;		if (DOWN(root)) {			dns_rbt_indent(depth);			printf("++ BEG down from ");			dns_rbt_printnodename(root);			printf("\n");			dns_rbt_printtree(DOWN(root), NULL, depth);			dns_rbt_indent(depth);			printf("-- END down from ");			dns_rbt_printnodename(root);			printf("\n");		}		if (IS_RED(root) && IS_RED(LEFT(root)))		    printf("** Red/Red color violation on left\n");		dns_rbt_printtree(LEFT(root), root, depth);		if (IS_RED(root) && IS_RED(RIGHT(root)))		    printf("** Red/Red color violation on right\n");		dns_rbt_printtree(RIGHT(root), root, depth);	} else		printf("NULL\n");}voiddns_rbt_printall(dns_rbt_t *rbt) {	REQUIRE(VALID_RBT(rbt));	dns_rbt_printtree(rbt->root, NULL, 0);}/* * Chain Functions */voiddns_rbtnodechain_init(dns_rbtnodechain_t *chain, isc_mem_t *mctx) {	/*	 * Initialize 'chain'.	 */	REQUIRE(chain != NULL);	chain->mctx = mctx;	chain->end = NULL;	chain->level_count = 0;	chain->level_matches = 0;	chain->magic = CHAIN_MAGIC;}isc_result_tdns_rbtnodechain_current(dns_rbtnodechain_t *chain, dns_name_t *name,			 dns_name_t *origin, dns_rbtnode_t **node){	isc_result_t result = ISC_R_SUCCESS;	REQUIRE(VALID_CHAIN(chain));	if (node != NULL)		*node = chain->end;	if (chain->end == NULL)		return (ISC_R_NOTFOUND);	if (name != NULL) {		NODENAME(chain->end, name);		if (chain->level_count == 0) {			/*			 * Names in the top level tree are all absolute.			 * Always make 'name' relative.			 */			INSIST(dns_name_isabsolute(name));			/*			 * This is cheaper than dns_name_getlabelsequence().			 */			name->labels--;			name->length--;			name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;		}	}	if (origin != NULL) {		if (chain->level_count > 0)			result = chain_name(chain, origin, ISC_FALSE);		else			result = dns_name_copy(dns_rootname, origin, NULL);	}	return (result);}isc_result_tdns_rbtnodechain_prev(dns_rbtnodechain_t *chain, dns_name_t *name,		      dns_name_t *origin){	dns_rbtnode_t *current, *previous, *predecessor;	isc_result_t result = ISC_R_SUCCESS;	isc_boolean_t new_origin = ISC_FALSE;	REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);	predecessor = NULL;	current = chain->end;	if (LEFT(current) != NULL) {		/*		 * Moving left one then right as far as possible is the		 * previous node, at least for this level.		 */		current = LEFT(current);		while (RIGHT(current) != NULL)			current = RIGHT(current);		predecessor = current;	} else {		/*		 * No left links, so move toward the root.  If at any point on		 * the way there the link from parent to child is a right		 * link, then the parent is the previous node, at least		 * for this level.		 */		while (! IS_ROOT(current)) {			previous = current;			current = PARENT(current);			if (RIGHT(current) == previous) {				predecessor = current;				break;			}		}	}	if (predecessor != NULL) {		/*		 * Found a predecessor node in this level.  It might not		 * really be the predecessor, however.		 */		if (DOWN(predecessor) != NULL) {			/*			 * The predecessor is really down at least one level.			 * Go down and as far right as possible, and repeat			 * as long as the rightmost node has a down pointer.			 */			do {				/*				 * XXX DCL Need to do something about origins				 * here. See whether to go down, and if so				 * whether it is truly what Bob calls a				 * new origin.				 */				ADD_LEVEL(chain, predecessor);				predecessor = DOWN(predecessor);				/* XXX DCL duplicated from above; clever				 * way to unduplicate? */				while (RIGHT(predecessor) != NULL)					predecessor = RIGHT(predecessor);			} while (DOWN(predecessor) != NULL);			/* XXX DCL probably needs work on the concept */			if (origin != NULL)				new_origin = ISC_TRUE;		}	} else if (chain->level_count > 0) {		/*		 * Dang, didn't find a predecessor in this level.		 * Got to the root of this level without having traversed		 * any right links.  Ascend the tree one level; the		 * node that points to this tree is the predecessor.		 */		INSIST(chain->level_count > 0 && IS_ROOT(current));		predecessor = chain->levels[--chain->level_count];		/* XXX DCL probably needs work on the concept */		/*		 * Don't declare an origin change when the new origin is "."		 * at the top level tree, because "." is declared as the origin		 * for the second level tree.		 */		if (origin != NULL &&		    (chain->level_count > 0 || OFFSETLEN(predecessor) > 1))			new_origin = ISC_TRUE;	}	if (predecessor != NULL) {		chain->end = predecessor;		if (new_origin) {			result = dns_rbtnodechain_current(chain, name, origin,							  NULL);			if (result == ISC_R_SUCCESS)				result = DNS_R_NEWORIGIN;		} else			result = dns_rbtnodechain_current(chain, name, NULL,							  NULL);	} else		result = ISC_R_NOMORE;	return (result);}isc_result_tdns_rbtnodechain_next(dns_rbtnodechain_t *chain, dns_name_t *name,		      dns_name_t *origin){	dns_rbtnode_t *current, *previous, *successor;	isc_result_t result = ISC_R_SUCCESS;	isc_boolean_t new_origin = ISC_FALSE;	REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);	successor = NULL;	current = chain->end;	/*	 * If there is a level below this node, the next node is the leftmost	 * node of the next level.	 */	if (DOWN(current) != NULL) {		/*		 * Don't declare an origin change when the new origin is "."		 * at the second level tree, because "." is already declared		 * as the origin for the top level tree.		 */		if (chain->level_count > 0 ||		    OFFSETLEN(current) > 1)			new_origin = ISC_TRUE;		ADD_LEVEL(chain, current);		current = DOWN(current);		while (LEFT(current) != NULL)			current = LEFT(current);		successor = current;	} else if (RIGHT(current) == NULL) {		/*		 * The successor is up, either in this level or a previous one.		 * Head back toward the root of the tree, looking for any path		 * that was via a left link; the successor is the node that has		 * that left link.  In the event the root of the level is		 * reached without having traversed any left links, ascend one		 * level and look for either a right link off the point of		 * ascent, or search for a left link upward again, repeating		 * ascents until either case is true.		 */		do {			while (! IS_ROOT(current)) {				previous = current;				current = PARENT(current);				if (LEFT(current) == previous) {					successor = current;					break;				}			}			if (successor == NULL) {				/*				 * Reached the root without having traversed				 * any left pointers, so this level is done.				 */				if (chain->level_count == 0)					break;				current = chain->levels[--chain->level_count];				new_origin = ISC_TRUE;				if (RIGHT(current) != NULL)					break;			}		} while (successor == NULL);	}	if (successor == NULL && RIGHT(current) != NULL) {		current = RIGHT(current);		while (LEFT(current) != NULL)			current = LEFT(current);		successor = current;	}	if (successor != NULL) {		chain->end = successor;		/*		 * It is not necessary to use dns_rbtnodechain_current like		 * the other functions because this function will never		 * find a node in the topmost level.  This is because the		 * root level will never be more than one name, and everything		 * in the megatree is a successor to that node, down at		 * the second level or below.		 */		if (name != NULL)			NODENAME(chain->end, name);		if (new_origin) {			if (origin != NULL)				result = chain_name(chain, origin, ISC_FALSE);			if (result == ISC_R_SUCCESS)				result = DNS_R_NEWORIGIN;		} else			result = ISC_R_SUCCESS;	} else		result = ISC_R_NOMORE;	return (result);}isc_result_tdns_rbtnodechain_first(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,		       dns_name_t *name, dns_name_t *origin){	isc_result_t result;	REQUIRE(VALID_RBT(rbt));	REQUIRE(VALID_CHAIN(chain));	dns_rbtnodechain_reset(chain);	chain->end = rbt->root;	result = dns_rbtnodechain_current(chain, name, origin, NULL);	if (result == ISC_R_SUCCESS)		result = DNS_R_NEWORIGIN;	return (result);}isc_result_tdns_rbtnodechain_last(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,		       dns_name_t *name, dns_name_t *origin){	isc_result_t result;	REQUIRE(VALID_RBT(rbt));	REQUIRE(VALID_CHAIN(chain

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -