| 
									
										
										
										
											2011-02-18 13:58:08 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  |  * 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 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program 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 this program; if not, write to the Free Software Foundation, | 
					
						
							| 
									
										
										
										
											2010-02-12 13:34:04 +00:00
										 |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-17 18:59:41 +00:00
										 |  |  | #pragma once
 | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 08:08:12 +11:00
										 |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup bli | 
					
						
							| 
									
										
										
										
											2011-02-18 13:58:08 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-02 15:04:53 +01:00
										 |  |  | #ifdef __cplusplus
 | 
					
						
							|  |  |  | extern "C" { | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  | /* Double-Linked Red-Black Tree Implementation:
 | 
					
						
							| 
									
										
										
										
											2018-06-01 18:19:39 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  |  * This is simply a Red-Black Tree implementation whose nodes can later | 
					
						
							|  |  |  |  * be arranged + retrieved as elements in a Double-Linked list (i.e. ListBase). | 
					
						
							|  |  |  |  * The Red-Black Tree implementation is based on the methods defined by Wikipedia. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ********************************************** */ | 
					
						
							|  |  |  | /* Data Types and Type Defines  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Base Structs --------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Basic Layout for a Node */ | 
					
						
							|  |  |  | typedef struct DLRBT_Node { | 
					
						
							|  |  |  |   /* ListBase capabilities */ | 
					
						
							| 
									
										
										
										
											2012-10-21 05:46:41 +00:00
										 |  |  |   struct DLRBT_Node *next, *prev; | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  |   /* Tree Associativity settings */ | 
					
						
							|  |  |  |   struct DLRBT_Node *left, *right; | 
					
						
							|  |  |  |   struct DLRBT_Node *parent; | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  |   char tree_col; | 
					
						
							|  |  |  |   /* ... for nice alignment, next item should usually be a char too... */ | 
					
						
							|  |  |  | } DLRBT_Node; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Red/Black defines for tree_col */ | 
					
						
							| 
									
										
										
										
											2009-11-15 11:20:44 +00:00
										 |  |  | typedef enum eDLRBT_Colors { | 
					
						
							| 
									
										
										
										
											2012-05-12 20:39:39 +00:00
										 |  |  |   DLRBT_BLACK = 0, | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  |   DLRBT_RED, | 
					
						
							| 
									
										
										
										
											2009-11-15 11:20:44 +00:00
										 |  |  | } eDLRBT_Colors; | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* -------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The Tree Data */ | 
					
						
							|  |  |  | typedef struct DLRBT_Tree { | 
					
						
							|  |  |  |   /* ListBase capabilities */ | 
					
						
							| 
									
										
										
										
											2012-05-12 20:39:39 +00:00
										 |  |  |   void *first, *last; /* these should be based on DLRBT_Node-s */ | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Root Node */ | 
					
						
							| 
									
										
										
										
											2012-05-12 20:39:39 +00:00
										 |  |  |   void *root; /* this should be based on DLRBT_Node-s */ | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  | } DLRBT_Tree; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 11:20:44 +00:00
										 |  |  | /* Callback Types --------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 00:54:27 +10:00
										 |  |  | /* Return -1, 0, 1 for whether the given data is less than,
 | 
					
						
							|  |  |  |  * equal to, or greater than the given node. | 
					
						
							| 
									
										
										
										
											2020-03-06 11:40:37 +11:00
										 |  |  |  * - node: <DLRBT_Node> the node to compare to. | 
					
						
							|  |  |  |  * - data: pointer to the relevant data or values stored in the bit-pattern. | 
					
						
							| 
									
										
										
										
											2019-04-22 00:54:27 +10:00
										 |  |  |  *   dependent on the function. | 
					
						
							| 
									
										
										
										
											2009-11-15 11:20:44 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | typedef short (*DLRBT_Comparator_FP)(void *node, void *data); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 00:54:27 +10:00
										 |  |  | /* Return a new node instance wrapping the given data
 | 
					
						
							|  |  |  |  * - data: Pointer to the relevant data to create a subclass of node from | 
					
						
							| 
									
										
										
										
											2009-11-15 11:20:44 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | typedef DLRBT_Node *(*DLRBT_NAlloc_FP)(void *data); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-06 11:40:37 +11:00
										 |  |  | /* Update an existing node instance accordingly to be in sync with the given data.
 | 
					
						
							| 
									
										
										
										
											2019-04-22 00:54:27 +10:00
										 |  |  |  * - node: <DLRBT_Node> the node to update. | 
					
						
							| 
									
										
										
										
											2020-03-06 11:40:37 +11:00
										 |  |  |  * - data: Pointer to the relevant data or values stored in the bit-pattern. | 
					
						
							| 
									
										
										
										
											2019-04-22 00:54:27 +10:00
										 |  |  |  *   dependent on the function. | 
					
						
							| 
									
										
										
										
											2009-11-15 11:20:44 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | typedef void (*DLRBT_NUpdate_FP)(void *node, void *data); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  | /* ********************************************** */ | 
					
						
							|  |  |  | /* Public API */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 11:20:44 +00:00
										 |  |  | /* ADT Management ------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-02 16:05:54 +00:00
										 |  |  | /* Create a new tree, and initialize as necessary */ | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  | DLRBT_Tree *BLI_dlrbTree_new(void); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-09 00:41:09 +00:00
										 |  |  | /* Initializes some given trees */ | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  | void BLI_dlrbTree_init(DLRBT_Tree *tree); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Free some tree */ | 
					
						
							|  |  |  | void BLI_dlrbTree_free(DLRBT_Tree *tree); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Make sure the tree's Double-Linked list representation is valid */ | 
					
						
							|  |  |  | void BLI_dlrbTree_linkedlist_sync(DLRBT_Tree *tree); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 11:20:44 +00:00
										 |  |  | /* Searching ------------------------------------ */ | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 11:20:44 +00:00
										 |  |  | /* Find the node which matches or is the closest to the requested node */ | 
					
						
							|  |  |  | DLRBT_Node *BLI_dlrbTree_search(DLRBT_Tree *tree, DLRBT_Comparator_FP cmp_cb, void *search_data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Find the node which exactly matches the required data */ | 
					
						
							|  |  |  | DLRBT_Node *BLI_dlrbTree_search_exact(DLRBT_Tree *tree, | 
					
						
							|  |  |  |                                       DLRBT_Comparator_FP cmp_cb, | 
					
						
							|  |  |  |                                       void *search_data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Find the node which occurs immediately before the best matching node */ | 
					
						
							|  |  |  | DLRBT_Node *BLI_dlrbTree_search_prev(DLRBT_Tree *tree, | 
					
						
							|  |  |  |                                      DLRBT_Comparator_FP cmp_cb, | 
					
						
							|  |  |  |                                      void *search_data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Find the node which occurs immediately after the best matching node */ | 
					
						
							|  |  |  | DLRBT_Node *BLI_dlrbTree_search_next(DLRBT_Tree *tree, | 
					
						
							|  |  |  |                                      DLRBT_Comparator_FP cmp_cb, | 
					
						
							|  |  |  |                                      void *search_data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Check whether there is a node matching the requested node */ | 
					
						
							|  |  |  | short BLI_dlrbTree_contains(DLRBT_Tree *tree, DLRBT_Comparator_FP cmp_cb, void *search_data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Node Operations (Managed) --------------------- */ | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | /* These methods automate the process of adding/removing nodes from the BST,
 | 
					
						
							| 
									
										
										
										
											2009-11-15 11:20:44 +00:00
										 |  |  |  * using the supplied data and callbacks | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2009-11-15 11:20:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Add the given data to the tree, and return the node added */ | 
					
						
							|  |  |  | // NOTE: for duplicates, the update_cb is called (if available), and the existing node is returned
 | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | DLRBT_Node *BLI_dlrbTree_add(DLRBT_Tree *tree, | 
					
						
							|  |  |  |                              DLRBT_Comparator_FP cmp_cb, | 
					
						
							| 
									
										
										
										
											2012-05-12 20:39:39 +00:00
										 |  |  |                              DLRBT_NAlloc_FP new_cb, | 
					
						
							|  |  |  |                              DLRBT_NUpdate_FP update_cb, | 
					
						
							|  |  |  |                              void *data); | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Remove the given element from the tree and balance again */ | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | // FIXME: this is not implemented yet...
 | 
					
						
							| 
									
										
										
										
											2012-02-29 15:00:37 +00:00
										 |  |  | // void BLI_dlrbTree_remove(DLRBT_Tree *tree, DLRBT_Node *node);
 | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 11:20:44 +00:00
										 |  |  | /* Node Operations (Manual) --------------------- */ | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | /* These methods require custom code for creating BST nodes and adding them to the
 | 
					
						
							| 
									
										
										
										
											2009-11-15 11:20:44 +00:00
										 |  |  |  * tree in special ways, such that the node can then be balanced. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * It is recommended that these methods are only used where the other method is too cumbersome... | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | /* Balance the tree after the given node has been added to it
 | 
					
						
							| 
									
										
										
										
											2009-11-15 11:20:44 +00:00
										 |  |  |  * (using custom code, in the Binary Tree way). | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void BLI_dlrbTree_insert(DLRBT_Tree *tree, DLRBT_Node *node); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-18 07:11:37 +00:00
										 |  |  | /* ********************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-02 15:04:53 +01:00
										 |  |  | #ifdef __cplusplus
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 |