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 /*****************************************************************************/
GenericInformation(const ByteString & rKey,const ByteString & rValue,GenericInformationList * pParentList,GenericInformationList * pSubInfos)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 /*****************************************************************************/
GenericInformation(const GenericInformation & rInf,sal_Bool bCopySubs)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 /*****************************************************************************/
~GenericInformation()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 /*****************************************************************************/
InsertSubInfo(GenericInformation * pInfo)79 sal_Bool GenericInformation::InsertSubInfo( GenericInformation *pInfo )
80 /*****************************************************************************/
81 {
82 return ( pInfoList && pInfoList->InsertInfo( pInfo ));
83 }
84
85 /*****************************************************************************/
InsertSubInfo(const ByteString & rPathKey,const ByteString & rValue,sal_Bool bSearchByPath,sal_Bool bNewPath)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 /*****************************************************************************/
RemoveSubInfo(GenericInformation * pInfo,sal_Bool bDelete)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 /*****************************************************************************/
GetSubInfo(ByteString & rKey,sal_Bool bSearchByPath,sal_Bool bCreatePath)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 /*****************************************************************************/
GenericInformationList(GenericInformation * pParent)134 GenericInformationList::GenericInformationList( GenericInformation *pParent )
135 /*****************************************************************************/
136 : pOwner( pParent )
137 {
138 }
139
140 /*****************************************************************************/
GenericInformationList(const GenericInformationList & rList,GenericInformation * pParent)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 /*****************************************************************************/
~GenericInformationList()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 /*****************************************************************************/
Search(sal_uIntPtr & rPos,ByteString sKey,sal_uIntPtr nStart,sal_uIntPtr nEnd)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 /*****************************************************************************/
GetInfo(ByteString & rKey,sal_Bool bSearchByPath,sal_Bool bCreatePath)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 /*****************************************************************************/
InsertSorted(GenericInformation * pInfo,sal_Bool bOverwrite,sal_uIntPtr nStart,sal_uIntPtr nEnd)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 already 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 already 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 /*****************************************************************************/
InsertInfo(GenericInformation * pInfo,sal_Bool bOverwrite)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 /*****************************************************************************/
InsertInfo(const ByteString & rPathKey,const ByteString & rValue,sal_Bool bSearchByPath,sal_Bool bNewPath)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 /*****************************************************************************/
RemoveInfo(GenericInformation * pInfo,sal_Bool bDelete)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
SetOwner(GenericInformation * pNewOwner)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