Root/
Source at commit 1322 created 12 years 8 months ago. By meklort, Add doxygen to utils folder | |
---|---|
1 | /****************************************************************************␊ |
2 | ** ␊ |
3 | **␊ |
4 | ** Implementation of QGCache and QGCacheIterator classes␊ |
5 | **␊ |
6 | ** Created : 950208␊ |
7 | **␊ |
8 | ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.␊ |
9 | **␊ |
10 | ** This file is part of the tools module of the Qt GUI Toolkit.␊ |
11 | **␊ |
12 | ** This file may be distributed under the terms of the Q Public License␊ |
13 | ** as defined by Trolltech AS of Norway and appearing in the file␊ |
14 | ** LICENSE.QPL included in the packaging of this file.␊ |
15 | **␊ |
16 | ** This file may be distributed and/or modified under the terms of the␊ |
17 | ** GNU General Public License version 2 as published by the Free Software␊ |
18 | ** Foundation and appearing in the file LICENSE.GPL included in the␊ |
19 | ** packaging of this file.␊ |
20 | **␊ |
21 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition␊ |
22 | ** licenses may use this file in accordance with the Qt Commercial License␊ |
23 | ** Agreement provided with the Software.␊ |
24 | **␊ |
25 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE␊ |
26 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.␊ |
27 | **␊ |
28 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for␊ |
29 | ** information about Qt Commercial License Agreements.␊ |
30 | ** See http://www.trolltech.com/qpl/ for QPL licensing information.␊ |
31 | ** See http://www.trolltech.com/gpl/ for GPL licensing information.␊ |
32 | **␊ |
33 | ** Contact info@trolltech.com if any conditions of this licensing are␊ |
34 | ** not clear to you.␊ |
35 | **␊ |
36 | **********************************************************************/␊ |
37 | ␊ |
38 | #include "qgcache.h"␊ |
39 | #include "qlist.h"␊ |
40 | #include "qdict.h"␊ |
41 | #include "qstring.h"␊ |
42 | ␊ |
43 | ␊ |
44 | // NOT REVISED␊ |
45 | /*!␊ |
46 | \class QGCache qgcache.h␊ |
47 | ␊ |
48 | \brief The QGCache class is an internal class for implementing QCache template classes.␊ |
49 | ␊ |
50 | QGCache is a strictly internal class that acts as a base class for the␊ |
51 | \link collection.html collection classes\endlink QCache and QIntCache.␊ |
52 | */␊ |
53 | ␊ |
54 | ␊ |
55 | /*****************************************************************************␊ |
56 | QGCacheItem class (internal cache item)␊ |
57 | *****************************************************************************/␊ |
58 | ␊ |
59 | struct QCacheItem␊ |
60 | {␊ |
61 | QCacheItem( void *k, QCollection::Item d, int c, short p )␊ |
62 | ␉: priority(p), skipPriority(p), cost(c), key(k), data(d), node(0) {}␊ |
63 | short␉priority;␊ |
64 | short␉skipPriority;␊ |
65 | int␉␉cost;␊ |
66 | void *key;␊ |
67 | QCollection::Item data;␊ |
68 | QLNode *node;␊ |
69 | };␊ |
70 | ␊ |
71 | ␊ |
72 | /*****************************************************************************␊ |
73 | QCList class (internal list of cache items)␊ |
74 | *****************************************************************************/␊ |
75 | ␊ |
76 | class QCList : private QList<QCacheItem>␊ |
77 | {␊ |
78 | friend class QGCacheIterator;␊ |
79 | friend class QCListIt;␊ |
80 | public:␊ |
81 | QCList()␉{}␊ |
82 | ~QCList();␊ |
83 | ␊ |
84 | void␉insert( QCacheItem * );␉␉// insert according to priority␊ |
85 | void␉insert( int, QCacheItem * );␊ |
86 | void␉take( QCacheItem * );␊ |
87 | void␉reference( QCacheItem * );␊ |
88 | ␊ |
89 | void␉setAutoDelete( bool del ) { QCollection::setAutoDelete(del); }␊ |
90 | ␊ |
91 | bool␉removeFirst()␉{ return QList<QCacheItem>::removeFirst(); }␊ |
92 | bool␉removeLast()␉{ return QList<QCacheItem>::removeLast(); }␊ |
93 | ␊ |
94 | QCacheItem *first()␉␉{ return QList<QCacheItem>::first(); }␊ |
95 | QCacheItem *last()␉␉{ return QList<QCacheItem>::last(); }␊ |
96 | QCacheItem *prev()␉␉{ return QList<QCacheItem>::prev(); }␊ |
97 | QCacheItem *next()␉␉{ return QList<QCacheItem>::next(); }␊ |
98 | ␊ |
99 | #if defined(DEBUG)␊ |
100 | int␉␉inserts;␉␉␉// variables for statistics␊ |
101 | int␉␉insertCosts;␊ |
102 | int␉␉insertMisses;␊ |
103 | int␉␉finds;␊ |
104 | int␉␉hits;␊ |
105 | int␉␉hitCosts;␊ |
106 | int␉␉dumps;␊ |
107 | int␉␉dumpCosts;␊ |
108 | #endif␊ |
109 | };␊ |
110 | ␊ |
111 | ␊ |
112 | QCList::~QCList()␊ |
113 | {␊ |
114 | #if defined(DEBUG)␊ |
115 | ASSERT( count() == 0 );␊ |
116 | #endif␊ |
117 | }␊ |
118 | ␊ |
119 | ␊ |
120 | void QCList::insert( QCacheItem *ci )␊ |
121 | {␊ |
122 | QCacheItem *item = first();␊ |
123 | while( item && item->skipPriority > ci->priority ) {␊ |
124 | ␉item->skipPriority--;␊ |
125 | ␉item = next();␊ |
126 | }␊ |
127 | if ( item )␊ |
128 | ␉QList<QCacheItem>::insert( at(), ci );␊ |
129 | else␊ |
130 | ␉append( ci );␊ |
131 | #if defined(DEBUG)␊ |
132 | ASSERT( ci->node == 0 );␊ |
133 | #endif␊ |
134 | ci->node = currentNode();␊ |
135 | }␊ |
136 | ␊ |
137 | inline void QCList::insert( int i, QCacheItem *ci )␊ |
138 | {␊ |
139 | QList<QCacheItem>::insert( i, ci );␊ |
140 | #if defined(DEBUG)␊ |
141 | ASSERT( ci->node == 0 );␊ |
142 | #endif␊ |
143 | ci->node = currentNode();␊ |
144 | }␊ |
145 | ␊ |
146 | ␊ |
147 | void QCList::take( QCacheItem *ci )␊ |
148 | {␊ |
149 | if ( ci ) {␊ |
150 | #if defined(DEBUG)␊ |
151 | ␉ASSERT( ci->node != 0 );␊ |
152 | #endif␊ |
153 | ␉takeNode( ci->node );␊ |
154 | ␉ci->node = 0;␊ |
155 | }␊ |
156 | }␊ |
157 | ␊ |
158 | ␊ |
159 | inline void QCList::reference( QCacheItem *ci )␊ |
160 | {␊ |
161 | #if defined(DEBUG)␊ |
162 | ASSERT( ci != 0 && ci->node != 0 );␊ |
163 | #endif␊ |
164 | ci->skipPriority = ci->priority;␊ |
165 | relinkNode( ci->node );␉␉␉// relink as first item␊ |
166 | }␊ |
167 | ␊ |
168 | ␊ |
169 | class QCListIt: public QListIterator<QCacheItem>␊ |
170 | {␊ |
171 | public:␊ |
172 | QCListIt( const QCList *p ): QListIterator<QCacheItem>( *p ) {}␊ |
173 | QCListIt( const QCListIt *p ): QListIterator<QCacheItem>( *p ) {}␊ |
174 | };␊ |
175 | ␊ |
176 | ␊ |
177 | /*****************************************************************************␊ |
178 | QCDict class (internal dictionary of cache items)␊ |
179 | *****************************************************************************/␊ |
180 | ␊ |
181 | //␊ |
182 | // Since we need to decide if the dictionary should use an int or const␊ |
183 | // char * key (the "bool trivial" argument in the constructor below)␊ |
184 | // we cannot use the macro/template dict, but inherit directly from QGDict.␊ |
185 | //␊ |
186 | ␊ |
187 | class QCDict : public QGDict␊ |
188 | {␊ |
189 | public:␊ |
190 | QCDict( uint size, uint kt, bool caseSensitive, bool copyKeys )␊ |
191 | ␉: QGDict( size, (KeyType)kt, caseSensitive, copyKeys ) {}␊ |
192 | ␊ |
193 | QCacheItem *find_string(const QString &key) const␊ |
194 | ␉{ return (QCacheItem*)((QCDict*)this)->look_string(key, 0, 0); }␊ |
195 | QCacheItem *find_ascii(const char *key) const␊ |
196 | ␉{ return (QCacheItem*)((QCDict*)this)->look_ascii(key, 0, 0); }␊ |
197 | QCacheItem *find_int(long key) const␊ |
198 | ␉{ return (QCacheItem*)((QCDict*)this)->look_int(key, 0, 0); }␊ |
199 | ␊ |
200 | QCacheItem *take_string(const QString &key)␊ |
201 | ␉{ return (QCacheItem*)QGDict::take_string(key); }␊ |
202 | QCacheItem *take_ascii(const char *key)␊ |
203 | ␉{ return (QCacheItem*)QGDict::take_ascii(key); }␊ |
204 | QCacheItem *take_int(long key)␊ |
205 | ␉{ return (QCacheItem*)QGDict::take_int(key); }␊ |
206 | ␊ |
207 | bool insert_string( const QString &key, const QCacheItem *ci )␊ |
208 | ␉{ return QGDict::look_string(key,(Item)ci,1)!=0;}␊ |
209 | bool insert_ascii( const char *key, const QCacheItem *ci )␊ |
210 | ␉{ return QGDict::look_ascii(key,(Item)ci,1)!=0;}␊ |
211 | bool insert_int( long key, const QCacheItem *ci )␊ |
212 | ␉{ return QGDict::look_int(key,(Item)ci,1)!=0;}␊ |
213 | ␊ |
214 | bool remove_string( QCacheItem *item )␊ |
215 | ␉{ return QGDict::remove_string(*((QString*)(item->key)),item); }␊ |
216 | bool remove_ascii( QCacheItem *item )␊ |
217 | ␉{ return QGDict::remove_ascii((const char *)item->key,item); }␊ |
218 | bool remove_int( QCacheItem *item )␊ |
219 | ␉{ return QGDict::remove_int((long)item->key,item);}␊ |
220 | ␊ |
221 | void statistics()␉␉␉{ QGDict::statistics(); }␊ |
222 | };␊ |
223 | ␊ |
224 | ␊ |
225 | /*****************************************************************************␊ |
226 | QGDict member functions␊ |
227 | *****************************************************************************/␊ |
228 | ␊ |
229 | /*!␊ |
230 | \internal␊ |
231 | Constructs a cache.␊ |
232 | */␊ |
233 | ␊ |
234 | QGCache::QGCache( int maxCost, uint size, KeyType kt, bool caseSensitive,␊ |
235 | ␉␉ bool copyKeys )␊ |
236 | {␊ |
237 | keytype = kt;␊ |
238 | lruList = new QCList;␊ |
239 | CHECK_PTR( lruList );␊ |
240 | lruList->setAutoDelete( TRUE );␊ |
241 | copyk = ((keytype == AsciiKey) && copyKeys);␊ |
242 | dict = new QCDict( size, kt, caseSensitive, FALSE );␊ |
243 | CHECK_PTR( dict );␊ |
244 | mCost = maxCost;␊ |
245 | tCost = 0;␊ |
246 | #if defined(DEBUG)␊ |
247 | lruList->inserts␉ = 0;␊ |
248 | lruList->insertCosts = 0;␊ |
249 | lruList->insertMisses = 0;␊ |
250 | lruList->finds␉ = 0;␊ |
251 | lruList->hits␉ = 0;␊ |
252 | lruList->hitCosts␉ = 0;␊ |
253 | lruList->dumps␉ = 0;␊ |
254 | lruList->dumpCosts␉ = 0;␊ |
255 | #endif␊ |
256 | }␊ |
257 | ␊ |
258 | /*!␊ |
259 | \internal␊ |
260 | Cannot copy a cache.␊ |
261 | */␊ |
262 | ␊ |
263 | QGCache::QGCache( const QGCache & )␊ |
264 | : QCollection()␊ |
265 | {␊ |
266 | #if defined(CHECK_NULL)␊ |
267 | qFatal( "QGCache::QGCache(QGCache &): Cannot copy a cache" );␊ |
268 | #endif␊ |
269 | }␊ |
270 | ␊ |
271 | /*!␊ |
272 | \internal␊ |
273 | Removes all items from the cache and destroys it.␊ |
274 | */␊ |
275 | ␊ |
276 | QGCache::~QGCache()␊ |
277 | {␊ |
278 | clear();␉␉␉␉␉// delete everything first␊ |
279 | delete dict;␊ |
280 | delete lruList;␊ |
281 | }␊ |
282 | ␊ |
283 | /*!␊ |
284 | \internal␊ |
285 | Cannot assign a cache.␊ |
286 | */␊ |
287 | ␊ |
288 | QGCache &QGCache::operator=( const QGCache & )␊ |
289 | {␊ |
290 | #if defined(CHECK_NULL)␊ |
291 | qFatal( "QGCache::operator=: Cannot copy a cache" );␊ |
292 | #endif␊ |
293 | return *this;␉␉␉␉// satisfy the compiler␊ |
294 | }␊ |
295 | ␊ |
296 | ␊ |
297 | /*!␊ |
298 | \fn uint QGCache::count() const␊ |
299 | \internal␊ |
300 | Returns the number of items in the cache.␊ |
301 | */␊ |
302 | ␊ |
303 | /*!␊ |
304 | \fn uint QGCache::size() const␊ |
305 | \internal␊ |
306 | Returns the size of the hash array.␊ |
307 | */␊ |
308 | ␊ |
309 | /*!␊ |
310 | \fn int QGCache::maxCost() const␊ |
311 | \internal␊ |
312 | Returns the maximum cache cost.␊ |
313 | */␊ |
314 | ␊ |
315 | /*!␊ |
316 | \fn int QGCache::totalCost() const␊ |
317 | \internal␊ |
318 | Returns the total cache cost.␊ |
319 | */␊ |
320 | ␊ |
321 | /*!␊ |
322 | \internal␊ |
323 | Sets the maximum cache cost.␊ |
324 | */␊ |
325 | ␊ |
326 | void QGCache::setMaxCost( int maxCost )␊ |
327 | {␊ |
328 | if ( maxCost < tCost ) {␊ |
329 | ␉if ( !makeRoomFor(tCost - maxCost) )␉// remove excess cost␊ |
330 | ␉ return;␊ |
331 | }␊ |
332 | mCost = maxCost;␊ |
333 | }␊ |
334 | ␊ |
335 | ␊ |
336 | /*!␊ |
337 | \internal␊ |
338 | Inserts an item into the cache.␊ |
339 | ␊ |
340 | \warning If this function returns FALSE, you must delete \a data␊ |
341 | yourself. Additionally, be very careful about using \a data after␊ |
342 | calling this function, as any other insertions into the cache, from␊ |
343 | anywhere in the application, or within Qt itself, could cause the␊ |
344 | data to be discarded from the cache, and the pointer to become␊ |
345 | invalid.␊ |
346 | */␊ |
347 | ␊ |
348 | bool QGCache::insert_string( const QString &key, QCollection::Item data,␊ |
349 | ␉␉␉ int cost, int priority)␊ |
350 | {␊ |
351 | if ( tCost + cost > mCost ) {␊ |
352 | ␉if ( !makeRoomFor(tCost + cost - mCost, priority) ) {␊ |
353 | #if defined(DEBUG)␊ |
354 | ␉ lruList->insertMisses++;␊ |
355 | #endif␊ |
356 | ␉ return FALSE;␊ |
357 | ␉}␊ |
358 | }␊ |
359 | #if defined(DEBUG)␊ |
360 | ASSERT( keytype == StringKey );␊ |
361 | lruList->inserts++;␊ |
362 | lruList->insertCosts += cost;␊ |
363 | #endif␊ |
364 | if ( priority < -32768 )␊ |
365 | ␉priority = -32768;␊ |
366 | else if ( priority > 32767 )␊ |
367 | ␉priority = 32677;␊ |
368 | QCacheItem *ci = new QCacheItem( new QString(key), newItem(data),␊ |
369 | ␉␉␉␉ cost, (short)priority );␊ |
370 | CHECK_PTR( ci );␊ |
371 | lruList->insert( 0, ci );␊ |
372 | dict->insert_string( key, ci );␊ |
373 | tCost += cost;␊ |
374 | return TRUE;␊ |
375 | }␊ |
376 | ␊ |
377 | ␊ |
378 | /*! \internal */␊ |
379 | ␊ |
380 | bool QGCache::insert_other( const char *key, QCollection::Item data,␊ |
381 | ␉␉␉ int cost, int priority)␊ |
382 | {␊ |
383 | if ( tCost + cost > mCost ) {␊ |
384 | ␉if ( !makeRoomFor(tCost + cost - mCost, priority) ) {␊ |
385 | #if defined(DEBUG)␊ |
386 | ␉ lruList->insertMisses++;␊ |
387 | #endif␊ |
388 | ␉ return FALSE;␊ |
389 | ␉}␊ |
390 | }␊ |
391 | #if defined(DEBUG)␊ |
392 | ASSERT( keytype != StringKey );␊ |
393 | lruList->inserts++;␊ |
394 | lruList->insertCosts += cost;␊ |
395 | #endif␊ |
396 | if ( keytype == AsciiKey && copyk )␊ |
397 | ␉key = qstrdup( key );␊ |
398 | if ( priority < -32768 )␊ |
399 | ␉priority = -32768;␊ |
400 | else if ( priority > 32767 )␊ |
401 | ␉priority = 32677;␊ |
402 | QCacheItem *ci = new QCacheItem( (void*)key, newItem(data), cost,␊ |
403 | ␉␉␉␉ (short)priority );␊ |
404 | CHECK_PTR( ci );␊ |
405 | lruList->insert( 0, ci );␊ |
406 | if ( keytype == AsciiKey )␊ |
407 | ␉dict->insert_ascii( key, ci );␊ |
408 | else␊ |
409 | ␉dict->insert_int( (long)key, ci );␊ |
410 | tCost += cost;␊ |
411 | return TRUE;␊ |
412 | }␊ |
413 | ␊ |
414 | ␊ |
415 | /*!␊ |
416 | \internal␊ |
417 | Removes an item from the cache.␊ |
418 | */␊ |
419 | ␊ |
420 | bool QGCache::remove_string( const QString &key )␊ |
421 | {␊ |
422 | Item d = take_string( key );␊ |
423 | if ( d )␊ |
424 | ␉deleteItem( d );␊ |
425 | return d != 0;␊ |
426 | }␊ |
427 | ␊ |
428 | ␊ |
429 | /*! \internal */␊ |
430 | ␊ |
431 | bool QGCache::remove_other( const char *key )␊ |
432 | {␊ |
433 | Item d = take_other( key );␊ |
434 | if ( d )␊ |
435 | ␉deleteItem( d );␊ |
436 | return d != 0;␊ |
437 | }␊ |
438 | ␊ |
439 | ␊ |
440 | /*!␊ |
441 | \internal␊ |
442 | Takes an item out of the cache (no delete).␊ |
443 | */␊ |
444 | ␊ |
445 | QCollection::Item QGCache::take_string( const QString &key )␊ |
446 | {␊ |
447 | QCacheItem *ci = dict->take_string( key );␉// take from dict␊ |
448 | Item d;␊ |
449 | if ( ci ) {␊ |
450 | ␉d = ci->data;␊ |
451 | ␉tCost -= ci->cost;␊ |
452 | ␉lruList->take( ci );␉␉␉// take from list␊ |
453 | ␉delete (QString*)ci->key;␊ |
454 | ␉delete ci;␊ |
455 | } else {␊ |
456 | ␉d = 0;␊ |
457 | }␊ |
458 | return d;␊ |
459 | }␊ |
460 | ␊ |
461 | /*!␊ |
462 | \internal␊ |
463 | Takes an item out of the cache (no delete).␊ |
464 | */␊ |
465 | ␊ |
466 | QCollection::Item QGCache::take_other( const char *key )␊ |
467 | {␊ |
468 | QCacheItem *ci;␊ |
469 | if ( keytype == AsciiKey )␊ |
470 | ␉ci = dict->take_ascii( key );␊ |
471 | else␊ |
472 | ␉ci = dict->take_int( (long)key );␊ |
473 | Item d;␊ |
474 | if ( ci ) {␊ |
475 | ␉d = ci->data;␊ |
476 | ␉tCost -= ci->cost;␊ |
477 | ␉lruList->take( ci );␉␉␉// take from list␊ |
478 | ␉if ( copyk )␊ |
479 | ␉ delete [] (char *)ci->key;␊ |
480 | ␉delete ci;␊ |
481 | } else {␊ |
482 | ␉d = 0;␊ |
483 | }␊ |
484 | return d;␊ |
485 | }␊ |
486 | ␊ |
487 | ␊ |
488 | /*!␊ |
489 | \internal␊ |
490 | Clears the cache.␊ |
491 | */␊ |
492 | ␊ |
493 | void QGCache::clear()␊ |
494 | {␊ |
495 | QCacheItem *ci;␊ |
496 | while ( (ci = lruList->first()) ) {␊ |
497 | ␉switch ( keytype ) {␊ |
498 | ␉ case StringKey:␊ |
499 | ␉␉dict->remove_string( ci );␊ |
500 | ␉␉delete (QString*)ci->key;␊ |
501 | ␉␉break;␊ |
502 | ␉ case AsciiKey:␊ |
503 | ␉␉dict->remove_ascii( ci );␊ |
504 | ␉␉if ( copyk )␊ |
505 | ␉␉ delete [] (char*)ci->key;␊ |
506 | ␉␉break;␊ |
507 | ␉ case IntKey:␊ |
508 | ␉␉dict->remove_int( ci );␊ |
509 | ␉␉break;␊ |
510 | ␉ case PtrKey:␉␉␉// unused␊ |
511 | ␉␉break;␊ |
512 | ␉}␊ |
513 | ␉deleteItem( ci->data );␉␉␉// delete data␊ |
514 | ␉lruList->removeFirst();␉␉␉// remove from list␊ |
515 | }␊ |
516 | tCost = 0;␊ |
517 | }␊ |
518 | ␊ |
519 | ␊ |
520 | /*!␊ |
521 | \internal␊ |
522 | Finds an item in the cache.␊ |
523 | */␊ |
524 | ␊ |
525 | QCollection::Item QGCache::find_string( const QString &key, bool ref ) const␊ |
526 | {␊ |
527 | QCacheItem *ci = dict->find_string( key );␊ |
528 | #if defined(DEBUG)␊ |
529 | lruList->finds++;␊ |
530 | #endif␊ |
531 | if ( ci ) {␊ |
532 | #if defined(DEBUG)␊ |
533 | ␉lruList->hits++;␊ |
534 | ␉lruList->hitCosts += ci->cost;␊ |
535 | #endif␊ |
536 | ␉if ( ref )␊ |
537 | ␉ lruList->reference( ci );␊ |
538 | ␉return ci->data;␊ |
539 | }␊ |
540 | return 0;␊ |
541 | }␊ |
542 | ␊ |
543 | ␊ |
544 | /*!␊ |
545 | \internal␊ |
546 | Finds an item in the cache.␊ |
547 | */␊ |
548 | ␊ |
549 | QCollection::Item QGCache::find_other( const char *key, bool ref ) const␊ |
550 | {␊ |
551 | QCacheItem *ci = keytype == AsciiKey ? dict->find_ascii(key)␊ |
552 | ␉␉␉␉␉ : dict->find_int((long)key);␊ |
553 | #if defined(DEBUG)␊ |
554 | lruList->finds++;␊ |
555 | #endif␊ |
556 | if ( ci ) {␊ |
557 | #if defined(DEBUG)␊ |
558 | ␉lruList->hits++;␊ |
559 | ␉lruList->hitCosts += ci->cost;␊ |
560 | #endif␊ |
561 | ␉if ( ref )␊ |
562 | ␉ lruList->reference( ci );␊ |
563 | ␉return ci->data;␊ |
564 | }␊ |
565 | return 0;␊ |
566 | }␊ |
567 | ␊ |
568 | ␊ |
569 | /*!␊ |
570 | \internal␊ |
571 | Allocates cache space for one or more items.␊ |
572 | */␊ |
573 | ␊ |
574 | bool QGCache::makeRoomFor( int cost, int priority )␊ |
575 | {␊ |
576 | if ( cost > mCost )␉␉␉␉// cannot make room for more␊ |
577 | ␉return FALSE;␉␉␉␉// than maximum cost␊ |
578 | if ( priority == -1 )␊ |
579 | ␉priority = 32767;␊ |
580 | register QCacheItem *ci = lruList->last();␊ |
581 | int cntCost = 0;␊ |
582 | int dumps␉= 0;␉␉␉␉// number of items to dump␊ |
583 | while ( cntCost < cost && ci && ci->skipPriority <= priority ) {␊ |
584 | ␉cntCost += ci->cost;␊ |
585 | ␉ci␉ = lruList->prev();␊ |
586 | ␉dumps++;␊ |
587 | }␊ |
588 | if ( cntCost < cost )␉␉␉// can enough cost be dumped?␊ |
589 | ␉return FALSE;␉␉␉␉// no␊ |
590 | #if defined(DEBUG)␊ |
591 | ASSERT( dumps > 0 );␊ |
592 | #endif␊ |
593 | while ( dumps-- ) {␊ |
594 | ␉ci = lruList->last();␊ |
595 | #if defined(DEBUG)␊ |
596 | ␉lruList->dumps++;␊ |
597 | ␉lruList->dumpCosts += ci->cost;␊ |
598 | #endif␊ |
599 | ␉switch ( keytype ) {␊ |
600 | ␉ case StringKey:␊ |
601 | ␉␉dict->remove_string( ci );␊ |
602 | ␉␉delete (QString*)ci->key;␊ |
603 | ␉␉break;␊ |
604 | ␉ case AsciiKey:␊ |
605 | ␉␉dict->remove_ascii( ci );␊ |
606 | ␉␉if ( copyk )␊ |
607 | ␉␉ delete [] (char *)ci->key;␊ |
608 | ␉␉break;␊ |
609 | ␉ case IntKey:␊ |
610 | ␉␉dict->remove_int( ci );␊ |
611 | ␉␉break;␊ |
612 | ␉ case PtrKey:␉␉␉// unused␊ |
613 | ␉␉break;␊ |
614 | ␉}␊ |
615 | ␉deleteItem( ci->data );␉␉␉// delete data␊ |
616 | ␉lruList->removeLast();␉␉␉// remove from list␊ |
617 | }␊ |
618 | tCost -= cntCost;␊ |
619 | return TRUE;␊ |
620 | }␊ |
621 | ␊ |
622 | ␊ |
623 | /*!␊ |
624 | \internal␊ |
625 | Outputs debug statistics.␊ |
626 | */␊ |
627 | ␊ |
628 | void QGCache::statistics() const␊ |
629 | {␊ |
630 | #if defined(DEBUG)␊ |
631 | QString line;␊ |
632 | line.fill( '*', 80 );␊ |
633 | qDebug( "%s",line.ascii() );␊ |
634 | qDebug( "CACHE STATISTICS:" );␊ |
635 | qDebug( "cache contains %d item%s, with a total cost of %d",␊ |
636 | ␉ count(), count() != 1 ? "s" : "", tCost );␊ |
637 | qDebug( "maximum cost is %d, cache is %d%% full.",␊ |
638 | ␉ mCost, (200*tCost + mCost) / (mCost*2) );␊ |
639 | qDebug( "find() has been called %d time%s",␊ |
640 | ␉ lruList->finds, lruList->finds != 1 ? "s" : "" );␊ |
641 | qDebug( "%d of these were hits, items found had a total cost of %d.",␊ |
642 | ␉ lruList->hits,lruList->hitCosts );␊ |
643 | qDebug( "%d item%s %s been inserted with a total cost of %d.",␊ |
644 | ␉ lruList->inserts,lruList->inserts != 1 ? "s" : "",␊ |
645 | ␉ lruList->inserts != 1 ? "have" : "has", lruList->insertCosts );␊ |
646 | qDebug( "%d item%s %s too large or had too low priority to be inserted.",␊ |
647 | ␉ lruList->insertMisses, lruList->insertMisses != 1 ? "s" : "",␊ |
648 | ␉ lruList->insertMisses != 1 ? "were" : "was" );␊ |
649 | qDebug( "%d item%s %s been thrown away with a total cost of %d.",␊ |
650 | ␉ lruList->dumps, lruList->dumps != 1 ? "s" : "",␊ |
651 | ␉ lruList->dumps != 1 ? "have" : "has", lruList->dumpCosts );␊ |
652 | qDebug( "Statistics from internal dictionary class:" );␊ |
653 | dict->statistics();␊ |
654 | qDebug( "%s",line.ascii() );␊ |
655 | #endif␊ |
656 | }␊ |
657 | ␊ |
658 | ␊ |
659 | /*****************************************************************************␊ |
660 | QGCacheIterator member functions␊ |
661 | *****************************************************************************/␊ |
662 | ␊ |
663 | /*!␊ |
664 | \class QGCacheIterator qgcache.h␊ |
665 | ␊ |
666 | \brief An internal class for implementing QCacheIterator and QIntCacheIterator.␊ |
667 | ␊ |
668 | QGCacheIterator is a strictly internal class that does the heavy work for␊ |
669 | QCacheIterator and QIntCacheIterator.␊ |
670 | */␊ |
671 | ␊ |
672 | /*!␊ |
673 | \internal␊ |
674 | Constructs an iterator that operates on the cache \e c.␊ |
675 | */␊ |
676 | ␊ |
677 | QGCacheIterator::QGCacheIterator( const QGCache &c )␊ |
678 | {␊ |
679 | it = new QCListIt( c.lruList );␊ |
680 | #if defined(DEBUG)␊ |
681 | ASSERT( it != 0 );␊ |
682 | #endif␊ |
683 | }␊ |
684 | ␊ |
685 | /*!␊ |
686 | \internal␊ |
687 | Constructs an iterator that operates on the same cache as \e ci.␊ |
688 | */␊ |
689 | ␊ |
690 | QGCacheIterator::QGCacheIterator( const QGCacheIterator &ci )␊ |
691 | {␊ |
692 | it = new QCListIt( ci.it );␊ |
693 | #if defined(DEBUG)␊ |
694 | ASSERT( it != 0 );␊ |
695 | #endif␊ |
696 | }␊ |
697 | ␊ |
698 | /*!␊ |
699 | \internal␊ |
700 | Destroys the iterator.␊ |
701 | */␊ |
702 | ␊ |
703 | QGCacheIterator::~QGCacheIterator()␊ |
704 | {␊ |
705 | delete it;␊ |
706 | }␊ |
707 | ␊ |
708 | /*!␊ |
709 | \internal␊ |
710 | Assigns the iterator \e ci to this cache iterator.␊ |
711 | */␊ |
712 | ␊ |
713 | QGCacheIterator &QGCacheIterator::operator=( const QGCacheIterator &ci )␊ |
714 | {␊ |
715 | *it = *ci.it;␊ |
716 | return *this;␊ |
717 | }␊ |
718 | ␊ |
719 | /*!␊ |
720 | \internal␊ |
721 | Returns the number of items in the cache.␊ |
722 | */␊ |
723 | ␊ |
724 | uint QGCacheIterator::count() const␊ |
725 | {␊ |
726 | return it->count();␊ |
727 | }␊ |
728 | ␊ |
729 | /*!␊ |
730 | \internal␊ |
731 | Returns TRUE if the iterator points to the first item.␊ |
732 | */␊ |
733 | ␊ |
734 | bool QGCacheIterator::atFirst() const␊ |
735 | {␊ |
736 | return it->atFirst();␊ |
737 | }␊ |
738 | ␊ |
739 | /*!␊ |
740 | \internal␊ |
741 | Returns TRUE if the iterator points to the last item.␊ |
742 | */␊ |
743 | ␊ |
744 | bool QGCacheIterator::atLast() const␊ |
745 | {␊ |
746 | return it->atLast();␊ |
747 | }␊ |
748 | ␊ |
749 | /*!␊ |
750 | \internal␊ |
751 | Sets the list iterator to point to the first item in the cache.␊ |
752 | */␊ |
753 | ␊ |
754 | QCollection::Item QGCacheIterator::toFirst()␊ |
755 | {␊ |
756 | QCacheItem *item = it->toFirst();␊ |
757 | return item ? item->data : 0;␊ |
758 | }␊ |
759 | ␊ |
760 | /*!␊ |
761 | \internal␊ |
762 | Sets the list iterator to point to the last item in the cache.␊ |
763 | */␊ |
764 | ␊ |
765 | QCollection::Item QGCacheIterator::toLast()␊ |
766 | {␊ |
767 | QCacheItem *item = it->toLast();␊ |
768 | return item ? item->data : 0;␊ |
769 | }␊ |
770 | ␊ |
771 | /*!␊ |
772 | \internal␊ |
773 | Returns the current item.␊ |
774 | */␊ |
775 | ␊ |
776 | QCollection::Item QGCacheIterator::get() const␊ |
777 | {␊ |
778 | QCacheItem *item = it->current();␊ |
779 | return item ? item->data : 0;␊ |
780 | }␊ |
781 | ␊ |
782 | /*!␊ |
783 | \internal␊ |
784 | Returns the key of the current item.␊ |
785 | */␊ |
786 | ␊ |
787 | QString QGCacheIterator::getKeyString() const␊ |
788 | {␊ |
789 | QCacheItem *item = it->current();␊ |
790 | return item ? *((QString*)item->key) : QString::null;␊ |
791 | }␊ |
792 | ␊ |
793 | /*!␊ |
794 | \internal␊ |
795 | Returns the key of the current item, as a \0-terminated C string.␊ |
796 | */␊ |
797 | ␊ |
798 | const char *QGCacheIterator::getKeyAscii() const␊ |
799 | {␊ |
800 | QCacheItem *item = it->current();␊ |
801 | return item ? (const char *)item->key : 0;␊ |
802 | }␊ |
803 | ␊ |
804 | /*!␊ |
805 | \internal␊ |
806 | Returns the key of the current item, as a long.␊ |
807 | */␊ |
808 | ␊ |
809 | long QGCacheIterator::getKeyInt() const␊ |
810 | {␊ |
811 | QCacheItem *item = it->current();␊ |
812 | return item ? (long)item->key : 0;␊ |
813 | }␊ |
814 | ␊ |
815 | /*!␊ |
816 | \internal␊ |
817 | Moves to the next item (postfix).␊ |
818 | */␊ |
819 | ␊ |
820 | QCollection::Item QGCacheIterator::operator()()␊ |
821 | {␊ |
822 | QCacheItem *item = it->operator()();␊ |
823 | return item ? item->data : 0;␊ |
824 | }␊ |
825 | ␊ |
826 | /*!␊ |
827 | \internal␊ |
828 | Moves to the next item (prefix).␊ |
829 | */␊ |
830 | ␊ |
831 | QCollection::Item QGCacheIterator::operator++()␊ |
832 | {␊ |
833 | QCacheItem *item = it->operator++();␊ |
834 | return item ? item->data : 0;␊ |
835 | }␊ |
836 | ␊ |
837 | /*!␊ |
838 | \internal␊ |
839 | Moves \e jumps positions forward.␊ |
840 | */␊ |
841 | ␊ |
842 | QCollection::Item QGCacheIterator::operator+=( uint jump )␊ |
843 | {␊ |
844 | QCacheItem *item = it->operator+=(jump);␊ |
845 | return item ? item->data : 0;␊ |
846 | }␊ |
847 | ␊ |
848 | /*!␊ |
849 | \internal␊ |
850 | Moves to the previous item (prefix).␊ |
851 | */␊ |
852 | ␊ |
853 | QCollection::Item QGCacheIterator::operator--()␊ |
854 | {␊ |
855 | QCacheItem *item = it->operator--();␊ |
856 | return item ? item->data : 0;␊ |
857 | }␊ |
858 | ␊ |
859 | /*!␊ |
860 | \internal␊ |
861 | Moves \e jumps positions backward.␊ |
862 | */␊ |
863 | ␊ |
864 | QCollection::Item QGCacheIterator::operator-=( uint jump )␊ |
865 | {␊ |
866 | QCacheItem *item = it->operator-=(jump);␊ |
867 | return item ? item->data : 0;␊ |
868 | }␊ |
869 |