office-gobmx/tools/source/memtools/table.cxx
2011-11-27 13:25:56 -06:00

373 lines
9.5 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org 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 version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
#define _TOOLS_TABLE_CXX
// -----------------------------------------------------------------------
#include <tools/debug.hxx>
#include <impcont.hxx>
#include <tools/table.hxx>
// =======================================================================
sal_uIntPtr Table::ImplGetIndex( sal_uIntPtr nKey, sal_uIntPtr* pIndex ) const
{
// Abpruefen, ob der erste Key groesser als der Vergleichskey ist
if ( !nCount || (nKey < (sal_uIntPtr)Container::ImpGetObject(0)) )
return TABLE_ENTRY_NOTFOUND;
sal_uIntPtr nLow;
sal_uIntPtr nHigh;
sal_uIntPtr nMid;
sal_uIntPtr nCompareKey;
void** pNodes = Container::ImpGetOnlyNodes();
// Binaeres Suchen
nLow = 0;
nHigh = nCount-1;
if ( pNodes )
{
do
{
nMid = (nLow + nHigh) / 2;
nCompareKey = (sal_uIntPtr)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 = (sal_uIntPtr)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( sal_uInt16 _nInitSize, sal_uInt16 _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;
}
// -----------------------------------------------------------------------
sal_Bool Table::Insert( sal_uIntPtr nKey, void* p )
{
// Tabellenelement einsortieren
sal_uIntPtr i;
if ( nCount )
{
if ( nCount <= 24 )
{
sal_uInt16 nTempCount = (sal_uInt16)nCount * 2;
if( void** pNodes = Container::ImpGetOnlyNodes() )
{
sal_uInt16 n = 0;
sal_uIntPtr nCompareKey = (sal_uIntPtr)(*pNodes);
while ( nKey > nCompareKey )
{
n += 2;
pNodes += 2;
if ( n < nTempCount )
nCompareKey = (sal_uIntPtr)(*pNodes);
else
{
nCompareKey = 0;
break;
}
}
// Testen, ob sich der Key schon in der Tabelle befindet
if ( nKey == nCompareKey )
return sal_False;
i = n;
}
else
{
i = 0;
if ( ImplGetIndex( nKey, &i ) != TABLE_ENTRY_NOTFOUND )
return sal_False;
}
}
else
{
i = 0;
if ( ImplGetIndex( nKey, &i ) != TABLE_ENTRY_NOTFOUND )
return sal_False;
}
}
else
i = 0;
// Eintrag einfuegen (Key vor Pointer)
Container::Insert( (void*)nKey, i );
Container::Insert( p, i+1 );
// Ein neuer Eintrag
nCount++;
return sal_True;
}
// -----------------------------------------------------------------------
void* Table::Remove( sal_uIntPtr nKey )
{
// Index besorgen
sal_uIntPtr 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( sal_uIntPtr nKey, void* p )
{
// Index abfragen
sal_uIntPtr 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( sal_uIntPtr nKey ) const
{
// Index besorgen
sal_uIntPtr 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 );
}
// -----------------------------------------------------------------------
sal_uIntPtr Table::GetKey( const void* p ) const
{
sal_uIntPtr 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 (sal_uIntPtr)Container::ImpGetObject( nIndex*2 );
nIndex++;
}
return TABLE_ENTRY_NOTFOUND;
}
// -----------------------------------------------------------------------
sal_Bool Table::IsKeyValid( sal_uIntPtr nKey ) const
{
return (ImplGetIndex( nKey ) != TABLE_ENTRY_NOTFOUND) ? sal_True : sal_False;
}
// -----------------------------------------------------------------------
sal_uIntPtr Table::SearchKey( sal_uIntPtr nKey, sal_uIntPtr* pPos ) const
{
*pPos = 0;
sal_uIntPtr nPos = ImplGetIndex( nKey, pPos );
if ( nPos != TABLE_ENTRY_NOTFOUND )
{
nPos /= 2;
*pPos = nPos;
}
else
*pPos /= 2;
return nPos;
}
// -----------------------------------------------------------------------
void* Table::Seek( sal_uIntPtr nKey )
{
// Testen, ob ein Eintrag vorhanden ist
if ( nCount )
{
sal_uIntPtr 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 )
{
sal_uIntPtr 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;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */