xref: /trunk/main/tools/source/communi/parser.cxx (revision 89b56da7)
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 
27 #include <stdio.h>
28 #include <tools/stream.hxx>
29 #include <tools/fsys.hxx>
30 
31 #include "tools/iparser.hxx"
32 #include "tools/geninfo.hxx"
33 
34 
35 
36 //
37 // class InformationParser
38 //
39 
40 #define cKeyLevelChar '\t'
41 
42 /*****************************************************************************/
InformationParser(sal_Bool bReplace)43 InformationParser::InformationParser( sal_Bool bReplace )
44 /*****************************************************************************/
45 				: bRecover( sal_False ),
46 				sOldLine( "" ),
47 				bReplaceVariables( bReplace ),
48 				nLevel( 0 ),
49 				sUPD( "" ),
50 				sVersion( "" ),
51 				pActStream( NULL ),
52 				nErrorCode( 0 ),
53 				nErrorLine( 0 ),
54 				sErrorText( "" ),
55 				nActLine( 0 )
56 {
57 }
58 
59 /*****************************************************************************/
~InformationParser()60 InformationParser::~InformationParser()
61 /*****************************************************************************/
62 {
63 }
64 
65 /*****************************************************************************/
ReadLine()66 ByteString &InformationParser::ReadLine()
67 /*****************************************************************************/
68 {
69 	ByteString sLine;
70 
71 	if ( bRecover ) {
72 		bRecover = sal_False;
73 	}
74 	else {
75 		 if ( !pActStream->IsEof()) {
76 			pActStream->ReadLine( sLine );
77             xub_StrLen nStart = 0;
78             xub_StrLen nEnd = sLine.Len();
79             sal_Bool bCopy = sal_False;
80             while ( nStart < nEnd && ( sLine.GetChar( nStart ) == ' ' || sLine.GetChar( nStart ) == 0x09 ) )
81             {
82                 nStart++;
83                 bCopy = sal_True;
84             }
85 
86             while ( nStart < nEnd && ( sLine.GetChar( nEnd-1 ) == ' ' || sLine.GetChar( nEnd-1 ) == 0x09 ) )
87             {
88                 nEnd--;
89                 bCopy = sal_True;
90             }
91 
92             if ( bCopy )
93                 sLine = sLine.Copy( nStart, nEnd - nStart );
94 
95 			if (( sLine.GetChar( 0 ) == '#' ) || ( !sLine.Len())) {
96 				if ( sCurrentComment.Len())
97 					sCurrentComment += "\n";
98 				sCurrentComment += sLine;
99 				return ReadLine();
100 			}
101 			else {
102 				if ( bReplaceVariables ) {
103 					sLine.SearchAndReplaceAll( "%UPD", sUPD );
104 					sLine.SearchAndReplaceAll( "%VERSION", sVersion );
105 				}
106 			}
107 		}
108         else {
109 			if ( nLevel ) {
110             	sLine = "}";
111 	            fprintf( stdout, "Reached EOF parsing %s. Suplying extra '}'\n",ByteString( sStreamName, gsl_getSystemTextEncoding()).GetBuffer() );
112 	//	        nErrorCode = IP_UNEXPECTED_EOF;
113 	//	        nErrorLine = nActLine;
114 			}
115 			else
116 				sLine = "";
117         }
118 
119 		sOldLine = sLine;
120 		nActLine++;
121 	}
122 
123 	return sOldLine;
124 }
125 
126 /*****************************************************************************/
ReadKey(GenericInformationList * pExistingList)127 GenericInformation *InformationParser::ReadKey(
128 									GenericInformationList *pExistingList )
129 /*****************************************************************************/
130 {
131 	// this method has no error handling yet, but it works very fast.
132 	// it is used to create whole informations and sub informations in
133 	// a simple data format in memory, readed in a configuration file with
134 	// following format:
135 
136 	/*
137 
138 	key [value]
139 	{
140 		key [value]
141 		key [value]
142 		{
143 			key [value]
144 			...
145 			...
146 		}
147 	}
148 	key [value]
149 	...
150 	...
151 
152 	*/
153 
154 	GenericInformation *pInfo = NULL;
155 
156 	ByteString sLine( ReadLine());
157 	ByteString sKey;
158 	ByteString sValue;
159 	ByteString sComment( sCurrentComment );
160 	sCurrentComment = "";
161 
162 	// key separated from value by tab?
163 	sal_uInt16 nWSPos = sLine.Search( ' ' );
164 	if ( sLine.Search( '\t' ) < nWSPos ) {
165 		nWSPos = sLine.Search( '\t' );
166 		sLine.SearchAndReplace( "\t", " " );
167 	}
168 
169 	if ( sLine.GetTokenCount( ' ' ) > 1 ) {
170 		sKey = sLine.GetToken( 0, ' ' );
171 		sValue = sLine.Copy( sKey.Len() + 1 );
172 		while (( sValue.Search( ' ' ) == 0 ) || ( sValue.Search( '\t' ) == 0 )) {
173 			sValue.Erase( 0, 1 );
174 		}
175 	}
176 	else
177 		sKey=sLine;
178 
179 	if ( bReplaceVariables && !nLevel ) {
180 		sUPD = sKey.Copy( sKey.Len() - 3 );
181 		sVersion = sKey;
182 	}
183 
184 	if ( ReadLine() == "{" ) {
185 		nLevel++;
186 		GenericInformationList *pSubList = new GenericInformationList();
187 		while ( ReadLine() != "}" ) {
188 			Recover();
189 			ReadKey( pSubList );
190 		}
191 		nLevel--;
192 		pInfo = new GenericInformation( sKey, sValue,
193 						pExistingList, pSubList );
194 		pInfo->SetComment( sComment );
195 	}
196 	else {
197 		Recover();
198         if ( !sKey.Equals( "}" ) && !sKey.Equals( "{" ) )
199         {
200 		    pInfo = new GenericInformation( sKey, sValue, pExistingList );
201 		    pInfo->SetComment( sComment );
202         }
203 	}
204 
205 	return pInfo;
206 }
207 
208 /*****************************************************************************/
Recover()209 void InformationParser::Recover()
210 /*****************************************************************************/
211 {
212 	bRecover = sal_True;
213 }
214 
215 /*****************************************************************************/
Save(SvStream & rOutStream,const GenericInformationList * pSaveList,sal_uInt16 level,sal_Bool bStripped)216 sal_Bool InformationParser::Save( SvStream &rOutStream,
217 			      const GenericInformationList *pSaveList,
218 			      sal_uInt16 level, sal_Bool bStripped )
219 /*****************************************************************************/
220 {
221 	sal_uInt16 i;
222 	sal_uIntPtr nInfoListCount;
223 	ByteString sTmpStr;
224 	GenericInformation *pGenericInfo;
225 	GenericInformationList *pGenericInfoList;
226 
227  	static ByteString aKeyLevel;
228     aKeyLevel.Expand( level, cKeyLevelChar );
229 
230 	for ( nInfoListCount = 0; nInfoListCount < pSaveList->Count(); nInfoListCount++) {
231 	    // Key-Value Paare schreiben
232     	pGenericInfo = pSaveList->GetObject( nInfoListCount );
233     	sTmpStr = "";
234         if ( !bStripped && level )
235         	sTmpStr.Append( aKeyLevel.GetBuffer(), level );
236 
237         if ( !bStripped )
238 		    for ( i = 0; i < pGenericInfo->GetComment().GetTokenCount( '\n' ); i++ ) {
239 			    sTmpStr += pGenericInfo->GetComment().GetToken( i, '\n' );
240 			    sTmpStr += "\n";
241                 if ( level )
242         	        sTmpStr.Append( aKeyLevel.GetBuffer(), level );
243 		    }
244 
245     	sTmpStr += pGenericInfo->GetBuffer();
246     	sTmpStr += ' ';
247     	sTmpStr += pGenericInfo->GetValue();
248     	if ( !rOutStream.WriteLine( sTmpStr ) )
249       		return sal_False;
250 
251     	// wenn vorhanden, bearbeite recursive die Sublisten
252     	if (( pGenericInfoList = pGenericInfo->GetSubList() ) != NULL ) {
253       		// oeffnende Klammer
254       		sTmpStr = "";
255             if ( !bStripped && level )
256         	    sTmpStr.Append( aKeyLevel.GetBuffer(), level );
257       		sTmpStr += '{';
258       		if ( !rOutStream.WriteLine( sTmpStr ) )
259 				return sal_False;
260       		// recursiv die sublist abarbeiten
261       		if ( !Save( rOutStream, pGenericInfoList, level+1, bStripped ) )
262     			return sal_False;
263       			// schliessende Klammer
264       		sTmpStr = "";
265             if ( !bStripped && level )
266         	    sTmpStr.Append( aKeyLevel.GetBuffer(), level );
267       		sTmpStr += '}';
268       		if ( !rOutStream.WriteLine( sTmpStr ) )
269 				return sal_False;
270     	}
271   	}
272   	return sal_True;
273 }
274 
275 /*****************************************************************************/
Execute(SvStream & rSourceStream,GenericInformationList * pExistingList)276 GenericInformationList *InformationParser::Execute(
277 								SvStream &rSourceStream,
278 								GenericInformationList *pExistingList )
279 /*****************************************************************************/
280 {
281 	GenericInformationList *pList;
282 	if ( pExistingList )
283 		pList = pExistingList;
284 	else
285 		pList = new GenericInformationList();
286 
287 	pActStream = &rSourceStream;
288 
289 	// read all infos out of current file
290 	while( !rSourceStream.IsEof()) {
291 		nLevel = 0;
292 		ReadKey( pList );
293 	}
294 
295 	return pList;
296 }
297 
298 /*****************************************************************************/
Execute(SvMemoryStream & rSourceStream,GenericInformationList * pExistingList)299 GenericInformationList *InformationParser::Execute( SvMemoryStream &rSourceStream,
300 						    GenericInformationList *pExistingList )
301 /*****************************************************************************/
302 {
303   	sStreamName = UniString( "Memory", gsl_getSystemTextEncoding());
304   	return Execute( (SvStream &)rSourceStream, pExistingList );
305 }
306 
307 /*****************************************************************************/
Execute(SvFileStream & rSourceStream,GenericInformationList * pExistingList)308 GenericInformationList *InformationParser::Execute(
309 								SvFileStream &rSourceStream,
310 								GenericInformationList *pExistingList )
311 /*****************************************************************************/
312 {
313 	if ( !rSourceStream.IsOpen())
314 		return NULL;
315 	sStreamName = rSourceStream.GetFileName();
316 	return Execute( (SvStream &)rSourceStream, pExistingList );
317 }
318 
319 /*****************************************************************************/
Execute(UniString & rSourceFile,GenericInformationList * pExistingList)320 GenericInformationList *InformationParser::Execute( UniString &rSourceFile,
321 								GenericInformationList *pExistingList )
322 /*****************************************************************************/
323 {
324 	DirEntry aDirEntry( rSourceFile );
325 	if ( !aDirEntry.Exists())
326 		return NULL;
327 
328 	GenericInformationList *pList;
329 	if ( pExistingList )
330 		pList = pExistingList;
331 	else
332 		pList = new GenericInformationList();
333 
334 	// reset status
335 	nErrorCode = 0;
336 	nErrorLine = 0;
337 	nActLine = 0;
338 
339 	SvFileStream aActStream;
340 	aActStream.Open( rSourceFile, STREAM_READ );
341 	if( aActStream.GetError())
342 		return NULL;
343 
344 	pActStream = &aActStream;
345 	if ( !Execute( aActStream, pList )) {
346 		delete pList;
347 		pList = NULL;
348 	}
349 
350 	// close the stream
351 	aActStream.Close();
352  	pActStream = NULL;
353 
354 	if ( !nErrorCode )
355 		return pList;
356 
357 	return NULL;
358 }
359 
360 /*****************************************************************************/
Execute(Dir & rDir,GenericInformationList * pExistingList)361 GenericInformationList *InformationParser::Execute( Dir &rDir,
362 								GenericInformationList *pExistingList )
363 /*****************************************************************************/
364 {
365 	GenericInformationList *pList;
366 
367 	if ( pExistingList )
368 		pList = pExistingList;
369 	else
370 		pList = new GenericInformationList();
371 
372 	for ( sal_uInt16 i = 0; i < rDir.Count(); i++ ) {
373 
374 		// execute this dir
375 		UniString sNextFile( rDir[i].GetFull());
376 		GenericInformationList *pSubList = Execute( sNextFile );
377 
378 		if ( !pSubList ) {
379 			// any errors ?
380 			delete pList;
381 			return NULL;
382 		}
383 
384 		// create new info and insert it into list
385 		ByteString sFileKey( rDir[i].GetName(), RTL_TEXTENCODING_UTF8 );
386 		new GenericInformation(
387 											sFileKey,
388 											ByteString( "" ),
389 											pList, pSubList );
390 	}
391 
392 	return pList;
393 }
394 
395 /*****************************************************************************/
Save(SvFileStream & rSourceStream,const GenericInformationList * pSaveList)396 sal_Bool InformationParser::Save( SvFileStream &rSourceStream,
397 			      const GenericInformationList *pSaveList )
398 /*****************************************************************************/
399 {
400 	if ( !rSourceStream.IsOpen() || !Save( (SvStream &)rSourceStream, pSaveList, 0, sal_False ))
401     {
402         printf( "ERROR saving file \"%s\"\n",ByteString( rSourceStream.GetFileName(), gsl_getSystemTextEncoding()).GetBuffer() );
403 		return sal_False;
404     }
405 
406 	return sal_True;
407 }
408 
409 /*****************************************************************************/
Save(SvMemoryStream & rSourceStream,const GenericInformationList * pSaveList)410 sal_Bool InformationParser::Save( SvMemoryStream &rSourceStream,
411 			      const GenericInformationList *pSaveList )
412 /*****************************************************************************/
413 {
414     Time a;
415     sal_Bool bRet = Save( (SvStream &)rSourceStream, pSaveList, 0, sal_True );
416     Time b;
417     b = b - a;
418     return bRet;
419 }
420 
421 /*****************************************************************************/
Save(const UniString & rSourceFile,const GenericInformationList * pSaveList)422 sal_Bool InformationParser::Save( const UniString &rSourceFile,
423 			      const GenericInformationList *pSaveList )
424 /*****************************************************************************/
425 {
426   SvFileStream *pOutFile = new SvFileStream( rSourceFile, STREAM_STD_WRITE | STREAM_TRUNC );
427 
428   if ( !Save( *pOutFile, pSaveList )) {
429     delete pOutFile;
430     return sal_False;
431   }
432   delete pOutFile;
433   return sal_True;
434 }
435 
436 /*****************************************************************************/
GetErrorCode()437 sal_uInt16 InformationParser::GetErrorCode()
438 /*****************************************************************************/
439 {
440 	return nErrorCode;
441 }
442 
443 /*****************************************************************************/
GetErrorText()444 ByteString &InformationParser::GetErrorText()
445 /*****************************************************************************/
446 {
447   //	sErrorText = pActStream->GetFileName();
448     sErrorText = ByteString( sStreamName, gsl_getSystemTextEncoding());
449 	sErrorText += ByteString( " (" );
450 	sErrorText += ByteString::CreateFromInt64(nErrorLine);
451 	sErrorText += ByteString( "): " );
452 
453 	switch ( nErrorCode ) {
454 	case IP_NO_ERROR:
455 		sErrorText += ByteString( "Keine Fehler aufgetereten" );
456 		break;
457 	case IP_UNEXPECTED_EOF:
458 		sErrorText += ByteString( "Ung�ltiges Dateiende!" );
459 		break;
460 	}
461 
462 	return sErrorText;
463 }
464 
465 
466