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 /*****************************************************************************/ 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 /*****************************************************************************/ 60 InformationParser::~InformationParser() 61 /*****************************************************************************/ 62 { 63 } 64 65 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 209 void InformationParser::Recover() 210 /*****************************************************************************/ 211 { 212 bRecover = sal_True; 213 } 214 215 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 437 sal_uInt16 InformationParser::GetErrorCode() 438 /*****************************************************************************/ 439 { 440 return nErrorCode; 441 } 442 443 /*****************************************************************************/ 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