/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_tools.hxx" #ifndef _LIMITS_H #include #endif #ifndef _STRING_H #include #endif #ifndef _STDIO_H #include #endif #include #include #include #include // ----------------------------------------------------------------------- DBG_NAME( CBlock ) DBG_NAME( Container ) /************************************************************************* |* |* DbgCheckCBlock() |* |* Beschreibung Pruefung eines CBlock fuer Debug-Utilities |* Ersterstellung MI 30.01.92 |* Letzte Aenderung TH 24.01.96 |* *************************************************************************/ #ifdef DBG_UTIL const char* CBlock::DbgCheckCBlock( const void* pBlock ) { CBlock* p = (CBlock*)pBlock; if ( p->nCount > p->nSize ) return "nCount > nSize"; if ( p->nSize && !p->pNodes ) return "nSize > 0 && pNodes == NULL"; return NULL; } #endif /************************************************************************* |* |* CBlock::CBlock() |* |* Beschreibung Construktor des Verwaltungsblocks |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ CBlock::CBlock( sal_uInt16 nInitSize, CBlock* _pPrev, CBlock* _pNext ) { DBG_CTOR( CBlock, DbgCheckCBlock ); pPrev = _pPrev; pNext = _pNext; nSize = nInitSize; nCount = 0; // Datenpuffer anlegen pNodes = new PVOID[nSize]; } /************************************************************************* |* |* CBlock::CBlock() |* |* Beschreibung Construktor des Verwaltungsblocks |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ CBlock::CBlock( sal_uInt16 _nSize, CBlock* _pPrev ) { DBG_CTOR( CBlock, DbgCheckCBlock ); DBG_ASSERT( _nSize, "CBlock::CBlock(): nSize == 0" ); pPrev = _pPrev; pNext = NULL; nSize = _nSize; nCount = _nSize; // Datenpuffer anlegen und initialisieren pNodes = new PVOID[nSize]; memset( pNodes, 0, nSize*sizeof(PVOID) ); } /************************************************************************* |* |* CBlock::CBlock() |* |* Beschreibung Copy-Construktor des Verwaltungsblocks |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ CBlock::CBlock( const CBlock& r, CBlock* _pPrev ) { DBG_CTOR( CBlock, DbgCheckCBlock ); DBG_CHKOBJ( &r, CBlock, DbgCheckCBlock ); pPrev = _pPrev; pNext = NULL; nSize = r.nSize; nCount = r.nCount; // Datenpuffer anlegen und Daten kopieren pNodes = new PVOID[nSize]; memcpy( pNodes, r.pNodes, nCount*sizeof(PVOID) ); } /************************************************************************* |* |* CBlock::~CBlock() |* |* Beschreibung Destruktor des Verwaltungsblocks |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ inline CBlock::~CBlock() { DBG_DTOR( CBlock, DbgCheckCBlock ); // Daten loeschen delete[] pNodes; } /************************************************************************* |* |* CBlock::Insert() |* |* Beschreibung Fuegt einen Pointer ein |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void CBlock::Insert( void* p, sal_uInt16 nIndex, sal_uInt16 nReSize ) { DBG_CHKTHIS( CBlock, DbgCheckCBlock ); DBG_ASSERT( nIndex <= nCount, "CBlock::Insert(): Index > nCount" ); // Muss Block realokiert werden if ( nCount == nSize ) { // Neue Daten anlegen nSize = nSize + nReSize; // MSVC warns here if += is used void** pNewNodes = new PVOID[nSize]; // Wird angehaengt if ( nCount == nIndex ) { // Daten kopieren memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) ); } else { // Daten kopieren memcpy( pNewNodes, pNodes, nIndex*sizeof(PVOID) ); memcpy( pNewNodes + nIndex + 1, pNodes + nIndex, (nCount-nIndex)*sizeof(PVOID) ); } // Alte Daten loeschen und neue setzen delete[] pNodes; pNodes = pNewNodes; } else { if ( nIndex < nCount ) { memmove( pNodes + nIndex + 1, pNodes + nIndex, (nCount-nIndex)*sizeof(PVOID) ); } } // Neuen Pointer setzen und Elementgroesse erhoehen pNodes[nIndex] = p; nCount++; } /************************************************************************* |* |* CBlock::Split() |* |* Beschreibung Fuegt einen Pointer ein und splittet den Block |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ CBlock* CBlock::Split( void* p, sal_uInt16 nIndex, sal_uInt16 nReSize ) { DBG_CHKTHIS( CBlock, DbgCheckCBlock ); sal_uInt16 nNewSize; sal_uInt16 nMiddle; CBlock* pNewBlock; nMiddle = nCount/2; if ( ( nIndex == nCount ) || ( nIndex == 0 ) ) nNewSize = nReSize; else { // Der aktuelle Block wird in der Mitte geteilt nNewSize = (nCount+1) / 2; if ( nNewSize < nReSize ) nNewSize = nReSize; else { // Neue Groesse muss ein vielfaches von Resize sein if ( nNewSize % nReSize ) nNewSize += nReSize - (nNewSize % nReSize); else nNewSize = nNewSize + nReSize; // MSVC warns here if += is used } } // Vor oder hinter dem aktuellem Block einfuegen? if ( nIndex > nMiddle ) { // Neuen Split-Block anlegen und hinter dem aktuellem Block einfuegen pNewBlock = new CBlock( nNewSize, this, pNext ); if ( pNext ) pNext->pPrev = pNewBlock; pNext = pNewBlock; if ( nIndex == nCount ) { // Neuen Pointer einfuegen pNewBlock->pNodes[0] = p; pNewBlock->nCount = 1; } else { nIndex = nIndex - nMiddle; // MSVC warns here if += is used // Alles von Mitte bis Index kopieren if ( nIndex ) memcpy( pNewBlock->pNodes, pNodes+nMiddle, nIndex*sizeof(PVOID) ); // Neuen Pointer einfuegen pNewBlock->pNodes[nIndex] = p; // Alles von Mitte bis Ende hinter Index kopieren memcpy( pNewBlock->pNodes+nIndex+1, pNodes+nMiddle+nIndex, (nCount-nMiddle-nIndex) * sizeof(PVOID) ); pNewBlock->nCount = (nCount-nMiddle+1); nCount = nMiddle; // Den aktuellen Datenbereich auch halbieren if ( nSize != nNewSize ) { void** pNewNodes = new PVOID[nNewSize]; memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) ); delete[] pNodes; pNodes = pNewNodes; nSize = nNewSize; } } } else { // Neuen Split-Block anlegen und vor dem aktuellem Block einfuegen pNewBlock = new CBlock( nNewSize, pPrev, this ); if ( pPrev ) pPrev->pNext = pNewBlock; pPrev = pNewBlock; if ( nIndex == 0 ) { // Neuen Pointer einfuegen pNewBlock->pNodes[0] = p; pNewBlock->nCount = 1; } else { // Alles von Anfang bis Index kopieren memcpy( pNewBlock->pNodes, pNodes, nIndex*sizeof(PVOID) ); // Neuen Pointer einfuegen pNewBlock->pNodes[nIndex] = p; // Alles von Index bis Mitte hinter Index kopieren if ( nIndex != nMiddle ) { memcpy( pNewBlock->pNodes+nIndex+1, pNodes+nIndex, (nMiddle-nIndex) * sizeof(PVOID) ); } pNewBlock->nCount = nMiddle+1; nCount = nCount - nMiddle; // MSVC warns here if += is used // Die zweite Haelfte in einen neuen Block kopieren if ( nSize != nNewSize ) { void** pNewNodes = new PVOID[nNewSize]; memcpy( pNewNodes, pNodes+nMiddle, nCount*sizeof(PVOID) ); delete[] pNodes; pNodes = pNewNodes; nSize = nNewSize; } else memmove( pNodes, pNodes+nMiddle, nCount*sizeof(PVOID) ); } } // Neu angelegten Block zurueckgeben, da gegebenfalls die Blockpointer // im Container angepast werden koennen return pNewBlock; } /************************************************************************* |* |* CBlock::Remove() |* |* Beschreibung Entfernt einen Pointer |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void* CBlock::Remove( sal_uInt16 nIndex, sal_uInt16 nReSize ) { DBG_CHKTHIS( CBlock, DbgCheckCBlock ); // Alten Pointer sichern void* pOld = pNodes[nIndex]; // 1 Element weniger nCount--; // Block verkleinern (wenn Reallokationsgroesse um 4 unterschritten wird) if ( nCount == (nSize-nReSize-4) ) { // Neue Daten anlegen nSize = nSize - nReSize; // MSVC warns here if += is used void** pNewNodes = new PVOID[nSize]; // Wird letzter Eintrag geloescht if ( nIndex == nCount ) { // Daten kopieren memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) ); } else { // Daten kopieren memcpy( pNewNodes, pNodes, nIndex*sizeof(PVOID) ); memcpy( pNewNodes + nIndex, pNodes + nIndex+1, (nCount-nIndex)*sizeof(PVOID) ); } // Alte Daten loeschen und neue setzen delete[] pNodes; pNodes = pNewNodes; } else { // Wenn nicht das letzte Element, dann zusammenschieben if ( nIndex < nCount ) { memmove( pNodes + nIndex, pNodes + nIndex + 1, (nCount-nIndex)*sizeof(PVOID) ); } } // Alten Pointer zurueckgeben return pOld; } /************************************************************************* |* |* CBlock::Replace() |* |* Beschreibung Ersetzt einen Pointer |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ inline void* CBlock::Replace( void* p, sal_uInt16 nIndex ) { DBG_CHKTHIS( CBlock, DbgCheckCBlock ); // Alten Pointer sichern, neuen setzen und alten zurueckgeben void* pOld = pNodes[nIndex]; pNodes[nIndex] = p; return pOld; } /************************************************************************* |* |* CBlock::GetObjectPtr() |* |* Beschreibung Gibt einen Pointer auf den Pointer aus dem Block |* zurueck |* Ersterstellung TH 26.01.93 |* Letzte Aenderung TH 26.01.93 |* *************************************************************************/ inline void** CBlock::GetObjectPtr( sal_uInt16 nIndex ) { DBG_CHKTHIS( CBlock, DbgCheckCBlock ); return &(pNodes[nIndex]); } /************************************************************************* |* |* CBlock::SetSize() |* |* Beschreibung Aendert die Groesse des Blocks |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void CBlock::SetSize( sal_uInt16 nNewSize ) { DBG_CHKTHIS( CBlock, DbgCheckCBlock ); DBG_ASSERT( nNewSize, "CBlock::SetSize(): nNewSize == 0" ); // Unterscheidet sich die Groesse if ( nNewSize != nCount ) { // Array erweitern void** pNewNodes = new PVOID[nNewSize]; // Alte Tabelle in die Neue kopieren if ( nNewSize < nCount ) memcpy( pNewNodes, pNodes, nNewSize*sizeof(PVOID) ); else { memcpy( pNewNodes, pNodes, nCount*sizeof(PVOID) ); // Array mit 0 initialisieren memset( pNewNodes+nCount, 0, (nNewSize-nCount)*sizeof(PVOID) ); } // Altes Array loeschen und neue Werte setzen nSize = nNewSize; nCount = nSize; delete[] pNodes; pNodes = pNewNodes; } } //------------------------------------------------------------------------ /************************************************************************* |* |* DbgCheckContainer() |* |* Beschreibung Pruefung eines Container fuer Debug-Utilities |* Ersterstellung MI 30.01.92 |* Letzte Aenderung TH 24.01.96 |* *************************************************************************/ #ifdef DBG_UTIL const char* Container::DbgCheckContainer( const void* pCont ) { Container* p = (Container*)pCont; if ( p->nCount && (!p->pFirstBlock || !p->pLastBlock || !p->pCurBlock) ) return "nCount > 0 but no CBlocks"; return NULL; } #endif /************************************************************************* |* |* ImpCopyContainer() |* |* Beschreibung Kopiert alle Daten des Containers |* Ersterstellung TH 24.01.96 |* Letzte Aenderung TH 24.01.96 |* *************************************************************************/ void Container::ImpCopyContainer( const Container* pCont2 ) { // Werte vom uebergebenen Container uebernehmen nCount = pCont2->nCount; nCurIndex = pCont2->nCurIndex; nInitSize = pCont2->nInitSize; nReSize = pCont2->nReSize; nBlockSize = pCont2->nBlockSize; // Alle Bloecke kopieren if ( pCont2->nCount ) { CBlock* pBlock1; CBlock* pBlock2; CBlock* pTempBlock; // Erstmal ersten Block kopieren pBlock2 = pCont2->pFirstBlock; pFirstBlock = new CBlock( *pBlock2, NULL ); // Ist erster Block der Current-Block, dann Current-Block setzen if ( pBlock2 == pCont2->pCurBlock ) pCurBlock = pFirstBlock; pBlock1 = pFirstBlock; pBlock2 = pBlock2->GetNextBlock(); while ( pBlock2 ) { // Neuen Block anlegen und aus der uebergebenen Liste kopieren pTempBlock = new CBlock( *pBlock2, pBlock1 ); pBlock1->SetNextBlock( pTempBlock ); pBlock1 = pTempBlock; // Current-Block beruecksichtigen if ( pBlock2 == pCont2->pCurBlock ) pCurBlock = pBlock1; // Auf naechsten Block weitersetzen pBlock2 = pBlock2->GetNextBlock(); } // Letzten Block setzen pLastBlock = pBlock1; } else { pFirstBlock = NULL; pLastBlock = NULL; pCurBlock = NULL; } } /************************************************************************* |* |* Container::Container() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ Container::Container( sal_uInt16 _nBlockSize, sal_uInt16 _nInitSize, sal_uInt16 _nReSize ) { DBG_CTOR( Container, DbgCheckContainer ); // BlockSize muss mindestens 4 sein und kleiner als 64 KB if ( _nBlockSize < 4 ) nBlockSize = 4; else { if ( _nBlockSize < CONTAINER_MAXBLOCKSIZE ) nBlockSize = _nBlockSize; else nBlockSize = CONTAINER_MAXBLOCKSIZE; } // ReSize muss mindestens 2 sein und kleiner als BlockSize if ( _nReSize >= nBlockSize ) nReSize = nBlockSize; else { if ( _nReSize < 2 ) nReSize = 2; else nReSize = _nReSize; // BlockSize muss ein vielfaches der Resizegroesse sein if ( nBlockSize % nReSize ) nBlockSize -= nReSize - (nBlockSize % nReSize); } // InitSize muss groesser gleich ReSize sein und kleiner als BlockSize if ( _nInitSize <= nReSize ) nInitSize = nReSize; else { if ( _nInitSize >= nBlockSize ) nInitSize = nBlockSize; else { nInitSize = _nInitSize; // InitSize muss ein vielfaches der Resizegroesse sein if ( nInitSize % nReSize ) nInitSize -= nReSize - (nInitSize % nReSize); } } // Werte initialisieren pFirstBlock = NULL; pLastBlock = NULL; pCurBlock = NULL; nCount = 0; nCurIndex = 0; } /************************************************************************* |* |* Container::Container() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ Container::Container( sal_uIntPtr nSize ) { DBG_CTOR( Container, DbgCheckContainer ); nCount = nSize; nCurIndex = 0; nBlockSize = CONTAINER_MAXBLOCKSIZE; nInitSize = 1; nReSize = 1; if ( !nSize ) { pFirstBlock = NULL; pLastBlock = NULL; pCurBlock = NULL; } else { // Muss mehr als ein Block angelegt werden if ( nSize <= nBlockSize ) { pFirstBlock = new CBlock( (sal_uInt16)nSize, NULL ); pLastBlock = pFirstBlock; } else { CBlock* pBlock1; CBlock* pBlock2; pFirstBlock = new CBlock( nBlockSize, NULL ); pBlock1 = pFirstBlock; nSize -= nBlockSize; // Solange die Blockgroesse ueberschritten wird, neue Bloecke anlegen while ( nSize > nBlockSize ) { pBlock2 = new CBlock( nBlockSize, pBlock1 ); pBlock1->SetNextBlock( pBlock2 ); pBlock1 = pBlock2; nSize -= nBlockSize; } pLastBlock = new CBlock( (sal_uInt16)nSize, pBlock1 ); pBlock1->SetNextBlock( pLastBlock ); } pCurBlock = pFirstBlock; } } /************************************************************************* |* |* Container::Container() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ Container::Container( const Container& r ) { DBG_CTOR( Container, DbgCheckContainer ); // Daten kopieren ImpCopyContainer( &r ); } /************************************************************************* |* |* Container::~Container() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ Container::~Container() { DBG_DTOR( Container, DbgCheckContainer ); // Alle Bloecke loeschen CBlock* pBlock = pFirstBlock; while ( pBlock ) { CBlock* pTemp = pBlock->GetNextBlock(); delete pBlock; pBlock = pTemp; } } /************************************************************************* |* |* Container::ImpInsert() |* |* Beschreibung Interne Methode zum Einfuegen eines Pointers |* Ersterstellung TH 17.09.91 |* Letzte Aenderung DV 01.07.97 |* *************************************************************************/ void Container::ImpInsert( void* p, CBlock* pBlock, sal_uInt16 nIndex ) { DBG_CHKTHIS( Container, DbgCheckContainer ); if ( !nCount ) { if ( !pBlock ) { pFirstBlock = new CBlock( nInitSize, NULL, NULL ); pLastBlock = pFirstBlock; pCurBlock = pFirstBlock; } pFirstBlock->Insert( p, nIndex, nReSize ); } else { // Ist im Block die maximale Blockgroesse erreicht, // dann neuen Block anlegen if ( pBlock->Count() == nBlockSize ) { // Block auftrennen CBlock* pNewBlock = pBlock->Split( p, nIndex, nReSize ); // Wurde Block dahinter angehaegnt if ( pBlock->pNext == pNewBlock ) { // Gegebenenfalls LastBlock anpassen if ( pBlock == pLastBlock ) pLastBlock = pNewBlock; // Current-Position nachfuehren if ( pBlock == pCurBlock ) { if ( pBlock->nCount <= nCurIndex ) { if ( nIndex <= nCurIndex ) nCurIndex++; pCurBlock = pNewBlock; nCurIndex = nCurIndex - pBlock->nCount; // MSVC warns here if += is used } } } else { // Gegebenenfalls FirstBlock anpassen if ( pBlock == pFirstBlock ) pFirstBlock = pNewBlock; // Current-Position nachfuehren if ( pBlock == pCurBlock ) { if ( nIndex <= nCurIndex ) nCurIndex++; if ( pNewBlock->nCount <= nCurIndex ) nCurIndex = nCurIndex - pNewBlock->nCount; // MSVC warns here if += is used else pCurBlock = pNewBlock; } } } else { // Sonst reicht normales einfuegen in den Block pBlock->Insert( p, nIndex, nReSize ); // Current-Position nachfuehren if ( (pBlock == pCurBlock) && (nIndex <= nCurIndex) ) nCurIndex++; } } // Ein neues Item im Container nCount++; } /************************************************************************* |* |* Container::Insert() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void Container::Insert( void* p ) { ImpInsert( p, pCurBlock, nCurIndex ); } /************************************************************************* |* |* Container::Insert() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void Container::Insert( void* p, sal_uIntPtr nIndex ) { if ( nCount <= nIndex ) { if ( pLastBlock ) ImpInsert( p, pLastBlock, pLastBlock->Count() ); else ImpInsert( p, NULL, 0 ); } else { // Block suchen CBlock* pTemp = pFirstBlock; while ( pTemp->Count() < nIndex ) { nIndex -= pTemp->Count(); pTemp = pTemp->GetNextBlock(); } ImpInsert( p, pTemp, (sal_uInt16)nIndex ); } } /************************************************************************* |* |* Container::Insert() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void Container::Insert( void* pNew, void* pOld ) { sal_uIntPtr nIndex = GetPos( pOld ); if ( nIndex != CONTAINER_ENTRY_NOTFOUND ) Insert( pNew, nIndex ); } /************************************************************************* |* |* Container::ImpRemove() |* |* Beschreibung Interne Methode zum Entfernen eines Pointers |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void* Container::ImpRemove( CBlock* pBlock, sal_uInt16 nIndex ) { DBG_CHKTHIS( Container, DbgCheckContainer ); void* pOld; // Ist Liste danach leer if ( nCount == 1 ) { // Block und CurIndex zuruecksetzen pOld = pBlock->GetObject( nIndex ); pBlock->Reset(); nCurIndex = 0; } else { // Ist Block nach Remove leer if ( pBlock->Count() == 1 ) { // dann Block entfernen und Block-Pointer umsetzen if ( pBlock->GetPrevBlock() ) (pBlock->GetPrevBlock())->SetNextBlock( pBlock->GetNextBlock() ); else pFirstBlock = pBlock->GetNextBlock(); if ( pBlock->GetNextBlock() ) (pBlock->GetNextBlock())->SetPrevBlock( pBlock->GetPrevBlock() ); else pLastBlock = pBlock->GetPrevBlock(); // Current-Position nachfuehren if ( pBlock == pCurBlock ) { if ( pBlock->GetNextBlock() ) { pCurBlock = pBlock->GetNextBlock(); nCurIndex = 0; } else { pCurBlock = pBlock->GetPrevBlock(); nCurIndex = pCurBlock->Count()-1; } } pOld = pBlock->GetObject( nIndex ); delete pBlock; } else { // Sonst Item aus dem Block entfernen pOld = pBlock->Remove( nIndex, nReSize ); // Current-Position nachfuehren if ( (pBlock == pCurBlock) && ((nIndex < nCurIndex) || ((nCurIndex == pBlock->Count()) && nCurIndex)) ) nCurIndex--; } } // Jetzt gibt es ein Item weniger nCount--; // Und den Pointer zurueckgeben, der entfernt wurde return pOld; } /************************************************************************* |* |* Container::Remove() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void* Container::Remove() { // Wenn kein Item vorhanden ist, NULL zurueckgeben if ( !nCount ) return NULL; else return ImpRemove( pCurBlock, nCurIndex ); } /************************************************************************* |* |* Container::Remove() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void* Container::Remove( sal_uIntPtr nIndex ) { // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben if ( nCount <= nIndex ) return NULL; else { // Block suchen CBlock* pTemp = pFirstBlock; while ( pTemp->Count() <= nIndex ) { nIndex -= pTemp->Count(); pTemp = pTemp->GetNextBlock(); } return ImpRemove( pTemp, (sal_uInt16)nIndex ); } } /************************************************************************* |* |* Container::Replace() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void* Container::Replace( void* p ) { DBG_CHKTHIS( Container, DbgCheckContainer ); if ( !nCount ) return NULL; else return pCurBlock->Replace( p, nCurIndex ); } /************************************************************************* |* |* Container::Replace() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void* Container::Replace( void* p, sal_uIntPtr nIndex ) { DBG_CHKTHIS( Container, DbgCheckContainer ); // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben if ( nCount <= nIndex ) return NULL; else { // Block suchen CBlock* pTemp = pFirstBlock; while ( pTemp->Count() <= nIndex ) { nIndex -= pTemp->Count(); pTemp = pTemp->GetNextBlock(); } return pTemp->Replace( p, (sal_uInt16)nIndex ); } } /************************************************************************* |* |* Container::SetSize() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void Container::SetSize( sal_uIntPtr nNewSize ) { DBG_CHKTHIS( Container, DbgCheckContainer ); if ( nNewSize ) { // Unterscheiden sich die Groessen if ( nNewSize != nCount ) { CBlock* pTemp; sal_uIntPtr nTemp; // Wird verkleinert if ( nNewSize < nCount ) { pTemp = pFirstBlock; nTemp = 0; while ( (nTemp+pTemp->Count()) < nNewSize ) { nTemp += pTemp->Count(); pTemp = pTemp->GetNextBlock(); } // Alle folgenden Bloecke loeschen sal_Bool bLast = sal_False; CBlock* pDelNext; CBlock* pDelBlock = pTemp->GetNextBlock(); while ( pDelBlock ) { // Muss CurrentBlock umgesetzt werden if ( pDelBlock == pCurBlock ) bLast = sal_True; pDelNext = pDelBlock->GetNextBlock(); delete pDelBlock; pDelBlock = pDelNext; } // Block in der Groesse anpassen, oder bei Groesse 0 loeschen if ( nNewSize > nTemp ) { pLastBlock = pTemp; pTemp->SetNextBlock( NULL ); pTemp->SetSize( (sal_uInt16)(nNewSize-nTemp) ); } else { pLastBlock = pTemp->GetPrevBlock(); pLastBlock->SetNextBlock( NULL ); delete pTemp; } nCount = nNewSize; if ( bLast ) { pCurBlock = pLastBlock; nCurIndex = pCurBlock->Count()-1; } } else { // Auf den letzen Puffer setzen pTemp = pLastBlock; nTemp = nNewSize - nCount; if ( !pTemp ) { // Muss mehr als ein Block angelegt werden if ( nNewSize <= nBlockSize ) { pFirstBlock = new CBlock( (sal_uInt16)nNewSize, NULL ); pLastBlock = pFirstBlock; } else { CBlock* pBlock1; CBlock* pBlock2; pFirstBlock = new CBlock( nBlockSize, NULL ); pBlock1 = pFirstBlock; nNewSize -= nBlockSize; // Solange die Blockgroesse ueberschritten wird, neue Bloecke anlegen while ( nNewSize > nBlockSize ) { pBlock2 = new CBlock( nBlockSize, pBlock1 ); pBlock1->SetNextBlock( pBlock2 ); pBlock1 = pBlock2; nNewSize -= nBlockSize; } pLastBlock = new CBlock( (sal_uInt16)nNewSize, pBlock1 ); pBlock1->SetNextBlock( pLastBlock ); } pCurBlock = pFirstBlock; } // Reicht es, den letzen Puffer in der Groesse anzupassen else if ( (nTemp+pTemp->Count()) <= nBlockSize ) pTemp->SetSize( (sal_uInt16)(nTemp+pTemp->Count()) ); else { // Puffer auf max. Blockgroesse setzen nTemp -= nBlockSize - pTemp->GetSize(); pTemp->SetSize( nBlockSize ); CBlock* pTemp2; // Solange die Blockgroesse ueberschritten wird, // neue Bloecke anlegen while ( nTemp > nBlockSize ) { pTemp2 = new CBlock( nBlockSize, pTemp ); pTemp->SetNextBlock( pTemp2 ); pTemp = pTemp2; nTemp -= nBlockSize; } // Den letzten Block anlegen if ( nTemp ) { pLastBlock = new CBlock( (sal_uInt16)nTemp, pTemp ); pTemp->SetNextBlock( pLastBlock ); } else pLastBlock = pTemp; } nCount = nNewSize; } } } else Clear(); } /************************************************************************* |* |* Container::Clear() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void Container::Clear() { DBG_CHKTHIS( Container, DbgCheckContainer ); // Erst alle Bloecke loeschen CBlock* pBlock = pFirstBlock; while ( pBlock ) { CBlock* pTemp = pBlock->GetNextBlock(); delete pBlock; pBlock = pTemp; } // Werte zuruecksetzen pFirstBlock = NULL; pLastBlock = NULL; pCurBlock = NULL; nCount = 0; nCurIndex = 0; } /************************************************************************* |* |* Container::GetCurObject() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void* Container::GetCurObject() const { DBG_CHKTHIS( Container, DbgCheckContainer ); // NULL, wenn Container leer if ( !nCount ) return NULL; else return pCurBlock->GetObject( nCurIndex ); } /************************************************************************* |* |* Container::GetCurPos() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ sal_uIntPtr Container::GetCurPos() const { DBG_CHKTHIS( Container, DbgCheckContainer ); // CONTAINER_ENTRY_NOTFOUND, wenn Container leer if ( !nCount ) return CONTAINER_ENTRY_NOTFOUND; else { // Block suchen CBlock* pTemp = pFirstBlock; sal_uIntPtr nTemp = 0; while ( pTemp != pCurBlock ) { nTemp += pTemp->Count(); pTemp = pTemp->GetNextBlock(); } return nTemp+nCurIndex; } } /************************************************************************* |* |* Container::GetObjectPtr() |* |* Beschreibung Interne Methode fuer Referenz-Container |* Ersterstellung TH 26.01.93 |* Letzte Aenderung TH 26.01.93 |* *************************************************************************/ void** Container::GetObjectPtr( sal_uIntPtr nIndex ) { DBG_CHKTHIS( Container, DbgCheckContainer ); // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben if ( nCount <= nIndex ) return NULL; else { // Block suchen CBlock* pTemp = pFirstBlock; while ( pTemp->Count() <= nIndex ) { nIndex -= pTemp->Count(); pTemp = pTemp->GetNextBlock(); } // Item innerhalb des gefundenen Blocks zurueckgeben return pTemp->GetObjectPtr( (sal_uInt16)nIndex ); } } /************************************************************************* |* |* Container::GetObject() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void* Container::GetObject( sal_uIntPtr nIndex ) const { DBG_CHKTHIS( Container, DbgCheckContainer ); // Ist Index nicht innerhalb des Containers, dann NULL zurueckgeben if ( nCount <= nIndex ) return NULL; else { // Block suchen CBlock* pTemp = pFirstBlock; while ( pTemp->Count() <= nIndex ) { nIndex -= pTemp->Count(); pTemp = pTemp->GetNextBlock(); } // Item innerhalb des gefundenen Blocks zurueckgeben return pTemp->GetObject( (sal_uInt16)nIndex ); } } /************************************************************************* |* |* Container::GetPos() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ sal_uIntPtr Container::GetPos( const void* p ) const { DBG_CHKTHIS( Container, DbgCheckContainer ); void** pNodes; CBlock* pTemp; sal_uIntPtr nTemp; sal_uInt16 nBlockCount; sal_uInt16 i; // Block suchen pTemp = pFirstBlock; nTemp = 0; while ( pTemp ) { pNodes = pTemp->GetNodes(); i = 0; nBlockCount = pTemp->Count(); while ( i < nBlockCount ) { if ( p == *pNodes ) return nTemp+i; pNodes++; i++; } nTemp += nBlockCount; pTemp = pTemp->GetNextBlock(); } return CONTAINER_ENTRY_NOTFOUND; } /************************************************************************* |* |* Container::GetPos() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 14.09.94 |* Letzte Aenderung TH 14.09.94 |* *************************************************************************/ sal_uIntPtr Container::GetPos( const void* p, sal_uIntPtr nStartIndex, sal_Bool bForward ) const { DBG_CHKTHIS( Container, DbgCheckContainer ); // Ist Index nicht innerhalb des Containers, dann NOTFOUND zurueckgeben if ( nCount <= nStartIndex ) return CONTAINER_ENTRY_NOTFOUND; else { void** pNodes; sal_uInt16 nBlockCount; sal_uInt16 i; // Block suchen CBlock* pTemp = pFirstBlock; sal_uIntPtr nTemp = 0; while ( nTemp+pTemp->Count() <= nStartIndex ) { nTemp += pTemp->Count(); pTemp = pTemp->GetNextBlock(); } // Jetzt den Pointer suchen if ( bForward ) { // Alle Bloecke durchrsuchen i = (sal_uInt16)(nStartIndex - nTemp); pNodes = pTemp->GetObjectPtr( i ); do { nBlockCount = pTemp->Count(); while ( i < nBlockCount ) { if ( p == *pNodes ) return nTemp+i; pNodes++; i++; } nTemp += nBlockCount; pTemp = pTemp->GetNextBlock(); if ( pTemp ) { i = 0; pNodes = pTemp->GetNodes(); } else break; } while ( sal_True ); } else { // Alle Bloecke durchrsuchen i = (sal_uInt16)(nStartIndex-nTemp)+1; pNodes = pTemp->GetObjectPtr( i-1 ); do { do { if ( p == *pNodes ) return nTemp+i-1; pNodes--; i--; } while ( i ); nTemp -= pTemp->Count(); pTemp = pTemp->GetPrevBlock(); if ( pTemp ) { i = pTemp->Count(); // Leere Bloecke in der Kette darf es nicht geben. Nur // wenn ein Block existiert, darf dieser leer sein pNodes = pTemp->GetObjectPtr( i-1 ); } else break; } while ( sal_True ); } } return CONTAINER_ENTRY_NOTFOUND; } /************************************************************************* |* |* Container::Seek() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void* Container::Seek( sal_uIntPtr nIndex ) { DBG_CHKTHIS( Container, DbgCheckContainer ); // Ist der Container leer, dann NULL zurueckgeben if ( nCount <= nIndex ) return NULL; else { // Block suchen CBlock* pTemp = pFirstBlock; while ( pTemp->Count() <= nIndex ) { nIndex -= pTemp->Count(); pTemp = pTemp->GetNextBlock(); } // Item innerhalb des gefundenen Blocks zurueckgeben pCurBlock = pTemp; nCurIndex = (sal_uInt16)nIndex; return pCurBlock->GetObject( nCurIndex ); } } /************************************************************************* |* |* Container::First() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void* Container::First() { DBG_CHKTHIS( Container, DbgCheckContainer ); // Ist Container leer, dann NULL zurueckgeben if ( !nCount ) return NULL; else { // Block und Index setzen und ersten Pointer zurueckgeben pCurBlock = pFirstBlock; nCurIndex = 0; return pCurBlock->GetObject( nCurIndex ); } } /************************************************************************* |* |* Container::Last() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void* Container::Last() { DBG_CHKTHIS( Container, DbgCheckContainer ); // Ist Container leer, dann NULL zurueckgeben if ( !nCount ) return NULL; else { // Block und Index setzen und ersten Pointer zurueckgeben pCurBlock = pLastBlock; nCurIndex = pCurBlock->Count()-1; return pCurBlock->GetObject( nCurIndex ); } } /************************************************************************* |* |* Container::Next() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void* Container::Next() { DBG_CHKTHIS( Container, DbgCheckContainer ); // Ist Container leer, dann NULL zurueckgeben, ansonsten preufen ob // naechste Position noch im aktuellen Block ist. Falls nicht, dann // einen Block weiterschalten (geht ohne Gefahr, da leere Bloecke // nicht vorkommen duerfen, es sein denn, es ist der einzige). if ( !nCount ) return NULL; else if ( (nCurIndex+1) < pCurBlock->Count() ) return pCurBlock->GetObject( ++nCurIndex ); else if ( pCurBlock->GetNextBlock() ) { pCurBlock = pCurBlock->GetNextBlock(); nCurIndex = 0; return pCurBlock->GetObject( nCurIndex ); } else return NULL; } /************************************************************************* |* |* Container::Prev() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ void* Container::Prev() { DBG_CHKTHIS( Container, DbgCheckContainer ); // Ist Container leer, dann NULL zurueckgeben, ansonsten preufen ob // vorherige Position noch im aktuellen Block ist. Falls nicht, dann // einen Block zurueckschalten (geht ohne Gefahr, da leere Bloecke // nicht vorkommen duerfen, es sein denn, es ist der einzige). if ( !nCount ) return NULL; else if ( nCurIndex ) return pCurBlock->GetObject( --nCurIndex ); else if ( pCurBlock->GetPrevBlock() ) { pCurBlock = pCurBlock->GetPrevBlock(); nCurIndex = pCurBlock->Count() - 1; return pCurBlock->GetObject( nCurIndex ); } else return NULL; } /************************************************************************* |* |* Container::operator =() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ Container& Container::operator =( const Container& r ) { DBG_CHKTHIS( Container, DbgCheckContainer ); // Erst alle Bloecke loeschen CBlock* pBlock = pFirstBlock; while ( pBlock ) { CBlock* pTemp = pBlock->GetNextBlock(); delete pBlock; pBlock = pTemp; } // Daten kopieren ImpCopyContainer( &r ); return *this; } /************************************************************************* |* |* Container::operator ==() |* |* Beschreibung CONTNR.SDW |* Ersterstellung TH 17.09.91 |* Letzte Aenderung TH 17.09.91 |* *************************************************************************/ sal_Bool Container::operator ==( const Container& r ) const { DBG_CHKTHIS( Container, DbgCheckContainer ); if ( nCount != r.nCount ) return sal_False; sal_uIntPtr i = 0; while ( i < nCount ) { if ( GetObject( i ) != r.GetObject( i ) ) return sal_False; i++; } return sal_True; }