]>
git.saurik.com Git - wxWidgets.git/blob - utils/HelpGen/src/wxstlac.h
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Contrib. demo
4 // Author: Aleksandras Gluchovas
8 // Copyright: (c) Aleskandars Gluchovas
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
20 #if !defined(__WXMAC__) || defined(__DARWIN__)
21 # include <sys/types.h>
25 /* #include <new.h> */
27 // the below macro used internally (see actual interface after this macro)
32 // ASSOC_CONT_CLASS_NAME
36 // ARG_ACTUAL_VALUE_TYPE
44 // _INSERT_METHOD_DEFINITION
46 #define __DEFINE_ASOC_CLASS( ARG_IS_UNIQUE, \
48 ASSOC_CONT_CLASS_NAME, \
51 ARG_ACTUAL_VALUE_TYPE, \
56 _INSERT_METHOD_DEFINITION \
58 ASSOC_CONT_CLASS_NAME\
63 typedef ARG_VALUE_TYPE value_type;\
64 typedef ARG_KEY_TYPE key_type;\
65 typedef ARG_ACTUAL_VALUE_TYPE actual_value_type;\
67 typedef value_type* pointer;\
68 typedef value_type& reference;\
70 typedef const value_type& const_reference;\
72 typedef FUNCTOR key_compare;\
73 typedef key_compare Compare;\
79 tree_node* m_pParent;\
87 typedef tree_node* node_ref_type;\
90 node_ref_type mpRoot;\
91 node_ref_type mpLeftMost;\
92 node_ref_type mpRightMost;\
94 node_ref_type mpFreeListHead;\
97 key_compare mCmpFunctorObj;\
101 static inline node_ref_type next( node_ref_type pNode )\
103 if ( pNode->mpRight ) \
105 pNode = pNode->mpRight;\
107 while ( pNode->mpLeft ) pNode = pNode->mpLeft;\
112 if ( pNode->m_pParent )\
114 if ( pNode == pNode->m_pParent->mpLeft )\
116 return pNode->m_pParent;\
118 pNode = pNode->m_pParent;\
120 node_ref_type prevNode = pNode;\
121 pNode = pNode->m_pParent;\
125 if ( pNode->mpRight &&\
126 pNode->mpRight != prevNode\
130 pNode= pNode->m_pParent;\
139 static inline node_ref_type prev( node_ref_type pNode )\
141 if ( pNode->mpLeft ) \
143 pNode = pNode->mpLeft;\
145 while ( pNode->mpRight ) pNode = pNode->mpRight;\
150 if ( pNode->m_pParent )\
152 if ( pNode == pNode->m_pParent->mpRight )\
153 return pNode->m_pParent;\
155 pNode = pNode->m_pParent;\
157 node_ref_type prevNode = pNode;\
158 pNode = pNode->m_pParent;\
162 if ( pNode->mpLeft &&\
163 pNode->mpLeft != prevNode\
167 pNode= pNode->m_pParent;\
178 inline int are_equel( const key_type& x, const key_type& y )\
180 return ( !mCmpFunctorObj(x,y) && !mCmpFunctorObj(y,x) );\
183 inline int is_less( const key_type& x, const key_type& y )\
185 return mCmpFunctorObj(x,y);\
188 static inline const actual_value_type& value( node_ref_type pNode )\
190 return pNode->_VALUE_NAME;\
193 static inline const key_type& key( node_ref_type pNode )\
195 return pNode->_KEY_NAME;\
198 inline node_ref_type AllocNode() \
200 if ( mpFreeListHead ) \
202 node_ref_type pFreeNode = mpFreeListHead;\
203 mpFreeListHead = mpFreeListHead->mpLeft;\
209 char* pHeapBlock = new char[sizeof(tree_node)];\
211 return (node_ref_type)pHeapBlock;\
215 inline void DestroyFreeList()\
217 while ( mpFreeListHead )\
219 node_ref_type tmp = mpFreeListHead;\
220 mpFreeListHead = mpFreeListHead->mpLeft;\
222 delete [](char*)tmp;\
226 inline void RecycleNode( node_ref_type pNode ) \
228 pNode->mpLeft = mpFreeListHead;\
229 mpFreeListHead = pNode;\
232 inline node_ref_type do_insert(const value_type& x = value_type() )\
234 node_ref_type pNewNode = AllocNode();\
236 pNewNode->m_pParent = \
238 pNewNode->mpRight = 0;\
240 node_ref_type pCurrent = mpRoot;\
241 node_ref_type pParent = 0;\
245 if ( mKeyIsUnique && are_equel( _X_KEY_NAME, value(pCurrent) ) )\
247 RecycleNode(pNewNode);\
253 pCurrent = is_less( _X_KEY_NAME, value(pCurrent) ) \
255 : pCurrent->mpRight;\
258 pNewNode->m_pParent = pParent;\
262 if( is_less(_X_KEY_NAME, value(pParent) ) )\
264 pParent->mpLeft = pNewNode;\
266 pParent->mpRight = pNewNode;\
270 new ( &pNewNode->_KEY_NAME ) key_type(_X_KEY_NAME);\
271 new ( &pNewNode->_VALUE_NAME ) actual_value_type(_X_VALUE_NAME);\
273 if ( prev(pNewNode) == 0 ) mpLeftMost = pNewNode;\
274 if ( next(pNewNode) == 0 ) mpRightMost = pNewNode;\
279 friend class iterator;\
284 class const_iterator;\
289 node_ref_type mpNode;\
290 friend class CONT_CLASS_NAME;\
291 friend class const_iterator;\
292 friend class const_reverse_iterator;\
294 inline iterator( node_ref_type pNode )\
300 inline iterator() {}\
301 inline int operator==( const iterator& rhs ) const { return (mpNode == rhs.mpNode); }\
302 inline int operator!=( const iterator& rhs ) const { return (mpNode != rhs.mpNode); }\
304 inline iterator( const iterator& other )\
306 mpNode = other.mpNode;\
309 inline const iterator& operator=( const iterator& other )\
311 mpNode = other.mpNode;\
315 inline const iterator& operator--() \
317 mpNode = ASSOC_CONT_CLASS_NAME::prev(mpNode);\
321 inline iterator operator--(int)\
323 iterator tmp = *this;\
324 mpNode = ASSOC_CONT_CLASS_NAME::prev(mpNode);\
328 inline const iterator& operator++() \
330 mpNode = ASSOC_CONT_CLASS_NAME::next(mpNode);\
334 inline iterator operator++(int)\
336 iterator tmp = *this;\
337 mpNode = ASSOC_CONT_CLASS_NAME::next(mpNode);\
341 inline reference operator*() const { return mpNode->mData; }\
345 class const_iterator \
348 node_ref_type mpNode;\
349 friend class CONT_CLASS_NAME;\
350 friend class const_reverse_iterator;\
352 inline const_iterator( node_ref_type pNode )\
358 inline const_iterator() {}\
360 inline int operator==( const const_iterator& rhs ) const { return (mpNode == rhs.mpNode); }\
361 inline int operator!=( const const_iterator& rhs ) const { return (mpNode != rhs.mpNode); }\
363 inline const_iterator( const iterator& other )\
365 mpNode = other.mpNode;\
368 inline const_iterator( const const_iterator& other )\
370 mpNode = other.mpNode;\
373 inline const const_iterator& operator=( const const_iterator& other )\
375 mpNode = other.mpNode;\
379 inline const const_iterator& operator--() \
381 mpNode = ASSOC_CONT_CLASS_NAME::prev(mpNode);\
385 inline const_iterator operator--(int)\
387 const_iterator tmp = *this;\
388 mpNode = ASSOC_CONT_CLASS_NAME::prev(mpNode);\
392 inline const const_iterator& operator++() \
394 mpNode = ASSOC_CONT_CLASS_NAME::next(mpNode);\
398 inline const_iterator operator++(int)\
400 const_iterator tmp = *this;\
401 mpNode = ASSOC_CONT_CLASS_NAME::next(mpNode);\
405 inline const_reference operator*() const { return mpNode->mData; }\
410 inline ASSOC_CONT_CLASS_NAME( key_compare cmpFunctorObj = key_compare(),\
411 int keyIsUnique = ARG_IS_UNIQUE )\
412 : mpFreeListHead( 0 ),\
413 mKeyIsUnique( keyIsUnique ),\
414 mCmpFunctorObj( cmpFunctorObj )\
421 inline ~ASSOC_CONT_CLASS_NAME() \
423 erase( begin(), end() ); \
428 inline iterator begin() { return mpLeftMost; }\
429 inline iterator end() { return 0; }\
431 inline const_iterator begin() const { return mpLeftMost; }\
432 inline const_iterator end() const { return 0; }\
434 inline iterator lower_bound( const key_type& x )\
436 node_ref_type pCurrent = mpRoot;\
440 node_ref_type pParent = pCurrent;\
442 if( are_equel( x, key(pCurrent) ) )\
446 pCurrent = is_less( x, key(pCurrent) ) \
448 : pCurrent->mpRight;\
450 if ( !pCurrent ) return (pParent);\
456 inline const_iterator lower_bound( const key_type& x ) const\
458 { return const_iterator( lower_bound(x).mpNode ); }\
460 inline iterator upper_bound( const key_type& x )\
462 node_ref_type pCurrent = mpRoot;\
466 node_ref_type pParent = pCurrent;\
468 if( are_equel( x, key(pCurrent) ) )\
472 pCurrent = is_less( x, key(pCurrent) ) \
474 : pCurrent->mpRight;\
476 if ( !pCurrent ) return next(pParent);\
482 inline const_iterator upper_bound( const key_type& x ) const\
484 { return const_iterator( upper_bound(x).mpNode ); }\
486 inline iterator find( const key_type& x )\
488 node_ref_type pCurrent = mpRoot;\
492 if( are_equel( x, key(pCurrent) ) )\
496 pCurrent = is_less( x, key(pCurrent) ) \
498 : pCurrent->mpRight;\
504 inline const_iterator find( const key_type& x ) const\
506 { return const_iterator( find(x).mpNode ); }\
508 inline void erase(iterator first, iterator last)\
510 if ( first.mpNode == 0 ) return;\
512 while( first != last ) \
514 iterator next = first;\
521 inline void erase(iterator position)\
523 if ( position.mpNode == 0 ) return;\
525 node_ref_type pZ = position.mpNode;\
526 node_ref_type pX, pY;\
528 if ( pZ == mpLeftMost ) mpLeftMost = next(pZ);\
529 if ( pZ == mpRightMost ) mpRightMost = prev( pZ );\
531 if ( !pZ->mpLeft || !pZ->mpRight )\
549 if ( pX ) pX->m_pParent = pY->m_pParent;\
553 if (pY == pY->m_pParent->mpLeft )\
555 pY->m_pParent->mpLeft = pX;\
557 pY->m_pParent->mpRight = pX;\
561 node_ref_type toRemove = 0;\
565 pY->mpLeft = pZ->mpLeft;\
567 if (pY->mpLeft) pY->mpLeft->m_pParent = pY;\
569 pY->mpRight = pZ->mpRight;\
573 pY->mpRight->m_pParent = pY;\
575 pY->m_pParent = pZ->m_pParent;\
579 if (pZ == pZ->m_pParent->mpLeft)\
581 pZ->m_pParent->mpLeft = pY;\
583 pZ->m_pParent->mpRight = pY;\
592 value(toRemove).~actual_value_type();\
593 key(toRemove).~actual_value_type();\
595 RecycleNode( toRemove );\
598 _INSERT_METHOD_DEFINITION\
601 // do not undefine ___WXSTL_COMMA, where associated containers are defined!
602 // (it is used as workaround for constraints of C-Preprocessor's nested macros)
604 #define ___WXSTL_COMMA ,
606 #define __DEFINE_MAP(ARG_IS_UNIQUE, KEY_TYPE, VAL_TYPE, FUNCTOR ) \
607 __DEFINE_ASOC_CLASS( ARG_IS_UNIQUE,\
609 __WXSTLMAP_##KEY_TYPE##VAL_TYPE##ARG_IS_UNIQUE, \
610 struct key_value_pair { KEY_TYPE first ; \
613 key_value_pair( const KEY_TYPE& key ___WXSTL_COMMA const VAL_TYPE& value ) \
614 : first(key) ___WXSTL_COMMA second( value ) {} \
618 mData.first, mData.second, x.first, x.second, \
619 struct insert_result_iterator\
624 inline insert_result_iterator insert( const value_type& x )\
626 insert_result_iterator result;\
628 result.first = do_insert(x);\
629 result.second = ( result.first == end() ) ? 0 : 1;\
634 #define __DEFINE_SET(ARG_IS_UNIQUE, KEY_TYPE, FUNCTOR ) \
635 __DEFINE_ASOC_CLASS( ARG_IS_UNIQUE,\
637 __WXSTLSET_##TYPE##ARG_IS_UNIQUE, \
641 mData, mData, x, x, \
642 struct insert_result_iterator\
647 inline insert_result_iterator insert( const value_type& x )\
649 insert_result_iterator result;\
651 result.first = do_insert(x);\
652 result.second = ( result.first == end() ) ? 0 : 1;\
657 // helper macros to create functor objects for associative containers of the given type
659 #define LESS_THEN_FUNCTOR(TYPE) struct \
660 { inline int operator()(const TYPE& x, const TYPE& y ) const { return x < y; } }
662 #define GREATER_THEN_FUNCTOR(TYPE) struct \
663 { inline int operator()(const TYPE& x, const TYPE& y ) const { return x > y; } }
665 // functor argument should be created using the two above macros
666 // or passing own class with method "operator()(const TYPE&,cosnt TYPE&)" defined in it
668 #define WXSTL_MAP( KEY_TYPE, VALUE_TYPE, FUNCTOR ) __DEFINE_MAP( 1 ,KEY_TYPE, VALUE_TYPE, FUNCTOR)
669 #define WXSTL_MULTIMAP( KEY_TYPE, VALUE_TYPE, FUNCTOR ) __DEFINE_MAP( 0 ,KEY_TYPE, VALUE_TYPE, FUNCTOR)
670 #define WXSTL_SET( KEY_TYPE, FUNCTOR ) __DEFINE_SET( 1 ,KEY_TYPE, FUNCTOR )
671 #define WXSTL_MULTISET( KEY_TYPE, FUNCTOR ) __DEFINE_SET( 0 ,KEY_TYPE, FUNCTOR )