xref: /trunk/main/soltools/giparser/gi_parse.cxx (revision cdf0e10c)
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