Blame qtools/qgcache.cpp

Packit 1c1d7e
/****************************************************************************
Packit 1c1d7e
** 
Packit 1c1d7e
**
Packit 1c1d7e
** Implementation of QGCache and QGCacheIterator classes
Packit 1c1d7e
**
Packit 1c1d7e
** Created : 950208
Packit 1c1d7e
**
Packit 1c1d7e
** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
Packit 1c1d7e
**
Packit 1c1d7e
** This file is part of the tools module of the Qt GUI Toolkit.
Packit 1c1d7e
**
Packit 1c1d7e
** This file may be distributed under the terms of the Q Public License
Packit 1c1d7e
** as defined by Trolltech AS of Norway and appearing in the file
Packit 1c1d7e
** LICENSE.QPL included in the packaging of this file.
Packit 1c1d7e
**
Packit 1c1d7e
** This file may be distributed and/or modified under the terms of the
Packit 1c1d7e
** GNU General Public License version 2 as published by the Free Software
Packit 1c1d7e
** Foundation and appearing in the file LICENSE.GPL included in the
Packit 1c1d7e
** packaging of this file.
Packit 1c1d7e
**
Packit 1c1d7e
** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
Packit 1c1d7e
** licenses may use this file in accordance with the Qt Commercial License
Packit 1c1d7e
** Agreement provided with the Software.
Packit 1c1d7e
**
Packit 1c1d7e
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
Packit 1c1d7e
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
Packit 1c1d7e
**
Packit 1c1d7e
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
Packit 1c1d7e
**   information about Qt Commercial License Agreements.
Packit 1c1d7e
** See http://www.trolltech.com/qpl/ for QPL licensing information.
Packit 1c1d7e
** See http://www.trolltech.com/gpl/ for GPL licensing information.
Packit 1c1d7e
**
Packit 1c1d7e
** Contact info@trolltech.com if any conditions of this licensing are
Packit 1c1d7e
** not clear to you.
Packit 1c1d7e
**
Packit 1c1d7e
**********************************************************************/
Packit 1c1d7e
Packit 1c1d7e
#include "qgcache.h"
Packit 1c1d7e
#include "qinternallist.h"
Packit 1c1d7e
#include "qdict.h"
Packit 1c1d7e
#include "qstring.h"
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
// NOT REVISED
Packit 1c1d7e
/*!
Packit 1c1d7e
  \class QGCache qgcache.h
Packit 1c1d7e
Packit 1c1d7e
  \brief The QGCache class is an internal class for implementing QCache template classes.
Packit 1c1d7e
Packit 1c1d7e
  QGCache is a strictly internal class that acts as a base class for the
Packit 1c1d7e
  \link collection.html collection classes\endlink QCache and QIntCache.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*****************************************************************************
Packit 1c1d7e
  QGCacheItem class (internal cache item)
Packit 1c1d7e
 *****************************************************************************/
Packit 1c1d7e
Packit 1c1d7e
struct QCacheItem
Packit 1c1d7e
{
Packit 1c1d7e
    QCacheItem( void *k, QCollection::Item d, int c, short p )
Packit 1c1d7e
	: priority(p), skipPriority(p), cost(c), key(k), data(d), node(0) {}
Packit 1c1d7e
    short	priority;
Packit 1c1d7e
    short	skipPriority;
Packit 1c1d7e
    int		cost;
Packit 1c1d7e
    void       *key;
Packit 1c1d7e
    QCollection::Item data;
Packit 1c1d7e
    QLNode     *node;
Packit 1c1d7e
};
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*****************************************************************************
Packit 1c1d7e
  QCList class (internal list of cache items)
Packit 1c1d7e
 *****************************************************************************/
Packit 1c1d7e
Packit 1c1d7e
class QCList : private QInternalList<QCacheItem>
Packit 1c1d7e
{
Packit 1c1d7e
friend class QGCacheIterator;
Packit 1c1d7e
friend class QCListIt;
Packit 1c1d7e
public:
Packit 1c1d7e
    QCList()	{}
Packit 1c1d7e
   ~QCList();
Packit 1c1d7e
Packit 1c1d7e
    void	insert( QCacheItem * );		// insert according to priority
Packit 1c1d7e
    void	insert( int, QCacheItem * );
Packit 1c1d7e
    void	take( QCacheItem * );
Packit 1c1d7e
    void	reference( QCacheItem * );
Packit 1c1d7e
Packit 1c1d7e
    void	setAutoDelete( bool del ) { QCollection::setAutoDelete(del); }
Packit 1c1d7e
Packit 1c1d7e
    bool	removeFirst()	{ return QInternalList<QCacheItem>::removeFirst(); }
Packit 1c1d7e
    bool	removeLast()	{ return QInternalList<QCacheItem>::removeLast(); }
Packit 1c1d7e
Packit 1c1d7e
    QCacheItem *first()		{ return QInternalList<QCacheItem>::first(); }
Packit 1c1d7e
    QCacheItem *last()		{ return QInternalList<QCacheItem>::last(); }
Packit 1c1d7e
    QCacheItem *prev()		{ return QInternalList<QCacheItem>::prev(); }
Packit 1c1d7e
    QCacheItem *next()		{ return QInternalList<QCacheItem>::next(); }
Packit 1c1d7e
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
    int		inserts;			// variables for statistics
Packit 1c1d7e
    int		insertCosts;
Packit 1c1d7e
    int		insertMisses;
Packit 1c1d7e
    int		finds;
Packit 1c1d7e
    int		hits;
Packit 1c1d7e
    int		hitCosts;
Packit 1c1d7e
    int		dumps;
Packit 1c1d7e
    int		dumpCosts;
Packit 1c1d7e
#endif
Packit 1c1d7e
};
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
QCList::~QCList()
Packit 1c1d7e
{
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
    ASSERT( count() == 0 );
Packit 1c1d7e
#endif
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
void QCList::insert( QCacheItem *ci )
Packit 1c1d7e
{
Packit 1c1d7e
    QCacheItem *item = first();
Packit 1c1d7e
    while( item && item->skipPriority > ci->priority ) {
Packit 1c1d7e
	item->skipPriority--;
Packit 1c1d7e
	item = next();
Packit 1c1d7e
    }
Packit 1c1d7e
    if ( item )
Packit 1c1d7e
	QInternalList<QCacheItem>::insert( at(), ci );
Packit 1c1d7e
    else
Packit 1c1d7e
	append( ci );
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
    ASSERT( ci->node == 0 );
Packit 1c1d7e
#endif
Packit 1c1d7e
    ci->node = currentNode();
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
inline void QCList::insert( int i, QCacheItem *ci )
Packit 1c1d7e
{
Packit 1c1d7e
    QInternalList<QCacheItem>::insert( i, ci );
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
    ASSERT( ci->node == 0 );
Packit 1c1d7e
#endif
Packit 1c1d7e
    ci->node = currentNode();
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
void QCList::take( QCacheItem *ci )
Packit 1c1d7e
{
Packit 1c1d7e
    if ( ci ) {
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
	ASSERT( ci->node != 0 );
Packit 1c1d7e
#endif
Packit 1c1d7e
	takeNode( ci->node );
Packit 1c1d7e
	ci->node = 0;
Packit 1c1d7e
    }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
inline void QCList::reference( QCacheItem *ci )
Packit 1c1d7e
{
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
    ASSERT( ci != 0 && ci->node != 0 );
Packit 1c1d7e
#endif
Packit 1c1d7e
    ci->skipPriority = ci->priority;
Packit 1c1d7e
    relinkNode( ci->node );			// relink as first item
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
class QCListIt: public QInternalListIterator<QCacheItem>
Packit 1c1d7e
{
Packit 1c1d7e
public:
Packit 1c1d7e
    QCListIt( const QCList *p ): QInternalListIterator<QCacheItem>( *p ) {}
Packit 1c1d7e
    QCListIt( const QCListIt *p ): QInternalListIterator<QCacheItem>( *p ) {}
Packit 1c1d7e
};
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*****************************************************************************
Packit 1c1d7e
  QCDict class (internal dictionary of cache items)
Packit 1c1d7e
 *****************************************************************************/
Packit 1c1d7e
Packit 1c1d7e
//
Packit 1c1d7e
// Since we need to decide if the dictionary should use an int or const
Packit 1c1d7e
// char * key (the "bool trivial" argument in the constructor below)
Packit 1c1d7e
// we cannot use the macro/template dict, but inherit directly from QGDict.
Packit 1c1d7e
//
Packit 1c1d7e
Packit 1c1d7e
class QCDict : public QGDict
Packit 1c1d7e
{
Packit 1c1d7e
public:
Packit 1c1d7e
    QCDict( uint size, uint kt, bool caseSensitive, bool copyKeys )
Packit 1c1d7e
	: QGDict( size, (KeyType)kt, caseSensitive, copyKeys ) {}
Packit 1c1d7e
Packit 1c1d7e
    QCacheItem *find_string(const QString &key) const
Packit 1c1d7e
	{ return (QCacheItem*)((QCDict*)this)->look_string(key, 0, 0); }
Packit 1c1d7e
    QCacheItem *find_ascii(const char *key) const
Packit 1c1d7e
	{ return (QCacheItem*)((QCDict*)this)->look_ascii(key, 0, 0); }
Packit 1c1d7e
    QCacheItem *find_int(long key) const
Packit 1c1d7e
	{ return (QCacheItem*)((QCDict*)this)->look_int(key, 0, 0); }
Packit 1c1d7e
Packit 1c1d7e
    QCacheItem *take_string(const QString &key)
Packit 1c1d7e
	{ return (QCacheItem*)QGDict::take_string(key); }
Packit 1c1d7e
    QCacheItem *take_ascii(const char *key)
Packit 1c1d7e
	{ return (QCacheItem*)QGDict::take_ascii(key); }
Packit 1c1d7e
    QCacheItem *take_int(long key)
Packit 1c1d7e
	{ return (QCacheItem*)QGDict::take_int(key); }
Packit 1c1d7e
Packit 1c1d7e
    bool  insert_string( const QString &key, const QCacheItem *ci )
Packit 1c1d7e
	{ return QGDict::look_string(key,(Item)ci,1)!=0;}
Packit 1c1d7e
    bool  insert_ascii( const char *key, const QCacheItem *ci )
Packit 1c1d7e
	{ return QGDict::look_ascii(key,(Item)ci,1)!=0;}
Packit 1c1d7e
    bool  insert_int( long key, const QCacheItem *ci )
Packit 1c1d7e
	{ return QGDict::look_int(key,(Item)ci,1)!=0;}
Packit 1c1d7e
Packit 1c1d7e
    bool  remove_string( QCacheItem *item )
Packit 1c1d7e
	{ return QGDict::remove_string(*((QString*)(item->key)),item); }
Packit 1c1d7e
    bool  remove_ascii( QCacheItem *item )
Packit 1c1d7e
	{ return QGDict::remove_ascii((const char *)item->key,item); }
Packit 1c1d7e
    bool  remove_int( QCacheItem *item )
Packit 1c1d7e
	{ return QGDict::remove_int((intptr_t)item->key,item);}
Packit 1c1d7e
Packit 1c1d7e
    void  statistics()			{ QGDict::statistics(); }
Packit 1c1d7e
};
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*****************************************************************************
Packit 1c1d7e
  QGDict member functions
Packit 1c1d7e
 *****************************************************************************/
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Constructs a cache.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGCache::QGCache( int maxCost, uint size, KeyType kt, bool caseSensitive,
Packit 1c1d7e
		  bool copyKeys )
Packit 1c1d7e
{
Packit 1c1d7e
    keytype = kt;
Packit 1c1d7e
    lruList = new QCList;
Packit 1c1d7e
    CHECK_PTR( lruList );
Packit 1c1d7e
    lruList->setAutoDelete( TRUE );
Packit 1c1d7e
    copyk   = ((keytype == AsciiKey) && copyKeys);
Packit 1c1d7e
    dict    = new QCDict( size, kt, caseSensitive, FALSE );
Packit 1c1d7e
    CHECK_PTR( dict );
Packit 1c1d7e
    mCost   = maxCost;
Packit 1c1d7e
    tCost   = 0;
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
    lruList->inserts	  = 0;
Packit 1c1d7e
    lruList->insertCosts  = 0;
Packit 1c1d7e
    lruList->insertMisses = 0;
Packit 1c1d7e
    lruList->finds	  = 0;
Packit 1c1d7e
    lruList->hits	  = 0;
Packit 1c1d7e
    lruList->hitCosts	  = 0;
Packit 1c1d7e
    lruList->dumps	  = 0;
Packit 1c1d7e
    lruList->dumpCosts	  = 0;
Packit 1c1d7e
#endif
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Cannot copy a cache.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGCache::QGCache( const QGCache & )
Packit 1c1d7e
    : QCollection()
Packit 1c1d7e
{
Packit 1c1d7e
#if defined(CHECK_NULL)
Packit 1c1d7e
    qFatal( "QGCache::QGCache(QGCache &): Cannot copy a cache" );
Packit 1c1d7e
#endif
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Removes all items from the cache and destroys it.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGCache::~QGCache()
Packit 1c1d7e
{
Packit 1c1d7e
    clear();					// delete everything first
Packit 1c1d7e
    delete dict;
Packit 1c1d7e
    delete lruList;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Cannot assign a cache.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGCache &QGCache::operator=( const QGCache & )
Packit 1c1d7e
{
Packit 1c1d7e
#if defined(CHECK_NULL)
Packit 1c1d7e
    qFatal( "QGCache::operator=: Cannot copy a cache" );
Packit 1c1d7e
#endif
Packit 1c1d7e
    return *this;				// satisfy the compiler
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \fn uint QGCache::count() const
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns the number of items in the cache.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \fn uint QGCache::size() const
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns the size of the hash array.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \fn int QGCache::maxCost() const
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns the maximum cache cost.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \fn int QGCache::totalCost() const
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns the total cache cost.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Sets the maximum cache cost.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
void QGCache::setMaxCost( int maxCost )
Packit 1c1d7e
{
Packit 1c1d7e
    if ( maxCost < tCost ) {
Packit 1c1d7e
	if ( !makeRoomFor(tCost - maxCost) )	// remove excess cost
Packit 1c1d7e
	    return;
Packit 1c1d7e
    }
Packit 1c1d7e
    mCost = maxCost;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Inserts an item into the cache.
Packit 1c1d7e
Packit 1c1d7e
  \warning If this function returns FALSE, you must delete \a data
Packit 1c1d7e
  yourself.  Additionally, be very careful about using \a data after
Packit 1c1d7e
  calling this function, as any other insertions into the cache, from
Packit 1c1d7e
  anywhere in the application, or within Qt itself, could cause the
Packit 1c1d7e
  data to be discarded from the cache, and the pointer to become
Packit 1c1d7e
  invalid.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
bool QGCache::insert_string( const QString &key, QCollection::Item data,
Packit 1c1d7e
			     int cost, int priority)
Packit 1c1d7e
{
Packit 1c1d7e
    if ( tCost + cost > mCost ) {
Packit 1c1d7e
	if ( !makeRoomFor(tCost + cost - mCost, priority) ) {
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
	    lruList->insertMisses++;
Packit 1c1d7e
#endif
Packit 1c1d7e
	    return FALSE;
Packit 1c1d7e
	}
Packit 1c1d7e
    }
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
    ASSERT( keytype == StringKey );
Packit 1c1d7e
    lruList->inserts++;
Packit 1c1d7e
    lruList->insertCosts += cost;
Packit 1c1d7e
#endif
Packit 1c1d7e
    if ( priority < -32768 )
Packit 1c1d7e
	priority = -32768;
Packit 1c1d7e
    else if ( priority > 32767 )
Packit 1c1d7e
	priority = 32677;
Packit 1c1d7e
    QCacheItem *ci = new QCacheItem( new QString(key), newItem(data),
Packit 1c1d7e
				     cost, (short)priority );
Packit 1c1d7e
    CHECK_PTR( ci );
Packit 1c1d7e
    lruList->insert( 0, ci );
Packit 1c1d7e
    dict->insert_string( key, ci );
Packit 1c1d7e
    tCost += cost;
Packit 1c1d7e
    return TRUE;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*! \internal */
Packit 1c1d7e
Packit 1c1d7e
bool QGCache::insert_other( const char *key, QCollection::Item data,
Packit 1c1d7e
			    int cost, int priority)
Packit 1c1d7e
{
Packit 1c1d7e
    if ( tCost + cost > mCost ) {
Packit 1c1d7e
	if ( !makeRoomFor(tCost + cost - mCost, priority) ) {
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
	    lruList->insertMisses++;
Packit 1c1d7e
#endif
Packit 1c1d7e
	    return FALSE;
Packit 1c1d7e
	}
Packit 1c1d7e
    }
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
    ASSERT( keytype != StringKey );
Packit 1c1d7e
    lruList->inserts++;
Packit 1c1d7e
    lruList->insertCosts += cost;
Packit 1c1d7e
#endif
Packit 1c1d7e
    if ( keytype == AsciiKey && copyk )
Packit 1c1d7e
	key = qstrdup( key );
Packit 1c1d7e
    if ( priority < -32768 )
Packit 1c1d7e
	priority = -32768;
Packit 1c1d7e
    else if ( priority > 32767 )
Packit 1c1d7e
	priority = 32677;
Packit 1c1d7e
    QCacheItem *ci = new QCacheItem( (void*)key, newItem(data), cost,
Packit 1c1d7e
				     (short)priority );
Packit 1c1d7e
    CHECK_PTR( ci );
Packit 1c1d7e
    lruList->insert( 0, ci );
Packit 1c1d7e
    if ( keytype == AsciiKey )
Packit 1c1d7e
	dict->insert_ascii( key, ci );
Packit 1c1d7e
    else
Packit 1c1d7e
	dict->insert_int( (intptr_t)key, ci );
Packit 1c1d7e
    tCost += cost;
Packit 1c1d7e
    return TRUE;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Removes an item from the cache.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
bool QGCache::remove_string( const QString &key )
Packit 1c1d7e
{
Packit 1c1d7e
    Item d = take_string( key );
Packit 1c1d7e
    if ( d )
Packit 1c1d7e
	deleteItem( d );
Packit 1c1d7e
    return d != 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*! \internal */
Packit 1c1d7e
Packit 1c1d7e
bool QGCache::remove_other( const char *key )
Packit 1c1d7e
{
Packit 1c1d7e
    Item d = take_other( key );
Packit 1c1d7e
    if ( d )
Packit 1c1d7e
	deleteItem( d );
Packit 1c1d7e
    return d != 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Takes an item out of the cache (no delete).
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QCollection::Item QGCache::take_string( const QString &key )
Packit 1c1d7e
{
Packit 1c1d7e
    QCacheItem *ci = dict->take_string( key );	// take from dict
Packit 1c1d7e
    Item d;
Packit 1c1d7e
    if ( ci ) {
Packit 1c1d7e
	d = ci->data;
Packit 1c1d7e
	tCost -= ci->cost;
Packit 1c1d7e
	lruList->take( ci );			// take from list
Packit 1c1d7e
	delete (QString*)ci->key;
Packit 1c1d7e
	delete ci;
Packit 1c1d7e
    } else {
Packit 1c1d7e
	d = 0;
Packit 1c1d7e
    }
Packit 1c1d7e
    return d;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Takes an item out of the cache (no delete).
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QCollection::Item QGCache::take_other( const char *key )
Packit 1c1d7e
{
Packit 1c1d7e
    QCacheItem *ci;
Packit 1c1d7e
    if ( keytype == AsciiKey )
Packit 1c1d7e
	ci = dict->take_ascii( key );
Packit 1c1d7e
    else
Packit 1c1d7e
	ci = dict->take_int( (intptr_t)key );
Packit 1c1d7e
    Item d;
Packit 1c1d7e
    if ( ci ) {
Packit 1c1d7e
	d = ci->data;
Packit 1c1d7e
	tCost -= ci->cost;
Packit 1c1d7e
	lruList->take( ci );			// take from list
Packit 1c1d7e
	if ( copyk )
Packit 1c1d7e
	    delete [] (char *)ci->key;
Packit 1c1d7e
	delete ci;
Packit 1c1d7e
    } else {
Packit 1c1d7e
	d = 0;
Packit 1c1d7e
    }
Packit 1c1d7e
    return d;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Clears the cache.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
void QGCache::clear()
Packit 1c1d7e
{
Packit 1c1d7e
    QCacheItem *ci;
Packit 1c1d7e
    while ( (ci = lruList->first()) ) {
Packit 1c1d7e
	switch ( keytype ) {
Packit 1c1d7e
	    case StringKey:
Packit 1c1d7e
		dict->remove_string( ci );
Packit 1c1d7e
		delete (QString*)ci->key;
Packit 1c1d7e
		break;
Packit 1c1d7e
	    case AsciiKey:
Packit 1c1d7e
		dict->remove_ascii( ci );
Packit 1c1d7e
		if ( copyk )
Packit 1c1d7e
		    delete [] (char*)ci->key;
Packit 1c1d7e
		break;
Packit 1c1d7e
	    case IntKey:
Packit 1c1d7e
		dict->remove_int( ci );
Packit 1c1d7e
		break;
Packit 1c1d7e
	    case PtrKey:			// unused
Packit 1c1d7e
		break;
Packit 1c1d7e
	}
Packit 1c1d7e
	deleteItem( ci->data );			// delete data
Packit 1c1d7e
	lruList->removeFirst();			// remove from list
Packit 1c1d7e
    }
Packit 1c1d7e
    tCost = 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Finds an item in the cache.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QCollection::Item QGCache::find_string( const QString &key, bool ref ) const
Packit 1c1d7e
{
Packit 1c1d7e
    QCacheItem *ci = dict->find_string( key );
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
    lruList->finds++;
Packit 1c1d7e
#endif
Packit 1c1d7e
    if ( ci ) {
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
	lruList->hits++;
Packit 1c1d7e
	lruList->hitCosts += ci->cost;
Packit 1c1d7e
#endif
Packit 1c1d7e
	if ( ref )
Packit 1c1d7e
	    lruList->reference( ci );
Packit 1c1d7e
	return ci->data;
Packit 1c1d7e
    }
Packit 1c1d7e
    return 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Finds an item in the cache.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QCollection::Item QGCache::find_other( const char *key, bool ref ) const
Packit 1c1d7e
{
Packit 1c1d7e
    QCacheItem *ci = keytype == AsciiKey ? dict->find_ascii(key)
Packit 1c1d7e
					 : dict->find_int((intptr_t)key);
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
    lruList->finds++;
Packit 1c1d7e
#endif
Packit 1c1d7e
    if ( ci ) {
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
	lruList->hits++;
Packit 1c1d7e
	lruList->hitCosts += ci->cost;
Packit 1c1d7e
#endif
Packit 1c1d7e
	if ( ref )
Packit 1c1d7e
	    lruList->reference( ci );
Packit 1c1d7e
	return ci->data;
Packit 1c1d7e
    }
Packit 1c1d7e
    return 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Allocates cache space for one or more items.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
bool QGCache::makeRoomFor( int cost, int priority )
Packit 1c1d7e
{
Packit 1c1d7e
    if ( cost > mCost )				// cannot make room for more
Packit 1c1d7e
	return FALSE;				//   than maximum cost
Packit 1c1d7e
    if ( priority == -1 )
Packit 1c1d7e
	priority = 32767;
Packit 1c1d7e
    register QCacheItem *ci = lruList->last();
Packit 1c1d7e
    int cntCost = 0;
Packit 1c1d7e
    int dumps	= 0;				// number of items to dump
Packit 1c1d7e
    while ( cntCost < cost && ci && ci->skipPriority <= priority ) {
Packit 1c1d7e
	cntCost += ci->cost;
Packit 1c1d7e
	ci	 = lruList->prev();
Packit 1c1d7e
	dumps++;
Packit 1c1d7e
    }
Packit 1c1d7e
    if ( cntCost < cost )			// can enough cost be dumped?
Packit 1c1d7e
	return FALSE;				// no
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
    ASSERT( dumps > 0 );
Packit 1c1d7e
#endif
Packit 1c1d7e
    while ( dumps-- ) {
Packit 1c1d7e
	ci = lruList->last();
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
	lruList->dumps++;
Packit 1c1d7e
	lruList->dumpCosts += ci->cost;
Packit 1c1d7e
#endif
Packit 1c1d7e
	switch ( keytype ) {
Packit 1c1d7e
	    case StringKey:
Packit 1c1d7e
		dict->remove_string( ci );
Packit 1c1d7e
		delete (QString*)ci->key;
Packit 1c1d7e
		break;
Packit 1c1d7e
	    case AsciiKey:
Packit 1c1d7e
		dict->remove_ascii( ci );
Packit 1c1d7e
		if ( copyk )
Packit 1c1d7e
		    delete [] (char *)ci->key;
Packit 1c1d7e
		break;
Packit 1c1d7e
	    case IntKey:
Packit 1c1d7e
		dict->remove_int( ci );
Packit 1c1d7e
		break;
Packit 1c1d7e
	    case PtrKey:			// unused
Packit 1c1d7e
		break;
Packit 1c1d7e
	}
Packit 1c1d7e
	deleteItem( ci->data );			// delete data
Packit 1c1d7e
	lruList->removeLast();			// remove from list
Packit 1c1d7e
    }
Packit 1c1d7e
    tCost -= cntCost;
Packit 1c1d7e
    return TRUE;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Outputs debug statistics.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
void QGCache::statistics() const
Packit 1c1d7e
{
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
    QString line;
Packit 1c1d7e
    line.fill( '*', 80 );
Packit 1c1d7e
    qDebug( "%s",line.ascii() );
Packit 1c1d7e
    qDebug( "CACHE STATISTICS:" );
Packit 1c1d7e
    qDebug( "cache contains %d item%s, with a total cost of %d",
Packit 1c1d7e
	   count(), count() != 1 ? "s" : "", tCost );
Packit 1c1d7e
    qDebug( "maximum cost is %d, cache is %d%% full.",
Packit 1c1d7e
	   mCost, (200*tCost + mCost) / (mCost*2) );
Packit 1c1d7e
    qDebug( "find() has been called %d time%s",
Packit 1c1d7e
	   lruList->finds, lruList->finds != 1 ? "s" : "" );
Packit 1c1d7e
    qDebug( "%d of these were hits, items found had a total cost of %d.",
Packit 1c1d7e
	   lruList->hits,lruList->hitCosts );
Packit 1c1d7e
    qDebug( "%d item%s %s been inserted with a total cost of %d.",
Packit 1c1d7e
	   lruList->inserts,lruList->inserts != 1 ? "s" : "",
Packit 1c1d7e
	   lruList->inserts != 1 ? "have" : "has", lruList->insertCosts );
Packit 1c1d7e
    qDebug( "%d item%s %s too large or had too low priority to be inserted.",
Packit 1c1d7e
	   lruList->insertMisses, lruList->insertMisses != 1 ? "s" : "",
Packit 1c1d7e
	   lruList->insertMisses != 1 ? "were" : "was" );
Packit 1c1d7e
    qDebug( "%d item%s %s been thrown away with a total cost of %d.",
Packit 1c1d7e
	   lruList->dumps, lruList->dumps != 1 ? "s" : "",
Packit 1c1d7e
	   lruList->dumps != 1 ? "have" : "has", lruList->dumpCosts );
Packit 1c1d7e
    qDebug( "Statistics from internal dictionary class:" );
Packit 1c1d7e
    dict->statistics();
Packit 1c1d7e
    qDebug( "%s",line.ascii() );
Packit 1c1d7e
#endif
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
int QGCache::hits() const
Packit 1c1d7e
{
Packit 1c1d7e
  return lruList->hits;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
int QGCache::misses() const
Packit 1c1d7e
{
Packit 1c1d7e
  return lruList->finds - lruList->hits;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
/*****************************************************************************
Packit 1c1d7e
  QGCacheIterator member functions
Packit 1c1d7e
 *****************************************************************************/
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \class QGCacheIterator qgcache.h
Packit 1c1d7e
Packit 1c1d7e
  \brief An internal class for implementing QCacheIterator and QIntCacheIterator.
Packit 1c1d7e
Packit 1c1d7e
  QGCacheIterator is a strictly internal class that does the heavy work for
Packit 1c1d7e
  QCacheIterator and QIntCacheIterator.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Constructs an iterator that operates on the cache \e c.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGCacheIterator::QGCacheIterator( const QGCache &c )
Packit 1c1d7e
{
Packit 1c1d7e
    it = new QCListIt( c.lruList );
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
    ASSERT( it != 0 );
Packit 1c1d7e
#endif
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Constructs an iterator that operates on the same cache as \e ci.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGCacheIterator::QGCacheIterator( const QGCacheIterator &ci )
Packit 1c1d7e
{
Packit 1c1d7e
    it = new QCListIt( ci.it );
Packit 1c1d7e
#if defined(DEBUG)
Packit 1c1d7e
    ASSERT( it != 0 );
Packit 1c1d7e
#endif
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Destroys the iterator.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGCacheIterator::~QGCacheIterator()
Packit 1c1d7e
{
Packit 1c1d7e
    delete it;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Assigns the iterator \e ci to this cache iterator.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QGCacheIterator &QGCacheIterator::operator=( const QGCacheIterator &ci )
Packit 1c1d7e
{
Packit 1c1d7e
    *it = *ci.it;
Packit 1c1d7e
    return *this;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns the number of items in the cache.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
uint QGCacheIterator::count() const
Packit 1c1d7e
{
Packit 1c1d7e
    return it->count();
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns TRUE if the iterator points to the first item.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
bool  QGCacheIterator::atFirst() const
Packit 1c1d7e
{
Packit 1c1d7e
    return it->atFirst();
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns TRUE if the iterator points to the last item.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
bool QGCacheIterator::atLast() const
Packit 1c1d7e
{
Packit 1c1d7e
    return it->atLast();
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Sets the list iterator to point to the first item in the cache.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QCollection::Item QGCacheIterator::toFirst()
Packit 1c1d7e
{
Packit 1c1d7e
    QCacheItem *item = it->toFirst();
Packit 1c1d7e
    return item ? item->data : 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Sets the list iterator to point to the last item in the cache.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QCollection::Item QGCacheIterator::toLast()
Packit 1c1d7e
{
Packit 1c1d7e
    QCacheItem *item = it->toLast();
Packit 1c1d7e
    return item ? item->data : 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns the current item.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QCollection::Item QGCacheIterator::get() const
Packit 1c1d7e
{
Packit 1c1d7e
    QCacheItem *item = it->current();
Packit 1c1d7e
    return item ? item->data : 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns the key of the current item.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QString QGCacheIterator::getKeyString() const
Packit 1c1d7e
{
Packit 1c1d7e
    QCacheItem *item = it->current();
Packit 1c1d7e
    return item ? *((QString*)item->key) : QString::null;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns the key of the current item, as a \0-terminated C string.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
const char *QGCacheIterator::getKeyAscii() const
Packit 1c1d7e
{
Packit 1c1d7e
    QCacheItem *item = it->current();
Packit 1c1d7e
    return item ? (const char *)item->key : 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Returns the key of the current item, as a long.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
intptr_t QGCacheIterator::getKeyInt() const
Packit 1c1d7e
{
Packit 1c1d7e
    QCacheItem *item = it->current();
Packit 1c1d7e
    return item ? (intptr_t)item->key : 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Moves to the next item (postfix).
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QCollection::Item QGCacheIterator::operator()()
Packit 1c1d7e
{
Packit 1c1d7e
    QCacheItem *item = it->operator()();
Packit 1c1d7e
    return item ? item->data : 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Moves to the next item (prefix).
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QCollection::Item QGCacheIterator::operator++()
Packit 1c1d7e
{
Packit 1c1d7e
    QCacheItem *item = it->operator++();
Packit 1c1d7e
    return item ? item->data : 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Moves \e jumps positions forward.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QCollection::Item QGCacheIterator::operator+=( uint jump )
Packit 1c1d7e
{
Packit 1c1d7e
    QCacheItem *item = it->operator+=(jump);
Packit 1c1d7e
    return item ? item->data : 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Moves to the previous item (prefix).
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QCollection::Item QGCacheIterator::operator--()
Packit 1c1d7e
{
Packit 1c1d7e
    QCacheItem *item = it->operator--();
Packit 1c1d7e
    return item ? item->data : 0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  \internal
Packit 1c1d7e
  Moves \e jumps positions backward.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
QCollection::Item QGCacheIterator::operator-=( uint jump )
Packit 1c1d7e
{
Packit 1c1d7e
    QCacheItem *item = it->operator-=(jump);
Packit 1c1d7e
    return item ? item->data : 0;
Packit 1c1d7e
}