LCOV - code coverage report
Current view: top level - writerfilter/source/rtftok - rtftokenizer.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 175 199 87.9 %
Date: 2014-04-11 Functions: 16 16 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 <vcl/settings.hxx>
      15             : #include <rtl/strbuf.hxx>
      16             : 
      17             : #include <rtftokenizer.hxx>
      18             : #include <rtfskipdestination.hxx>
      19             : #include <com/sun/star/io/BufferSizeExceededException.hpp>
      20             : 
      21             : using namespace com::sun::star;
      22             : 
      23             : namespace writerfilter {
      24             : namespace rtftok {
      25             : 
      26          14 : std::vector<RTFSymbol> RTFTokenizer::m_aRTFControlWords;
      27             : bool RTFTokenizer::m_bControlWordsSorted;
      28          14 : std::vector<RTFMathSymbol> RTFTokenizer::m_aRTFMathControlWords;
      29             : bool RTFTokenizer::m_bMathControlWordsSorted;
      30             : 
      31         317 : RTFTokenizer::RTFTokenizer(RTFListener& rImport, SvStream* pInStream, uno::Reference<task::XStatusIndicator> const& xStatusIndicator)
      32             :     : m_rImport(rImport),
      33             :     m_pInStream(pInStream),
      34             :     m_xStatusIndicator(xStatusIndicator),
      35             :     m_nGroup(0),
      36             :     m_nLineNumber(0),
      37             :     m_nLineStartPos(0),
      38         317 :     m_nGroupStart(0)
      39             : {
      40         317 :     if (!RTFTokenizer::m_bControlWordsSorted)
      41             :     {
      42           5 :         RTFTokenizer::m_bControlWordsSorted = true;
      43           5 :         m_aRTFControlWords = std::vector<RTFSymbol>(aRTFControlWords, aRTFControlWords + nRTFControlWords);
      44           5 :         std::sort(m_aRTFControlWords.begin(), m_aRTFControlWords.end());
      45             :     }
      46         317 :     if (!RTFTokenizer::m_bMathControlWordsSorted)
      47             :     {
      48           5 :         RTFTokenizer::m_bMathControlWordsSorted = true;
      49           5 :         m_aRTFMathControlWords = std::vector<RTFMathSymbol>(aRTFMathControlWords, aRTFMathControlWords + nRTFMathControlWords);
      50           5 :         std::sort(m_aRTFMathControlWords.begin(), m_aRTFMathControlWords.end());
      51             :     }
      52         317 : }
      53             : 
      54         634 : RTFTokenizer::~RTFTokenizer()
      55             : {
      56         634 : }
      57             : 
      58     1351587 : SvStream& RTFTokenizer::Strm()
      59             : {
      60     1351587 :     return *m_pInStream;
      61             : }
      62             : 
      63         317 : int RTFTokenizer::resolveParse()
      64             : {
      65             :     SAL_INFO( "writerfilter", OSL_THIS_FUNC );
      66             :     char ch;
      67             :     int ret;
      68             :     // for hex chars
      69         317 :     int b = 0, count = 2;
      70         317 :     sal_uInt32 nPercentSize = 0;
      71         317 :     sal_uInt32 nLastPos = 0;
      72             : 
      73         317 :     if (m_xStatusIndicator.is())
      74             :     {
      75         280 :         static ResMgr* pResMgr = ResMgr::CreateResMgr("svx", Application::GetSettings().GetUILanguageTag());
      76         280 :         OUString sDocLoad(ResId(RID_SVXSTR_DOC_LOAD, *pResMgr).toString());
      77             : 
      78         280 :         sal_Size nCurrentPos = Strm().Tell();
      79         280 :         Strm().Seek(STREAM_SEEK_TO_END);
      80         280 :         sal_Size nEndPos = Strm().Tell();
      81         280 :         Strm().Seek(nCurrentPos);
      82         280 :         m_xStatusIndicator->start(sDocLoad, nEndPos);
      83         280 :         nPercentSize = nEndPos / 100;
      84             : 
      85         280 :         m_xStatusIndicator->setValue(nLastPos = nCurrentPos);
      86             :     }
      87             : 
      88      165778 :     while ((Strm().ReadChar( ch ), !Strm().IsEof()))
      89             :     {
      90             :         //SAL_INFO("writerfilter", OSL_THIS_FUNC << ": parsing character '" << ch << "'");
      91             : 
      92      165459 :         sal_Size nCurrentPos = Strm().Tell();
      93      165459 :         if (m_xStatusIndicator.is() && nCurrentPos > (nLastPos + nPercentSize))
      94       12622 :             m_xStatusIndicator->setValue(nLastPos = nCurrentPos);
      95             : 
      96      165459 :         if (m_nGroup < 0)
      97           0 :             return ERROR_GROUP_UNDER;
      98      165459 :         if (m_nGroup > 0 && m_rImport.getInternalState() == INTERNAL_BIN)
      99             :         {
     100           2 :             ret = m_rImport.resolveChars(ch);
     101           2 :             if (ret)
     102           0 :                 return ret;
     103             :         }
     104             :         else
     105             :         {
     106      165457 :             switch (ch)
     107             :             {
     108             :                 case '{':
     109        9695 :                     m_nGroupStart = Strm().Tell() - 1;
     110        9695 :                     ret = m_rImport.pushState();
     111        9695 :                     if (ret)
     112           0 :                         return ret;
     113        9695 :                     break;
     114             :                 case '}':
     115        9692 :                     ret = m_rImport.popState();
     116        9692 :                     if (ret)
     117           0 :                         return ret;
     118        9692 :                     if (m_nGroup == 0)
     119             :                     {
     120         314 :                         if (m_rImport.isSubstream())
     121          25 :                             m_rImport.finishSubstream();
     122         314 :                         return 0;
     123             :                     }
     124        9378 :                     break;
     125             :                 case '\\':
     126       77818 :                     ret = resolveKeyword();
     127       77817 :                     if (ret)
     128           0 :                         return ret;
     129       77817 :                     break;
     130             :                 case 0x0d:
     131        4208 :                     break; // ignore this
     132             :                 case 0x0a:
     133        9753 :                     m_nLineNumber++;
     134        9753 :                     m_nLineStartPos = nCurrentPos;
     135        9753 :                     break;
     136             :                 default:
     137       54291 :                     if (m_nGroup == 0)
     138           0 :                         return ERROR_CHAR_OVER;
     139       54291 :                     if (m_rImport.getInternalState() == INTERNAL_NORMAL)
     140             :                     {
     141        7215 :                         ret = m_rImport.resolveChars(ch);
     142        7215 :                         if (ret)
     143           0 :                             return ret;
     144             :                     }
     145             :                     else
     146             :                     {
     147             :                         SAL_INFO("writerfilter", OSL_THIS_FUNC << ": hex internal state");
     148       47076 :                         b = b << 4;
     149       47076 :                         sal_Int8 parsed = asHex(ch);
     150       47076 :                         if (parsed == -1)
     151           0 :                             return ERROR_HEX_INVALID;
     152       47076 :                         b += parsed;
     153       47076 :                         count--;
     154       47076 :                         if (!count)
     155             :                         {
     156       23538 :                             ret = m_rImport.resolveChars(b);
     157       23538 :                             if (ret)
     158           0 :                                 return ret;
     159       23538 :                             count = 2;
     160       23538 :                             b = 0;
     161       23538 :                             m_rImport.setInternalState(INTERNAL_NORMAL);
     162             :                         }
     163             :                     }
     164       54291 :                     break;
     165             :             }
     166             :         }
     167             :     }
     168             : 
     169           2 :     if (m_nGroup < 0)
     170           0 :         return ERROR_GROUP_UNDER;
     171           2 :     else if (m_nGroup > 0)
     172           2 :         return ERROR_GROUP_OVER;
     173           0 :     return 0;
     174             : }
     175             : 
     176       95162 : int RTFTokenizer::asHex(char ch)
     177             : {
     178       95162 :     int ret = 0;
     179       95162 :     if (isdigit(ch))
     180       71567 :         ret = ch - '0';
     181             :     else
     182             :     {
     183       23595 :         if (islower(ch))
     184             :         {
     185       23595 :             if (ch < 'a' || ch > 'f')
     186           0 :                 return -1;
     187       23595 :             ret = ch - 'a';
     188             :         }
     189             :         else
     190             :         {
     191           0 :             if (ch < 'A' || ch > 'F')
     192           0 :                 return -1;
     193           0 :             ret = ch - 'A';
     194             :         }
     195       23595 :         ret += 10;
     196             :     }
     197       95162 :     return ret;
     198             : }
     199             : 
     200        9452 : int RTFTokenizer::getGroup() const
     201             : {
     202        9452 :     return m_nGroup;
     203             : }
     204             : 
     205        9695 : void RTFTokenizer::pushGroup()
     206             : {
     207        9695 :     m_nGroup++;
     208        9695 : }
     209             : 
     210        9692 : void RTFTokenizer::popGroup()
     211             : {
     212        9692 :     m_nGroup--;
     213        9692 : }
     214             : 
     215       77818 : int RTFTokenizer::resolveKeyword()
     216             : {
     217             :     char ch;
     218       77818 :     OStringBuffer aBuf;
     219       77818 :     bool bNeg = false;
     220       77818 :     bool bParam = false;
     221       77818 :     int nParam = 0;
     222             : 
     223       77818 :     Strm().ReadChar( ch );
     224       77818 :     if (Strm().IsEof())
     225           0 :         return ERROR_EOF;
     226             : 
     227       77818 :     if (!isalpha(ch))
     228             :     {
     229       24826 :         aBuf.append(ch);
     230       24826 :         OString aKeyword = aBuf.makeStringAndClear();
     231             :         // control symbols aren't followed by a space, so we can return here
     232             :         // without doing any SeekRel()
     233       24826 :         return dispatchKeyword(aKeyword, bParam, nParam);
     234             :     }
     235      364657 :     while(isalpha(ch))
     236             :     {
     237      258674 :         aBuf.append(ch);
     238      258674 :         Strm().ReadChar( ch );
     239      258674 :         if (Strm().IsEof())
     240             :         {
     241           1 :             ch = ' ';
     242           1 :             break;
     243             :         }
     244             :     }
     245       52992 :     if (aBuf.getLength() > 32)
     246             :         // See RTF spec v1.9.1, page 7
     247             :         // A control word's name cannot be longer than 32 letters.
     248           1 :         throw io::BufferSizeExceededException();
     249             : 
     250       52991 :     if (ch == '-')
     251             :     {
     252             :         // in case we'll have a parameter, that will be negative
     253         276 :         bNeg = true;
     254         276 :         Strm().ReadChar( ch );
     255         276 :         if (Strm().IsEof())
     256           0 :             return ERROR_EOF;
     257             :     }
     258       52991 :     if (isdigit(ch))
     259             :     {
     260       29693 :         OStringBuffer aParameter;
     261             : 
     262             :         // we have a parameter
     263       29693 :         bParam = true;
     264      125036 :         while(isdigit(ch))
     265             :         {
     266       65650 :             aParameter.append(ch);
     267       65650 :             Strm().ReadChar( ch );
     268       65650 :             if (Strm().IsEof())
     269             :             {
     270           0 :                 ch = ' ';
     271           0 :                 break;
     272             :             }
     273             :         }
     274       29693 :         nParam = aParameter.makeStringAndClear().toInt32();
     275       29693 :         if (bNeg)
     276         276 :             nParam = -nParam;
     277             :     }
     278       52991 :     if (ch != ' ')
     279       39553 :         Strm().SeekRel(-1);
     280      105982 :     OString aKeyword = aBuf.makeStringAndClear();
     281      130809 :     return dispatchKeyword(aKeyword, bParam, nParam);
     282             : }
     283             : 
     284        1296 : bool RTFTokenizer::lookupMathKeyword(RTFMathSymbol& rSymbol)
     285             : {
     286        1296 :     std::vector<RTFMathSymbol>::iterator low = std::lower_bound(m_aRTFMathControlWords.begin(), m_aRTFMathControlWords.end(), rSymbol);
     287        1296 :     int i = low - m_aRTFMathControlWords.begin();
     288        1296 :     if (low == m_aRTFMathControlWords.end() || rSymbol < *low)
     289         137 :         return false;
     290        1159 :     rSymbol = m_aRTFMathControlWords[i];
     291        1159 :     return true;
     292             : }
     293             : 
     294       77817 : int RTFTokenizer::dispatchKeyword(OString& rKeyword, bool bParam, int nParam)
     295             : {
     296       77817 :     if (m_rImport.getDestinationState() == DESTINATION_SKIP)
     297        4303 :         return 0;
     298             : #if OSL_DEBUG_LEVEL > 1
     299             :     SAL_INFO("writerfilter.rtf", OSL_THIS_FUNC << ": keyword '\\" << rKeyword.getStr() <<
     300             :                "' with param? " << (bParam ? 1 : 0) <<" param val: '" << (bParam ? nParam : 0) << "'");
     301             : #endif
     302             :     RTFSymbol aSymbol;
     303       73514 :     aSymbol.sKeyword = rKeyword.getStr();
     304       73514 :     std::vector<RTFSymbol>::iterator low = std::lower_bound(m_aRTFControlWords.begin(), m_aRTFControlWords.end(), aSymbol);
     305       73514 :     int i = low - m_aRTFControlWords.begin();
     306       73514 :     if (low == m_aRTFControlWords.end() || aSymbol < *low)
     307             :     {
     308             :         SAL_INFO("writerfilter", OSL_THIS_FUNC << ": unknown keyword '\\" << rKeyword.getStr() << "'");
     309         356 :         RTFSkipDestination aSkip(m_rImport);
     310         356 :         aSkip.setParsed(false);
     311         356 :         return 0;
     312             :     }
     313             : 
     314             :     int ret;
     315       73158 :     switch (m_aRTFControlWords[i].nControlType)
     316             :     {
     317             :         case CONTROL_FLAG:
     318             :             // flags ignore any parameter by definition
     319       14401 :             ret = m_rImport.dispatchFlag(m_aRTFControlWords[i].nIndex);
     320       14401 :             if (ret)
     321           0 :                 return ret;
     322       14401 :             break;
     323             :         case CONTROL_DESTINATION:
     324             :             // same for destinations
     325        5946 :             ret = m_rImport.dispatchDestination(m_aRTFControlWords[i].nIndex);
     326        5946 :             if (ret)
     327           0 :                 return ret;
     328        5946 :             break;
     329             :         case CONTROL_SYMBOL:
     330             :             // and symbols
     331       25934 :             ret = m_rImport.dispatchSymbol(m_aRTFControlWords[i].nIndex);
     332       25934 :             if (ret)
     333           0 :                 return ret;
     334       25934 :             break;
     335             :         case CONTROL_TOGGLE:
     336         965 :             ret = m_rImport.dispatchToggle(m_aRTFControlWords[i].nIndex, bParam, nParam);
     337         965 :             if (ret)
     338           0 :                 return ret;
     339         965 :             break;
     340             :         case CONTROL_VALUE:
     341             :             // values require a parameter by definition
     342       25912 :             if (bParam) {
     343       25820 :                 ret = m_rImport.dispatchValue(m_aRTFControlWords[i].nIndex, nParam);
     344       25820 :                 if (ret)
     345           0 :                     return ret;
     346             :             }
     347       25912 :             break;
     348             :     }
     349             : 
     350       73158 :     return 0;
     351             : }
     352             : 
     353           2 : OUString RTFTokenizer::getPosition()
     354             : {
     355           2 :     OUStringBuffer aRet;
     356           2 :     aRet.append(m_nLineNumber + 1);
     357           2 :     aRet.append(",");
     358           2 :     aRet.append(sal_Int32(Strm().Tell() - m_nLineStartPos + 1));
     359           2 :     return aRet.makeStringAndClear();
     360             : }
     361             : 
     362           5 : sal_Size RTFTokenizer::getGroupStart()
     363             : {
     364           5 :     return m_nGroupStart;
     365             : }
     366             : 
     367             : } // namespace rtftok
     368          42 : } // namespace writerfilter
     369             : 
     370             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10