diff options
Diffstat (limited to 'source/luametatex/source/libraries/avl/avl.h')
-rw-r--r-- | source/luametatex/source/libraries/avl/avl.h | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/source/luametatex/source/libraries/avl/avl.h b/source/luametatex/source/libraries/avl/avl.h new file mode 100644 index 000000000..03a1384b7 --- /dev/null +++ b/source/luametatex/source/libraries/avl/avl.h @@ -0,0 +1,445 @@ +/* + This small C package is made of an independent set of routines dedicated to manipulating AVL + trees (files avl.c, avl.h), and of an extension module for Python that builds upon it (file + avlmodule.c). Unlike collectionsmodule.c, the latter file contains only Python bindings: it + adds nothing to the underlying implementation. + + license: this package, pyavl, is donated to the public domain + author : Richard McGraw + email : dasnar@fastmail.fm +*/ + +/* + This file is reformatted a little. As there has not been any changed in the original we assume + this is okay. No changes means that the code is fine and we never ran into issues. + + The avl code is used for hashing strings. It is also used in the backend of luatex but in + luametatex we don't have that. +*/ + +# ifndef LIBRARIES_AVL_H +# define LIBRARIES_AVL_H + +# include <stdarg.h> +# include <stdio.h> +# include <stdlib.h> + +// # define avl_del mp_avl_del +// # define avl_ins mp_avl_ins +// # define avl_tree mp_avl_tree +// # define avl_entry mp_avl_entry +// # define avl_find mp_avl_find +// # define avl_create mp_avl_create +// # define avl_destroy mp_avl_destroy + +typedef enum avl_bool_t { + avl_false, + avl_true +} avl_bool_t; + +# include <inttypes.h> + +typedef int8_t avl_code_t; +typedef int8_t avl_bal_t; +typedef uint32_t avl_size_t; + +typedef int (*avl_compare_func) (void *param, const void *lhs, const void *rhs); +typedef void *(*avl_item_copy_func) (const void *item); +typedef void *(*avl_item_dispose_func) (void *item); +typedef void (*avl_item_func) (const void *item, void *param); +typedef void *(*avl_alloc_func) (size_t); +typedef void (*avl_dealloc_func) (void *); + +/* At minimum, shallow copy */ + +const void *avl_default_item_copy (const void *); +void *avl_default_item_dispose (void *); + +# define AVL_STACK_CAPACITY 32 /* for avl_split() function */ + +typedef enum avl_ini_t { + AVL_ITERATOR_INI_PRE, + AVL_ITERATOR_INI_POST, + AVL_ITERATOR_INI_INTREE +} avl_ini_t; + +typedef struct avl_tree_ *avl_tree; +typedef struct avl_iterator_ *avl_iterator; +typedef struct avl_itersource_ avl_itersource_struct; +typedef struct avl_itersource_ *avl_itersource; + +struct avl_itersource_ { + void *p; + /* return nonzero on error */ + avl_code_t(*f) (avl_itersource from, void **to); +}; + +typedef struct { + avl_compare_func compare; + avl_item_copy_func copy; + avl_item_dispose_func dispose; + avl_alloc_func alloc; + avl_dealloc_func dealloc; +} avl_config_struct, *avl_config; + +/* Public Functions */ + +/* + --- CREATE --- + Return a new tree and set its config. + Return NULL on allocation failure. + * 'alloc' defaults to malloc from stdlib + * 'dealloc' defaults to free from stdlib + * 'param' user param/refcon +*/ + +avl_tree avl_create( + avl_compare_func compare, + avl_item_copy_func copy, + avl_item_dispose_func dispose, + avl_alloc_func alloc, + avl_dealloc_func dealloc, + void *param +); + +/* + --- RESET --- + Empty tree 't' as in 'avl_empty()' and modify its config. +*/ + +void avl_reset( + avl_tree t, + avl_compare_func compare, + avl_item_copy_func copy, + avl_item_dispose_func dispose, + avl_alloc_func alloc, + avl_dealloc_func dealloc +); + +/* + --- EMPTY --- + Empty tree 't', calling its dispose_func for each item in 't'. The config is + untouched. +*/ + +void avl_empty(avl_tree t); + +/* + --- DESTROY --- + Empty tree 't' and free the handle. +*/ + +void avl_destroy(avl_tree t); + +/* + --- DUPLICATE (COPY) --- + Return a copy of tree 't', using its copy_func for each item in 't'. Upon + failure to allocate room for some item, return NULL. +*/ + +avl_tree avl_dup(avl_tree t, void *param); + +/* + --- EMPTYNESS --- + Return 'avl_true' iff tree 't' is empty (i.e. the handle is NULL or 't' + contains no item). +*/ + +avl_bool_t avl_isempty(avl_tree t); + +/* + --- SIZE --- + Return number of items contained in tree 't'. +*/ + +avl_size_t avl_size(avl_tree t); + +/* + --- FIRST (MINIMUM) --- + Return first item in in-order traversal of 't'. Return NULL if 't' is empty. +*/ + +void *avl_first(avl_tree t); + +/* + --- LAST (MAXIMUM) --- + Return last item in in-order traversal of 't'. Return NULL if 't' is empty. +*/ + +void *avl_last(avl_tree t); + +/* + --- FIND MATCHING ITEM --- + Find item matching 'item' parameter in tree 't'. Return NULL if it's not + found. If there are multiple matches, the first one that is encountered + during the search is returned; it may not be the one with lowest rank. +*/ + +void *avl_find(const void *item, avl_tree t); + +/* + --- INDEX (RANK) OF ITEM --- + Return smallest index 'i' s.t. 't[i]' matches 'item', or zero if 'item' is + not found. +*/ + +avl_size_t avl_index(const void *item, avl_tree t); + +/* + --- SPAN ITEMS --- + Return integers 'i,j' s.t. 't[i,j]' + i smallest index s.t. t[i] >= lo_item, or t->count+1 and + j greatest one s.t. t[j] <= hi_item, or 0. + + If 'hi_item' is less than 'lo_item' those are swapped. + + Return codes: + 0 success + -1 error: tree had no root + -2 error: compare failed +*/ + +avl_code_t avl_span( + const void *lo_item, + const void *hi_item, + avl_tree t, + avl_size_t *lo_idx, + avl_size_t *hi_idx +); + +/* + --- FIND AT LEAST --- + Return smallest item in 't' that is GEQ 'item', or NULL. +*/ + +void *avl_find_atleast(const void *item, avl_tree t); + +/* + --- FIND AT MOST --- + Return largest item in 't' that is LEQ 'item', or NULL. +*/ + +void *avl_find_atmost(const void *item, avl_tree t); + +/* + --- FIND BY INDEX (RANK) --- + Find item in 't' by index, that is return 't[idx]'. If 'idx' is not in + '[1,avl_size(t)]' then return NULL. If a compare failed then return NULL. +*/ + +void *avl_find_index(avl_size_t idx, avl_tree t); + +/* + --- INSERTION --- + Insert 'item' in tree 't' with regard to its compare_func. Say + 'avl_ins(item,t,avl_true)' to insert 'item' in 't' even if it is there + already. If 'item' is a duplicate and 'allow_duplicates' is avl_false, + nothing is done. + + Return codes: + -1 error: allocation of new node failed + -2 error: compare failed, tree unchanged + 0 nothing was done, no error + +1 operation successful + +2 the same and height(t) increased by one. +*/ + +avl_code_t avl_ins(void *item, avl_tree t, avl_bool_t allow_duplicates); + +/* + --- DELETION --- + Remove 'item' from tree 't', calling its dispose_func. To make a backup of + 'item' involving its copy_func, say 't(item,backup)' where 'backup' is some + pointer to pointer to item. Otherwise set it to NULL. + + Return codes: + 0 item not found + -2 error: compare failed, tree unchanged + +1 operation successful + +2 the same and height(t) decreased by one. +*/ + +avl_code_t avl_del(void *item, avl_tree t, void **backup); + +/* + --- DELETE FIRST --- + Remove first item in in-order traversal from tree 't'. Note that only one + item is removed. Return +1 or +2 as above. +*/ + +avl_code_t avl_del_first(avl_tree t, void **backup); + +/* + --- DELETE LAST --- + Remove last item in in-order traversal from tree 't'. Note that only one item + is removed. Return +1 or +2 as above. +*/ + +avl_code_t avl_del_last(avl_tree t, void **backup); + +/* + --- INSERT IN FRONT OF INDEX --- + Insert 'item' in tree 't' so that afterwards, 't[idx]=item' except if + 'idx<=0' or 'idx>size(t)+1'. To append 'item' to 't' regardless of order, say + 'avl_ins_index(item,size+1,t)'. +*/ + +avl_code_t avl_ins_index(void *item, avl_size_t idx, avl_tree t); + +/* + --- DELETE ITEM BY INDEX --- + Remove item of rank 'idx' from tree 't' and return +1 or +2 as above except + if 'idx' is not in '[1,avl_size(t)]' in which case return 0. +*/ + +avl_code_t avl_del_index(avl_size_t idx, avl_tree t, void **backup); + +/* + --- IN-PLACE CONCATENATION --- + Pre-condition: 't0' and 't1' are valid avl_trees Note that the code does not + check whether the maximal item in 't0' is LEQ than the minimal item in 't1'. + Post-condition: 't0' handles the concatenation of 't0' and 't1' which becomes + empty (but its config is untouched). +*/ + +void avl_cat(avl_tree t0, avl_tree t1); + +/* + --- SPLITTING --- + Pre-condition: 't0' and 't1' are existing handles. Post-condition: items in + 't0' all compare LEQ than 'item' and items in 't1' all compare GEQ than + 'item'. This implementation removes one item. + + Return codes: + 0 item not found, no-op + -2 compare failed, tree unchanged + +1 success +*/ + +avl_code_t avl_split(const void *item, avl_tree t, avl_tree t0, avl_tree t1); + +/* + --- IN-ORDER TRAVERSAL --- + Walk tree 't' in in-order, applying 'proc' at each node. The 'param' pointer + is passed to 'proc', like this: '(*proc) (item_at_node,param)'. +*/ + +void avl_walk(avl_tree t, avl_item_func proc, void *param); + +/* + --- SLICE --- + Create a _new tree_ from the slice 't[lo_idx,hi_idx)' provided 'lo_idx <= + hi_idx' and these indices are both in range. If a new tree can't be created + or if some item can't be allocated, return NULL. Otherwise if the indices are + inconsistent return NULL. +*/ + +avl_tree avl_slice(avl_tree t, avl_size_t lo_idx, avl_size_t hi_idx, void *param); + +/* + ITERATORS + + An iterator assigned to a tree 't' is still usable after any item is inserted + into 't' and after any item not located at this iterator's current position + is deleted. The 'avl_iterator_del()' function may be used to remove the item + at the iterator's current position. + +*/ + +/* + --- ITERATOR --- SEEK + Find 'item' in this iterator's tree as in 'avl_find()' and make it the + current position. +*/ + +void avl_iterator_seek(const void *item, avl_iterator iter); + +/* + --- ITERATOR --- COUNT + Return size of this iterator's tree +*/ + +avl_size_t avl_iterator_count(avl_iterator iter); + +/* + --- ITERATOR --- SEEK BY INDEX + Set the current position of 'iter' to 't[idx]' where 't' is the tree that is + iterated over. +*/ + +void avl_iterator_seek_index(avl_size_t idx, avl_iterator iter); + +/* + --- ITERATOR --- CURRENT POSITION + Return item at current position of 'iter'. +*/ + +void *avl_iterator_cur(avl_iterator iter); + +/* + --- ITERATOR --- INDEX + Return rank of current item of 'iter' (as a result of computation) except it + returns 0 or size of tree plus one if 'iter' is a pre- or post- iterator. +*/ + +avl_size_t avl_iterator_index(avl_iterator iter); + +/* + --- ITERATOR --- CREATE + Return a new cursor for tree 't'. If allocation of an iterator struct is + impossible, return NULL. Say 'avl_iterator_new(t, ini)' with + 'ini==AVL_ITERATOR_INI_PRE' or 'ini==AVL_ITERATOR_INI_POST' or say + 'avl_iterator_new(t, AVL_ITERATOR_INI_INTREE, item_pointer)' to set the + iterator's current position via + 'avl_iterator_seek(item_pointer,the_iterator)'. In the latter case, the + iterator is flagged as pre-iterator if the item is not found. +*/ + +avl_iterator avl_iterator_new(avl_tree t, avl_ini_t ini, ...); + +/* + --- ITERATOR --- KILL + Cleanup: free the iterator struct. +*/ + +void avl_iterator_kill(avl_iterator iter); + +/* + --- ITERATOR --- SUCCESSOR + Get next item pointer in iterator or NULL. 'iter' is flagged as post-iterator + if it's in post-position. +*/ + +void *avl_iterator_next(avl_iterator iter); + +/* + --- ITERATOR --- PREDECESSOR + Get next item pointer in iterator or NULL. 'iter' is flagged as pre-iterator + if it's in pre-position. +*/ + +void *avl_iterator_prev(avl_iterator iter); + +/* + --- ITERATOR --- DELETION + Remove item at current position of iterator 'iter' from its tree, if there is + one. Current position is set to next item or iterator is flagged as + post-iterator. +*/ + +avl_code_t avl_iterator_del(avl_iterator iter, void **backup); + +/* + --- LOAD --- + More general version of avl_slice +*/ + +avl_tree avl_xload( + avl_itersource src, + void **pres, + avl_size_t len, + avl_config conf, + void *param +); + +# endif |