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() const27OString 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)60SvToken & 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()73void 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)84SvTokenStream::SvTokenStream( const OUString & rFileName ) 85 : pInStream( new SvFileStream( rFileName, StreamMode::STD_READ ) ) 86 , aFileName( rFileName ) 87 { 88 InitCtor(); 89 } 90 ~SvTokenStream()91SvTokenStream::~SvTokenStream() 92 { 93 } 94 FillTokenList()95void 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()127char 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()151sal_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)191bool 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