UTLists.h

Go to the documentation of this file.
00001 //==================================================================================================
00002 // Copyright (C) 2010  Brian Tietz    sdbtietz at yahoo dot com
00003 //
00004 // This program is free software; you can redistribute it and/or modify it under the terms of the
00005 // GNU General Public License as published by the Free Software Foundation, version 2.0 of the
00006 // License.
00007 //
00008 // This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
00009 // even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00010 // General Public License for more details.
00011 //
00012 // You should have received a copy of the GNU General Public License along with this program; if
00013 // not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00014 // 02110-1301, USA.
00015 //
00016 // For commercial software, the copyright holder (Brian Tietz, email sdbtietz at yahoo dot com)
00017 // reserves the right and is willing to waive the proprietary source code disclosure aspects of that
00018 // license as applied to the UT library in exchange for either substantial contributions to the
00019 // development of the UT library or other forms of compensation.  Any such waiver must be
00020 // established in writing between the copyright holder and the commercial entity obtaining such a
00021 // waiver.
00022 //==================================================================================================
00023 
00024 
00025 #ifndef _UT_LISTS_H_
00026 #define _UT_LISTS_H_
00027 
00028 
00029 //==================================================================================================
00030 //=== Project headers
00031 //==================================================================================================
00032 #include "UT.h"
00033 
00034 
00035 //==================================================================================================
00036 template <class T>
00037 class Array_t
00038 //==================================================================================================
00046 {
00047     //----------------------------------------------------------------------------------------------
00048     public:
00049     //----------------------------------------------------------------------------------------------
00050                 Array_t();
00052 
00053                 Array_t( T* stack_buffer, int stack_buffer_num_items_allcoated );
00057 
00058                 ~Array_t();
00062 
00063     void        InstallStackBuffer( T* stack_buffer, int stack_buffer_num_items_allcoated );
00065 
00066     T           AddHead(const T& item);
00068 
00069     T           AddTail(const T& item);
00071 
00072     T           AddItemAt( const T& item, int index );
00077 
00078     T           RemoveHead();
00080 
00081     T           RemoveTail();
00083 
00084     T           RemoveItemAt(int index);
00087 
00088     inline int  CountItems() const;
00090 
00091     inline int  AllocatedItems() const;
00094 
00095     inline void SetNumValidItems(int count);
00100 
00101     void        GrowIfNeeded( int min_allocated_items, bool expect_more_growth = false );
00106 
00107     inline T    Head() const;
00109 
00110     inline T    Tail() const;
00112 
00113     inline T    ItemAt(int index) const;
00118 
00119     inline T&   operator [](int index) const;
00125 
00126     inline void operator +=(const T& item);
00128 
00129     //----------------------------------------------------------------------------------------------
00130     private:
00131     //----------------------------------------------------------------------------------------------
00132     T*          m_items;
00133     int         m_num_items;
00134     int         m_items_allocated;
00135     bool        m_items_allocated_on_stack;
00136     int         m_head_index;
00137 };
00138 
00139 
00140 //==================================================================================================
00141 template <class T>
00142 class List_t
00143 //==================================================================================================
00144 : public Array_t<T*>
00146 {
00147     //----------------------------------------------------------------------------------------------
00148     public:
00149     //----------------------------------------------------------------------------------------------
00150     inline      List_t();
00152 
00153     inline      List_t( T** stack_buffer, int stack_buffer_num_items_allcoated );
00157 
00158     T*          RemoveItem(T* item);
00160 
00161     int         IndexOfItem(T* item);
00164 
00165     inline T&   operator [](int index) const;
00168 
00169     inline void operator -=(T* item);
00171 };
00172 
00173 
00174 //==================================================================================================
00175 template <class T>
00176 class OwnedList_t
00177 //==================================================================================================
00178 : public List_t<T>
00180 {
00181     //----------------------------------------------------------------------------------------------
00182     public:
00183     //----------------------------------------------------------------------------------------------
00184     inline  OwnedList_t();
00186 
00187     inline  OwnedList_t( T** stack_buffer, int stack_buffer_num_items_allcoated );
00191 
00192             ~OwnedList_t();
00194 };
00195 
00196 
00197 //==================================================================================================
00198 template <class T>
00199 class LinkedList_t
00200 //==================================================================================================
00202 {
00203     //----------------------------------------------------------------------------------------------
00204     public:
00205     //----------------------------------------------------------------------------------------------
00206     inline          LinkedList_t();
00208 
00209     T*              AddHead(T* item);
00211 
00212     T*              AddTail(T* item);
00214 
00215     T*              AddItemBefore( T* new_item, T* after_item );
00217 
00218     T*              AddItemAfter( T* before_item, T* new_item );
00220 
00221     T*              RemoveHead();
00223 
00224     T*              RemoveTail();
00226 
00227     T*              RemoveItem(T* item);
00229 
00230     inline int      CountItems() const;
00232 
00233     inline T*       Head() const;
00236 
00237     inline T*       Tail() const;
00240 
00241     inline void     operator +=(T* item);
00243 
00244     inline void     operator -=(T* item);
00246 
00247     void            SortSmallOrSlow();
00253 
00254     //----------------------------------------------------------------------------------------------
00255     private:
00256     //----------------------------------------------------------------------------------------------
00257     T*              m_head;
00258     T*              m_tail;
00259     int             m_num_items;
00260 };
00261 
00262 
00263 //==================================================================================================
00264 template <class T>
00265 class LinkedListNode_t
00266 //==================================================================================================
00273 {
00274     //----------------------------------------------------------------------------------------------
00275     protected:
00276     //----------------------------------------------------------------------------------------------
00277     inline                  LinkedListNode_t();
00279 
00280     //----------------------------------------------------------------------------------------------
00281     public:
00282     //----------------------------------------------------------------------------------------------
00283     inline T*               Next() const;
00286 
00287     inline T*               Prev() const;
00290 
00291     //----------------------------------------------------------------------------------------------
00292     private:
00293     //----------------------------------------------------------------------------------------------
00294     LinkedListNode_t<T>*    m_next;
00295     LinkedListNode_t<T>*    m_prev;
00296 
00297     friend class LinkedList_t<T>;
00298 };
00299 
00300 
00301 //==================================================================================================
00302 template <class T>
00303 class OwnedLinkedList_t
00304 //==================================================================================================
00305 : public LinkedList_t<T>
00311 {
00312     //----------------------------------------------------------------------------------------------
00313     public:
00314     //----------------------------------------------------------------------------------------------
00315         ~OwnedLinkedList_t();
00317 };
00318 
00319 
00320 //==================================================================================================
00321 template <class T, class K>
00322 class BTree_t
00323 //==================================================================================================
00346 {
00347     //----------------------------------------------------------------------------------------------
00348     public:
00349     //----------------------------------------------------------------------------------------------
00350     inline      BTree_t();
00352 
00353     T*          FindItem(K key) const;
00357 
00358     T*          FindItemAtOrBefore(K key) const;
00363 
00364     T*          FindItemAtOrAfter(K key) const;
00369 
00370     T*          IsInTree(T* item) const;
00373 
00374     void        AddItem( T* new_item, bool balance_tree = true );
00378 
00379     T*          RemoveHead(bool balance_tree = true);
00381 
00382     T*          RemoveTail(bool balance_tree = true);
00384 
00385     T*          RemoveItem( T* item, bool balance_tree = true );
00387 
00388     inline int  CountItems() const;
00390 
00391     T*          Head() const;
00394 
00395     T*          Tail() const;
00398 
00399     inline T*   Root() const;
00403 
00404     inline void operator +=(T* new_item);
00408 
00409     inline void operator -=(T* item);
00411 
00412     //----------------------------------------------------------------------------------------------
00413     private:
00414     //----------------------------------------------------------------------------------------------
00415     void        UpdateChildNodeCountsAndBalanceToRoot( T* node, bool balance_tree );
00416                     // Balances the tree from node back up to the root node, updating the child node
00417                     // counts all the way back up.
00418 
00419     //----------------------------------------------------------------------------------------------
00420     private:
00421     //----------------------------------------------------------------------------------------------
00422     T*          m_root;
00423     int         m_num_items;
00424 };
00425 
00426 
00427 //==================================================================================================
00428 template <class T, class K>
00429 class BTreeNode_t
00430 //==================================================================================================
00437 {
00438     //----------------------------------------------------------------------------------------------
00439     protected:
00440     //----------------------------------------------------------------------------------------------
00441     inline              BTreeNode_t();
00443 
00444     //----------------------------------------------------------------------------------------------
00445     public:
00446     //----------------------------------------------------------------------------------------------
00447     T*                  Next() const;
00451 
00452     T*                  Prev() const;
00456 
00457     inline bool         operator < (const T& other);
00464 
00465     inline bool         operator <= (const T& other);
00468 
00469     inline bool         operator > (const T& other);
00472 
00473     inline bool         operator >= (const T& other);
00476 
00477     inline bool         operator == (const T& other);
00480 
00481     inline bool         operator < (K key);
00488 
00489     inline bool         operator <= (K key);
00492 
00493     inline bool         operator > (K key);
00496 
00497     inline bool         operator >= (K key);
00500 
00501     inline bool         operator == (K key);
00504 
00505     inline int          ChildNodesDepth() const;
00507 
00508     void                ValidateChildNodeDepth() const;
00510 
00511     //----------------------------------------------------------------------------------------------
00512     private:
00513     //----------------------------------------------------------------------------------------------
00514     BTreeNode_t<T,K>*   m_prev;                 // Down the tree and to a lower position
00515     BTreeNode_t<T,K>*   m_parent;               // Up the tree
00516     BTreeNode_t<T,K>*   m_next;                 // Down the tree and to a higher position
00517     int                 m_child_nodes_depth;
00518 
00519     friend class BTree_t<T,K>;
00520 };
00521 
00522 
00523 //==================================================================================================
00524 template <class T, class K>
00525 class OwnedBTree_t
00526 //==================================================================================================
00527 : public BTree_t<T,K>
00534 {
00535     //----------------------------------------------------------------------------------------------
00536     public:
00537     //----------------------------------------------------------------------------------------------
00538         ~OwnedBTree_t();
00540 };
00541 
00542 
00543 //==================================================================================================
00544 template <class T, class K>
00545 class SortedList_t
00546 //==================================================================================================
00574 {
00575     //----------------------------------------------------------------------------------------------
00576     public:
00577     //----------------------------------------------------------------------------------------------
00578                 SortedList_t();
00580 
00581                 SortedList_t( T** stack_buffer, int stack_buffer_num_items_allcoated );
00585 
00586                 ~SortedList_t();
00590 
00591     T*          FindItem( K key, out int* index = NULL ) const;
00597 
00598     T*          FindItemAtOrBefore( K key, out int* index = NULL ) const;
00605 
00606     T*          FindItemAtOrAfter( K key, out int* index = NULL ) const;
00613 
00614     T*          IsInList(T* item) const;
00617 
00618     void        AddItem(T* new_item);
00625 
00626     void        AddHead(T* item);
00631 
00632     void        AddTail( T* item, bool will_sort_later = false );
00637 
00638     void        Sort();
00647 
00648     T*          RemoveItem(T* item);
00653 
00654     T*          RemoveHead();
00658 
00659     inline T*   RemoveTail();
00661 
00662     T*          RemoveItemAt(int index);
00667 
00668     int         IndexOfItem(T* item);
00671 
00672     inline int  CountItems() const;
00674 
00675     inline T*   Head() const;
00677 
00678     inline T*   Tail() const;
00680 
00681     inline T*   ItemAt(int index) const;
00684 
00685     inline T&   operator [](int index) const;
00688 
00689     inline void operator +=(T* new_item);
00693 
00694     inline void operator -=(T* item);
00699 
00700     //----------------------------------------------------------------------------------------------
00701     private:
00702     //----------------------------------------------------------------------------------------------
00703     int         FindItemIndex( K key, bool at_or_before, bool at_or_after ) const;
00704     int         FindItemIndex( T* item, bool adding ) const;
00705     static bool MergeSort( T** from, T** to, int num_items );
00706                     // Returns true if the sorted items actually end up in the to buffer.
00707 
00708     //----------------------------------------------------------------------------------------------
00709     private:
00710     //----------------------------------------------------------------------------------------------
00711     T**         m_items;
00712     int         m_num_items;
00713     int         m_items_allocated;
00714     bool        m_items_allocated_on_stack;
00715 };
00716 
00717 
00718 //==================================================================================================
00719 template <class T, class K>
00720 class OwnedSortedList_t
00721 //==================================================================================================
00722 : public SortedList_t<T,K>
00724 {
00725     //----------------------------------------------------------------------------------------------
00726     public:
00727     //----------------------------------------------------------------------------------------------
00728     inline  OwnedSortedList_t();
00730 
00731     inline  OwnedSortedList_t( T** stack_buffer, int stack_buffer_num_items_allcoated );
00735 
00736             ~OwnedSortedList_t();
00738 };
00739 
00740 
00741 
00742 
00743 //==================================================================================================
00744 //==================================================================================================
00745 //===
00746 //=== Template function implementations: class Array_t
00747 //===
00748 //==================================================================================================
00749 //==================================================================================================
00750 template <class T>
00751 Array_t<T>::Array_t()
00752 {
00753     m_items = NULL;
00754     m_num_items = 0;
00755     m_items_allocated = 0;
00756     m_items_allocated_on_stack = false;
00757     m_head_index = 0;
00758 }
00759 
00760 
00761 template <class T>
00762 Array_t<T>::Array_t( T* stack_buffer, int stack_buffer_num_items_allcoated )
00763 {
00764     m_items = stack_buffer;
00765     m_num_items = 0;
00766     m_items_allocated = stack_buffer_num_items_allcoated;
00767     m_items_allocated_on_stack = true;
00768     m_head_index = 0;
00769 }
00770 
00771 
00772 template <class T>
00773 Array_t<T>::~Array_t()
00774 {
00775     if(m_items && !m_items_allocated_on_stack)
00776         delete[] m_items;
00777 }
00778 
00779 
00780 template <class T>
00781 void    
00782 Array_t<T>::InstallStackBuffer( T* stack_buffer, int stack_buffer_num_items_allcoated )
00783 {
00784     assert(m_items == NULL);
00785     m_items = stack_buffer;
00786     m_items_allocated = stack_buffer_num_items_allcoated;
00787     m_items_allocated_on_stack = true;
00788 }
00789 
00790 
00791 template <class T>
00792 T
00793 Array_t<T>::AddHead(const T& item)
00794 {
00795     assert(m_head_index < m_items_allocated || !m_items_allocated);
00796     assert(m_items_allocated >= m_num_items);
00797 
00798     if(m_num_items == m_items_allocated)
00799     {
00800         // Need to make room for the item: figure out how big to make the new list
00801         int new_items_allocated = m_items_allocated;
00802         if(new_items_allocated == 0)
00803             new_items_allocated = 16;
00804         else if(new_items_allocated < 128)
00805             new_items_allocated *= 2;
00806         else
00807             new_items_allocated += new_items_allocated / 2;
00808 
00809         // Allocate the new list
00810         T* new_list = new T[new_items_allocated];
00811 
00812         // Insert the new item as the head
00813         new_list[0] = item;
00814 
00815         // Copy the existing items
00816         int copy_items_from_head_index = m_num_items;
00817         if(copy_items_from_head_index > m_items_allocated - m_head_index)
00818             copy_items_from_head_index = m_items_allocated - m_head_index;
00819         memcpy( new_list+1, m_items+m_head_index, copy_items_from_head_index * sizeof(T) );
00820         memcpy( new_list+1+copy_items_from_head_index,
00821                 m_items,
00822                 (m_num_items - copy_items_from_head_index) * sizeof(T) );
00823 
00824         // Increment the item count
00825         m_num_items++;
00826 
00827         // Install the new list
00828         if(m_items && !m_items_allocated_on_stack)
00829             delete[] m_items;
00830         m_items = new_list;
00831         m_items_allocated = new_items_allocated;
00832         m_items_allocated_on_stack = false;
00833         m_head_index = 0;
00834         return item;
00835     }
00836 
00837     m_head_index--;
00838     if(m_head_index <= -1)
00839     {
00840         assert(m_head_index == -1);
00841         m_head_index = m_items_allocated-1;
00842     }
00843     m_items[m_head_index] = item;
00844     m_num_items++;
00845     return item;
00846 }
00847 
00848 
00849 template <class T>
00850 T
00851 Array_t<T>::AddTail(const T& item)
00852 {
00853     assert(m_head_index < m_items_allocated || !m_items_allocated);
00854     assert(m_items_allocated >= m_num_items);
00855 
00856     if(m_num_items == m_items_allocated)
00857     {
00858         // Need to make room for the item: figure out how big to make the new list
00859         int new_items_allocated = m_items_allocated;
00860         if(new_items_allocated == 0)
00861             new_items_allocated = 16;
00862         else if(new_items_allocated < 128)
00863             new_items_allocated *= 2;
00864         else
00865             new_items_allocated += new_items_allocated / 2;
00866 
00867         // Allocate the new list
00868         T* new_list = new T[new_items_allocated];
00869 
00870         // Copy the existing items
00871         int copy_items_from_head_index = m_num_items;
00872         if(copy_items_from_head_index > m_items_allocated - m_head_index)
00873             copy_items_from_head_index = m_items_allocated - m_head_index;
00874         memcpy( new_list, m_items+m_head_index, copy_items_from_head_index * sizeof(T) );
00875         memcpy( new_list+copy_items_from_head_index,
00876                 m_items,
00877                 (m_num_items - copy_items_from_head_index) * sizeof(T) );
00878 
00879         // Add the new item as the tail
00880         new_list[m_num_items] = item;
00881 
00882         // Increment the item count
00883         m_num_items++;
00884 
00885         // Install the new list
00886         if(m_items && !m_items_allocated_on_stack)
00887             delete[] m_items;
00888         m_items = new_list;
00889         m_items_allocated = new_items_allocated;
00890         m_items_allocated_on_stack = false;
00891         m_head_index = 0;
00892         return item;
00893     }
00894 
00895     int add_index;
00896     #if TARGET_CPU_FAST_INTEGER_MOD
00897         add_index = (m_head_index + m_num_items) % m_items_allocated;
00898     #else
00899         add_index = m_head_index + m_num_items;
00900         if(add_index >= m_items_allocated)
00901             add_index -= m_items_allocated;
00902     #endif
00903 
00904     m_items[add_index] = item;
00905     m_num_items++;
00906     return item;
00907 }
00908 
00909 
00910 template <class T>
00911 T
00912 Array_t<T>::AddItemAt( const T& item, int index )
00913 {
00914     int head_segment_count;
00915     int tail_segment_count;
00916 
00917     if(index == -1)
00918         index = m_num_items;
00919     assert(m_head_index < m_items_allocated || !m_items_allocated);
00920     assert(m_items_allocated >= m_num_items);
00921     assert(index >= 0 && index <= m_num_items);
00922 
00923     if(m_num_items == m_items_allocated)
00924     {
00925         // Need to make room for the item: figure out how big to make the new list
00926         int new_items_allocated = m_items_allocated;
00927         if(new_items_allocated == 0)
00928             new_items_allocated = 16;
00929         else if(new_items_allocated < 128)
00930             new_items_allocated *= 2;
00931         else
00932             new_items_allocated += new_items_allocated / 2;
00933 
00934         // Allocate the new list
00935         T* new_list = new T[new_items_allocated];
00936 
00937         // Assemble the new list
00938         head_segment_count = m_items_allocated - m_head_index;
00939         tail_segment_count = m_num_items - head_segment_count;
00940         if(index <= head_segment_count)
00941         {
00942             // Item insertion will occur in the segment starting with the head index and extending
00943             // to the end of the allocated item list
00944             memcpy( new_list, m_items+m_head_index, index * sizeof(T) );
00945             new_list[index] = item;
00946             memcpy( new_list+index+1,
00947                     m_items+m_head_index+index,
00948                     (head_segment_count-index) * sizeof(T) );
00949             memcpy( new_list+head_segment_count+1, m_items, tail_segment_count * sizeof(T) );
00950         }
00951         else
00952         {
00953             // Item insertion will occur in the segment starting with the beginning of the allocated
00954             // item list and extending to the tail item
00955             memcpy( new_list, m_items+m_head_index, head_segment_count * sizeof(T) );
00956             memcpy( new_list+head_segment_count, m_items, (index-head_segment_count) * sizeof(T) );
00957             new_list[index] = item;
00958             memcpy( new_list+index+1,
00959                     m_items+index-head_segment_count,
00960                     (m_num_items-index) * sizeof(T) );
00961         }
00962 
00963         // Increment the item count
00964         m_num_items++;
00965 
00966         // Install the new list
00967         if(m_items && !m_items_allocated_on_stack)
00968             delete[] m_items;
00969         m_items = new_list;
00970         m_items_allocated = new_items_allocated;
00971         m_items_allocated_on_stack = false;
00972         m_head_index = 0;
00973         return item;
00974     }
00975 
00976     if(index == 0)
00977         return AddHead(item);
00978     if(index == m_num_items)
00979         return AddTail(item);
00980 
00981     int array_index;
00982 
00983     // Shifting the head, the number of items to be moved is index
00984     // Shifting the tail, the number of items to be moved is m_num_items - index
00985     if(index < m_num_items - index)
00986     {
00987         // It is more efficient to shift the head back one to make room
00988 
00989         // Possible scenarios:
00990         // H****I******T-------
00991         // -H****I******T------
00992         // ----H****I******T---
00993         // ------H****I******T-
00994         // -------H****I******T
00995         // T-------H****I******
00996         // *T-------H****I*****
00997         // **T-------H****I****
00998         // *****T-------H****I*
00999         // ******T-------H****I
01000         // I******T-------H****
01001         // *I******T-------H***
01002         // ***I******T-------H*
01003         // ****I******T-------H
01004 
01005         #if TARGET_CPU_FAST_INTEGER_MOD
01006             array_index = (m_head_index + index - 1) % m_items_allocated;
01007         #else
01008             array_index = m_head_index + index - 1;
01009             if(array_index >= m_items_allocated)
01010                 array_index -= m_items_allocated;
01011         #endif
01012 
01013         if(m_head_index == 0)
01014         {
01015             // 00000000001111111111
01016             // 01234567890123456789
01017             // H****I******T-------
01018             // H1234z******T------- m_head_index = 0, index = 5, array_index = 4
01019             // 1234Iz******T------H
01020             m_head_index = m_items_allocated-1;
01021             m_items[m_head_index] = m_items[0];
01022             memmove( m_items, m_items+1, array_index * sizeof(T) );
01023             m_items[array_index] = item;
01024             m_num_items++;
01025             return item;
01026         }
01027 
01028         else if(m_head_index <= array_index)
01029         {
01030             // 00000000001111111111
01031             // 01234567890123456789
01032             // -H****I******T------
01033             // -H1234z******T------ m_head_index = 1, index = 5, array_index = 5
01034             // H1234Iz******T------
01035 
01036             // ----H****I******T---
01037             // ----H1234z******T--- m_head_index = 4, index = 5, array_index = 8
01038             // ---H1234Iz******T---
01039 
01040             // ------H****I******T-
01041             // ------H1234z******T- m_head_index = 6, index = 5, array_index = 10
01042             // -----H1234Iz******T-
01043 
01044             // -------H****I******T
01045             // -------H1234z******T m_head_index = 7, index = 5, array_index = 11
01046             // ------H1234Iz******T
01047 
01048             // T-------H****I******
01049             // T-------H1234z****** m_head_index = 8, index = 5, array_index = 12
01050             // T------H1234iz******
01051 
01052             // *T-------H****I*****
01053             // *T-------H1234z***** m_head_index = 9, index = 5, array_index = 13
01054             // *T------H1234iz*****
01055 
01056             // **T-------H****I****
01057             // **T-------H1234z**** m_head_index = 10, index = 5, array_index = 14
01058             // **T------H1234Iz****
01059 
01060             // *****T-------H****I*
01061             // *****T-------H1234z* m_head_index = 13, index = 5, array_index = 17
01062             // *****T------H1234Iz*
01063 
01064             // ******T-------H****I
01065             // ******T-------H1234z m_head_index = 14, index = 5, array_index = 18
01066             // ******T------H1234Iz
01067 
01068             // I******T-------H****
01069             // z******T-------H1234 m_head_index = 15, index = 5, array_index = 19
01070             // z******T------H1234I
01071             memmove( m_items+m_head_index-1, m_items+m_head_index, index * sizeof(T) );
01072             m_head_index--;
01073             m_items[array_index] = item;
01074             m_num_items++;
01075             return item;
01076         }
01077 
01078         else
01079         {
01080             // 00000000001111111111
01081             // 01234567890123456789
01082             // *I******T-------H***
01083             // 4z******T-------H123 m_head_index = 16, index = 5, array_index = 0
01084             // Iz******T------H1234
01085 
01086             // ***I******T-------H*
01087             // 234z******T-------H1 m_head_index = 18, index = 5, array_index = 2
01088             // 34Iz******T------H12
01089 
01090             // ****I******T-------H
01091             // 1234z******T-------H m_head_index = 19, index = 5, array_index = 3
01092             // 234Iz******T------H1
01093             memmove(    m_items+m_head_index-1,
01094                         m_items+m_head_index,
01095                         (m_items_allocated-m_head_index) * sizeof(T) );
01096             m_head_index--;
01097             m_items[m_items_allocated-1] = m_items[0];
01098             memmove(    m_items,
01099                         m_items+1,
01100                         array_index * sizeof(T) );
01101             m_items[array_index] = item;
01102             m_num_items++;
01103             return item;
01104         }
01105     }
01106     else
01107     {
01108         // It is more efficient to shift the tail forward one to make room
01109 
01110         // Possible scenarios:
01111         // H******I****T-------
01112         // -H******I****T------
01113         // ----H******I****T---
01114         // ------H******I****T-
01115         // -------H******I****T
01116         // T-------H******I****
01117         // *T-------H******I***
01118         // **T-------H******I**
01119         // ***T-------H******I*
01120         // ****T-------H******I
01121         // I****T-------H******
01122         // *I****T-------H*****
01123         // *****I****T-------H*
01124         // ******I****T-------H
01125 
01126         #if TARGET_CPU_FAST_INTEGER_MOD
01127             array_index = (m_head_index + index) % m_items_allocated;
01128         #else
01129             array_index = m_head_index + index;
01130             if(array_index >= m_items_allocated)
01131                 array_index -= m_items_allocated;
01132         #endif
01133 
01134         if(m_head_index + m_num_items < m_items_allocated)
01135         {
01136             // 00000000001111111111
01137             // 01234567890123456789
01138             // H******I****T-------
01139             // H123456z****T------- m_head_index = 0, index = 7, array_index = 7
01140             // H123456Iz****T------
01141 
01142             // -H******I****T------
01143             // -H123456z****T------ m_head_index = 1, index = 7, array_index = 8
01144             // -H123456Iz****T-----
01145 
01146             // ----H******I****T---
01147             // ----H123456z****T--- m_head_index = 4, index = 7, array_index = 11
01148             // ----H123456Iz****T--
01149 
01150             // ------H******I****T-
01151             // ------H123456z****T- m_head_index = 6, index = 7, array_index = 13
01152             // ------H123456Iz****T
01153             memmove(    m_items+array_index+1,
01154                         m_items+array_index,
01155                         (m_num_items-index) * sizeof(T) );
01156             m_items[array_index] = item;
01157             m_num_items++;
01158             return item;
01159         }
01160 
01161         else if(array_index > m_head_index)
01162         {
01163             // 00000000001111111111
01164             // 01234567890123456789
01165             // -------H******I****T
01166             // -------H123456z****T m_head_index = 7, index = 7, array_index = 14
01167             // T------H123456Iz****
01168 
01169             // T-------H******I****
01170             // T-------H123456z**** m_head_index = 8, index = 7, array_index = 15
01171             // *T------H123456Iz***
01172 
01173             // *T-------H******I***
01174             // *T-------H123456z*** m_head_index = 9, index = 7, array_index = 16
01175             // **T------H123456Iz**
01176 
01177             // **T-------H******I**
01178             // **T-------H123456z** m_head_index = 10, index = 7, array_index = 17
01179             // ***T------H123456Iz*
01180 
01181             // ***T-------H******I*
01182             // ***T-------H123456z* m_head_index = 11, index = 7, array_index = 18
01183             // ****T------H123456Iz
01184 
01185             // ****T-------H******I
01186             // ****T-------H123456z m_head_index = 12, index = 7, array_index = 19
01187             // z****T------H123456I
01188             memmove(    m_items+1,
01189                         m_items,
01190                         (m_head_index + m_num_items - m_items_allocated) * sizeof(T) );
01191             m_items[0] = m_items[m_items_allocated-1];
01192             memmove(    m_items+array_index+1,
01193                         m_items+array_index,
01194                         ( m_items_allocated - (array_index+1) ) * sizeof(T) );
01195             m_items[array_index] = item;
01196             m_num_items++;
01197             return item;
01198         }
01199 
01200         else
01201         {
01202             // 00000000001111111111
01203             // 01234567890123456789
01204             // I****T-------H******
01205             // z****T-------H123456 m_head_index = 13, index = 7, array_index = 0
01206             // Iz****T------H123456
01207 
01208             // *I****T-------H*****
01209             // 6z****T-------H12345 m_head_index = 14, index = 7, array_index = 1
01210             // 6Iz****T------H12345
01211 
01212             // *****I****T-------H*
01213             // 23456z****T-------H1 m_head_index = 18, index = 7, array_index = 5
01214             // 23456Iz****T------H1
01215 
01216             // ******I****T-------H
01217             // 123456z****T-------H m_head_index = 19, index = 7, array_index = 6
01218             // 123456Iz****T------H
01219             memmove(    m_items+array_index+1,
01220                         m_items+array_index,
01221                         (m_num_items-index) * sizeof(T) );
01222             m_items[array_index] = item;
01223             m_num_items++;
01224             return item;
01225         }
01226     }
01227 }
01228 
01229 
01230 template <class T>
01231 T
01232 Array_t<T>::RemoveHead()
01233 {
01234     assert(m_num_items);
01235     assert(m_head_index >= 0 && m_head_index < m_items_allocated);
01236 
01237     T* item = &m_items[m_head_index];
01238     m_num_items--;
01239     #if TARGET_CPU_FAST_INTEGER_MOD
01240         m_head_index = (m_head_index + 1) % m_items_allocated;
01241     #else
01242         m_head_index++;
01243         if(m_head_index == m_items_allocated)
01244             m_head_index = 0;
01245     #endif
01246 
01247     return *item;
01248 }
01249 
01250 
01251 template <class T>
01252 T
01253 Array_t<T>::RemoveTail()
01254 {
01255     assert(m_num_items);
01256     assert(m_head_index >= 0 && m_head_index < m_items_allocated);
01257 
01258     m_num_items--;
01259     int tail_index;
01260     #if TARGET_CPU_FAST_INTEGER_MOD
01261         tail_index = (m_head_index + m_num_items) % m_items_allocated;
01262     #else
01263         tail_index = m_head_index + m_num_items;
01264         if(tail_index >= m_items_allocated)
01265             tail_index -= m_items_allocated;
01266     #endif
01267     return m_items[tail_index];
01268 }
01269 
01270 
01271 template <class T>
01272 T
01273 Array_t<T>::RemoveItemAt(int index)
01274 {
01275     assert(index >= 0 && index < m_num_items);
01276     assert(m_head_index >= 0 && m_head_index < m_items_allocated);
01277 
01278     int array_index;
01279     #if TARGET_CPU_FAST_INTEGER_MOD
01280         array_index = (m_head_index + index) % m_items_allocated;
01281     #else
01282         array_index = m_head_index + index;
01283         if(array_index >= m_items_allocated)
01284             array_index -= m_items_allocated;
01285     #endif
01286     T item = m_items[array_index];
01287 
01288     // Shifting the head, the number of items to be moved is index
01289     // Shifting the tail, the number of items to be moved is m_num_items - (index+1)
01290 
01291     if (index < m_num_items - (index+1) )
01292     {
01293         // It is more efficient to shift the head forward one
01294 
01295         // Possible scenarios:
01296         // H****R******T-------
01297         // ----H****R******T---
01298         // -------H****R******T
01299         // T-------H****R******
01300         // *****T-------H****R*
01301         // ******T-------H****R
01302         // R******T-------H****
01303         // *R******T-------H***
01304         // ***R******T-------H*
01305         // ****R******T-------H
01306 
01307         if(m_head_index <= array_index)
01308         {
01309             // H****R******T-------
01310             // ----H****R******T---
01311             // -------H****R******T
01312             // T-------H****R******
01313             // *****T-------H****R*
01314             // ******T-------H****R
01315             memmove( m_items+m_head_index+1, m_items+m_head_index, index * sizeof(T) );
01316             #if TARGET_CPU_FAST_INTEGER_MOD
01317                 m_head_index = (m_head_index + 1) % m_items_allocated;
01318             #else
01319                 m_head_index++;
01320                 if(m_head_index == m_items_allocated)
01321                     m_head_index = 0;
01322             #endif
01323             m_num_items--;
01324             return item;
01325         }
01326 
01327         else
01328         {
01329             // R******T-------H****
01330             // *R******T-------H***
01331             // ***R******T-------H*
01332             // ****R******T-------H
01333             memmove( m_items+1, m_items, array_index * sizeof(T) );
01334             m_items[0] = m_items[m_items_allocated-1];
01335             memmove(    m_items+m_head_index+1,
01336                         m_items+m_head_index,
01337                         ( m_items_allocated-(m_head_index+1) ) * sizeof(T) );
01338             #if TARGET_CPU_FAST_INTEGER_MOD
01339                 m_head_index = (m_head_index + 1) % m_items_allocated;
01340             #else
01341                 m_head_index++;
01342                 if(m_head_index == m_items_allocated)
01343                     m_head_index = 0;
01344             #endif
01345             m_num_items--;
01346             return item;
01347         }
01348     }
01349     else
01350     {
01351         // It is more efficient to shift the tail back one
01352 
01353         // Possible scenarios:
01354         // H******R****T-------
01355         // ----H******R****T---
01356         // -------H******R****T
01357         // T-------H******R****
01358         // *T-------H******R***
01359         // ***T-------H******R*
01360         // ****T-------H******R
01361         // R****T-------H******
01362         // *R****T-------H*****
01363         // ******R****T-------H
01364 
01365         int tail_array_index;
01366         #if TARGET_CPU_FAST_INTEGER_MOD
01367             tail_array_index = (m_head_index + m_num_items - 1) % m_items_allocated;
01368         #else
01369             tail_array_index = m_head_index + m_num_items - 1;
01370             if(tail_array_index >= m_items_allocated)
01371                 tail_array_index -= m_items_allocated;
01372         #endif
01373         if(tail_array_index >= array_index)
01374         {
01375             // H******R****T-------
01376             // ----H******R****T---
01377             // -------H******R****T
01378             // R****T-------H******
01379             // *R****T-------H*****
01380             // ******R****T-------H
01381             memmove(    m_items+array_index,
01382                         m_items+array_index+1,
01383                         ( m_num_items - (index+1) ) * sizeof(T) );
01384             m_num_items--;
01385             return item;
01386         }
01387 
01388         else
01389         {
01390             // T-------H******R****
01391             // *T-------H******R***
01392             // ***T-------H******R*
01393             // ****T-------H******R
01394             memmove(    m_items+array_index,
01395                         m_items+array_index+1,
01396                         ( m_items_allocated - (array_index+1) ) * sizeof(T) );
01397             m_items[m_items_allocated-1] = m_items[0];
01398             memmove( m_items, m_items+1, tail_array_index * sizeof(T) );
01399             m_num_items--;
01400             return item;
01401         }
01402     }
01403 }
01404 
01405 
01406 template <class T>
01407 inline int
01408 Array_t<T>::CountItems() const
01409 {
01410     return m_num_items;
01411 }
01412 
01413 
01414 template <class T>
01415 inline int
01416 Array_t<T>::AllocatedItems() const
01417 {
01418     return m_items_allocated;
01419 }
01420 
01421 
01422 template <class T>
01423 inline void
01424 Array_t<T>::SetNumValidItems(int count)
01425 {
01426     assert(count <= m_num_items);
01427     m_num_items = count;
01428 }
01429 
01430 
01431 template <class T>
01432 void
01433 Array_t<T>::GrowIfNeeded( int min_allocated_items, bool expect_more_growth )
01434 {
01435     if(m_items_allocated >= min_allocated_items)
01436         return;
01437 
01438     // Figure out how many items to allocate
01439     int new_items_allocated = min_allocated_items;
01440     if(expect_more_growth)
01441     {
01442         if(new_items_allocated == 0)
01443             new_items_allocated = 16;
01444         else if(new_items_allocated < 128)
01445             new_items_allocated *= 2;
01446         else
01447             new_items_allocated += new_items_allocated / 2;
01448     }
01449 
01450     // Allocate the new list
01451     T* new_list = new T[new_items_allocated];
01452 
01453     // Copy the existing items
01454     int copy_items_from_head_index = m_num_items;
01455     if(copy_items_from_head_index > m_items_allocated - m_head_index)
01456         copy_items_from_head_index = m_items_allocated - m_head_index;
01457     memcpy( new_list, m_items+m_head_index, copy_items_from_head_index * sizeof(T) );
01458     memcpy( new_list+copy_items_from_head_index,
01459             m_items,
01460             (m_num_items - copy_items_from_head_index) * sizeof(T) );
01461 
01462     // Install the new list
01463     if(m_items && !m_items_allocated_on_stack)
01464         delete[] m_items;
01465     m_items = new_list;
01466     m_items_allocated = new_items_allocated;
01467     m_items_allocated_on_stack = false;
01468     m_head_index = 0;
01469 }
01470 
01471 
01472 
01473 template <class T>
01474 inline T
01475 Array_t<T>::Head() const
01476 {
01477     if(m_num_items == 0)
01478         return NULL;
01479     return m_items[m_head_index];
01480 }
01481 
01482 
01483 template <class T>
01484 inline T
01485 Array_t<T>::Tail() const
01486 {
01487     if(m_num_items == 0)
01488         return NULL;
01489     int tail_array_index;
01490     #if TARGET_CPU_FAST_INTEGER_MOD
01491         tail_array_index = (m_head_index + m_num_items - 1) % m_items_allocated;
01492     #else
01493         tail_array_index = m_head_index + m_num_items - 1;
01494         if(tail_array_index >= m_items_allocated)
01495             tail_array_index -= m_items_allocated;
01496     #endif
01497     return m_items[tail_array_index];
01498 }
01499 
01500 
01501 template <class T>
01502 inline T
01503 Array_t<T>::ItemAt(int index) const
01504 {
01505     assert(index >= 0 && index < m_num_items);
01506     int array_index;
01507     #if TARGET_CPU_FAST_INTEGER_MOD
01508         array_index = (m_head_index + index) % m_items_allocated;
01509     #else
01510         array_index = m_head_index + index;
01511         if(array_index >= m_items_allocated)
01512             array_index -= m_items_allocated;
01513     #endif
01514     return m_items[array_index];
01515 }
01516 
01517 
01518 template <class T>
01519 inline T&
01520 Array_t<T>::operator [](int index) const
01521 {
01522     assert(index >= 0 && index <= m_num_items);
01523     if(index == m_num_items)
01524         const_cast<Array_t<T>*>(this)->GrowIfNeeded( m_num_items+1, true );
01525 
01526     int array_index;
01527     #if TARGET_CPU_FAST_INTEGER_MOD
01528         array_index = (m_head_index + index) % m_items_allocated;
01529     #else
01530         array_index = m_head_index + index;
01531         if(array_index >= m_items_allocated)
01532             array_index -= m_items_allocated;
01533     #endif
01534     return m_items[array_index];
01535 }
01536 
01537 
01538 template <class T>
01539 inline void
01540 Array_t<T>::operator +=(const T& item)
01541 {
01542     AddTail(item);
01543 }
01544 
01545 
01546 
01547 
01548 //==================================================================================================
01549 //==================================================================================================
01550 //===
01551 //=== Template function implementations: class List_t
01552 //===
01553 //==================================================================================================
01554 //==================================================================================================
01555 template <class T>
01556 inline
01557 List_t<T>::List_t()
01558 { }
01559 
01560 
01561 template <class T>
01562 inline
01563 List_t<T>::List_t( T** stack_buffer, int stack_buffer_num_items_allcoated )
01564 : Array_t<T*>( stack_buffer, stack_buffer_num_items_allcoated )
01565 { }
01566 
01567 
01568 template <class T>
01569 T*
01570 List_t<T>::RemoveItem(T* item)
01571 {
01572     for(int i = 0; i < Array_t<T*>::CountItems(); i++)
01573     {
01574         if(Array_t<T*>::ItemAt(i) == item)
01575         {
01576             Array_t<T*>::RemoveItemAt(i);
01577             return item;
01578         }
01579     }
01580     debug_error("The specified item was not found");
01581     return NULL;
01582 }
01583 
01584 
01585 template <class T>
01586 int
01587 List_t<T>::IndexOfItem(T* item)
01588 {
01589     for(int i = 0; i < Array_t<T*>::CountItems(); i++)
01590         if(Array_t<T*>::ItemAt(i) == item)
01591             return i;
01592     return -1;
01593 }
01594 
01595 
01596 template <class T>
01597 inline T&
01598 List_t<T>::operator [](int index) const
01599 {
01600     return *Array_t<T*>::ItemAt(index);
01601 }
01602 
01603 
01604 template <class T>
01605 inline void
01606 List_t<T>::operator -=(T* item)
01607 {
01608     RemoveItem(item);
01609 }
01610 
01611 
01612 
01613 
01614 //==================================================================================================
01615 //==================================================================================================
01616 //===
01617 //=== Template function implementations: class OwnedList_t
01618 //===
01619 //==================================================================================================
01620 //==================================================================================================
01621 template <class T>
01622 inline
01623 OwnedList_t<T>::OwnedList_t()
01624 { }
01625 
01626 
01627 template <class T>
01628 inline
01629 OwnedList_t<T>::OwnedList_t( T** stack_buffer, int stack_buffer_num_items_allcoated )
01630 : List_t<T*>( stack_buffer, stack_buffer_num_items_allcoated )
01631 { }
01632 
01633 
01634 template <class T>
01635 OwnedList_t<T>::~OwnedList_t()
01636 {
01637     for(int i=0; i<List_t<T>::CountItems(); i++)
01638         delete List_t<T>::ItemAt(i);
01639 }
01640 
01641 
01642 
01643 
01644 //==================================================================================================
01645 //==================================================================================================
01646 //===
01647 //=== Template function implementations: class LinkedList_t
01648 //===
01649 //==================================================================================================
01650 //==================================================================================================
01651 template <class T>
01652 inline
01653 LinkedList_t<T>::LinkedList_t()
01654 {
01655     m_head = NULL;
01656     m_tail = NULL;
01657     m_num_items = 0;
01658 }
01659 
01660 
01661 template <class T>
01662 T*
01663 LinkedList_t<T>::AddHead(T* item)
01664 {
01665     assert(!item->m_next);
01666     assert(!item->m_prev);
01667     if(m_num_items == 0)
01668     {
01669         m_head = item;
01670         m_tail = item;
01671         m_num_items = 1;
01672         return item;
01673     }
01674     assert(!static_cast<LinkedListNode_t<T>*>(m_head)->m_prev);
01675     assert(static_cast<LinkedListNode_t<T>*>(m_head) != item);
01676     m_head->m_prev = item;
01677     item->m_next = m_head;
01678     m_head = item;
01679     m_num_items++;
01680     return item;
01681 }
01682 
01683 
01684 template <class T>
01685 T*
01686 LinkedList_t<T>::AddTail(T* item)
01687 {
01688     assert(!static_cast<LinkedListNode_t<T>*>(item)->m_next);
01689     assert(!static_cast<LinkedListNode_t<T>*>(item)->m_prev);
01690     if(m_num_items == 0)
01691     {
01692         m_head = item;
01693         m_tail = item;
01694         m_num_items = 1;
01695         return item;
01696     }
01697     assert(!static_cast<LinkedListNode_t<T>*>(m_tail)->m_next);
01698     assert(static_cast<LinkedListNode_t<T>*>(m_tail) != item);
01699     static_cast<LinkedListNode_t<T>*>(m_tail)->m_next = item;
01700     static_cast<LinkedListNode_t<T>*>(item)->m_prev = m_tail;
01701     m_tail = item;
01702     m_num_items++;
01703     return item;
01704 }
01705 
01706 
01707 template <class T>
01708 T*
01709 LinkedList_t<T>::AddItemBefore( T* new_item, T* after_item )
01710 {
01711     assert(new_item && after_item);
01712     if(after_item == m_head)
01713     {
01714         AddHead(new_item);
01715         return new_item;
01716     }
01717     assert(!static_cast<LinkedListNode_t<T>*>(new_item)->m_next);
01718     assert(!static_cast<LinkedListNode_t<T>*>(new_item)->m_prev);
01719     assert(m_num_items);
01720     static_cast<LinkedListNode_t<T>*>(new_item)->m_prev =
01721                                             static_cast<LinkedListNode_t<T>*>(after_item)->m_prev;
01722     static_cast<LinkedListNode_t<T>*>(new_item)->m_next = after_item;
01723     static_cast<LinkedListNode_t<T>*>(new_item)->m_prev->m_next = new_item;
01724     after_item->m_prev = new_item;
01725     m_num_items++;
01726     return new_item;
01727 }
01728 
01729 
01730 template <class T>
01731 T*
01732 LinkedList_t<T>::AddItemAfter( T* before_item, T* new_item )
01733 {
01734     assert(before_item && new_item);
01735     if(before_item == m_tail)
01736     {
01737         AddTail(new_item);
01738         return new_item;
01739     }
01740     assert(!new_item->m_next);
01741     assert(!new_item->m_prev);
01742     assert(m_num_items);
01743     new_item->m_prev = before_item;
01744     new_item->m_next = before_item->m_next;
01745     before_item->m_next = new_item;
01746     new_item->m_next->m_prev = new_item;
01747     m_num_items++;
01748     return new_item;
01749 }
01750 
01751 
01752 template <class T>
01753 T*
01754 LinkedList_t<T>::RemoveHead()
01755 {
01756     assert(m_num_items && m_head);
01757     LinkedListNode_t<T>* item = m_head;
01758     assert(!item->m_prev);
01759     if(m_num_items == 1)
01760     {
01761         assert(m_head == m_tail);
01762         assert(!item->m_next);
01763         assert(!item->m_prev);
01764         m_head = NULL;
01765         m_tail = NULL;
01766         m_num_items = 0;
01767         return static_cast<T*>(item);
01768     }
01769     m_head = static_cast<T*>(item->m_next);
01770     static_cast<LinkedListNode_t<T>*>(m_head)->m_prev = NULL;
01771     item->m_next = NULL;
01772     m_num_items--;
01773     return static_cast<T*>(item);
01774 }
01775 
01776 
01777 template <class T>
01778 T*
01779 LinkedList_t<T>::RemoveTail()
01780 {
01781     assert(m_num_items && m_tail);
01782     LinkedListNode_t<T>* item = m_tail;
01783     assert(!item->m_next);
01784     if(m_num_items == 1)
01785     {
01786         assert(m_head == m_tail);
01787         assert(!item->m_prev);
01788         m_head = NULL;
01789         m_tail = NULL;
01790         m_num_items = 0;
01791         return static_cast<T*>(item);
01792     }
01793     m_tail = static_cast<T*>(item->m_prev);
01794     static_cast<LinkedListNode_t<T>*>(m_tail)->m_next = NULL;
01795     item->m_prev = NULL;
01796     m_num_items--;
01797     return static_cast<T*>(item);
01798 }
01799 
01800 
01801 template <class T>
01802 T*
01803 LinkedList_t<T>::RemoveItem(T* item)
01804 {
01805     assert(m_num_items);
01806     if(item == m_head)
01807         return RemoveHead();
01808     if(item == m_tail)
01809         return RemoveTail();
01810     assert(m_head && (m_head != m_tail) && m_tail);
01811     assert(     static_cast<LinkedListNode_t<T>*>(item)->m_prev
01812             &&  static_cast<LinkedListNode_t<T>*>(item)->m_next);
01813     #if DEBUG
01814         LinkedListNode_t<T>* check_item_fwd = static_cast<LinkedListNode_t<T>*>(m_head)->m_next;
01815         LinkedListNode_t<T>* check_item_back = static_cast<LinkedListNode_t<T>*>(m_tail)->m_prev;
01816         while(check_item_fwd)
01817         {
01818             assert(check_item_back);
01819             if(check_item_fwd == item)
01820                 break;
01821             if(check_item_fwd == check_item_back)
01822                 break;
01823             if(check_item_back == item)
01824                 break;
01825 
01826             check_item_fwd = check_item_fwd->m_next;
01827             if(check_item_fwd == check_item_back)
01828                 break;
01829             check_item_back = check_item_back->m_prev;
01830         }
01831 
01832         assert(check_item_fwd == item || check_item_back == item);
01833         // Otherwise, the item was not in the list
01834     #endif
01835     static_cast<LinkedListNode_t<T>*>(static_cast<LinkedListNode_t<T>*>(item)->m_prev)->m_next =
01836                                                     static_cast<LinkedListNode_t<T>*>(item)->m_next;
01837     static_cast<LinkedListNode_t<T>*>(static_cast<LinkedListNode_t<T>*>(item)->m_next)->m_prev =
01838                                                     static_cast<LinkedListNode_t<T>*>(item)->m_prev;
01839     static_cast<LinkedListNode_t<T>*>(item)->m_prev = NULL;
01840     static_cast<LinkedListNode_t<T>*>(item)->m_next = NULL;
01841     m_num_items--;
01842     return item;
01843 }
01844 
01845 
01846 template <class T>
01847 inline int
01848 LinkedList_t<T>::CountItems() const
01849 {
01850     return m_num_items;
01851 }
01852 
01853 
01854 template <class T>
01855 inline T*
01856 LinkedList_t<T>::Head() const
01857 {
01858     return m_head;
01859 }
01860 
01861 
01862 template <class T>
01863 inline T*
01864 LinkedList_t<T>::Tail() const
01865 {
01866     return m_tail;
01867 }
01868 
01869 
01870 template <class T>
01871 inline void
01872 LinkedList_t<T>::operator +=(T* item)
01873 {
01874     AddTail(item);
01875 }
01876 
01877 
01878 template <class T>
01879 inline void
01880 LinkedList_t<T>::operator -=(T* item)
01881 {
01882     RemoveItem(item);
01883 }
01884 
01885 
01886 template <class T>
01887 void
01888 LinkedList_t<T>::SortSmallOrSlow()
01889 {
01890     if(m_num_items < 2)
01891         return;
01892 
01893     T* first_unsorted = static_cast<T*>(m_head->m_next);
01894     while(first_unsorted)
01895     {
01896         if( (*first_unsorted) < *( static_cast<T*>(first_unsorted->m_prev) ) )
01897         {
01898             T* reposition_item = first_unsorted;
01899             T* check_pos = static_cast<T*>(first_unsorted->m_prev->m_prev);
01900             // first_unsorted->m_prev cannot be NULL, but check_pos could be NULL
01901             first_unsorted = static_cast<T*>(first_unsorted->m_next);
01902             RemoveItem(reposition_item);
01903 
01904             // Find where to reposition the item to
01905             while(check_pos)
01906             {
01907                 if( (*reposition_item) < (*check_pos) )
01908                     check_pos = static_cast<T*>(check_pos->m_prev);
01909                 else
01910                 {
01911                     AddItemAfter( check_pos, reposition_item );
01912                     break;
01913                 }
01914             }
01915             if(!check_pos)
01916                 AddHead(reposition_item);
01917         }
01918         else
01919             first_unsorted = static_cast<T*>(first_unsorted->m_next);
01920     }
01921 }
01922 
01923 
01924 
01925 
01926 //==================================================================================================
01927 //==================================================================================================
01928 //===
01929 //=== Template function implementations: class LinkedListNode_t
01930 //===
01931 //==================================================================================================
01932 //==================================================================================================
01933 template <class T>
01934 inline
01935 LinkedListNode_t<T>::LinkedListNode_t()
01936 {
01937     m_next = NULL;
01938     m_prev = NULL;
01939 }
01940 
01941 
01942 template <class T>
01943 inline T*
01944 LinkedListNode_t<T>::Next() const
01945 {
01946     assert( (!m_next) || m_next->m_prev == this );
01947     return static_cast<T*>(m_next);
01948 }
01949 
01950 
01951 template <class T>
01952 inline T*
01953 LinkedListNode_t<T>::Prev() const
01954 {
01955     assert( (!m_prev) || m_prev->m_next == this );
01956     return static_cast<T*>(m_prev);
01957 }
01958 
01959 
01960 
01961 
01962 //==================================================================================================
01963 //==================================================================================================
01964 //===
01965 //=== Template function implementations: class OwnedLinkedList_t
01966 //===
01967 //==================================================================================================
01968 //==================================================================================================
01969 template <class T>
01970 OwnedLinkedList_t<T>::~OwnedLinkedList_t()
01971 {
01972     while( LinkedList_t<T>::Tail() )
01973         delete LinkedList_t<T>::RemoveTail();
01974 }
01975 
01976 
01977 
01978 
01979 //==================================================================================================
01980 //==================================================================================================
01981 //===
01982 //=== Template function implementations: class BTree_t
01983 //===
01984 //==================================================================================================
01985 //==================================================================================================
01986 template <class T, class K>
01987 inline
01988 BTree_t<T,K>::BTree_t()
01989 {
01990     m_root = NULL;
01991     m_num_items = 0;
01992 }
01993 
01994 
01995 template <class T, class K>
01996 T*
01997 BTree_t<T,K>::FindItem(K key) const
01998 {
01999     BTreeNode_t<T,K>* node = static_cast<BTreeNode_t<T,K>*>( const_cast<T*>(m_root) );
02000     for(;;)
02001     {
02002         if(!node)
02003             return NULL;
02004 
02005         int compare = static_cast<T*>(node)->Compare(key);
02006 
02007         if(compare < 0)
02008             node = node->m_next;    // node comes before key
02009         else if(compare > 0)
02010             node = node->m_prev;    // node comes after key
02011         else
02012         {
02013             // Found a matching item.  Return the one closest to the head with a matching key.
02014             for(;;)
02015             {
02016                 BTreeNode_t<T,K>* prev = node->Prev();
02017                 if(prev && static_cast<T*>(prev)->Compare(key) == 0)
02018                     node = prev;
02019                 else
02020                     return static_cast<T*>(node);
02021             }
02022         }
02023     }
02024 }
02025 
02026 
02027 template <class T, class K>
02028 T*
02029 BTree_t<T,K>::FindItemAtOrBefore(K key) const
02030 {
02031     BTreeNode_t<T,K>* node = m_root;
02032     BTreeNode_t<T,K>* last_before_node = NULL;
02033     for(;;)
02034     {
02035         if(!node)
02036             return static_cast<T*>(last_before_node);
02037 
02038         int compare = static_cast<T*>(node)->Compare(key);
02039 
02040         if(compare < 0)
02041         {
02042             last_before_node = node;    // node comes before key
02043             node = node->m_next;
02044         }
02045         else if(compare > 0)
02046             node = node->m_prev;        // node comes after key
02047         else
02048         {
02049             // Found a matching item.  Return the one closest to the tail with a matching key.
02050             for(;;)
02051             {
02052                 BTreeNode_t<T,K>* next = node->Next();
02053                 if(next && static_cast<T*>(next)->Compare(key) == 0)
02054                     node = next;
02055                 else
02056                     return static_cast<T*>(node);
02057             }
02058         }
02059     }
02060 }
02061 
02062 
02063 template <class T, class K>
02064 T*
02065 BTree_t<T,K>::FindItemAtOrAfter(K key) const
02066 {
02067     BTreeNode_t<T,K>* node = m_root;
02068     BTreeNode_t<T,K>* last_after_node = NULL;
02069     for(;;)
02070     {
02071         if(!node)
02072             return static_cast<T*>(last_after_node);
02073 
02074         int compare = static_cast<T*>(node)->Compare(key);
02075 
02076         if(compare < 0)
02077             node = node->m_next;        // node comes before key
02078         else if(compare > 0)
02079         {
02080             last_after_node = node;     // node comes after key
02081             node = node->m_prev;
02082         }
02083         else
02084         {
02085             // Found a matching item.  Return the one closest to the head with a matching key.
02086             for(;;)
02087             {
02088                 BTreeNode_t<T,K>* prev = node->Prev();
02089                 if(prev && static_cast<T*>(prev)->Compare(key) == 0)
02090                     node = prev;
02091                 else
02092                     return static_cast<T*>(node);
02093             }
02094         }
02095     }
02096 }
02097 
02098 
02099 template <class T, class K>
02100 void
02101 BTree_t<T,K>::AddItem( T* new_item, bool balance_tree )
02102 {
02103     assert(new_item);
02104     assert( (static_cast<BTreeNode_t<T,K>*>(new_item) )->m_prev == NULL);
02105     assert( (static_cast<BTreeNode_t<T,K>*>(new_item) )->m_next == NULL);
02106     assert( (static_cast<BTreeNode_t<T,K>*>(new_item) )->m_parent == NULL);
02107     assert( (static_cast<BTreeNode_t<T,K>*>(new_item) )->m_child_nodes_depth == 0);
02108 
02109     if(!m_root)
02110     {
02111         assert(m_num_items == 0);
02112         m_root = new_item;
02113         m_num_items = 1;
02114         return;
02115     }
02116 
02117     BTreeNode_t<T,K>* node = m_root;
02118     m_num_items++;
02119     for(;;)
02120     {
02121         int compare = static_cast<T*>(node)->Compare( static_cast<K>(*new_item) );
02122 
02123         if(compare <= 0)
02124         {
02125             // node comes before new_item
02126             if(node->m_next)
02127                 node = node->m_next;
02128             else
02129             {
02130                 node->m_next = new_item;
02131                 static_cast<BTreeNode_t<T,K>*>(new_item)->m_parent = node;
02132                 UpdateChildNodeCountsAndBalanceToRoot( static_cast<T*>(node), balance_tree );
02133                 return;
02134             }
02135         }
02136         else if(compare > 0)
02137         {
02138             // node comes after new_item
02139             if(node->m_prev)
02140                 node = node->m_prev;
02141             else
02142             {
02143                 node->m_prev = new_item;
02144                 static_cast<BTreeNode_t<T,K>*>(new_item)->m_parent = node;
02145                 UpdateChildNodeCountsAndBalanceToRoot( static_cast<T*>(node), balance_tree );
02146                 return;
02147             }
02148         }
02149     }
02150 }
02151 
02152 
02153 template <class T, class K>
02154 void
02155 BTree_t<T,K>::UpdateChildNodeCountsAndBalanceToRoot( T* a_node, bool balance_tree )
02156 {
02157     assert(a_node);
02158     BTreeNode_t<T,K>* node = a_node;
02159     BTreeNode_t<T,K>* parent;
02160     BTreeNode_t<T,K>* a;
02161     BTreeNode_t<T,K>* b;
02162     BTreeNode_t<T,K>* c;
02163     BTreeNode_t<T,K>* d;
02164 
02165     while(node)
02166     {
02167         int left_child_nodes_depth = 0;
02168         int right_child_nodes_depth = 0;
02169         if(node->m_prev)
02170             left_child_nodes_depth = node->m_prev->m_child_nodes_depth + 1;
02171         if(node->m_next)
02172             right_child_nodes_depth = node->m_next->m_child_nodes_depth + 1;
02173 
02174         if(!balance_tree)
02175             node->m_child_nodes_depth = max( left_child_nodes_depth, right_child_nodes_depth );
02176         else if(left_child_nodes_depth >= right_child_nodes_depth + 2)
02177         {
02178             // The left is too deep compared with the right; balance it
02179             //  parent          parent     (parent might not exist)
02180             //   node             b        (node then b could be m_next or m_prev in parent)
02181             //  b    d    ->     a node    (d might not exist)
02182             // a c                 c  d    (either a or c might not exist)
02183             parent = node->m_parent;
02184             b = node->m_prev;
02185             d = node->m_next;
02186             a = b->m_prev;
02187             c = b->m_next;
02188 
02189             // Shifting won't reduce the depth if c is the limiting factor
02190             if(c && c->m_child_nodes_depth == left_child_nodes_depth - 2)
02191             {
02192                 // c is the limiting factor; do nothing
02193                 node->m_child_nodes_depth = max( left_child_nodes_depth, right_child_nodes_depth );
02194             }
02195             else
02196             {
02197                 // Reestablish all connections
02198                 if(parent)
02199                 {
02200                     if(parent->m_prev == node)
02201                         parent->m_prev = b;
02202                     else
02203                     {
02204                         assert(parent->m_next == node);
02205                         parent->m_next = b;
02206                     }
02207                 }
02208                 else
02209                     m_root = static_cast<T*>(b);
02210                 b->m_parent = parent;
02211                 b->m_prev = a;
02212                 if(a)
02213                     a->m_parent = b;
02214                 b->m_next = node;
02215                 node->m_parent = b;
02216                 node->m_prev = c;
02217                 if(c)
02218                     c->m_parent = node;
02219 
02220                 // Reevaluate node depths for node, b, parent
02221 
02222                 // node
02223                 left_child_nodes_depth = 0;
02224                 if(c)
02225                     left_child_nodes_depth = c->m_child_nodes_depth + 1;
02226                 right_child_nodes_depth = 0;
02227                 if(d)
02228                     right_child_nodes_depth = d->m_child_nodes_depth + 1;
02229                 node->m_child_nodes_depth = max( left_child_nodes_depth, right_child_nodes_depth );
02230 
02231                 // b
02232                 left_child_nodes_depth = 0;
02233                 if(a)
02234                     left_child_nodes_depth = a->m_child_nodes_depth + 1;
02235                 right_child_nodes_depth = node->m_child_nodes_depth + 1;
02236                 b->m_child_nodes_depth = max( left_child_nodes_depth, right_child_nodes_depth );
02237 
02238                 // parent
02239                 if(parent)
02240                 {
02241                     left_child_nodes_depth = 0;
02242                     if(parent->m_prev)
02243                         left_child_nodes_depth = parent->m_prev->m_child_nodes_depth + 1;
02244                     right_child_nodes_depth = 0;
02245                     if(parent->m_next)
02246                         right_child_nodes_depth = parent->m_next->m_child_nodes_depth + 1;
02247                     parent->m_child_nodes_depth = max(  left_child_nodes_depth,
02248                                                         right_child_nodes_depth );
02249                 }
02250             }
02251         }
02252         else if(right_child_nodes_depth >= left_child_nodes_depth + 2)
02253         {
02254             // The right is too deep compared with the left; balance it
02255             //  parent             parent   (parent might not exist)
02256             //   node                c      (node then b could be m_next or m_prev in parent)
02257             //  a    c     ->    node d     (d might not exist)
02258             //      b d          a  b       (either a or c might not exist)
02259             parent = node->m_parent;
02260             a = node->m_prev;
02261             c = node->m_next;
02262             b = c->m_prev;
02263             d = c->m_next;
02264 
02265             // Shifting won't reduce the depth if b is the limiting factor
02266             if(b && b->m_child_nodes_depth == right_child_nodes_depth - 2)
02267             {
02268                 // c is the limiting factor; do nothing
02269                 node->m_child_nodes_depth = max( left_child_nodes_depth, right_child_nodes_depth );
02270             }
02271             else
02272             {
02273                 // Reestablish all connections
02274                 if(parent)
02275                 {
02276                     if(parent->m_prev == node)
02277                         parent->m_prev = c;
02278                     else
02279                     {
02280                         assert(parent->m_next == node);
02281                         parent->m_next = c;
02282                     }
02283                 }
02284                 else
02285                     m_root = static_cast<T*>(c);
02286                 c->m_parent = parent;
02287                 c->m_prev = node;
02288                 c->m_next = d;
02289                 if(d)
02290                     d->m_parent = c;
02291                 node->m_parent = c;
02292                 node->m_next = b;
02293                 if(b)
02294                     b->m_parent = node;
02295 
02296                 // Reevaluate node depths for node, c, parent
02297 
02298                 // node
02299                 left_child_nodes_depth = 0;
02300                 if(a)
02301                     left_child_nodes_depth = a->m_child_nodes_depth + 1;
02302                 right_child_nodes_depth = 0;
02303                 if(b)
02304                     right_child_nodes_depth = b->m_child_nodes_depth + 1;
02305                 node->m_child_nodes_depth = max( left_child_nodes_depth, right_child_nodes_depth );
02306 
02307                 // c
02308                 left_child_nodes_depth = node->m_child_nodes_depth + 1;
02309                 right_child_nodes_depth = 0;
02310                 if(d)
02311                     right_child_nodes_depth = d->m_child_nodes_depth + 1;
02312                 c->m_child_nodes_depth = max( left_child_nodes_depth, right_child_nodes_depth );
02313 
02314                 // parent
02315                 if(parent)
02316                 {
02317                     left_child_nodes_depth = 0;
02318                     if(parent->m_prev)
02319                         left_child_nodes_depth = parent->m_prev->m_child_nodes_depth + 1;
02320                     right_child_nodes_depth = 0;
02321                     if(parent->m_next)
02322                         right_child_nodes_depth = parent->m_next->m_child_nodes_depth + 1;
02323                     parent->m_child_nodes_depth = max(  left_child_nodes_depth,
02324                                                         right_child_nodes_depth );
02325                 }
02326             }
02327         }
02328         else
02329             node->m_child_nodes_depth = max( left_child_nodes_depth, right_child_nodes_depth );
02330 
02331         node = node->m_parent;
02332     }
02333 }
02334 
02335 
02336 template <class T, class K>
02337 T*
02338 BTree_t<T,K>::RemoveHead(bool balance_tree)
02339 {
02340     assert(m_root);
02341 
02342     BTreeNode_t<T,K>* node = m_root;
02343     while(node->m_prev)
02344         node = node->m_prev;
02345 
02346     if(node->m_parent)
02347     {
02348         node->m_parent->m_prev = node->m_next;
02349         if(node->m_next)
02350             node->m_next->m_parent = node->m_parent;
02351     }
02352     else
02353     {
02354         m_root = static_cast<T*>(node->m_next);
02355         if(node->m_next)
02356             node->m_next->m_parent = NULL;
02357     }
02358 
02359     if(node->m_parent)
02360         UpdateChildNodeCountsAndBalanceToRoot( static_cast<T*>(node->m_parent), balance_tree );
02361 
02362     m_num_items--;
02363 
02364     node->m_next = NULL;
02365     node->m_parent = NULL;
02366     node->m_child_nodes_depth = 0;
02367 
02368     #if DEBUG
02369         if(m_num_items)
02370             assert(m_root);
02371         else
02372             assert(!m_root);
02373     #endif
02374 
02375     return static_cast<T*>(node);
02376 }
02377 
02378 
02379 template <class T, class K>
02380 T*
02381 BTree_t<T,K>::RemoveTail(bool balance_tree)
02382 {
02383     assert(m_root);
02384 
02385     BTreeNode_t<T,K>* node = m_root;
02386     while(node->m_next)
02387         node = node->m_next;
02388 
02389     if(node->m_parent)
02390     {
02391         node->m_parent->m_next = node->m_prev;
02392         if(node->m_prev)
02393             node->m_prev->m_parent = node->m_parent;
02394     }
02395     else
02396     {
02397         m_root = static_cast<T*>(node->m_prev);
02398         if(node->m_prev)
02399             node->m_prev->m_parent = NULL;
02400     }
02401 
02402     if(node->m_parent)
02403         UpdateChildNodeCountsAndBalanceToRoot( static_cast<T*>(node->m_parent), balance_tree );
02404 
02405     m_num_items--;
02406 
02407     node->m_prev = NULL;
02408     node->m_parent = NULL;
02409     node->m_child_nodes_depth = 0;
02410 
02411     #if DEBUG
02412         if(m_num_items)
02413             assert(m_root);
02414         else
02415             assert(!m_root);
02416     #endif
02417 
02418     return static_cast<T*>(node);
02419 }
02420 
02421 
02422 template <class T, class K>
02423 T*
02424 BTree_t<T,K>::IsInTree(T* item) const
02425 {
02426     BTreeNode_t<T,K>* check_root = item;
02427     while(check_root && check_root->m_parent)
02428         check_root = check_root->m_parent;
02429     if(check_root == m_root)
02430         return item;
02431     return NULL;
02432 }
02433 
02434 
02435 template <class T, class K>
02436 T*
02437 BTree_t<T,K>::RemoveItem( T* item, bool balance_tree )
02438 {
02439     BTreeNode_t<T,K>* prev = static_cast<BTreeNode_t<T,K>*>(item)->m_prev;
02440     BTreeNode_t<T,K>* next = static_cast<BTreeNode_t<T,K>*>(item)->m_next;
02441     BTreeNode_t<T,K>* parent = static_cast<BTreeNode_t<T,K>*>(item)->m_parent;
02442 
02443     #if DEBUG
02444         BTreeNode_t<T,K>* check_root = item;
02445         while(check_root->m_parent)
02446             check_root = check_root->m_parent;
02447         assert(check_root == m_root);
02448     #endif
02449 
02450     if(prev && !next)
02451     {
02452         //     parent       parent   (parent might not exist)
02453         //      node     ->  prev
02454         //  prev    NULL
02455         if(parent)
02456         {
02457             if(parent->m_prev == item)
02458                 parent->m_prev = prev;
02459             else
02460             {
02461                 assert(parent->m_next == item);
02462                 parent->m_next = prev;
02463             }
02464             prev->m_parent = parent;
02465             UpdateChildNodeCountsAndBalanceToRoot( static_cast<T*>(parent), balance_tree );
02466         }
02467         else
02468         {
02469             m_root = static_cast<T*>(prev);
02470             prev->m_parent = NULL;
02471         }
02472     }
02473     else if(next && !prev)
02474     {
02475         //     parent       parent   (parent might not exist)
02476         //      node     ->  next
02477         //  NULL    next
02478         if(parent)
02479         {
02480             if(parent->m_prev == item)
02481                 parent->m_prev = next;
02482             else
02483             {
02484                 assert(parent->m_next == item);
02485                 parent->m_next = next;
02486             }
02487             next->m_parent = parent;
02488             UpdateChildNodeCountsAndBalanceToRoot( static_cast<T*>(parent), balance_tree );
02489         }
02490         else
02491         {
02492             m_root = static_cast<T*>(next);
02493             next->m_parent = NULL;
02494         }
02495     }
02496     else if( !(prev || next) )
02497     {
02498         //     parent       parent   (parent might not exist)
02499         //      node     ->  NULL
02500         //  NULL    NULL
02501         if(parent)
02502         {
02503             if(parent->m_prev == item)
02504                 parent->m_prev = NULL;
02505             else
02506             {
02507                 assert(parent->m_next == item);
02508                 parent->m_next = NULL;
02509             }
02510             UpdateChildNodeCountsAndBalanceToRoot( static_cast<T*>(parent), balance_tree );
02511         }
02512         else
02513             m_root = NULL;
02514     }
02515     else
02516     {
02517         //     parent                parent    parent         (parent might not exist)
02518         //      node        ->     prev     or     prev
02519         //  prev    next           a  b            a  b       (a, b, c, d might not exist)
02520         //  a  b    c  d               next            next
02521         //                             c  d            c  d
02522         // If next had a deeper child tree than prev, this wouldn't be the ideal arrangement, but
02523         // tree balancing will take care of that
02524         if(parent)
02525         {
02526             if(parent->m_prev == item)
02527                 parent->m_prev = prev;
02528             else
02529             {
02530                 assert(parent->m_next == item);
02531                 parent->m_next = prev;
02532             }
02533             prev->m_parent = parent;
02534         }
02535         else
02536         {
02537             m_root = static_cast<T*>(prev);
02538             prev->m_parent = NULL;
02539         }
02540 
02541         // The diagram above is actually simplified; where next is chained off of b, there could
02542         // be any number of layers below b, with next belonging after b->m_next->m_next, etc
02543         while(prev->m_next)
02544             prev = prev->m_next;
02545 
02546         prev->m_next = next;
02547         next->m_parent = prev;
02548         UpdateChildNodeCountsAndBalanceToRoot( static_cast<T*>(prev), balance_tree );
02549     }
02550 
02551     m_num_items--;
02552 
02553     static_cast<BTreeNode_t<T,K>*>(item)->m_prev = NULL;
02554     static_cast<BTreeNode_t<T,K>*>(item)->m_parent = NULL;
02555     static_cast<BTreeNode_t<T,K>*>(item)->m_next = NULL;
02556     static_cast<BTreeNode_t<T,K>*>(item)->m_child_nodes_depth = 0;
02557 
02558     #if DEBUG
02559         if(m_num_items)
02560             assert(m_root);
02561         else
02562             assert(!m_root);
02563     #endif
02564 
02565     return item;
02566 }
02567 
02568 
02569 template <class T, class K>
02570 inline int
02571 BTree_t<T,K>::CountItems() const
02572 {
02573     return m_num_items;
02574 }
02575 
02576 
02577 template <class T, class K>
02578 T*
02579 BTree_t<T,K>::Head() const
02580 {
02581     BTreeNode_t<T,K>* node = m_root;
02582     if(!node)
02583         return NULL;
02584     while(node->m_prev)
02585         node = node->m_prev;
02586     return static_cast<T*>(node);
02587 }
02588 
02589 
02590 template <class T, class K>
02591 T*
02592 BTree_t<T,K>::Tail() const
02593 {
02594     BTreeNode_t<T,K>* node = m_root;
02595     if(!node)
02596         return NULL;
02597     while(node->m_next)
02598         node = node->m_next;
02599     return static_cast<T*>(node);
02600 }
02601 
02602 
02603 template <class T, class K>
02604 inline T*
02605 BTree_t<T,K>::Root() const
02606 {
02607     return m_root;
02608 }
02609 
02610 
02611 template <class T, class K>
02612 inline void
02613 BTree_t<T,K>::operator +=(T* item)
02614 {
02615     AddItem(item);
02616 }
02617 
02618 
02619 template <class T, class K>
02620 inline void
02621 BTree_t<T,K>::operator -=(T* item)
02622 {
02623     RemoveItem(item);
02624 }
02625 
02626 
02627 
02628 
02629 //==================================================================================================
02630 //==================================================================================================
02631 //===
02632 //=== Template function implementations: class BTreeNode_t
02633 //===
02634 //==================================================================================================
02635 //==================================================================================================
02636 template <class T, class K>
02637 inline
02638 BTreeNode_t<T,K>::BTreeNode_t()
02639 {
02640     m_prev = NULL;
02641     m_next = NULL;
02642     m_parent = NULL;
02643     m_child_nodes_depth = 0;
02644 }
02645 
02646 
02647 template <class T, class K>
02648 T*
02649 BTreeNode_t<T,K>::Next() const
02650 {
02651     BTreeNode_t<T,K>* node;
02652     if(m_next)
02653     {
02654         node = m_next;
02655         while(node && node->m_prev)
02656             node = node->m_prev;
02657         return static_cast<T*>(node);
02658     }
02659 
02660     node = const_cast<T*>( static_cast<const T*>(this) );
02661     for(;;)
02662     {
02663         if(!node->m_parent)
02664             return NULL;
02665         if(node->m_parent->m_prev == node)
02666             return static_cast<T*>(node->m_parent);
02667         node = node->m_parent;
02668     }
02669 }
02670 
02671 
02672 template <class T, class K>
02673 T*
02674 BTreeNode_t<T,K>::Prev() const
02675 {
02676     BTreeNode_t<T,K>* node;
02677     if(m_prev)
02678     {
02679         node = m_prev;
02680         while(node && node->m_next)
02681             node = node->m_next;
02682         return static_cast<T*>(node);
02683     }
02684 
02685     node = const_cast<T*>( static_cast<const T*>(this) );
02686     for(;;)
02687     {
02688         if(!node->m_parent)
02689             return NULL;
02690         if(node->m_parent->m_next == node)
02691             return static_cast<T*>(node->m_parent);
02692         node = node->m_parent;
02693     }
02694 }
02695 
02696 
02697 template <class T, class K>
02698 inline bool
02699 BTreeNode_t<T,K>::operator < (const T& other)
02700 {
02701     return (static_cast<T*>(this)->Compare( static_cast<K>(other) ) < 0);
02702 }
02703 
02704 
02705 template <class T, class K>
02706 inline bool
02707 BTreeNode_t<T,K>::operator <= (const T& other)
02708 {
02709     return (static_cast<T*>(this)->Compare( static_cast<K>(other) ) <= 0);
02710 }
02711 
02712 
02713 template <class T, class K>
02714 inline bool
02715 BTreeNode_t<T,K>::operator > (const T& other)
02716 {
02717     return (static_cast<T*>(this)->Compare( static_cast<K>(other) ) > 0);
02718 }
02719 
02720 
02721 template <class T, class K>
02722 inline bool
02723 BTreeNode_t<T,K>::operator >= (const T& other)
02724 {
02725     return (static_cast<T*>(this)->Compare( static_cast<K>(other) ) >= 0);
02726 }
02727 
02728 
02729 template <class T, class K>
02730 inline bool
02731 BTreeNode_t<T,K>::operator == (const T& other)
02732 {
02733     return (static_cast<T*>(this)->Compare( static_cast<K>(other) ) == 0);
02734 }
02735 
02736 
02737 template <class T, class K>
02738 inline bool
02739 BTreeNode_t<T,K>::operator < (K key)
02740 {
02741     return (static_cast<T*>(this)->Compare(key) < 0);
02742 }
02743 
02744 
02745 template <class T, class K>
02746 inline bool
02747 BTreeNode_t<T,K>::operator <= (K key)
02748 {
02749     return (static_cast<T*>(this)->Compare(key) <= 0);
02750 }
02751 
02752 
02753 template <class T, class K>
02754 inline bool
02755 BTreeNode_t<T,K>::operator > (K key)
02756 {
02757     return (static_cast<T*>(this)->Compare(key) > 0);
02758 }
02759 
02760 
02761 template <class T, class K>
02762 inline bool
02763 BTreeNode_t<T,K>::operator >= (K key)
02764 {
02765     return (static_cast<T*>(this)->Compare(key) >= 0);
02766 }
02767 
02768 
02769 template <class T, class K>
02770 inline bool
02771 BTreeNode_t<T,K>::operator == (K key)
02772 {
02773     return (static_cast<T*>(this)->Compare(key) == 0);
02774 }
02775 
02776 
02777 template <class T, class K>
02778 inline int
02779 BTreeNode_t<T,K>::ChildNodesDepth() const
02780 {
02781     return m_child_nodes_depth;
02782 }
02783 
02784 
02785 template <class T, class K>
02786 void
02787 BTreeNode_t<T,K>::ValidateChildNodeDepth() const
02788 {
02789     assert(     (m_next && m_child_nodes_depth == m_next->m_child_nodes_depth + 1)
02790             ||  (m_prev && m_child_nodes_depth == m_prev->m_child_nodes_depth + 1)
02791             ||  (m_child_nodes_depth == 0) );
02792 }
02793 
02794 
02795 
02796 
02797 //==================================================================================================
02798 //==================================================================================================
02799 //===
02800 //=== Template function implementations: class OwnedBTree_t
02801 //===
02802 //==================================================================================================
02803 //==================================================================================================
02804 template <class T, class K>
02805 OwnedBTree_t<T,K>::~OwnedBTree_t()
02806 {
02807     while( BTree_t<T,K>::CountItems() )
02808         delete BTree_t<T,K>::RemoveHead(false);
02809 }
02810 
02811 
02812 
02813 
02814 //==================================================================================================
02815 //==================================================================================================
02816 //===
02817 //=== Template function implementations: class SortedList_t
02818 //===
02819 //==================================================================================================
02820 //==================================================================================================
02821 template <class T, class K>
02822 SortedList_t<T,K>::SortedList_t()
02823 {
02824     m_items = NULL;
02825     m_num_items = 0;
02826     m_items_allocated = 0;
02827     m_items_allocated_on_stack = false;
02828 }
02829 
02830 
02831 template <class T, class K>
02832 SortedList_t<T,K>::SortedList_t( T** stack_buffer, int stack_buffer_num_items_allcoated )
02833 {
02834     m_items = stack_buffer;
02835     m_num_items = 0;
02836     m_items_allocated = stack_buffer_num_items_allcoated;
02837     m_items_allocated_on_stack = true;
02838 }
02839 
02840 template <class T, class K>
02841 SortedList_t<T,K>::~SortedList_t()
02842 {
02843     if(m_items && !m_items_allocated_on_stack)
02844         delete[] m_items;
02845 }
02846 
02847 
02848 template <class T, class K>
02849 int
02850 SortedList_t<T,K>::FindItemIndex( K key, bool at_or_before, bool at_or_after ) const
02851 {
02852     if(m_num_items == 0)
02853         return -1;
02854 
02855     int first_unchecked = 0;
02856     int last_unchecked = m_num_items-1;
02857     for(;;)
02858     {
02859         int mid = (first_unchecked + last_unchecked) / 2;
02860         assert(mid >= 0 && mid < m_num_items);
02861         int result = m_items[mid]->Compare(key);
02862         if(result == 0)
02863         {
02864             // The item at mid has a matching key.
02865             if(at_or_before)
02866             {
02867                 // Go towards the tail.
02868                 for(;;)
02869                 {
02870                     int next = mid+1;
02871                     if(next < m_num_items && m_items[next]->Compare(key) == 0)
02872                         mid = next;
02873                     else
02874                         return mid;
02875                 }
02876             }
02877             else
02878             {
02879                 // Go towards the head.
02880                 for(;;)
02881                 {
02882                     int prev = mid-1;
02883                     if(prev >= 0 && m_items[prev]->Compare(key) == 0)
02884                         mid = prev;
02885                     else
02886                         return mid;
02887                 }
02888             }
02889         }
02890         else if(result < 0)
02891         {
02892             // this comes before key: mid comes before key
02893             first_unchecked = mid+1;
02894             if(last_unchecked < first_unchecked)
02895             {
02896                 // For at_or_before or at_or_after evaluation, mid is before key, mid+1 must be
02897                 // after (if it exists).
02898                 if(at_or_before)
02899                 {
02900                     #if DEBUG
02901                         if(mid+1 < m_num_items)
02902                             assert(m_items[mid+1]->Compare(key) > 0);
02903                     #endif
02904                     return mid;
02905                 }
02906                 else if(at_or_after)
02907                 {
02908                     // Item at mid+1 (if it exists) is after key
02909                     if(mid+1 == m_num_items)
02910                         return -1;
02911                     assert(m_items[mid+1]->Compare(key) > 0);
02912                     return mid+1;
02913                 }
02914                 return -1;
02915             }
02916         }
02917         else // result > 0
02918         {
02919             // this comes after key: mid comes after key
02920             last_unchecked = mid-1;
02921             if(last_unchecked < first_unchecked)
02922             {
02923                 // For at_or_before or at_or_after evaluation, mid is after key, mid-1 must be
02924                 // before (if it exists).
02925                 if(at_or_before)
02926                 {
02927                     if(mid-1 < 0)
02928                         return -1;
02929                     assert(m_items[mid-1]->Compare(key) < 0);
02930                     return mid-1;
02931                 }
02932                 else if(at_or_after)
02933                 {
02934                     #if DEBUG
02935                         if(mid-1 >= 0)
02936                             assert(m_items[mid-1]->Compare(key) < 0);
02937                     #endif
02938                     return mid;
02939                 }
02940                 return -1;
02941             }
02942         }
02943     }
02944 }
02945 
02946 
02947 template <class T, class K>
02948 int
02949 SortedList_t<T,K>::FindItemIndex( T* item, bool adding ) const
02950 {
02951     if(m_num_items == 0)
02952         return -1;
02953 
02954     int first_unchecked = 0;
02955     int last_unchecked = m_num_items-1;
02956     for(;;)
02957     {
02958         int mid = (first_unchecked + last_unchecked) / 2;
02959         assert(mid >= 0 && mid < m_num_items);
02960         int result = m_items[mid]->Compare( static_cast<K>(*item) );
02961         if(result == 0)
02962         {
02963             // Found a matching key. 
02964             if(adding)
02965             {
02966                 // The item at mid has a matching key.  Go towards the head.
02967                 for(;;)
02968                 {
02969                     int next = mid+1;
02970                     if(     next < m_num_items
02971                         &&  m_items[next]->Compare( static_cast<K>(*item) ) == 0 )
02972                     {
02973                         mid = next;
02974                     }
02975                     else
02976                         return mid;
02977                 }
02978             }
02979             else
02980             {
02981                 // Searching for the item
02982                 if(m_items[mid] == item)
02983                     return mid;
02984 
02985                 // See if one of the adjacent items with the same key is an exact match for the item.
02986                 int sibling = mid-1;
02987                 while(sibling >= 0)
02988                 {
02989                     if(m_items[sibling]->Compare( static_cast<K>(*item) ) != 0)
02990                         break;
02991                     if(m_items[sibling] == item)
02992                         return sibling;
02993                     sibling--;
02994                 }
02995                 sibling = mid+1;
02996                 while(sibling < m_num_items)
02997                 {
02998                     if(m_items[sibling]->Compare( static_cast<K>(*item) ) != 0)
02999                         break;
03000                     if(m_items[sibling] == item)
03001                         return sibling;
03002                     sibling++;
03003                 }
03004                 return -1;
03005             }
03006         }
03007         else if(result < 0)
03008         {
03009             // this comes before item: mid comes before item
03010             first_unchecked = mid+1;
03011             if(last_unchecked < first_unchecked)
03012             {
03013                 // mid is before item, mid+1 must be after (if it exists).
03014                 if(adding)
03015                 {
03016                     // Item at mid+1 (if it exists) is after item
03017                     return mid;
03018                 }
03019                 return -1;
03020             }
03021         }
03022         else // result > 0
03023         {
03024             // this comes after item: mid comes after item
03025             last_unchecked = mid-1;
03026             if(last_unchecked < first_unchecked)
03027             {
03028                 // mid is after item, mid-1 must be before (if it exists).
03029                 if(adding)
03030                 {
03031                     return mid-1;
03032                 }
03033                 return -1;
03034             }
03035         }
03036     }
03037 }
03038 
03039 
03040 template <class T, class K>
03041 T*
03042 SortedList_t<T,K>::FindItem( K key, out int* a_index ) const
03043 {
03044     int index = FindItemIndex( key, false, false );
03045     if(index == -1)
03046     {
03047         if(a_index)
03048             *a_index = -1;
03049         return NULL;
03050     }
03051     if(a_index)
03052         *a_index = index;
03053     return m_items[index];
03054 }
03055 
03056 
03057 template <class T, class K>
03058 T*
03059 SortedList_t<T,K>::FindItemAtOrBefore( K key, out int* a_index ) const
03060 {
03061     int index = FindItemIndex( key, true, false );
03062     if(index == -1)
03063     {
03064         if(a_index)
03065             *a_index = -1;
03066         return NULL;
03067     }
03068     if(a_index)
03069         *a_index = index;
03070     return m_items[index];
03071 }
03072 
03073 
03074 template <class T, class K>
03075 T*
03076 SortedList_t<T,K>::FindItemAtOrAfter( K key, out int* a_index ) const
03077 {
03078     int index = FindItemIndex( key, false, true );
03079     if(index == -1)
03080     {
03081         if(a_index)
03082             *a_index = -1;
03083         return NULL;
03084     }
03085     if(a_index)
03086         *a_index = index;
03087     return m_items[index];
03088 }
03089 
03090 
03091 template <class T, class K>
03092 void
03093 SortedList_t<T,K>::AddItem(T* item)
03094 {
03095     assert(item);
03096     if(     m_num_items == 0
03097         ||  m_items[m_num_items-1]->Compare( static_cast<K>(*item) ) <= 0 )
03098     {
03099         AddTail(item);
03100         return;
03101     }
03102     int result = m_items[0]->Compare( static_cast<K>(*item) );
03103     if(result > 0)
03104     {
03105         AddHead(item);
03106         return;
03107     }
03108 
03109     // FindItemIndex will return the index of the item before where the new one should be inserted
03110     int index = FindItemIndex( item, true ) + 1;
03111 
03112     if(m_num_items < m_items_allocated)
03113     {
03114         // Insert at index
03115         memmove( m_items+index+1, m_items+index, (m_num_items-index) * sizeof(T*) );
03116         m_items[index] = item;
03117     }
03118     else
03119     {
03120         // Need to make room for the item: figure out how big to make the new list
03121         int new_items_allocated = m_items_allocated;
03122         if(new_items_allocated == 0)
03123             new_items_allocated = 16;
03124         else if(new_items_allocated < 128)
03125             new_items_allocated *= 2;
03126         else
03127             new_items_allocated += new_items_allocated / 2;
03128 
03129         // Allocate the new list
03130         T** new_list = new T*[new_items_allocated];
03131 
03132         // Copy the existing items before index
03133         memcpy( new_list, m_items, index * sizeof(T*) );
03134         new_list[index] = item;
03135         memcpy( new_list+index+1, m_items+index, (m_num_items-index) * sizeof(T*) );
03136         if(m_items && !m_items_allocated_on_stack)
03137             delete[] m_items;
03138         m_items = new_list;
03139         m_items_allocated = new_items_allocated;
03140         m_items_allocated_on_stack = false;
03141     }
03142     m_num_items++;
03143 }
03144 
03145 
03146 template <class T, class K>
03147 void
03148 SortedList_t<T,K>::AddHead(T* item)
03149 {
03150     if(m_num_items == 0)
03151     {
03152         if(!m_items)
03153         {   
03154             assert(m_items_allocated == 0);
03155             m_items_allocated = 16;
03156             m_items = new T*[m_items_allocated];
03157         }
03158         m_items[0] = item;
03159         m_num_items = 1;
03160         return;
03161     }
03162 
03163     // Make sure the item to be added comes before the existing head
03164     assert(item->Compare( static_cast<K>(*m_items[0]) ) <= 0);
03165 
03166     if(m_num_items < m_items_allocated)
03167     {
03168         // Insert at index 0
03169         memmove( m_items+1, m_items, (m_num_items) * sizeof(T*) );
03170         m_items[0] = item;
03171     }
03172     else
03173     {
03174         // Need to make room for the item: figure out how big to make the new list
03175         int new_items_allocated = m_items_allocated;
03176         if(new_items_allocated == 0)
03177             new_items_allocated = 16;
03178         else if(new_items_allocated < 128)
03179             new_items_allocated *= 2;
03180         else
03181             new_items_allocated += new_items_allocated / 2;
03182 
03183         // Allocate the new list
03184         T** new_list = new T*[new_items_allocated];
03185         new_list[0] = item;
03186 
03187         // Copy the existing items before index
03188         memcpy( new_list+1, m_items, m_num_items * sizeof(T*) );
03189         if(m_items && !m_items_allocated_on_stack)
03190             delete[] m_items;
03191         m_items = new_list;
03192         m_items_allocated = new_items_allocated;
03193         m_items_allocated_on_stack = false;
03194     }
03195     m_num_items++;
03196 }
03197 
03198 
03199 template <class T, class K>
03200 void
03201 SortedList_t<T,K>::AddTail( T* item, bool will_sort_later )
03202 {
03203     if(m_num_items == 0)
03204     {
03205         if(!m_items)
03206         {   
03207             assert(m_items_allocated == 0);
03208             m_items_allocated = 16;
03209             m_items = new T*[m_items_allocated];
03210         }
03211         m_items[0] = item;
03212         m_num_items = 1;
03213         return;
03214     }
03215 
03216     // Make sure the item to be added comes after the existing tail
03217     assert(will_sort_later || item->Compare( static_cast<K>(*m_items[m_num_items-1]) ) >= 0);
03218 
03219     if(m_num_items == m_items_allocated)
03220     {
03221         // Need to make room for the item: figure out how big to make the new list
03222         int new_items_allocated = m_items_allocated;
03223         if(new_items_allocated == 0)
03224             new_items_allocated = 16;
03225         else if(new_items_allocated < 128)
03226             new_items_allocated *= 2;
03227         else
03228             new_items_allocated += new_items_allocated / 2;
03229 
03230         // Allocate the new list
03231         T** new_list = new T*[new_items_allocated];
03232 
03233         // Copy the existing items
03234         memcpy( new_list, m_items, m_num_items * sizeof(T*) );
03235 
03236         if(m_items && !m_items_allocated_on_stack)
03237             delete[] m_items;
03238         m_items = new_list;
03239         m_items_allocated = new_items_allocated;
03240         m_items_allocated_on_stack = false;
03241     }
03242     m_items[m_num_items] = item;
03243     m_num_items++;
03244 }
03245 
03246 
03247 template <class T, class K>
03248 void
03249 SortedList_t<T,K>::Sort()
03250 {
03251     if(m_num_items < 2)
03252         return;
03253 
03254     T** alt_buf;
03255     T* stack_buf[c_max_stack_buf/sizeof(T*)];
03256     if( m_num_items > static_cast<int>( c_max_stack_buf/sizeof(T*) ) )
03257         alt_buf = new T*[m_num_items];
03258     else
03259         alt_buf = stack_buf;
03260 
03261     bool sorted_items_in_alt_buf = MergeSort( m_items, alt_buf, m_num_items );
03262 
03263     // Use the target platform's reasonable stack buffer size as a guage for what is reasonable to
03264     // waste in terms of heap space.  Waste up to 1/32 of the max stack buffer.  If the max stack
03265     // buffer is 8192 with 32-bit pointers, that's 1/32 of 2048 item pointers, or 64 pointers, or
03266     // 256 bytes.
03267     int max_waste_heap_items = ( c_max_stack_buf/sizeof(T*) ) / 32;
03268 
03269     if(alt_buf == stack_buf)
03270     {
03271         // The items must end up back in the m_items buffer, which might be reallocated to optimize
03272         // its memory usage.
03273         if(m_items_allocated_on_stack)
03274         {
03275             // There is no reason to reallocate m_items since it's already a stack buffer.
03276             if(sorted_items_in_alt_buf)
03277             {
03278                 // The sorted items are in alt_buf, so copy back to m_items.
03279                 memcpy( m_items, alt_buf, m_num_items*sizeof(T*) );
03280             }
03281         }
03282         else
03283         {
03284             // m_items is a heap buffer, so we might want to compact it.
03285             if(m_num_items < m_items_allocated - max_waste_heap_items)
03286             {
03287                 // Do reallocate the m_items buffer
03288                 T** new_items = new T*[m_num_items];
03289                 if(sorted_items_in_alt_buf)
03290                     memcpy( new_items, alt_buf, m_num_items*sizeof(T*) );
03291                 else
03292                     memcpy( new_items, m_items, m_num_items*sizeof(T*) );
03293                 delete[] m_items;
03294                 m_items = new_items;
03295                 m_items_allocated = m_num_items;
03296             }
03297             else
03298             {
03299                 // Don't bother reallocating the m_items buffer.
03300                 if(sorted_items_in_alt_buf)
03301                 {
03302                     // The sorted items are in alt_buf, so copy back to m_items.
03303                     memcpy( m_items, alt_buf, m_num_items*sizeof(T*) );
03304                 }
03305             }
03306         }
03307     }
03308     else
03309     {
03310         // alt_buf is a heap buffer.  If it would optimize memory usage, m_items will be freed and
03311         // alt_buf will be installed in its place.
03312         if(m_items_allocated_on_stack)
03313         {
03314             // There is no reason to reallocate m_items since it's already a stack buffer.
03315             if(sorted_items_in_alt_buf)
03316             {
03317                 // The sorted items are in alt_buf, so copy back to m_items.
03318                 memcpy( m_items, alt_buf, m_num_items*sizeof(T*) );
03319             }
03320             delete[] alt_buf;
03321         }
03322         else
03323         {
03324             if(sorted_items_in_alt_buf)
03325             {
03326                 // The sorted items are in alt_buf, so install it in place of m_items
03327                 delete[] m_items;
03328                 m_items = alt_buf;
03329                 m_items_allocated = m_num_items;
03330             }
03331             else
03332             {
03333                 // The sorted items are in m_items.  If that buffer is oversized, use alt_buf
03334                 // instead.
03335                 if(m_num_items < m_items_allocated - max_waste_heap_items)
03336                 {
03337                     // Switch to using alt_buf
03338                     memcpy( alt_buf, m_items, m_num_items*sizeof(T*) );
03339                     delete[] m_items;
03340                     m_items = alt_buf;
03341                     m_items_allocated = m_num_items;
03342                 }
03343                 else
03344                 {
03345                     // Don't bother reallocating the m_items buffer.
03346                     delete[] alt_buf;
03347                 }
03348             }
03349         }
03350     }
03351 }
03352 
03353 
03354 template <class T, class K>
03355 bool
03356 SortedList_t<T,K>::MergeSort( T** from, T** to, int num_items )
03357 {
03358     int first_half_num_items = num_items/2;
03359     assert(first_half_num_items >= 1);
03360     int second_half_num_items = num_items - first_half_num_items;
03361     assert(second_half_num_items >= 1);
03362     T* temp;
03363 
03364     // Force the first half to be a sorted list
03365     bool first_half_in_to;
03366     if(first_half_num_items == 1)
03367         first_half_in_to = false;
03368     else if(first_half_num_items == 2)
03369     {
03370         if(from[0]->Compare( static_cast<K>(*from[1]) ) > 0)
03371         {
03372             // from[0] is after from[1]
03373             temp = from[0];
03374             from[0] = from[1];
03375             from[1] = temp;
03376         }
03377         first_half_in_to = false;
03378     }
03379     else
03380     {
03381         first_half_in_to = MergeSort( from, to, first_half_num_items );
03382     }
03383 
03384     // Force the second half to be a sorted list
03385     bool second_half_in_to;
03386     if(second_half_num_items == 1)
03387         second_half_in_to = false;
03388     else if(second_half_num_items == 2)
03389     {
03390         if(from[first_half_num_items]->Compare( static_cast<K>(*from[first_half_num_items+1]) ) > 0)
03391         {
03392             // from[0] is after from[1]
03393             temp = from[first_half_num_items];
03394             from[first_half_num_items] = from[first_half_num_items+1];
03395             from[first_half_num_items+1] = temp;
03396         }
03397         second_half_in_to = false;
03398     }
03399     else
03400     {
03401         second_half_in_to = MergeSort(  from+first_half_num_items,
03402                                         to+first_half_num_items,
03403                                         second_half_num_items );
03404     }
03405 
03406     // At this point, both halves are sorted, but not necessarily in the same buffer.  They need to
03407     // be in the same buffer before merging.
03408     bool result_in_caller_to;
03409     if(first_half_in_to && !second_half_in_to)
03410     {
03411         // Move the first half to the "from" buffer, then merge into the caller's "to" buffer
03412         result_in_caller_to = true;
03413         memcpy( from, to, first_half_num_items*sizeof(T*) );
03414     }
03415     else if(second_half_in_to && !first_half_in_to)
03416     {
03417         // Move the second half to the "from" buffer, then merge into the caller's "to" buffer
03418         result_in_caller_to = true;
03419         memcpy( from + first_half_num_items,
03420                 to + first_half_num_items,
03421                 second_half_num_items * sizeof(T*) );
03422     }
03423     else if(first_half_in_to)
03424     {
03425         // Both halves must already be in the caller's "to" buffer, so we'll merge into the caller's
03426         // "from" buffer.  That being the case, swap the from/to relationship for the merge.
03427         assert(second_half_in_to);
03428         T** temp_buf = from;
03429         from = to;
03430         to = temp_buf;
03431         result_in_caller_to = false;
03432     }
03433     else
03434     {
03435         // Both halves must already be in the caller's "from" buffer, so we'll merge into the "to"
03436         // buffer.
03437         assert(!second_half_in_to);
03438         result_in_caller_to = true;
03439     }
03440 
03441     // Perform the merge of the two halves from "from" into a sorted list in "to"
03442     int first_half_index = 0;
03443     int second_half_index = 0;
03444     int to_index = 0;
03445     T** from_second_half = from + first_half_num_items;
03446     for(;;)
03447     {
03448         assert(first_half_index < first_half_num_items);
03449         assert(second_half_index < second_half_num_items);
03450         if(     from[first_half_index]->Compare(
03451                                             static_cast<K>(*from_second_half[second_half_index]) )
03452             <= 0 )
03453         {
03454             // The next first half item comes before or is equal to the next second half item
03455             to[to_index++] = from[first_half_index++];
03456             if(first_half_index == first_half_num_items)
03457             {
03458                 // Out of items in the first half, so insert everything from the second half
03459                 while(second_half_index < second_half_num_items)
03460                     to[to_index++] = from_second_half[second_half_index++];
03461                 break;
03462             }
03463         }
03464         else
03465         {
03466             // The next first half item comes after the next second half item
03467             to[to_index++] = from_second_half[second_half_index++];
03468             if(second_half_index == second_half_num_items)
03469             {
03470                 // Out of items in the second half, so insert everything from the first half
03471                 while(first_half_index < first_half_num_items)
03472                     to[to_index++] = from[first_half_index++];
03473                 break;
03474             }
03475         }
03476     }
03477 
03478     // All items must have been merged
03479     assert(first_half_index == first_half_num_items);
03480     assert(second_half_index == second_half_num_items);
03481     assert(to_index == num_items);
03482 
03483     return result_in_caller_to;
03484 }
03485 
03486 
03487 template <class T, class K>
03488 T*
03489 SortedList_t<T,K>::IsInList(T* item) const
03490 {
03491     if(item == NULL)
03492         return NULL;
03493     int index = FindItemIndex( item, false );
03494     if(index == -1)
03495         return NULL;
03496     return item;
03497 }
03498 
03499 
03500 template <class T, class K>
03501 T*
03502 SortedList_t<T,K>::RemoveItem(T* item)
03503 {
03504     int index = FindItemIndex( item, false );
03505     if(index == -1)
03506     {
03507         debug_error("The specified item was not found");
03508         return NULL;
03509     }
03510 
03511     // Found it.
03512     m_num_items--;
03513     assert(m_items[index] == item);
03514     memmove( m_items+index, m_items+index+1, (m_num_items-index) * sizeof(T*) );
03515     return item;
03516 }
03517 
03518 
03519 template <class T, class K>
03520 T*
03521 SortedList_t<T,K>::RemoveHead()
03522 {
03523     assert(m_num_items);
03524     T* head = m_items[0];
03525     m_num_items--;
03526     memmove( m_items, m_items+1, m_num_items * sizeof(T*) );
03527     return head;
03528 }
03529 
03530 
03531 template <class T, class K>
03532 inline T*
03533 SortedList_t<T,K>::RemoveTail()
03534 {
03535     assert(m_num_items);
03536     m_num_items--;
03537     return m_items[m_num_items];
03538 }
03539 
03540 
03541 template <class T, class K>
03542 T*
03543 SortedList_t<T,K>::RemoveItemAt(int index)
03544 {
03545     m_num_items--;
03546     assert(m_num_items > index);
03547     T* item = m_items[index];
03548     memmove( m_items+index, m_items+index+1, (m_num_items-index) * sizeof(T*) );
03549     return item;
03550 }
03551 
03552 
03553 template <class T, class K>
03554 int
03555 SortedList_t<T,K>::IndexOfItem(T* item)
03556 {
03557     return FindItemIndex( item, false );
03558 }
03559 
03560 
03561 template <class T, class K>
03562 inline int
03563 SortedList_t<T,K>::CountItems() const
03564 {
03565     return m_num_items;
03566 }
03567 
03568 
03569 template <class T, class K>
03570 inline T*
03571 SortedList_t<T,K>::Head() const
03572 {
03573     if(m_num_items == 0)
03574         return NULL;
03575     return m_items[0];
03576 }
03577 
03578 
03579 template <class T, class K>
03580 inline T*
03581 SortedList_t<T,K>::Tail() const
03582 {
03583     if(m_num_items == 0)
03584         return NULL;
03585     return m_items[m_num_items-1];
03586 }
03587 
03588 
03589 template <class T, class K>
03590 inline T*
03591 SortedList_t<T,K>::ItemAt(int index) const
03592 {
03593     assert(m_num_items > index);
03594     return m_items[index];
03595 }
03596 
03597 
03598 template <class T, class K>
03599 inline T&
03600 SortedList_t<T,K>::operator [](int index) const
03601 {
03602     assert(m_num_items > index);
03603     return *m_items[index];
03604 }
03605 
03606 
03607 template <class T, class K>
03608 inline void
03609 SortedList_t<T,K>::operator +=(T* item)
03610 {
03611     AddItem(item);
03612 }
03613 
03614 
03615 template <class T, class K>
03616 inline void
03617 SortedList_t<T,K>::operator -=(T* item)
03618 {
03619     RemoveItem(item);
03620 }
03621 
03622 
03623 
03624 
03625 //==================================================================================================
03626 //==================================================================================================
03627 //===
03628 //=== Template function implementations: class OwnedSortedList_t
03629 //===
03630 //==================================================================================================
03631 //==================================================================================================
03632 template <class T, class K>
03633 inline
03634 OwnedSortedList_t<T,K>::OwnedSortedList_t()
03635 { }
03636 
03637 
03638 template <class T, class K>
03639 inline
03640 OwnedSortedList_t<T,K>::OwnedSortedList_t( T** stack_buffer, int stack_buffer_num_items_allcoated )
03641 : List_t<T*>( stack_buffer, stack_buffer_num_items_allcoated )
03642 { }
03643 
03644 
03645 template <class T, class K>
03646 OwnedSortedList_t<T,K>::~OwnedSortedList_t()
03647 {
03648     for(int i=0; i<SortedList_t<T,K>::CountItems(); i++)
03649         delete SortedList_t<T,K>::ItemAt(i);
03650 }
03651 
03652 
03653 #endif // _UT_LISTS_H_

Generated on Tue Dec 14 22:35:05 2010 for UT library by  doxygen 1.6.1