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