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

Generated by: LCOV version 1.11