Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/bullet/BulletCollision/GIMPACT/gim_hash_table.h @ 2192

Last change on this file since 2192 was 2192, checked in by rgrieder, 16 years ago

Reverted all changes of attempt to update physics branch.

  • Property svn:eol-style set to native
File size: 23.7 KB
Line 
1#ifndef GIM_HASH_TABLE_H_INCLUDED
2#define GIM_HASH_TABLE_H_INCLUDED
3/*! \file gim_trimesh_data.h
4\author Francisco Len Nßjera
5*/
6/*
7-----------------------------------------------------------------------------
8This source file is part of GIMPACT Library.
9
10For the latest info, see http://gimpact.sourceforge.net/
11
12Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
13email: projectileman@yahoo.com
14
15 This library is free software; you can redistribute it and/or
16 modify it under the terms of EITHER:
17   (1) The GNU Lesser General Public License as published by the Free
18       Software Foundation; either version 2.1 of the License, or (at
19       your option) any later version. The text of the GNU Lesser
20       General Public License is included with this library in the
21       file GIMPACT-LICENSE-LGPL.TXT.
22   (2) The BSD-style license that is included with this library in
23       the file GIMPACT-LICENSE-BSD.TXT.
24   (3) The zlib/libpng license that is included with this library in
25       the file GIMPACT-LICENSE-ZLIB.TXT.
26
27 This library is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
30 GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
31
32-----------------------------------------------------------------------------
33*/
34
35#include "gim_radixsort.h"
36
37/*! \addtogroup CONTAINERS
38\brief
39Abstract class for collision objects
40*/
41//! @{
42
43#define GIM_INVALID_HASH 0xffffffff //!< A very very high value
44#define GIM_DEFAULT_HASH_TABLE_SIZE 380
45#define GIM_DEFAULT_HASH_TABLE_NODE_SIZE 4
46#define GIM_HASH_TABLE_GROW_FACTOR 2
47
48#define GIM_MIN_RADIX_SORT_SIZE 860 //!< calibrated on a PIII
49
50template<typename T>
51struct GIM_HASH_TABLE_NODE
52{
53    GUINT m_key;
54    T m_data;
55    GIM_HASH_TABLE_NODE()
56    {
57    }
58
59    GIM_HASH_TABLE_NODE(const GIM_HASH_TABLE_NODE & value)
60    {
61        m_key = value.m_key;
62        m_data = value.m_data;
63    }
64
65    GIM_HASH_TABLE_NODE(GUINT key, const T & data)
66    {
67        m_key = key;
68        m_data = data;
69    }
70
71    bool operator <(const GIM_HASH_TABLE_NODE<T> & other) const
72        {
73                ///inverse order, further objects are first
74                if(m_key <  other.m_key) return true;
75                return false;
76        }
77
78        bool operator >(const GIM_HASH_TABLE_NODE<T> & other) const
79        {
80                ///inverse order, further objects are first
81                if(m_key >  other.m_key) return true;
82                return false;
83        }
84
85        bool operator ==(const GIM_HASH_TABLE_NODE<T> & other) const
86        {
87                ///inverse order, further objects are first
88                if(m_key ==  other.m_key) return true;
89                return false;
90        }
91};
92
93///Macro for getting the key
94class GIM_HASH_NODE_GET_KEY
95{
96public:
97        template<class T>
98        inline GUINT operator()( const T& a)
99        {
100                return a.m_key;
101        }
102};
103
104
105
106///Macro for comparing the key and the element
107class GIM_HASH_NODE_CMP_KEY_MACRO
108{
109public:
110        template<class T>
111        inline int operator() ( const T& a, GUINT key)
112        {
113                return ((int)(a.m_key - key));
114        }
115};
116
117///Macro for comparing Hash nodes
118class GIM_HASH_NODE_CMP_MACRO
119{
120public:
121        template<class T>
122        inline int operator() ( const T& a, const T& b )
123        {
124                return ((int)(a.m_key - b.m_key));
125        }
126};
127
128
129
130
131
132//! Sorting for hash table
133/*!
134switch automatically between quicksort and radixsort
135*/
136template<typename T>
137void gim_sort_hash_node_array(T * array, GUINT array_count)
138{
139    if(array_count<GIM_MIN_RADIX_SORT_SIZE)
140    {
141        gim_heap_sort(array,array_count,GIM_HASH_NODE_CMP_MACRO());
142    }
143    else
144    {
145        memcopy_elements_func cmpfunc;
146        gim_radix_sort(array,array_count,GIM_HASH_NODE_GET_KEY(),cmpfunc);
147    }
148}
149
150
151
152
153
154
155// Note: assumes long is at least 32 bits.
156#define GIM_NUM_PRIME 28
157
158static const GUINT gim_prime_list[GIM_NUM_PRIME] =
159{
160  53ul,         97ul,         193ul,       389ul,       769ul,
161  1543ul,       3079ul,       6151ul,      12289ul,     24593ul,
162  49157ul,      98317ul,      196613ul,    393241ul,    786433ul,
163  1572869ul,    3145739ul,    6291469ul,   12582917ul,  25165843ul,
164  50331653ul,   100663319ul,  201326611ul, 402653189ul, 805306457ul,
165  1610612741ul, 3221225473ul, 4294967291ul
166};
167
168inline GUINT gim_next_prime(GUINT number)
169{
170    //Find nearest upper prime
171    GUINT result_ind = 0;
172    gim_binary_search(gim_prime_list,0,(GIM_NUM_PRIME-2),number,result_ind);
173
174    // inv: result_ind < 28
175    return gim_prime_list[result_ind];
176}
177
178
179
180//! A compact hash table implementation
181/*!
182A memory aligned compact hash table that coud be treated as an array.
183It could be a simple sorted array without the overhead of the hash key bucked, or could
184be a formely hash table with an array of keys.
185You can use switch_to_hashtable() and switch_to_sorted_array for saving space or increase speed.
186</br>
187
188<ul>
189<li> if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes.
190When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable.
191<li> If node_size != 0, then this container becomes a hash table for ever
192</ul>
193
194*/
195template<class T>
196class gim_hash_table
197{
198protected:
199    typedef GIM_HASH_TABLE_NODE<T> _node_type;
200
201    //!The nodes
202    //array< _node_type, SuperAllocator<_node_type> > m_nodes;
203    gim_array< _node_type > m_nodes;
204    //SuperBufferedArray< _node_type > m_nodes;
205    bool m_sorted;
206
207    /*! \defgroup HASH_TABLE_STRUCTURES
208    \brief
209    Hash table data management. The hash table has the indices to the corresponding m_nodes array
210    */
211    //! @{
212
213    GUINT * m_hash_table;//!<
214    GUINT m_table_size;//!<
215    GUINT m_node_size;//!<
216    GUINT m_min_hash_table_size;
217
218
219
220    //! Returns the cell index
221    inline GUINT _find_cell(GUINT hashkey)
222    {
223        _node_type * nodesptr = m_nodes.pointer();
224        GUINT start_index = (hashkey%m_table_size)*m_node_size;
225        GUINT end_index = start_index + m_node_size;
226
227        while(start_index<end_index)
228        {
229            GUINT value = m_hash_table[start_index];
230            if(value != GIM_INVALID_HASH)
231            {
232                if(nodesptr[value].m_key == hashkey) return start_index;
233            }
234            start_index++;
235        }
236        return GIM_INVALID_HASH;
237    }
238
239    //! Find the avaliable cell for the hashkey, and return an existing cell if it has the same hash key
240    inline GUINT _find_avaliable_cell(GUINT hashkey)
241    {
242        _node_type * nodesptr = m_nodes.pointer();
243        GUINT avaliable_index = GIM_INVALID_HASH;
244        GUINT start_index = (hashkey%m_table_size)*m_node_size;
245        GUINT end_index = start_index + m_node_size;
246
247        while(start_index<end_index)
248        {
249            GUINT value = m_hash_table[start_index];
250            if(value == GIM_INVALID_HASH)
251            {
252                if(avaliable_index==GIM_INVALID_HASH)
253                {
254                    avaliable_index = start_index;
255                }
256            }
257            else if(nodesptr[value].m_key == hashkey)
258            {
259                return start_index;
260            }
261            start_index++;
262        }
263        return avaliable_index;
264    }
265
266
267
268    //! reserves the memory for the hash table.
269    /*!
270    \pre hash table must be empty
271    \post reserves the memory for the hash table, an initializes all elements to GIM_INVALID_HASH.
272    */
273    inline void _reserve_table_memory(GUINT newtablesize)
274    {
275        if(newtablesize==0) return;
276        if(m_node_size==0) return;
277
278        //Get a Prime size
279
280        m_table_size = gim_next_prime(newtablesize);
281
282        GUINT datasize = m_table_size*m_node_size;
283        //Alloc the data buffer
284        m_hash_table =  (GUINT *)gim_alloc(datasize*sizeof(GUINT));
285    }
286
287    inline void _invalidate_keys()
288    {
289        GUINT datasize = m_table_size*m_node_size;
290        for(GUINT i=0;i<datasize;i++)
291        {
292            m_hash_table[i] = GIM_INVALID_HASH;// invalidate keys
293        }
294    }
295
296    //! Clear all memory for the hash table
297    inline void _clear_table_memory()
298    {
299        if(m_hash_table==NULL) return;
300        gim_free(m_hash_table);
301        m_hash_table = NULL;
302        m_table_size = 0;
303    }
304
305    //! Invalidates the keys (Assigning GIM_INVALID_HASH to all) Reorders the hash keys
306    inline void _rehash()
307    {
308        _invalidate_keys();
309
310        _node_type * nodesptr = m_nodes.pointer();
311        for(GUINT i=0;i<(GUINT)m_nodes.size();i++)
312        {
313            GUINT nodekey = nodesptr[i].m_key;
314            if(nodekey != GIM_INVALID_HASH)
315            {
316                //Search for the avaliable cell in buffer
317                GUINT index = _find_avaliable_cell(nodekey);
318
319
320                                if(m_hash_table[index]!=GIM_INVALID_HASH)
321                                {//The new index is alreade used... discard this new incomming object, repeated key
322                                    btAssert(m_hash_table[index]==nodekey);
323                                        nodesptr[i].m_key = GIM_INVALID_HASH;
324                                }
325                                else
326                                {
327                                        //;
328                                        //Assign the value for alloc
329                                        m_hash_table[index] = i;
330                                }
331            }
332        }
333    }
334
335    //! Resize hash table indices
336    inline void _resize_table(GUINT newsize)
337    {
338        //Clear memory
339        _clear_table_memory();
340        //Alloc the data
341        _reserve_table_memory(newsize);
342        //Invalidate keys and rehash
343        _rehash();
344    }
345
346    //! Destroy hash table memory
347    inline void _destroy()
348    {
349        if(m_hash_table==NULL) return;
350        _clear_table_memory();
351    }
352
353    //! Finds an avaliable hash table cell, and resizes the table if there isn't space
354    inline GUINT _assign_hash_table_cell(GUINT hashkey)
355    {
356        GUINT cell_index = _find_avaliable_cell(hashkey);
357
358        if(cell_index==GIM_INVALID_HASH)
359        {
360            //rehashing
361            _resize_table(m_table_size+1);
362            GUINT cell_index = _find_avaliable_cell(hashkey);
363            btAssert(cell_index!=GIM_INVALID_HASH);
364        }
365        return cell_index;
366    }
367
368    //! erase by index in hash table
369    inline bool _erase_by_index_hash_table(GUINT index)
370    {
371        if(index >= m_nodes.size()) return false;
372        if(m_nodes[index].m_key != GIM_INVALID_HASH)
373        {
374            //Search for the avaliable cell in buffer
375            GUINT cell_index = _find_cell(m_nodes[index].m_key);
376
377            btAssert(cell_index!=GIM_INVALID_HASH);
378            btAssert(m_hash_table[cell_index]==index);
379
380            m_hash_table[cell_index] = GIM_INVALID_HASH;
381        }
382
383        return this->_erase_unsorted(index);
384    }
385
386    //! erase by key in hash table
387    inline bool _erase_hash_table(GUINT hashkey)
388    {
389        if(hashkey == GIM_INVALID_HASH) return false;
390
391        //Search for the avaliable cell in buffer
392        GUINT cell_index = _find_cell(hashkey);
393        if(cell_index ==GIM_INVALID_HASH) return false;
394
395        GUINT index = m_hash_table[cell_index];
396        m_hash_table[cell_index] = GIM_INVALID_HASH;
397
398        return this->_erase_unsorted(index);
399    }
400
401
402
403    //! insert an element in hash table
404    /*!
405    If the element exists, this won't insert the element
406    \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
407    If so, the element has been inserted at the last position of the array.
408    */
409    inline GUINT _insert_hash_table(GUINT hashkey, const T & value)
410    {
411        if(hashkey==GIM_INVALID_HASH)
412        {
413            //Insert anyway
414            _insert_unsorted(hashkey,value);
415            return GIM_INVALID_HASH;
416        }
417
418        GUINT cell_index = _assign_hash_table_cell(hashkey);
419
420        GUINT value_key = m_hash_table[cell_index];
421
422        if(value_key!= GIM_INVALID_HASH) return value_key;// Not overrited
423
424        m_hash_table[cell_index] = m_nodes.size();
425
426        _insert_unsorted(hashkey,value);
427        return GIM_INVALID_HASH;
428    }
429
430    //! insert an element in hash table.
431    /*!
432    If the element exists, this replaces the element.
433    \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
434    If so, the element has been inserted at the last position of the array.
435    */
436    inline GUINT _insert_hash_table_replace(GUINT hashkey, const T & value)
437    {
438        if(hashkey==GIM_INVALID_HASH)
439        {
440            //Insert anyway
441            _insert_unsorted(hashkey,value);
442            return GIM_INVALID_HASH;
443        }
444
445        GUINT cell_index = _assign_hash_table_cell(hashkey);
446
447        GUINT value_key = m_hash_table[cell_index];
448
449        if(value_key!= GIM_INVALID_HASH)
450        {//replaces the existing
451            m_nodes[value_key] = _node_type(hashkey,value);
452            return value_key;// index of the replaced element
453        }
454
455        m_hash_table[cell_index] = m_nodes.size();
456
457        _insert_unsorted(hashkey,value);
458        return GIM_INVALID_HASH;
459
460    }
461
462    //! @}
463
464    /*! \defgroup SORTED_ARRAY_STRUCTURES
465    \brief
466    Sorted array data management. The hash table has the indices to the corresponding m_nodes array
467    */
468    //! @{
469    inline bool _erase_sorted(GUINT index)
470    {
471        if(index>=(GUINT)m_nodes.size()) return false;
472        m_nodes.erase_sorted(index);
473                if(m_nodes.size()<2) m_sorted = false;
474        return true;
475    }
476
477    //! faster, but unsorted
478    inline bool _erase_unsorted(GUINT index)
479    {
480        if(index>=m_nodes.size()) return false;
481
482        GUINT lastindex = m_nodes.size()-1;
483        if(index<lastindex && m_hash_table!=0)
484        {
485                        GUINT hashkey =  m_nodes[lastindex].m_key;
486                        if(hashkey!=GIM_INVALID_HASH)
487                        {
488                                //update the new position of the last element
489                                GUINT cell_index = _find_cell(hashkey);
490                                btAssert(cell_index!=GIM_INVALID_HASH);
491                                //new position of the last element which will be swaped
492                                m_hash_table[cell_index] = index;
493                        }
494        }
495        m_nodes.erase(index);
496        m_sorted = false;
497        return true;
498    }
499
500    //! Insert in position ordered
501    /*!
502    Also checks if it is needed to transform this container to a hash table, by calling check_for_switching_to_hashtable
503    */
504    inline void _insert_in_pos(GUINT hashkey, const T & value, GUINT pos)
505    {
506        m_nodes.insert(_node_type(hashkey,value),pos);
507        this->check_for_switching_to_hashtable();
508    }
509
510    //! Insert an element in an ordered array
511    inline GUINT _insert_sorted(GUINT hashkey, const T & value)
512    {
513        if(hashkey==GIM_INVALID_HASH || size()==0)
514        {
515            m_nodes.push_back(_node_type(hashkey,value));
516            return GIM_INVALID_HASH;
517        }
518        //Insert at last position
519        //Sort element
520
521
522        GUINT result_ind=0;
523        GUINT last_index = m_nodes.size()-1;
524        _node_type * ptr = m_nodes.pointer();
525
526        bool found = gim_binary_search_ex(
527                ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
528
529
530        //Insert before found index
531        if(found)
532        {
533            return result_ind;
534        }
535        else
536        {
537            _insert_in_pos(hashkey, value, result_ind);
538        }
539        return GIM_INVALID_HASH;
540    }
541
542    inline GUINT _insert_sorted_replace(GUINT hashkey, const T & value)
543    {
544        if(hashkey==GIM_INVALID_HASH || size()==0)
545        {
546            m_nodes.push_back(_node_type(hashkey,value));
547            return GIM_INVALID_HASH;
548        }
549        //Insert at last position
550        //Sort element
551        GUINT result_ind;
552        GUINT last_index = m_nodes.size()-1;
553        _node_type * ptr = m_nodes.pointer();
554
555        bool found = gim_binary_search_ex(
556                ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
557
558        //Insert before found index
559        if(found)
560        {
561            m_nodes[result_ind] = _node_type(hashkey,value);
562        }
563        else
564        {
565            _insert_in_pos(hashkey, value, result_ind);
566        }
567        return result_ind;
568    }
569
570    //! Fast insertion in m_nodes array
571    inline GUINT  _insert_unsorted(GUINT hashkey, const T & value)
572    {
573        m_nodes.push_back(_node_type(hashkey,value));
574        m_sorted = false;
575        return GIM_INVALID_HASH;
576    }
577
578    //! @}
579
580
581public:
582
583    /*!
584        <li> if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes.
585        When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable.
586        <li> If node_size != 0, then this container becomes a hash table for ever
587        </ul>
588    */
589    gim_hash_table(GUINT reserve_size = GIM_DEFAULT_HASH_TABLE_SIZE,
590                     GUINT node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE,
591                     GUINT min_hash_table_size = GIM_INVALID_HASH)
592    {
593        m_hash_table = NULL;
594        m_table_size = 0;
595        m_sorted = false;
596        m_node_size = node_size;
597        m_min_hash_table_size = min_hash_table_size;
598
599        if(m_node_size!=0)
600        {
601            if(reserve_size!=0)
602            {
603                m_nodes.reserve(reserve_size);
604                _reserve_table_memory(reserve_size);
605                _invalidate_keys();
606            }
607            else
608            {
609                m_nodes.reserve(GIM_DEFAULT_HASH_TABLE_SIZE);
610                _reserve_table_memory(GIM_DEFAULT_HASH_TABLE_SIZE);
611                _invalidate_keys();
612            }
613        }
614        else if(reserve_size!=0)
615        {
616            m_nodes.reserve(reserve_size);
617        }
618
619    }
620
621    ~gim_hash_table()
622    {
623        _destroy();
624    }
625
626    inline bool is_hash_table()
627    {
628        if(m_hash_table) return true;
629        return false;
630    }
631
632    inline bool is_sorted()
633    {
634        if(size()<2) return true;
635        return m_sorted;
636    }
637
638    bool sort()
639    {
640        if(is_sorted()) return true;
641        if(m_nodes.size()<2) return false;
642
643
644        _node_type * ptr = m_nodes.pointer();
645        GUINT siz = m_nodes.size();
646        gim_sort_hash_node_array(ptr,siz);
647        m_sorted=true;
648
649
650
651        if(m_hash_table)
652        {
653            _rehash();
654        }
655        return true;
656    }
657
658    bool switch_to_hashtable()
659    {
660        if(m_hash_table) return false;
661        if(m_node_size==0) m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
662        if(m_nodes.size()<GIM_DEFAULT_HASH_TABLE_SIZE)
663        {
664            _resize_table(GIM_DEFAULT_HASH_TABLE_SIZE);
665        }
666        else
667        {
668            _resize_table(m_nodes.size()+1);
669        }
670
671        return true;
672    }
673
674    bool switch_to_sorted_array()
675    {
676        if(m_hash_table==NULL) return true;
677        _clear_table_memory();
678        return sort();
679    }
680
681    //!If the container reaches the
682    bool check_for_switching_to_hashtable()
683    {
684        if(this->m_hash_table) return true;
685
686        if(!(m_nodes.size()< m_min_hash_table_size))
687        {
688            if(m_node_size == 0)
689            {
690                m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
691            }
692
693            _resize_table(m_nodes.size()+1);
694            return true;
695        }
696        return false;
697    }
698
699    inline void set_sorted(bool value)
700    {
701        m_sorted = value;
702    }
703
704    //! Retrieves the amount of keys.
705    inline GUINT size() const
706    {
707        return m_nodes.size();
708    }
709
710    //! Retrieves the hash key.
711    inline GUINT get_key(GUINT index) const
712    {
713        return m_nodes[index].m_key;
714    }
715
716    //! Retrieves the value by index
717    /*!
718    */
719    inline T * get_value_by_index(GUINT index)
720    {
721        return &m_nodes[index].m_data;
722    }
723
724    inline const T& operator[](GUINT index) const
725    {
726        return m_nodes[index].m_data;
727    }
728
729    inline T& operator[](GUINT index)
730    {
731        return m_nodes[index].m_data;
732    }
733
734    //! Finds the index of the element with the key
735    /*!
736    \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
737    If so, the element has been inserted at the last position of the array.
738    */
739    inline GUINT find(GUINT hashkey)
740    {
741        if(m_hash_table)
742        {
743            GUINT cell_index = _find_cell(hashkey);
744            if(cell_index==GIM_INVALID_HASH) return GIM_INVALID_HASH;
745            return m_hash_table[cell_index];
746        }
747                GUINT last_index = m_nodes.size();
748        if(last_index<2)
749        {
750                        if(last_index==0) return GIM_INVALID_HASH;
751            if(m_nodes[0].m_key == hashkey) return 0;
752            return GIM_INVALID_HASH;
753        }
754        else if(m_sorted)
755        {
756            //Binary search
757            GUINT result_ind = 0;
758                        last_index--;
759            _node_type *  ptr =  m_nodes.pointer();
760
761            bool found = gim_binary_search_ex(ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
762
763
764            if(found) return result_ind;
765        }
766        return GIM_INVALID_HASH;
767    }
768
769    //! Retrieves the value associated with the index
770    /*!
771    \return the found element, or null
772    */
773    inline T * get_value(GUINT hashkey)
774    {
775        GUINT index = find(hashkey);
776        if(index == GIM_INVALID_HASH) return NULL;
777        return &m_nodes[index].m_data;
778    }
779
780
781    /*!
782    */
783    inline bool erase_by_index(GUINT index)
784    {
785        if(index > m_nodes.size()) return false;
786
787        if(m_hash_table == NULL)
788        {
789            if(is_sorted())
790            {
791                return this->_erase_sorted(index);
792            }
793            else
794            {
795                return this->_erase_unsorted(index);
796            }
797        }
798        else
799        {
800            return this->_erase_by_index_hash_table(index);
801        }
802        return false;
803    }
804
805
806
807    inline bool erase_by_index_unsorted(GUINT index)
808    {
809        if(index > m_nodes.size()) return false;
810
811        if(m_hash_table == NULL)
812        {
813            return this->_erase_unsorted(index);
814        }
815        else
816        {
817            return this->_erase_by_index_hash_table(index);
818        }
819        return false;
820    }
821
822
823
824    /*!
825
826    */
827    inline bool erase_by_key(GUINT hashkey)
828    {
829        if(size()==0) return false;
830
831        if(m_hash_table)
832        {
833            return this->_erase_hash_table(hashkey);
834        }
835        //Binary search
836
837        if(is_sorted()==false) return false;
838
839        GUINT result_ind = find(hashkey);
840        if(result_ind!= GIM_INVALID_HASH)
841        {
842            return this->_erase_sorted(result_ind);
843        }
844        return false;
845    }
846
847    void clear()
848    {
849        m_nodes.clear();
850
851        if(m_hash_table==NULL) return;
852        GUINT datasize = m_table_size*m_node_size;
853        //Initialize the hashkeys.
854        GUINT i;
855        for(i=0;i<datasize;i++)
856        {
857            m_hash_table[i] = GIM_INVALID_HASH;// invalidate keys
858        }
859                m_sorted = false;
860    }
861
862    //! Insert an element into the hash
863    /*!
864    \return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position
865    of the existing element.
866    */
867    inline GUINT insert(GUINT hashkey, const T & element)
868    {
869        if(m_hash_table)
870        {
871            return this->_insert_hash_table(hashkey,element);
872        }
873        if(this->is_sorted())
874        {
875            return this->_insert_sorted(hashkey,element);
876        }
877        return this->_insert_unsorted(hashkey,element);
878    }
879
880    //! Insert an element into the hash, and could overrite an existing object with the same hash.
881    /*!
882    \return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position
883    of the replaced element.
884    */
885    inline GUINT insert_override(GUINT hashkey, const T & element)
886    {
887        if(m_hash_table)
888        {
889            return this->_insert_hash_table_replace(hashkey,element);
890        }
891        if(this->is_sorted())
892        {
893            return this->_insert_sorted_replace(hashkey,element);
894        }
895        this->_insert_unsorted(hashkey,element);
896        return m_nodes.size();
897    }
898
899
900
901    //! Insert an element into the hash,But if this container is a sorted array, this inserts it unsorted
902    /*!
903    */
904    inline GUINT insert_unsorted(GUINT hashkey,const T & element)
905    {
906        if(m_hash_table)
907        {
908            return this->_insert_hash_table(hashkey,element);
909        }
910        return this->_insert_unsorted(hashkey,element);
911    }
912
913
914};
915
916//! @}
917
918
919
920#endif // GIM_CONTAINERS_H_INCLUDED
Note: See TracBrowser for help on using the repository browser.