1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_tools.hxx" 30 #include "tools/geninfo.hxx" 31 #include <stdio.h> 32 33 // 34 // class GenericInformation 35 // 36 37 /*****************************************************************************/ 38 GenericInformation::GenericInformation( const ByteString &rKey, 39 const ByteString &rValue, 40 GenericInformationList *pParentList, 41 GenericInformationList *pSubInfos ) 42 /*****************************************************************************/ 43 : ByteString( rKey ), 44 sValue( rValue ), 45 pInfoList( pSubInfos ), 46 pParent( pParentList ) 47 { 48 // if a ParentList exists, insert this object into it 49 if ( pParent ) 50 pParent->InsertInfo( this ); 51 // make myself owner of pInfoList 52 if ( pInfoList ) 53 pInfoList->SetOwner( this ); 54 } 55 56 /*****************************************************************************/ 57 GenericInformation::GenericInformation( const GenericInformation& rInf, 58 sal_Bool bCopySubs) 59 /*****************************************************************************/ 60 : ByteString( rInf ), 61 sValue( rInf.sValue ), 62 pInfoList( 0L ), 63 pParent(NULL) 64 { 65 if(bCopySubs && rInf.pInfoList) 66 pInfoList = new GenericInformationList(*rInf.pInfoList, this); 67 } 68 69 /*****************************************************************************/ 70 GenericInformation::~GenericInformation() 71 /*****************************************************************************/ 72 { 73 // remove pInfoList and all childs out of memory 74 delete pInfoList; 75 pInfoList = 0; 76 77 // remove this Info out of ParentList 78 if ( pParent ) 79 pParent->RemoveInfo( this ); 80 } 81 82 /*****************************************************************************/ 83 sal_Bool GenericInformation::InsertSubInfo( GenericInformation *pInfo ) 84 /*****************************************************************************/ 85 { 86 return ( pInfoList && pInfoList->InsertInfo( pInfo )); 87 } 88 89 /*****************************************************************************/ 90 sal_Bool GenericInformation::InsertSubInfo( const ByteString &rPathKey, const ByteString &rValue, 91 sal_Bool bSearchByPath, sal_Bool bNewPath ) 92 /*****************************************************************************/ 93 { 94 return (pInfoList && pInfoList->InsertInfo( rPathKey, rValue, bSearchByPath, bNewPath )); 95 } 96 97 /*****************************************************************************/ 98 void GenericInformation::RemoveSubInfo( GenericInformation *pInfo, 99 sal_Bool bDelete ) 100 /*****************************************************************************/ 101 { 102 pInfoList->RemoveInfo( pInfo, bDelete ); 103 } 104 105 /*****************************************************************************/ 106 //void GenericInformation::RemoveSelf( sal_Bool bDelete ) 107 /*****************************************************************************/ 108 /*{ 109 if ( pParent ) 110 pParent->RemoveInfo( this, bDelete ); // loescht sich aus der Liste vom Parent und 111 // bei Bedarf auch mit obiger Methode alle Sublisten 112 113 // loescht sich bei Bedarf auch selbst 114 if ( bDelete ) 115 delete this; 116 } 117 */ 118 119 /*****************************************************************************/ 120 GenericInformation *GenericInformation::GetSubInfo( ByteString &rKey, 121 sal_Bool bSearchByPath, 122 sal_Bool bCreatePath ) 123 /*****************************************************************************/ 124 { 125 if ( !pInfoList && bCreatePath ) 126 pInfoList = new GenericInformationList( this ); 127 if ( pInfoList ) 128 return pInfoList->GetInfo( rKey, bSearchByPath, bCreatePath ); 129 return NULL; 130 } 131 132 133 // 134 // class GenericInformationList 135 // 136 137 /*****************************************************************************/ 138 GenericInformationList::GenericInformationList( GenericInformation *pParent ) 139 /*****************************************************************************/ 140 : pOwner( pParent ) 141 { 142 } 143 144 /*****************************************************************************/ 145 GenericInformationList::GenericInformationList(const GenericInformationList& rList, 146 GenericInformation *pParent) 147 /*****************************************************************************/ 148 : GenericInformationList_Impl() 149 { 150 sal_uInt16 i; 151 GenericInformation* pTemp,*pWork; 152 153 pOwner = pParent; 154 155 for(i=0;i<rList.Count();i++) 156 { 157 pTemp = rList.GetObject(i); 158 pWork = new GenericInformation(*pTemp,sal_True); 159 160 Insert(pWork,LIST_APPEND); 161 } 162 } 163 164 /*****************************************************************************/ 165 GenericInformationList::~GenericInformationList() 166 /*****************************************************************************/ 167 { 168 // delete all Informations stored in this List 169 // ### GH: Hier werden dann wohl etwa die H�lfte der Eintr�ge gel�scht 170 /* for ( sal_uIntPtr i = 0; i < Count(); i++ ) { 171 GetObject( i )->ListDeleted(); 172 delete GetObject( i ); 173 Remove( i );*/ 174 // Neue Variante: 175 while ( Count() ) { 176 GetObject( 0 )->ListDeleted(); 177 delete GetObject( 0 ); 178 Remove( (sal_uIntPtr)0 ); 179 } 180 } 181 182 /*****************************************************************************/ 183 GenericInformation *GenericInformationList::Search( sal_uIntPtr &rPos, ByteString sKey, 184 sal_uIntPtr nStart, sal_uIntPtr nEnd ) 185 /*****************************************************************************/ 186 { 187 if ( Count() == 0 ) { 188 rPos = 0; 189 return NULL; 190 } 191 192 if ( nStart == nEnd ) { 193 rPos = nStart; 194 ByteString sCandidate = ByteString( *GetObject( nStart )); 195 if ( sCandidate.ToUpperAscii() == sKey.ToUpperAscii()) { 196 return GetObject( nStart ); // found !!! 197 } 198 else { 199 // requested key not found 200 return NULL; 201 } 202 } 203 204 // search binary in existing list 205 sal_uIntPtr nActPos = nStart + (( nEnd - nStart ) / 2 ); 206 rPos = nActPos; 207 ByteString sCandidate = ByteString( *GetObject( nActPos )); 208 209 if ( sCandidate.ToUpperAscii() == sKey.ToUpperAscii()) 210 return GetObject( nActPos ); // found !!! 211 212 // split the list at ActPos 213 if ( sCandidate < sKey ) 214 return Search( rPos, sKey, nActPos + 1, nEnd ); 215 else 216 return Search( rPos, sKey, nStart, nActPos ); 217 } 218 219 /*****************************************************************************/ 220 GenericInformation *GenericInformationList::GetInfo( ByteString &rKey, 221 sal_Bool bSearchByPath, 222 sal_Bool bCreatePath ) 223 /*****************************************************************************/ 224 { 225 226 rKey.EraseLeadingChars( '/' ); 227 rKey.EraseTrailingChars( '/' ); 228 229 ByteString sKey; 230 if ( bSearchByPath ) 231 sKey = rKey.GetToken( 0, '/' ); 232 else 233 sKey = rKey; 234 235 sal_uIntPtr nPos = 0; 236 GenericInformation *pReturnInfo = Search( nPos, sKey, 0, Count() - 1 ); 237 /* wenn kein Searchpath gesetzt und kein Returninfo vorhanden, 238 * gib NULL zurueck 239 * wenn Searchpath gesetzt und returninfo vorhanden, 240 * suche weiter nach unten 241 * wenn searchpath gesetzt kein returninfo vorhanden und newpath gesetzt, 242 * mache neues Verzeichniss 243 */ 244 sal_uInt16 nTokenCount = rKey.GetTokenCount('/'); 245 // search for next key of path in next level of tree 246 if ( bSearchByPath && (nTokenCount > 1)) { 247 ByteString sPath = ByteString(rKey.Copy( sKey.Len() + 1 )); 248 if ( !pReturnInfo ) { // wenn kein Return, dann muss man es anlegen 249 if ( !bCreatePath ) // wenn aber kein Create, dann nicht anlegen 250 return NULL; 251 pReturnInfo = new GenericInformation( sKey, "", this, NULL); 252 pReturnInfo->SetSubList( new GenericInformationList( pReturnInfo )); 253 } 254 return pReturnInfo->GetSubInfo( sPath, sal_True, bCreatePath ); 255 } 256 if ( !pReturnInfo && bCreatePath ) { 257 pReturnInfo = new GenericInformation ( sKey, "", this, NULL); 258 } 259 260 return pReturnInfo; // kann durchaus NULL sein. 261 } 262 263 /*****************************************************************************/ 264 sal_uIntPtr GenericInformationList::InsertSorted( GenericInformation *pInfo, 265 sal_Bool bOverwrite, 266 sal_uIntPtr nStart, sal_uIntPtr nEnd ) 267 /*****************************************************************************/ 268 { 269 if ( Count() == 0 ) { 270 // empty list, so insert at first pos 271 Insert( pInfo, LIST_APPEND ); 272 return 0; 273 } 274 275 ByteString sKey( pInfo->GetBuffer()); 276 sKey.ToUpperAscii(); 277 278 // Check to sppeed up reading a (partially) sorted list 279 if ( nStart == 0 && Count()-1 == nEnd ) 280 { 281 ByteString sCandidate( *GetObject( nEnd )); 282 if ( sCandidate.ToUpperAscii() < sKey ) 283 { 284 Insert( pInfo, LIST_APPEND ); 285 return nEnd+1; 286 } 287 } 288 289 // ### GH: dieser Block schein �berfl�ssig zu sein 290 if ( Count() == 1 ) { 291 ByteString sCandidate( *GetObject( 0 )); 292 if ( sCandidate.ToUpperAscii() == sKey ) { 293 // key allready exists in list 294 if ( bOverwrite ) 295 Replace( pInfo, sal_uIntPtr(0)); // ### Laut NF scheint hier ein Memory Leak zu sein 296 return 0; 297 } 298 else if ( sCandidate > sKey ) { 299 Insert( pInfo, sal_uIntPtr(0)); 300 return 0; 301 } 302 else { 303 Insert( pInfo, LIST_APPEND ); 304 return 1; 305 } 306 } 307 // ### GH: /ENDE/ dieser Block schein �berfl�ssig zu sein 308 309 sal_uIntPtr nActPos = nStart + (( nEnd - nStart ) / 2 ); 310 ByteString sCandidate = ByteString( *GetObject( nActPos )); 311 312 if ( sCandidate.ToUpperAscii() == sKey ) { 313 // key allready exists in list 314 if ( bOverwrite ) 315 Replace( pInfo, nActPos ); // ### Laut NF scheint hier ein Memory Leak zu sein 316 return nActPos; 317 } 318 319 if ( nStart == nEnd ) { 320 // now more ways to search for key -> insert here 321 if ( sCandidate > sKey ) { 322 Insert( pInfo, nStart ); 323 return nStart; 324 } 325 else { 326 Insert( pInfo, nStart + 1 ); 327 return ( nStart + 1 ); 328 } 329 } 330 331 if ( nActPos == Count() - 1 ) { 332 // reached end of list -> insert here 333 Insert( pInfo, LIST_APPEND ); 334 return ( nActPos + 1 ); 335 } 336 337 ByteString sSecondCand = ByteString( *GetObject( nActPos + 1 )); 338 if (( sCandidate < sKey ) && ( sSecondCand.ToUpperAscii() > sKey )) { 339 // optimal position to insert object 340 Insert( pInfo, nActPos + 1 ); 341 return ( nActPos + 1 ); 342 } 343 344 if ( sCandidate < sKey ) 345 return InsertSorted( pInfo, bOverwrite, nActPos + 1, nEnd ); 346 else 347 return InsertSorted( pInfo, bOverwrite, nStart, nActPos ); 348 } 349 350 /*****************************************************************************/ 351 sal_Bool GenericInformationList::InsertInfo( GenericInformation *pInfo, 352 sal_Bool bOverwrite ) 353 /*****************************************************************************/ 354 { 355 if ( !pInfo->Len()) 356 return sal_False; 357 358 InsertSorted( pInfo, bOverwrite, 0, Count() - 1 ); 359 return sal_True; 360 } 361 362 363 /*****************************************************************************/ 364 sal_Bool GenericInformationList::InsertInfo( const ByteString &rPathKey, const ByteString &rValue, 365 sal_Bool bSearchByPath, sal_Bool bNewPath ) 366 /*****************************************************************************/ 367 { 368 GenericInformation *pInfo; 369 ByteString sPathKey ( rPathKey ); 370 sPathKey.EraseLeadingChars( '/' ); 371 sPathKey.EraseTrailingChars( '/' ); 372 373 pInfo = GetInfo( sPathKey, bSearchByPath, bNewPath ); 374 375 if ( pInfo ) { 376 pInfo->SetValue( rValue ); 377 return sal_True; 378 } 379 return sal_False; 380 } 381 382 /*****************************************************************************/ 383 void GenericInformationList::RemoveInfo( GenericInformation *pInfo, 384 sal_Bool bDelete ) 385 /*****************************************************************************/ 386 { 387 Remove( pInfo ); 388 if ( bDelete ) 389 delete pInfo; 390 /* if ( Count() == 0 && pOwner ) // Leere Listen entfernen; 391 { 392 SetOwner( NULL ); 393 delete this; 394 } Rausgepatched by GH */ 395 } 396 397 GenericInformation* GenericInformationList::SetOwner( GenericInformation *pNewOwner ) 398 { 399 GenericInformation *pOldOwner = pOwner; 400 if ( pOwner ) // bei parent austragen; 401 pOwner->SetSubList( NULL ); 402 if ( pNewOwner ) 403 pNewOwner->SetSubList( this ); 404 pOwner = pNewOwner; 405 return pOldOwner; 406 } 407 408 409