| 1 | /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. |
| 2 | |
| 3 | This program is free software; you can redistribute it and/or modify |
| 4 | it under the terms of the GNU General Public License as published by |
| 5 | the Free Software Foundation; version 2 of the License. |
| 6 | |
| 7 | This program is distributed in the hope that it will be useful, |
| 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 10 | GNU General Public License for more details. |
| 11 | |
| 12 | You should have received a copy of the GNU General Public License |
| 13 | along with this program; if not, write to the Free Software |
| 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
| 15 | |
| 16 | #ifndef _tree_h |
| 17 | #define _tree_h |
| 18 | #ifdef __cplusplus |
| 19 | extern "C" { |
| 20 | #endif |
| 21 | |
| 22 | #include "my_base.h" /* get 'enum ha_rkey_function' */ |
| 23 | #include "my_alloc.h" /* MEM_ROOT */ |
| 24 | |
| 25 | /* Worst case tree is half full. This gives use 2^(MAX_TREE_HEIGHT/2) leafs */ |
| 26 | #define MAX_TREE_HEIGHT 64 |
| 27 | |
| 28 | #define ELEMENT_KEY(tree,element)\ |
| 29 | (tree->offset_to_key ? (void*)((uchar*) element+tree->offset_to_key) :\ |
| 30 | *((void**) (element+1))) |
| 31 | |
| 32 | #define tree_set_pointer(element,ptr) *((uchar **) (element+1))=((uchar*) (ptr)) |
| 33 | |
| 34 | /* |
| 35 | A tree with its flag set to TREE_ONLY_DUPS behaves differently on inserting |
| 36 | an element that is not in the tree: |
| 37 | the element is not added at all, but instead tree_insert() returns a special |
| 38 | address TREE_ELEMENT_UNIQUE as an indication that the function has not failed |
| 39 | due to lack of memory. |
| 40 | */ |
| 41 | |
| 42 | #define TREE_ELEMENT_UNIQUE ((TREE_ELEMENT *) 1) |
| 43 | #define TREE_NO_DUPS 1 |
| 44 | #define TREE_ONLY_DUPS 2 |
| 45 | |
| 46 | typedef enum { left_root_right, right_root_left } TREE_WALK; |
| 47 | typedef uint32 element_count; |
| 48 | typedef int (*tree_walk_action)(void *,element_count,void *); |
| 49 | |
| 50 | typedef enum { free_init, free_free, free_end } TREE_FREE; |
| 51 | typedef int (*tree_element_free)(void*, TREE_FREE, void *); |
| 52 | |
| 53 | typedef struct st_tree_element { |
| 54 | struct st_tree_element *left,*right; |
| 55 | uint32 count:31, |
| 56 | colour:1; /* black is marked as 1 */ |
| 57 | } TREE_ELEMENT; |
| 58 | |
| 59 | #define ELEMENT_CHILD(element, offs) (*(TREE_ELEMENT**)((char*)element + offs)) |
| 60 | |
| 61 | typedef struct st_tree { |
| 62 | TREE_ELEMENT *root,null_element; |
| 63 | TREE_ELEMENT **parents[MAX_TREE_HEIGHT]; |
| 64 | uint offset_to_key,elements_in_tree,size_of_element; |
| 65 | size_t memory_limit, allocated; |
| 66 | qsort_cmp2 compare; |
| 67 | void *custom_arg; |
| 68 | MEM_ROOT mem_root; |
| 69 | my_bool with_delete; |
| 70 | tree_element_free free; |
| 71 | myf my_flags; |
| 72 | uint flag; |
| 73 | } TREE; |
| 74 | |
| 75 | /* Functions on whole tree */ |
| 76 | void init_tree(TREE *tree, size_t default_alloc_size, size_t memory_limit, |
| 77 | int size, qsort_cmp2 compare, |
| 78 | tree_element_free free_element, void *custom_arg, |
| 79 | myf my_flags); |
| 80 | int delete_tree(TREE*, my_bool abort); |
| 81 | int reset_tree(TREE*); |
| 82 | |
| 83 | /* similar to delete tree, except we do not my_free() blocks in mem_root */ |
| 84 | #define is_tree_inited(tree) ((tree)->root != 0) |
| 85 | |
| 86 | /* Functions on leafs */ |
| 87 | TREE_ELEMENT *tree_insert(TREE *tree,void *key, uint key_size, |
| 88 | void *custom_arg); |
| 89 | void *tree_search(TREE *tree, void *key, void *custom_arg); |
| 90 | int tree_walk(TREE *tree,tree_walk_action action, |
| 91 | void *argument, TREE_WALK visit); |
| 92 | int tree_delete(TREE *tree, void *key, uint key_size, void *custom_arg); |
| 93 | void *tree_search_key(TREE *tree, const void *key, |
| 94 | TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos, |
| 95 | enum ha_rkey_function flag, void *custom_arg); |
| 96 | void *tree_search_edge(TREE *tree, TREE_ELEMENT **parents, |
| 97 | TREE_ELEMENT ***last_pos, int child_offs); |
| 98 | void *tree_search_next(TREE *tree, TREE_ELEMENT ***last_pos, int l_offs, |
| 99 | int r_offs); |
| 100 | ha_rows tree_record_pos(TREE *tree, const void *key, |
| 101 | enum ha_rkey_function search_flag, void *custom_arg); |
| 102 | #define reset_free_element(tree) (tree)->free= 0 |
| 103 | |
| 104 | #define (sizeof(TREE_ELEMENT) + sizeof(void*)) |
| 105 | |
| 106 | #ifdef __cplusplus |
| 107 | } |
| 108 | #endif |
| 109 | #endif |
| 110 | |