| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_tools.hxx" |
| |
| #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 n = 0; |
| sal_uInt16 nTempCount = (sal_uInt16)nCount * 2; |
| //<!--Modified by PengYunQuan for resolving a NULL pointer access |
| |
| if( void** pNodes = Container::ImpGetOnlyNodes() ) |
| { |
| 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; |
| } |
| //-->Modified by PengYunQuan for resolving a NULL pointer access |
| } |
| 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::GetUniqueKey( sal_uIntPtr nStartKey ) const |
| { |
| DBG_ASSERT( (nStartKey > 1) && (nStartKey < 0xFFFFFFFF), |
| "Table::GetUniqueKey() - nStartKey == 0 or nStartKey >= 0xFFFFFFFF" ); |
| |
| if ( !nCount ) |
| return nStartKey; |
| |
| sal_uIntPtr nLastKey = (sal_uIntPtr)Container::GetObject( (nCount*2)-2 ); |
| if ( nLastKey < nStartKey ) |
| return nStartKey; |
| else |
| { |
| if ( nLastKey < 0xFFFFFFFE ) |
| return nLastKey+1; |
| else |
| { |
| sal_uIntPtr nPos; |
| sal_uIntPtr nTempPos = ImplGetIndex( nStartKey, &nPos ); |
| if ( nTempPos != TABLE_ENTRY_NOTFOUND ) |
| nPos = nTempPos; |
| nLastKey = (sal_uIntPtr)Container::GetObject( nPos ); |
| if ( nStartKey < nLastKey ) |
| return nStartKey; |
| while ( nLastKey < 0xFFFFFFFE ) |
| { |
| nPos += 2; |
| nLastKey++; |
| if ( nLastKey != (sal_uIntPtr)Container::GetObject( nPos ) ) |
| return nLastKey; |
| } |
| } |
| } |
| |
| return 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| 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; |
| } |