LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/writerfilter/source/rtftok - rtftokenizer.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 163 187 87.2 %
Date: 2013-07-09 Functions: 15 15 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      10             : #include <tools/stream.hxx>
      11             : #include <tools/resmgr.hxx>
      12             : #include <svx/dialogs.hrc>
      13             : #include <vcl/svapp.hxx>
      14             : #include <rtl/strbuf.hxx>
      15             : 
      16             : #include <rtftokenizer.hxx>
      17             : #include <rtfskipdestination.hxx>
      18             : #include <com/sun/star/io/BufferSizeExceededException.hpp>
      19             : 
      20             : using namespace com::sun::star;
      21             : 
      22             : namespace writerfilter {
      23             : namespace rtftok {
      24             : 
      25           8 : std::vector<RTFSymbol> RTFTokenizer::m_aRTFControlWords;
      26             : bool RTFTokenizer::m_bControlWordsSorted;
      27             : 
      28         207 : RTFTokenizer::RTFTokenizer(RTFListener& rImport, SvStream* pInStream, uno::Reference<task::XStatusIndicator> const& xStatusIndicator)
      29             :     : m_rImport(rImport),
      30             :     m_pInStream(pInStream),
      31             :     m_xStatusIndicator(xStatusIndicator),
      32             :     m_nGroup(0),
      33             :     m_nLineNumber(0),
      34             :     m_nLineStartPos(0),
      35         207 :     m_nGroupStart(0)
      36             : {
      37         207 :     if (!RTFTokenizer::m_bControlWordsSorted)
      38             :     {
      39           4 :         RTFTokenizer::m_bControlWordsSorted = true;
      40           4 :         m_aRTFControlWords = std::vector<RTFSymbol>(aRTFControlWords, aRTFControlWords + nRTFControlWords);
      41           4 :         std::sort(m_aRTFControlWords.begin(), m_aRTFControlWords.end());
      42             :     }
      43         207 : }
      44             : 
      45         414 : RTFTokenizer::~RTFTokenizer()
      46             : {
      47         414 : }
      48             : 
      49     1108726 : SvStream& RTFTokenizer::Strm()
      50             : {
      51     1108726 :     return *m_pInStream;
      52             : }
      53             : 
      54         207 : int RTFTokenizer::resolveParse()
      55             : {
      56             :     SAL_INFO( "writerfilter", OSL_THIS_FUNC );
      57             :     char ch;
      58             :     int ret;
      59             :     // for hex chars
      60         207 :     int b = 0, count = 2;
      61         207 :     sal_uInt32 nPercentSize = 0;
      62         207 :     sal_uInt32 nLastPos = 0;
      63             : 
      64         207 :     if (m_xStatusIndicator.is())
      65             :     {
      66         188 :         static ResMgr* pResMgr = ResMgr::CreateResMgr("svx", Application::GetSettings().GetUILanguageTag());
      67         188 :         OUString sDocLoad(ResId(RID_SVXSTR_DOC_LOAD, *pResMgr).toString());
      68             : 
      69         188 :         sal_uInt32 nCurrentPos = Strm().Tell();
      70         188 :         Strm().Seek(STREAM_SEEK_TO_END);
      71         188 :         sal_uInt32 nEndPos = Strm().Tell();
      72         188 :         Strm().Seek(nCurrentPos);
      73         188 :         m_xStatusIndicator->start(sDocLoad, nEndPos);
      74         188 :         nPercentSize = nEndPos / 100;
      75             : 
      76         188 :         m_xStatusIndicator->setValue(nLastPos = nCurrentPos);
      77             :     }
      78             : 
      79      143483 :     while ((Strm() >> ch, !Strm().IsEof()))
      80             :     {
      81             :         //SAL_INFO("writerfilter", OSL_THIS_FUNC << ": parsing character '" << ch << "'");
      82             : 
      83      143274 :         sal_uInt32 nCurrentPos = Strm().Tell();
      84      143274 :         if (m_xStatusIndicator.is() && nCurrentPos > (nLastPos + nPercentSize))
      85        8200 :             m_xStatusIndicator->setValue(nLastPos = nCurrentPos);
      86             : 
      87      143274 :         if (m_nGroup < 0)
      88           0 :             return ERROR_GROUP_UNDER;
      89      143274 :         if (m_nGroup > 0 && m_rImport.getInternalState() == INTERNAL_BIN)
      90             :         {
      91           1 :             ret = m_rImport.resolveChars(ch);
      92           1 :             if (ret)
      93           0 :                 return ret;
      94             :         }
      95             :         else
      96             :         {
      97      143273 :             switch (ch)
      98             :             {
      99             :                 case '{':
     100        7446 :                     m_nGroupStart = Strm().Tell() - 1;
     101        7446 :                     ret = m_rImport.pushState();
     102        7446 :                     if (ret)
     103           0 :                         return ret;
     104        7446 :                     break;
     105             :                 case '}':
     106        7443 :                     ret = m_rImport.popState();
     107        7443 :                     if (ret)
     108           0 :                         return ret;
     109        7443 :                     if (m_nGroup == 0)
     110             :                     {
     111         204 :                         if (m_rImport.isSubstream())
     112          13 :                             m_rImport.finishSubstream();
     113         204 :                         return 0;
     114             :                     }
     115        7239 :                     break;
     116             :                 case '\\':
     117       65410 :                     ret = resolveKeyword();
     118       65409 :                     if (ret)
     119           0 :                         return ret;
     120       65409 :                     break;
     121             :                 case 0x0d:
     122        3401 :                     break; // ignore this
     123             :                 case 0x0a:
     124        6684 :                     m_nLineNumber++;
     125        6684 :                     m_nLineStartPos = nCurrentPos;
     126        6684 :                     break;
     127             :                 default:
     128       52889 :                     if (m_nGroup == 0)
     129           0 :                         return ERROR_CHAR_OVER;
     130       52889 :                     if (m_rImport.getInternalState() == INTERNAL_NORMAL)
     131             :                     {
     132        5991 :                         ret = m_rImport.resolveChars(ch);
     133        5991 :                         if (ret)
     134           0 :                             return ret;
     135             :                     }
     136             :                     else
     137             :                     {
     138             :                         SAL_INFO("writerfilter", OSL_THIS_FUNC << ": hex internal state");
     139       46898 :                         b = b << 4;
     140       46898 :                         sal_Int8 parsed = asHex(ch);
     141       46898 :                         if (parsed == -1)
     142           0 :                             return ERROR_HEX_INVALID;
     143       46898 :                         b += parsed;
     144       46898 :                         count--;
     145       46898 :                         if (!count)
     146             :                         {
     147       23449 :                             ret = m_rImport.resolveChars(b);
     148       23449 :                             if (ret)
     149           0 :                                 return ret;
     150       23449 :                             count = 2;
     151       23449 :                             b = 0;
     152       23449 :                             m_rImport.setInternalState(INTERNAL_NORMAL);
     153             :                         }
     154             :                     }
     155       52889 :                     break;
     156             :             }
     157             :         }
     158             :     }
     159             : 
     160           2 :     if (m_nGroup < 0)
     161           0 :         return ERROR_GROUP_UNDER;
     162           2 :     else if (m_nGroup > 0)
     163           2 :         return ERROR_GROUP_OVER;
     164           0 :     return 0;
     165             : }
     166             : 
     167       92640 : int RTFTokenizer::asHex(char ch)
     168             : {
     169       92640 :     int ret = 0;
     170       92640 :     if (isdigit(ch))
     171       69831 :         ret = ch - '0';
     172             :     else
     173             :     {
     174       22809 :         if (islower(ch))
     175             :         {
     176       22809 :             if (ch < 'a' || ch > 'f')
     177           0 :                 return -1;
     178       22809 :             ret = ch - 'a';
     179             :         }
     180             :         else
     181             :         {
     182           0 :             if (ch < 'A' || ch > 'F')
     183           0 :                 return -1;
     184           0 :             ret = ch - 'A';
     185             :         }
     186       22809 :         ret += 10;
     187             :     }
     188       92640 :     return ret;
     189             : }
     190             : 
     191        7392 : int RTFTokenizer::getGroup() const
     192             : {
     193        7392 :     return m_nGroup;
     194             : }
     195             : 
     196        7446 : void RTFTokenizer::pushGroup()
     197             : {
     198        7446 :     m_nGroup++;
     199        7446 : }
     200             : 
     201        7443 : void RTFTokenizer::popGroup()
     202             : {
     203        7443 :     m_nGroup--;
     204        7443 : }
     205             : 
     206       65410 : int RTFTokenizer::resolveKeyword()
     207             : {
     208             :     char ch;
     209       65410 :     OStringBuffer aBuf;
     210       65410 :     bool bNeg = false;
     211       65410 :     bool bParam = false;
     212       65410 :     int nParam = 0;
     213             : 
     214       65410 :     Strm() >> ch;
     215       65410 :     if (Strm().IsEof())
     216           0 :         return ERROR_EOF;
     217             : 
     218       65410 :     if (!isalpha(ch))
     219             :     {
     220       24451 :         aBuf.append(ch);
     221       24451 :         OString aKeyword = aBuf.makeStringAndClear();
     222             :         // control symbols aren't followed by a space, so we can return here
     223             :         // without doing any SeekRel()
     224       24451 :         return dispatchKeyword(aKeyword, bParam, nParam);
     225             :     }
     226      285105 :     while(isalpha(ch))
     227             :     {
     228      203188 :         aBuf.append(ch);
     229      203188 :         Strm() >> ch;
     230      203188 :         if (Strm().IsEof())
     231             :         {
     232           1 :             ch = ' ';
     233           1 :             break;
     234             :         }
     235             :     }
     236       40959 :     if (aBuf.getLength() > 32)
     237             :         // See RTF spec v1.9.1, page 7
     238             :         // A control word's name cannot be longer than 32 letters.
     239           1 :         throw io::BufferSizeExceededException();
     240             : 
     241       40958 :     if (ch == '-')
     242             :     {
     243             :         // in case we'll have a parameter, that will be negative
     244         193 :         bNeg = true;
     245         193 :         Strm() >> ch;
     246         193 :         if (Strm().IsEof())
     247           0 :             return ERROR_EOF;
     248             :     }
     249       40958 :     if (isdigit(ch))
     250             :     {
     251       23010 :         OStringBuffer aParameter;
     252             : 
     253             :         // we have a parameter
     254       23010 :         bParam = true;
     255       97400 :         while(isdigit(ch))
     256             :         {
     257       51380 :             aParameter.append(ch);
     258       51380 :             Strm() >> ch;
     259       51380 :             if (Strm().IsEof())
     260             :             {
     261           0 :                 ch = ' ';
     262           0 :                 break;
     263             :             }
     264             :         }
     265       23010 :         nParam = aParameter.makeStringAndClear().toInt32();
     266       23010 :         if (bNeg)
     267         193 :             nParam = -nParam;
     268             :     }
     269       40958 :     if (ch != ' ')
     270       30358 :         Strm().SeekRel(-1);
     271       81916 :     OString aKeyword = aBuf.makeStringAndClear();
     272      106368 :     return dispatchKeyword(aKeyword, bParam, nParam);
     273             : }
     274             : 
     275       65409 : int RTFTokenizer::dispatchKeyword(OString& rKeyword, bool bParam, int nParam)
     276             : {
     277       65409 :     if (m_rImport.getDestinationState() == DESTINATION_SKIP)
     278        3525 :         return 0;
     279             :     /*SAL_INFO("writefilter", OSL_THIS_FUNC << ": keyword '\\" << rKeyword.getStr() <<
     280             :                "' with param? " << (bParam ? 1 : 0) <<" param val: '" << (bParam ? nParam : 0) << "'");*/
     281             :     RTFSymbol aSymbol;
     282       61884 :     aSymbol.sKeyword = rKeyword.getStr();
     283       61884 :     std::vector<RTFSymbol>::iterator low = std::lower_bound(m_aRTFControlWords.begin(), m_aRTFControlWords.end(), aSymbol);
     284       61884 :     int i = low - m_aRTFControlWords.begin();
     285       61884 :     if (low == m_aRTFControlWords.end() || aSymbol < *low)
     286             :     {
     287             :         SAL_INFO("writerfilter", OSL_THIS_FUNC << ": unknown keyword '\\" << rKeyword.getStr() << "'");
     288         273 :         RTFSkipDestination aSkip(m_rImport);
     289         273 :         aSkip.setParsed(false);
     290         273 :         return 0;
     291             :     }
     292             : 
     293             :     int ret;
     294       61611 :     switch (m_aRTFControlWords[i].nControlType)
     295             :     {
     296             :         case CONTROL_FLAG:
     297             :             // flags ignore any parameter by definition
     298       11295 :             ret = m_rImport.dispatchFlag(m_aRTFControlWords[i].nIndex);
     299       11295 :             if (ret)
     300           0 :                 return ret;
     301       11295 :             break;
     302             :         case CONTROL_DESTINATION:
     303             :             // same for destinations
     304        4365 :             ret = m_rImport.dispatchDestination(m_aRTFControlWords[i].nIndex);
     305        4365 :             if (ret)
     306           0 :                 return ret;
     307        4365 :             break;
     308             :         case CONTROL_SYMBOL:
     309             :             // and symbols
     310       25232 :             ret = m_rImport.dispatchSymbol(m_aRTFControlWords[i].nIndex);
     311       25232 :             if (ret)
     312           0 :                 return ret;
     313       25232 :             break;
     314             :         case CONTROL_TOGGLE:
     315         674 :             ret = m_rImport.dispatchToggle(m_aRTFControlWords[i].nIndex, bParam, nParam);
     316         674 :             if (ret)
     317           0 :                 return ret;
     318         674 :             break;
     319             :         case CONTROL_VALUE:
     320             :             // values require a parameter by definition
     321       20045 :             if (bParam) {
     322       19957 :                 ret = m_rImport.dispatchValue(m_aRTFControlWords[i].nIndex, nParam);
     323       19957 :                 if (ret)
     324           0 :                     return ret;
     325             :             }
     326       20045 :             break;
     327             :     }
     328             : 
     329       61611 :     return 0;
     330             : }
     331             : 
     332           2 : OUString RTFTokenizer::getPosition()
     333             : {
     334           2 :     OUStringBuffer aRet;
     335           2 :     aRet.append(m_nLineNumber + 1);
     336           2 :     aRet.append(",");
     337           2 :     aRet.append(sal_Int32(Strm().Tell() - m_nLineStartPos + 1));
     338           2 :     return aRet.makeStringAndClear();
     339             : }
     340             : 
     341           1 : sal_Size RTFTokenizer::getGroupStart()
     342             : {
     343           1 :     return m_nGroupStart;
     344             : }
     345             : 
     346             : } // namespace rtftok
     347          24 : } // namespace writerfilter
     348             : 
     349             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10