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