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