7 changed files with 3497 additions and 1 deletions
			
			
		@ -0,0 +1,380 @@ | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2013-2014 Andrew Smith - BlackArrow Ltd | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * This program 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 3 of the License, or (at your option) | 
				
			||||||
 | 
					 * any later version.  See COPYING for more details. | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "klist.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void k_alloc_items(K_LIST *list, KLIST_FFL_ARGS) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						K_ITEM *item; | 
				
			||||||
 | 
						int allocate, i; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (list->is_store) { | 
				
			||||||
 | 
							quithere(1, "List %s store can't %s()" KLIST_FFL, | 
				
			||||||
 | 
									list->name, __func__, KLIST_FFL_PASS); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (list->limit > 0 && list->total >= list->limit) | 
				
			||||||
 | 
							return; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						allocate = list->allocate; | 
				
			||||||
 | 
						if (list->limit > 0 && (list->total + allocate) > list->limit) | 
				
			||||||
 | 
							allocate = list->limit - list->total; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list->item_mem_count++; | 
				
			||||||
 | 
						if (!(list->item_memory = realloc(list->item_memory, | 
				
			||||||
 | 
										  list->item_mem_count * sizeof(*(list->item_memory))))) { | 
				
			||||||
 | 
							quithere(1, "List %s item_memory failed to realloc count=%d", | 
				
			||||||
 | 
									list->name, list->item_mem_count); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						item = calloc(allocate, sizeof(*item)); | 
				
			||||||
 | 
						if (!item) { | 
				
			||||||
 | 
							quithere(1, "List %s failed to calloc %d new items - total was %d, limit was %d", | 
				
			||||||
 | 
									list->name, allocate, list->total, list->limit); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						list->item_memory[list->item_mem_count - 1] = (void *)item; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list->total += allocate; | 
				
			||||||
 | 
						list->count = allocate; | 
				
			||||||
 | 
						list->count_up = allocate; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						item[0].name = list->name; | 
				
			||||||
 | 
						item[0].prev = NULL; | 
				
			||||||
 | 
						item[0].next = &(item[1]); | 
				
			||||||
 | 
						for (i = 1; i < allocate-1; i++) { | 
				
			||||||
 | 
							item[i].name = list->name; | 
				
			||||||
 | 
							item[i].prev = &item[i-1]; | 
				
			||||||
 | 
							item[i].next = &item[i+1]; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						item[allocate-1].name = list->name; | 
				
			||||||
 | 
						item[allocate-1].prev = &(item[allocate-2]); | 
				
			||||||
 | 
						item[allocate-1].next = NULL; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list->head = item; | 
				
			||||||
 | 
						if (list->do_tail) | 
				
			||||||
 | 
							list->tail = &(item[allocate-1]); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						item = list->head; | 
				
			||||||
 | 
						while (item) { | 
				
			||||||
 | 
							list->data_mem_count++; | 
				
			||||||
 | 
							if (!(list->data_memory = realloc(list->data_memory, | 
				
			||||||
 | 
											  list->data_mem_count * | 
				
			||||||
 | 
											  sizeof(*(list->data_memory))))) { | 
				
			||||||
 | 
								quithere(1, "List %s data_memory failed to realloc count=%d", | 
				
			||||||
 | 
										list->name, list->data_mem_count); | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
							item->data = calloc(1, list->siz); | 
				
			||||||
 | 
							if (!(item->data)) | 
				
			||||||
 | 
								quithere(1, "List %s failed to calloc item data", list->name); | 
				
			||||||
 | 
							list->data_memory[list->data_mem_count - 1] = (void *)(item->data); | 
				
			||||||
 | 
							item = item->next; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					K_STORE *k_new_store(K_LIST *list) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						K_STORE *store; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						store = calloc(1, sizeof(*store)); | 
				
			||||||
 | 
						if (!store) | 
				
			||||||
 | 
							quithere(1, "Failed to calloc store for %s", list->name); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						store->is_store = true; | 
				
			||||||
 | 
						store->lock = list->lock; | 
				
			||||||
 | 
						store->name = list->name; | 
				
			||||||
 | 
						store->do_tail = list->do_tail; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return store; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					K_LIST *_k_new_list(const char *name, size_t siz, int allocate, int limit, bool do_tail, KLIST_FFL_ARGS) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						K_LIST *list; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (allocate < 1) | 
				
			||||||
 | 
							quithere(1, "Invalid new list %s with allocate %d must be > 0", name, allocate); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (limit < 0) | 
				
			||||||
 | 
							quithere(1, "Invalid new list %s with limit %d must be >= 0", name, limit); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list = calloc(1, sizeof(*list)); | 
				
			||||||
 | 
						if (!list) | 
				
			||||||
 | 
							quithere(1, "Failed to calloc list %s", name); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list->is_store = false; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list->lock = calloc(1, sizeof(*(list->lock))); | 
				
			||||||
 | 
						if (!(list->lock)) | 
				
			||||||
 | 
							quithere(1, "Failed to calloc lock for list %s", name); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cklock_init(list->lock); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list->name = name; | 
				
			||||||
 | 
						list->siz = siz; | 
				
			||||||
 | 
						list->allocate = allocate; | 
				
			||||||
 | 
						list->limit = limit; | 
				
			||||||
 | 
						list->do_tail = do_tail; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						k_alloc_items(list, KLIST_FFL_PASS); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return list; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Unlink and return the head of the list | 
				
			||||||
 | 
					 * If the list is empty: | 
				
			||||||
 | 
					 * 1) If it's a store - return NULL | 
				
			||||||
 | 
					 * 2) alloc a new list and return the head - | 
				
			||||||
 | 
					 *	which is NULL if the list limit has been reached | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					K_ITEM *_k_unlink_head(K_LIST *list, KLIST_FFL_ARGS) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						K_ITEM *item; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(list->head) && !(list->is_store)) | 
				
			||||||
 | 
							k_alloc_items(list, KLIST_FFL_PASS); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(list->head)) | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						item = list->head; | 
				
			||||||
 | 
						list->head = item->next; | 
				
			||||||
 | 
						if (list->head) | 
				
			||||||
 | 
							list->head->prev = NULL; | 
				
			||||||
 | 
						else { | 
				
			||||||
 | 
							if (list->do_tail) | 
				
			||||||
 | 
								list->tail = NULL; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						item->prev = item->next = NULL; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list->count--; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return item; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Zeros the head returned
 | 
				
			||||||
 | 
					K_ITEM *_k_unlink_head_zero(K_LIST *list, KLIST_FFL_ARGS) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						K_ITEM *item; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						item = _k_unlink_head(list, KLIST_FFL_PASS); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (item) | 
				
			||||||
 | 
							memset(item->data, 0, list->siz); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return item; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Returns NULL if empty
 | 
				
			||||||
 | 
					K_ITEM *_k_unlink_tail(K_LIST *list, KLIST_FFL_ARGS) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						K_ITEM *item; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(list->do_tail)) { | 
				
			||||||
 | 
							quithere(1, "List %s can't %s() - do_tail is false" KLIST_FFL, | 
				
			||||||
 | 
									list->name, __func__, KLIST_FFL_PASS); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(list->tail)) | 
				
			||||||
 | 
							return NULL; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						item = list->tail; | 
				
			||||||
 | 
						list->tail = item->prev; | 
				
			||||||
 | 
						if (list->tail) | 
				
			||||||
 | 
							list->tail->next = NULL; | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
							list->head = NULL; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						item->prev = item->next = NULL; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list->count--; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return item; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void _k_add_head(K_LIST *list, K_ITEM *item, KLIST_FFL_ARGS) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						if (item->name != list->name) { | 
				
			||||||
 | 
							quithere(1, "List %s can't %s() a %s item" KLIST_FFL, | 
				
			||||||
 | 
									list->name, __func__, item->name, KLIST_FFL_PASS); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						item->prev = NULL; | 
				
			||||||
 | 
						item->next = list->head; | 
				
			||||||
 | 
						if (list->head) | 
				
			||||||
 | 
							list->head->prev = item; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list->head = item; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (list->do_tail) { | 
				
			||||||
 | 
							if (!(list->tail)) | 
				
			||||||
 | 
								list->tail = item; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list->count++; | 
				
			||||||
 | 
						list->count_up++; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* slows it down (of course) - only for debugging
 | 
				
			||||||
 | 
					void _k_free_head(K_LIST *list, K_ITEM *item, KLIST_FFL_ARGS) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						memset(item->data, 0xff, list->siz); | 
				
			||||||
 | 
						_k_add_head(list, item, KLIST_FFL_PASS); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					*/ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void _k_add_tail(K_LIST *list, K_ITEM *item, KLIST_FFL_ARGS) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						if (item->name != list->name) { | 
				
			||||||
 | 
							quithere(1, "List %s can't %s() a %s item" KLIST_FFL, | 
				
			||||||
 | 
									list->name, __func__, item->name, KLIST_FFL_PASS); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(list->do_tail)) { | 
				
			||||||
 | 
							quithere(1, "List %s can't %s() - do_tail is false" KLIST_FFL, | 
				
			||||||
 | 
									list->name, __func__, KLIST_FFL_PASS); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						item->prev = list->tail; | 
				
			||||||
 | 
						item->next = NULL; | 
				
			||||||
 | 
						if (list->tail) | 
				
			||||||
 | 
							list->tail->next = item; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list->tail = item; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(list->head)) | 
				
			||||||
 | 
							list->head = item; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list->count++; | 
				
			||||||
 | 
						list->count_up++; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void _k_unlink_item(K_LIST *list, K_ITEM *item, KLIST_FFL_ARGS) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						if (item->name != list->name) { | 
				
			||||||
 | 
							quithere(1, "List %s can't %s() a %s item" KLIST_FFL, | 
				
			||||||
 | 
									list->name, __func__, item->name, KLIST_FFL_PASS); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (item->prev) | 
				
			||||||
 | 
							item->prev->next = item->next; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (item->next) | 
				
			||||||
 | 
							item->next->prev = item->prev; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (list->head == item) | 
				
			||||||
 | 
							list->head = item->next; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (list->do_tail) { | 
				
			||||||
 | 
							if (list->tail == item) | 
				
			||||||
 | 
								list->tail = item->prev; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						item->prev = item->next = NULL; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list->count--; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void _k_list_transfer_to_head(K_LIST *from, K_LIST *to, KLIST_FFL_ARGS) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						if (from->name != to->name) { | 
				
			||||||
 | 
							quithere(1, "List %s can't %s() to a %s list" KLIST_FFL, | 
				
			||||||
 | 
									from->name, __func__, to->name, KLIST_FFL_PASS); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(from->do_tail)) { | 
				
			||||||
 | 
							quithere(1, "List %s can't %s() - do_tail is false" KLIST_FFL, | 
				
			||||||
 | 
									from->name, __func__, KLIST_FFL_PASS); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(from->head)) | 
				
			||||||
 | 
							return; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (to->head) | 
				
			||||||
 | 
							to->head->prev = from->tail; | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
							to->tail = from->tail; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						from->tail->next = to->head; | 
				
			||||||
 | 
						to->head = from->head; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						from->head = from->tail = NULL; | 
				
			||||||
 | 
						to->count += from->count; | 
				
			||||||
 | 
						from->count = 0; | 
				
			||||||
 | 
						to->count_up += from->count_up; | 
				
			||||||
 | 
						from->count_up = 0; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void _k_list_transfer_to_tail(K_LIST *from, K_LIST *to, KLIST_FFL_ARGS) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						if (from->name != to->name) { | 
				
			||||||
 | 
							quithere(1, "List %s can't %s() to a %s list" KLIST_FFL, | 
				
			||||||
 | 
									from->name, __func__, to->name, KLIST_FFL_PASS); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(from->do_tail)) { | 
				
			||||||
 | 
							quithere(1, "List %s can't %s() - do_tail is false" KLIST_FFL, | 
				
			||||||
 | 
									from->name, __func__, KLIST_FFL_PASS); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(from->head)) | 
				
			||||||
 | 
							return; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (to->tail) | 
				
			||||||
 | 
							to->tail->next = from->head; | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
							to->head = from->head; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						from->head->prev = to->tail; | 
				
			||||||
 | 
						to->tail = from->tail; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						from->head = from->tail = NULL; | 
				
			||||||
 | 
						to->count += from->count; | 
				
			||||||
 | 
						from->count = 0; | 
				
			||||||
 | 
						to->count_up += from->count_up; | 
				
			||||||
 | 
						from->count_up = 0; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					K_LIST *_k_free_list(K_LIST *list, KLIST_FFL_ARGS) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						int i; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (list->is_store) { | 
				
			||||||
 | 
							quithere(1, "List %s can't %s() a store" KLIST_FFL, | 
				
			||||||
 | 
									list->name, __func__, KLIST_FFL_PASS); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < list->item_mem_count; i++) | 
				
			||||||
 | 
							free(list->item_memory[i]); | 
				
			||||||
 | 
						free(list->item_memory); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < list->data_mem_count; i++) | 
				
			||||||
 | 
							free(list->data_memory[i]); | 
				
			||||||
 | 
						free(list->data_memory); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cklock_destroy(list->lock); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(list->lock); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(list); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					K_STORE *_k_free_store(K_STORE *store, KLIST_FFL_ARGS) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						if (!(store->is_store)) { | 
				
			||||||
 | 
							quithere(1, "Store %s can't %s() the list" KLIST_FFL, | 
				
			||||||
 | 
									store->name, __func__, KLIST_FFL_PASS); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(store); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,93 @@ | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2013-2014 Andrew Smith - BlackArrow Ltd | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * This program 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 3 of the License, or (at your option) | 
				
			||||||
 | 
					 * any later version.  See COPYING for more details. | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef KLIST_H | 
				
			||||||
 | 
					#define KLIST_H | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "libckpool.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define quithere(status, fmt, ...) \ | 
				
			||||||
 | 
						quitfrom(status, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define KLIST_FFL " - from %s %s() line %d" | 
				
			||||||
 | 
					#define KLIST_FFL_HERE __FILE__, __func__, __LINE__ | 
				
			||||||
 | 
					#define KLIST_FFL_PASS file, func, line | 
				
			||||||
 | 
					#define KLIST_FFL_ARGS  __maybe_unused const char *file, \ | 
				
			||||||
 | 
								__maybe_unused const char *func, \
 | 
				
			||||||
 | 
								__maybe_unused const int line | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct k_item { | 
				
			||||||
 | 
						const char *name; | 
				
			||||||
 | 
						struct k_item *prev; | 
				
			||||||
 | 
						struct k_item *next; | 
				
			||||||
 | 
						void *data; | 
				
			||||||
 | 
					} K_ITEM; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct k_list { | 
				
			||||||
 | 
						const char *name; | 
				
			||||||
 | 
						bool is_store; | 
				
			||||||
 | 
						cklock_t *lock; | 
				
			||||||
 | 
						struct k_item *head; | 
				
			||||||
 | 
						struct k_item *tail; | 
				
			||||||
 | 
						size_t siz;		// item data size
 | 
				
			||||||
 | 
						int total;		// total allocated
 | 
				
			||||||
 | 
						int count;		// in this list
 | 
				
			||||||
 | 
						int count_up;		// incremented every time one is added
 | 
				
			||||||
 | 
						int allocate;		// number to intially allocate and each time we run out
 | 
				
			||||||
 | 
						int limit;		// total limit - 0 means unlimited
 | 
				
			||||||
 | 
						bool do_tail;		// track the tail?
 | 
				
			||||||
 | 
						int item_mem_count;	// how many item memory buffers have been allocated
 | 
				
			||||||
 | 
						void **item_memory;	// allocated item memory buffers
 | 
				
			||||||
 | 
						int data_mem_count;	// how many item data memory buffers have been allocated
 | 
				
			||||||
 | 
						void **data_memory;	// allocated item data memory buffers
 | 
				
			||||||
 | 
					} K_LIST; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * K_STORE is for a list of items taken from a K_LIST | 
				
			||||||
 | 
					 * The restriction is, a K_STORE must not allocate new items, | 
				
			||||||
 | 
					 * only the K_LIST should do that | 
				
			||||||
 | 
					 * i.e. all K_STORE items came from a K_LIST | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					#define K_STORE K_LIST | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * N.B. all locking is done in the code using the K_*LOCK macros | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					#define K_WLOCK(_list) ck_wlock(_list->lock) | 
				
			||||||
 | 
					#define K_WUNLOCK(_list) ck_wunlock(_list->lock) | 
				
			||||||
 | 
					#define K_RLOCK(_list) ck_rlock(_list->lock) | 
				
			||||||
 | 
					#define K_RUNLOCK(_list) ck_runlock(_list->lock) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern K_STORE *k_new_store(K_LIST *list); | 
				
			||||||
 | 
					extern K_LIST *_k_new_list(const char *name, size_t siz, int allocate, int limit, bool do_tail, KLIST_FFL_ARGS); | 
				
			||||||
 | 
					#define k_new_list(_name, _siz, _allocate, _limit, _do_tail) _k_new_list(_name, _siz, _allocate, _limit, _do_tail, KLIST_FFL_HERE) | 
				
			||||||
 | 
					extern K_ITEM *_k_unlink_head(K_LIST *list, KLIST_FFL_ARGS); | 
				
			||||||
 | 
					#define k_unlink_head(_list) _k_unlink_head(_list, KLIST_FFL_HERE) | 
				
			||||||
 | 
					extern K_ITEM *_k_unlink_head_zero(K_LIST *list, KLIST_FFL_ARGS); | 
				
			||||||
 | 
					#define k_unlink_head_zero(_list) _k_unlink_head_zero(_list, KLIST_FFL_HERE) | 
				
			||||||
 | 
					extern K_ITEM *_k_unlink_tail(K_LIST *list, KLIST_FFL_ARGS); | 
				
			||||||
 | 
					#define k_unlink_tail(_list) _k_unlink_tail(_list, KLIST_FFL_HERE) | 
				
			||||||
 | 
					extern void _k_add_head(K_LIST *list, K_ITEM *item, KLIST_FFL_ARGS); | 
				
			||||||
 | 
					#define k_add_head(_list, _item) _k_add_head(_list, _item, KLIST_FFL_HERE) | 
				
			||||||
 | 
					// extern void k_free_head(K_LIST *list, K_ITEM *item, KLIST_FFL_ARGS);
 | 
				
			||||||
 | 
					#define k_free_head(__list, __item) _k_add_head(__list, __item, KLIST_FFL_HERE) | 
				
			||||||
 | 
					extern void _k_add_tail(K_LIST *list, K_ITEM *item, KLIST_FFL_ARGS); | 
				
			||||||
 | 
					#define k_add_tail(_list, _item) _k_add_tail(_list, _item, KLIST_FFL_HERE) | 
				
			||||||
 | 
					extern void _k_unlink_item(K_LIST *list, K_ITEM *item, KLIST_FFL_ARGS); | 
				
			||||||
 | 
					#define k_unlink_item(_list, _item) _k_unlink_item(_list, _item, KLIST_FFL_HERE) | 
				
			||||||
 | 
					void _k_list_transfer_to_head(K_LIST *from, K_LIST *to, KLIST_FFL_ARGS); | 
				
			||||||
 | 
					#define k_list_transfer_to_head(_from, _to) _k_list_transfer_to_head(_from, _to, KLIST_FFL_HERE) | 
				
			||||||
 | 
					void _k_list_transfer_to_tail(K_LIST *from, K_LIST *to, KLIST_FFL_ARGS); | 
				
			||||||
 | 
					#define k_list_transfer_to_tail(_from, _to) _k_list_transfer_to_tail(_from, _to, KLIST_FFL_HERE) | 
				
			||||||
 | 
					extern K_LIST *_k_free_list(K_LIST *list, KLIST_FFL_ARGS); | 
				
			||||||
 | 
					#define k_free_list(_list) _k_free_list(_list, KLIST_FFL_HERE) | 
				
			||||||
 | 
					extern K_STORE *_k_free_store(K_STORE *store, KLIST_FFL_ARGS); | 
				
			||||||
 | 
					#define k_free_store(_store) _k_free_store(_store, KLIST_FFL_HERE) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif | 
				
			||||||
@ -0,0 +1,872 @@ | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2003-2014 Andrew Smith | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * This program 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 3 of the License, or (at your option) | 
				
			||||||
 | 
					 * any later version.  See COPYING for more details. | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ktree.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const int dbg = 0; | 
				
			||||||
 | 
					#define DBG	if (dbg != 0) printf | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define FAIL(fmt, ...) do \ | 
				
			||||||
 | 
						{ \
 | 
				
			||||||
 | 
							quithere(1, fmt, ##__VA_ARGS__); \
 | 
				
			||||||
 | 
						} while (0); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define RED_RED         true | 
				
			||||||
 | 
					#define RED_BLACK       false | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define Yo true | 
				
			||||||
 | 
					#define No false | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static K_TREE nil[1] = { Yo, RED_BLACK, NULL, NULL, NULL, NULL, 0 }; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					K_TREE *new_ktree() | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						K_TREE *ktree = (K_TREE *)malloc(sizeof(*ktree)); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ktree == NULL) | 
				
			||||||
 | 
							FAIL("%s", "%K_TREE-F-OOM"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ktree->isNil = Yo; | 
				
			||||||
 | 
						ktree->red = RED_BLACK; | 
				
			||||||
 | 
						ktree->parent = nil; | 
				
			||||||
 | 
						ktree->left = nil; | 
				
			||||||
 | 
						ktree->right = nil; | 
				
			||||||
 | 
						ktree->data = NULL; | 
				
			||||||
 | 
						ktree->test = 0; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ktree; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static K_TREE *new_data(K_ITEM *data) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						K_TREE *ktree = (K_TREE *)malloc(sizeof(*ktree)); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ktree == NULL) | 
				
			||||||
 | 
							FAIL("%s", "%K_TREE-F-OOM"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ktree->isNil = No; | 
				
			||||||
 | 
						ktree->red = RED_RED; | 
				
			||||||
 | 
						ktree->parent = nil; | 
				
			||||||
 | 
						ktree->left = nil; | 
				
			||||||
 | 
						ktree->right = nil; | 
				
			||||||
 | 
						ktree->data = data; | 
				
			||||||
 | 
						ktree->test = 0; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ktree; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int bCount = 0; | 
				
			||||||
 | 
					static long bTestValue = 0; | 
				
			||||||
 | 
					static long nilTestValue = 0; | 
				
			||||||
 | 
					static long lrpTestValue = 0; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static long testValue = 1231230L; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static long getTestValue() | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						return ++testValue; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void show_ktree(K_TREE *root, char *path, int pos, char *(*dsp_funct)(K_ITEM *)) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						char col; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (root->isNil == Yo) | 
				
			||||||
 | 
							return; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (root->left->isNil == No) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							path[pos] = 'L'; | 
				
			||||||
 | 
							path[pos+1] = '\0'; | 
				
			||||||
 | 
							show_ktree(root->left, path, pos+1, dsp_funct); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						path[pos] = '\0'; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch(root->red) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
						case RED_RED: | 
				
			||||||
 | 
							col = 'R'; | 
				
			||||||
 | 
							break; | 
				
			||||||
 | 
						case RED_BLACK: | 
				
			||||||
 | 
							col = 'B'; | 
				
			||||||
 | 
							break; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printf(" %c %s=%s\n", col, path, dsp_funct(root->data)); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (root->right->isNil == No) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							path[pos] = 'R'; | 
				
			||||||
 | 
							path[pos+1] = '\0'; | 
				
			||||||
 | 
							show_ktree(root->right, path, pos+1, dsp_funct); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void dump_ktree(K_TREE *root, char *(*dsp_funct)(K_ITEM *)) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						char buf[42424]; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printf("dump:\n"); | 
				
			||||||
 | 
						if (root->isNil == No) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							buf[0] = 'T'; | 
				
			||||||
 | 
							buf[1] = '\0'; | 
				
			||||||
 | 
							show_ktree(root, buf, 1, dsp_funct); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
							printf(" Empty ktree\n"); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int nilTest(K_TREE *node, char *msg, int depth, int count, K_TREE *nil2) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						if (node->isNil == Yo || node == nil2) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							if (node == nil2 && node->isNil == No) | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-NIL2NOTNIL '%s' depth=%d count=%d", msg, depth, count); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (node != nil && node != nil2) | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-NOTNILNIL2 '%s' depth=%d count=%d", msg, depth, count); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (node->red == RED_RED) | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-NIRED '%s' depth=%d count=%d", msg, depth, count); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (node != nil2 && node->parent != NULL) | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-NILPARENT '%s' depth=%d count=%d", msg, depth, count); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (node != nil2 && node->left != NULL) | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-NILLEFT '%s' depth=%d count=%d", msg, depth, count); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (node == nil2 && node->left != nil) | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-NIL2LEFT '%s' depth=%d count=%d", msg, depth, count); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (node != nil2 && node->right != NULL) | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-NILRIGHT '%s' depth=%d count=%d", msg, depth, count); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (node == nil2 && node->right != nil) | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-NIL2RIGHT '%s' depth=%d count=%d", msg, depth, count); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (node->data != NULL) | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-NIDATA '%s' depth=%d count=%d", msg, depth, count); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							count++; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (node->parent == NULL) | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-NOPAR '%s' depth=%d count=%d", msg, depth, count); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (node->left == NULL) | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-NOLEFT '%s' depth=%d count=%d", msg, depth, count); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (node->right == NULL) | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-NORIGHT '%s' depth=%d count=%d", msg, depth, count); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (node->data == NULL) | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-NODATA '%s' depth=%d count=%d", msg, depth, count); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (node->test != nilTestValue) | 
				
			||||||
 | 
								node->test = nilTestValue; | 
				
			||||||
 | 
							else | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-NILTESTVALUE '%s' depth=%d count=%d", msg, depth, count); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							count = nilTest(node->left, msg, depth+1, count, nil2); | 
				
			||||||
 | 
							count = nilTest(node->right, msg, depth+1, count, nil2); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return(count); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void bTest(K_TREE *root, K_TREE *cur, char *msg, int count) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						if (cur->red != RED_RED) | 
				
			||||||
 | 
							count++; | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							if (cur->left->red == RED_RED) | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-CURLR '%s' count=%d", msg, count); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (cur->right->red == RED_RED) | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-CURRR '%s' count=%d", msg, count); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cur->isNil == Yo) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							if (bCount == 0) | 
				
			||||||
 | 
								bCount = count; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (count != bCount) | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-BCOUNT '%s' count=%d bCount=%d", msg, count, bCount); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							if (cur->test != bTestValue) | 
				
			||||||
 | 
								cur->test = bTestValue; | 
				
			||||||
 | 
							else | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-BTESTVALUE '%s' count=%d", msg, count); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bTest(root, cur->left, msg, count); | 
				
			||||||
 | 
							bTest(root, cur->right, msg, count); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void bTestInit(K_TREE *root, char *msg) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						bCount = 0; | 
				
			||||||
 | 
						bTestValue = getTestValue(); | 
				
			||||||
 | 
						bTest(root, root, msg, 0); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void lrpTest(K_TREE *top, char *msg) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						if (top->test != lrpTestValue) | 
				
			||||||
 | 
							top->test = lrpTestValue; | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
							FAIL("%%K_TREE-F-LRPTESTVALUE '%s'", msg); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (top->left->isNil == No) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							if (top->left->parent != top) | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-LRPTESTL '%s'", msg); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							lrpTest(top->left, msg); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (top->right->isNil == No) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							if (top->right->parent != top) | 
				
			||||||
 | 
								FAIL("%%K_TREE-F-LRPTESTR '%s'", msg); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							lrpTest(top->right, msg); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static __maybe_unused void check_ktree(K_TREE *root, char *msg, K_TREE *nil2, int debugNil, int debugLRP, int debugColor) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						if (root->isNil == Yo) | 
				
			||||||
 | 
							return; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (debugNil) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							nilTestValue = getTestValue(); | 
				
			||||||
 | 
							nilTest(root, msg, 1, 0, nil2); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (debugLRP && root->isNil == No) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							lrpTestValue = getTestValue(); | 
				
			||||||
 | 
							lrpTest(root, msg); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (debugColor && root->isNil == No) | 
				
			||||||
 | 
							bTestInit(root, msg); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					K_ITEM *first_in_ktree(K_TREE *root, K_TREE_CTX *ctx) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						if (root->isNil == No) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							while (root->left->isNil == No) | 
				
			||||||
 | 
								root = root->left; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							*ctx = root; | 
				
			||||||
 | 
							return(root->data); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*ctx = NULL; | 
				
			||||||
 | 
						return(NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					K_ITEM *last_in_ktree(K_TREE *root, K_TREE_CTX *ctx) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						if (root->isNil == No) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							while (root->right->isNil == No) | 
				
			||||||
 | 
								root = root->right; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							*ctx = root; | 
				
			||||||
 | 
							return(root->data); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*ctx = NULL; | 
				
			||||||
 | 
						return(NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					K_ITEM *next_in_ktree(K_TREE_CTX *ctx) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						K_TREE *parent; | 
				
			||||||
 | 
						K_TREE *ktree = (K_TREE *)(*ctx); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ktree->isNil == No) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							if (ktree->right->isNil == No) | 
				
			||||||
 | 
								return(first_in_ktree(ktree->right, ctx)); | 
				
			||||||
 | 
							else | 
				
			||||||
 | 
							{ | 
				
			||||||
 | 
								parent = ktree->parent; | 
				
			||||||
 | 
								while (parent->isNil == No && ktree == parent->right) | 
				
			||||||
 | 
								{ | 
				
			||||||
 | 
									ktree = parent; | 
				
			||||||
 | 
									parent = parent->parent; | 
				
			||||||
 | 
								} | 
				
			||||||
 | 
								if (parent->isNil == No) | 
				
			||||||
 | 
								{ | 
				
			||||||
 | 
									*ctx = parent; | 
				
			||||||
 | 
									return(parent->data); | 
				
			||||||
 | 
								} | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*ctx = NULL; | 
				
			||||||
 | 
						return(NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					K_ITEM *prev_in_ktree(K_TREE_CTX *ctx) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						K_TREE *parent; | 
				
			||||||
 | 
						K_TREE *ktree = (K_TREE *)(*ctx); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ktree->isNil == No) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							if (ktree->left->isNil == No) | 
				
			||||||
 | 
								return(last_in_ktree(ktree->left, ctx)); | 
				
			||||||
 | 
							else | 
				
			||||||
 | 
							{ | 
				
			||||||
 | 
								parent = ktree->parent; | 
				
			||||||
 | 
								while (parent->isNil == No && ktree == parent->left) | 
				
			||||||
 | 
								{ | 
				
			||||||
 | 
									ktree = parent; | 
				
			||||||
 | 
									parent = parent->parent; | 
				
			||||||
 | 
								} | 
				
			||||||
 | 
								if (parent->isNil == No) | 
				
			||||||
 | 
								{ | 
				
			||||||
 | 
									*ctx = parent; | 
				
			||||||
 | 
									return(parent->data); | 
				
			||||||
 | 
								} | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*ctx = NULL; | 
				
			||||||
 | 
						return(NULL); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static K_TREE *left_rotate(K_TREE *root, K_TREE *about) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						K_TREE *rotate; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rotate = about->right; | 
				
			||||||
 | 
						about->right = rotate->left; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (rotate->left->isNil == No) | 
				
			||||||
 | 
							rotate->left->parent = about; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rotate->parent = about->parent; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (about->parent->isNil == Yo) | 
				
			||||||
 | 
							root = rotate; | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							if (about == about->parent->left) | 
				
			||||||
 | 
								about->parent->left = rotate; | 
				
			||||||
 | 
							else | 
				
			||||||
 | 
								about->parent->right = rotate; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rotate->left = about; | 
				
			||||||
 | 
						about->parent = rotate; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return(root); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static K_TREE *right_rotate(K_TREE *root, K_TREE *about) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						K_TREE *rotate; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rotate = about->left; | 
				
			||||||
 | 
						about->left = rotate->right; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (rotate->right->isNil == No) | 
				
			||||||
 | 
							rotate->right->parent = about; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rotate->parent = about->parent; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (about->parent->isNil == Yo) | 
				
			||||||
 | 
							root = rotate; | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
							if (about == about->parent->right) | 
				
			||||||
 | 
								about->parent->right = rotate; | 
				
			||||||
 | 
							else | 
				
			||||||
 | 
								about->parent->left = rotate; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rotate->right = about; | 
				
			||||||
 | 
						about->parent = rotate; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return(root); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					K_TREE *add_to_ktree(K_TREE *root, K_ITEM *data, double (*cmp_funct)(K_ITEM *, K_ITEM *)) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						K_TREE *ktree; | 
				
			||||||
 | 
						K_TREE *x, *y; | 
				
			||||||
 | 
						K_TREE *pp; | 
				
			||||||
 | 
						double cmp; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (root == NULL) | 
				
			||||||
 | 
							FAIL("%s", "%K_TREE-F-ADDNULL add ktree is NULL"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//check_ktree(root, ">add", NULL, 1, 1, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (root->parent != nil && root->parent != NULL) | 
				
			||||||
 | 
							FAIL("%s", "%K_TREE-F-ADDROOT add root isn't the root"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ktree = new_data(data); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (root->isNil == Yo) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							if (root != nil) | 
				
			||||||
 | 
								free(root); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							root = ktree; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							x = root; | 
				
			||||||
 | 
							y = nil; | 
				
			||||||
 | 
							while (x->isNil == No) | 
				
			||||||
 | 
							{ | 
				
			||||||
 | 
								y = x; | 
				
			||||||
 | 
								if ((cmp = (*cmp_funct)(ktree->data, x->data)) < 0.0) | 
				
			||||||
 | 
									x = x->left; | 
				
			||||||
 | 
								else | 
				
			||||||
 | 
									x = x->right; | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
							ktree->parent = y; | 
				
			||||||
 | 
							if (cmp < 0.0) | 
				
			||||||
 | 
								y->left = ktree; | 
				
			||||||
 | 
							else | 
				
			||||||
 | 
								y->right = ktree; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							x = ktree; | 
				
			||||||
 | 
							while (x != root && x->parent->red == RED_RED) | 
				
			||||||
 | 
							{ | 
				
			||||||
 | 
								pp = x->parent->parent; | 
				
			||||||
 | 
								if (x->parent == pp->left) | 
				
			||||||
 | 
								{ | 
				
			||||||
 | 
									y = pp->right; | 
				
			||||||
 | 
									if (y->red == RED_RED) | 
				
			||||||
 | 
									{ | 
				
			||||||
 | 
										x->parent->red = RED_BLACK; | 
				
			||||||
 | 
										y->red = RED_BLACK; | 
				
			||||||
 | 
										pp->red = RED_RED; | 
				
			||||||
 | 
										x = pp; | 
				
			||||||
 | 
									} | 
				
			||||||
 | 
									else | 
				
			||||||
 | 
									{ | 
				
			||||||
 | 
										if (x == x->parent->right) | 
				
			||||||
 | 
										{ | 
				
			||||||
 | 
											x = x->parent; | 
				
			||||||
 | 
											root = left_rotate(root, x); | 
				
			||||||
 | 
											pp = x->parent->parent; | 
				
			||||||
 | 
										} | 
				
			||||||
 | 
										x->parent->red = RED_BLACK; | 
				
			||||||
 | 
										pp->red = RED_RED; | 
				
			||||||
 | 
										root = right_rotate(root, pp); | 
				
			||||||
 | 
									} | 
				
			||||||
 | 
								} | 
				
			||||||
 | 
								else | 
				
			||||||
 | 
								{ | 
				
			||||||
 | 
									y = pp->left; | 
				
			||||||
 | 
									if (y->red == RED_RED) | 
				
			||||||
 | 
									{ | 
				
			||||||
 | 
										x->parent->red = RED_BLACK; | 
				
			||||||
 | 
										y->red = RED_BLACK; | 
				
			||||||
 | 
										pp->red = RED_RED; | 
				
			||||||
 | 
										x = pp; | 
				
			||||||
 | 
									} | 
				
			||||||
 | 
									else | 
				
			||||||
 | 
									{ | 
				
			||||||
 | 
										if (x == x->parent->left) | 
				
			||||||
 | 
										{ | 
				
			||||||
 | 
											x = x->parent; | 
				
			||||||
 | 
											root = right_rotate(root, x); | 
				
			||||||
 | 
											pp = x->parent->parent; | 
				
			||||||
 | 
										} | 
				
			||||||
 | 
										x->parent->red = RED_BLACK; | 
				
			||||||
 | 
										pp->red = RED_RED; | 
				
			||||||
 | 
										root = left_rotate(root, pp); | 
				
			||||||
 | 
									} | 
				
			||||||
 | 
								} | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						root->red = RED_BLACK; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//check_ktree(root, "<add", NULL, 1, 1, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return(root); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					K_ITEM *find_in_ktree(K_TREE *ktree, K_ITEM *data, double (*cmp_funct)(K_ITEM *, K_ITEM *), K_TREE_CTX *ctx) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						double cmp = -1.0; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (ktree->isNil == No && cmp != 0.0) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							if ((cmp = (*cmp_funct)(ktree->data, data))) | 
				
			||||||
 | 
							{ | 
				
			||||||
 | 
								if (cmp > 0.0) | 
				
			||||||
 | 
									ktree = ktree->left; | 
				
			||||||
 | 
								else | 
				
			||||||
 | 
									ktree = ktree->right; | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ktree->isNil == No) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							*ctx = ktree; | 
				
			||||||
 | 
							return(ktree->data); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							*ctx = NULL; | 
				
			||||||
 | 
							return(NULL); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					K_ITEM *find_after_in_ktree(K_TREE *ktree, K_ITEM *data, double (*cmp_funct)(K_ITEM *, K_ITEM *), K_TREE_CTX *ctx) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						K_TREE *prev = NULL; | 
				
			||||||
 | 
						double cmp = -1.0, prevcmp = -1; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (ktree->isNil == No && cmp != 0.0) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							if ((cmp = (*cmp_funct)(ktree->data, data))) | 
				
			||||||
 | 
							{ | 
				
			||||||
 | 
								prev = ktree; | 
				
			||||||
 | 
								prevcmp = cmp; | 
				
			||||||
 | 
								if (cmp > 0.0) | 
				
			||||||
 | 
									ktree = ktree->left; | 
				
			||||||
 | 
								else | 
				
			||||||
 | 
									ktree = ktree->right; | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ktree->isNil == No) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							*ctx = ktree; | 
				
			||||||
 | 
							return next_in_ktree(ctx); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							if (prev) | 
				
			||||||
 | 
							{ | 
				
			||||||
 | 
								if (prevcmp > 0.0) | 
				
			||||||
 | 
								{ | 
				
			||||||
 | 
									*ctx = prev; | 
				
			||||||
 | 
									return(prev->data); | 
				
			||||||
 | 
								} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								*ctx = prev; | 
				
			||||||
 | 
								return next_in_ktree(ctx); | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							*ctx = NULL; | 
				
			||||||
 | 
							return(NULL); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static K_TREE *removeFixup(K_TREE *root, K_TREE *fix) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						K_TREE *w = NULL; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (fix != root && fix->red != RED_RED) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							if (fix == fix->parent->left) | 
				
			||||||
 | 
							{ | 
				
			||||||
 | 
								w = fix->parent->right; | 
				
			||||||
 | 
								if (w->red == RED_RED) | 
				
			||||||
 | 
								{ | 
				
			||||||
 | 
									w->red = RED_BLACK; | 
				
			||||||
 | 
									fix->parent->red = RED_RED; | 
				
			||||||
 | 
									root = left_rotate(root, fix->parent); | 
				
			||||||
 | 
									w = fix->parent->right; | 
				
			||||||
 | 
								} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (w->left->red != RED_RED && w->right->red != RED_RED) | 
				
			||||||
 | 
								{ | 
				
			||||||
 | 
									w->red = RED_RED; | 
				
			||||||
 | 
									fix = fix->parent; | 
				
			||||||
 | 
								} | 
				
			||||||
 | 
								else | 
				
			||||||
 | 
								{ | 
				
			||||||
 | 
									if (w->right->red != RED_RED) | 
				
			||||||
 | 
									{ | 
				
			||||||
 | 
										w->left->red = RED_BLACK; | 
				
			||||||
 | 
										w->red = RED_RED; | 
				
			||||||
 | 
										root = right_rotate(root, w); | 
				
			||||||
 | 
										w = fix->parent->right; | 
				
			||||||
 | 
									} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									w->red = fix->parent->red; | 
				
			||||||
 | 
									fix->parent->red = RED_BLACK; | 
				
			||||||
 | 
									w->right->red = RED_BLACK; | 
				
			||||||
 | 
									root = left_rotate(root, fix->parent); | 
				
			||||||
 | 
									fix = root; | 
				
			||||||
 | 
								} | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
							else | 
				
			||||||
 | 
							{ | 
				
			||||||
 | 
								w = fix->parent->left; | 
				
			||||||
 | 
								if (w->red == RED_RED) | 
				
			||||||
 | 
								{ | 
				
			||||||
 | 
									w->red = RED_BLACK; | 
				
			||||||
 | 
									fix->parent->red = RED_RED; | 
				
			||||||
 | 
									root = right_rotate(root, fix->parent); | 
				
			||||||
 | 
									w = fix->parent->left; | 
				
			||||||
 | 
								} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (w->right->red != RED_RED && w->left->red != RED_RED) | 
				
			||||||
 | 
								{ | 
				
			||||||
 | 
									w->red = RED_RED; | 
				
			||||||
 | 
									fix = fix->parent; | 
				
			||||||
 | 
								} | 
				
			||||||
 | 
								else | 
				
			||||||
 | 
								{ | 
				
			||||||
 | 
									if (w->left->red != RED_RED) | 
				
			||||||
 | 
									{ | 
				
			||||||
 | 
										w->right->red = RED_BLACK; | 
				
			||||||
 | 
										w->red = RED_RED; | 
				
			||||||
 | 
										root = left_rotate(root, w); | 
				
			||||||
 | 
										w = fix->parent->left; | 
				
			||||||
 | 
									} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									w->red = fix->parent->red; | 
				
			||||||
 | 
									fix->parent->red = RED_BLACK; | 
				
			||||||
 | 
									w->left->red = RED_BLACK; | 
				
			||||||
 | 
									root = right_rotate(root, fix->parent); | 
				
			||||||
 | 
									fix = root; | 
				
			||||||
 | 
								} | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fix->red = RED_BLACK; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return root; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Does this work OK when you remove the last element in the ktree?
 | 
				
			||||||
 | 
					// It should return the root as 'nil'
 | 
				
			||||||
 | 
					K_TREE *remove_from_ktree(K_TREE *root, K_ITEM *data, double (*cmp_funct)(K_ITEM *, K_ITEM *), K_TREE_CTX *ctx) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						K_TREE_CTX tmpctx[1]; | 
				
			||||||
 | 
						K_TREE *found; | 
				
			||||||
 | 
						K_ITEM *fdata; | 
				
			||||||
 | 
						K_TREE *x, *y, *nil2; | 
				
			||||||
 | 
						// double cmp;
 | 
				
			||||||
 | 
						int yred; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//check_ktree(root, ">remove", NULL, 1, 1, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (root == NULL) | 
				
			||||||
 | 
							FAIL("%s", "%K_TREE-F-REMNULL remove ktree is NULL"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (root->isNil == Yo) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							*ctx = NULL; | 
				
			||||||
 | 
							return(root); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (root->parent->isNil == No) | 
				
			||||||
 | 
							FAIL("%s", "%K_TREE-F-REMROOT remove root isn't the root"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fdata = find_in_ktree(root, data, cmp_funct, ctx); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fdata == NULL) | 
				
			||||||
 | 
							return(root); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cmp_funct(fdata, data) != 0.0) | 
				
			||||||
 | 
							FAIL("%s", "%K_TREE-F-BADFIND cmp(found, remove) != 0"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						found = *ctx; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x = nil; | 
				
			||||||
 | 
						y = nil; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (found->left->isNil == Yo || found->right->isNil == Yo) | 
				
			||||||
 | 
							y = found; | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							*tmpctx = found; | 
				
			||||||
 | 
							next_in_ktree(tmpctx); | 
				
			||||||
 | 
							y = *tmpctx; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						yred = y->red; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (y->left->isNil == No && y->right->isNil == No) | 
				
			||||||
 | 
							FAIL("%s", "%K_TREE-F-REMBADY remove error"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (y->left->isNil == Yo) | 
				
			||||||
 | 
							x = y->right; | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
							x = y->left; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (x != nil) | 
				
			||||||
 | 
							nil2 = NULL; | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							nil2 = new_ktree(); | 
				
			||||||
 | 
							x = nil2; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x->parent = y->parent; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (x->parent->isNil == Yo) | 
				
			||||||
 | 
							root = x; | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							if (x->parent->left == y) | 
				
			||||||
 | 
								x->parent->left = x; | 
				
			||||||
 | 
							else | 
				
			||||||
 | 
								x->parent->right = x; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (y != found) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							if (root == found) | 
				
			||||||
 | 
								root = y; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (x == found) | 
				
			||||||
 | 
								x = y; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							y->red = found->red; | 
				
			||||||
 | 
							y->parent = found->parent; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (y->parent->isNil == No) | 
				
			||||||
 | 
							{ | 
				
			||||||
 | 
								if (y->parent->left == found) | 
				
			||||||
 | 
									y->parent->left = y; | 
				
			||||||
 | 
								else | 
				
			||||||
 | 
									y->parent->right = y; | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							y->left = found->left; | 
				
			||||||
 | 
							if (y->left->isNil == No || y->left == nil2) | 
				
			||||||
 | 
								y->left->parent = y; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							y->right = found->right; | 
				
			||||||
 | 
							if (y->right->isNil == No || y->right == nil2) | 
				
			||||||
 | 
								y->right->parent = y; | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (yred != RED_RED) | 
				
			||||||
 | 
							root = removeFixup(root, x); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (nil2 != NULL) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							if (nil2->parent->isNil == No && nil2->parent->left == nil2) | 
				
			||||||
 | 
								nil2->parent->left = nil; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (nil2->parent->isNil == No && nil2->parent->right == nil2) | 
				
			||||||
 | 
								nil2->parent->right = nil; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (root == nil2) | 
				
			||||||
 | 
								root = nil; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					if (dbg != 0) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					 if (nil2->left != nil) | 
				
			||||||
 | 
					 { | 
				
			||||||
 | 
					DBG("@remove nil2->left wasn't nil!!!\n"); | 
				
			||||||
 | 
					 } | 
				
			||||||
 | 
					 if (nil2->right != nil) | 
				
			||||||
 | 
					 { | 
				
			||||||
 | 
					DBG("@remove nil2->right wasn't nil!!!\n"); | 
				
			||||||
 | 
					 } | 
				
			||||||
 | 
					 cmp = 0.0; | 
				
			||||||
 | 
					 fdata = first_in_ktree(root, tmpctx);; | 
				
			||||||
 | 
					 while (fdata != NULL) | 
				
			||||||
 | 
					 { | 
				
			||||||
 | 
						cmp++; | 
				
			||||||
 | 
						x = *tmpctx; | 
				
			||||||
 | 
						if (x == nil2) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
					DBG("@remove found nil2 in ktree %f!!!\n", cmp); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
							if (x->left == nil2) | 
				
			||||||
 | 
							{ | 
				
			||||||
 | 
					DBG("@remove found nil2 in ktree(left) %f!!!\n", cmp); | 
				
			||||||
 | 
							} | 
				
			||||||
 | 
							else | 
				
			||||||
 | 
								if (x->right == nil2) | 
				
			||||||
 | 
								{ | 
				
			||||||
 | 
					DBG("@remove found nil2 in ktree(right) %f!!!\n", cmp); | 
				
			||||||
 | 
								} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fdata = next_in_ktree(tmpctx);; | 
				
			||||||
 | 
					 } | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					*/ | 
				
			||||||
 | 
							free(nil2); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					if (dbg != 0) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					 cmp = 0.0 | 
				
			||||||
 | 
					 fdata = first_in_ktree(root, tmpctx);; | 
				
			||||||
 | 
					 while (fdata != NULL) | 
				
			||||||
 | 
					 { | 
				
			||||||
 | 
						if (cmp_funct(fdata, root->data) < 0) | 
				
			||||||
 | 
							cmp--; | 
				
			||||||
 | 
						else | 
				
			||||||
 | 
							cmp++; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fdata = next_in_ktree(tmpctx);; | 
				
			||||||
 | 
					 } | 
				
			||||||
 | 
					 if (cmp < -10.0 || cmp > 10.0) | 
				
			||||||
 | 
					 { | 
				
			||||||
 | 
					DBG("@remove after balance=%f :(\n", cmp); | 
				
			||||||
 | 
					 } | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					*/ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//check_ktree(root, "<remove", NULL, 1, 1, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return root; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void free_ktree_sub(K_TREE *ktree, void (*free_funct)(void *)) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						if (ktree != NULL && ktree != nil) | 
				
			||||||
 | 
						{ | 
				
			||||||
 | 
							if (ktree->data != NULL && free_funct) | 
				
			||||||
 | 
								(*free_funct)(ktree->data); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							free_ktree_sub(ktree->left, free_funct); | 
				
			||||||
 | 
							free_ktree_sub(ktree->right, free_funct); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							free(ktree); | 
				
			||||||
 | 
						} | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					K_TREE *free_ktree(K_TREE *ktree, void (*free_funct)(void *)) | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						if (ktree == NULL) | 
				
			||||||
 | 
							FAIL("%s", "%K_TREE-F-FREENULL free NULL ktree"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ktree->parent != NULL && ktree->parent != nil) | 
				
			||||||
 | 
							FAIL("%s", "%K_TREE-F-FREENOTROOT free ktree not root"); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free_ktree_sub(ktree, free_funct); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return(nil); | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,44 @@ | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2003-2014 Andrew Smith | 
				
			||||||
 | 
					 * | 
				
			||||||
 | 
					 * This program 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 3 of the License, or (at your option) | 
				
			||||||
 | 
					 * any later version.  See COPYING for more details. | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef ___KTREE_H | 
				
			||||||
 | 
					#define ___KTREE_H | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "klist.h" | 
				
			||||||
 | 
					#include "libckpool.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define quithere(status, fmt, ...) \ | 
				
			||||||
 | 
						quitfrom(status, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct ktree | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
						bool	isNil; | 
				
			||||||
 | 
						bool	red; | 
				
			||||||
 | 
						struct	ktree	*parent; | 
				
			||||||
 | 
						struct	ktree	*left; | 
				
			||||||
 | 
						struct	ktree	*right; | 
				
			||||||
 | 
						K_ITEM	*data; | 
				
			||||||
 | 
						long	test; | 
				
			||||||
 | 
					} K_TREE; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef void *K_TREE_CTX; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern K_TREE *new_ktree(); | 
				
			||||||
 | 
					extern void dump_ktree(K_TREE *root, char *(*dsp_funct)(K_ITEM *)); | 
				
			||||||
 | 
					extern K_ITEM *first_in_ktree(K_TREE *root, K_TREE_CTX *ctx); | 
				
			||||||
 | 
					extern K_ITEM *last_in_ktree(K_TREE *root, K_TREE_CTX *ctx); | 
				
			||||||
 | 
					extern K_ITEM *next_in_ktree(K_TREE_CTX *ctx); | 
				
			||||||
 | 
					extern K_ITEM *prev_in_ktree(K_TREE_CTX *ctx); | 
				
			||||||
 | 
					extern K_TREE *add_to_ktree(K_TREE *root, K_ITEM *data, double (*cmp_func)(K_ITEM *, K_ITEM *)); | 
				
			||||||
 | 
					extern K_ITEM *find_in_ktree(K_TREE *root, K_ITEM *data, double (*cmp_funct)(K_ITEM *, K_ITEM *), K_TREE_CTX *ctx); | 
				
			||||||
 | 
					extern K_ITEM *find_after_in_ktree(K_TREE *ktree, K_ITEM *data, double (*cmp_funct)(K_ITEM *, K_ITEM *), K_TREE_CTX *ctx); | 
				
			||||||
 | 
					extern K_TREE *remove_from_ktree(K_TREE *root, K_ITEM *data, double (*cmp_funct)(K_ITEM *, K_ITEM *), K_TREE_CTX *ctx); | 
				
			||||||
 | 
					extern K_TREE *free_ktree(K_TREE *root, void (*free_funct)(void *)); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif | 
				
			||||||
					Loading…
					
					
				
		Reference in new issue