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

Generated by: LCOV version 1.10