Orb/Doxygen/src/sortdict.h
changeset 3 d8fccb2cd802
parent 0 42188c7ea2d9
child 4 468f4c8d3d5b
equal deleted inserted replaced
2:932c358ece3e 3:d8fccb2cd802
       
     1 /******************************************************************************
       
     2  *
       
     3  * 
       
     4  *
       
     5  *
       
     6  * Copyright (C) 1997-2008 by Dimitri van Heesch.
       
     7  *
       
     8  * Permission to use, copy, modify, and distribute this software and its
       
     9  * documentation under the terms of the GNU General Public License is hereby 
       
    10  * granted. No representations are made about the suitability of this software 
       
    11  * for any purpose. It is provided "as is" without express or implied warranty.
       
    12  * See the GNU General Public License for more details.
       
    13  *
       
    14  * Documents produced by Doxygen are derivative works derived from the
       
    15  * input used in their production; they are not affected by this license.
       
    16  *
       
    17  */
       
    18 
       
    19 #ifndef _SORTDICT_H
       
    20 #define _SORTDICT_H
       
    21 
       
    22 #include "qtbc.h"
       
    23 #include <qlist.h>
       
    24 #include <qdict.h>
       
    25 #include <qintdict.h>
       
    26 
       
    27 #define AUTORESIZE 1
       
    28 
       
    29 #if AUTORESIZE
       
    30 const uint SDict_primes[] = 
       
    31 {
       
    32   17,
       
    33   29,
       
    34   47,
       
    35   71,
       
    36   113,
       
    37   179,
       
    38   293,
       
    39   457,
       
    40   733,
       
    41   1171,
       
    42   1871,
       
    43   2999,
       
    44   4787,
       
    45   7669,
       
    46   12251,
       
    47   19603,
       
    48   31379,
       
    49   50177,
       
    50   80287,
       
    51   128449,
       
    52   205519,
       
    53   328829,
       
    54   526139,
       
    55   841801,
       
    56   1346881,
       
    57   2155007,
       
    58   3448033,
       
    59   5516827,
       
    60   8826919,
       
    61   14123059,
       
    62   23538433,
       
    63   39230771,
       
    64   65384537,
       
    65   108974231,
       
    66   181623707,
       
    67   302706181,
       
    68   504510283,
       
    69   840850487,
       
    70   0xffffffff
       
    71 };
       
    72 #endif
       
    73 
       
    74 template<class T> class SDict;
       
    75 template<class T> class SIntDict;
       
    76 
       
    77 /*! internal wrapper class that redirects compareItems() to the 
       
    78  *  dictionary 
       
    79  */
       
    80 template<class T>
       
    81 class SList : public QList<T>
       
    82 {
       
    83   public:
       
    84     SList(SDict<T> *owner) : m_owner(owner) {}
       
    85     virtual ~SList() {}
       
    86     int compareItems(GCI item1,GCI item2)
       
    87     {
       
    88       return m_owner->compareItems(item1,item2);
       
    89     }
       
    90   private:
       
    91     SDict<T> *m_owner;  
       
    92 };
       
    93 
       
    94 /*! Ordered dictionary of elements of type T. 
       
    95  *  Internally uses a QList<T> and a QDict<T>.
       
    96  */
       
    97 template<class T>
       
    98 class SDict 
       
    99 {
       
   100   private:
       
   101     SList<T> *m_list;
       
   102     QDict<T> *m_dict;
       
   103     int m_sizeIndex;
       
   104     
       
   105   public:
       
   106     /*! Create an ordered dictionary.
       
   107      *  \param size The size of the dictionary. Should be a prime number for
       
   108      *              best distribution of elements.
       
   109      *  \param caseSensitive indicated whether the keys should be sorted
       
   110      *         in a case sensitive way.
       
   111      */
       
   112     SDict(int size,bool caseSensitive=TRUE) : m_sizeIndex(0)
       
   113     {
       
   114       m_list = new SList<T>(this);
       
   115 #if AUTORESIZE
       
   116       while ((uint)size>SDict_primes[m_sizeIndex]) m_sizeIndex++;
       
   117       m_dict = new QDict<T>(SDict_primes[m_sizeIndex],caseSensitive);
       
   118 #else
       
   119       m_dict = new QDict<T>(size,caseSensitive);
       
   120 #endif
       
   121     }
       
   122 
       
   123     /*! Destroys the dictionary */
       
   124     virtual ~SDict() 
       
   125     {
       
   126       delete m_list;
       
   127       delete m_dict;
       
   128     }
       
   129 
       
   130     /*! Appends an element to the dictionary. The element is owned by the
       
   131      *  dictionary.
       
   132      *  \param key The unique key to use to quicky find the item later on.
       
   133      *  \param d The compound to add.
       
   134      *  \sa find()
       
   135      */
       
   136     void append(const char *key,const T *d)
       
   137     {
       
   138       m_list->append(d);
       
   139       m_dict->insert(key,d);
       
   140 #if AUTORESIZE
       
   141       if (m_dict->size()>SDict_primes[m_sizeIndex])
       
   142       {
       
   143         m_dict->resize(SDict_primes[++m_sizeIndex]);
       
   144       }
       
   145 #endif
       
   146     }
       
   147 
       
   148     /*! Prepends an element to the dictionary. The element is owned by the
       
   149      *  dictionary.
       
   150      *  \param key The unique key to use to quicky find the item later on.
       
   151      *  \param d The compound to add.
       
   152      *  \sa find()
       
   153      */
       
   154     void prepend(const char *key,const T *d)
       
   155     {
       
   156       m_list->prepend(d);
       
   157       m_dict->insert(key,d);
       
   158 #if AUTORESIZE
       
   159       if (m_dict->size()>SDict_primes[m_sizeIndex])
       
   160       {
       
   161         m_dict->resize(SDict_primes[++m_sizeIndex]);
       
   162       }
       
   163 #endif
       
   164     }
       
   165 
       
   166     /*! Remove an item from the dictionary */
       
   167     bool remove(const char *key)
       
   168     {
       
   169       T *item = m_dict->take(key);
       
   170       return item ? m_list->remove(item) : FALSE;
       
   171     }
       
   172 
       
   173     /*! Take an item out of the dictionary without deleting it */
       
   174     T *take(const char *key)
       
   175     {
       
   176       T *item = m_dict->take(key);
       
   177       if (item)
       
   178       {
       
   179         int i = m_list->find(item);
       
   180         m_list->take(i);
       
   181       }
       
   182       return item;
       
   183     }
       
   184 
       
   185     /*! Sorts the members of the dictionary. First appending a number
       
   186      *  of members and then sorting them is faster (O(NlogN) than using 
       
   187      *  inSort() for each member (O(N^2)).
       
   188      */
       
   189     void sort()
       
   190     {
       
   191       m_list->sort();
       
   192     }
       
   193     /*! Inserts a compound into the dictionary in a sorted way.
       
   194      *  \param key The unique key to use to quicky find the item later on.
       
   195      *  \param d The compound to add.
       
   196      *  \sa find()
       
   197      */
       
   198     void inSort(const char *key,const T *d)
       
   199     {
       
   200       m_list->inSort(d);
       
   201       m_dict->insert(key,d);
       
   202 #if AUTORESIZE
       
   203       if (m_dict->size()>SDict_primes[m_sizeIndex])
       
   204       {
       
   205         m_dict->resize(SDict_primes[++m_sizeIndex]);
       
   206       }
       
   207 #endif
       
   208     }
       
   209 
       
   210     /*! Indicates whether or not the dictionary owns its elements */
       
   211     void setAutoDelete(bool val)
       
   212     {
       
   213       m_list->setAutoDelete(val);
       
   214     }
       
   215 
       
   216     /*! Looks up a compound given its key. 
       
   217      *  \param key The key to identify this element.
       
   218      *  \return The requested compound or zero if it cannot be found.
       
   219      *  \sa append() 
       
   220      */
       
   221     T *find(const char *key)
       
   222     {
       
   223       return m_dict->find(key);
       
   224     }
       
   225     T *find(const QCString &key)
       
   226     {
       
   227       return m_dict->find(key);
       
   228     }
       
   229     T *find(const QString &key)
       
   230     {
       
   231       return m_dict->find(key);
       
   232     }
       
   233 
       
   234     /*! Equavalent to find(). */
       
   235     T *operator[](const char *key) const
       
   236     {
       
   237       return m_dict->find(key);
       
   238     }
       
   239 
       
   240     /*! Returns the item at position \a i in the sorted dictionary */
       
   241     T *at(uint i)
       
   242     {
       
   243       return m_list->at(i);
       
   244     }
       
   245 
       
   246     /*! Function that is used to compare two items when sorting.
       
   247      *  Overload this to properly sort items.
       
   248      *  \sa inSort()
       
   249      */
       
   250     virtual int compareItems(GCI item1,GCI item2)
       
   251     {
       
   252       return item1!=item2;
       
   253     }
       
   254 
       
   255     /*! Clears the dictionary. Will delete items if setAutoDelete() was
       
   256      *  set to \c TRUE.
       
   257      *  \sa setAutoDelete
       
   258      */
       
   259     void clear()
       
   260     {
       
   261       m_list->clear();
       
   262       m_dict->clear();
       
   263     }
       
   264     
       
   265     /*! Returns the number of items stored in the dictionary
       
   266      */
       
   267     int count() const
       
   268     {
       
   269       return m_list->count();
       
   270     }
       
   271 
       
   272     class Iterator;         // first forward declare
       
   273     friend class Iterator;  // then make it a friend
       
   274     /*! Simple iterator for SDict. It iterates in the order in which the
       
   275      *  elements are stored.
       
   276      */
       
   277     class Iterator
       
   278     {
       
   279       public:
       
   280         /*! Create an iterator given the dictionary. */
       
   281         Iterator(const SDict<T> &dict)
       
   282         {
       
   283           m_li = new QListIterator<T>(*dict.m_list);
       
   284         }
       
   285 
       
   286         /*! Destroys the dictionary */
       
   287         virtual ~Iterator()
       
   288         {
       
   289           delete m_li;
       
   290         }
       
   291 
       
   292         /*! Set the iterator to the first element in the list. 
       
   293          *  \return The first compound, or zero if the list was empty. 
       
   294          */
       
   295         T *toFirst() const
       
   296         {
       
   297           return m_li->toFirst();
       
   298         }
       
   299 
       
   300         /*! Set the iterator to the last element in the list. 
       
   301          *  \return The first compound, or zero if the list was empty. 
       
   302          */
       
   303         T *toLast() const
       
   304         {
       
   305           return m_li->toLast();
       
   306         }
       
   307 
       
   308         /*! Returns the current compound */
       
   309         T *current() const
       
   310         {
       
   311           return m_li->current();
       
   312         }
       
   313         
       
   314         /*! Moves the iterator to the next element.
       
   315          *  \return the new "current" element, or zero if the iterator was
       
   316          *          already pointing at the last element.
       
   317          */
       
   318         T *operator++()
       
   319         {
       
   320           return m_li->operator++();
       
   321         }
       
   322 
       
   323         /*! Moves the iterator to the previous element.
       
   324          *  \return the new "current" element, or zero if the iterator was
       
   325          *          already pointing at the first element.
       
   326          */
       
   327         T *operator--()
       
   328         {
       
   329           return m_li->operator--();
       
   330         }
       
   331 
       
   332       private:
       
   333         QListIterator<T> *m_li;
       
   334     };
       
   335 
       
   336     class IteratorDict;         // first forward declare
       
   337     friend class IteratorDict;  // then make it a friend
       
   338     /*! Simple iterator for SDict. It iterates in over the dictionary elements
       
   339      *  in an unsorted way, but does provide information about the element's key.
       
   340      */
       
   341     class IteratorDict
       
   342     {
       
   343       public:
       
   344         /*! Create an iterator given the dictionary. */
       
   345         IteratorDict(const SDict<T> &dict)
       
   346         {
       
   347           m_di = new QDictIterator<T>(*dict.m_dict);
       
   348         }
       
   349 
       
   350         /*! Destroys the dictionary */
       
   351         virtual ~IteratorDict()
       
   352         {
       
   353           delete m_di;
       
   354         }
       
   355 
       
   356         /*! Set the iterator to the first element in the list. 
       
   357          *  \return The first compound, or zero if the list was empty. 
       
   358          */
       
   359         T *toFirst() const
       
   360         {
       
   361           return m_di->toFirst();
       
   362         }
       
   363 
       
   364         /*! Set the iterator to the last element in the list. 
       
   365          *  \return The first compound, or zero if the list was empty. 
       
   366          */
       
   367         T *toLast() const
       
   368         {
       
   369           return m_di->toLast();
       
   370         }
       
   371 
       
   372         /*! Returns the current compound */
       
   373         T *current() const
       
   374         {
       
   375           return m_di->current();
       
   376         }
       
   377         
       
   378         /*! Returns the current key */
       
   379         QCString currentKey() const
       
   380         {
       
   381           return m_di->currentKey();
       
   382         }
       
   383         
       
   384         /*! Moves the iterator to the next element.
       
   385          *  \return the new "current" element, or zero if the iterator was
       
   386          *          already pointing at the last element.
       
   387          */
       
   388         T *operator++()
       
   389         {
       
   390           return m_di->operator++();
       
   391         }
       
   392 
       
   393         /*! Moves the iterator to the previous element.
       
   394          *  \return the new "current" element, or zero if the iterator was
       
   395          *          already pointing at the first element.
       
   396          */
       
   397         T *operator--()
       
   398         {
       
   399           return m_di->operator--();
       
   400         }
       
   401 
       
   402       private:
       
   403         QDictIterator<T> *m_di;
       
   404     };
       
   405 };
       
   406 
       
   407 /*! internal wrapper class that redirects compareItems() to the 
       
   408  *  dictionary 
       
   409  */
       
   410 template<class T>
       
   411 class SIntList : public QList<T>
       
   412 {
       
   413   public:
       
   414     SIntList(SIntDict<T> *owner) : m_owner(owner) {}
       
   415     virtual ~SIntList() {}
       
   416     int compareItems(GCI item1,GCI item2)
       
   417     {
       
   418       return m_owner->compareItems(item1,item2);
       
   419     }
       
   420   private:
       
   421     SIntDict<T> *m_owner;  
       
   422 };
       
   423 
       
   424 /*! Ordered dictionary of elements of type T. 
       
   425  *  Internally uses a QList<T> and a QIntDict<T>.
       
   426  */
       
   427 template<class T>
       
   428 class SIntDict 
       
   429 {
       
   430   private:
       
   431     SIntList<T> *m_list;
       
   432     QIntDict<T> *m_dict;
       
   433     int m_sizeIndex;
       
   434     
       
   435   public:
       
   436     /*! Create an ordered dictionary.
       
   437      *  \param size The size of the dictionary. Should be a prime number for
       
   438      *              best distribution of elements.
       
   439      */
       
   440     SIntDict(int size) : m_sizeIndex(0)
       
   441     {
       
   442       m_list = new SIntList<T>(this);
       
   443 #if AUTORESIZE
       
   444       while ((uint)size>SDict_primes[m_sizeIndex]) m_sizeIndex++;
       
   445       m_dict = new QIntDict<T>(SDict_primes[m_sizeIndex]);
       
   446 #else
       
   447       m_dict = new QIntDict<T>(size);
       
   448 #endif
       
   449     }
       
   450 
       
   451     /*! Destroys the dictionary */
       
   452     virtual ~SIntDict() 
       
   453     {
       
   454       delete m_list;
       
   455       delete m_dict;
       
   456     }
       
   457 
       
   458     /*! Appends a compound to the dictionary. The element is owned by the
       
   459      *  dictionary.
       
   460      *  \param key The unique key to use to quicky find the item later on.
       
   461      *  \param d The compound to add.
       
   462      *  \sa find()
       
   463      */
       
   464     void append(int key,const T *d)
       
   465     {
       
   466       m_list->append(d);
       
   467       m_dict->insert(key,d);
       
   468 #if AUTORESIZE
       
   469       if (m_dict->size()>SDict_primes[m_sizeIndex])
       
   470       {
       
   471         m_dict->resize(SDict_primes[++m_sizeIndex]);
       
   472       }
       
   473 #endif
       
   474     }
       
   475 
       
   476     /*! Prepend a compound to the dictionary. The element is owned by the
       
   477      *  dictionary.
       
   478      *  \param key The unique key to use to quicky find the item later on.
       
   479      *  \param d The compound to add.
       
   480      *  \sa find()
       
   481      */
       
   482     void prepend(int key,const T *d)
       
   483     {
       
   484       m_list->prepend(d);
       
   485       m_dict->insert(key,d);
       
   486 #if AUTORESIZE
       
   487       if (m_dict->size()>SDict_primes[m_sizeIndex])
       
   488       {
       
   489         m_dict->resize(SDict_primes[++m_sizeIndex]);
       
   490       }
       
   491 #endif
       
   492     }
       
   493 
       
   494     /*! Remove an item from the dictionary */
       
   495     bool remove(int key)
       
   496     {
       
   497       T *item = m_dict->take(key);
       
   498       return item ? m_list->remove(item) : FALSE;
       
   499     }
       
   500 
       
   501     /*! Sorts the members of the dictionary. First appending a number
       
   502      *  of members and then sorting them is faster (O(NlogN) than using 
       
   503      *  inSort() for each member (O(N^2)).
       
   504      */
       
   505     void sort()
       
   506     {
       
   507       m_list->sort();
       
   508     }
       
   509 
       
   510     /*! Inserts a compound into the dictionary in a sorted way.
       
   511      *  \param key The unique key to use to quicky find the item later on.
       
   512      *  \param d The compound to add.
       
   513      *  \sa find()
       
   514      */
       
   515     void inSort(int key,const T *d)
       
   516     {
       
   517       m_list->inSort(d);
       
   518       m_dict->insert(key,d);
       
   519 #if AUTORESIZE
       
   520       if (m_dict->size()>SDict_primes[m_sizeIndex])
       
   521       {
       
   522         m_dict->resize(SDict_primes[++m_sizeIndex]);
       
   523       }
       
   524 #endif
       
   525     }
       
   526 
       
   527     /*! Indicates whether or not the dictionary owns its elements */
       
   528     void setAutoDelete(bool val)
       
   529     {
       
   530       m_list->setAutoDelete(val);
       
   531     }
       
   532 
       
   533     /*! Looks up a compound given its key. 
       
   534      *  \param key The key to identify this element.
       
   535      *  \return The requested compound or zero if it cannot be found.
       
   536      *  \sa append() 
       
   537      */
       
   538     T *find(int key)
       
   539     {
       
   540       return m_dict->find(key);
       
   541     }
       
   542 
       
   543     /*! Equavalent to find(). */
       
   544     T *operator[](int key) const
       
   545     {
       
   546       return m_dict->find(key);
       
   547     }
       
   548 
       
   549     /*! Returns the item at position \a i in the sorted dictionary */
       
   550     T *at(uint i)
       
   551     {
       
   552       return m_list->at(i);
       
   553     }
       
   554 
       
   555     /*! Function that is used to compare two items when sorting.
       
   556      *  Overload this to properly sort items.
       
   557      *  \sa inSort()
       
   558      */
       
   559     virtual int compareItems(GCI item1,GCI item2)
       
   560     {
       
   561       return item1!=item2;
       
   562     }
       
   563 
       
   564     /*! Clears the dictionary. Will delete items if setAutoDelete() was
       
   565      *  set to \c TRUE.
       
   566      *  \sa setAutoDelete
       
   567      */
       
   568     void clear()
       
   569     {
       
   570       m_list->clear();
       
   571       m_dict->clear();
       
   572     }
       
   573 
       
   574     /*! Returns the number of items stored in the dictionary
       
   575      */
       
   576     int count()
       
   577     {
       
   578       return m_list->count();
       
   579     }
       
   580 
       
   581     class Iterator;         // first forward declare
       
   582     friend class Iterator;  // then make it a friend
       
   583     /*! Simple iterator for SDict. It iterates in the order in which the
       
   584      *  elements are stored.
       
   585      */
       
   586     class Iterator
       
   587     {
       
   588       public:
       
   589         /*! Create an iterator given the dictionary. */
       
   590         Iterator(const SIntDict<T> &dict)
       
   591         {
       
   592           m_li = new QListIterator<T>(*dict.m_list);
       
   593         }
       
   594         
       
   595         /*! Destroys the dictionary */
       
   596         virtual ~Iterator()
       
   597         {
       
   598           delete m_li;
       
   599         }
       
   600         
       
   601         /*! Set the iterator to the first element in the list. 
       
   602          *  \return The first compound, or zero if the list was empty. 
       
   603          */
       
   604         T *toFirst() const
       
   605         {
       
   606           return m_li->toFirst();
       
   607         }
       
   608         
       
   609         /*! Set the iterator to the last element in the list. 
       
   610          *  \return The first compound, or zero if the list was empty. 
       
   611          */
       
   612         T *toLast() const
       
   613         {
       
   614           return m_li->toLast();
       
   615         }
       
   616         
       
   617         /*! Returns the current compound */
       
   618         T *current() const
       
   619         {
       
   620           return m_li->current();
       
   621         }
       
   622         
       
   623         /*! Moves the iterator to the next element.
       
   624          *  \return the new "current" element, or zero if the iterator was
       
   625          *          already pointing at the last element.
       
   626          */
       
   627         T *operator++()
       
   628         {
       
   629           return m_li->operator++();
       
   630         }
       
   631         
       
   632         /*! Moves the iterator to the previous element.
       
   633          *  \return the new "current" element, or zero if the iterator was
       
   634          *          already pointing at the first element.
       
   635          */
       
   636         T *operator--()
       
   637         {
       
   638           return m_li->operator--();
       
   639         }
       
   640 
       
   641       private:
       
   642         QListIterator<T> *m_li;
       
   643     };
       
   644 
       
   645 };
       
   646 
       
   647 #endif