summaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/include')
-rw-r--r--src/include/sglib.h1952
-rw-r--r--src/include/tome/enum_string_map.hpp55
-rw-r--r--src/include/tome/make_array.hpp13
-rw-r--r--src/include/tome/squelch/automatizer.hpp156
-rw-r--r--src/include/tome/squelch/automatizer_fwd.hpp10
-rw-r--r--src/include/tome/squelch/condition.hpp632
-rw-r--r--src/include/tome/squelch/condition_fwd.hpp15
-rw-r--r--src/include/tome/squelch/condition_metadata.hpp12
-rw-r--r--src/include/tome/squelch/condition_metadata_fwd.hpp14
-rw-r--r--src/include/tome/squelch/cursor.hpp50
-rw-r--r--src/include/tome/squelch/cursor_fwd.hpp10
-rw-r--r--src/include/tome/squelch/object_status.hpp28
-rw-r--r--src/include/tome/squelch/object_status_fwd.hpp12
-rw-r--r--src/include/tome/squelch/rule.hpp162
-rw-r--r--src/include/tome/squelch/rule_fwd.hpp16
-rw-r--r--src/include/tome/squelch/tree_printer.hpp49
-rw-r--r--src/include/tome/squelch/tree_printer_fwd.hpp10
17 files changed, 1244 insertions, 1952 deletions
diff --git a/src/include/sglib.h b/src/include/sglib.h
deleted file mode 100644
index 1a4780fa..00000000
--- a/src/include/sglib.h
+++ /dev/null
@@ -1,1952 +0,0 @@
-/*
-
- This is SGLIB version 1.0.3
-
- (C) by Marian Vittek, Bratislava, http://www.xref-tech.com/sglib, 2003-5
-
- License Conditions: You can use a verbatim copy (including this
- copyright notice) of sglib freely in any project, commercial or not.
- You can also use derivative forms freely under terms of Open Source
- Software license or under terms of GNU Public License. If you need
- to use a derivative form in a commercial project, or you need sglib
- under any other license conditions, contact the author.
-
-
-
-*/
-
-
-#ifndef _SGLIB__h_
-#define _SGLIB__h_
-
-/* the assert is used exclusively to write unexpected error messages */
-#include <assert.h>
-
-
-/* ---------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------- */
-/* - LEVEL - 0 INTERFACE - */
-/* ---------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------- */
-
-
-/* ---------------------------------------------------------------------------- */
-/* ------------------------------ STATIC ARRAYS ------------------------------- */
-/* ---------------------------------------------------------------------------- */
-
-/*
-
- Basic algorithms for sorting arrays. Multiple depending arrays can
- be rearranged using user defined 'elem_exchangers'
-
-*/
-
-/* HEAP - SORT (level 0) */
-
-#define SGLIB_ARRAY_SINGLE_HEAP_SORT(type, a, max, comparator) {\
- SGLIB_ARRAY_HEAP_SORT(type, a, max, comparator, SGLIB_ARRAY_ELEMENTS_EXCHANGER);\
-}
-
-#define SGLIB_ARRAY_HEAP_SORT(type, a, max, comparator, elem_exchanger) {\
- int _k_;\
- for(_k_=(max)/2; _k_>=0; _k_--) {\
- SGLIB___ARRAY_HEAP_DOWN(type, a, _k_, max, comparator, elem_exchanger);\
- }\
- for(_k_=(max)-1; _k_>=0; _k_--) {\
- elem_exchanger(type, a, 0, _k_);\
- SGLIB___ARRAY_HEAP_DOWN(type, a, 0, _k_, comparator, elem_exchanger);\
- }\
-}
-
-#define SGLIB___ARRAY_HEAP_DOWN(type, a, ind, max, comparator, elem_exchanger) {\
- type _t_;\
- int _m_, _l_, _r_, _i_;\
- _i_ = (ind);\
- _m_ = _i_;\
- do {\
- _i_ = _m_; \
- _l_ = 2*_i_+1;\
- _r_ = _l_+1;\
- if (_l_ < (max)){\
- if (comparator(((a)[_m_]), ((a)[_l_])) < 0) _m_ = _l_;\
- if (_r_ < (max)) {\
- if (comparator(((a)[_m_]), ((a)[_r_])) < 0) _m_ = _r_;\
- }\
- }\
- if (_m_ != _i_) {\
- elem_exchanger(type, a, _i_, _m_);\
- }\
- } while (_m_ != _i_);\
-}
-
-
-/* QUICK - SORT (level 0) */
-
-#define SGLIB_ARRAY_SINGLE_QUICK_SORT(type, a, max, comparator) {\
- SGLIB_ARRAY_QUICK_SORT(type, a, max, comparator, SGLIB_ARRAY_ELEMENTS_EXCHANGER);\
-}
-
-#define SGLIB_ARRAY_QUICK_SORT(type, a, max, comparator, elem_exchanger) {\
- int _i_, _j_, _p_, _stacki_, _start_, _end_;\
- /* can sort up to 2^64 elements */\
- int _startStack_[64]; \
- int _endStack_[64];\
- type _tmp_;\
- _startStack_[0] = 0;\
- _endStack_[0] = (max);\
- _stacki_ = 1;\
- while (_stacki_ > 0) {\
- _stacki_ --;\
- _start_ = _startStack_[_stacki_];\
- _end_ = _endStack_[_stacki_];\
- while (_end_ - _start_ > 2) {\
- _p_ = _start_;\
- _i_ = _start_ + 1;\
- _j_ = _end_ - 1;\
- while (_i_<_j_) {\
- for(; _i_<=_j_ && comparator(((a)[_i_]),((a)[_p_]))<=0; _i_++) ;\
- if (_i_ > _j_) {\
- /* all remaining elements lesseq than pivot */\
- elem_exchanger(type, a, _j_, _p_);\
- _i_ = _j_;\
- } else {\
- for(; _i_<=_j_ && comparator(((a)[_j_]),((a)[_p_]))>=0; _j_--) ;\
- if (_i_ > _j_) {\
- /* all remaining elements greater than pivot */\
- elem_exchanger(type, a, _j_, _p_);\
- _i_ = _j_;\
- } else if (_i_ < _j_) {\
- elem_exchanger(type, a, _i_, _j_);\
- if (_i_+2 < _j_) {_i_++; _j_--;}\
- else if (_i_+1 < _j_) _i_++;\
- }\
- }\
- }\
- /* O.K. i==j and pivot is on a[i] == a[j] */\
- /* handle recursive calls without recursion */\
- if (_i_-_start_ > 1 && _end_-_j_ > 1) {\
- /* two recursive calls, use array-stack */\
- if (_i_-_start_ < _end_-_j_-1) {\
- _startStack_[_stacki_] = _j_+1;\
- _endStack_[_stacki_] = _end_;\
- _stacki_ ++;\
- _end_ = _i_;\
- } else {\
- _startStack_[_stacki_] = _start_;\
- _endStack_[_stacki_] = _i_;\
- _stacki_ ++;\
- _start_ = _j_+1;\
- }\
- } else {\
- if (_i_-_start_ > 1) {\
- _end_ = _i_;\
- } else {\
- _start_ = _j_+1;\
- }\
- }\
- }\
- if (_end_ - _start_ == 2) {\
- if (comparator(((a)[_start_]),((a)[_end_-1])) > 0) {\
- elem_exchanger(type, a, _start_, _end_-1);\
- }\
- }\
- }\
-}
-
-/* BINARY SEARCH (level 0) */
-
-#define SGLIB_ARRAY_BINARY_SEARCH(type, a, start_index, end_index, key, comparator, found, result_index) {\
- int _kk_, _cc_, _ii_, _jj_, _ff_;\
- _ii_ = (start_index); \
- _jj_ = (end_index);\
- _ff_ = 0;\
- while (_ii_ <= _jj_ && _ff_==0) {\
- _kk_ = (_jj_+_ii_)/2;\
- _cc_ = comparator(((a)[_kk_]), (key));\
- if (_cc_ == 0) {\
- (result_index) = _kk_; \
- _ff_ = 1;\
- } else if (_cc_ < 0) {\
- _ii_ = _kk_+1;\
- } else {\
- _jj_ = _kk_-1;\
- }\
- }\
- if (_ff_ == 0) {\
- /* not found, but set its resulting place in the array */\
- (result_index) = _jj_+1;\
- }\
- (found) = _ff_;\
-}
-
-/* -------------------------------- queue (in an array) ------------------ */
-/* queue is a quadruple (a,i,j,dim) such that: */
-/* a is the array storing values */
-/* i is the index of the first used element in the array */
-/* j is the index of the first free element in the array */
-/* dim is the size of the array a */
-/* !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! */
-
-#define SGLIB_QUEUE_INIT(type, a, i, j) { i = j = 0; }
-#define SGLIB_QUEUE_IS_EMPTY(type, a, i, j) ((i)==(j))
-#define SGLIB_QUEUE_IS_FULL(type, a, i, j, dim) ((i)==((j)+1)%(dim))
-#define SGLIB_QUEUE_FIRST_ELEMENT(type, a, i, j) (a[i])
-#define SGLIB_QUEUE_ADD_NEXT(type, a, i, j, dim) {\
- if (SGLIB_QUEUE_IS_FULL(type, a, i, j, dim)) assert(0 && "the queue is full");\
- (j) = ((j)+1) % (dim);\
-}
-#define SGLIB_QUEUE_ADD(type, a, elem, i, j, dim) {\
- a[j] = (elem);\
- SGLIB_QUEUE_ADD_NEXT(type, a, i, j, dim);\
-}
-#define SGLIB_QUEUE_DELETE_FIRST(type, a, i, j, dim) {\
- if (SGLIB_QUEUE_IS_EMPTY(type, a, i, j)) assert(0 && "the queue is empty");\
- (i) = ((i)+1) % (dim);\
-}
-#define SGLIB_QUEUE_DELETE(type, a, i, j, dim) {\
- SGLIB_QUEUE_DELETE_FIRST(type, a, i, j, dim);\
-}
-
-/* ----------------- priority queue (heap) (in an array) -------------------- */
-/* heap is a triple (a,i,dim) such that: */
-/* a is the array storing values */
-/* i is the index of the first free element in the array */
-/* dim is the size of the array a */
-/* !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! */
-
-#define SGLIB_HEAP_INIT(type, a, i) { i = 0; }
-#define SGLIB_HEAP_IS_EMPTY(type, a, i) ((i)==0)
-#define SGLIB_HEAP_IS_FULL(type, a, i, dim) ((i)==(dim))
-#define SGLIB_HEAP_FIRST_ELEMENT(type, a, i) (a[0])
-#define SGLIB_HEAP_ADD_NEXT(type, a, i, dim, comparator, elem_exchanger) {\
- int _i_;\
- if (SGLIB_HEAP_IS_FULL(type, a, i, dim)) assert(0 && "the heap is full");\
- _i_ = (i)++;\
- while (_i_ > 0 && comparator(a[_i_/2], a[_i_]) < 0) {\
- elem_exchanger(type, a, (_i_/2), _i_);\
- _i_ = _i_/2;\
- }\
-}
-#define SGLIB_HEAP_ADD(type, a, elem, i, dim, comparator) {\
- if (SGLIB_HEAP_IS_FULL(type, a, i, dim)) assert(0 && "the heap is full");\
- a[i] = (elem);\
- SGLIB_HEAP_ADD_NEXT(type, a, i, dim, comparator, SGLIB_ARRAY_ELEMENTS_EXCHANGER);\
-}
-#define SGLIB_HEAP_DELETE_FIRST(type, a, i, dim, comparator, elem_exchanger) {\
- if (SGLIB_HEAP_IS_EMPTY(type, a, i)) assert(0 && "the heap is empty");\
- (i)--;\
- a[0] = a[i];\
- SGLIB___ARRAY_HEAP_DOWN(type, a, 0, i, comparator, elem_exchanger);\
-}
-#define SGLIB_HEAP_DELETE(type, a, i, dim, comparator) {\
- SGLIB_HEAP_DELETE_FIRST(type, a, i, dim, comparator, SGLIB_ARRAY_ELEMENTS_EXCHANGER);\
-}
-
-
-/* ----------------- hashed table of pointers (in an array) -------------------- */
-
-/*
-
- This hashed table is storing pointers to objects (not containers).
- In this table there is a one-to-one mapping between 'objects' stored
- in the table and indexes where they are placed. Each index is
- pointing to exactly one 'object' and each 'object' stored in the
- table occurs on exactly one index. Once an object is stored in the
- table, it can be represented via its index.
-
- In case of collision while adding an object the index shifted
- by SGLIB_HASH_TAB_SHIFT_CONSTANT (constant can be redefined)
-
- You can NOT delete an element from such hash table. The only
- justification (I can see) for this data structure is an exchange
- file format, having an index table at the beginning and then
- refering objects via indexes.
-
- !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!!
-
-*/
-
-#define SGLIB_HASH_TAB_INIT(type, table, dim) {\
- int _i_;\
- for(_i_ = 0; _i_ < (dim); _i_++) (table)[_i_] = NULL;\
-}
-
-#define SGLIB_HASH_TAB_ADD_IF_NOT_MEMBER(type, table, dim, elem, hash_function, comparator, member){\
- unsigned _pos_;\
- type *_elem_;\
- SGLIB_HASH_TAB_FIND_MEMBER(type, table, dim, elem, _pos_, _elem_);\
- (member) = (table)[_pos_];\
- if (_elem_ == NULL) {\
- if ((table)[_pos_] != NULL) assert(0 && "the hash table is full");\
- (table)[_pos_] = (elem);\
- }\
-}
-
-#define SGLIB_HASH_TAB_FIND_MEMBER(type, table, dim, elem, hash_function, comparator, resultIndex, resultMember) {\
- unsigned _i_;\
- int _count_;\
- type *_e_;\
- _count = 0;\
- _i_ = hash_function(elem);\
- _i_ %= (dim);\
- while ((_e_=(table)[_i_])!=NULL && comparator(_e_, (elem))!=0 && _count_<(dim)) {\
- _count_ ++;\
- _i_ = (_i_ + SGLIB_HASH_TAB_SHIFT_CONSTANT) % (dim);\
- }\
- (resultIndex) = _i_;\
- if (_count_ < (dim)) (resultMember) = _e_;\
- else (resultMember) = NULL;\
-}
-
-#define SGLIB_HASH_TAB_IS_MEMBER(type, table, dim, elem, hash_function, resultIndex) {\
- unsigned _i_;\
- int _c_;\
- type *_e_;\
- _count = 0;\
- _i_ = hash_function(elem);\
- _i_ %= (dim);\
- while ((_e_=(table)[_i_])!=NULL && _e_!=(elem) && _c_<(dim)) {\
- _c_ ++;\
- _i_ = (_i_ + SGLIB_HASH_TAB_SHIFT_CONSTANT) % (dim);\
- }\
- if (_e_==(elem)) (resultIndex) = _i_;\
- else (resultIndex) = -1;\
-}
-
-#define SGLIB_HASH_TAB_MAP_ON_ELEMENTS(type, table, dim, iteratedIndex, iteratedVariable, command) {\
- unsigned iteratedIndex;\
- type *iteratedVariable;\
- for(iteratedIndex=0; iteratedIndex < (dim); iteratedIndex++) {\
- iteratedVariable = (table)[iteratedIndex];\
- if (iteratedVariable != NULL) {command;}\
- }\
-}
-
-
-/* ---------------------------------------------------------------------------- */
-/* ------------------------- DYNAMIC DATA STRUCTURES -------------------------- */
-/* ---------------------------------------------------------------------------- */
-
-/* ------------------------------------ lists (level 0) --------------------- */
-
-#define SGLIB_LIST_ADD(type, list, elem, next) {\
- (elem)->next = (list);\
- (list) = (elem);\
-}
-
-#define SGLIB_LIST_CONCAT(type, first, second, next) {\
- if ((first)==NULL) {\
- (first) = (second);\
- } else {\
- type *_p_;\
- for(_p_ = (first); _p_->next!=NULL; _p_=_p_->next) ;\
- _p_->next = (second);\
- }\
-}
-
-#define SGLIB_LIST_DELETE(type, list, elem, next) {\
- type **_p_;\
- for(_p_ = &(list); *_p_!=NULL && *_p_!=(elem); _p_= &(*_p_)->next) ;\
- assert(*_p_!=NULL && "element is not member of the container, use DELETE_IF_MEMBER instead"!=NULL);\
- *_p_ = (*_p_)->next;\
-}
-
-#define SGLIB_LIST_ADD_IF_NOT_MEMBER(type, list, elem, comparator, next, member) {\
- type *_p_;\
- for(_p_ = (list); _p_!=NULL && comparator(_p_, (elem)) != 0; _p_= _p_->next) ;\
- (member) = _p_;\
- if (_p_ == NULL) {\
- SGLIB_LIST_ADD(type, list, elem, next);\
- }\
-}
-
-#define SGLIB_LIST_DELETE_IF_MEMBER(type, list, elem, comparator, next, member) {\
- type **_p_;\
- for(_p_ = &(list); *_p_!=NULL && comparator((*_p_), (elem)) != 0; _p_= &(*_p_)->next) ;\
- (member) = *_p_;\
- if (*_p_ != NULL) {\
- *_p_ = (*_p_)->next;\
- }\
-}
-
-#define SGLIB_LIST_IS_MEMBER(type, list, elem, next, result) {\
- type *_p_;\
- for(_p_ = (list); _p_!=NULL && _p_ != (elem); _p_= _p_->next) ;\
- (result) = (_p_!=NULL);\
-}
-
-#define SGLIB_LIST_FIND_MEMBER(type, list, elem, comparator, next, member) {\
- type *_p_;\
- for(_p_ = (list); _p_!=NULL && comparator(_p_, (elem)) != 0; _p_= _p_->next) ;\
- (member) = _p_;\
-}
-
-#define SGLIB_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, next, command) {\
- type *_ne_;\
- type *iteratedVariable;\
- (iteratedVariable) = (list); \
- while ((iteratedVariable)!=NULL) {\
- _ne_ = (iteratedVariable)->next;\
- {command;};\
- (iteratedVariable) = _ne_;\
- }\
-}
-
-#define SGLIB_LIST_LEN(type, list, next, result) {\
- type *_ce_;\
- (result) = 0;\
- SGLIB_LIST_MAP_ON_ELEMENTS(type, list, _ce_, next, (result)++);\
-}
-
-#define SGLIB_LIST_REVERSE(type, list, next) {\
- type *_list_,*_tmp_,*_res_;\
- _list_ = (list);\
- _res_ = NULL;\
- while (_list_!=NULL) {\
- _tmp_ = _list_->next; _list_->next = _res_;\
- _res_ = _list_; _list_ = _tmp_;\
- }\
- (list) = _res_;\
-}
-
-#define SGLIB_LIST_SORT(type, list, comparator, next) {\
- /* a non-recursive merge sort on lists */\
- type *_r_;\
- type *_a_, *_b_, *_todo_, *_t_, **_restail_;\
- int _i_, _n_, _contFlag_;\
- _r_ = (list);\
- _contFlag_ = 1;\
- for(_n_ = 1; _contFlag_; _n_ = _n_+_n_) {\
- _todo_ = _r_; _r_ = NULL; _restail_ = &_r_; _contFlag_ =0;\
- while (_todo_!=NULL) {\
- _a_ = _todo_;\
- for(_i_ = 1, _t_ = _a_; _i_ < _n_ && _t_!=NULL; _i_++, _t_ = _t_->next) ;\
- if (_t_ ==NULL) {\
- *_restail_ = _a_;\
- break;\
- }\
- _b_ = _t_->next; _t_->next=NULL;\
- for(_i_ =1, _t_ = _b_; _i_<_n_ && _t_!=NULL; _i_++, _t_ = _t_->next) ;\
- if (_t_ ==NULL) {\
- _todo_ =NULL;\
- } else {\
- _todo_ = _t_->next; _t_->next=NULL;\
- }\
- /* merge */\
- while (_a_!=NULL && _b_!=NULL) {\
- if (comparator(_a_, _b_) < 0) {\
- *_restail_ = _a_; _restail_ = &(_a_->next); _a_ = _a_->next;\
- } else {\
- *_restail_ = _b_; _restail_ = &(_b_->next); _b_ = _b_->next;\
- }\
- }\
- if (_a_!=NULL) *_restail_ = _a_;\
- else *_restail_ = _b_;\
- while (*_restail_!=NULL) _restail_ = &((*_restail_)->next);\
- _contFlag_ =1;\
- }\
- }\
- (list) = _r_;\
-}
-
-/* --------------------------------- sorted list (level 0) --------------------- */
-/*
- All operations suppose that the list is sorted and they preserve
- this property.
-*/
-
-
-#define SGLIB_SORTED_LIST_ADD(type, list, elem, comparator, next) {\
- type **_e_;\
- int _cmpres_;\
- SGLIB_SORTED_LIST_FIND_MEMBER_OR_PLACE(type, list, elem, comparator, next, _cmpres_, _e_);\
- (elem)->next = *_e_;\
- *_e_ = (elem);\
-}
-
-#define SGLIB_SORTED_LIST_ADD_IF_NOT_MEMBER(type, list, elem, comparator, next, member) {\
- type **_e_;\
- int _cmp_res_;\
- SGLIB_SORTED_LIST_FIND_MEMBER_OR_PLACE(type, list, elem, comparator, next, _cmp_res_, _e_);\
- if (_cmp_res_ != 0) {\
- (elem)->next = *_e_;\
- *_e_ = (elem);\
- (member) = NULL;\
- } else {\
- (member) = *_e_;\
- }\
-}
-
-#define SGLIB_SORTED_LIST_DELETE(type, list, elem, next) {\
- SGLIB_LIST_DELETE(type, list, elem, next);\
-}
-
-#define SGLIB_SORTED_LIST_DELETE_IF_MEMBER(type, list, elem, comparator, next, member) {\
- type **_e_;\
- int _cmp_res_;\
- SGLIB_SORTED_LIST_FIND_MEMBER_OR_PLACE(type, list, elem, comparator, next, _cmp_res_, _e_);\
- if (_cmp_res_ == 0) {\
- (member) = *_e_;\
- *_e_ = (*_e_)->next;\
- } else {\
- (member) = NULL;\
- }\
-}
-
-#define SGLIB_SORTED_LIST_FIND_MEMBER(type, list, elem, comparator, next, member) {\
- type *_p_;\
- int _cmpres_ = 1;\
- for(_p_ = (list); _p_!=NULL && (_cmpres_=comparator(_p_, (elem))) < 0; _p_=_p_->next) ;\
- if (_cmpres_ != 0) (member) = NULL;\
- else (member) = _p_;\
-}
-
-#define SGLIB_SORTED_LIST_IS_MEMBER(type, list, elem, comparator, next, result) {\
- type *_p_;\
- for(_p_ = (list); _p_!=NULL && comparator(_p_, (elem)) < 0; _p_=_p_->next) ;\
- while (_p_ != NULL && _p_ != (elem) && comparator(_p_, (elem)) == 0) _p_=_p_->next;\
- (result) = (_p_ == (elem));\
-}
-
-#define SGLIB_SORTED_LIST_FIND_MEMBER_OR_PLACE(type, list, elem, comparator, next, comparator_result, member_ptr) {\
- (comparator_result) = -1;\
- for((member_ptr) = &(list); \
- *(member_ptr)!=NULL && ((comparator_result)=comparator((*member_ptr), (elem))) < 0; \
- (member_ptr) = &(*(member_ptr))->next) ;\
-}
-
-#define SGLIB_SORTED_LIST_LEN(type, list, next, result) {\
- SGLIB_LIST_LEN(type, list, next, result);\
-}
-
-#define SGLIB_SORTED_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, next, command) {\
- SGLIB_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, next, command);\
-}
-
-
-/* ------------------------------- double linked list (level 0) ------------------------- */
-/*
- Lists with back pointer to previous element. Those lists implements deletion
- of an element in a constant time.
-*/
-
-#define SGLIB___DL_LIST_CREATE_SINGLETON(type, list, elem, previous, next) {\
- (list) = (elem);\
- (list)->next = (list)->previous = NULL;\
-}
-
-#define SGLIB_DL_LIST_ADD_AFTER(type, place, elem, previous, next) {\
- if ((place) == NULL) {\
- SGLIB___DL_LIST_CREATE_SINGLETON(type, place, elem, previous, next);\
- } else {\
- (elem)->next = (place)->next;\
- (elem)->previous = (place);\
- (place)->next = (elem);\
- if ((elem)->next != NULL) (elem)->next->previous = (elem);\
- }\
-}
-
-#define SGLIB_DL_LIST_ADD_BEFORE(type, place, elem, previous, next) {\
- if ((place) == NULL) {\
- SGLIB___DL_LIST_CREATE_SINGLETON(type, place, elem, previous, next);\
- } else {\
- (elem)->next = (place);\
- (elem)->previous = (place)->previous;\
- (place)->previous = (elem);\
- if ((elem)->previous != NULL) (elem)->previous->next = (elem);\
- }\
-}
-
-#define SGLIB_DL_LIST_ADD(type, list, elem, previous, next) {\
- SGLIB_DL_LIST_ADD_BEFORE(type, list, elem, previous, next)\
-}
-
-#define SGLIB___DL_LIST_GENERIC_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member, the_add_operation) {\
- type *_dlp_;\
- for(_dlp_ = (list); _dlp_!=NULL && comparator(_dlp_, (elem)) != 0; _dlp_= _dlp_->previous) ;\
- if (_dlp_ == NULL && (list) != NULL) {\
- for(_dlp_ = (list)->next; _dlp_!=NULL && comparator(_dlp_, (elem)) != 0; _dlp_= _dlp_->next) ;\
- }\
- (member) = _dlp_;\
- if (_dlp_ == NULL) {\
- the_add_operation(type, list, elem, previous, next);\
- }\
-}
-
-#define SGLIB_DL_LIST_ADD_BEFORE_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member) {\
- SGLIB___DL_LIST_GENERIC_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member, SGLIB_DL_LIST_ADD_BEFORE);\
-}
-
-#define SGLIB_DL_LIST_ADD_AFTER_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member) {\
- SGLIB___DL_LIST_GENERIC_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member, SGLIB_DL_LIST_ADD_AFTER);\
-}
-
-#define SGLIB_DL_LIST_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member) {\
- SGLIB___DL_LIST_GENERIC_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member, SGLIB_DL_LIST_ADD);\
-}
-
-#define SGLIB_DL_LIST_CONCAT(type, first, second, previous, next) {\
- if ((first)==NULL) {\
- (first) = (second);\
- } else if ((second)!=NULL) {\
- type *_dlp_;\
- for(_dlp_ = (first); _dlp_->next!=NULL; _dlp_=_dlp_->next) ;\
- SGLIB_DL_LIST_ADD_AFTER(type, _dlp_, second, previous, next);\
- }\
-}
-
-#define SGLIB_DL_LIST_DELETE(type, list, elem, previous, next) {\
- type *_l_;\
- _l_ = (list);\
- if (_l_ == (elem)) {\
- if ((elem)->previous != NULL) _l_ = (elem)->previous;\
- else _l_ = (elem)->next;\
- }\
- if ((elem)->next != NULL) (elem)->next->previous = (elem)->previous;\
- if ((elem)->previous != NULL) (elem)->previous->next = (elem)->next;\
- (list) = _l_;\
-}
-
-#define SGLIB_DL_LIST_DELETE_IF_MEMBER(type, list, elem, comparator, previous, next, member) {\
- type *_dlp_;\
- for(_dlp_ = (list); _dlp_!=NULL && comparator(_dlp_, (elem)) != 0; _dlp_= _dlp_->previous) ;\
- if (_dlp_ == NULL && (list) != NULL) {\
- for(_dlp_ = (list)->next; _dlp_!=NULL && comparator(_dlp_, (elem)) != 0; _dlp_= _dlp_->next) ;\
- }\
- (member) = _dlp_;\
- if (_dlp_ != NULL) {\
- SGLIB_DL_LIST_DELETE(type, list, _dlp_, previous, next);\
- }\
-}
-
-#define SGLIB_DL_LIST_IS_MEMBER(type, list, elem, previous, next, result) {\
- type *_dlp_;\
- SGLIB_LIST_IS_MEMBER(type, list, elem, previous, result);\
- if (result == 0 && (list) != NULL) {\
- _dlp_ = (list)->next;\
- SGLIB_LIST_IS_MEMBER(type, _dlp_, elem, next, result);\
- }\
-}
-
-#define SGLIB_DL_LIST_FIND_MEMBER(type, list, elem, comparator, previous, next, member) {\
- type *_dlp_;\
- SGLIB_LIST_FIND_MEMBER(type, list, elem, comparator, previous, member);\
- if ((member) == NULL && (list) != NULL) {\
- _dlp_ = (list)->next;\
- SGLIB_LIST_FIND_MEMBER(type, _dlp_, elem, comparator, next, member);\
- }\
-}
-
-#define SGLIB_DL_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, previous, next, command) {\
- type *_dl_;\
- type *iteratedVariable;\
- if ((list)!=NULL) {\
- _dl_ = (list)->next;\
- SGLIB_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, previous, command);\
- SGLIB_LIST_MAP_ON_ELEMENTS(type, _dl_, iteratedVariable, next, command);\
- }\
-}
-
-#define SGLIB_DL_LIST_SORT(type, list, comparator, previous, next) {\
- type *_dll_, *_dlp_, *_dlt_;\
- _dll_ = (list);\
- if (_dll_ != NULL) {\
- for(; _dll_->previous!=NULL; _dll_=_dll_->previous) ;\
- SGLIB_LIST_SORT(type, _dll_, comparator, next);\
- SGLIB___DL_LIST_CREATE_FROM_LIST(type, _dll_, previous, next);\
- (list) = _dll_;\
- }\
-}
-
-#define SGLIB_DL_LIST_GET_FIRST(type, list, previous, next, result) {\
- type *_dll_;\
- _dll_ = (list);\
- if (_dll_ != NULL) {\
- for(; _dll_->previous!=NULL; _dll_=_dll_->previous) ;\
- }\
- (result) = _dll_;\
-}
-
-#define SGLIB_DL_LIST_GET_LAST(type, list, previous, next, result) {\
- type *_dll_;\
- _dll_ = (list);\
- if (_dll_ != NULL) {\
- for(; _dll_->next!=NULL; _dll_=_dll_->next) ;\
- }\
- (result) = _dll_;\
-}
-
-#define SGLIB_DL_LIST_LEN(type, list, previous, next, result) {\
- type *_dl_;\
- int _r1_, _r2_;\
- if ((list)==NULL) {\
- (result) = 0;\
- } else {\
- SGLIB_LIST_LEN(type, list, previous, _r1_);\
- _dl_ = (list)->next;\
- SGLIB_LIST_LEN(type, _dl_, next, _r2_);\
- (result) = _r1_ + _r2_;\
- }\
-}
-
-#define SGLIB_DL_LIST_REVERSE(type, list, previous, next) {\
- type *_list_,*_nlist_,*_dlp_,*_dln_;\
- _list_ = (list);\
- if (_list_!=NULL) {\
- _nlist_ = _list_->next;\
- while (_list_!=NULL) {\
- _dln_ = _list_->next; \
- _dlp_ = _list_->previous; \
- _list_->next = _dlp_;\
- _list_->previous = _dln_;\
- _list_ = _dlp_;\
- }\
- while (_nlist_!=NULL) {\
- _dln_ = _nlist_->next; \
- _dlp_ = _nlist_->previous; \
- _nlist_->next = _dlp_;\
- _nlist_->previous = _dln_;\
- _nlist_ = _dln_;\
- }\
- }\
-}
-
-#define SGLIB___DL_LIST_CREATE_FROM_LIST(type, list, previous, next) {\
- type *_dlp_, *_dlt_;\
- _dlp_ = NULL;\
- for(_dlt_ = (list); _dlt_!=NULL; _dlt_ = _dlt_->next) {\
- _dlt_->previous = _dlp_;\
- _dlp_ = _dlt_;\
- }\
-}
-
-
-/* ------------------------------- binary tree traversal (level 0) -------------------- */
-
-
-#define SGLIB___BIN_TREE_MAP_ON_ELEMENTS(type, tree, iteratedVariable, order, left, right, command) {\
- /* this is non-recursive implementation of tree traversal */\
- /* it maintains the path to the current node in the array '_path_' */\
- /* the _path_[0] contains the root of the tree; */\
- /* the _path_[_pathi_] contains the _current_element_ */\
- /* the macro does not use the _current_element_ after execution of command */\
- /* command can destroy it, it can free the element for example */\
- type *_path_[SGLIB_MAX_TREE_DEEP];\
- type *_right_[SGLIB_MAX_TREE_DEEP];\
- char _pass_[SGLIB_MAX_TREE_DEEP];\
- type *_cn_;\
- int _pathi_;\
- type *iteratedVariable;\
- _cn_ = (tree);\
- _pathi_ = 0;\
- while (_cn_!=NULL) {\
- /* push down to leftmost innermost element */\
- while(_cn_!=NULL) {\
- _path_[_pathi_] = _cn_;\
- _right_[_pathi_] = _cn_->right;\
- _pass_[_pathi_] = 0;\
- _cn_ = _cn_->left;\
- if (order == 0) {\
- iteratedVariable = _path_[_pathi_];\
- {command;}\
- }\
- _pathi_ ++;\
- if (_pathi_ >= SGLIB_MAX_TREE_DEEP) assert(0 && "the binary_tree is too deep");\
- }\
- do {\
- _pathi_ --;\
- if ((order==1 && _pass_[_pathi_] == 0)\
- || (order == 2 && (_pass_[_pathi_] == 1 || _right_[_pathi_]==NULL))) {\
- iteratedVariable = _path_[_pathi_];\
- {command;}\
- }\
- _pass_[_pathi_] ++;\
- } while (_pathi_>0 && _right_[_pathi_]==NULL) ;\
- _cn_ = _right_[_pathi_];\
- _right_[_pathi_] = NULL;\
- _pathi_ ++;\
- }\
-}
-
-#define SGLIB_BIN_TREE_MAP_ON_ELEMENTS(type, tree, _current_element_, left, right, command) {\
- SGLIB___BIN_TREE_MAP_ON_ELEMENTS(type, tree, _current_element_, 1, left, right, command);\
-}
-
-#define SGLIB_BIN_TREE_MAP_ON_ELEMENTS_PREORDER(type, tree, _current_element_, left, right, command) {\
- SGLIB___BIN_TREE_MAP_ON_ELEMENTS(type, tree, _current_element_, 0, left, right, command);\
-}
-
-#define SGLIB_BIN_TREE_MAP_ON_ELEMENTS_POSTORDER(type, tree, _current_element_, left, right, command) {\
- SGLIB___BIN_TREE_MAP_ON_ELEMENTS(type, tree, _current_element_, 2, left, right, command);\
-}
-
-#define SGLIB___BIN_TREE_FIND_MEMBER(type, tree, elem, left, right, comparator, res) {\
- type *_s_;\
- int _c_;\
- _s_ = (tree);\
- while (_s_!=NULL) {\
- _c_ = comparator((elem), _s_);\
- if (_c_ < 0) _s_ = _s_->left;\
- else if (_c_ > 0) _s_ = _s_->right;\
- else break;\
- }\
- (res) = _s_;\
-}
-
-/* ---------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------- */
-/* - LEVEL - 1 INTERFACE - */
-/* ---------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------- */
-
-
-
-/* ---------------------------------------------------------------------------- */
-/* ------------------------------ STATIC ARRAYS ------------------------------- */
-/* ---------------------------------------------------------------------------- */
-
-/* ----------------------------- array sorting (level 1) ---------------------- */
-
-#define SGLIB_DEFINE_ARRAY_SORTING_PROTOTYPES(type, comparator) \
- extern void sglib_##type##_array_quick_sort(type *a, int max);\
- extern void sglib_##type##_array_heap_sort(type *a, int max);\
-
-
-#define SGLIB_DEFINE_ARRAY_SORTING_FUNCTIONS(type, comparator) \
- void sglib_##type##_array_quick_sort(type *a, int max) {\
- SGLIB_ARRAY_SINGLE_QUICK_SORT(type, a, max, comparator);\
- }\
- void sglib_##type##_array_heap_sort(type *a, int max) {\
- SGLIB_ARRAY_SINGLE_HEAP_SORT(type, a, max, comparator);\
- }\
-
-
-/* ----------------------------- array queue (level 1) ------------------- */
-/* sglib's queue is stored in a fixed sized array */
-/* queue_type MUST be a structure containing fields: */
-/* afield is the array storing elem_type */
-/* ifield is the index of the first element in the queue */
-/* jfield is the index of the first free element after the queue */
-/* dim is the size of the array afield */
-/* !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! */
-
-
-#define SGLIB_DEFINE_QUEUE_PROTOTYPES(queue_type, elem_type, afield, ifield, jfield, dim) \
- extern void sglib_##queue_type##_init(queue_type *q); \
- extern int sglib_##queue_type##_is_empty(queue_type *q); \
- extern int sglib_##queue_type##_is_full(queue_type *q); \
- extern elem_type sglib_##queue_type##_first_element(queue_type *q); \
- extern elem_type *sglib_##queue_type##_first_element_ptr(queue_type *q); \
- extern void sglib_##queue_type##_add_next(queue_type *q); \
- extern void sglib_##queue_type##_add(queue_type *q, elem_type elem); \
- extern void sglib_##queue_type##_delete_first(queue_type *q); \
- extern void sglib_##queue_type##_delete(queue_type *q);
-
-
-#define SGLIB_DEFINE_QUEUE_FUNCTIONS(queue_type, elem_type, afield, ifield, jfield, dim) \
- void sglib_##queue_type##_init(queue_type *q) {\
- SGLIB_QUEUE_INIT(elem_type, q->afield, q->ifield, q->jfield);\
- }\
- int sglib_##queue_type##_is_empty(queue_type *q) {\
- return(SGLIB_QUEUE_IS_EMPTY(elem_type, q->afield, q->ifield, q->jfield));\
- }\
- int sglib_##queue_type##_is_full(queue_type *q) {\
- return(SGLIB_QUEUE_IS_FULL(elem_type, q->afield, q->ifield, q->jfield));\
- }\
- elem_type sglib_##queue_type##_first_element(queue_type *q) {\
- return(SGLIB_QUEUE_FIRST_ELEMENT(elem_type, q->afield, q->ifield, q->jfield));\
- }\
- elem_type *sglib_##queue_type##_first_element_ptr(queue_type *q) {\
- return(& SGLIB_QUEUE_FIRST_ELEMENT(elem_type, q->afield, q->ifield, q->jfield));\
- }\
- void sglib_##queue_type##_add_next(queue_type *q) {\
- SGLIB_QUEUE_ADD_NEXT(elem_type, q->afield, q->ifield, q->jfield, dim);\
- }\
- void sglib_##queue_type##_add(queue_type *q, elem_type elem) {\
- SGLIB_QUEUE_ADD(elem_type, q->afield, elem, q->ifield, q->jfield, dim);\
- }\
- void sglib_##queue_type##_delete_first(queue_type *q) {\
- SGLIB_QUEUE_DELETE_FIRST(elem_type, q->afield, q->ifield, q->jfield, dim);\
- }\
- void sglib_##queue_type##_delete(queue_type *q) {\
- SGLIB_QUEUE_DELETE_FIRST(elem_type, q->afield, q->ifield, q->jfield, dim);\
- }
-
-
-/* ------------------------ array heap (level 1) ------------------------- */
-/* sglib's heap is a priority queue implemented in a fixed sized array */
-/* heap_type MUST be a structure containing fields: */
-/* afield is the array of size dim storing elem_type */
-/* ifield is the index of the first free element after the queue */
-/* !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! */
-
-
-#define SGLIB_DEFINE_HEAP_PROTOTYPES(heap_type, elem_type, afield, ifield, dim, comparator, elem_exchanger) \
- extern void sglib_##heap_type##_init(heap_type *q); \
- extern int sglib_##heap_type##_is_empty(heap_type *q); \
- extern int sglib_##heap_type##_is_full(heap_type *q); \
- extern elem_type sglib_##heap_type##_first_element(heap_type *q); \
- extern elem_type *sglib_##heap_type##_first_element_ptr(heap_type *q); \
- extern void sglib_##heap_type##_add_next(heap_type *q); \
- extern void sglib_##heap_type##_add(heap_type *q, elem_type elem); \
- extern void sglib_##heap_type##_delete_first(heap_type *q); \
- extern void sglib_##heap_type##_delete(heap_type *q)
-
-#define SGLIB_DEFINE_HEAP_FUNCTIONS(heap_type, elem_type, afield, ifield, dim, comparator, elem_exchanger) \
- void sglib_##heap_type##_init(heap_type *q) {\
- SGLIB_HEAP_INIT(elem_type, q->afield, q->ifield);\
- }\
- int sglib_##heap_type##_is_empty(heap_type *q) {\
- return(SGLIB_HEAP_IS_EMPTY(elem_type, q->afield, q->ifield));\
- }\
- int sglib_##heap_type##_is_full(heap_type *q) {\
- return(SGLIB_HEAP_IS_FULL(elem_type, q->afield, q->ifield));\
- }\
- elem_type sglib_##heap_type##_first_element(heap_type *q) {\
- return(SGLIB_HEAP_FIRST_ELEMENT(elem_type, q->afield, q->ifield));\
- }\
- elem_type *sglib_##heap_type##_first_element_ptr(heap_type *q) {\
- return(& SGLIB_HEAP_FIRST_ELEMENT(elem_type, q->afield, q->ifield));\
- }\
- void sglib_##heap_type##_add_next(heap_type *q) {\
- SGLIB_HEAP_ADD_NEXT(elem_type, q->afield, q->ifield, dim, comparator, elem_exchanger);\
- }\
- void sglib_##heap_type##_add(heap_type *q, elem_type elem) {\
- SGLIB_HEAP_ADD(elem_type, q->afield, elem, q->ifield, dim, comparator, elem_exchanger);\
- }\
- void sglib_##heap_type##_delete_first(heap_type *q) {\
- SGLIB_HEAP_DELETE_FIRST(elem_type, q->afield, q->ifield, dim, comparator, elem_exchanger);\
- }\
- void sglib_##heap_type##_delete(heap_type *q) {\
- SGLIB_HEAP_DELETE_FIRST(elem_type, q->afield, q->ifield, dim, comparator, elem_exchanger);\
- }
-
-
-/* ------------------------ hashed table (level 1) ------------------------- */
-/*
-
- sglib's hash table is an array storing directly pointers to objects (not containers).
- In this table there is a one-to-one mapping between 'objects' stored
- in the table and indexes where they are placed. Each index is
- pointing to exactly one 'object' and each 'object' stored in the
- table occurs on exactly one index. Once an object is stored in the
- table, it can be represented via its index.
-
- type - is the type of elements
- dim - is the size of the hash array
- hash_function - is a hashing function mapping type* to unsigned
- comparator - is a comparator on elements
-
- !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!!
-*/
-
-#define SGLIB_DEFINE_HASHED_TABLE_PROTOTYPES(type, dim, hash_function, comparator) \
- struct sglib_hashed_##type##_iterator {\
- int currentIndex;\
- int (*subcomparator)(type *, type *);\
- type *equalto;\
- };\
- extern void sglib_hashed_##type##_init(type *table[dim]);\
- extern int sglib_hashed_##type##_add_if_not_member(type *table[dim], type *elem, type **member);\
- extern int sglib_hashed_##type##_is_member(type *table[dim], type *elem);\
- extern type * sglib_hashed_##type##_find_member(type *table[dim], type *elem);\
- extern type *sglib_hashed_##type##_it_init(struct sglib_hashed_##type##_iterator *it, type *table[dim]); \
- extern type *sglib_hashed_##type##_it_init_on_equal(struct sglib_hashed_##type##_iterator *it, type *table[dim], int (*subcomparator)(type *, type *), type *equalto); \
- extern type *sglib_hashed_##type##_it_current(struct sglib_hashed_##type##_iterator *it); \
- extern type *sglib_hashed_##type##_it_next(struct sglib_hashed_##type##_iterator *it);
-
-#define SGLIB_DEFINE_HASHED_TABLE_FUNCTIONS(type, dim, hash_function, comparator) \
- struct sglib_hashed_##type##_iterator {\
- int currentIndex;\
- type **table;\
- int (*subcomparator)(type *, type *);\
- type *equalto;\
- };\
- void sglib_hashed_##type##_init(type *table[dim]) {\
- SGLIB_HASH_TAB_INIT(type, table, dim);\
- }\
- int sglib_hashed_##type##_add_if_not_member(type *table[dim], type *elem, type **member) {\
- SGLIB_HASH_TAB_ADD_IF_NOT_MEMBER(type, table, dim, elem, hash_function, comparator, *member);\
- }\
- int sglib_hashed_##type##_is_member(type *table[dim], type *elem) {\
- int ind;\
- SGLIB_HASH_TAB_IS_MEMBER(type, table, dim, elem, hash_function, ind);\
- return(ind != -1);\
- }\
- type * sglib_hashed_##type##_find_member(type *table[dim], type *elem) {\
- type *mmb;\
- int ind;\
- SGLIB_HASH_TAB_FIND_MEMBER(type, table, dim, elem, hash_function, comparator, ind, mmb);\
- return(mmb);\
- }\
- type *sglib_hashed_##type##_it_init_on_equal(struct sglib_hashed_##type##_iterator *it, type *table[dim], int (*subcomparator)(type *, type *), type *equalto) {\
- int i;\
- it->table = table;\
- it->subcomparator = subcomparator;\
- it->equalto = equalto;\
- for(i=0; i<(dim) && table[i]==NULL; i++) ;\
- it->currentIndex = i;\
- if (i<(dim)) return(table[i]);\
- return(NULL);\
- }\
- type *sglib_hashed_##type##_it_init(struct sglib_hashed_##type##_iterator *it, type *table[dim]) {\
- sglib_hashed_##type##_it_init_on_equal(it, table, NULL, NULL);\
- }\
- type *sglib_hashed_##type##_it_current(struct sglib_hashed_##type##_iterator *it) {\
- return(table[it->currentIndex]);\
- }\
- type *sglib_hashed_##type##_it_next(struct sglib_hashed_##type##_iterator *it) {\
- i=it->currentIndex;\
- if (i<(dim)) {\
- for(i++; i<(dim) && table[i]==NULL; i++) ;\
- }\
- it->currentIndex = i;\
- if (i<(dim)) return(table[i]);\
- return(NULL);\
- }
-
-
-/* ------------------- hashed container (only for level 1) -------------------- */
-/*
- hashed container is a table of given fixed size containing another
- (dynamic) base container in each cell. Once an object should be
- inserted into the hashed container, a hash function is used to
- determine the cell where the object belongs and the object is
- inserted into the base container stored in this cell. Usually the
- base container is simply a list or a sorted list, but it can be a
- red-black tree as well.
-
- parameters:
- type - the type of the container stored in each cell.
- dim - the size of the hashed array
- hash_function - the hashing function hashing 'type *' to unsigned.
-
-*/
-
-#define SGLIB_DEFINE_HASHED_CONTAINER_PROTOTYPES(type, dim, hash_function) \
- struct sglib_hashed_##type##_iterator {\
- struct sglib_##type##_iterator containerIt;\
- type **table;\
- int currentIndex;\
- int (*subcomparator)(type *, type *);\
- type *equalto;\
- };\
- extern void sglib_hashed_##type##_init(type *table[dim]);\
- extern void sglib_hashed_##type##_add(type *table[dim], type *elem);\
- extern int sglib_hashed_##type##_add_if_not_member(type *table[dim], type *elem, type **member);\
- extern void sglib_hashed_##type##_delete(type *table[dim], type *elem);\
- extern int sglib_hashed_##type##_delete_if_member(type *table[dim], type *elem, type **memb);\
- extern int sglib_hashed_##type##_is_member(type *table[dim], type *elem);\
- extern type * sglib_hashed_##type##_find_member(type *table[dim], type *elem);\
- extern type *sglib_hashed_##type##_it_init(struct sglib_hashed_##type##_iterator *it, type *table[dim]); \
- extern type *sglib_hashed_##type##_it_init_on_equal(struct sglib_hashed_##type##_iterator *it, type *table[dim], int (*subcomparator)(type *, type *), type *equalto); \
- extern type *sglib_hashed_##type##_it_current(struct sglib_hashed_##type##_iterator *it); \
- extern type *sglib_hashed_##type##_it_next(struct sglib_hashed_##type##_iterator *it);
-
-#define SGLIB_DEFINE_HASHED_CONTAINER_FUNCTIONS(type, dim, hash_function) \
- /*extern unsigned hash_function(type *elem);*/\
- void sglib_hashed_##type##_init(type *table[dim]) {\
- unsigned i;\
- for(i=0; i<(dim); i++) table[i] = NULL;\
- }\
- void sglib_hashed_##type##_add(type *table[dim], type *elem) {\
- unsigned i;\
- i = ((unsigned)hash_function(elem)) % (dim);\
- sglib_##type##_add(&(table)[i], elem);\
- }\
- int sglib_hashed_##type##_add_if_not_member(type *table[dim], type *elem, type **member) {\
- unsigned i;\
- i = ((unsigned)hash_function(elem)) % (dim);\
- return(sglib_##type##_add_if_not_member(&(table)[i], elem, member));\
- }\
- void sglib_hashed_##type##_delete(type *table[dim], type *elem) {\
- unsigned i;\
- i = ((unsigned)hash_function(elem)) % (dim);\
- sglib_##type##_delete(&(table)[i], elem);\
- }\
- int sglib_hashed_##type##_delete_if_member(type *table[dim], type *elem, type **memb) {\
- unsigned i;\
- i = ((unsigned)hash_function(elem)) % (dim);\
- return(sglib_##type##_delete_if_member(&(table)[i], elem, memb));\
- }\
- int sglib_hashed_##type##_is_member(type *table[dim], type *elem) {\
- unsigned i;\
- i = ((unsigned)hash_function(elem)) % (dim);\
- return(sglib_##type##_is_member((table)[i], elem));\
- }\
- type * sglib_hashed_##type##_find_member(type *table[dim], type *elem) {\
- unsigned i;\
- i = ((unsigned)hash_function(elem)) % (dim);\
- return(sglib_##type##_find_member((table)[i], elem));\
- }\
- type *sglib_hashed_##type##_it_init_on_equal(struct sglib_hashed_##type##_iterator *it, type *table[dim], int (*subcomparator)(type *, type *), type *equalto) {\
- type *e;\
- it->table = table;\
- it->currentIndex = 0;\
- it->subcomparator = subcomparator;\
- it->equalto = equalto;\
- e = sglib_##type##_it_init_on_equal(&it->containerIt, table[it->currentIndex], it->subcomparator, it->equalto);\
- if (e==NULL) e = sglib_hashed_##type##_it_next(it);\
- return(e);\
- }\
- type *sglib_hashed_##type##_it_init(struct sglib_hashed_##type##_iterator *it, type *table[dim]) {\
- return(sglib_hashed_##type##_it_init_on_equal(it, table, NULL, NULL));\
- }\
- type *sglib_hashed_##type##_it_current(struct sglib_hashed_##type##_iterator *it) {\
- return(sglib_##type##_it_current(&it->containerIt));\
- }\
- type *sglib_hashed_##type##_it_next(struct sglib_hashed_##type##_iterator *it) {\
- type *e;\
- e = sglib_##type##_it_next(&it->containerIt);\
- while (e==NULL && (++(it->currentIndex))<(dim)) {\
- e = sglib_##type##_it_init_on_equal(&it->containerIt, it->table[it->currentIndex], it->subcomparator, it->equalto);\
- }\
- return(e);\
- }
-
-
-
-/* ---------------------------------------------------------------------------- */
-/* ------------------------- DYNAMIC DATA STRUCTURES -------------------------- */
-/* ---------------------------------------------------------------------------- */
-
-
-
-/* ------------------------------------ list (level 1) -------------------------------- */
-
-#define SGLIB_DEFINE_LIST_PROTOTYPES(type, comparator, next) \
- struct sglib_##type##_iterator {\
- type *currentelem;\
- type *nextelem;\
- int (*subcomparator)(type *, type *);\
- type *equalto;\
- };\
- extern void sglib_##type##_add(type **list, type *elem);\
- extern int sglib_##type##_add_if_not_member(type **list, type *elem, type **member);\
- extern void sglib_##type##_concat(type **first, type *second);\
- extern void sglib_##type##_delete(type **list, type *elem);\
- extern int sglib_##type##_delete_if_member(type **list, type *elem, type **member);\
- extern int sglib_##type##_is_member(type *list, type *elem);\
- extern type *sglib_##type##_find_member(type *list, type *elem);\
- extern void sglib_##type##_sort(type **list);\
- extern int sglib_##type##_len(type *list);\
- extern void sglib_##type##_reverse(type **list);\
- extern type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list); \
- extern type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto); \
- extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \
- extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it);
-
-
-#define SGLIB_DEFINE_LIST_FUNCTIONS(type, comparator, next) \
- int sglib_##type##_is_member(type *list, type *elem) {\
- int result;\
- SGLIB_LIST_IS_MEMBER(type, list, elem, next, result);\
- return(result);\
- }\
- type *sglib_##type##_find_member(type *list, type *elem) {\
- type *result;\
- SGLIB_LIST_FIND_MEMBER(type, list, elem, comparator, next, result);\
- return(result);\
- }\
- int sglib_##type##_add_if_not_member(type **list, type *elem, type **member) {\
- SGLIB_LIST_ADD_IF_NOT_MEMBER(type, *list, elem, comparator, next, *member);\
- return(*member==NULL);\
- }\
- void sglib_##type##_add(type **list, type *elem) {\
- SGLIB_LIST_ADD(type, *list, elem, next);\
- }\
- void sglib_##type##_concat(type **first, type *second) {\
- SGLIB_LIST_CONCAT(type, *first, second, next);\
- }\
- void sglib_##type##_delete(type **list, type *elem) {\
- SGLIB_LIST_DELETE(type, *list, elem, next);\
- }\
- int sglib_##type##_delete_if_member(type **list, type *elem, type **member) {\
- SGLIB_LIST_DELETE_IF_MEMBER(type, *list, elem, comparator, next, *member);\
- return(*member!=NULL);\
- }\
- void sglib_##type##_sort(type **list) { \
- SGLIB_LIST_SORT(type, *list, comparator, next);\
- }\
- int sglib_##type##_len(type *list) {\
- int res;\
- SGLIB_LIST_LEN(type, list, next, res);\
- return(res);\
- }\
- void sglib_##type##_reverse(type **list) {\
- SGLIB_LIST_REVERSE(type, *list, next);\
- }\
- \
- type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto) {\
- it->subcomparator = subcomparator;\
- it->equalto = equalto;\
- it->nextelem = list;\
- return(sglib_##type##_it_next(it));\
- }\
- type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list) {\
- return(sglib_##type##_it_init_on_equal(it, list, NULL, NULL));\
- }\
- type *sglib_##type##_it_current(struct sglib_##type##_iterator *it) {\
- return(it->currentelem);\
- }\
- type *sglib_##type##_it_next(struct sglib_##type##_iterator *it) {\
- type *ce, *eq;\
- int (*scp)(type *, type *);\
- ce = it->nextelem;\
- it->nextelem = NULL;\
- if (it->subcomparator != NULL) {\
- eq = it->equalto; \
- scp = it->subcomparator;\
- while (ce!=NULL && scp(ce, eq)!=0) ce = ce->next;\
- }\
- it->currentelem = ce;\
- if (ce != NULL) it->nextelem = ce->next;\
- return(ce);\
- }
-
-/* ----------------------------- sorted list (level 1) ----------------------------------- */
-
-
-#define SGLIB_DEFINE_SORTED_LIST_PROTOTYPES(type, comparator, next) \
- struct sglib_##type##_iterator {\
- type *currentelem;\
- type *nextelem;\
- int (*subcomparator)(type *, type *);\
- type *equalto;\
- };\
- extern void sglib_##type##_add(type **list, type *elem);\
- extern int sglib_##type##_add_if_not_member(type **list, type *elem, type **member);\
- extern void sglib_##type##_delete(type **list, type *elem);\
- extern int sglib_##type##_delete_if_member(type **list, type *elem, type **member);\
- extern int sglib_##type##_is_member(type *list, type *elem);\
- extern type *sglib_##type##_find_member(type *list, type *elem);\
- extern int sglib_##type##_len(type *list);\
- extern void sglib_##type##_sort(type **list);\
- extern type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list); \
- extern type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto); \
- extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \
- extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it);
-
-
-#define SGLIB_DEFINE_SORTED_LIST_FUNCTIONS(type, comparator, next) \
- int sglib_##type##_is_member(type *list, type *elem) {\
- int result;\
- SGLIB_SORTED_LIST_IS_MEMBER(type, list, elem, comparator, next, result);\
- return(result);\
- }\
- type *sglib_##type##_find_member(type *list, type *elem) {\
- type *result;\
- SGLIB_SORTED_LIST_FIND_MEMBER(type, list, elem, comparator, next, result);\
- return(result);\
- }\
- int sglib_##type##_add_if_not_member(type **list, type *elem, type **member) {\
- SGLIB_SORTED_LIST_ADD_IF_NOT_MEMBER(type, *list, elem, comparator, next, *member);\
- return(*member==NULL);\
- }\
- void sglib_##type##_add(type **list, type *elem) {\
- SGLIB_SORTED_LIST_ADD(type, *list, elem, comparator, next);\
- }\
- void sglib_##type##_delete(type **list, type *elem) {\
- SGLIB_SORTED_LIST_DELETE(type, *list, elem, next);\
- }\
- int sglib_##type##_delete_if_member(type **list, type *elem, type **member) {\
- SGLIB_SORTED_LIST_DELETE_IF_MEMBER(type, *list, elem, comparator, next, *member);\
- return(*member!=NULL);\
- }\
- int sglib_##type##_len(type *list) {\
- int res;\
- SGLIB_SORTED_LIST_LEN(type, list, next, res);\
- return(res);\
- }\
- void sglib_##type##_sort(type **list) { \
- SGLIB_LIST_SORT(type, *list, comparator, next);\
- }\
- \
- type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto) {\
- it->subcomparator = subcomparator;\
- it->equalto = equalto;\
- it->nextelem = list;\
- return(sglib_##type##_it_next(it));\
- }\
- type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list) {\
- return(sglib_##type##_it_init_on_equal(it, list, NULL, NULL));\
- }\
- type *sglib_##type##_it_current(struct sglib_##type##_iterator *it) {\
- return(it->currentelem);\
- }\
- type *sglib_##type##_it_next(struct sglib_##type##_iterator *it) {\
- type *ce, *eq;\
- int (*scp)(type *, type *);\
- int c;\
- ce = it->nextelem;\
- it->nextelem = NULL;\
- if (it->subcomparator != NULL) {\
- eq = it->equalto; \
- scp = it->subcomparator;\
- while (ce!=NULL && (c=scp(ce, eq)) < 0) ce = ce->next;\
- if (ce != NULL && c > 0) ce = NULL;\
- }\
- it->currentelem = ce;\
- if (ce != NULL) it->nextelem = ce->next;\
- return(ce);\
- }
-
-
-/* ----------------------------- double linked list (level 1) ------------------------------ */
-
-
-#define SGLIB_DEFINE_DL_LIST_PROTOTYPES(type, comparator, previous, next) \
- struct sglib_##type##_iterator {\
- type *currentelem;\
- type *prevelem;\
- type *nextelem;\
- int (*subcomparator)(type *, type *);\
- type *equalto;\
- };\
- extern void sglib_##type##_add(type **list, type *elem);\
- extern void sglib_##type##_add_before(type **list, type *elem);\
- extern void sglib_##type##_add_after(type **list, type *elem);\
- extern int sglib_##type##_add_if_not_member(type **list, type *elem, type **member);\
- extern int sglib_##type##_add_before_if_not_member(type **list, type *elem, type **member);\
- extern int sglib_##type##_add_after_if_not_member(type **list, type *elem, type **member);\
- extern void sglib_##type##_concat(type **first, type *second);\
- extern void sglib_##type##_delete(type **list, type *elem);\
- extern int sglib_##type##_delete_if_member(type **list, type *elem, type **member);\
- extern int sglib_##type##_is_member(type *list, type *elem);\
- extern type *sglib_##type##_find_member(type *list, type *elem);\
- extern type *sglib_##type##_get_first(type *list);\
- extern type *sglib_##type##_get_last(type *list);\
- extern void sglib_##type##_sort(type **list);\
- extern int sglib_##type##_len(type *list);\
- extern void sglib_##type##_reverse(type **list);\
- extern type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list); \
- extern type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto); \
- extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \
- extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it);
-
-
-#define SGLIB_DEFINE_DL_LIST_FUNCTIONS(type, comparator, previous, next) \
- void sglib_##type##_add(type **list, type *elem) {\
- SGLIB_DL_LIST_ADD(type, *list, elem, previous, next);\
- }\
- void sglib_##type##_add_after(type **list, type *elem) {\
- SGLIB_DL_LIST_ADD_AFTER(type, *list, elem, previous, next);\
- }\
- void sglib_##type##_add_before(type **list, type *elem) {\
- SGLIB_DL_LIST_ADD_BEFORE(type, *list, elem, previous, next);\
- }\
- int sglib_##type##_add_if_not_member(type **list, type *elem, type **member) {\
- SGLIB_DL_LIST_ADD_IF_NOT_MEMBER(type, *list, elem, comparator, previous, next, *member);\
- return(*member==NULL);\
- }\
- int sglib_##type##_add_after_if_not_member(type **list, type *elem, type **member) {\
- SGLIB_DL_LIST_ADD_AFTER_IF_NOT_MEMBER(type, *list, elem, comparator, previous, next, *member);\
- return(*member==NULL);\
- }\
- int sglib_##type##_add_before_if_not_member(type **list, type *elem, type **member) {\
- SGLIB_DL_LIST_ADD_BEFORE_IF_NOT_MEMBER(type, *list, elem, comparator, previous, next, *member);\
- return(*member==NULL);\
- }\
- void sglib_##type##_concat(type **first, type *second) {\
- SGLIB_DL_LIST_CONCAT(type, *first, second, previous, next);\
- }\
- void sglib_##type##_delete(type **list, type *elem) {\
- SGLIB_DL_LIST_DELETE(type, *list, elem, previous, next);\
- }\
- int sglib_##type##_delete_if_member(type **list, type *elem, type **member) {\
- SGLIB_DL_LIST_DELETE_IF_MEMBER(type, *list, elem, comparator, previous, next, *member);\
- return(*member!=NULL);\
- }\
- int sglib_##type##_is_member(type *list, type *elem) {\
- int result;\
- SGLIB_DL_LIST_IS_MEMBER(type, list, elem, previous, next, result);\
- return(result);\
- }\
- type *sglib_##type##_find_member(type *list, type *elem) {\
- type *result;\
- SGLIB_DL_LIST_FIND_MEMBER(type, list, elem, comparator, previous, next, result);\
- return(result);\
- }\
- type *sglib_##type##_get_first(type *list) {\
- type *result;\
- SGLIB_DL_LIST_GET_FIRST(type, list, previous, next, result);\
- return(result);\
- }\
- type *sglib_##type##_get_last(type *list) {\
- type *result;\
- SGLIB_DL_LIST_GET_LAST(type, list, previous, next, result);\
- return(result);\
- }\
- void sglib_##type##_sort(type **list) {\
- SGLIB_DL_LIST_SORT(type, *list, comparator, previous, next);\
- }\
- int sglib_##type##_len(type *list) {\
- int res;\
- SGLIB_DL_LIST_LEN(type, list, previous, next, res);\
- return(res);\
- }\
- void sglib_##type##_reverse(type **list) {\
- SGLIB_DL_LIST_REVERSE(type, *list, previous, next);\
- }\
- \
- type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto) {\
- it->subcomparator = subcomparator;\
- it->equalto = equalto;\
- it->prevelem = list;\
- it->nextelem = list;\
- if (list != NULL) it->nextelem = list->next;\
- return(sglib_##type##_it_next(it));\
- }\
- type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list) {\
- return(sglib_##type##_it_init_on_equal(it, list, NULL, NULL));\
- }\
- type *sglib_##type##_it_current(struct sglib_##type##_iterator *it) {\
- return(it->currentelem);\
- }\
- type *sglib_##type##_it_next(struct sglib_##type##_iterator *it) {\
- type *ce, *eq;\
- int (*scp)(type *, type *);\
- ce = it->prevelem;\
- it->prevelem = NULL;\
- if (it->subcomparator != NULL) {\
- eq = it->equalto; \
- scp = it->subcomparator;\
- while (ce!=NULL && scp(eq, ce)!=0) ce = ce->previous;\
- }\
- if (ce != NULL) {\
- it->prevelem = ce->previous;\
- } else {\
- ce = it->nextelem;\
- it->nextelem = NULL;\
- if (it->subcomparator != NULL) {\
- eq = it->equalto; \
- scp = it->subcomparator;\
- while (ce!=NULL && scp(ce, eq)!=0) ce = ce->next;\
- }\
- if (ce != NULL) it->nextelem = ce->next;\
- }\
- it->currentelem = ce;\
- return(ce);\
- }
-
-
-/* --------------------------------- red-black trees (level 1) -------------------------------- */
-
-/*
-
-This implementation requires pointers to left and right sons (no
-parent pointer is needed) and one bit of additional information
-storing the color of the node. The implementation follows discrepancy
-fixing rules from:
-http://www.cis.ohio-state.edu/~gurari/course/cis680/cis680Ch11.html
-
-*/
-
-#define SGLIB___RBTREE_FIX_INSERTION_DISCREPANCY(type, tree, leftt, rightt, bits, RED, BLACK) {\
- type *t, *tl, *a, *b, *c, *ar, *bl, *br, *cl, *cr;\
- t = *tree;\
- tl = t->leftt;\
- if (t->rightt!=NULL && SGLIB___GET_VALUE(t->rightt->bits)==RED) {\
- if (SGLIB___GET_VALUE(tl->bits)==RED) {\
- if ((tl->leftt!=NULL && SGLIB___GET_VALUE(tl->leftt->bits)==RED) \
- || (tl->rightt!=NULL && SGLIB___GET_VALUE(tl->rightt->bits)==RED)) {\
- SGLIB___SET_VALUE(t->leftt->bits,BLACK);\
- SGLIB___SET_VALUE(t->rightt->bits,BLACK);\
- SGLIB___SET_VALUE(t->bits,RED);\
- }\
- }\
- } else {\
- if (SGLIB___GET_VALUE(tl->bits)==RED) {\
- if (tl->leftt!=NULL && SGLIB___GET_VALUE(tl->leftt->bits)==RED) {\
- a = t; b = tl; c = tl->leftt;\
- br = b->rightt;\
- a->leftt = br;\
- b->leftt = c; b->rightt = a;\
- SGLIB___SET_VALUE(a->bits,RED);\
- SGLIB___SET_VALUE(b->bits,BLACK);\
- *tree = b;\
- } else if (tl->rightt!=NULL && SGLIB___GET_VALUE(tl->rightt->bits)==RED) {\
- a = t; b = tl; ar=a->rightt;\
- bl=b->leftt; c=b->rightt;\
- cl=c->leftt; cr=c->rightt;\
- b->rightt = cl;\
- a->leftt = cr;\
- c->leftt = b;\
- c->rightt = a;\
- SGLIB___SET_VALUE(c->bits,BLACK);\
- SGLIB___SET_VALUE(a->bits,RED);\
- *tree = c;\
- }\
- }\
- }\
-}
-
-#define SGLIB___RBTREE_FIX_DELETION_DISCREPANCY(type, tree, leftt, rightt, bits, RED, BLACK, res) {\
- type *t, *a, *b, *c, *d, *ar, *bl, *br, *cl, *cr, *dl, *dr;\
- t = a = *tree;\
- assert(t!=NULL);\
- ar = a->rightt;\
- b = t->leftt;\
- if (b==NULL) {\
- assert(SGLIB___GET_VALUE(t->bits)==RED);\
- SGLIB___SET_VALUE(t->bits,BLACK);\
- res = 0;\
- } else {\
- bl = b->leftt;\
- br = b->rightt;\
- if (SGLIB___GET_VALUE(b->bits)==RED) {\
- if (br==NULL) {\
- *tree = b;\
- SGLIB___SET_VALUE(b->bits,BLACK);\
- b->rightt = a;\
- a->leftt = br;\
- res = 0;\
- } else {\
- c = br;\
- assert(c!=NULL && SGLIB___GET_VALUE(c->bits)==BLACK);\
- cl = c->leftt;\
- cr = c->rightt;\
- if ((cl==NULL||SGLIB___GET_VALUE(cl->bits)==BLACK) && (cr==NULL||SGLIB___GET_VALUE(cr->bits)==BLACK)) {\
- *tree = b;\
- b->rightt = a;\
- SGLIB___SET_VALUE(b->bits,BLACK);\
- a->leftt = c;\
- SGLIB___SET_VALUE(c->bits,RED);\
- res = 0;\
- } else if (cl!=NULL && SGLIB___GET_VALUE(cl->bits)==RED) {\
- if (cr!=NULL && SGLIB___GET_VALUE(cr->bits)==RED) {\
- d = cr;\
- dl = d->leftt;\
- dr = d->rightt;\
- *tree = d;\
- SGLIB___SET_VALUE(d->bits,BLACK);\
- d->leftt = b;\
- c->rightt = dl;\
- d->rightt = a;\
- a->leftt = dr;\
- res = 0;\
- } else {\
- *tree = c;\
- c->leftt = b;\
- c->rightt = a;\
- b->leftt = bl;\
- b->rightt = cl;\
- a->leftt = cr;\
- SGLIB___SET_VALUE(cl->bits,BLACK);\
- res = 0;\
- }\
- } else if (cr!=NULL && SGLIB___GET_VALUE(cr->bits)==RED) {\
- assert(cl==NULL || SGLIB___GET_VALUE(cl->bits)==BLACK);\
- d = cr;\
- dl = d->leftt;\
- dr = d->rightt;\
- *tree = d;\
- SGLIB___SET_VALUE(d->bits,BLACK);\
- d->leftt = b;\
- c->rightt = dl;\
- d->rightt = a;\
- a->leftt = dr;\
- res = 0;\
- } else {\
- assert(0);\
- res = 0;\
- }\
- }\
- } else {\
- if ((bl==NULL || SGLIB___GET_VALUE(bl->bits)==BLACK) && (br==NULL || SGLIB___GET_VALUE(br->bits)==BLACK)) {\
- res = (SGLIB___GET_VALUE(a->bits)==BLACK);\
- SGLIB___SET_VALUE(a->bits,BLACK);\
- SGLIB___SET_VALUE(b->bits,RED);\
- } else if (bl!=NULL && SGLIB___GET_VALUE(bl->bits)==RED) {\
- if (br==NULL || SGLIB___GET_VALUE(br->bits)==BLACK) {\
- *tree = b;\
- SGLIB___SET_VALUE(b->bits,SGLIB___GET_VALUE(a->bits));\
- SGLIB___SET_VALUE(a->bits,BLACK);\
- b->rightt = a;\
- a->leftt = br;\
- SGLIB___SET_VALUE(bl->bits,BLACK);\
- res = 0;\
- } else {\
- assert(bl!=NULL);\
- assert(br!=NULL);\
- assert(SGLIB___GET_VALUE(bl->bits)==RED);\
- assert(SGLIB___GET_VALUE(br->bits)==RED);\
- c = br;\
- cl = c->leftt;\
- cr = c->rightt;\
- *tree = c;\
- SGLIB___SET_VALUE(c->bits,SGLIB___GET_VALUE(a->bits));\
- SGLIB___SET_VALUE(a->bits,BLACK);\
- c->leftt = b;\
- c->rightt = a;\
- b->rightt = cl;\
- a->leftt = cr;\
- res = 0;\
- }\
- } else {\
- assert(br!=NULL && SGLIB___GET_VALUE(br->bits)==RED);\
- c = br;\
- cl = c->leftt;\
- cr = c->rightt;\
- *tree = c;\
- SGLIB___SET_VALUE(c->bits,SGLIB___GET_VALUE(a->bits));\
- SGLIB___SET_VALUE(a->bits,BLACK);\
- c->leftt = b;\
- c->rightt = a;\
- b->rightt = cl;\
- a->leftt = cr;\
- res = 0;\
- }\
- }\
- }\
-}
-
-
-#define SGLIB_DEFINE_RBTREE_FUNCTIONS_GENERAL(type, left, right, bits, comparator, RED, BLACK) \
-static void sglib___##type##_fix_left_insertion_discrepancy(type **tree) {\
- SGLIB___RBTREE_FIX_INSERTION_DISCREPANCY(type, tree, left, right, bits, RED, BLACK);\
-}\
-\
-static void sglib___##type##_fix_right_insertion_discrepancy(type **tree) {\
- SGLIB___RBTREE_FIX_INSERTION_DISCREPANCY(type, tree, right, left, bits, RED, BLACK);\
-}\
-\
-static int sglib___##type##_fix_left_deletion_discrepancy(type **tree) {\
- int res;\
- SGLIB___RBTREE_FIX_DELETION_DISCREPANCY(type, tree, right, left, bits, RED, BLACK, res);\
- return(res);\
-}\
-\
-static int sglib___##type##_fix_right_deletion_discrepancy(type **tree) {\
- int res;\
- SGLIB___RBTREE_FIX_DELETION_DISCREPANCY(type, tree, left, right, bits, RED, BLACK, res);\
- return(res);\
-}\
-\
-static void sglib___##type##_add_recursive(type **tree, type *elem) {\
- int cmp;\
- type *t;\
- t = *tree;\
- if (t == NULL) {\
- SGLIB___SET_VALUE(elem->bits,RED);\
- *tree =elem;\
- } else {\
- cmp = comparator(elem, t);\
- if (cmp < 0 || (cmp==0 && elem<t)) {\
- sglib___##type##_add_recursive(&t->left, elem);\
- if (SGLIB___GET_VALUE(t->bits)==BLACK) sglib___##type##_fix_left_insertion_discrepancy(tree);\
- } else {\
- sglib___##type##_add_recursive(&t->right, elem);\
- if (SGLIB___GET_VALUE(t->bits)==BLACK) sglib___##type##_fix_right_insertion_discrepancy(tree);\
- }\
- }\
-}\
-\
-static int sglib___##type##_delete_rightmost_leaf(type **tree, type **theLeaf) {\
- type *t;\
- int res, deepDecreased;\
- t = *tree;\
- res = 0;\
- assert(t!=NULL);\
- if (t->right == NULL) {\
- *theLeaf = t;\
- if (t->left!=NULL) {\
- if (SGLIB___GET_VALUE(t->bits)==BLACK && SGLIB___GET_VALUE(t->left->bits)==BLACK) res = 1;\
- SGLIB___SET_VALUE(t->left->bits,BLACK);\
- *tree = t->left;\
- } else {\
- *tree = NULL;\
- res = (SGLIB___GET_VALUE(t->bits)==BLACK);\
- }\
- } else {\
- deepDecreased = sglib___##type##_delete_rightmost_leaf(&t->right, theLeaf);\
- if (deepDecreased) res = sglib___##type##_fix_right_deletion_discrepancy(tree);\
- }\
- return(res);\
-}\
-\
-int sglib___##type##_delete_recursive(type **tree, type *elem) {\
- type *t, *theLeaf;\
- int cmp, res, deepDecreased;\
- t = *tree;\
- res = 0;\
- if (t==NULL) {\
- assert(0 && "The element to delete not found in the tree, use 'delete_if_member'"!=NULL);\
- } else {\
- cmp = comparator(elem, t);\
- if (cmp < 0 || (cmp==0 && elem<t)) {\
- deepDecreased = sglib___##type##_delete_recursive(&t->left, elem);\
- if (deepDecreased) {\
- res = sglib___##type##_fix_left_deletion_discrepancy(tree);\
- }\
- } else if (cmp > 0 || (cmp==0 && elem>t)) {\
- deepDecreased = sglib___##type##_delete_recursive(&t->right, elem);\
- if (deepDecreased) {\
- res = sglib___##type##_fix_right_deletion_discrepancy(tree);\
- }\
- } else {\
- assert(elem==t && "Deleting an element which is non member of the tree, use 'delete_if_member'"!=NULL);\
- if (t->left == NULL) {\
- if (t->right == NULL) {\
- /* a leaf, delete, it; */\
- *tree = NULL;\
- res = (SGLIB___GET_VALUE(t->bits)==BLACK);\
- } else {\
- if (SGLIB___GET_VALUE(t->bits)==0 && SGLIB___GET_VALUE(t->right->bits)==0) res = 1;\
- SGLIB___SET_VALUE(t->right->bits,BLACK);\
- *tree = t->right;\
- }\
- } else {\
- /* propagate deletion until righmost leaf of left subtree */\
- deepDecreased = sglib___##type##_delete_rightmost_leaf(&t->left, &theLeaf);\
- theLeaf->left = t->left;\
- theLeaf->right = t->right;\
- SGLIB___SET_VALUE(theLeaf->bits,SGLIB___GET_VALUE(t->bits));\
- *tree = theLeaf;\
- if (deepDecreased) res = sglib___##type##_fix_left_deletion_discrepancy(tree);\
- }\
- }\
- }\
- return(res);\
-}\
-\
-void sglib_##type##_add(type **tree, type *elem) {\
- elem->left = elem->right = NULL;\
- sglib___##type##_add_recursive(tree, elem);\
- SGLIB___SET_VALUE((*tree)->bits,BLACK);\
-}\
-\
-void sglib_##type##_delete(type **tree, type *elem) {\
- sglib___##type##_delete_recursive(tree, elem);\
- if (*tree!=NULL) SGLIB___SET_VALUE((*tree)->bits,BLACK);\
-}\
-\
-type *sglib_##type##_find_member(type *t, type *elem) {\
- type *res;\
- SGLIB___BIN_TREE_FIND_MEMBER(type, t, elem, left, right, comparator, res);\
- return(res);\
-}\
-\
-int sglib_##type##_is_member(type *t, type *elem) {\
- int cmp;\
- while (t!=NULL) {\
- cmp = comparator(elem, t);\
- if (cmp < 0 || (cmp==0 && elem<t)) {\
- t = t->left;\
- } else if (cmp > 0 || (cmp==0 && elem>t)) {\
- t = t->right;\
- } else {\
- assert(t == elem);\
- return(1);\
- }\
- }\
- return(0);\
-}\
-\
-int sglib_##type##_delete_if_member(type **tree, type *elem, type **memb) {\
- if ((*memb=sglib_##type##_find_member(*tree, elem))!=NULL) {\
- sglib_##type##_delete(tree, *memb);\
- return(1);\
- } else {\
- return(0);\
- }\
-}\
-int sglib_##type##_add_if_not_member(type **tree, type *elem, type **memb) {\
- if ((*memb=sglib_##type##_find_member(*tree, elem))==NULL) {\
- sglib_##type##_add(tree, elem);\
- return(1);\
- } else {\
- return(0);\
- }\
-}\
-int sglib_##type##_len(type *t) {\
- int n;\
- type *e;\
- n = 0;\
- SGLIB_BIN_TREE_MAP_ON_ELEMENTS(type, t, e, left, right, n++);\
- return(n);\
-}\
-\
-void sglib__##type##_it_compute_current_elem(struct sglib_##type##_iterator *it) {\
- int i,j,cmp;\
- type *s, *eqt;\
- int (*subcomparator)(type *, type *);\
- eqt = it->equalto;\
- subcomparator = it->subcomparator;\
- it->currentelem = NULL;\
- while(it->pathi > 0 && it->currentelem==NULL) {\
- i = it->pathi-1;\
- if (i >= 0) {\
- if (it->pass[i] >= 2) {\
- /* goto up */\
- it->pathi --;\
- } else {\
- if (it->pass[i] == 0) {\
- /* goto left */\
- s = it->path[i]->left;\
- } else {\
- /* goto right */\
- s = it->path[i]->right;\
- }\
- if (eqt != NULL) {\
- if (subcomparator == NULL) {\
- SGLIB___BIN_TREE_FIND_MEMBER(type, s, eqt, left, right, comparator, s);\
- } else {\
- SGLIB___BIN_TREE_FIND_MEMBER(type, s, eqt, left, right, subcomparator, s);\
- }\
- }\
- if (s != NULL) {\
- j = i+1;\
- it->path[j] = s;\
- it->pass[j] = 0;\
- it->pathi ++;\
- }\
- it->pass[i] ++;\
- }\
- }\
- if (it->pathi>0 && it->order == it->pass[it->pathi-1]) {\
- it->currentelem = it->path[it->pathi-1];\
- }\
- }\
-}\
-type *sglib__##type##_it_init(struct sglib_##type##_iterator *it, type *tree, int order, int (*subcomparator)(type *, type *), type *equalto) {\
- type *t;\
- assert(it!=NULL);\
- it->order = order;\
- it->equalto = equalto;\
- it->subcomparator = subcomparator;\
- if (equalto == NULL) { \
- t = tree;\
- } else {\
- if (subcomparator == NULL) {\
- SGLIB___BIN_TREE_FIND_MEMBER(type, tree, equalto, left, right, comparator, t);\
- } else {\
- SGLIB___BIN_TREE_FIND_MEMBER(type, tree, equalto, left, right, subcomparator, t);\
- }\
- }\
- if (t == NULL) {\
- it->pathi = 0;\
- it->currentelem = NULL;\
- } else {\
- it->pathi = 1;\
- it->pass[0] = 0;\
- it->path[0] = t;\
- if (order == 0) {\
- it->currentelem = t;\
- } else {\
- sglib__##type##_it_compute_current_elem(it);\
- }\
- }\
- return(it->currentelem);\
-}\
-type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *tree) {\
- return(sglib__##type##_it_init(it, tree, 2, NULL, NULL));\
-}\
-type *sglib_##type##_it_init_preorder(struct sglib_##type##_iterator *it, type *tree) {\
- return(sglib__##type##_it_init(it, tree, 0, NULL, NULL));\
-}\
-type *sglib_##type##_it_init_inorder(struct sglib_##type##_iterator *it, type *tree) {\
- return(sglib__##type##_it_init(it, tree, 1, NULL, NULL));\
-}\
-type *sglib_##type##_it_init_postorder(struct sglib_##type##_iterator *it, type *tree) {\
- return(sglib__##type##_it_init(it, tree, 2, NULL, NULL));\
-}\
-type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *tree, int (*subcomparator)(type *, type *), type *equalto) {\
- return(sglib__##type##_it_init(it, tree, 1, subcomparator, equalto));\
-}\
-type *sglib_##type##_it_current(struct sglib_##type##_iterator *it) {\
- return(it->currentelem);\
-}\
-type *sglib_##type##_it_next(struct sglib_##type##_iterator *it) {\
- sglib__##type##_it_compute_current_elem(it);\
- return(it->currentelem);\
-}\
-\
-static void sglib___##type##_consistency_check_recursive(type *t, int *pathdeep, int cdeep) {\
- if (t==NULL) {\
- if (*pathdeep < 0) *pathdeep = cdeep;\
- else assert(*pathdeep == cdeep);\
- } else {\
- if (t->left!=NULL) assert(comparator(t->left, t) <= 0);\
- if (t->right!=NULL) assert(comparator(t, t->right) <= 0);\
- if (SGLIB___GET_VALUE(t->bits) == RED) {\
- assert(t->left == NULL || SGLIB___GET_VALUE(t->left->bits)==BLACK);\
- assert(t->right == NULL || SGLIB___GET_VALUE(t->right->bits)==BLACK);\
- sglib___##type##_consistency_check_recursive(t->left, pathdeep, cdeep);\
- sglib___##type##_consistency_check_recursive(t->right, pathdeep, cdeep);\
- } else {\
- sglib___##type##_consistency_check_recursive(t->left, pathdeep, cdeep+1);\
- sglib___##type##_consistency_check_recursive(t->right, pathdeep, cdeep+1);\
- }\
- }\
-}\
-\
-void sglib___##type##_consistency_check(type *t) {\
- int pathDeep;\
- assert(t==NULL || SGLIB___GET_VALUE(t->bits) == BLACK);\
- pathDeep = -1;\
- sglib___##type##_consistency_check_recursive(t, &pathDeep, 0);\
-}
-
-
-#define SGLIB_DEFINE_RBTREE_PROTOTYPES(type, left, right, colorbit, comparator) \
- struct sglib_##type##_iterator {\
- type *currentelem;\
- char pass[SGLIB_MAX_TREE_DEEP];\
- type *path[SGLIB_MAX_TREE_DEEP];\
- short int pathi;\
- short int order;\
- type *equalto;\
- int (*subcomparator)(type *, type *);\
- };\
- extern void sglib___##type##_consistency_check(type *t); \
- extern void sglib_##type##_add(type **tree, type *elem); \
- extern int sglib_##type##_add_if_not_member(type **tree, type *elem, type **memb); \
- extern void sglib_##type##_delete(type **tree, type *elem); \
- extern int sglib_##type##_delete_if_member(type **tree, type *elem, type **memb); \
- extern int sglib_##type##_is_member(type *t, type *elem); \
- extern type *sglib_##type##_find_member(type *t, type *elem); \
- extern int sglib_##type##_len(type *t); \
- extern type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *tree); \
- extern type *sglib_##type##_it_init_preorder(struct sglib_##type##_iterator *it, type *tree); \
- extern type *sglib_##type##_it_init_inorder(struct sglib_##type##_iterator *it, type *tree); \
- extern type *sglib_##type##_it_init_postorder(struct sglib_##type##_iterator *it, type *tree); \
- extern type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *tree, int (*subcomparator)(type *, type *), type *equalto); \
- extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \
- extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it); \
-
-
-#define SGLIB_DEFINE_RBTREE_FUNCTIONS(type, left, right, colorbit, comparator) \
- SGLIB_DEFINE_RBTREE_FUNCTIONS_GENERAL(type, left, right, colorbit, comparator, 1, 0)
-
-
-
-/* ---------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------- */
-/* - SUPPLEMENTARY DEFINITIONS - */
-/* ---------------------------------------------------------------------------- */
-/* ---------------------------------------------------------------------------- */
-
-
-#define SGLIB___GET_VALUE(x) (x)
-#define SGLIB___SET_VALUE(x, value) {(x) = (value);}
-#define SGLIB_ARRAY_ELEMENTS_EXCHANGER(type, a, i, j) {type _sgl_aee_tmp_; _sgl_aee_tmp_=(a)[(i)]; (a)[(i)]=(a)[(j)]; (a)[(j)]= _sgl_aee_tmp_;}
-
-
-#define SGLIB_SAFE_NUMERIC_COMPARATOR(x, y) (((x)>(y)?1:((x)<(y)?-1:0)))
-#define SGLIB_SAFE_REVERSE_NUMERIC_COMPARATOR(x, y) (((x)>(y)?-1:((x)<(y)?1:0)))
-#define SGLIB_FAST_NUMERIC_COMPARATOR(x, y) ((int)((x) - (y)))
-#define SGLIB_FAST_REVERSE_NUMERIC_COMPARATOR(x, y) ((int)((y) - (x)))
-#define SGLIB_NUMERIC_COMPARATOR(x, y) SGLIB_SAFE_NUMERIC_COMPARATOR(x, y)
-#define SGLIB_REVERSE_NUMERIC_COMPARATOR(x, y) SGLIB_SAFE_REVERSE_NUMERIC_COMPARATOR(x, y)
-
-#ifndef SGLIB_MAX_TREE_DEEP
-#define SGLIB_MAX_TREE_DEEP 128
-#endif
-
-#ifndef SGLIB_HASH_TAB_SHIFT_CONSTANT
-#define SGLIB_HASH_TAB_SHIFT_CONSTANT 16381 /* should be a prime */
-/* #define SGLIB_HASH_TAB_SHIFT_CONSTANT 536870912*/ /* for large tables :) */
-#endif
-
-#endif /* _SGLIB__h_ */
diff --git a/src/include/tome/enum_string_map.hpp b/src/include/tome/enum_string_map.hpp
new file mode 100644
index 00000000..8ae1e115
--- /dev/null
+++ b/src/include/tome/enum_string_map.hpp
@@ -0,0 +1,55 @@
+#pragma once
+
+#include <boost/bimap.hpp>
+#include <boost/noncopyable.hpp>
+#include <string>
+#include <cassert>
+
+/**
+ * Bidirectional mapping between enumerated values
+ * and strings.
+ */
+template <class E>
+class EnumStringMap : boost::noncopyable {
+
+private:
+ typedef boost::bimap< E, std::string > bimap_type;
+ typedef typename bimap_type::value_type value_type;
+
+ bimap_type bimap;
+
+public:
+ explicit EnumStringMap(std::initializer_list< std::pair<E, const char *> > in) {
+ for (auto es : in)
+ {
+ bimap.insert(value_type(es.first, es.second));
+ }
+ // Sanity check that there were no
+ // duplicate mappings.
+ assert(bimap.size() == in.size());
+ }
+
+ const char *stringify(E e) {
+ auto i = bimap.left.find(e);
+ assert(i != bimap.left.end() && "Missing mapping for enumerated value");
+ return i->second.c_str();
+ }
+
+ E parse(const char *s) {
+ E e;
+ bool result = parse(s, &e);
+ assert(result && "Missing string->enum mapping");
+ return e;
+ }
+
+ bool parse(const char *s, E *e) {
+ auto i = bimap.right.find(s);
+ if (i == bimap.right.end())
+ {
+ return false;
+ }
+
+ *e = i->second;
+ return true;
+ }
+};
diff --git a/src/include/tome/make_array.hpp b/src/include/tome/make_array.hpp
new file mode 100644
index 00000000..23cb8ac0
--- /dev/null
+++ b/src/include/tome/make_array.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <type_traits>
+
+/*
+ * Make an array of a POD type.
+ */
+template <typename T> T *make_array(std::size_t n) {
+ static_assert(std::is_pod<T>::value, "Type parameter must be POD type");
+ T *array = new T[n];
+ memset(array, 0, n*sizeof(T));
+ return array;
+}
diff --git a/src/include/tome/squelch/automatizer.hpp b/src/include/tome/squelch/automatizer.hpp
new file mode 100644
index 00000000..786ca1ae
--- /dev/null
+++ b/src/include/tome/squelch/automatizer.hpp
@@ -0,0 +1,156 @@
+#pragma once
+
+#include <boost/noncopyable.hpp>
+#include <memory>
+#include <vector>
+#include <jansson.h>
+
+#include "tome/squelch/rule_fwd.hpp"
+#include "tome/squelch/cursor_fwd.hpp"
+#include "tome/squelch/tree_printer_fwd.hpp"
+#include "tome/squelch/condition_fwd.hpp"
+#include "../object_type_fwd.hpp"
+
+namespace squelch {
+
+/**
+ * Automatizer
+ */
+class Automatizer : public boost::noncopyable
+{
+public:
+ Automatizer(std::shared_ptr<TreePrinter> tree_printer,
+ std::shared_ptr<Cursor> cursor)
+ : m_selected_rule(0)
+ , m_begin(0)
+ , m_tree_printer(tree_printer)
+ , m_cursor(cursor)
+ , m_rules() {
+ }
+
+ /**
+ * Append a rule
+ */
+ int append_rule(std::shared_ptr<Rule> rule);
+
+ /**
+ * Swap two rules
+ */
+ void swap_rules(int i, int j);
+
+ /**
+ * Apply all rules to the given object
+ */
+ bool apply_rules(object_type *o_ptr, int item_idx) const;
+
+ /**
+ * Build a JSON data structure to represent
+ * all the rules.
+ */
+ std::shared_ptr<json_t> to_json() const;
+
+ /**
+ * Load rules from a JSON data structure.
+ */
+ void load_json(json_t *json);
+
+ /**
+ * Remove currently selected condition or rule.
+ */
+ int remove_current_selection();
+
+ /**
+ * Reset view.
+ */
+ void reset_view();
+
+ /**
+ * Show current rule
+ */
+ void show_current() const;
+
+ /**
+ * Scroll view up
+ */
+ void scroll_up();
+
+ /**
+ * Scroll view down
+ */
+ void scroll_down();
+
+ /**
+ * Scroll view left
+ */
+ void scroll_left();
+
+ /**
+ * Scroll view right
+ */
+ void scroll_right();
+
+ /**
+ * Move selection up
+ */
+ void move_up();
+
+ /**
+ * Move selection down
+ */
+ void move_down();
+
+ /**
+ * Move selection left
+ */
+ void move_left();
+
+ /**
+ * Move selection right
+ */
+ void move_right();
+
+ /**
+ * Add new condition to selected rule
+ */
+ void add_new_condition(std::function<std::shared_ptr<Condition> ()> factory);
+
+ /**
+ * Get rule names. The names are not stable across multiple
+ * calls to methods on this class.
+ */
+ void get_rule_names(std::vector<const char *> *names) const;
+
+ /**
+ * Get current number of rules.
+ */
+ int rules_count() const;
+
+ /**
+ * Get the "beginning" rule.
+ */
+ int rules_begin() const;
+
+ /**
+ * Select a new rule.
+ */
+ void select_rule(int selected_rule);
+
+ /**
+ * Return selected rule index
+ */
+ int selected_rule() const;
+
+ /**
+ * Return selected rule
+ */
+ std::shared_ptr<Rule> current_rule();
+
+private:
+ int m_selected_rule;
+ int m_begin;
+ std::shared_ptr<TreePrinter> m_tree_printer;
+ std::shared_ptr<Cursor> m_cursor;
+ std::vector < std::shared_ptr < Rule > > m_rules;
+};
+
+} // namespace
diff --git a/src/include/tome/squelch/automatizer_fwd.hpp b/src/include/tome/squelch/automatizer_fwd.hpp
new file mode 100644
index 00000000..068f297a
--- /dev/null
+++ b/src/include/tome/squelch/automatizer_fwd.hpp
@@ -0,0 +1,10 @@
+#ifndef H_cbf79126_fd24_4f80_8f2d_9dd69cb7010f
+#define H_cbf79126_fd24_4f80_8f2d_9dd69cb7010f
+
+namespace squelch {
+
+class Automatizer;
+
+} // namespace
+
+#endif
diff --git a/src/include/tome/squelch/condition.hpp b/src/include/tome/squelch/condition.hpp
new file mode 100644
index 00000000..5d1240f5
--- /dev/null
+++ b/src/include/tome/squelch/condition.hpp
@@ -0,0 +1,632 @@
+#pragma once
+
+#include "tome/squelch/condition_fwd.hpp"
+
+#include <boost/noncopyable.hpp>
+#include <functional>
+#include <memory>
+#include <cstdint>
+#include <jansson.h>
+
+#include "tome/squelch/cursor_fwd.hpp"
+#include "tome/squelch/tree_printer_fwd.hpp"
+#include "tome/squelch/object_status_fwd.hpp"
+#include "tome/enum_string_map.hpp"
+#include "../object_type_fwd.hpp"
+
+namespace squelch {
+
+/**
+ * Types of matches used for conditions.
+ */
+enum class match_type {
+ AND , OR , NOT , NAME , CONTAIN ,
+ INSCRIBED, DISCOUNT, SYMBOL , STATE , STATUS ,
+ TVAL , SVAL , RACE , SUBRACE , CLASS ,
+ LEVEL , SKILL , ABILITY, INVENTORY, EQUIPMENT };
+
+/**
+ * Bidirectional map between enumeration values and strings.
+ */
+EnumStringMap<match_type> &match_mapping();
+
+/**
+ * Identification states an object can have: identified or not
+ * identified.
+ */
+enum class identification_state {
+ IDENTIFIED, NOT_IDENTIFIED };
+
+/**
+ * Biredectional map between identification_state values and strings.
+ */
+EnumStringMap<identification_state> &identification_state_mapping();
+
+/**
+ * Condition represents a tree of checks which
+ * can be applied to objects, the player, etc.
+ */
+class Condition : public boost::noncopyable
+{
+public:
+ Condition(match_type match_) : match(match_) {
+ }
+
+ void display(TreePrinter *, Cursor *) const;
+
+ virtual bool is_match(object_type *) const = 0;
+
+ virtual ~Condition() {
+ }
+
+public:
+ json_t *to_json() const;
+
+ virtual void add_child(ConditionFactory const &factory) {
+ // Default is to not support children.
+ };
+
+ virtual void remove_child(Condition *c) {
+ // Nothing to do by default.
+ }
+
+ virtual std::shared_ptr<Condition> first_child() {
+ // No children.
+ return nullptr;
+ }
+
+ virtual std::shared_ptr<Condition> previous_child(Condition *) {
+ // Default no children, so no predecessor.
+ return nullptr;
+ }
+
+ virtual std::shared_ptr<Condition> next_child(Condition *) {
+ // Default no children, so no successor.
+ return nullptr;
+ }
+
+ /**
+ * Parse condition from JSON
+ */
+ static std::shared_ptr<Condition> parse_condition(json_t *);
+
+ /**
+ * Convert an (optional) condition to JSON.
+ */
+ static json_t *optional_to_json(std::shared_ptr<Condition> condition);
+
+protected:
+ virtual void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const = 0;
+ virtual void to_json(json_t *) const = 0;
+
+ // What do we want to match?
+ match_type match;
+};
+
+/**
+ * Check for a specific TVAL
+ */
+class TvalCondition : public Condition
+{
+public:
+ TvalCondition(uint8_t tval)
+ : Condition(match_type::TVAL)
+ , m_tval(tval) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ uint8_t m_tval;
+};
+
+/**
+ * Check for object name
+ */
+class NameCondition : public Condition
+{
+public:
+ NameCondition(std::string name) :
+ Condition(match_type::NAME),
+ m_name(name) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ std::string m_name;
+};
+
+/**
+ * Check for infix of object name
+ */
+class ContainCondition : public Condition
+{
+public:
+ ContainCondition(std::string contain) :
+ Condition(match_type::CONTAIN),
+ m_contain(contain) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ std::string m_contain;
+};
+
+/**
+ * Check for specific SVAL
+ */
+class SvalCondition : public Condition
+{
+public:
+ SvalCondition(uint8_t min, uint8_t max)
+ : Condition(match_type::SVAL)
+ , m_min(min)
+ , m_max(max) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ uint8_t m_min;
+ uint8_t m_max;
+};
+
+/**
+ * Groupings of subconditions
+ */
+class GroupingCondition : public Condition
+{
+public:
+ GroupingCondition(match_type match,
+ std::vector< std::shared_ptr<Condition> > conditions = std::vector< std::shared_ptr<Condition> >())
+ : Condition(match)
+ , m_conditions(conditions) {
+ }
+
+ virtual void add_condition(std::shared_ptr<Condition> condition) {
+ if (condition)
+ {
+ m_conditions.push_back(condition);
+ }
+ }
+
+ // Child manipulation
+ virtual void add_child(ConditionFactory const &factory) override;
+ virtual void remove_child(Condition *condition) override;
+ virtual std::shared_ptr<Condition> first_child() override;
+ virtual std::shared_ptr<Condition> previous_child(Condition *) override;
+ virtual std::shared_ptr<Condition> next_child(Condition *current) override;
+
+ // Parse a list of conditions from JSON property
+ static std::vector< std::shared_ptr<Condition> > parse_conditions(json_t *);
+
+protected:
+ void to_json(json_t *) const override;
+
+protected:
+ std::vector< std::shared_ptr<Condition> > m_conditions;
+};
+
+/**
+ * Conditions that are AND'ed together
+ */
+class AndCondition : public GroupingCondition
+{
+public:
+ AndCondition() : GroupingCondition(match_type::AND) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+};
+
+/**
+ * Conditions that are OR'ed together
+ */
+class OrCondition : public GroupingCondition
+{
+public:
+ OrCondition() : GroupingCondition(match_type::OR) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+};
+
+/**
+ * Check for object status
+ */
+class StatusCondition : public Condition
+{
+public:
+ StatusCondition(status_type status)
+ : Condition(match_type::STATUS)
+ , m_status(status) {
+ }
+
+public:
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ status_type m_status;
+};
+
+/**
+ * Check for player race
+ */
+class RaceCondition : public Condition
+{
+public:
+ RaceCondition(std::string race)
+ : Condition(match_type::RACE)
+ , m_race(race) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ std::string m_race;
+};
+
+/**
+ * Check player subrace
+ */
+class SubraceCondition : public Condition
+{
+public:
+ SubraceCondition(std::string subrace)
+ : Condition(match_type::SUBRACE)
+ , m_subrace(subrace) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ std::string m_subrace;
+};
+
+/**
+ * Check player class
+ */
+class ClassCondition : public Condition
+{
+public:
+ ClassCondition(std::string klass)
+ : Condition(match_type::CLASS)
+ , m_class(klass) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ std::string m_class;
+};
+
+/**
+ * Check object inscription
+ */
+class InscriptionCondition : public Condition
+{
+public:
+ InscriptionCondition(std::string inscription)
+ : Condition(match_type::INSCRIBED)
+ , m_inscription(inscription) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ std::string m_inscription;
+};
+
+/**
+ * Check object discount
+ */
+class DiscountCondition : public Condition
+{
+public:
+ DiscountCondition(int min, int max)
+ : Condition(match_type::DISCOUNT)
+ , m_min(min)
+ , m_max(max) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ int m_min;
+ int m_max;
+};
+
+/**
+ * Check player level
+ */
+class LevelCondition : public Condition
+{
+public:
+ LevelCondition(int min, int max)
+ : Condition(match_type::LEVEL)
+ , m_min(min)
+ , m_max(max) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ int m_min;
+ int m_max;
+};
+
+/**
+ * Check player's skill level
+ */
+class SkillCondition : public Condition
+{
+public:
+ SkillCondition(uint16_t skill_idx, uint16_t min, uint16_t max)
+ : Condition(match_type::SKILL)
+ , m_skill_idx(skill_idx)
+ , m_min(min)
+ , m_max(max) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ uint16_t m_skill_idx;
+ uint16_t m_min;
+ uint16_t m_max;
+};
+
+/**
+ * Check identification state
+ */
+class StateCondition : public Condition
+{
+public:
+ StateCondition(identification_state state)
+ : Condition(match_type::STATE)
+ , m_state(state) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ identification_state m_state;
+};
+
+/**
+ * Check object symbol
+ */
+class SymbolCondition : public Condition
+{
+public:
+ SymbolCondition(char symbol)
+ : Condition(match_type::SYMBOL)
+ , m_symbol(symbol) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ char m_symbol;
+};
+
+/**
+ * Check if player has a particular ability
+ */
+class AbilityCondition : public Condition
+{
+public:
+ AbilityCondition(uint16_t ability_idx)
+ : Condition(match_type::ABILITY)
+ , m_ability_idx(ability_idx) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ uint16_t m_ability_idx;
+};
+
+/**
+ * Condition with a single subcondition
+ */
+class SingleSubconditionCondition : public Condition
+{
+public:
+ SingleSubconditionCondition(match_type match,
+ std::shared_ptr<Condition> subcondition)
+ : Condition(match)
+ , m_subcondition(subcondition) {
+ }
+
+ virtual void add_child(std::function< std::shared_ptr<Condition> () > const &factory) override;
+
+ virtual void remove_child(Condition *c) override;
+
+ virtual std::shared_ptr<Condition> first_child() override;
+
+protected:
+ void to_json(json_t *) const override;
+
+ static std::shared_ptr<Condition> parse_single_subcondition(
+ json_t *condition_json);
+
+protected:
+ std::shared_ptr<Condition> m_subcondition;
+};
+
+/**
+ * Condition which negates another condition
+ */
+class NotCondition : public SingleSubconditionCondition
+{
+public:
+ NotCondition(std::shared_ptr<Condition> subcondition = nullptr)
+ : SingleSubconditionCondition(match_type::NOT, subcondition) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+};
+
+/**
+ * Condition which checks if player inventory contains object(s)
+ * satisfying another condition.
+ */
+class InventoryCondition : public SingleSubconditionCondition
+{
+public:
+ InventoryCondition(std::shared_ptr<Condition> subcondition = nullptr)
+ : SingleSubconditionCondition(match_type::INVENTORY, subcondition) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+};
+
+/**
+ * Condition which checks if player equipment contains object(s)
+ * satisfying another condition.
+ */
+class EquipmentCondition : public SingleSubconditionCondition
+{
+public:
+ EquipmentCondition(std::shared_ptr<Condition> subcondition = nullptr)
+ : SingleSubconditionCondition(match_type::EQUIPMENT, subcondition) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+};
+
+} // namespace
diff --git a/src/include/tome/squelch/condition_fwd.hpp b/src/include/tome/squelch/condition_fwd.hpp
new file mode 100644
index 00000000..744e7884
--- /dev/null
+++ b/src/include/tome/squelch/condition_fwd.hpp
@@ -0,0 +1,15 @@
+#ifndef H_1122f873_e83d_4af8_b6a8_a9e8db195473
+#define H_1122f873_e83d_4af8_b6a8_a9e8db195473
+
+#include <functional>
+#include <memory>
+
+namespace squelch {
+
+enum class match_type : int;
+class Condition;
+typedef std::function< std::shared_ptr<Condition> () > ConditionFactory;
+
+} // namespace
+
+#endif
diff --git a/src/include/tome/squelch/condition_metadata.hpp b/src/include/tome/squelch/condition_metadata.hpp
new file mode 100644
index 00000000..fbb26bc3
--- /dev/null
+++ b/src/include/tome/squelch/condition_metadata.hpp
@@ -0,0 +1,12 @@
+#ifndef H_787198a1_aa3e_45c9_bc9f_fd7f490db78c
+#define H_787198a1_aa3e_45c9_bc9f_fd7f490db78c
+
+#include "tome/squelch/condition_metadata_fwd.hpp"
+
+namespace squelch {
+
+std::shared_ptr<Condition> new_condition_interactive();
+
+} // namespace
+
+#endif
diff --git a/src/include/tome/squelch/condition_metadata_fwd.hpp b/src/include/tome/squelch/condition_metadata_fwd.hpp
new file mode 100644
index 00000000..1f57481b
--- /dev/null
+++ b/src/include/tome/squelch/condition_metadata_fwd.hpp
@@ -0,0 +1,14 @@
+#ifndef H_7922f591_bdfd_491d_8561_b11225285fea
+#define H_7922f591_bdfd_491d_8561_b11225285fea
+
+#include "tome/squelch/condition_fwd.hpp"
+
+#include <memory>
+
+namespace squelch {
+
+std::shared_ptr<Condition> new_condition_interactive();
+
+} // namespace
+
+#endif
diff --git a/src/include/tome/squelch/cursor.hpp b/src/include/tome/squelch/cursor.hpp
new file mode 100644
index 00000000..8dbfc6bf
--- /dev/null
+++ b/src/include/tome/squelch/cursor.hpp
@@ -0,0 +1,50 @@
+#ifndef H_8a10111d_64a1_4af9_a85b_24ec8922d3fa
+#define H_8a10111d_64a1_4af9_a85b_24ec8922d3fa
+
+#include <boost/noncopyable.hpp>
+#include <deque>
+
+#include "tome/squelch/condition_fwd.hpp"
+
+namespace squelch {
+
+/**
+ * Cursor which maintains selected condition(s)
+ */
+class Cursor : public boost::noncopyable
+{
+public:
+ bool is_selected(Condition const *condition) const;
+
+ void push(Condition *condition) {
+ m_conditions.push_back(condition);
+ }
+
+ Condition *pop();
+
+ Condition *current();
+
+ void clear() {
+ m_conditions.clear();
+ }
+
+ bool empty() const {
+ return m_conditions.empty();
+ }
+
+ std::size_t size() const {
+ return m_conditions.size();
+ }
+
+ void move_left();
+ void move_right();
+ void move_up();
+ void move_down();
+
+private:
+ std::deque<Condition *> m_conditions;
+};
+
+} // namespace
+
+#endif
diff --git a/src/include/tome/squelch/cursor_fwd.hpp b/src/include/tome/squelch/cursor_fwd.hpp
new file mode 100644
index 00000000..f07e9aa9
--- /dev/null
+++ b/src/include/tome/squelch/cursor_fwd.hpp
@@ -0,0 +1,10 @@
+#ifndef H_a4caa98a_1044_4192_b1af_27c2e8790cae
+#define H_a4caa98a_1044_4192_b1af_27c2e8790cae
+
+namespace squelch {
+
+class Cursor;
+
+} // namespace
+
+#endif
diff --git a/src/include/tome/squelch/object_status.hpp b/src/include/tome/squelch/object_status.hpp
new file mode 100644
index 00000000..c52a35ea
--- /dev/null
+++ b/src/include/tome/squelch/object_status.hpp
@@ -0,0 +1,28 @@
+#ifndef H_e3f9ebbe_ff9a_4687_a847_6101f094b483
+#define H_e3f9ebbe_ff9a_4687_a847_6101f094b483
+
+#include "tome/enum_string_map.hpp"
+
+namespace squelch {
+
+/**
+ * Types of statuses for objects, e.g. "special" for artifacts and
+ * "average" for plain objects with no plusses.
+ */
+enum class status_type {
+ BAD , VERY_BAD, AVERAGE, GOOD, VERY_GOOD,
+ SPECIAL, TERRIBLE, NONE, CHEST_EMPTY, CHEST_DISARMED };
+
+/**
+ * Bidirectional map between status_type values and strings.
+ */
+EnumStringMap<status_type> &status_mapping();
+
+/**
+ * Find the status of an object
+ */
+status_type object_status(object_type *o_ptr);
+
+} // namespace
+
+#endif
diff --git a/src/include/tome/squelch/object_status_fwd.hpp b/src/include/tome/squelch/object_status_fwd.hpp
new file mode 100644
index 00000000..361ea2fe
--- /dev/null
+++ b/src/include/tome/squelch/object_status_fwd.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "../object_type_fwd.hpp"
+#include "tome/enum_string_map.hpp"
+
+namespace squelch {
+
+enum class status_type;
+EnumStringMap<status_type> &status_mapping();
+status_type object_status(object_type *o_ptr);
+
+} // namespace
diff --git a/src/include/tome/squelch/rule.hpp b/src/include/tome/squelch/rule.hpp
new file mode 100644
index 00000000..63f1b6c0
--- /dev/null
+++ b/src/include/tome/squelch/rule.hpp
@@ -0,0 +1,162 @@
+#pragma once
+
+#include <jansson.h>
+#include <memory>
+
+#include "tome/squelch/condition_fwd.hpp"
+#include "tome/squelch/cursor_fwd.hpp"
+#include "tome/squelch/tree_printer_fwd.hpp"
+#include "tome/enum_string_map.hpp"
+#include "../object_type_fwd.hpp"
+
+namespace squelch {
+
+/**
+ * Types of automatizer actions: destroy, pick up, and inscribe.
+ */
+enum class action_type { AUTO_DESTROY, AUTO_PICKUP, AUTO_INSCRIBE };
+
+/**
+ * Bidirectional map between rule actions and strings.
+ */
+EnumStringMap<action_type> &action_mapping();
+
+/**
+ * Rules are the representation of "when condition X is true, do Y".
+ */
+class Rule : public boost::noncopyable
+{
+public:
+ Rule(std::string name,
+ action_type action,
+ int module_idx,
+ std::shared_ptr<Condition> condition)
+ : m_name(name)
+ , m_action(action)
+ , m_module_idx(module_idx)
+ , m_condition(condition) {
+ }
+
+ /**
+ * Set the name of the rule
+ */
+ void set_name(const char *new_name);
+
+ /**
+ * Get the name of the rule
+ */
+ const char *get_name() const;
+
+ /**
+ * Get condition
+ */
+ std::shared_ptr<Condition> get_condition() const;
+
+ /**
+ * Add new condition using a factory to instantiate the
+ * condition only if the rule permits adding a condition.
+ */
+ void add_new_condition(Cursor *cursor,
+ ConditionFactory const &factory);
+
+ /**
+ * Remove currently selected condition
+ */
+ void delete_selected_condition(Cursor *cursor);
+
+ /**
+ * Write out tree representing rule
+ */
+ void write_tree(TreePrinter *p, Cursor *cursor) const;
+
+ /**
+ * Apply rule to object
+ */
+ bool apply_rule(object_type *o_ptr, int item_idx) const;
+
+ /**
+ * Convert rule to JSON
+ */
+ virtual json_t *to_json() const;
+
+ /**
+ * Parse rule from JSON
+ */
+ static std::shared_ptr<Rule> parse_rule(json_t *);
+
+protected:
+ virtual bool do_apply_rule(object_type *, int) const = 0;
+ virtual void do_write_tree(TreePrinter *p) const = 0;
+
+protected:
+ // Rule name
+ std::string m_name;
+ // What does the rule do?
+ action_type m_action;
+ // Which module does this rule apply to?
+ int m_module_idx;
+ // Condition to check
+ std::shared_ptr<Condition> m_condition;
+};
+
+/**
+ * Rule for destroying matching objects
+ */
+class DestroyRule : public Rule
+{
+public:
+ DestroyRule(std::string name,
+ int module_idx,
+ std::shared_ptr<Condition> condition)
+ : Rule(name, action_type::AUTO_DESTROY, module_idx, condition) {
+ }
+
+protected:
+ virtual bool do_apply_rule(object_type *o_ptr, int item_idx) const override;
+ virtual void do_write_tree(TreePrinter *p) const override;
+};
+
+/**
+ * Rule for picking up matching objects
+ */
+class PickUpRule : public Rule
+{
+public:
+
+ PickUpRule(std::string name,
+ int module_idx,
+ std::shared_ptr<Condition> condition)
+ : Rule(name, action_type::AUTO_PICKUP, module_idx, condition) {
+ }
+
+protected:
+ virtual void do_write_tree(TreePrinter *p) const override;
+ virtual bool do_apply_rule(object_type *o_ptr, int item_idx) const override;
+};
+
+/**
+ * Rule for inscribing matching objects
+ */
+class InscribeRule : public Rule
+{
+public:
+ InscribeRule(std::string name,
+ int module_idx,
+ std::shared_ptr<Condition> condition,
+ std::string inscription)
+ : Rule(name, action_type::AUTO_INSCRIBE, module_idx, condition)
+ , m_inscription(inscription) {
+ }
+
+ json_t *to_json() const override;
+
+protected:
+ virtual void do_write_tree(TreePrinter *p) const override;
+ virtual bool do_apply_rule(object_type *o_ptr, int) const override;
+
+private:
+ // Inscription to use for inscription rules.
+ std::string m_inscription;
+};
+
+} // namespace
diff --git a/src/include/tome/squelch/rule_fwd.hpp b/src/include/tome/squelch/rule_fwd.hpp
new file mode 100644
index 00000000..091e77ef
--- /dev/null
+++ b/src/include/tome/squelch/rule_fwd.hpp
@@ -0,0 +1,16 @@
+#ifndef H_4a8d2cfb_182c_4138_983d_606a9ac70784
+#define H_4a8d2cfb_182c_4138_983d_606a9ac70784
+
+#include "tome/enum_string_map.hpp"
+
+namespace squelch {
+
+enum class action_type;
+
+EnumStringMap<action_type> &action_mapping();
+
+class Rule;
+
+} // namespace
+
+#endif
diff --git a/src/include/tome/squelch/tree_printer.hpp b/src/include/tome/squelch/tree_printer.hpp
new file mode 100644
index 00000000..e8ee1e56
--- /dev/null
+++ b/src/include/tome/squelch/tree_printer.hpp
@@ -0,0 +1,49 @@
+#ifndef H_3d6cc652_c674_4a84_911d_e8ec35cc992a
+#define H_3d6cc652_c674_4a84_911d_e8ec35cc992a
+
+#include <boost/noncopyable.hpp>
+#include <cstdint>
+
+namespace squelch {
+
+/**
+ * Printing trees.
+ */
+class TreePrinter : boost::noncopyable
+{
+public:
+ TreePrinter();
+
+ void indent();
+
+ void dedent();
+
+ void reset();
+
+ void reset_scroll();
+
+ void scroll_up();
+
+ void scroll_down();
+
+ void scroll_left();
+
+ void scroll_right();
+
+ void write(uint8_t color, const char *line);
+
+private:
+ int m_indent;
+ int m_write_out_y;
+ int m_write_out_x;
+ int m_write_out_h;
+ int m_write_out_w;
+ int m_write_y;
+ int m_write_x;
+ int m_write_off_x;
+ int m_write_off_y;
+};
+
+} // namespace
+
+#endif
diff --git a/src/include/tome/squelch/tree_printer_fwd.hpp b/src/include/tome/squelch/tree_printer_fwd.hpp
new file mode 100644
index 00000000..d7d75453
--- /dev/null
+++ b/src/include/tome/squelch/tree_printer_fwd.hpp
@@ -0,0 +1,10 @@
+#ifndef H_4ce68eb3_c475_4fc4_8a70_0590c16dc684
+#define H_4ce68eb3_c475_4fc4_8a70_0590c16dc684
+
+namespace squelch {
+
+class TreePrinter;
+
+} // namespace
+
+#endif