|
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 |