diff options
Diffstat (limited to 'tools/source/memtools')
-rw-r--r-- | tools/source/memtools/contnr.cxx | 1754 | ||||
-rw-r--r-- | tools/source/memtools/makefile.mk | 92 | ||||
-rw-r--r-- | tools/source/memtools/mempool.cxx | 323 | ||||
-rw-r--r-- | tools/source/memtools/multisel.cxx | 897 | ||||
-rw-r--r-- | tools/source/memtools/table.cxx | 442 | ||||
-rw-r--r-- | tools/source/memtools/unqidx.cxx | 643 |
6 files changed, 4151 insertions, 0 deletions
diff --git a/tools/source/memtools/contnr.cxx b/tools/source/memtools/contnr.cxx new file mode 100644 index 000000000000..8228ecb4c880 --- /dev/null +++ b/tools/source/memtools/contnr.cxx @@ -0,0 +1,1754 @@ +/************************************************************************* + * + * $RCSfile: contnr.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#define private public +#define protected public + +#ifndef _LIMITS_H +#include <limits.h> +#endif + +#ifndef _STRING_H +#include <string.h> +#endif + +#ifndef _STDIO_H +#include <stdio.h> +#endif + +#ifndef _SOLAR_H +#include <solar.h> +#endif + +#ifndef _IMPCONT_HXX +#include <impcont.hxx> +#endif + +#ifndef _CONTNR_HXX +#include <contnr.hxx> +#endif + +#ifndef _DEBUG_HXX +#include <debug.hxx> +#endif + +// ----------------------------------------------------------------------- + +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* 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( USHORT nInitSize, CBlock* _pPrev, CBlock* _pNext ) +{ + DBG_CTOR( CBlock, DbgCheckCBlock ); + + pPrev = _pPrev; + pNext = _pNext; + nSize = nInitSize; + nCount = 0; + + // Datenpuffer anlegen + pNodes = (void**)new PVOID[nSize]; +} + +/************************************************************************* +|* +|* CBlock::CBlock() +|* +|* Beschreibung Construktor des Verwaltungsblocks +|* Ersterstellung TH 17.09.91 +|* Letzte Aenderung TH 17.09.91 +|* +*************************************************************************/ + +CBlock::CBlock( USHORT _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 = (void**)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 = (void**)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, USHORT nIndex, USHORT nReSize ) +{ + DBG_CHKTHIS( CBlock, DbgCheckCBlock ); + DBG_ASSERT( nIndex <= nCount, "CBlock::Insert(): Index > nCount" ); + + // Muss Block realokiert werden + if ( nCount == nSize ) + { + // Neue Daten anlegen + nSize += nReSize; + void** pNewNodes = (void**)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, USHORT nIndex, USHORT nReSize ) +{ + DBG_CHKTHIS( CBlock, DbgCheckCBlock ); + + USHORT nNewSize; + USHORT 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 += nReSize; + } + } + + // 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 -= nMiddle; + // 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 = (void**)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 -= nMiddle; + + // Die zweite Haelfte in einen neuen Block kopieren + if ( nSize != nNewSize ) + { + void** pNewNodes = (void**)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( USHORT nIndex, USHORT 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 -= nReSize; + void** pNewNodes = (void**)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, USHORT 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( USHORT 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( USHORT 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* 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 +|* +*************************************************************************/ + +static void ImpCopyContainer( Container* pCont1, const Container* pCont2 ) +{ + // Werte vom uebergebenen Container uebernehmen + pCont1->nCount = pCont2->nCount; + pCont1->nCurIndex = pCont2->nCurIndex; + pCont1->nInitSize = pCont2->nInitSize; + pCont1->nReSize = pCont2->nReSize; + pCont1->nBlockSize = pCont2->nBlockSize; + + // Alle Bloecke kopieren + if ( pCont2->nCount ) + { + CBlock* pBlock1; + CBlock* pBlock2; + CBlock* pTempBlock; + + // Erstmal ersten Block kopieren + pBlock2 = pCont2->pFirstBlock; + pCont1->pFirstBlock = new CBlock( *pBlock2, NULL ); + // Ist erster Block der Current-Block, dann Current-Block setzen + if ( pBlock2 == pCont2->pCurBlock ) + pCont1->pCurBlock = pCont1->pFirstBlock; + pBlock1 = pCont1->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 ) + pCont1->pCurBlock = pBlock1; + + // Auf naechsten Block weitersetzen + pBlock2 = pBlock2->GetNextBlock(); + } + + // Letzten Block setzen + pCont1->pLastBlock = pBlock1; + } + else + { + pCont1->pFirstBlock = NULL; + pCont1->pLastBlock = NULL; + pCont1->pCurBlock = NULL; + } +} + +/************************************************************************* +|* +|* Container::Container() +|* +|* Beschreibung CONTNR.SDW +|* Ersterstellung TH 17.09.91 +|* Letzte Aenderung TH 17.09.91 +|* +*************************************************************************/ + +Container::Container( USHORT _nBlockSize, USHORT _nInitSize, USHORT _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( ULONG 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( (USHORT)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( (USHORT)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( this, &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, USHORT 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 -= pBlock->nCount; + } + } + } + else + { + // Gegebenenfalls FirstBlock anpassen + if ( pBlock == pFirstBlock ) + pFirstBlock = pNewBlock; + + // Current-Position nachfuehren + if ( pBlock == pCurBlock ) + { + if ( nIndex <= nCurIndex ) + nCurIndex++; + if ( pNewBlock->nCount <= nCurIndex ) + nCurIndex -= pNewBlock->nCount; + 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, ULONG 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, (USHORT)nIndex ); + } +} + +/************************************************************************* +|* +|* Container::Insert() +|* +|* Beschreibung CONTNR.SDW +|* Ersterstellung TH 17.09.91 +|* Letzte Aenderung TH 17.09.91 +|* +*************************************************************************/ + +void Container::Insert( void* pNew, void* pOld ) +{ + ULONG 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, USHORT 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( ULONG 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, (USHORT)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, ULONG 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, (USHORT)nIndex ); + } +} + +/************************************************************************* +|* +|* Container::SetSize() +|* +|* Beschreibung CONTNR.SDW +|* Ersterstellung TH 17.09.91 +|* Letzte Aenderung TH 17.09.91 +|* +*************************************************************************/ + +void Container::SetSize( ULONG nNewSize ) +{ + DBG_CHKTHIS( Container, DbgCheckContainer ); + + if ( nNewSize ) + { + // Unterscheiden sich die Groessen + if ( nNewSize != nCount ) + { + CBlock* pTemp; + ULONG 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 + BOOL bLast = FALSE; + CBlock* pDelNext; + CBlock* pDelBlock = pTemp->GetNextBlock(); + while ( pDelBlock ) + { + // Muss CurrentBlock umgesetzt werden + if ( pDelBlock == pCurBlock ) + bLast = 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( (USHORT)(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( (USHORT)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( (USHORT)nNewSize, pBlock1 ); + pBlock1->SetNextBlock( pLastBlock ); + } + + pCurBlock = pFirstBlock; + } + // Reicht es, den letzen Puffer in der Groesse anzupassen + else if ( (nTemp+pTemp->Count()) <= nBlockSize ) + pTemp->SetSize( (USHORT)(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( (USHORT)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 +|* +*************************************************************************/ + +ULONG 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; + ULONG 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( ULONG 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( (USHORT)nIndex ); + } +} + +/************************************************************************* +|* +|* Container::GetObject() +|* +|* Beschreibung CONTNR.SDW +|* Ersterstellung TH 17.09.91 +|* Letzte Aenderung TH 17.09.91 +|* +*************************************************************************/ + +void* Container::GetObject( ULONG 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( (USHORT)nIndex ); + } +} + +/************************************************************************* +|* +|* Container::GetPos() +|* +|* Beschreibung CONTNR.SDW +|* Ersterstellung TH 17.09.91 +|* Letzte Aenderung TH 17.09.91 +|* +*************************************************************************/ + +ULONG Container::GetPos( const void* p ) const +{ + DBG_CHKTHIS( Container, DbgCheckContainer ); + + void** pNodes; + CBlock* pTemp; + ULONG nTemp; + USHORT nBlockCount; + USHORT 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 +|* +*************************************************************************/ + +ULONG Container::GetPos( const void* p, ULONG nStartIndex, + 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; + USHORT nBlockCount; + USHORT i; + + // Block suchen + CBlock* pTemp = pFirstBlock; + ULONG nTemp = 0; + while ( nTemp+pTemp->Count() <= nStartIndex ) + { + nTemp += pTemp->Count(); + pTemp = pTemp->GetNextBlock(); + } + + // Jetzt den Pointer suchen + if ( bForward ) + { + // Alle Bloecke durchrsuchen + i = (USHORT)(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 ( TRUE ); + } + else + { + // Alle Bloecke durchrsuchen + i = (USHORT)(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 ( TRUE ); + } + } + + return CONTAINER_ENTRY_NOTFOUND; +} + +/************************************************************************* +|* +|* Container::Seek() +|* +|* Beschreibung CONTNR.SDW +|* Ersterstellung TH 17.09.91 +|* Letzte Aenderung TH 17.09.91 +|* +*************************************************************************/ + +void* Container::Seek( ULONG 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 = (USHORT)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( this, &r ); + return *this; +} + +/************************************************************************* +|* +|* Container::operator ==() +|* +|* Beschreibung CONTNR.SDW +|* Ersterstellung TH 17.09.91 +|* Letzte Aenderung TH 17.09.91 +|* +*************************************************************************/ + +BOOL Container::operator ==( const Container& r ) const +{ + DBG_CHKTHIS( Container, DbgCheckContainer ); + + if ( nCount != r.nCount ) + return FALSE; + + ULONG i = 0; + while ( i < nCount ) + { + if ( GetObject( i ) != r.GetObject( i ) ) + return FALSE; + i++; + } + + return TRUE; +} diff --git a/tools/source/memtools/makefile.mk b/tools/source/memtools/makefile.mk new file mode 100644 index 000000000000..bc8e84bf15b1 --- /dev/null +++ b/tools/source/memtools/makefile.mk @@ -0,0 +1,92 @@ +#************************************************************************* +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.1.1.1 $ +# +# last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $ +# +# The Contents of this file are made available subject to the terms of +# either of the following licenses +# +# - GNU Lesser General Public License Version 2.1 +# - Sun Industry Standards Source License Version 1.1 +# +# Sun Microsystems Inc., October, 2000 +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2000 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +# +# Sun Industry Standards Source License Version 1.1 +# ================================================= +# The contents of this file are subject to the Sun Industry Standards +# Source License Version 1.1 (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.openoffice.org/license.html. +# +# Software provided under this License is provided on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, +# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. +# See the License for the specific provisions governing your rights and +# obligations concerning the Software. +# +# The Initial Developer of the Original Code is: Sun Microsystems, Inc. +# +# Copyright: 2000 by Sun Microsystems, Inc. +# +# All Rights Reserved. +# +# Contributor(s): _______________________________________ +# +# +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=tools +TARGET=mtools + +# --- Settings ----------------------------------------------------- + +.INCLUDE : svpre.mk +.INCLUDE : settings.mk +.INCLUDE : sv.mk + +# --- Files -------------------------------------------------------- + +SLOFILES= $(SLO)$/contnr.obj \ + $(SLO)$/table.obj \ + $(SLO)$/unqidx.obj \ + $(SLO)$/mempool.obj \ + $(SLO)$/multisel.obj + +.IF "$(UPDATER)"!="" +OBJFILES= $(OBJ)$/contnr.obj \ + $(OBJ)$/table.obj \ + $(OBJ)$/unqidx.obj \ + $(OBJ)$/mempool.obj \ + $(OBJ)$/multisel.obj +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/tools/source/memtools/mempool.cxx b/tools/source/memtools/mempool.cxx new file mode 100644 index 000000000000..25d4149bcdb4 --- /dev/null +++ b/tools/source/memtools/mempool.cxx @@ -0,0 +1,323 @@ +/************************************************************************* + * + * $RCSfile: mempool.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#define private public + +#include <limits.h> + +#include <debug.hxx> +#include <mempool.hxx> + +// ----------------------------------------------------------------------- + +#if ( __ALIGNMENT8 > 4 ) +#define MEMPOOL_ALIGNMENT __ALIGNMENT8 +#else +#define MEMPOOL_ALIGNMENT 4 +#endif + +// ----------------- +// - FixedMemBlock - +// ----------------- + +struct FixedMemBlock +{ + USHORT nSize; + USHORT nFree; + USHORT nFirst; + USHORT nDummyAlign1; + FixedMemBlock* pNext; +#if (__SIZEOFPOINTER == 4) && (__ALIGNMENT8 == 8) + void* pDummyAlign2; +#endif + char aData[1]; +}; + +/************************************************************************* +|* +|* ImpDbgPoolTest() +|* +|* Beschreibung MEMPOOL.SDW +|* Ersterstellung TH 30.11.94 +|* Letzte Aenderung TH 30.11.94 +|* +*************************************************************************/ + +#ifdef DBG_UTIL + +static void ImpDbgPoolTest( FixedMemPool* pMemPool ) +{ + DbgData* pData = DbgGetData(); + + if ( !pData ) + return; + + if ( !(pData->nTestFlags & (DBG_TEST_MEM_OVERWRITE | DBG_TEST_MEM_OVERWRITEFREE)) ) + return; + + FixedMemBlock* pFirst = pMemPool->pFirst; + FixedMemBlock* pBlock = pFirst; + while ( pBlock ) + { + if ( pBlock->nFree ) + { + USHORT i = pBlock->nFree; + USHORT n = pBlock->nFirst; + char* pData = pBlock->aData; + while ( i ) + { + if ( !(n < (pBlock->nSize/pMemPool->nTypeSize)) ) + DbgError( "MemPool: Memory Overwrite" ); + + char* pNext = pData+(n*pMemPool->nTypeSize); + n = *((USHORT*)pNext); + i--; + } + } + + pBlock = pBlock->pNext; + } +} + +#endif + +/************************************************************************* +|* +|* FixedMemPool::FixedMemPool() +|* +|* Beschreibung MEMPOOL.SDW +|* Ersterstellung TH 02.09.94 +|* Letzte Aenderung TH 02.09.94 +|* +*************************************************************************/ + +FixedMemPool::FixedMemPool( USHORT _nTypeSize, + USHORT _nInitSize, USHORT _nGrowSize ) +{ + pFirst = NULL; + nInitSize = _nInitSize; + nGrowSize = _nGrowSize; + + if ( _nTypeSize > 4 ) + nTypeSize = (_nTypeSize + (MEMPOOL_ALIGNMENT-1)) & ~(MEMPOOL_ALIGNMENT-1); + else if ( _nTypeSize <= 2 ) + nTypeSize = 2; + else + nTypeSize = 4; + + DBG_ASSERT( (ULONG)nTypeSize*nInitSize <= USHRT_MAX, + "FixedMemPool: TypeSize*nInitSize > USHRT_MAX" ); + DBG_ASSERT( (ULONG)nTypeSize*nGrowSize <= USHRT_MAX, + "FixedMemPool: TypeSize*GrowSize > USHRT_MAX" ); +} + +/************************************************************************* +|* +|* FixedMemPool::~FixedMemPool() +|* +|* Beschreibung MEMPOOL.SDW +|* Ersterstellung TH 02.09.94 +|* Letzte Aenderung TH 02.09.94 +|* +*************************************************************************/ + +FixedMemPool::~FixedMemPool() +{ + FixedMemBlock* pBlock = pFirst; + while ( pBlock ) + { + FixedMemBlock* pTemp = pBlock; + pBlock = pBlock->pNext; + delete pTemp; + } +} + +/************************************************************************* +|* +|* FixedMemPool::Alloc() +|* +|* Beschreibung MEMPOOL.SDW +|* Ersterstellung TH 02.09.94 +|* Letzte Aenderung TH 02.09.94 +|* +*************************************************************************/ + +void* FixedMemPool::Alloc() +{ +#ifdef DBG_UTIL + ImpDbgPoolTest( this ); +#endif + + USHORT i; + char* pData; + + if ( !pFirst ) + { + pFirst = (FixedMemBlock*)new char[sizeof(FixedMemBlock)-1+(nInitSize*nTypeSize)]; + + if ( !pFirst ) + return NULL; + + pFirst->pNext = NULL; + pFirst->nSize = nInitSize*nTypeSize;; + pFirst->nFree = nInitSize-1; + pFirst->nFirst = 1; + + pData = pFirst->aData; + for ( i = 1; i < nInitSize; i++ ) + { + *((USHORT*)pData) = i; + pData += nTypeSize; + } + + return (void*)(pFirst->aData); + } + + FixedMemBlock* pBlock = pFirst; + while ( pBlock && !pBlock->nFree ) + pBlock = pBlock->pNext; + + if ( pBlock ) + { + pData = pBlock->aData; + char* pFree = pData+(pBlock->nFirst*nTypeSize); + pBlock->nFirst = *((USHORT*)pFree); // UMR, wenn letzter freier Block, ist OK + pBlock->nFree--; + return (void*)pFree; + } + else + { + if ( !nGrowSize ) + return NULL; + + pBlock = (FixedMemBlock*)new char[sizeof(FixedMemBlock)-1+(nGrowSize*nTypeSize)]; + + if ( !pBlock ) + return NULL; + + pData = pBlock->aData; + for ( i = 1; i < nGrowSize; i++ ) + { + *((USHORT*)pData) = i; + pData += nTypeSize; + } + + pBlock->pNext = pFirst->pNext; + pBlock->nSize = nGrowSize*nTypeSize; + pBlock->nFree = nGrowSize-1; + pBlock->nFirst = 1; + pFirst->pNext = pBlock; + + return (void*)(pBlock->aData); + } +} + +/************************************************************************* +|* +|* FixedMemPool::Free() +|* +|* Beschreibung MEMPOOL.SDW +|* Ersterstellung TH 02.09.94 +|* Letzte Aenderung TH 02.09.94 +|* +*************************************************************************/ + +void FixedMemPool::Free( void* pFree ) +{ + if ( !pFree ) + return; + +#ifdef DBG_UTIL + ImpDbgPoolTest( this ); +#endif + + FixedMemBlock* pBlock = pFirst; + FixedMemBlock* pPrev = NULL; + while ( ((ULONG)pBlock->aData > (ULONG)pFree) || + ((ULONG)pFree >= ((ULONG)pBlock->aData+pBlock->nSize)) ) + { + pPrev = pBlock; + pBlock = pBlock->pNext; + +#ifdef DBG_UTIL + DBG_ASSERT( pBlock, "FixedMemPool - Delete: Wrong Pointer" ); +#endif + } + + pBlock->nFree++; + *((USHORT*)pFree) = pBlock->nFirst; + pBlock->nFirst = (USHORT)(((ULONG)pFree-(ULONG)(pBlock->aData)) / nTypeSize); + + if ( pPrev && (pBlock->nFree*nTypeSize == pBlock->nSize) ) + { + pPrev->pNext = pBlock->pNext; + delete pBlock; + } + else + { + if ( pPrev ) + { + pPrev->pNext = pBlock->pNext; + pBlock->pNext = pFirst->pNext; + pFirst->pNext = pBlock; + } + } +} diff --git a/tools/source/memtools/multisel.cxx b/tools/source/memtools/multisel.cxx new file mode 100644 index 000000000000..8bd47a028019 --- /dev/null +++ b/tools/source/memtools/multisel.cxx @@ -0,0 +1,897 @@ +/************************************************************************* + * + * $RCSfile: multisel.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#define _SV_MULTISEL_CXX + +#ifdef MI_DEBUG +#define private public +#include <stdio.h> +#endif + +#include <debug.hxx> +#include <multisel.hxx> + +#pragma hdrstop + +#ifdef MI_DEBUG +#define DBG(x) x +#else +#define DBG(x) +#endif + +//================================================================== + +#ifdef MI_DEBUG + +static void Print( const MultiSelection* pSel ) +{ + DbgOutf( "TotRange: %4ld-%4ld\n", + pSel->aTotRange.Min(), pSel->aTotRange.Max() ); + if ( pSel->bCurValid ) + { + DbgOutf( "CurSubSel: %4ld\n", pSel->nCurSubSel ); + DbgOutf( "CurIndex: %4ld\n", pSel->nCurIndex ); + } + DbgOutf( "SelCount: %4ld\n", pSel->nSelCount ); + DbgOutf( "SubCount: %4ld\n", pSel->aSels.Count() ); + for ( ULONG nPos = 0; nPos < pSel->aSels.Count(); ++nPos ) + { + DbgOutf( "SubSel #%2ld: %4ld-%4ld\n", nPos, + pSel->aSels.GetObject(nPos)->Min(), + pSel->aSels.GetObject(nPos)->Max() ); + } + DbgOutf( "\n" ); + fclose( pFile ); +} + +#endif + +// ----------------------------------------------------------------------- + +void MultiSelection::ImplClear() +{ + // no selected indexes + nSelCount = 0; + + Range* pRange = aSels.First(); + while ( pRange ) + { + delete pRange; + pRange = aSels.Next(); + } + aSels.Clear(); +} + +// ----------------------------------------------------------------------- + +ULONG MultiSelection::ImplFindSubSelection( long nIndex ) const +{ + // iterate through the sub selections + ULONG n = 0; + for ( ; + n < aSels.Count() && nIndex > aSels.GetObject(n)->Max(); + ++n ) {} /* empty loop */ + return n; +} + +// ----------------------------------------------------------------------- + +BOOL MultiSelection::ImplMergeSubSelections( ULONG nPos1, ULONG nPos2 ) +{ + // didn't a sub selection at nPos2 exist? + if ( nPos2 >= aSels.Count() ) + return FALSE; + + // did the sub selections touch each other? + if ( (aSels.GetObject(nPos1)->Max() + 1) == aSels.GetObject(nPos2)->Min() ) + { + // merge them + aSels.GetObject(nPos1)->Max() = aSels.GetObject(nPos2)->Max(); + delete aSels.Remove(nPos2); + return TRUE; + } + + return FALSE; +} + +// ----------------------------------------------------------------------- + +MultiSelection::MultiSelection(): + aTotRange( 0, -1 ), + nSelCount(0), + nCurSubSel(0), + bCurValid(FALSE), + bSelectNew(FALSE) +{ +} + +// ----------------------------------------------------------------------- + +MultiSelection::MultiSelection( const UniString& rString, sal_Unicode cRange, sal_Unicode cSep ): + aTotRange(0,RANGE_MAX), + nSelCount(0), + nCurSubSel(0), + bCurValid(FALSE), + bSelectNew(FALSE) +{ + // Dies ist nur ein Schnellschuss und sollte bald optimiert, + // an die verschiedenen Systeme (MAC, UNIX etc.) + // und die gewuenschte Eingabe-Syntax angepasst werden. + + UniString aStr( rString ); + sal_Unicode* pStr = aStr.GetBufferAccess(); + sal_Unicode* pOld = pStr; + BOOL bReady = FALSE; + BOOL bUntil = FALSE; + xub_StrLen nCut = 0; + + // Hier normieren wir den String, sodass nur Ziffern, + // Semikola als Trenn- und Minus als VonBis-Zeichen + // uebrigbleiben, z.B. "99-117;55;34;-17;37-43" + while ( *pOld ) + { + switch( *pOld ) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + DBG_ASSERT( *pOld != cRange, "digit for range char not allowed" ); + DBG_ASSERT( *pOld != cSep, "digit for separator not allowed" ); + if( bReady ) + { + *pStr++ = ';'; + nCut++; + bReady = FALSE; + } + *pStr++ = *pOld; + nCut++; + bUntil = FALSE; + break; + + case '-': + case ':': + case '/': + if ( *pOld != cSep ) + { + if ( !bUntil ) + { + *pStr++ = '-'; + nCut++; + bUntil = TRUE; + } + bReady = FALSE; + } + else + bReady = TRUE; + break; + + case ' ': + DBG_ASSERT( *pOld != cRange, "SPACE for range char not allowed" ); + DBG_ASSERT( *pOld != cSep, "SPACE for separator not allowed" ); + bReady = !bUntil; + break; + + default: + if ( *pOld == cRange ) + { + if ( !bUntil ) + { + *pStr++ = '-'; + nCut++; + bUntil = TRUE; + } + bReady = FALSE; + } + else + bReady = TRUE; + break; + } + + pOld++; + } + aStr.ReleaseBufferAccess( nCut ); + + // Jetzt wird der normierte String ausgewertet .. + UniString aNumStr; + Range aRg( 1, RANGE_MAX ); + const sal_Unicode* pCStr = aStr.GetBuffer(); + long nPage = 1; + long nNum = 1; + bUntil = FALSE; + while ( *pCStr ) + { + switch ( *pCStr ) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + aNumStr += *pCStr; + break; + case ';': + nNum = aNumStr.ToInt32(); + if ( bUntil ) + { + if ( !aNumStr.Len() ) + nNum = RANGE_MAX; + aRg.Min() = nPage; + aRg.Max() = nNum; + aRg.Justify(); + Select( aRg ); + } + else + Select( nNum ); + nPage = 0; + aNumStr.Erase(); + bUntil = FALSE; + break; + + case '-': + nPage = aNumStr.ToInt32(); + aNumStr.Erase(); + bUntil = TRUE; + break; + } + + pCStr++; + } + + nNum = aNumStr.ToInt32(); + if ( bUntil ) + { + if ( !aNumStr.Len() ) + nNum = RANGE_MAX; + aRg.Min() = nPage; + aRg.Max() = nNum; + aRg.Justify(); + Select( aRg ); + } + else + Select( nNum ); +} + +// ----------------------------------------------------------------------- + +MultiSelection::MultiSelection( const MultiSelection& rOrig ) : + aTotRange(rOrig.aTotRange), + bCurValid(rOrig.bCurValid), + nSelCount(rOrig.nSelCount), + bSelectNew(FALSE) +{ + if ( bCurValid ) + { + nCurSubSel = rOrig.nCurSubSel; + nCurIndex = rOrig.nCurIndex; + } + + // copy the sub selections + for ( ULONG n = 0; n < rOrig.aSels.Count(); ++n ) + aSels.Insert( new Range( *rOrig.aSels.GetObject(n) ), LIST_APPEND ); +} + +// ----------------------------------------------------------------------- + +MultiSelection::MultiSelection( const Range& rRange ): + aTotRange(rRange), + nSelCount(0), + nCurSubSel(0), + bCurValid(FALSE), + bSelectNew(FALSE) +{ +} + +// ----------------------------------------------------------------------- + +MultiSelection::~MultiSelection() +{ + Range* pRange = aSels.First(); + while ( pRange ) + { + delete pRange; + pRange = aSels.Next(); + } +} + +// ----------------------------------------------------------------------- + +MultiSelection& MultiSelection::operator= ( const MultiSelection& rOrig ) +{ + aTotRange = rOrig.aTotRange; + bCurValid = rOrig.bCurValid; + if ( bCurValid ) + { + nCurSubSel = rOrig.nCurSubSel; + nCurIndex = rOrig.nCurIndex; + } + + // clear the old and copy the sub selections + ImplClear(); + for ( ULONG n = 0; n < rOrig.aSels.Count(); ++n ) + aSels.Insert( new Range( *rOrig.aSels.GetObject(n) ), LIST_APPEND ); + nSelCount = rOrig.nSelCount; + + return *this; +} + +// ----------------------------------------------------------------------- + +BOOL MultiSelection::operator== ( MultiSelection& rWith ) +{ + if ( aTotRange != rWith.aTotRange || nSelCount != rWith.nSelCount || + aSels.Count() != rWith.aSels.Count() ) + return FALSE; + + // compare the sub seletions + for ( ULONG n = 0; n < aSels.Count(); ++n ) + if ( *aSels.GetObject(n) != *rWith.aSels.GetObject(n) ) + return FALSE; + return TRUE; +} + +// ----------------------------------------------------------------------- + +void MultiSelection::SelectAll( BOOL bSelect ) +{ + DBG(DbgOutf( "::SelectAll(%s)\n", bSelect ? "TRUE" : "FALSE" )); + + ImplClear(); + if ( bSelect ) + { + aSels.Insert( new Range(aTotRange), LIST_APPEND ); + nSelCount = aTotRange.Len(); + } + + DBG(Print( this )); +} + +// ----------------------------------------------------------------------- + +BOOL MultiSelection::Select( long nIndex, BOOL bSelect ) +{ + DBG_ASSERT( aTotRange.IsInside(nIndex), "selected index out of range" ); + + // out of range? + if ( !aTotRange.IsInside(nIndex) ) + return FALSE; + + // find the virtual target position + ULONG nSubSelPos = ImplFindSubSelection( nIndex ); + + if ( bSelect ) + { + // is it included in the found sub selection? + if ( nSubSelPos < aSels.Count() && + aSels.GetObject(nSubSelPos)->IsInside( nIndex ) ) + // already selected, nothing to do + return FALSE; + + // it will become selected + ++nSelCount; + + // is it at the end of the previous sub selection + if ( nSubSelPos > 0 && + aSels.GetObject(nSubSelPos-1)->Max() == (nIndex-1) ) + { + // expand the previous sub selection + aSels.GetObject(nSubSelPos-1)->Max() = nIndex; + + // try to merge the previous sub selection + ImplMergeSubSelections( nSubSelPos-1, nSubSelPos ); + } + // is is at the beginning of the found sub selection + else if ( nSubSelPos < aSels.Count() && + aSels.GetObject(nSubSelPos)->Min() == (nIndex+1) ) + // expand the found sub selection + aSels.GetObject(nSubSelPos)->Min() = nIndex; + else + { + // create a new sub selection + aSels.Insert( new Range( nIndex, nIndex ), nSubSelPos ); + if ( bCurValid && nCurSubSel >= nSubSelPos ) + ++nCurSubSel; + } + } + else + { + // is it excluded from the found sub selection? + if ( nSubSelPos >= aSels.Count() || + !aSels.GetObject(nSubSelPos)->IsInside( nIndex ) ) + { + // not selected, nothing to do + DBG(Print( this )); + return FALSE; + } + + // it will become deselected + --nSelCount; + + // is it the only index in the found sub selection? + if ( aSels.GetObject(nSubSelPos)->Len() == 1 ) + { + // remove the complete sub selection + delete aSels.Remove( nSubSelPos ); + DBG(Print( this )); + return TRUE; + } + + // is it at the beginning of the found sub selection? + if ( aSels.GetObject(nSubSelPos)->Min() == nIndex ) + ++aSels.GetObject(nSubSelPos)->Min(); + // is it at the end of the found sub selection? + else if ( aSels.GetObject(nSubSelPos)->Max() == nIndex ) + --aSels.GetObject(nSubSelPos)->Max(); + // it is in the middle of the found sub selection? + else + { + // split the sub selection + aSels.Insert( + new Range( aSels.GetObject(nSubSelPos)->Min(), nIndex-1 ), + nSubSelPos ); + aSels.GetObject(nSubSelPos+1)->Min() = nIndex + 1; + } + } + + DBG(Print( this )); + + return TRUE; +} + +// ----------------------------------------------------------------------- + +void MultiSelection::Select( const Range& rIndexRange, BOOL bSelect ) +{ + Range* pRange; + long nOld; + + ULONG nTmpMin = rIndexRange.Min(); + ULONG nTmpMax = rIndexRange.Max(); + ULONG nCurMin = FirstSelected(); + ULONG nCurMax = LastSelected(); + DBG_ASSERT(aTotRange.IsInside(nTmpMax), "selected index out of range" ); + DBG_ASSERT(aTotRange.IsInside(nTmpMin), "selected index out of range" ); + + // gesamte Selektion ersetzen ? + if( nTmpMin <= nCurMin && nTmpMax >= nCurMax ) + { + ImplClear(); + if ( bSelect ) + { + aSels.Insert( new Range(rIndexRange), LIST_APPEND ); + nSelCount = rIndexRange.Len(); + } + return; + } + // links erweitern ? + if( nTmpMax < nCurMin ) + { + if( bSelect ) + { + // ersten Range erweitern ? + if( nCurMin > (nTmpMax+1) ) + { + pRange = new Range( rIndexRange ); + aSels.Insert( pRange, (ULONG)0 ); + nSelCount += pRange->Len(); + } + else + { + pRange = aSels.First(); + nOld = pRange->Min(); + pRange->Min() = (long)nTmpMin; + nSelCount += ( nOld - nTmpMin ); + } + bCurValid = FALSE; + } + return; + } + // rechts erweitern ? + else if( nTmpMin > nCurMax ) + { + if( bSelect ) + { + // letzten Range erweitern ? + if( nTmpMin > (nCurMax+1) ) + { + pRange = new Range( rIndexRange ); + aSels.Insert( pRange, LIST_APPEND ); + nSelCount += pRange->Len(); + } + else + { + pRange = aSels.Last(); + nOld = pRange->Max(); + pRange->Max() = (long)nTmpMax; + nSelCount += ( nTmpMax - nOld ); + } + bCurValid = FALSE; + } + return; + } + + //HACK(Hier muss noch optimiert werden) + while( nTmpMin <= nTmpMax ) + { + Select( nTmpMin, bSelect ); + nTmpMin++; + } +} + +// ----------------------------------------------------------------------- + +BOOL MultiSelection::IsSelected( long nIndex ) const +{ + // find the virtual target position + ULONG nSubSelPos = ImplFindSubSelection( nIndex ); + + return nSubSelPos < aSels.Count() && + aSels.GetObject(nSubSelPos)->IsInside(nIndex); +} + +// ----------------------------------------------------------------------- + +void MultiSelection::Insert( long nIndex, long nCount ) +{ + DBG(DbgOutf( "::Insert(%ld, %ld)\n", nIndex, nCount )); + + // find the virtual target position + ULONG nSubSelPos = ImplFindSubSelection( nIndex ); + + // did we need to shift the sub selections? + if ( nSubSelPos < aSels.Count() ) + { + // did we insert an unselected into an existing sub selection? + if ( !bSelectNew && aSels.GetObject(nSubSelPos)->Min() != nIndex && + aSels.GetObject(nSubSelPos)->IsInside(nIndex) ) + { + // split the sub selection + aSels.Insert( + new Range( aSels.GetObject(nSubSelPos)->Min(), nIndex-1 ), + nSubSelPos ); + ++nSubSelPos; + aSels.GetObject(nSubSelPos)->Min() = nIndex; + } + + // did we append an selected to an existing sub selection? + else if ( bSelectNew && nSubSelPos > 0 && + aSels.GetObject(nSubSelPos)->Max() == nIndex-1 ) + // expand the previous sub selection + aSels.GetObject(nSubSelPos-1)->Max() += nCount; + + // did we insert an selected into an existing sub selection? + else if ( bSelectNew && aSels.GetObject(nSubSelPos)->Min() == nIndex ) + { + // expand the sub selection + aSels.GetObject(nSubSelPos)->Max() += nCount; + ++nSubSelPos; + } + + // shift the sub selections behind the inserting position + for ( ULONG nPos = nSubSelPos; nPos < aSels.Count(); ++nPos ) + { + aSels.GetObject(nPos)->Min() += nCount; + aSels.GetObject(nPos)->Max() += nCount; + } + } + + bCurValid = FALSE; + aTotRange.Max() += nCount; + if ( bSelectNew ) + nSelCount += nCount; + + DBG(Print( this )); +} + +// ----------------------------------------------------------------------- + +void MultiSelection::Remove( long nIndex ) +{ + DBG(DbgOutf( "::Remove(%ld)\n", nIndex )); + + // find the virtual target position + ULONG nSubSelPos = ImplFindSubSelection( nIndex ); + + // did we remove from an existing sub selection? + if ( nSubSelPos < aSels.Count() && + aSels.GetObject(nSubSelPos)->IsInside(nIndex) ) + { + // does this sub selection only contain the index to be deleted + if ( aSels.GetObject(nSubSelPos)->Len() == 1 ) + // completely remove the sub selection + aSels.Remove(nSubSelPos); + else + // shorten this sub selection + --( aSels.GetObject(nSubSelPos++)->Max() ); + + // adjust the selected counter + --nSelCount; + } + + // shift the sub selections behind the removed index + for ( ULONG nPos = nSubSelPos; nPos < aSels.Count(); ++nPos ) + { + --( aSels.GetObject(nPos)->Min() ); + --( aSels.GetObject(nPos)->Max() ); + } + + bCurValid = FALSE; + aTotRange.Max() -= 1; + + DBG(Print( this )); +} + +// ----------------------------------------------------------------------- + +void MultiSelection::Append( long nCount ) +{ + long nPrevLast = aTotRange.Max(); + aTotRange.Max() += nCount; + if ( bSelectNew ) + { + nSelCount += nCount; + aSels.Insert( new Range( nPrevLast+1, nPrevLast + nCount ), + LIST_APPEND ); + if ( aSels.Count() > 1 ) + ImplMergeSubSelections( aSels.Count() - 2, aSels.Count() ); + } +} + +// ----------------------------------------------------------------------- + +long MultiSelection::ImplFwdUnselected() +{ + if ( !bCurValid ) + return SFX_ENDOFSELECTION; + + if ( ( nCurSubSel < aSels.Count() ) && + ( aSels.GetObject(nCurSubSel)->Min() <= nCurIndex ) ) + nCurIndex = aSels.GetObject(nCurSubSel++)->Max() + 1; + + if ( nCurIndex <= aTotRange.Max() ) + return nCurIndex; + else + return SFX_ENDOFSELECTION; +} + +// ----------------------------------------------------------------------- + +long MultiSelection::ImplBwdUnselected() +{ + if ( !bCurValid ) + return SFX_ENDOFSELECTION; + + if ( aSels.GetObject(nCurSubSel)->Max() < nCurIndex ) + return nCurIndex; + + nCurIndex = aSels.GetObject(nCurSubSel--)->Min() - 1; + if ( nCurIndex >= 0 ) + return nCurIndex; + else + return SFX_ENDOFSELECTION; +} + +// ----------------------------------------------------------------------- + +long MultiSelection::FirstSelected( BOOL bInverse ) +{ + bInverseCur = bInverse; + nCurSubSel = 0; + + if ( bInverseCur ) + { + bCurValid = nSelCount < ULONG(aTotRange.Len()); + if ( bCurValid ) + { + nCurIndex = 0; + return ImplFwdUnselected(); + } + } + else + { + bCurValid = aSels.Count() > 0; + if ( bCurValid ) + return nCurIndex = aSels.GetObject(0)->Min(); + } + + return SFX_ENDOFSELECTION; +} + +// ----------------------------------------------------------------------- + +long MultiSelection::LastSelected( BOOL bInverse ) +{ + nCurSubSel = aSels.Count() - 1; + bCurValid = aSels.Count() > 0; + + if ( bCurValid ) + return nCurIndex = aSels.GetObject(nCurSubSel)->Max(); + + return SFX_ENDOFSELECTION; +} + +// ----------------------------------------------------------------------- + +long MultiSelection::NextSelected() +{ + if ( !bCurValid ) + return SFX_ENDOFSELECTION; + + if ( bInverseCur ) + { + ++nCurIndex; + return ImplFwdUnselected(); + } + else + { + // is the next index in the current sub selection too? + if ( nCurIndex < aSels.GetObject(nCurSubSel)->Max() ) + return ++nCurIndex; + + // are there further sub selections? + if ( ++nCurSubSel < aSels.Count() ) + return nCurIndex = aSels.GetObject(nCurSubSel)->Min(); + + // we are at the end! + return SFX_ENDOFSELECTION; + } +} + +// ----------------------------------------------------------------------- + +long MultiSelection::PrevSelected() +{ + if ( !bCurValid ) + return SFX_ENDOFSELECTION; + + if ( bInverseCur ) + { + --nCurIndex; + return ImplBwdUnselected(); + } + else + { + // is the previous index in the current sub selection too? + if ( nCurIndex > aSels.GetObject(nCurSubSel)->Min() ) + return --nCurIndex; + + // are there previous sub selections? + if ( nCurSubSel > 0 ) + { + --nCurSubSel; + return nCurIndex = aSels.GetObject(nCurSubSel)->Max(); + } + + // we are at the beginning! + return SFX_ENDOFSELECTION; + } +} + +// ----------------------------------------------------------------------- + +void MultiSelection::SetTotalRange( const Range& rTotRange ) +{ + aTotRange = rTotRange; + + // die untere Bereichsgrenze anpassen + Range* pRange = aSels.GetObject( 0 ); + while( pRange ) + { + if( pRange->Max() < aTotRange.Min() ) + { + delete pRange; + aSels.Remove( (ULONG)0 ); + } + else if( pRange->Min() < aTotRange.Min() ) + { + pRange->Min() = aTotRange.Min(); + break; + } + else + break; + + pRange = aSels.GetObject( 0 ); + } + + // die obere Bereichsgrenze anpassen + ULONG nCount = aSels.Count(); + while( nCount ) + { + pRange = aSels.GetObject( nCount - 1 ); + if( pRange->Min() > aTotRange.Max() ) + { + delete pRange; + aSels.Remove( (ULONG)(nCount - 1) ); + } + else if( pRange->Max() > aTotRange.Max() ) + { + pRange->Max() = aTotRange.Max(); + break; + } + else + break; + + nCount = aSels.Count(); + } + + // Selection-Count neu berechnen + nSelCount = 0; + pRange = aSels.First(); + while( pRange ) + { + nSelCount += pRange->Len(); + pRange = aSels.Next(); + } + + bCurValid = FALSE; + nCurIndex = 0; +} diff --git a/tools/source/memtools/table.cxx b/tools/source/memtools/table.cxx new file mode 100644 index 000000000000..d84676f2c052 --- /dev/null +++ b/tools/source/memtools/table.cxx @@ -0,0 +1,442 @@ +/************************************************************************* + * + * $RCSfile: table.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#define _TOOLS_TABLE_CXX + +// ----------------------------------------------------------------------- + +#define protected public + +#ifndef _DEBUG_HXX +#include <debug.hxx> +#endif +#ifndef _IMPCONT_HXX +#include <impcont.hxx> +#endif +#ifndef _TOOLS_TABLE_HXX +#include <table.hxx> +#endif + +// ======================================================================= + +ULONG Table::ImplGetIndex( ULONG nKey, ULONG* pIndex ) const +{ + // Abpruefen, ob der erste Key groesser als der Vergleichskey ist + if ( !nCount || (nKey < (ULONG)Container::ImpGetObject(0)) ) + return TABLE_ENTRY_NOTFOUND; + + ULONG nLow; + ULONG nHigh; + ULONG nMid; + ULONG nCompareKey; + void** pNodes = Container::ImpGetOnlyNodes(); + + // Binaeres Suchen + nLow = 0; + nHigh = nCount-1; + if ( pNodes ) + { + do + { + nMid = (nLow + nHigh) / 2; + nCompareKey = (ULONG)pNodes[nMid*2]; + if ( nKey < nCompareKey ) + nHigh = nMid-1; + else + { + if ( nKey > nCompareKey ) + nLow = nMid + 1; + else + return nMid*2; + } + } + while ( nLow <= nHigh ); + } + else + { + do + { + nMid = (nLow + nHigh) / 2; + nCompareKey = (ULONG)Container::ImpGetObject( nMid*2 ); + if ( nKey < nCompareKey ) + nHigh = nMid-1; + else + { + if ( nKey > nCompareKey ) + nLow = nMid + 1; + else + return nMid*2; + } + } + while ( nLow <= nHigh ); + } + + if ( pIndex ) + { + if ( nKey > nCompareKey ) + *pIndex = (nMid+1)*2; + else + *pIndex = nMid*2; + } + + return TABLE_ENTRY_NOTFOUND; +} + +// ======================================================================= + +Table::Table( USHORT _nInitSize, USHORT _nReSize ) : + Container( CONTAINER_MAXBLOCKSIZE, _nInitSize*2, _nReSize*2 ) +{ + DBG_ASSERT( _nInitSize <= 32767, "Table::Table(): InitSize > 32767" ); + DBG_ASSERT( _nReSize <= 32767, "Table::Table(): ReSize > 32767" ); + nCount = 0; +} + +// ----------------------------------------------------------------------- + +BOOL Table::Insert( ULONG nKey, void* p ) +{ + // Tabellenelement einsortieren + ULONG i; + if ( nCount ) + { + if ( nCount <= 24 ) + { + USHORT n = 0; + USHORT nTempCount = (USHORT)nCount * 2; + void** pNodes = Container::ImpGetOnlyNodes(); + ULONG nCompareKey = (ULONG)(*pNodes); + while ( nKey > nCompareKey ) + { + n += 2; + pNodes += 2; + if ( n < nTempCount ) + nCompareKey = (ULONG)(*pNodes); + else + { + nCompareKey = 0; + break; + } + } + + // Testen, ob sich der Key schon in der Tabelle befindet + if ( nKey == nCompareKey ) + return FALSE; + + i = n; + } + else + { + i = 0; + if ( ImplGetIndex( nKey, &i ) != TABLE_ENTRY_NOTFOUND ) + return FALSE; + } + } + else + i = 0; + + // Eintrag einfuegen (Key vor Pointer) + Container::Insert( (void*)nKey, i ); + Container::Insert( p, i+1 ); + + // Ein neuer Eintrag + nCount++; + + return TRUE; +} + +// ----------------------------------------------------------------------- + +void* Table::Remove( ULONG nKey ) +{ + // Index besorgen + ULONG nIndex = ImplGetIndex( nKey ); + + // Testen, ob sich der Key in der Tabelle befindet + if ( nIndex == TABLE_ENTRY_NOTFOUND ) + return NULL; + + // Itemanzahl erniedrigen + nCount--; + + // Key entfernen + Container::Remove( nIndex ); + + // Pointer entfernen und zurueckgeben + return Container::Remove( nIndex ); +} + +// ----------------------------------------------------------------------- + +void* Table::Replace( ULONG nKey, void* p ) +{ + // Index abfragen + ULONG nIndex = ImplGetIndex( nKey ); + + // Existiert kein Eintrag mit dem Schluessel + if ( nIndex == TABLE_ENTRY_NOTFOUND ) + return NULL; + else + return Container::Replace( p, nIndex+1 ); +} + +// ----------------------------------------------------------------------- + +void* Table::Get( ULONG nKey ) const +{ + // Index besorgen + ULONG nIndex = ImplGetIndex( nKey ); + + // Testen, ob sich der Key in der Tabelle befindet + if ( nIndex == TABLE_ENTRY_NOTFOUND ) + return NULL; + else + return Container::ImpGetObject( nIndex+1 ); +} + +// ----------------------------------------------------------------------- + +void* Table::GetCurObject() const +{ + return Container::ImpGetObject( Container::GetCurPos()+1 ); +} + +// ----------------------------------------------------------------------- + +ULONG Table::GetKey( const void* p ) const +{ + ULONG nIndex = 0; + + // Solange noch Eintraege Vorhanden sind + while ( nIndex < nCount ) + { + // Stimmt der Pointer ueberein, wird der Key zurueckgegeben + if ( p == Container::ImpGetObject( (nIndex*2)+1 ) ) + return (ULONG)Container::ImpGetObject( nIndex*2 ); + + nIndex++; + } + + return TABLE_ENTRY_NOTFOUND; +} + +// ----------------------------------------------------------------------- + +BOOL Table::IsKeyValid( ULONG nKey ) const +{ + return (ImplGetIndex( nKey ) != TABLE_ENTRY_NOTFOUND) ? TRUE : FALSE; +} + +// ----------------------------------------------------------------------- + +ULONG Table::GetUniqueKey( ULONG nStartKey ) const +{ + DBG_ASSERT( (nStartKey > 1) && (nStartKey < 0xFFFFFFFF), + "Table::GetUniqueKey() - nStartKey == 0 or nStartKey >= 0xFFFFFFFF" ); + + if ( !nCount ) + return nStartKey; + + ULONG nLastKey = (ULONG)Container::GetObject( (nCount*2)-2 ); + if ( nLastKey < nStartKey ) + return nStartKey; + else + { + if ( nLastKey < 0xFFFFFFFE ) + return nLastKey+1; + else + { + ULONG nPos; + ULONG nTempPos = ImplGetIndex( nStartKey, &nPos ); + if ( nTempPos != TABLE_ENTRY_NOTFOUND ) + nPos = nTempPos; + nLastKey = (ULONG)Container::GetObject( nPos ); + if ( nStartKey < nLastKey ) + return nStartKey; + while ( nLastKey < 0xFFFFFFFE ) + { + nPos += 2; + nLastKey++; + if ( nLastKey != (ULONG)Container::GetObject( nPos ) ) + return nLastKey; + } + } + } + + return 0; +} + +// ----------------------------------------------------------------------- + +ULONG Table::SearchKey( ULONG nKey, ULONG* pPos ) const +{ + *pPos = 0; + ULONG nPos = ImplGetIndex( nKey, pPos ); + if ( nPos != TABLE_ENTRY_NOTFOUND ) + { + nPos /= 2; + *pPos = nPos; + } + else + *pPos /= 2; + return nPos; +} + +// ----------------------------------------------------------------------- + +void* Table::Seek( ULONG nKey ) +{ + // Testen, ob ein Eintrag vorhanden ist + if ( nCount ) + { + ULONG nIndex = ImplGetIndex( nKey ); + + // Ist Key nicht enthalten + if ( nIndex == TABLE_ENTRY_NOTFOUND ) + return NULL; + else + { + // Index setzen + Container::Seek( nIndex ); + + // Pointer zurueckgeben + return Container::ImpGetObject( Container::GetCurPos() + 1 ); + } + } + else + return NULL; +} + +// ----------------------------------------------------------------------- + +void* Table::Seek( void* p ) +{ + ULONG nKey = GetKey( p ); + + // Ist Key vorhanden, dann als aktuellen Eintrag setzen + if ( nKey != TABLE_ENTRY_NOTFOUND ) + return Seek( nKey ); + else + return NULL; +} + +// ----------------------------------------------------------------------- + +void* Table::First() +{ + // Testen, ob ein Eintrag vorhanden ist + if ( nCount ) + { + // Auf ersten Eintag setzen + Container::First(); + + // Pointer zurueckgeben + return Container::ImpGetObject( 1 ); + } + else + return NULL; +} + +// ----------------------------------------------------------------------- + +void* Table::Last() +{ + // Testen, ob ein Eintrag vorhanden ist + if ( nCount ) + { + // Last auf letzten Eintrag setzen + void* p = Container::Last(); + Container::Prev(); + + // Pointer zurueckgeben + return p; + } + else + return NULL; +} + +// ----------------------------------------------------------------------- + +void* Table::Next() +{ + // Ueber den Pointer weiterschalten + Container::Next(); + + // Nachsten Eintag + Container::Next(); + + // Pointer vom naechsten Key zurueckgeben + return Container::ImpGetObject( Container::GetCurPos() + 1 ); +} + +// ----------------------------------------------------------------------- + +void* Table::Prev() +{ + // Ueber den Pointer weiterschalten + void* p = Container::Prev(); + + // Nachsten Eintag + Container::Prev(); + + // Pointer vom vorherigen Key zurueckgeben + return p; +} diff --git a/tools/source/memtools/unqidx.cxx b/tools/source/memtools/unqidx.cxx new file mode 100644 index 000000000000..435e5fc117be --- /dev/null +++ b/tools/source/memtools/unqidx.cxx @@ -0,0 +1,643 @@ +/************************************************************************* + * + * $RCSfile: unqidx.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:03:08 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#define protected public + +#ifndef _IMPCONT_HXX +#include <impcont.hxx> +#endif + +#ifndef _UNQIDX_HXX +#include <unqidx.hxx> +#endif + +#ifndef _UNQID_HXX +#include <unqid.hxx> +#endif + +/************************************************************************* +|* +|* UniqueIndex::UniqueIndex() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung TH 24.09.91 +|* Letzte Aenderung TH 24.09.91 +|* +*************************************************************************/ + +UniqueIndex::UniqueIndex( ULONG _nStartIndex, + ULONG _nInitSize, ULONG _nReSize ) : + Container( _nInitSize ) +{ + nReSize = _nReSize; + nStartIndex = _nStartIndex; + nUniqIndex = 0; + nCount = 0; +} + +/************************************************************************* +|* +|* UniqueIndex::UniqueIndex() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung TH 24.09.91 +|* Letzte Aenderung TH 24.09.91 +|* +*************************************************************************/ + +UniqueIndex::UniqueIndex( const UniqueIndex& rIdx ) : + Container( rIdx ) +{ + nReSize = rIdx.nReSize; + nStartIndex = rIdx.nStartIndex; + nUniqIndex = rIdx.nUniqIndex; + nCount = rIdx.nCount; +} + +/************************************************************************* +|* +|* UniqueIndex::Insert() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung TH 24.09.91 +|* Letzte Aenderung TH 24.09.91 +|* +*************************************************************************/ + +ULONG UniqueIndex::Insert( void* p ) +{ + // NULL-Pointer ist nicht erlaubt + if ( !p ) + return UNIQUEINDEX_ENTRY_NOTFOUND; + + // Ist Array voll, dann expandieren + if ( nCount == Container::GetSize() ) + SetSize( nCount + nReSize ); + + // Damit UniqIndex nicht ueberlaeuft, wenn Items geloescht wurden + nUniqIndex = nUniqIndex % Container::GetSize(); + + // Leeren Eintrag suchen + while ( Container::ImpGetObject( nUniqIndex ) != NULL ) + nUniqIndex = (nUniqIndex+1) % Container::GetSize(); + + // Object im Array speichern + Container::Replace( p, nUniqIndex ); + + // Anzahl der Eintraege erhoehen und Index zurueckgeben + nCount++; + nUniqIndex++; + return ( nUniqIndex + nStartIndex - 1 ); +} + +/************************************************************************* +|* +|* UniqueIndex::Insert() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung MM 21.04.96 +|* Letzte Aenderung MM 21.04.96 +|* +*************************************************************************/ + +ULONG UniqueIndex::Insert( ULONG nIndex, void* p ) +{ + // NULL-Pointer ist nicht erlaubt + if ( !p ) + return UNIQUEINDEX_ENTRY_NOTFOUND; + + ULONG nContIndex = nIndex - nStartIndex; + // Ist Array voll, dann expandieren + if ( nContIndex >= Container::GetSize() ) + SetSize( nContIndex + nReSize ); + + // Object im Array speichern + Container::Replace( p, nContIndex ); + + // Anzahl der Eintraege erhoehen und Index zurueckgeben + nCount++; + return nIndex; +} + +/************************************************************************* +|* +|* UniqueIndex::Remove() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung TH 24.09.91 +|* Letzte Aenderung TH 24.09.91 +|* +*************************************************************************/ + +void* UniqueIndex::Remove( ULONG nIndex ) +{ + // Ist Index zulaessig + if ( (nIndex >= nStartIndex) && + (nIndex < (Container::GetSize()+nStartIndex)) ) + { + // Index-Eintrag als leeren Eintrag setzen und Anzahl der + // gespeicherten Indexe erniedriegen, wenn Eintrag belegt war + void* p = Container::Replace( NULL, nIndex-nStartIndex ); + if ( p ) + nCount--; + return p; + } + else + return NULL; +} + +/************************************************************************* +|* +|* UniqueIndex::Replace() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung TH 24.09.91 +|* Letzte Aenderung TH 24.09.91 +|* +*************************************************************************/ + +void* UniqueIndex::Replace( ULONG nIndex, void* p ) +{ + // NULL-Pointer ist nicht erlaubt + if ( !p ) + return NULL; + + // Ist Index zulaessig + if ( IsIndexValid( nIndex ) ) + { + // Index-Eintrag ersetzen und alten zurueckgeben + return Container::Replace( p, nIndex-nStartIndex ); + } + else + return NULL; +} + +/************************************************************************* +|* +|* UniqueIndex::Get() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung TH 24.09.91 +|* Letzte Aenderung TH 24.09.91 +|* +*************************************************************************/ + +void* UniqueIndex::Get( ULONG nIndex ) const +{ + // Ist Index zulaessig + if ( (nIndex >= nStartIndex) && + (nIndex < (Container::GetSize()+nStartIndex)) ) + return Container::ImpGetObject( nIndex-nStartIndex ); + else + return NULL; +} + +/************************************************************************* +|* +|* UniqueIndex::GetCurIndex() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung TH 24.09.91 +|* Letzte Aenderung TH 24.09.91 +|* +*************************************************************************/ + +ULONG UniqueIndex::GetCurIndex() const +{ + ULONG nPos = Container::GetCurPos(); + + // Ist der Current-Index nicht belegt, dann gibt es keinen Current-Index + if ( !Container::ImpGetObject( nPos ) ) + return UNIQUEINDEX_ENTRY_NOTFOUND; + else + return nPos+nStartIndex; +} + +/************************************************************************* +|* +|* UniqueIndex::GetIndex() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung TH 24.09.91 +|* Letzte Aenderung TH 24.09.91 +|* +*************************************************************************/ + +ULONG UniqueIndex::GetIndex( const void* p ) const +{ + // Wird ein NULL-Pointer uebergeben, dann wurde Pointer nicht gefunden + if ( !p ) + return UNIQUEINDEX_ENTRY_NOTFOUND; + + ULONG nIndex = Container::GetPos( p ); + + if ( nIndex != CONTAINER_ENTRY_NOTFOUND ) + return nIndex+nStartIndex; + else + return UNIQUEINDEX_ENTRY_NOTFOUND; +} + +/************************************************************************* +|* +|* UniqueIndex::IsIndexValid() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung TH 24.09.91 +|* Letzte Aenderung TH 24.09.91 +|* +*************************************************************************/ + +BOOL UniqueIndex::IsIndexValid( ULONG nIndex ) const +{ + // Ist Index zulaessig + if ( (nIndex >= nStartIndex) && + (nIndex < (Container::GetSize()+nStartIndex)) ) + { + // Index ist nur zulaessig, wenn Eintrag auch belegt ist + if ( Container::ImpGetObject( nIndex-nStartIndex ) ) + return TRUE; + else + return FALSE; + } + else + return FALSE; +} + +/************************************************************************* +|* +|* UniqueIndex::Seek() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung TH 24.09.91 +|* Letzte Aenderung TH 24.09.91 +|* +*************************************************************************/ + +void* UniqueIndex::Seek( ULONG nIndex ) +{ + // Index-Eintrag als aktuellen setzten, wenn er gueltig ist + if ( IsIndexValid( nIndex ) ) + return Container::Seek( nIndex-nStartIndex ); + else + return NULL; +} + +/************************************************************************* +|* +|* UniqueIndex::Seek() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung TH 24.09.91 +|* Letzte Aenderung TH 24.09.91 +|* +*************************************************************************/ + +void* UniqueIndex::Seek( void* p ) +{ + // Wird ein NULL-Pointer uebergeben, dann wurde Pointer nicht gefunden + if ( !p ) + return NULL; + + ULONG nIndex = GetIndex( p ); + + // Ist Index vorhanden, dann als aktuellen Eintrag setzen + if ( nIndex != UNIQUEINDEX_ENTRY_NOTFOUND ) + return Container::Seek( nIndex-nStartIndex ); + else + return NULL; +} + +/************************************************************************* +|* +|* UniqueIndex::First() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung TH 24.09.91 +|* Letzte Aenderung TH 24.09.91 +|* +*************************************************************************/ + +void* UniqueIndex::First() +{ + void* p = Container::First(); + + while ( !p && (Container::GetCurPos() < (Container::GetSize()-1)) ) + p = Container::Next(); + + return p; +} + +/************************************************************************* +|* +|* UniqueIndex::Last() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung TH 24.09.91 +|* Letzte Aenderung TH 24.09.91 +|* +*************************************************************************/ + +void* UniqueIndex::Last() +{ + void* p = Container::Last(); + + while ( !p && Container::GetCurPos() ) + p = Container::Prev(); + + return p; +} + +/************************************************************************* +|* +|* UniqueIndex::Next() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung TH 24.09.91 +|* Letzte Aenderung TH 24.09.91 +|* +*************************************************************************/ + +void* UniqueIndex::Next() +{ + void* p = NULL; + + while ( !p && (Container::GetCurPos() < (Container::GetSize()-1)) ) + p = Container::Next(); + + return p; +} + +/************************************************************************* +|* +|* UniqueIndex::Prev() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung TH 24.09.91 +|* Letzte Aenderung TH 24.09.91 +|* +*************************************************************************/ + +void* UniqueIndex::Prev() +{ + void* p = NULL; + + while ( !p && Container::GetCurPos() ) + p = Container::Prev(); + + return p; +} + +/************************************************************************* +|* +|* UniqueIndex::operator =() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung TH 24.09.91 +|* Letzte Aenderung TH 24.09.91 +|* +*************************************************************************/ + +UniqueIndex& UniqueIndex::operator =( const UniqueIndex& rIdx ) +{ + // Neue Werte zuweisen + Container::operator =( rIdx ); + nReSize = rIdx.nReSize; + nStartIndex = rIdx.nStartIndex; + nUniqIndex = rIdx.nUniqIndex; + nCount = rIdx.nCount; + return *this; +} + +/************************************************************************* +|* +|* UniqueIndex::operator ==() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung TH 24.09.91 +|* Letzte Aenderung TH 24.09.91 +|* +*************************************************************************/ + +BOOL UniqueIndex::operator ==( const UniqueIndex& rIdx ) const +{ + // Neue Werte zuweisen + if ( (nStartIndex == rIdx.nStartIndex) && + (nCount == rIdx.nCount) && + (Container::operator ==( rIdx )) ) + return TRUE; + else + return FALSE; +} +/************************************************************************* +|* +|* UniqueIdContainer::UniqueIdContainer () +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung MM 29.04.96 +|* Letzte Aenderung MM 29.04.96 +|* +*************************************************************************/ + +UniqueIdContainer::UniqueIdContainer( const UniqueIdContainer& rObj ) + : UniqueIndex( rObj ) + , nCollectCount( rObj.nCollectCount ) +{ + ULONG nCur = GetCurIndex(); + + ImpUniqueId * pEle = (ImpUniqueId *)First(); + while( pEle ) + { + pEle->nRefCount++; + pEle = (ImpUniqueId *)Next(); + } + Seek( nCur ); +} + +/************************************************************************* +|* +|* UniqueIdContainer::operator = () +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung MM 01.08.94 +|* Letzte Aenderung MM 01.08.94 +|* +*************************************************************************/ + +UniqueIdContainer& UniqueIdContainer::operator = ( const UniqueIdContainer & rObj ) +{ + UniqueIndex::operator = ( rObj ); + nCollectCount = rObj.nCollectCount; + + ULONG nCur = GetCurIndex(); + + ImpUniqueId * pEle = (ImpUniqueId *)First(); + while( pEle ) + { + pEle->nRefCount++; + pEle = (ImpUniqueId *)Next(); + } + Seek( nCur ); + return *this; +} + +/************************************************************************* +|* +|* UniqueIdContainer::Clear() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung MM 01.08.94 +|* Letzte Aenderung MM 01.08.94 +|* +*************************************************************************/ + +void UniqueIdContainer::Clear( BOOL bAll ) +{ + USHORT nFree = bAll ? 0xFFFF : 1; + + ImpUniqueId* pId = (ImpUniqueId*)Last(); + BOOL bLast = TRUE; + while ( pId ) + { + if ( pId->nRefCount <= nFree ) + { + ((ImpUniqueId *)Remove( pId->nId ))->Release(); + if( bLast ) + pId = (ImpUniqueId *)Last(); + else + pId = (ImpUniqueId *)Prev(); + } + else + { + pId = (ImpUniqueId *)Prev(); + bLast = FALSE; + } + } +} + +/************************************************************************* +|* +|* UniqueIdContainer::CreateId() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung MM 01.08.94 +|* Letzte Aenderung MM 01.08.94 +|* +*************************************************************************/ + +UniqueItemId UniqueIdContainer::CreateId() +{ + if( nCollectCount > 50 ) + { // aufraeumen + Clear( FALSE ); + nCollectCount = 0; + } + nCollectCount++; + + ImpUniqueId * pId = new ImpUniqueId; + pId->nRefCount = 1; + pId->nId = Insert( pId ); + return UniqueItemId( pId ); +} + +/************************************************************************* +|* +|* UniqueIdContainer::CreateIdProt() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung MM 01.08.94 +|* Letzte Aenderung MM 01.08.94 +|* +*************************************************************************/ + +UniqueItemId UniqueIdContainer::CreateFreeId( ULONG nId ) +{ + // Einfach erzeugen, fuer abgeleitete Klasse + ImpUniqueId * pId = new ImpUniqueId; + pId->nRefCount = 0; + pId->nId = nId; + return UniqueItemId( pId ); +} + +/************************************************************************* +|* +|* UniqueIdContainer::CreateIdProt() +|* +|* Beschreibung UNQIDX.SDW +|* Ersterstellung MM 01.08.94 +|* Letzte Aenderung MM 01.08.94 +|* +*************************************************************************/ + +UniqueItemId UniqueIdContainer::CreateIdProt( ULONG nId ) +{ + if ( IsIndexValid( nId ) ) + return UniqueItemId( (ImpUniqueId *)Get( nId ) ); + + ImpUniqueId * pId; + do + { + pId = new ImpUniqueId; + pId->nRefCount = 1; + pId->nId = Insert( pId ); + } + while( pId->nId != nId ); + return UniqueItemId( pId ); +} |