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