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