blob: f3ef670df5bae263bfe8e1e5cec4026c7904abe0 [file] [log] [blame]
/**************************************************************
*
* 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"
#include "tools/geninfo.hxx"
#include <stdio.h>
//
// class GenericInformation
//
/*****************************************************************************/
GenericInformation::GenericInformation( const ByteString &rKey,
const ByteString &rValue,
GenericInformationList *pParentList,
GenericInformationList *pSubInfos )
/*****************************************************************************/
: ByteString( rKey ),
sValue( rValue ),
pInfoList( pSubInfos ),
pParent( pParentList )
{
// if a ParentList exists, insert this object into it
if ( pParent )
pParent->InsertInfo( this );
// make myself owner of pInfoList
if ( pInfoList )
pInfoList->SetOwner( this );
}
/*****************************************************************************/
GenericInformation::GenericInformation( const GenericInformation& rInf,
sal_Bool bCopySubs)
/*****************************************************************************/
: ByteString( rInf ),
sValue( rInf.sValue ),
pInfoList( 0L ),
pParent(NULL)
{
if(bCopySubs && rInf.pInfoList)
pInfoList = new GenericInformationList(*rInf.pInfoList, this);
}
/*****************************************************************************/
GenericInformation::~GenericInformation()
/*****************************************************************************/
{
// remove pInfoList and all childs out of memory
delete pInfoList;
pInfoList = 0;
// remove this Info out of ParentList
if ( pParent )
pParent->RemoveInfo( this );
}
/*****************************************************************************/
sal_Bool GenericInformation::InsertSubInfo( GenericInformation *pInfo )
/*****************************************************************************/
{
return ( pInfoList && pInfoList->InsertInfo( pInfo ));
}
/*****************************************************************************/
sal_Bool GenericInformation::InsertSubInfo( const ByteString &rPathKey, const ByteString &rValue,
sal_Bool bSearchByPath, sal_Bool bNewPath )
/*****************************************************************************/
{
return (pInfoList && pInfoList->InsertInfo( rPathKey, rValue, bSearchByPath, bNewPath ));
}
/*****************************************************************************/
void GenericInformation::RemoveSubInfo( GenericInformation *pInfo,
sal_Bool bDelete )
/*****************************************************************************/
{
pInfoList->RemoveInfo( pInfo, bDelete );
}
/*****************************************************************************/
//void GenericInformation::RemoveSelf( sal_Bool bDelete )
/*****************************************************************************/
/*{
if ( pParent )
pParent->RemoveInfo( this, bDelete ); // loescht sich aus der Liste vom Parent und
// bei Bedarf auch mit obiger Methode alle Sublisten
// loescht sich bei Bedarf auch selbst
if ( bDelete )
delete this;
}
*/
/*****************************************************************************/
GenericInformation *GenericInformation::GetSubInfo( ByteString &rKey,
sal_Bool bSearchByPath,
sal_Bool bCreatePath )
/*****************************************************************************/
{
if ( !pInfoList && bCreatePath )
pInfoList = new GenericInformationList( this );
if ( pInfoList )
return pInfoList->GetInfo( rKey, bSearchByPath, bCreatePath );
return NULL;
}
//
// class GenericInformationList
//
/*****************************************************************************/
GenericInformationList::GenericInformationList( GenericInformation *pParent )
/*****************************************************************************/
: pOwner( pParent )
{
}
/*****************************************************************************/
GenericInformationList::GenericInformationList(const GenericInformationList& rList,
GenericInformation *pParent)
/*****************************************************************************/
: GenericInformationList_Impl()
{
sal_uInt16 i;
GenericInformation* pTemp,*pWork;
pOwner = pParent;
for(i=0;i<rList.Count();i++)
{
pTemp = rList.GetObject(i);
pWork = new GenericInformation(*pTemp,sal_True);
Insert(pWork,LIST_APPEND);
}
}
/*****************************************************************************/
GenericInformationList::~GenericInformationList()
/*****************************************************************************/
{
// delete all Informations stored in this List
// ### GH: Hier werden dann wohl etwa die H�lfte der Eintr�ge gel�scht
/* for ( sal_uIntPtr i = 0; i < Count(); i++ ) {
GetObject( i )->ListDeleted();
delete GetObject( i );
Remove( i );*/
// Neue Variante:
while ( Count() ) {
GetObject( 0 )->ListDeleted();
delete GetObject( 0 );
Remove( (sal_uIntPtr)0 );
}
}
/*****************************************************************************/
GenericInformation *GenericInformationList::Search( sal_uIntPtr &rPos, ByteString sKey,
sal_uIntPtr nStart, sal_uIntPtr nEnd )
/*****************************************************************************/
{
if ( Count() == 0 ) {
rPos = 0;
return NULL;
}
if ( nStart == nEnd ) {
rPos = nStart;
ByteString sCandidate = ByteString( *GetObject( nStart ));
if ( sCandidate.ToUpperAscii() == sKey.ToUpperAscii()) {
return GetObject( nStart ); // found !!!
}
else {
// requested key not found
return NULL;
}
}
// search binary in existing list
sal_uIntPtr nActPos = nStart + (( nEnd - nStart ) / 2 );
rPos = nActPos;
ByteString sCandidate = ByteString( *GetObject( nActPos ));
if ( sCandidate.ToUpperAscii() == sKey.ToUpperAscii())
return GetObject( nActPos ); // found !!!
// split the list at ActPos
if ( sCandidate < sKey )
return Search( rPos, sKey, nActPos + 1, nEnd );
else
return Search( rPos, sKey, nStart, nActPos );
}
/*****************************************************************************/
GenericInformation *GenericInformationList::GetInfo( ByteString &rKey,
sal_Bool bSearchByPath,
sal_Bool bCreatePath )
/*****************************************************************************/
{
rKey.EraseLeadingChars( '/' );
rKey.EraseTrailingChars( '/' );
ByteString sKey;
if ( bSearchByPath )
sKey = rKey.GetToken( 0, '/' );
else
sKey = rKey;
sal_uIntPtr nPos = 0;
GenericInformation *pReturnInfo = Search( nPos, sKey, 0, Count() - 1 );
/* wenn kein Searchpath gesetzt und kein Returninfo vorhanden,
* gib NULL zurueck
* wenn Searchpath gesetzt und returninfo vorhanden,
* suche weiter nach unten
* wenn searchpath gesetzt kein returninfo vorhanden und newpath gesetzt,
* mache neues Verzeichniss
*/
sal_uInt16 nTokenCount = rKey.GetTokenCount('/');
// search for next key of path in next level of tree
if ( bSearchByPath && (nTokenCount > 1)) {
ByteString sPath = ByteString(rKey.Copy( sKey.Len() + 1 ));
if ( !pReturnInfo ) { // wenn kein Return, dann muss man es anlegen
if ( !bCreatePath ) // wenn aber kein Create, dann nicht anlegen
return NULL;
pReturnInfo = new GenericInformation( sKey, "", this, NULL);
pReturnInfo->SetSubList( new GenericInformationList( pReturnInfo ));
}
return pReturnInfo->GetSubInfo( sPath, sal_True, bCreatePath );
}
if ( !pReturnInfo && bCreatePath ) {
pReturnInfo = new GenericInformation ( sKey, "", this, NULL);
}
return pReturnInfo; // kann durchaus NULL sein.
}
/*****************************************************************************/
sal_uIntPtr GenericInformationList::InsertSorted( GenericInformation *pInfo,
sal_Bool bOverwrite,
sal_uIntPtr nStart, sal_uIntPtr nEnd )
/*****************************************************************************/
{
if ( Count() == 0 ) {
// empty list, so insert at first pos
Insert( pInfo, LIST_APPEND );
return 0;
}
ByteString sKey( pInfo->GetBuffer());
sKey.ToUpperAscii();
// Check to sppeed up reading a (partially) sorted list
if ( nStart == 0 && Count()-1 == nEnd )
{
ByteString sCandidate( *GetObject( nEnd ));
if ( sCandidate.ToUpperAscii() < sKey )
{
Insert( pInfo, LIST_APPEND );
return nEnd+1;
}
}
// ### GH: dieser Block schein �berfl�ssig zu sein
if ( Count() == 1 ) {
ByteString sCandidate( *GetObject( 0 ));
if ( sCandidate.ToUpperAscii() == sKey ) {
// key allready exists in list
if ( bOverwrite )
Replace( pInfo, sal_uIntPtr(0)); // ### Laut NF scheint hier ein Memory Leak zu sein
return 0;
}
else if ( sCandidate > sKey ) {
Insert( pInfo, sal_uIntPtr(0));
return 0;
}
else {
Insert( pInfo, LIST_APPEND );
return 1;
}
}
// ### GH: /ENDE/ dieser Block schein �berfl�ssig zu sein
sal_uIntPtr nActPos = nStart + (( nEnd - nStart ) / 2 );
ByteString sCandidate = ByteString( *GetObject( nActPos ));
if ( sCandidate.ToUpperAscii() == sKey ) {
// key allready exists in list
if ( bOverwrite )
Replace( pInfo, nActPos ); // ### Laut NF scheint hier ein Memory Leak zu sein
return nActPos;
}
if ( nStart == nEnd ) {
// now more ways to search for key -> insert here
if ( sCandidate > sKey ) {
Insert( pInfo, nStart );
return nStart;
}
else {
Insert( pInfo, nStart + 1 );
return ( nStart + 1 );
}
}
if ( nActPos == Count() - 1 ) {
// reached end of list -> insert here
Insert( pInfo, LIST_APPEND );
return ( nActPos + 1 );
}
ByteString sSecondCand = ByteString( *GetObject( nActPos + 1 ));
if (( sCandidate < sKey ) && ( sSecondCand.ToUpperAscii() > sKey )) {
// optimal position to insert object
Insert( pInfo, nActPos + 1 );
return ( nActPos + 1 );
}
if ( sCandidate < sKey )
return InsertSorted( pInfo, bOverwrite, nActPos + 1, nEnd );
else
return InsertSorted( pInfo, bOverwrite, nStart, nActPos );
}
/*****************************************************************************/
sal_Bool GenericInformationList::InsertInfo( GenericInformation *pInfo,
sal_Bool bOverwrite )
/*****************************************************************************/
{
if ( !pInfo->Len())
return sal_False;
InsertSorted( pInfo, bOverwrite, 0, Count() - 1 );
return sal_True;
}
/*****************************************************************************/
sal_Bool GenericInformationList::InsertInfo( const ByteString &rPathKey, const ByteString &rValue,
sal_Bool bSearchByPath, sal_Bool bNewPath )
/*****************************************************************************/
{
GenericInformation *pInfo;
ByteString sPathKey ( rPathKey );
sPathKey.EraseLeadingChars( '/' );
sPathKey.EraseTrailingChars( '/' );
pInfo = GetInfo( sPathKey, bSearchByPath, bNewPath );
if ( pInfo ) {
pInfo->SetValue( rValue );
return sal_True;
}
return sal_False;
}
/*****************************************************************************/
void GenericInformationList::RemoveInfo( GenericInformation *pInfo,
sal_Bool bDelete )
/*****************************************************************************/
{
Remove( pInfo );
if ( bDelete )
delete pInfo;
/* if ( Count() == 0 && pOwner ) // Leere Listen entfernen;
{
SetOwner( NULL );
delete this;
} Rausgepatched by GH */
}
GenericInformation* GenericInformationList::SetOwner( GenericInformation *pNewOwner )
{
GenericInformation *pOldOwner = pOwner;
if ( pOwner ) // bei parent austragen;
pOwner->SetSubList( NULL );
if ( pNewOwner )
pNewOwner->SetSubList( this );
pOwner = pNewOwner;
return pOldOwner;
}