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