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
WriteStr(ostream & o_rOut,const Simstr & i_rStr)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
WriteStr(ostream & o_rOut,const char * i_rStr)49 WriteStr( ostream & o_rOut, const char * i_rStr )
50 {
51 o_rOut.write( i_rStr, strlen(i_rStr) );
52 }
53
54 inline void
SetError(E_Error i_eError)55 GenericInfo_Parser::SetError( E_Error i_eError )
56 {
57 eErrorCode = i_eError;
58 nErrorLine = nCurLine;
59 }
60
61
GenericInfo_Parser()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
~GenericInfo_Parser()75 GenericInfo_Parser::~GenericInfo_Parser()
76 {
77 }
78
79 bool
LoadList(GenericInfoList_Builder & o_rResult,const Simstr & i_sSourceFileName)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
SaveList(const Simstr & i_rOutputFile,GenericInfoList_Browser & io_rListBrowser)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
ResetState(GenericInfoList_Builder & io_rResult)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
ResetState(GenericInfoList_Browser & io_rSrc)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
ReadLine()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
InterpretLine()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
ClassifyLine()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
ReadKey()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
PushLevel_Read()275 GenericInfo_Parser::PushLevel_Read()
276 {
277 nLevel++;
278 pResult->OpenList();
279 }
280
281 void
PopLevel_Read()282 GenericInfo_Parser::PopLevel_Read()
283 {
284 nLevel--;
285 pResult->CloseList();
286 }
287
288 void
AddCurLine2CurComment()289 GenericInfo_Parser::AddCurLine2CurComment()
290 {
291 sCurComment += sCurParsePosition;
292 sCurComment += C_sLineEnd;
293 }
294
295 void
WriteList(ostream & o_rFile)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
PushLevel_Write()335 GenericInfo_Parser::PushLevel_Write()
336 {
337 nLevel++;
338 pResource->Push_CurList();
339 }
340
341 void
PopLevel_Write()342 GenericInfo_Parser::PopLevel_Write()
343 {
344 nLevel--;
345 pResource->Pop_CurList();
346 }
347
348 void
WriteComment(ostream & o_rFile,const char * i_sStr)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
WriteKey(ostream & o_rFile,const char * i_sStr)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
WriteValue(ostream & o_rFile,const char * i_sStr)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
WriteIndentation(ostream & o_rFile)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