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