xref: /AOO41X/main/tools/source/memtools/contnr.cxx (revision 79aad27f7f29270c03e208e3d687e8e3850af11d)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_tools.hxx"
26 
27 #ifndef _LIMITS_H
28 #include <limits.h>
29 #endif
30 
31 #ifndef _STRING_H
32 #include <string.h>
33 #endif
34 
35 #ifndef _STDIO_H
36 #include <stdio.h>
37 #endif
38 #include <tools/solar.h>
39 #include <impcont.hxx>
40 #include <tools/contnr.hxx>
41 #include <tools/debug.hxx>
42 
43 // -----------------------------------------------------------------------
44 
45 DBG_NAME( CBlock )
DBG_NAME(Container) const46 DBG_NAME( Container )
47 
48 /*************************************************************************
49 |*
50 |*    DbgCheckCBlock()
51 |*
52 |*    Beschreibung      Pruefung eines CBlock fuer Debug-Utilities
53 |*    Ersterstellung    MI 30.01.92
54 |*    Letzte Aenderung  TH 24.01.96
55 |*
56 *************************************************************************/
57 
58 #ifdef DBG_UTIL
59 const char* CBlock::DbgCheckCBlock( const void* pBlock )
60 {
61     CBlock* p = (CBlock*)pBlock;
62 
63     if ( p->nCount > p->nSize )
64         return "nCount > nSize";
65 
66     if ( p->nSize && !p->pNodes )
67         return "nSize > 0 && pNodes == NULL";
68 
69     return NULL;
70 }
71 #endif
72 
73 /*************************************************************************
74 |*
75 |*    CBlock::CBlock()
76 |*
77 |*    Beschreibung      Construktor des Verwaltungsblocks
78 |*    Ersterstellung    TH 17.09.91
79 |*    Letzte Aenderung  TH 17.09.91
80 |*
81 *************************************************************************/
82 
CBlock(sal_uInt16 nInitSize,CBlock * _pPrev,CBlock * _pNext)83 CBlock::CBlock( sal_uInt16 nInitSize, CBlock* _pPrev, CBlock* _pNext )
84 {
85     DBG_CTOR( CBlock, DbgCheckCBlock );
86 
87     pPrev   = _pPrev;
88     pNext   = _pNext;
89     nSize   = nInitSize;
90     nCount  = 0;
91 
92     // Datenpuffer anlegen
93     pNodes = new PVOID[nSize];
94 }
95 
96 /*************************************************************************
97 |*
98 |*    CBlock::CBlock()
99 |*
100 |*    Beschreibung      Construktor des Verwaltungsblocks
101 |*    Ersterstellung    TH 17.09.91
102 |*    Letzte Aenderung  TH 17.09.91
103 |*
104 *************************************************************************/
105 
CBlock(sal_uInt16 _nSize,CBlock * _pPrev)106 CBlock::CBlock( sal_uInt16 _nSize, CBlock* _pPrev )
107 {
108     DBG_CTOR( CBlock, DbgCheckCBlock );
109     DBG_ASSERT( _nSize, "CBlock::CBlock(): nSize == 0" );
110 
111     pPrev   = _pPrev;
112     pNext   = NULL;
113     nSize   = _nSize;
114     nCount  = _nSize;
115 
116     // Datenpuffer anlegen und initialisieren
117     pNodes = new PVOID[nSize];
118     memset( pNodes, 0, nSize*sizeof(PVOID) );
119 }
120 
121 /*************************************************************************
122 |*
123 |*    CBlock::CBlock()
124 |*
125 |*    Beschreibung      Copy-Construktor des Verwaltungsblocks
126 |*    Ersterstellung    TH 17.09.91
127 |*    Letzte Aenderung  TH 17.09.91
128 |*
129 *************************************************************************/
130 
CBlock(const CBlock & r,CBlock * _pPrev)131 CBlock::CBlock( const CBlock& r, CBlock* _pPrev )
132 {
133     DBG_CTOR( CBlock, DbgCheckCBlock );
134     DBG_CHKOBJ( &r, CBlock, DbgCheckCBlock );
135 
136     pPrev   = _pPrev;
137     pNext   = NULL;
138     nSize   = r.nSize;
139     nCount  = r.nCount;
140 
141     // Datenpuffer anlegen und Daten kopieren
142     pNodes = new PVOID[nSize];
143     memcpy( pNodes, r.pNodes, nCount*sizeof(PVOID) );
144 }
145 
146 /*************************************************************************
147 |*
148 |*    CBlock::~CBlock()
149 |*
150 |*    Beschreibung      Destruktor des Verwaltungsblocks
151 |*    Ersterstellung    TH 17.09.91
152 |*    Letzte Aenderung  TH 17.09.91
153 |*
154 *************************************************************************/
155 
~CBlock()156 inline CBlock::~CBlock()
157 {
158     DBG_DTOR( CBlock, DbgCheckCBlock );
159 
160     // Daten loeschen
161     delete[] pNodes;
162 }
163 
164 /*************************************************************************
165 |*
166 |*    CBlock::Insert()
167 |*
168 |*    Beschreibung      Fuegt einen Pointer ein
169 |*    Ersterstellung    TH 17.09.91
170 |*    Letzte Aenderung  TH 17.09.91
171 |*
172 *************************************************************************/
173 
Insert(void * p,sal_uInt16 nIndex,sal_uInt16 nReSize)174 void CBlock::Insert( void* p, sal_uInt16 nIndex, sal_uInt16 nReSize )
175 {
176     DBG_CHKTHIS( CBlock, DbgCheckCBlock );
177     DBG_ASSERT( nIndex <= nCount, "CBlock::Insert(): Index > nCount" );
178 
179     // Muss Block realokiert werden
180     if ( nCount == nSize )
181     {
182         // Neue Daten anlegen
183         nSize = nSize + nReSize;    // MSVC warns here if += is used
184         void** pNewNodes = new PVOID[nSize];
185 
186         // Wird angehaengt
187         if ( nCount == nIndex )
188         {
189             // Daten kopieren
190             memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) );
191         }
192         else
193         {
194             // Daten kopieren
195             memcpy( pNewNodes, pNodes, nIndex*sizeof(PVOID) );
196             memcpy( pNewNodes + nIndex + 1,
197                     pNodes + nIndex,
198                     (nCount-nIndex)*sizeof(PVOID) );
199         }
200 
201         // Alte Daten loeschen und neue setzen
202         delete[] pNodes;
203         pNodes = pNewNodes;
204     }
205     else
206     {
207         if ( nIndex < nCount )
208         {
209             memmove( pNodes + nIndex + 1,
210                      pNodes + nIndex,
211                      (nCount-nIndex)*sizeof(PVOID) );
212         }
213     }
214 
215     // Neuen Pointer setzen und Elementgroesse erhoehen
216     pNodes[nIndex] = p;
217     nCount++;
218 }
219 
220 /*************************************************************************
221 |*
222 |*    CBlock::Split()
223 |*
224 |*    Beschreibung      Fuegt einen Pointer ein und splittet den Block
225 |*    Ersterstellung    TH 17.09.91
226 |*    Letzte Aenderung  TH 17.09.91
227 |*
228 *************************************************************************/
229 
Split(void * p,sal_uInt16 nIndex,sal_uInt16 nReSize)230 CBlock* CBlock::Split( void* p, sal_uInt16 nIndex, sal_uInt16 nReSize )
231 {
232     DBG_CHKTHIS( CBlock, DbgCheckCBlock );
233 
234     sal_uInt16  nNewSize;
235     sal_uInt16  nMiddle;
236     CBlock* pNewBlock;
237 
238     nMiddle = nCount/2;
239 
240     if ( ( nIndex == nCount ) || ( nIndex == 0 ) )
241         nNewSize = nReSize;
242     else
243     {
244         // Der aktuelle Block wird in der Mitte geteilt
245         nNewSize = (nCount+1) / 2;
246 
247         if ( nNewSize < nReSize )
248             nNewSize = nReSize;
249         else
250         {
251             // Neue Groesse muss ein vielfaches von Resize sein
252             if ( nNewSize % nReSize )
253                 nNewSize += nReSize - (nNewSize % nReSize);
254             else
255                 nNewSize = nNewSize + nReSize;  // MSVC warns here if += is used
256         }
257     }
258 
259     // Vor oder hinter dem aktuellem Block einfuegen?
260     if ( nIndex > nMiddle )
261     {
262         // Neuen Split-Block anlegen und hinter dem aktuellem Block einfuegen
263         pNewBlock = new CBlock( nNewSize, this, pNext );
264 
265         if ( pNext )
266             pNext->pPrev = pNewBlock;
267         pNext = pNewBlock;
268 
269         if ( nIndex == nCount )
270         {
271             // Neuen Pointer einfuegen
272             pNewBlock->pNodes[0] = p;
273             pNewBlock->nCount = 1;
274         }
275         else
276         {
277             nIndex = nIndex - nMiddle;  // MSVC warns here if += is used
278             // Alles von Mitte bis Index kopieren
279             if ( nIndex )
280                 memcpy( pNewBlock->pNodes, pNodes+nMiddle, nIndex*sizeof(PVOID) );
281 
282             // Neuen Pointer einfuegen
283             pNewBlock->pNodes[nIndex] = p;
284 
285             // Alles von Mitte bis Ende hinter Index kopieren
286             memcpy( pNewBlock->pNodes+nIndex+1,
287                     pNodes+nMiddle+nIndex,
288                     (nCount-nMiddle-nIndex) * sizeof(PVOID) );
289 
290             pNewBlock->nCount = (nCount-nMiddle+1);
291             nCount = nMiddle;
292 
293             // Den aktuellen Datenbereich auch halbieren
294             if ( nSize != nNewSize )
295             {
296                 void** pNewNodes = new PVOID[nNewSize];
297                 memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) );
298                 delete[] pNodes;
299                 pNodes = pNewNodes;
300                 nSize = nNewSize;
301             }
302         }
303     }
304     else
305     {
306         // Neuen Split-Block anlegen und vor dem aktuellem Block einfuegen
307         pNewBlock = new CBlock( nNewSize, pPrev, this );
308 
309         if ( pPrev )
310             pPrev->pNext = pNewBlock;
311         pPrev = pNewBlock;
312 
313         if ( nIndex == 0 )
314         {
315             // Neuen Pointer einfuegen
316             pNewBlock->pNodes[0] = p;
317             pNewBlock->nCount = 1;
318         }
319         else
320         {
321             // Alles von Anfang bis Index kopieren
322             memcpy( pNewBlock->pNodes, pNodes, nIndex*sizeof(PVOID) );
323 
324             // Neuen Pointer einfuegen
325             pNewBlock->pNodes[nIndex] = p;
326 
327             // Alles von Index bis Mitte hinter Index kopieren
328             if ( nIndex != nMiddle )
329             {
330                 memcpy( pNewBlock->pNodes+nIndex+1,
331                         pNodes+nIndex,
332                         (nMiddle-nIndex) * sizeof(PVOID) );
333             }
334 
335             pNewBlock->nCount = nMiddle+1;
336             nCount = nCount - nMiddle;  // MSVC warns here if += is used
337 
338             // Die zweite Haelfte in einen neuen Block kopieren
339             if ( nSize != nNewSize )
340             {
341                 void** pNewNodes = new PVOID[nNewSize];
342                 memcpy( pNewNodes, pNodes+nMiddle, nCount*sizeof(PVOID) );
343                 delete[] pNodes;
344                 pNodes = pNewNodes;
345                 nSize = nNewSize;
346             }
347             else
348                 memmove( pNodes, pNodes+nMiddle, nCount*sizeof(PVOID) );
349         }
350     }
351 
352     // Neu angelegten Block zurueckgeben, da gegebenfalls die Blockpointer
353     // im Container angepast werden koennen
354     return pNewBlock;
355 }
356 
357 /*************************************************************************
358 |*
359 |*    CBlock::Remove()
360 |*
361 |*    Beschreibung      Entfernt einen Pointer
362 |*    Ersterstellung    TH 17.09.91
363 |*    Letzte Aenderung  TH 17.09.91
364 |*
365 *************************************************************************/
366 
Remove(sal_uInt16 nIndex,sal_uInt16 nReSize)367 void* CBlock::Remove( sal_uInt16 nIndex, sal_uInt16 nReSize )
368 {
369     DBG_CHKTHIS( CBlock, DbgCheckCBlock );
370 
371     // Alten Pointer sichern
372     void* pOld = pNodes[nIndex];
373 
374     // 1 Element weniger
375     nCount--;
376 
377     // Block verkleinern (wenn Reallokationsgroesse um 4 unterschritten wird)
378     if ( nCount == (nSize-nReSize-4) )
379     {
380         // Neue Daten anlegen
381         nSize = nSize - nReSize;    // MSVC warns here if += is used
382         void** pNewNodes = new PVOID[nSize];
383 
384         // Wird letzter Eintrag geloescht
385         if ( nIndex == nCount )
386         {
387             // Daten kopieren
388             memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) );
389         }
390         else
391         {
392             // Daten kopieren
393             memcpy( pNewNodes, pNodes, nIndex*sizeof(PVOID) );
394             memcpy( pNewNodes + nIndex, pNodes + nIndex+1,
395                     (nCount-nIndex)*sizeof(PVOID) );
396         }
397 
398         // Alte Daten loeschen und neue setzen
399         delete[] pNodes;
400         pNodes = pNewNodes;
401     }
402     else
403     {
404         // Wenn nicht das letzte Element, dann zusammenschieben
405         if ( nIndex < nCount )
406         {
407             memmove( pNodes + nIndex, pNodes + nIndex + 1,
408                      (nCount-nIndex)*sizeof(PVOID) );
409         }
410     }
411 
412     // Alten Pointer zurueckgeben
413     return pOld;
414 }
415 
416 /*************************************************************************
417 |*
418 |*    CBlock::Replace()
419 |*
420 |*    Beschreibung      Ersetzt einen Pointer
421 |*    Ersterstellung    TH 17.09.91
422 |*    Letzte Aenderung  TH 17.09.91
423 |*
424 *************************************************************************/
425 
Replace(void * p,sal_uInt16 nIndex)426 inline void* CBlock::Replace( void* p, sal_uInt16 nIndex )
427 {
428     DBG_CHKTHIS( CBlock, DbgCheckCBlock );
429 
430     // Alten Pointer sichern, neuen setzen und alten zurueckgeben
431     void* pOld = pNodes[nIndex];
432     pNodes[nIndex] = p;
433     return pOld;
434 }
435 
436 /*************************************************************************
437 |*
438 |*    CBlock::GetObjectPtr()
439 |*
440 |*    Beschreibung      Gibt einen Pointer auf den Pointer aus dem Block
441 |*                      zurueck
442 |*    Ersterstellung    TH 26.01.93
443 |*    Letzte Aenderung  TH 26.01.93
444 |*
445 *************************************************************************/
446 
GetObjectPtr(sal_uInt16 nIndex)447 inline void** CBlock::GetObjectPtr( sal_uInt16 nIndex )
448 {
449     DBG_CHKTHIS( CBlock, DbgCheckCBlock );
450 
451     return &(pNodes[nIndex]);
452 }
453 
454 /*************************************************************************
455 |*
456 |*    CBlock::SetSize()
457 |*
458 |*    Beschreibung      Aendert die Groesse des Blocks
459 |*    Ersterstellung    TH 17.09.91
460 |*    Letzte Aenderung  TH 17.09.91
461 |*
462 *************************************************************************/
463 
SetSize(sal_uInt16 nNewSize)464 void CBlock::SetSize( sal_uInt16 nNewSize )
465 {
466     DBG_CHKTHIS( CBlock, DbgCheckCBlock );
467     DBG_ASSERT( nNewSize, "CBlock::SetSize(): nNewSize == 0" );
468 
469     // Unterscheidet sich die Groesse
470     if ( nNewSize != nCount )
471     {
472         // Array erweitern
473         void** pNewNodes = new PVOID[nNewSize];
474 
475         // Alte Tabelle in die Neue kopieren
476         if ( nNewSize < nCount )
477             memcpy( pNewNodes, pNodes, nNewSize*sizeof(PVOID) );
478         else
479         {
480             memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) );
481 
482             // Array mit 0 initialisieren
483             memset( pNewNodes+nCount, 0, (nNewSize-nCount)*sizeof(PVOID) );
484         }
485 
486         // Altes Array loeschen und neue Werte setzen
487         nSize  = nNewSize;
488         nCount = nSize;
489         delete[] pNodes;
490         pNodes = pNewNodes;
491     }
492 }
493 
494 //------------------------------------------------------------------------
495 
496 /*************************************************************************
497 |*
498 |*    DbgCheckContainer()
499 |*
500 |*    Beschreibung      Pruefung eines Container fuer Debug-Utilities
501 |*    Ersterstellung    MI 30.01.92
502 |*    Letzte Aenderung  TH 24.01.96
503 |*
504 *************************************************************************/
505 
506 #ifdef DBG_UTIL
DbgCheckContainer(const void * pCont)507 const char* Container::DbgCheckContainer( const void* pCont )
508 {
509     Container* p = (Container*)pCont;
510 
511     if ( p->nCount && (!p->pFirstBlock || !p->pLastBlock || !p->pCurBlock) )
512         return "nCount > 0 but no CBlocks";
513 
514     return NULL;
515 }
516 #endif
517 
518 /*************************************************************************
519 |*
520 |*    ImpCopyContainer()
521 |*
522 |*    Beschreibung      Kopiert alle Daten des Containers
523 |*    Ersterstellung    TH 24.01.96
524 |*    Letzte Aenderung  TH 24.01.96
525 |*
526 *************************************************************************/
527 
ImpCopyContainer(const Container * pCont2)528 void Container::ImpCopyContainer( const Container* pCont2 )
529 {
530     // Werte vom uebergebenen Container uebernehmen
531     nCount     = pCont2->nCount;
532     nCurIndex  = pCont2->nCurIndex;
533     nInitSize  = pCont2->nInitSize;
534     nReSize    = pCont2->nReSize;
535     nBlockSize = pCont2->nBlockSize;
536 
537     // Alle Bloecke kopieren
538     if ( pCont2->nCount )
539     {
540         CBlock* pBlock1;
541         CBlock* pBlock2;
542         CBlock* pTempBlock;
543 
544         // Erstmal ersten Block kopieren
545         pBlock2 = pCont2->pFirstBlock;
546         pFirstBlock = new CBlock( *pBlock2, NULL );
547         // Ist erster Block der Current-Block, dann Current-Block setzen
548         if ( pBlock2 == pCont2->pCurBlock )
549             pCurBlock = pFirstBlock;
550         pBlock1 = pFirstBlock;
551         pBlock2 = pBlock2->GetNextBlock();
552         while ( pBlock2 )
553         {
554             // Neuen Block anlegen und aus der uebergebenen Liste kopieren
555             pTempBlock = new CBlock( *pBlock2, pBlock1 );
556             pBlock1->SetNextBlock( pTempBlock );
557             pBlock1 = pTempBlock;
558 
559             // Current-Block beruecksichtigen
560             if ( pBlock2 == pCont2->pCurBlock )
561                 pCurBlock = pBlock1;
562 
563             // Auf naechsten Block weitersetzen
564             pBlock2 = pBlock2->GetNextBlock();
565         }
566 
567         // Letzten Block setzen
568         pLastBlock = pBlock1;
569     }
570     else
571     {
572         pFirstBlock = NULL;
573         pLastBlock  = NULL;
574         pCurBlock   = NULL;
575     }
576 }
577 
578 /*************************************************************************
579 |*
580 |*    Container::Container()
581 |*
582 |*    Beschreibung      CONTNR.SDW
583 |*    Ersterstellung    TH 17.09.91
584 |*    Letzte Aenderung  TH 17.09.91
585 |*
586 *************************************************************************/
587 
Container(sal_uInt16 _nBlockSize,sal_uInt16 _nInitSize,sal_uInt16 _nReSize)588 Container::Container( sal_uInt16 _nBlockSize, sal_uInt16 _nInitSize, sal_uInt16 _nReSize )
589 {
590     DBG_CTOR( Container, DbgCheckContainer );
591 
592     // BlockSize muss mindestens 4 sein und kleiner als 64 KB
593     if ( _nBlockSize < 4 )
594         nBlockSize = 4;
595     else
596     {
597         if ( _nBlockSize < CONTAINER_MAXBLOCKSIZE )
598             nBlockSize = _nBlockSize;
599         else
600             nBlockSize = CONTAINER_MAXBLOCKSIZE;
601     }
602 
603     // ReSize muss mindestens 2 sein und kleiner als BlockSize
604     if ( _nReSize >= nBlockSize )
605         nReSize = nBlockSize;
606     else
607     {
608         if ( _nReSize < 2 )
609             nReSize = 2;
610         else
611             nReSize = _nReSize;
612 
613         // BlockSize muss ein vielfaches der Resizegroesse sein
614         if ( nBlockSize % nReSize )
615             nBlockSize -= nReSize - (nBlockSize % nReSize);
616     }
617 
618     // InitSize muss groesser gleich ReSize sein und kleiner als BlockSize
619     if ( _nInitSize <= nReSize )
620         nInitSize = nReSize;
621     else
622     {
623         if ( _nInitSize >= nBlockSize )
624             nInitSize = nBlockSize;
625         else
626         {
627             nInitSize = _nInitSize;
628 
629             // InitSize muss ein vielfaches der Resizegroesse sein
630             if ( nInitSize % nReSize )
631                 nInitSize -= nReSize - (nInitSize % nReSize);
632         }
633     }
634 
635     // Werte initialisieren
636     pFirstBlock = NULL;
637     pLastBlock  = NULL;
638     pCurBlock   = NULL;
639     nCount      = 0;
640     nCurIndex   = 0;
641 }
642 
643 /*************************************************************************
644 |*
645 |*    Container::Container()
646 |*
647 |*    Beschreibung      CONTNR.SDW
648 |*    Ersterstellung    TH 17.09.91
649 |*    Letzte Aenderung  TH 17.09.91
650 |*
651 *************************************************************************/
652 
Container(sal_uIntPtr nSize)653 Container::Container( sal_uIntPtr nSize )
654 {
655     DBG_CTOR( Container, DbgCheckContainer );
656 
657     nCount     = nSize;
658     nCurIndex  = 0;
659     nBlockSize = CONTAINER_MAXBLOCKSIZE;
660     nInitSize  = 1;
661     nReSize    = 1;
662 
663     if ( !nSize )
664     {
665         pFirstBlock = NULL;
666         pLastBlock  = NULL;
667         pCurBlock   = NULL;
668     }
669     else
670     {
671         // Muss mehr als ein Block angelegt werden
672         if ( nSize <= nBlockSize )
673         {
674             pFirstBlock = new CBlock( (sal_uInt16)nSize, NULL );
675             pLastBlock = pFirstBlock;
676         }
677         else
678         {
679             CBlock* pBlock1;
680             CBlock* pBlock2;
681 
682             pFirstBlock = new CBlock( nBlockSize, NULL );
683             pBlock1 = pFirstBlock;
684             nSize -= nBlockSize;
685 
686             // Solange die Blockgroesse ueberschritten wird, neue Bloecke anlegen
687             while ( nSize > nBlockSize )
688             {
689                 pBlock2 = new CBlock( nBlockSize, pBlock1 );
690                 pBlock1->SetNextBlock( pBlock2 );
691                 pBlock1 = pBlock2;
692                 nSize -= nBlockSize;
693             }
694 
695             pLastBlock = new CBlock( (sal_uInt16)nSize, pBlock1 );
696             pBlock1->SetNextBlock( pLastBlock );
697         }
698 
699         pCurBlock  = pFirstBlock;
700     }
701 }
702 
703 /*************************************************************************
704 |*
705 |*    Container::Container()
706 |*
707 |*    Beschreibung      CONTNR.SDW
708 |*    Ersterstellung    TH 17.09.91
709 |*    Letzte Aenderung  TH 17.09.91
710 |*
711 *************************************************************************/
712 
Container(const Container & r)713 Container::Container( const Container& r )
714 {
715     DBG_CTOR( Container, DbgCheckContainer );
716 
717     // Daten kopieren
718     ImpCopyContainer( &r );
719 }
720 
721 /*************************************************************************
722 |*
723 |*    Container::~Container()
724 |*
725 |*    Beschreibung      CONTNR.SDW
726 |*    Ersterstellung    TH 17.09.91
727 |*    Letzte Aenderung  TH 17.09.91
728 |*
729 *************************************************************************/
730 
~Container()731 Container::~Container()
732 {
733     DBG_DTOR( Container, DbgCheckContainer );
734 
735     // Alle Bloecke loeschen
736     CBlock* pBlock = pFirstBlock;
737     while ( pBlock )
738     {
739         CBlock* pTemp = pBlock->GetNextBlock();
740         delete pBlock;
741         pBlock = pTemp;
742     }
743 }
744 
745 /*************************************************************************
746 |*
747 |*    Container::ImpInsert()
748 |*
749 |*    Beschreibung      Interne Methode zum Einfuegen eines Pointers
750 |*    Ersterstellung    TH 17.09.91
751 |*    Letzte Aenderung  DV 01.07.97
752 |*
753 *************************************************************************/
754 
ImpInsert(void * p,CBlock * pBlock,sal_uInt16 nIndex)755 void Container::ImpInsert( void* p, CBlock* pBlock, sal_uInt16 nIndex )
756 {
757     DBG_CHKTHIS( Container, DbgCheckContainer );
758 
759     if ( !nCount )
760     {
761         if ( !pBlock )
762         {
763             pFirstBlock = new CBlock( nInitSize, NULL, NULL );
764             pLastBlock  = pFirstBlock;
765             pCurBlock   = pFirstBlock;
766         }
767         pFirstBlock->Insert( p, nIndex, nReSize );
768     }
769     else
770     {
771         // Ist im Block die maximale Blockgroesse erreicht,
772         // dann neuen Block anlegen
773         if ( pBlock->Count() == nBlockSize )
774         {
775             // Block auftrennen
776             CBlock* pNewBlock = pBlock->Split( p, nIndex, nReSize );
777 
778             // Wurde Block dahinter angehaegnt
779             if ( pBlock->pNext == pNewBlock )
780             {
781                 // Gegebenenfalls LastBlock anpassen
782                 if ( pBlock == pLastBlock )
783                     pLastBlock = pNewBlock;
784 
785                 // Current-Position nachfuehren
786                 if ( pBlock == pCurBlock )
787                 {
788                     if ( pBlock->nCount <= nCurIndex )
789                     {
790                         if ( nIndex <= nCurIndex )
791                             nCurIndex++;
792                         pCurBlock  = pNewBlock;
793                         nCurIndex = nCurIndex - pBlock->nCount; // MSVC warns here if += is used
794                     }
795                 }
796             }
797             else
798             {
799                 // Gegebenenfalls FirstBlock anpassen
800                 if ( pBlock == pFirstBlock )
801                     pFirstBlock = pNewBlock;
802 
803                 // Current-Position nachfuehren
804                 if ( pBlock == pCurBlock )
805                 {
806                     if ( nIndex <= nCurIndex )
807                         nCurIndex++;
808                     if ( pNewBlock->nCount <= nCurIndex )
809                         nCurIndex = nCurIndex - pNewBlock->nCount;  // MSVC warns here if += is used
810                     else
811                         pCurBlock = pNewBlock;
812                 }
813             }
814         }
815         else
816         {
817             // Sonst reicht normales einfuegen in den Block
818             pBlock->Insert( p, nIndex, nReSize );
819 
820             // Current-Position nachfuehren
821             if ( (pBlock == pCurBlock) && (nIndex <= nCurIndex) )
822                 nCurIndex++;
823         }
824     }
825 
826     // Ein neues Item im Container
827     nCount++;
828 }
829 
830 /*************************************************************************
831 |*
832 |*    Container::Insert()
833 |*
834 |*    Beschreibung      CONTNR.SDW
835 |*    Ersterstellung    TH 17.09.91
836 |*    Letzte Aenderung  TH 17.09.91
837 |*
838 *************************************************************************/
839 
Insert(void * p)840 void Container::Insert( void* p )
841 {
842     ImpInsert( p, pCurBlock, nCurIndex );
843 }
844 
845 /*************************************************************************
846 |*
847 |*    Container::Insert()
848 |*
849 |*    Beschreibung      CONTNR.SDW
850 |*    Ersterstellung    TH 17.09.91
851 |*    Letzte Aenderung  TH 17.09.91
852 |*
853 *************************************************************************/
854 
Insert(void * p,sal_uIntPtr nIndex)855 void Container::Insert( void* p, sal_uIntPtr nIndex )
856 {
857     if ( nCount <= nIndex )
858     {
859         if ( pLastBlock )
860             ImpInsert( p, pLastBlock, pLastBlock->Count() );
861         else
862             ImpInsert( p, NULL, 0 );
863     }
864     else
865     {
866         // Block suchen
867         CBlock* pTemp = pFirstBlock;
868         while ( pTemp->Count() < nIndex )
869         {
870             nIndex -= pTemp->Count();
871             pTemp   = pTemp->GetNextBlock();
872         }
873 
874         ImpInsert( p, pTemp, (sal_uInt16)nIndex );
875     }
876 }
877 
878 /*************************************************************************
879 |*
880 |*    Container::Insert()
881 |*
882 |*    Beschreibung      CONTNR.SDW
883 |*    Ersterstellung    TH 17.09.91
884 |*    Letzte Aenderung  TH 17.09.91
885 |*
886 *************************************************************************/
887 
Insert(void * pNew,void * pOld)888 void Container::Insert( void* pNew, void* pOld )
889 {
890     sal_uIntPtr nIndex = GetPos( pOld );
891     if ( nIndex != CONTAINER_ENTRY_NOTFOUND )
892         Insert( pNew, nIndex );
893 }
894 
895 /*************************************************************************
896 |*
897 |*    Container::ImpRemove()
898 |*
899 |*    Beschreibung      Interne Methode zum Entfernen eines Pointers
900 |*    Ersterstellung    TH 17.09.91
901 |*    Letzte Aenderung  TH 17.09.91
902 |*
903 *************************************************************************/
904 
ImpRemove(CBlock * pBlock,sal_uInt16 nIndex)905 void* Container::ImpRemove( CBlock* pBlock, sal_uInt16 nIndex )
906 {
907     DBG_CHKTHIS( Container, DbgCheckContainer );
908 
909     void* pOld;
910 
911     // Ist Liste danach leer
912     if ( nCount == 1 )
913     {
914         // Block und CurIndex zuruecksetzen
915         pOld = pBlock->GetObject( nIndex );
916         pBlock->Reset();
917         nCurIndex = 0;
918     }
919     else
920     {
921         // Ist Block nach Remove leer
922         if ( pBlock->Count() == 1 )
923         {
924             // dann Block entfernen und Block-Pointer umsetzen
925             if ( pBlock->GetPrevBlock() )
926                 (pBlock->GetPrevBlock())->SetNextBlock( pBlock->GetNextBlock() );
927             else
928                 pFirstBlock = pBlock->GetNextBlock();
929 
930             if ( pBlock->GetNextBlock() )
931                 (pBlock->GetNextBlock())->SetPrevBlock( pBlock->GetPrevBlock() );
932             else
933                 pLastBlock = pBlock->GetPrevBlock();
934 
935             // Current-Position nachfuehren
936             if ( pBlock == pCurBlock )
937             {
938                 if ( pBlock->GetNextBlock() )
939                 {
940                     pCurBlock = pBlock->GetNextBlock();
941                     nCurIndex = 0;
942                 }
943                 else
944                 {
945                     pCurBlock = pBlock->GetPrevBlock();
946                     nCurIndex = pCurBlock->Count()-1;
947                 }
948             }
949 
950             pOld = pBlock->GetObject( nIndex );
951             delete pBlock;
952         }
953         else
954         {
955             // Sonst Item aus dem Block entfernen
956             pOld = pBlock->Remove( nIndex, nReSize );
957 
958             // Current-Position nachfuehren
959             if ( (pBlock == pCurBlock) &&
960                  ((nIndex < nCurIndex) || ((nCurIndex == pBlock->Count()) && nCurIndex)) )
961                 nCurIndex--;
962         }
963     }
964 
965     // Jetzt gibt es ein Item weniger
966     nCount--;
967 
968     // Und den Pointer zurueckgeben, der entfernt wurde
969     return pOld;
970 }
971 
972 /*************************************************************************
973 |*
974 |*    Container::Remove()
975 |*
976 |*    Beschreibung      CONTNR.SDW
977 |*    Ersterstellung    TH 17.09.91
978 |*    Letzte Aenderung  TH 17.09.91
979 |*
980 *************************************************************************/
981 
Remove()982 void* Container::Remove()
983 {
984     // Wenn kein Item vorhanden ist, NULL zurueckgeben
985     if ( !nCount )
986         return NULL;
987     else
988         return ImpRemove( pCurBlock, nCurIndex );
989 }
990 
991 /*************************************************************************
992 |*
993 |*    Container::Remove()
994 |*
995 |*    Beschreibung      CONTNR.SDW
996 |*    Ersterstellung    TH 17.09.91
997 |*    Letzte Aenderung  TH 17.09.91
998 |*
999 *************************************************************************/
1000 
Remove(sal_uIntPtr nIndex)1001 void* Container::Remove( sal_uIntPtr nIndex )
1002 {
1003     // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben
1004     if ( nCount <= nIndex )
1005         return NULL;
1006     else
1007     {
1008         // Block suchen
1009         CBlock* pTemp = pFirstBlock;
1010         while ( pTemp->Count() <= nIndex )
1011         {
1012             nIndex -= pTemp->Count();
1013             pTemp   = pTemp->GetNextBlock();
1014         }
1015 
1016         return ImpRemove( pTemp, (sal_uInt16)nIndex );
1017     }
1018 }
1019 
1020 /*************************************************************************
1021 |*
1022 |*    Container::Replace()
1023 |*
1024 |*    Beschreibung      CONTNR.SDW
1025 |*    Ersterstellung    TH 17.09.91
1026 |*    Letzte Aenderung  TH 17.09.91
1027 |*
1028 *************************************************************************/
1029 
Replace(void * p)1030 void* Container::Replace( void* p )
1031 {
1032     DBG_CHKTHIS( Container, DbgCheckContainer );
1033 
1034     if ( !nCount )
1035         return NULL;
1036     else
1037         return pCurBlock->Replace( p, nCurIndex );
1038 }
1039 
1040 /*************************************************************************
1041 |*
1042 |*    Container::Replace()
1043 |*
1044 |*    Beschreibung      CONTNR.SDW
1045 |*    Ersterstellung    TH 17.09.91
1046 |*    Letzte Aenderung  TH 17.09.91
1047 |*
1048 *************************************************************************/
1049 
Replace(void * p,sal_uIntPtr nIndex)1050 void* Container::Replace( void* p, sal_uIntPtr nIndex )
1051 {
1052     DBG_CHKTHIS( Container, DbgCheckContainer );
1053 
1054     // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben
1055     if ( nCount <= nIndex )
1056         return NULL;
1057     else
1058     {
1059         // Block suchen
1060         CBlock* pTemp = pFirstBlock;
1061         while ( pTemp->Count() <= nIndex )
1062         {
1063             nIndex -= pTemp->Count();
1064             pTemp   = pTemp->GetNextBlock();
1065         }
1066 
1067         return pTemp->Replace( p, (sal_uInt16)nIndex );
1068     }
1069 }
1070 
1071 /*************************************************************************
1072 |*
1073 |*    Container::SetSize()
1074 |*
1075 |*    Beschreibung      CONTNR.SDW
1076 |*    Ersterstellung    TH 17.09.91
1077 |*    Letzte Aenderung  TH 17.09.91
1078 |*
1079 *************************************************************************/
1080 
SetSize(sal_uIntPtr nNewSize)1081 void Container::SetSize( sal_uIntPtr nNewSize )
1082 {
1083     DBG_CHKTHIS( Container, DbgCheckContainer );
1084 
1085     if ( nNewSize )
1086     {
1087         // Unterscheiden sich die Groessen
1088         if ( nNewSize != nCount )
1089         {
1090             CBlock* pTemp;
1091             sal_uIntPtr nTemp;
1092 
1093             // Wird verkleinert
1094             if ( nNewSize < nCount )
1095             {
1096                 pTemp = pFirstBlock;
1097                 nTemp = 0;
1098                 while ( (nTemp+pTemp->Count()) < nNewSize )
1099                 {
1100                     nTemp += pTemp->Count();
1101                     pTemp  = pTemp->GetNextBlock();
1102                 }
1103 
1104                 // Alle folgenden Bloecke loeschen
1105                 sal_Bool    bLast = sal_False;
1106                 CBlock* pDelNext;
1107                 CBlock* pDelBlock = pTemp->GetNextBlock();
1108                 while ( pDelBlock )
1109                 {
1110                     // Muss CurrentBlock umgesetzt werden
1111                     if ( pDelBlock == pCurBlock )
1112                         bLast = sal_True;
1113                     pDelNext = pDelBlock->GetNextBlock();
1114                     delete pDelBlock;
1115                     pDelBlock = pDelNext;
1116                 }
1117 
1118                 // Block in der Groesse anpassen, oder bei Groesse 0 loeschen
1119                 if ( nNewSize > nTemp )
1120                 {
1121                     pLastBlock = pTemp;
1122                     pTemp->SetNextBlock( NULL );
1123                     pTemp->SetSize( (sal_uInt16)(nNewSize-nTemp) );
1124                 }
1125                 else
1126                 {
1127                     pLastBlock = pTemp->GetPrevBlock();
1128                     pLastBlock->SetNextBlock( NULL );
1129                     delete pTemp;
1130                 }
1131 
1132                 nCount = nNewSize;
1133                 if ( bLast )
1134                 {
1135                     pCurBlock = pLastBlock;
1136                     nCurIndex = pCurBlock->Count()-1;
1137                 }
1138             }
1139             else
1140             {
1141                 // Auf den letzen Puffer setzen
1142                 pTemp = pLastBlock;
1143                 nTemp = nNewSize - nCount;
1144 
1145                 if ( !pTemp )
1146                 {
1147                     // Muss mehr als ein Block angelegt werden
1148                     if ( nNewSize <= nBlockSize )
1149                     {
1150                         pFirstBlock = new CBlock( (sal_uInt16)nNewSize, NULL );
1151                         pLastBlock = pFirstBlock;
1152                     }
1153                     else
1154                     {
1155                         CBlock* pBlock1;
1156                         CBlock* pBlock2;
1157 
1158                         pFirstBlock = new CBlock( nBlockSize, NULL );
1159                         pBlock1 = pFirstBlock;
1160                         nNewSize -= nBlockSize;
1161 
1162                         // Solange die Blockgroesse ueberschritten wird, neue Bloecke anlegen
1163                         while ( nNewSize > nBlockSize )
1164                         {
1165                             pBlock2 = new CBlock( nBlockSize, pBlock1 );
1166                             pBlock1->SetNextBlock( pBlock2 );
1167                             pBlock1 = pBlock2;
1168                             nNewSize -= nBlockSize;
1169                         }
1170 
1171                         pLastBlock = new CBlock( (sal_uInt16)nNewSize, pBlock1 );
1172                         pBlock1->SetNextBlock( pLastBlock );
1173                     }
1174 
1175                     pCurBlock  = pFirstBlock;
1176                 }
1177                 // Reicht es, den letzen Puffer in der Groesse anzupassen
1178                 else if ( (nTemp+pTemp->Count()) <= nBlockSize )
1179                     pTemp->SetSize( (sal_uInt16)(nTemp+pTemp->Count()) );
1180                 else
1181                 {
1182                     // Puffer auf max. Blockgroesse setzen
1183                     nTemp -= nBlockSize - pTemp->GetSize();
1184                     pTemp->SetSize( nBlockSize );
1185 
1186                     CBlock* pTemp2;
1187                     // Solange die Blockgroesse ueberschritten wird,
1188                     // neue Bloecke anlegen
1189                     while ( nTemp > nBlockSize )
1190                     {
1191                         pTemp2 = new CBlock( nBlockSize, pTemp );
1192                         pTemp->SetNextBlock( pTemp2 );
1193                         pTemp = pTemp2;
1194                         nTemp -= nBlockSize;
1195                     }
1196 
1197                     // Den letzten Block anlegen
1198                     if ( nTemp )
1199                     {
1200                         pLastBlock = new CBlock( (sal_uInt16)nTemp, pTemp );
1201                         pTemp->SetNextBlock( pLastBlock );
1202                     }
1203                     else
1204                         pLastBlock = pTemp;
1205                 }
1206 
1207                 nCount = nNewSize;
1208             }
1209         }
1210     }
1211     else
1212         Clear();
1213 }
1214 
1215 /*************************************************************************
1216 |*
1217 |*    Container::Clear()
1218 |*
1219 |*    Beschreibung      CONTNR.SDW
1220 |*    Ersterstellung    TH 17.09.91
1221 |*    Letzte Aenderung  TH 17.09.91
1222 |*
1223 *************************************************************************/
1224 
Clear()1225 void Container::Clear()
1226 {
1227     DBG_CHKTHIS( Container, DbgCheckContainer );
1228 
1229     // Erst alle Bloecke loeschen
1230     CBlock* pBlock = pFirstBlock;
1231     while ( pBlock )
1232     {
1233         CBlock* pTemp = pBlock->GetNextBlock();
1234         delete pBlock;
1235         pBlock = pTemp;
1236     }
1237 
1238     // Werte zuruecksetzen
1239     pFirstBlock = NULL;
1240     pLastBlock  = NULL;
1241     pCurBlock   = NULL;
1242     nCount      = 0;
1243     nCurIndex   = 0;
1244 }
1245 
1246 /*************************************************************************
1247 |*
1248 |*    Container::GetCurObject()
1249 |*
1250 |*    Beschreibung      CONTNR.SDW
1251 |*    Ersterstellung    TH 17.09.91
1252 |*    Letzte Aenderung  TH 17.09.91
1253 |*
1254 *************************************************************************/
1255 
GetCurObject() const1256 void* Container::GetCurObject() const
1257 {
1258     DBG_CHKTHIS( Container, DbgCheckContainer );
1259 
1260     // NULL, wenn Container leer
1261     if ( !nCount )
1262         return NULL;
1263     else
1264         return pCurBlock->GetObject( nCurIndex );
1265 }
1266 
1267 /*************************************************************************
1268 |*
1269 |*    Container::GetCurPos()
1270 |*
1271 |*    Beschreibung      CONTNR.SDW
1272 |*    Ersterstellung    TH 17.09.91
1273 |*    Letzte Aenderung  TH 17.09.91
1274 |*
1275 *************************************************************************/
1276 
GetCurPos() const1277 sal_uIntPtr Container::GetCurPos() const
1278 {
1279     DBG_CHKTHIS( Container, DbgCheckContainer );
1280 
1281     // CONTAINER_ENTRY_NOTFOUND, wenn Container leer
1282     if ( !nCount )
1283         return CONTAINER_ENTRY_NOTFOUND;
1284     else
1285     {
1286         // Block suchen
1287         CBlock* pTemp = pFirstBlock;
1288         sal_uIntPtr nTemp = 0;
1289         while ( pTemp != pCurBlock )
1290         {
1291             nTemp += pTemp->Count();
1292             pTemp  = pTemp->GetNextBlock();
1293         }
1294 
1295         return nTemp+nCurIndex;
1296     }
1297 }
1298 
1299 /*************************************************************************
1300 |*
1301 |*    Container::GetObjectPtr()
1302 |*
1303 |*    Beschreibung      Interne Methode fuer Referenz-Container
1304 |*    Ersterstellung    TH 26.01.93
1305 |*    Letzte Aenderung  TH 26.01.93
1306 |*
1307 *************************************************************************/
1308 
GetObjectPtr(sal_uIntPtr nIndex)1309 void** Container::GetObjectPtr( sal_uIntPtr nIndex )
1310 {
1311     DBG_CHKTHIS( Container, DbgCheckContainer );
1312 
1313     // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben
1314     if ( nCount <= nIndex )
1315         return NULL;
1316     else
1317     {
1318         // Block suchen
1319         CBlock* pTemp = pFirstBlock;
1320         while ( pTemp->Count() <= nIndex )
1321         {
1322             nIndex -= pTemp->Count();
1323             pTemp   = pTemp->GetNextBlock();
1324         }
1325 
1326         // Item innerhalb des gefundenen Blocks zurueckgeben
1327         return pTemp->GetObjectPtr( (sal_uInt16)nIndex );
1328     }
1329 }
1330 
1331 /*************************************************************************
1332 |*
1333 |*    Container::GetObject()
1334 |*
1335 |*    Beschreibung      CONTNR.SDW
1336 |*    Ersterstellung    TH 17.09.91
1337 |*    Letzte Aenderung  TH 17.09.91
1338 |*
1339 *************************************************************************/
1340 
GetObject(sal_uIntPtr nIndex) const1341 void* Container::GetObject( sal_uIntPtr nIndex ) const
1342 {
1343     DBG_CHKTHIS( Container, DbgCheckContainer );
1344 
1345     // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben
1346     if ( nCount <= nIndex )
1347         return NULL;
1348     else
1349     {
1350         // Block suchen
1351         CBlock* pTemp = pFirstBlock;
1352         while ( pTemp->Count() <= nIndex )
1353         {
1354             nIndex -= pTemp->Count();
1355             pTemp   = pTemp->GetNextBlock();
1356         }
1357 
1358         // Item innerhalb des gefundenen Blocks zurueckgeben
1359         return pTemp->GetObject( (sal_uInt16)nIndex );
1360     }
1361 }
1362 
1363 /*************************************************************************
1364 |*
1365 |*    Container::GetPos()
1366 |*
1367 |*    Beschreibung      CONTNR.SDW
1368 |*    Ersterstellung    TH 17.09.91
1369 |*    Letzte Aenderung  TH 17.09.91
1370 |*
1371 *************************************************************************/
1372 
GetPos(const void * p) const1373 sal_uIntPtr Container::GetPos( const void* p ) const
1374 {
1375     DBG_CHKTHIS( Container, DbgCheckContainer );
1376 
1377     void**  pNodes;
1378     CBlock* pTemp;
1379     sal_uIntPtr nTemp;
1380     sal_uInt16  nBlockCount;
1381     sal_uInt16  i;
1382 
1383     // Block suchen
1384     pTemp = pFirstBlock;
1385     nTemp = 0;
1386     while ( pTemp )
1387     {
1388         pNodes = pTemp->GetNodes();
1389         i = 0;
1390         nBlockCount = pTemp->Count();
1391         while ( i < nBlockCount )
1392         {
1393             if ( p == *pNodes )
1394                 return nTemp+i;
1395             pNodes++;
1396             i++;
1397         }
1398         nTemp += nBlockCount;
1399         pTemp  = pTemp->GetNextBlock();
1400     }
1401 
1402     return CONTAINER_ENTRY_NOTFOUND;
1403 }
1404 
1405 /*************************************************************************
1406 |*
1407 |*    Container::GetPos()
1408 |*
1409 |*    Beschreibung      CONTNR.SDW
1410 |*    Ersterstellung    TH 14.09.94
1411 |*    Letzte Aenderung  TH 14.09.94
1412 |*
1413 *************************************************************************/
1414 
GetPos(const void * p,sal_uIntPtr nStartIndex,sal_Bool bForward) const1415 sal_uIntPtr Container::GetPos( const void* p, sal_uIntPtr nStartIndex,
1416                          sal_Bool bForward ) const
1417 {
1418     DBG_CHKTHIS( Container, DbgCheckContainer );
1419 
1420     // Ist Index nicht innerhalb des Containers, dann NOTFOUND zurueckgeben
1421     if ( nCount <= nStartIndex )
1422         return CONTAINER_ENTRY_NOTFOUND;
1423     else
1424     {
1425         void**  pNodes;
1426         sal_uInt16  nBlockCount;
1427         sal_uInt16  i;
1428 
1429         // Block suchen
1430         CBlock* pTemp = pFirstBlock;
1431         sal_uIntPtr nTemp = 0;
1432         while ( nTemp+pTemp->Count() <= nStartIndex )
1433         {
1434             nTemp += pTemp->Count();
1435             pTemp  = pTemp->GetNextBlock();
1436         }
1437 
1438         // Jetzt den Pointer suchen
1439         if ( bForward )
1440         {
1441             // Alle Bloecke durchrsuchen
1442             i = (sal_uInt16)(nStartIndex - nTemp);
1443             pNodes = pTemp->GetObjectPtr( i );
1444             do
1445             {
1446                 nBlockCount = pTemp->Count();
1447                 while ( i < nBlockCount )
1448                 {
1449                     if ( p == *pNodes )
1450                         return nTemp+i;
1451                     pNodes++;
1452                     i++;
1453                 }
1454                 nTemp += nBlockCount;
1455                 pTemp  = pTemp->GetNextBlock();
1456                 if ( pTemp )
1457                 {
1458                     i = 0;
1459                     pNodes = pTemp->GetNodes();
1460                 }
1461                 else
1462                     break;
1463             }
1464             while ( sal_True );
1465         }
1466         else
1467         {
1468             // Alle Bloecke durchrsuchen
1469             i = (sal_uInt16)(nStartIndex-nTemp)+1;
1470             pNodes = pTemp->GetObjectPtr( i-1 );
1471             do
1472             {
1473                 do
1474                 {
1475                     if ( p == *pNodes )
1476                         return nTemp+i-1;
1477                     pNodes--;
1478                     i--;
1479                 }
1480                 while ( i );
1481                 nTemp -= pTemp->Count();
1482                 pTemp  = pTemp->GetPrevBlock();
1483                 if ( pTemp )
1484                 {
1485                     i = pTemp->Count();
1486                     // Leere Bloecke in der Kette darf es nicht geben. Nur
1487                     // wenn ein Block existiert, darf dieser leer sein
1488                     pNodes = pTemp->GetObjectPtr( i-1 );
1489                 }
1490                 else
1491                     break;
1492             }
1493             while ( sal_True );
1494         }
1495     }
1496 
1497     return CONTAINER_ENTRY_NOTFOUND;
1498 }
1499 
1500 /*************************************************************************
1501 |*
1502 |*    Container::Seek()
1503 |*
1504 |*    Beschreibung      CONTNR.SDW
1505 |*    Ersterstellung    TH 17.09.91
1506 |*    Letzte Aenderung  TH 17.09.91
1507 |*
1508 *************************************************************************/
1509 
Seek(sal_uIntPtr nIndex)1510 void* Container::Seek( sal_uIntPtr nIndex )
1511 {
1512     DBG_CHKTHIS( Container, DbgCheckContainer );
1513 
1514     // Ist der Container leer, dann NULL zurueckgeben
1515     if ( nCount <= nIndex )
1516         return NULL;
1517     else
1518     {
1519         // Block suchen
1520         CBlock* pTemp = pFirstBlock;
1521         while ( pTemp->Count() <= nIndex )
1522         {
1523             nIndex -= pTemp->Count();
1524             pTemp   = pTemp->GetNextBlock();
1525         }
1526 
1527         // Item innerhalb des gefundenen Blocks zurueckgeben
1528         pCurBlock = pTemp;
1529         nCurIndex = (sal_uInt16)nIndex;
1530         return pCurBlock->GetObject( nCurIndex );
1531     }
1532 }
1533 
1534 /*************************************************************************
1535 |*
1536 |*    Container::First()
1537 |*
1538 |*    Beschreibung      CONTNR.SDW
1539 |*    Ersterstellung    TH 17.09.91
1540 |*    Letzte Aenderung  TH 17.09.91
1541 |*
1542 *************************************************************************/
1543 
First()1544 void* Container::First()
1545 {
1546     DBG_CHKTHIS( Container, DbgCheckContainer );
1547 
1548     // Ist Container leer, dann NULL zurueckgeben
1549     if ( !nCount )
1550         return NULL;
1551     else
1552     {
1553         // Block und Index setzen und ersten Pointer zurueckgeben
1554         pCurBlock = pFirstBlock;
1555         nCurIndex = 0;
1556         return pCurBlock->GetObject( nCurIndex );
1557     }
1558 }
1559 
1560 /*************************************************************************
1561 |*
1562 |*    Container::Last()
1563 |*
1564 |*    Beschreibung      CONTNR.SDW
1565 |*    Ersterstellung    TH 17.09.91
1566 |*    Letzte Aenderung  TH 17.09.91
1567 |*
1568 *************************************************************************/
1569 
Last()1570 void* Container::Last()
1571 {
1572     DBG_CHKTHIS( Container, DbgCheckContainer );
1573 
1574     // Ist Container leer, dann NULL zurueckgeben
1575     if ( !nCount )
1576         return NULL;
1577     else
1578     {
1579         // Block und Index setzen und ersten Pointer zurueckgeben
1580         pCurBlock = pLastBlock;
1581         nCurIndex = pCurBlock->Count()-1;
1582         return pCurBlock->GetObject( nCurIndex );
1583     }
1584 }
1585 
1586 /*************************************************************************
1587 |*
1588 |*    Container::Next()
1589 |*
1590 |*    Beschreibung      CONTNR.SDW
1591 |*    Ersterstellung    TH 17.09.91
1592 |*    Letzte Aenderung  TH 17.09.91
1593 |*
1594 *************************************************************************/
1595 
Next()1596 void* Container::Next()
1597 {
1598     DBG_CHKTHIS( Container, DbgCheckContainer );
1599 
1600     // Ist Container leer, dann NULL zurueckgeben, ansonsten preufen ob
1601     // naechste Position noch im aktuellen Block ist. Falls nicht, dann
1602     // einen Block weiterschalten (geht ohne Gefahr, da leere Bloecke
1603     // nicht vorkommen duerfen, es sein denn, es ist der einzige).
1604     if ( !nCount )
1605         return NULL;
1606     else if ( (nCurIndex+1) < pCurBlock->Count() )
1607         return pCurBlock->GetObject( ++nCurIndex );
1608     else if ( pCurBlock->GetNextBlock() )
1609     {
1610         pCurBlock = pCurBlock->GetNextBlock();
1611         nCurIndex = 0;
1612         return pCurBlock->GetObject( nCurIndex );
1613     }
1614     else
1615         return NULL;
1616 }
1617 
1618 /*************************************************************************
1619 |*
1620 |*    Container::Prev()
1621 |*
1622 |*    Beschreibung      CONTNR.SDW
1623 |*    Ersterstellung    TH 17.09.91
1624 |*    Letzte Aenderung  TH 17.09.91
1625 |*
1626 *************************************************************************/
1627 
Prev()1628 void* Container::Prev()
1629 {
1630     DBG_CHKTHIS( Container, DbgCheckContainer );
1631 
1632     // Ist Container leer, dann NULL zurueckgeben, ansonsten preufen ob
1633     // vorherige Position noch im aktuellen Block ist. Falls nicht, dann
1634     // einen Block zurueckschalten (geht ohne Gefahr, da leere Bloecke
1635     // nicht vorkommen duerfen, es sein denn, es ist der einzige).
1636     if ( !nCount )
1637         return NULL;
1638     else if ( nCurIndex )
1639         return pCurBlock->GetObject( --nCurIndex );
1640     else if ( pCurBlock->GetPrevBlock() )
1641     {
1642         pCurBlock = pCurBlock->GetPrevBlock();
1643         nCurIndex = pCurBlock->Count() - 1;
1644         return pCurBlock->GetObject( nCurIndex );
1645     }
1646     else
1647         return NULL;
1648 }
1649 
1650 /*************************************************************************
1651 |*
1652 |*    Container::operator =()
1653 |*
1654 |*    Beschreibung      CONTNR.SDW
1655 |*    Ersterstellung    TH 17.09.91
1656 |*    Letzte Aenderung  TH 17.09.91
1657 |*
1658 *************************************************************************/
1659 
operator =(const Container & r)1660 Container& Container::operator =( const Container& r )
1661 {
1662     DBG_CHKTHIS( Container, DbgCheckContainer );
1663 
1664     // Erst alle Bloecke loeschen
1665     CBlock* pBlock = pFirstBlock;
1666     while ( pBlock )
1667     {
1668         CBlock* pTemp = pBlock->GetNextBlock();
1669         delete pBlock;
1670         pBlock = pTemp;
1671     }
1672 
1673     // Daten kopieren
1674     ImpCopyContainer( &r );
1675     return *this;
1676 }
1677 
1678 /*************************************************************************
1679 |*
1680 |*    Container::operator ==()
1681 |*
1682 |*    Beschreibung      CONTNR.SDW
1683 |*    Ersterstellung    TH 17.09.91
1684 |*    Letzte Aenderung  TH 17.09.91
1685 |*
1686 *************************************************************************/
1687 
operator ==(const Container & r) const1688 sal_Bool Container::operator ==( const Container& r ) const
1689 {
1690     DBG_CHKTHIS( Container, DbgCheckContainer );
1691 
1692     if ( nCount != r.nCount )
1693         return sal_False;
1694 
1695     sal_uIntPtr i = 0;
1696     while ( i < nCount )
1697     {
1698         if ( GetObject( i ) != r.GetObject( i ) )
1699             return sal_False;
1700         i++;
1701     }
1702 
1703     return sal_True;
1704 }
1705