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