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_soltools.hxx" 30 31 #include <gi_parse.hxx> 32 33 #include <stdio.h> 34 #include <string.h> 35 #include <fstream> 36 #include <gilacces.hxx> 37 38 39 using namespace std; 40 41 42 const char * C_sLineEnd = "\r\n"; 43 44 45 46 inline void 47 WriteStr( ostream & o_rOut, const Simstr & i_rStr ) 48 { 49 o_rOut.write( i_rStr.str(), i_rStr.l() ); 50 } 51 52 inline void 53 WriteStr( ostream & o_rOut, const char * i_rStr ) 54 { 55 o_rOut.write( i_rStr, strlen(i_rStr) ); 56 } 57 58 inline void 59 GenericInfo_Parser::SetError( E_Error i_eError ) 60 { 61 eErrorCode = i_eError; 62 nErrorLine = nCurLine; 63 } 64 65 66 GenericInfo_Parser::GenericInfo_Parser() 67 : sCurParsePosition(""), 68 nCurLine(0), 69 nLevel(0), 70 bGoon(false), 71 // sCurComment, 72 eErrorCode(ok), 73 nErrorLine(0), 74 pResult(0), 75 pResource(0) 76 { 77 } 78 79 GenericInfo_Parser::~GenericInfo_Parser() 80 { 81 } 82 83 bool 84 GenericInfo_Parser::LoadList( GenericInfoList_Builder & o_rResult, 85 const Simstr & i_sSourceFileName ) 86 { 87 ifstream aFile( i_sSourceFileName.str() ); 88 if ( aFile.fail() ) 89 { 90 SetError(cannot_open); 91 return false; 92 } 93 94 aFile.seekg(0, ios::end); 95 UINT32 nTextSize = aFile.tellg(); 96 if ( nTextSize == 0 || nTextSize == UINT32(-1) ) 97 return true; 98 dpBuffer = new char[nTextSize+2]; 99 100 aFile.seekg(0); 101 aFile.read( dpBuffer, nTextSize ); 102 aFile.close(); 103 104 sFilePtr = dpBuffer; 105 char * sLastChar = dpBuffer + nTextSize - 1; 106 107 while ( sFilePtr != sLastChar && *sFilePtr <= 32 ) 108 ++sCurParsePosition; 109 if ( sFilePtr == sLastChar ) 110 { 111 if ( *sFilePtr <= 32 ) 112 return true; 113 } 114 else while ( *sLastChar <= 32 ) 115 { 116 --sLastChar; 117 } 118 119 *(sLastChar+1) = '\n'; 120 *(sLastChar+2) = '\0'; 121 122 ResetState(o_rResult); 123 124 for ( ReadLine(); bGoon; ReadLine() ) 125 { 126 bool bOk = InterpretLine(); 127 if ( !bOk) 128 { 129 SetError(syntax_error); 130 break; 131 } 132 } 133 134 if ( nLevel > 0 && eErrorCode == ok) 135 { 136 SetError(unexpected_eof); 137 } 138 else if ( nLevel < 0 ) 139 { 140 SetError(unexpected_list_end); 141 } 142 143 delete [] dpBuffer; 144 dpBuffer = 0; 145 sFilePtr = 0; 146 147 return eErrorCode == ok; 148 } 149 150 bool 151 GenericInfo_Parser::SaveList( const Simstr & i_rOutputFile, 152 GenericInfoList_Browser & io_rListBrowser ) 153 { 154 ofstream aFile( i_rOutputFile.str() ); 155 if ( aFile.fail() ) 156 { 157 SetError(cannot_open); 158 return false; 159 } 160 161 ResetState(io_rListBrowser); 162 163 WriteList(aFile); 164 165 aFile.close(); 166 return eErrorCode == ok; 167 } 168 169 void 170 GenericInfo_Parser::ResetState( GenericInfoList_Builder & io_rResult ) 171 { 172 sCurParsePosition = ""; 173 nCurLine = 0; 174 nLevel = 0; 175 bGoon = true; 176 sCurComment = ""; 177 eErrorCode = ok; 178 nErrorLine = 0; 179 pResult = &io_rResult; 180 pResource = 0; 181 } 182 183 void 184 GenericInfo_Parser::ResetState( GenericInfoList_Browser & io_rSrc ) 185 { 186 sCurParsePosition = ""; 187 nCurLine = 0; 188 nLevel = 0; 189 bGoon = false; 190 sCurComment = ""; 191 eErrorCode = ok; 192 nErrorLine = 0; 193 pResult = 0; 194 pResource = &io_rSrc; 195 } 196 197 198 void 199 GenericInfo_Parser::ReadLine() 200 { 201 if ( *sFilePtr == '\0' ) // See initialising of dpBuffer and sLastChar in LoadList(). 202 { 203 bGoon = false; 204 return; 205 } 206 207 sCurParsePosition = sFilePtr; 208 while ( *sFilePtr != '\n' ) 209 ++sFilePtr; 210 nCurLine++; 211 212 // Remove leading and trailing whitespace from line: 213 while ( sCurParsePosition != sFilePtr && *sCurParsePosition <= 32 ) 214 ++sCurParsePosition; 215 216 char * sEndOfLine = sFilePtr; 217 while ( sEndOfLine != sCurParsePosition && *sEndOfLine <= 32 ) 218 --sEndOfLine; 219 if ( sCurParsePosition != sEndOfLine || *sCurParsePosition > 32 ) 220 ++sEndOfLine; 221 *sEndOfLine = '\0'; 222 223 ++sFilePtr; // Go beyond line end to first character of next line. 224 } 225 226 bool 227 GenericInfo_Parser::InterpretLine() 228 { 229 switch ( ClassifyLine() ) 230 { 231 case lt_key: ReadKey(); 232 break; 233 case lt_open_list: PushLevel_Read(); 234 break; 235 case lt_close_list: PopLevel_Read(); 236 break; 237 case lt_comment: AddCurLine2CurComment(); 238 break; 239 case lt_empty: AddCurLine2CurComment(); 240 break; 241 default: 242 return false; 243 } 244 return true; 245 } 246 247 GenericInfo_Parser::E_LineType 248 GenericInfo_Parser::ClassifyLine() 249 { 250 switch ( *sCurParsePosition ) 251 { 252 case '{': return lt_open_list; 253 case '}': return lt_close_list; 254 case '#': return lt_comment; 255 case '\0': return lt_empty; 256 } 257 258 return lt_key; 259 } 260 261 void 262 GenericInfo_Parser::ReadKey() 263 { 264 const char * pSearch = sCurParsePosition; 265 266 for ( ; *pSearch > 32; ++pSearch ) ; 267 UINT32 nKeyLength = pSearch - sCurParsePosition; 268 269 for ( ; *pSearch <= 32 && *pSearch > '\0'; ++pSearch ) ; 270 271 pResult->AddKey( sCurParsePosition, nKeyLength, 272 pSearch, strlen(pSearch), 273 sCurComment.str(), sCurComment.l() 274 ); 275 sCurComment = ""; 276 } 277 278 void 279 GenericInfo_Parser::PushLevel_Read() 280 { 281 nLevel++; 282 pResult->OpenList(); 283 } 284 285 void 286 GenericInfo_Parser::PopLevel_Read() 287 { 288 nLevel--; 289 pResult->CloseList(); 290 } 291 292 void 293 GenericInfo_Parser::AddCurLine2CurComment() 294 { 295 sCurComment += sCurParsePosition; 296 sCurComment += C_sLineEnd; 297 } 298 299 void 300 GenericInfo_Parser::WriteList( ostream & o_rFile ) 301 { 302 static char sBuffer[32000]; 303 304 for ( bGoon = pResource->Start_CurList(); 305 bGoon; 306 bGoon = pResource->NextOf_CurList() ) 307 { 308 pResource->Get_CurComment(&sBuffer[0]); 309 WriteComment(o_rFile,sBuffer); 310 311 pResource->Get_CurKey(&sBuffer[0]); 312 WriteKey(o_rFile,sBuffer); 313 314 pResource->Get_CurValue(&sBuffer[0]); 315 WriteValue(o_rFile,sBuffer); 316 317 if ( pResource->HasSubList_CurKey() ) 318 { 319 PushLevel_Write(); 320 321 /* 322 WriteIndentation(); 323 o_rFile.write("{",1); 324 o_rFile.write(C_sLineEnd, C_nLineEndLength); 325 */ 326 WriteList(o_rFile); 327 328 /* 329 WriteIndentation(); 330 o_rFile.write("}",1); 331 o_rFile.write(C_sLineEnd, C_nLineEndLength); 332 */ 333 PopLevel_Write(); 334 } 335 } // end for 336 } 337 338 void 339 GenericInfo_Parser::PushLevel_Write() 340 { 341 nLevel++; 342 pResource->Push_CurList(); 343 } 344 345 void 346 GenericInfo_Parser::PopLevel_Write() 347 { 348 nLevel--; 349 pResource->Pop_CurList(); 350 } 351 352 void 353 GenericInfo_Parser::WriteComment( ostream & o_rFile, 354 const char * i_sStr ) 355 { 356 WriteStr( o_rFile, i_sStr ); 357 if ( i_sStr[ strlen(i_sStr)-1 ] != '\n' ) 358 WriteStr( o_rFile, C_sLineEnd ); 359 } 360 361 void 362 GenericInfo_Parser::WriteKey( ostream & o_rFile, 363 const char * i_sStr ) 364 { 365 WriteIndentation(o_rFile); 366 WriteStr( o_rFile, i_sStr ); 367 } 368 369 void 370 GenericInfo_Parser::WriteValue( ostream & o_rFile, 371 const char * i_sStr ) 372 { 373 if ( i_sStr != 0 ? strlen(i_sStr) > 0 : false ) 374 { 375 WriteStr(o_rFile," "); 376 WriteStr(o_rFile,i_sStr); 377 } 378 379 WriteStr(o_rFile,C_sLineEnd); 380 } 381 382 void 383 GenericInfo_Parser::WriteIndentation( ostream & o_rFile ) 384 { 385 const int nIndentBound = 60; 386 387 static const char sIndentation[nIndentBound+1] = 388 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" 389 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" 390 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; 391 392 if ( nLevel == 0 ) 393 return; 394 395 if ( nLevel <= nIndentBound ) 396 o_rFile.write( sIndentation, nLevel ); 397 else 398 { 399 INT16 iLevel = nLevel; 400 for ( ; iLevel > nIndentBound; iLevel-=nIndentBound ) 401 o_rFile.write( sIndentation, nIndentBound ); 402 o_rFile.write( sIndentation, iLevel ); 403 } 404 } 405 406 407 408