1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <memory>
21 #include <hash.hxx>
22 #include <lex.hxx>
23 #include <globals.hxx>
24 #include <rtl/strbuf.hxx>
25 #include<rtl/character.hxx>
26 
GetTokenAsString() const27 OString SvToken::GetTokenAsString() const
28 {
29     OString aStr;
30     switch( nType )
31     {
32         case SVTOKENTYPE::Empty:
33             break;
34         case SVTOKENTYPE::Comment:
35             aStr = aString;
36             break;
37         case SVTOKENTYPE::Integer:
38             aStr = OString::number(nLong);
39             break;
40         case SVTOKENTYPE::String:
41             aStr = aString;
42             break;
43         case SVTOKENTYPE::Bool:
44             aStr = bBool ? "TRUE" : "FALSE";
45             break;
46         case SVTOKENTYPE::Identifier:
47             aStr = aString;
48             break;
49         case SVTOKENTYPE::Char:
50             aStr = OString(cChar);
51             break;
52         case SVTOKENTYPE::EndOfFile:
53         case SVTOKENTYPE::HashId:
54             break;
55     }
56 
57     return aStr;
58 }
59 
operator =(const SvToken & rObj)60 SvToken & SvToken::operator = ( const SvToken & rObj )
61 {
62     if( this != &rObj )
63     {
64         nLine = rObj.nLine;
65         nColumn = rObj.nColumn;
66         nType = rObj.nType;
67         aString = rObj.aString;
68         nLong = rObj.nLong;
69     }
70     return *this;
71 }
72 
InitCtor()73 void SvTokenStream::InitCtor()
74 {
75     aStrTrue = OString("TRUE");
76     aStrFalse = OString("FALSE");
77     nLine       = nColumn = 0;
78     nBufPos     = 0;
79     nMaxPos     = 0;
80     c           = GetNextChar();
81     FillTokenList();
82 }
83 
SvTokenStream(const OUString & rFileName)84 SvTokenStream::SvTokenStream( const OUString & rFileName )
85     : pInStream( new SvFileStream( rFileName, StreamMode::STD_READ ) )
86     , aFileName( rFileName )
87 {
88     InitCtor();
89 }
90 
~SvTokenStream()91 SvTokenStream::~SvTokenStream()
92 {
93 }
94 
FillTokenList()95 void SvTokenStream::FillTokenList()
96 {
97     SvToken * pToken = new SvToken();
98     aTokList.push_back(std::unique_ptr<SvToken>(pToken));
99     do
100     {
101         if( !MakeToken( *pToken ) )
102         {
103             if (!aTokList.empty())
104             {
105                 *pToken = SvToken();
106                 std::vector<std::unique_ptr<SvToken> >::const_iterator it = aTokList.begin();
107 
108                 pToken->SetLine((*it)->GetLine());
109                 pToken->SetColumn((*it)->GetColumn());
110             }
111             break;
112         }
113         else if( pToken->IsComment() )
114             *pToken = SvToken();
115         else if( pToken->IsEof() )
116             break;
117         else
118         {
119             pToken = new SvToken();
120             aTokList.push_back(std::unique_ptr<SvToken>(pToken));
121         }
122     }
123     while( !pToken->IsEof() );
124     pCurToken = aTokList.begin();
125 }
126 
GetNextChar()127 char SvTokenStream::GetNextChar()
128 {
129     char nChar;
130     while (aBufStr.getLength() <= nBufPos)
131     {
132         if (pInStream->ReadLine(aBufStr))
133         {
134             nLine++;
135             nColumn = 0;
136             nBufPos = 0;
137         }
138         else
139         {
140             aBufStr.clear();
141             nColumn = 0;
142             nBufPos = 0;
143             return '\0';
144         }
145     }
146     nChar = aBufStr[nBufPos++];
147     nColumn += nChar == '\t' ? nTabSize : 1;
148     return nChar;
149 }
150 
GetNumber()151 sal_uInt64 SvTokenStream::GetNumber()
152 {
153     sal_uInt64   l = 0;
154     short   nLog = 10;
155 
156     if( '0' == c )
157     {
158         c = GetFastNextChar();
159         if( 'x' == c )
160         {
161             nLog = 16;
162             c = GetFastNextChar();
163         }
164     }
165 
166     if( nLog == 16 )
167     {
168         while( rtl::isAsciiHexDigit( static_cast<unsigned char>(c) ) )
169         {
170             if( rtl::isAsciiDigit( static_cast<unsigned char>(c) ) )
171                 l = l * nLog + (c - '0');
172             else
173                 l = l * nLog
174                     + (rtl::toAsciiUpperCase( static_cast<unsigned char>(c) )
175                        - 'A' + 10 );
176             c = GetFastNextChar();
177         }
178     }
179     else
180     {
181         while( rtl::isAsciiDigit( static_cast<unsigned char>(c) ) || 'x' == c )
182         {
183             l = l * nLog + (c - '0');
184             c = GetFastNextChar();
185         }
186     }
187 
188     return l;
189 }
190 
MakeToken(SvToken & rToken)191 bool SvTokenStream::MakeToken( SvToken & rToken )
192 {
193     do
194     {
195         if( 0 == c )
196             c = GetNextChar();
197         // skip whitespace
198         while( rtl::isAsciiWhiteSpace( static_cast<unsigned char>(c) )
199                || 26 == c )
200         {
201             c = GetFastNextChar();
202             nColumn += c == '\t' ? nTabSize : 1;
203         }
204     }
205     while( 0 == c && !IsEof() && ( ERRCODE_NONE == pInStream->GetError() ) );
206 
207     sal_uInt64 nLastLine     = nLine;
208     sal_uInt64 nLastColumn   = nColumn;
209     // comment
210     if( '/' == c )
211     {
212         // time optimization, no comments
213         char c1 = c;
214         c = GetFastNextChar();
215         if( '/' == c )
216         {
217             while( '\0' != c )
218             {
219                 c = GetFastNextChar();
220             }
221             c = GetNextChar();
222             rToken.nType    = SVTOKENTYPE::Comment;
223         }
224         else if( '*' == c )
225         {
226             c = GetFastNextChar();
227             do
228             {
229                 while( '*' != c )
230                 {
231                     if( '\0' == c )
232                     {
233                         c = GetNextChar();
234                         if( IsEof() )
235                             return false;
236                     }
237                     else
238                         c = GetFastNextChar();
239                 }
240                 c = GetFastNextChar();
241             }
242             while( '/' != c && !IsEof() && ( ERRCODE_NONE == pInStream->GetError() ) );
243             if( IsEof() || ( ERRCODE_NONE != pInStream->GetError() ) )
244                 return false;
245             c = GetNextChar();
246             rToken.nType = SVTOKENTYPE::Comment;
247             CalcColumn();
248         }
249         else
250         {
251             rToken.nType = SVTOKENTYPE::Char;
252             rToken.cChar = c1;
253         }
254     }
255     else if( c == '"' )
256     {
257         OStringBuffer aStr(128);
258         bool bDone = false;
259         while( !bDone && !IsEof() && c )
260         {
261             c = GetFastNextChar();
262             if( '\0' == c )
263             {
264                 // read strings beyond end of line
265                 aStr.append('\n');
266                 c = GetNextChar();
267                 if( IsEof() )
268                     return false;
269             }
270             if( c == '"' )
271             {
272                 c = GetFastNextChar();
273                 bDone = true;
274             }
275             else
276                 aStr.append(c);
277         }
278         if( IsEof() || ( ERRCODE_NONE != pInStream->GetError() ) )
279             return false;
280         rToken.nType   = SVTOKENTYPE::String;
281         rToken.aString = aStr.makeStringAndClear();
282     }
283     else if( rtl::isAsciiDigit( static_cast<unsigned char>(c) ) )
284     {
285         rToken.nType = SVTOKENTYPE::Integer;
286         rToken.nLong = GetNumber();
287 
288     }
289     else if( rtl::isAsciiAlpha (static_cast<unsigned char>(c)) || (c == '_') )
290     {
291         OStringBuffer aBuf(64);
292         while( rtl::isAsciiAlphanumeric( static_cast<unsigned char>(c) )
293                || c == '_' || c == ':')
294         {
295             aBuf.append(c);
296             c = GetFastNextChar();
297         }
298         OString aStr = aBuf.makeStringAndClear();
299         if( aStr.equalsIgnoreAsciiCase( aStrTrue ) )
300         {
301             rToken.nType = SVTOKENTYPE::Bool;
302             rToken.bBool = true;
303         }
304         else if( aStr.equalsIgnoreAsciiCase( aStrFalse ) )
305         {
306             rToken.nType = SVTOKENTYPE::Bool;
307             rToken.bBool = false;
308         }
309         else
310         {
311             sal_uInt32 nHashId;
312             if( GetIdlApp().pHashTable->Test( aStr, &nHashId ) )
313                 rToken.SetHash( GetIdlApp().pHashTable->Get( nHashId ) );
314             else
315             {
316                 rToken.nType   = SVTOKENTYPE::Identifier;
317                 rToken.aString = aStr;
318             }
319         }
320     }
321     else if( IsEof() )
322     {
323         rToken.nType = SVTOKENTYPE::EndOfFile;
324     }
325     else
326     {
327         rToken.nType = SVTOKENTYPE::Char;
328         rToken.cChar = c;
329         c = GetFastNextChar();
330     }
331     rToken.SetLine( nLastLine );
332     rToken.SetColumn( nLastColumn );
333     return pInStream->GetError() == ERRCODE_NONE;
334 }
335 
336 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
337