diff options
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/sglib.h | 1952 | ||||
-rw-r--r-- | src/include/tome/enum_string_map.hpp | 55 | ||||
-rw-r--r-- | src/include/tome/make_array.hpp | 13 | ||||
-rw-r--r-- | src/include/tome/squelch/automatizer.hpp | 156 | ||||
-rw-r--r-- | src/include/tome/squelch/automatizer_fwd.hpp | 10 | ||||
-rw-r--r-- | src/include/tome/squelch/condition.hpp | 632 | ||||
-rw-r--r-- | src/include/tome/squelch/condition_fwd.hpp | 15 | ||||
-rw-r--r-- | src/include/tome/squelch/condition_metadata.hpp | 12 | ||||
-rw-r--r-- | src/include/tome/squelch/condition_metadata_fwd.hpp | 14 | ||||
-rw-r--r-- | src/include/tome/squelch/cursor.hpp | 50 | ||||
-rw-r--r-- | src/include/tome/squelch/cursor_fwd.hpp | 10 | ||||
-rw-r--r-- | src/include/tome/squelch/object_status.hpp | 28 | ||||
-rw-r--r-- | src/include/tome/squelch/object_status_fwd.hpp | 12 | ||||
-rw-r--r-- | src/include/tome/squelch/rule.hpp | 162 | ||||
-rw-r--r-- | src/include/tome/squelch/rule_fwd.hpp | 16 | ||||
-rw-r--r-- | src/include/tome/squelch/tree_printer.hpp | 49 | ||||
-rw-r--r-- | src/include/tome/squelch/tree_printer_fwd.hpp | 10 |
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 |