xref: /trunk/main/tools/source/communi/geninfo.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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