LCOV - code coverage report
Current view: top level - libreoffice/writerfilter/source/rtftok - rtftokenizer.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 160 184 87.0 %
Date: 2012-12-27 Functions: 14 14 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             :  * Version: MPL 1.1 / GPLv3+ / LGPLv3+
       4             :  *
       5             :  * The contents of this file are subject to the Mozilla Public License Version
       6             :  * 1.1 (the "License"); you may not use this file except in compliance with
       7             :  * the License. You may obtain a copy of the License at
       8             :  * http://www.mozilla.org/MPL/
       9             :  *
      10             :  * Software distributed under the License is distributed on an "AS IS" basis,
      11             :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12             :  * for the specific language governing rights and limitations under the
      13             :  * License.
      14             :  *
      15             :  * The Initial Developer of the Original Code is
      16             :  *       Miklos Vajna <vmiklos@frugalware.org>
      17             :  * Portions created by the Initial Developer are Copyright (C) 2011 the
      18             :  * Initial Developer. All Rights Reserved.
      19             :  *
      20             :  * Contributor(s):
      21             :  *
      22             :  * Alternatively, the contents of this file may be used under the terms of
      23             :  * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
      24             :  * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
      25             :  * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
      26             :  * instead of those above.
      27             :  */
      28             : 
      29             : #include <tools/stream.hxx>
      30             : #include <tools/resmgr.hxx>
      31             : #include <svx/dialogs.hrc>
      32             : #include <vcl/svapp.hxx>
      33             : 
      34             : #include <rtftokenizer.hxx>
      35             : #include <rtfskipdestination.hxx>
      36             : 
      37             : using rtl::OString;
      38             : using rtl::OStringBuffer;
      39             : using rtl::OUString;
      40             : using rtl::OUStringBuffer;
      41             : using rtl::OUStringToOString;
      42             : 
      43             : namespace writerfilter {
      44             : namespace rtftok {
      45             : 
      46           5 : std::vector<RTFSymbol> RTFTokenizer::m_aRTFControlWords;
      47             : bool RTFTokenizer::m_bControlWordsSorted;
      48             : 
      49         138 : RTFTokenizer::RTFTokenizer(RTFDocumentImpl& rImport, SvStream* pInStream, uno::Reference<task::XStatusIndicator> const& xStatusIndicator)
      50             :     : m_rImport(rImport),
      51             :     m_pInStream(pInStream),
      52             :     m_xStatusIndicator(xStatusIndicator),
      53             :     m_nGroup(0),
      54             :     m_nLineNumber(0),
      55         138 :     m_nLineStartPos(0)
      56             : {
      57         138 :     if (!RTFTokenizer::m_bControlWordsSorted)
      58             :     {
      59           3 :         RTFTokenizer::m_bControlWordsSorted = true;
      60           3 :         m_aRTFControlWords = std::vector<RTFSymbol>(aRTFControlWords, aRTFControlWords + nRTFControlWords);
      61           3 :         std::sort(m_aRTFControlWords.begin(), m_aRTFControlWords.end());
      62             :     }
      63         138 : }
      64             : 
      65         276 : RTFTokenizer::~RTFTokenizer()
      66             : {
      67         276 : }
      68             : 
      69      886154 : SvStream& RTFTokenizer::Strm()
      70             : {
      71      886154 :     return *m_pInStream;
      72             : }
      73             : 
      74         138 : int RTFTokenizer::resolveParse()
      75             : {
      76             :     SAL_INFO( "writerfilter", OSL_THIS_FUNC );
      77             :     char ch;
      78             :     int ret;
      79             :     // for hex chars
      80         138 :     int b = 0, count = 2;
      81         138 :     sal_uInt32 nPercentSize = 0;
      82         138 :     sal_uInt32 nLastPos = 0;
      83             : 
      84         138 :     if (m_xStatusIndicator.is())
      85             :     {
      86         127 :         static ResMgr* pResMgr = ResMgr::CreateResMgr("svx", Application::GetSettings().GetUILanguageTag().getLocale());
      87         127 :         OUString sDocLoad(ResId(RID_SVXSTR_DOC_LOAD, *pResMgr).toString());
      88             : 
      89         127 :         sal_uInt32 nCurrentPos = Strm().Tell();
      90         127 :         Strm().Seek(STREAM_SEEK_TO_END);
      91         127 :         sal_uInt32 nEndPos = Strm().Tell();
      92         127 :         Strm().Seek(nCurrentPos);
      93         127 :         m_xStatusIndicator->start(sDocLoad, nEndPos);
      94         127 :         nPercentSize = nEndPos / 100;
      95             : 
      96         127 :         m_xStatusIndicator->setValue(nLastPos = nCurrentPos);
      97             :     }
      98             : 
      99      124695 :     while ((Strm() >> ch, !Strm().IsEof()))
     100             :     {
     101             :         //SAL_INFO("writerfilter", OSL_THIS_FUNC << ": parsing character '" << ch << "'");
     102             : 
     103      124555 :         sal_uInt32 nCurrentPos = Strm().Tell();
     104      124555 :         if (m_xStatusIndicator.is() && nCurrentPos > (nLastPos + nPercentSize))
     105        4862 :             m_xStatusIndicator->setValue(nLastPos = nCurrentPos);
     106             : 
     107      124555 :         if (m_nGroup < 0)
     108           0 :             return ERROR_GROUP_UNDER;
     109      124555 :         if (m_nGroup > 0 && m_rImport.getState().nInternalState == INTERNAL_BIN)
     110             :         {
     111           1 :             ret = m_rImport.resolveChars(ch);
     112           1 :             if (ret)
     113           0 :                 return ret;
     114             :         }
     115             :         else
     116             :         {
     117      124554 :             switch (ch)
     118             :             {
     119             :                 case '{':
     120        5386 :                     ret = m_rImport.pushState();
     121        5386 :                     if (ret)
     122           0 :                         return ret;
     123        5386 :                     break;
     124             :                 case '}':
     125        5383 :                     ret = m_rImport.popState();
     126        5383 :                     if (ret)
     127           0 :                         return ret;
     128        5383 :                     if (m_nGroup == 0)
     129             :                     {
     130         135 :                         if (m_rImport.isSubstream())
     131           9 :                             m_rImport.finishSubstream();
     132         135 :                         return 0;
     133             :                     }
     134        5248 :                     break;
     135             :                 case '\\':
     136       54505 :                     ret = resolveKeyword();
     137       54504 :                     if (ret)
     138           0 :                         return ret;
     139       54504 :                     break;
     140             :                 case 0x0d:
     141        3275 :                     break; // ignore this
     142             :                 case 0x0a:
     143        4753 :                     m_nLineNumber++;
     144        4753 :                     m_nLineStartPos = nCurrentPos;
     145        4753 :                     break;
     146             :                 default:
     147       51252 :                     if (m_nGroup == 0)
     148           0 :                         return ERROR_CHAR_OVER;
     149       51252 :                     if (m_rImport.getState().nInternalState == INTERNAL_NORMAL)
     150             :                     {
     151        4534 :                         ret = m_rImport.resolveChars(ch);
     152        4534 :                         if (ret)
     153           0 :                             return ret;
     154             :                     }
     155             :                     else
     156             :                     {
     157             :                         SAL_INFO("writerfilter", OSL_THIS_FUNC << ": hex internal state");
     158       46718 :                         b = b << 4;
     159       46718 :                         sal_Int8 parsed = asHex(ch);
     160       46718 :                         if (parsed == -1)
     161           0 :                             return ERROR_HEX_INVALID;
     162       46718 :                         b += parsed;
     163       46718 :                         count--;
     164       46718 :                         if (!count)
     165             :                         {
     166       23359 :                             ret = m_rImport.resolveChars(b);
     167       23359 :                             if (ret)
     168           0 :                                 return ret;
     169       23359 :                             count = 2;
     170       23359 :                             b = 0;
     171       23359 :                             m_rImport.getState().nInternalState = INTERNAL_NORMAL;
     172             :                         }
     173             :                     }
     174       51252 :                     break;
     175             :             }
     176             :         }
     177             :     }
     178             : 
     179           2 :     if (m_nGroup < 0)
     180           0 :         return ERROR_GROUP_UNDER;
     181           2 :     else if (m_nGroup > 0)
     182           2 :         return ERROR_GROUP_OVER;
     183           0 :     return 0;
     184             : }
     185             : 
     186       86406 : int RTFTokenizer::asHex(char ch)
     187             : {
     188       86406 :     int ret = 0;
     189       86406 :     if (isdigit(ch))
     190       64840 :         ret = ch - '0';
     191             :     else
     192             :     {
     193       21566 :         if (islower(ch))
     194             :         {
     195       21566 :             if (ch < 'a' || ch > 'f')
     196           0 :                 return -1;
     197       21566 :             ret = ch - 'a';
     198             :         }
     199             :         else
     200             :         {
     201           0 :             if (ch < 'A' || ch > 'F')
     202           0 :                 return -1;
     203           0 :             ret = ch - 'A';
     204             :         }
     205       21566 :         ret += 10;
     206             :     }
     207       86406 :     return ret;
     208             : }
     209             : 
     210        5383 : int RTFTokenizer::getGroup() const
     211             : {
     212        5383 :     return m_nGroup;
     213             : }
     214             : 
     215        5386 : void RTFTokenizer::pushGroup()
     216             : {
     217        5386 :     m_nGroup++;
     218        5386 : }
     219             : 
     220        5383 : void RTFTokenizer::popGroup()
     221             : {
     222        5383 :     m_nGroup--;
     223        5383 : }
     224             : 
     225       54505 : int RTFTokenizer::resolveKeyword()
     226             : {
     227             :     char ch;
     228       54505 :     OStringBuffer aBuf;
     229       54505 :     bool bNeg = false;
     230       54505 :     bool bParam = false;
     231       54505 :     int nParam = 0;
     232             : 
     233       54505 :     Strm() >> ch;
     234       54505 :     if (Strm().IsEof())
     235           0 :         return ERROR_EOF;
     236             : 
     237       54505 :     if (!isalpha(ch))
     238             :     {
     239       24123 :         aBuf.append(ch);
     240       24123 :         OString aKeyword = aBuf.makeStringAndClear();
     241             :         // control symbols aren't followed by a space, so we can return here
     242             :         // without doing any SeekRel()
     243       24123 :         return dispatchKeyword(aKeyword, bParam, nParam);
     244             :     }
     245      212594 :     while(isalpha(ch))
     246             :     {
     247      151831 :         aBuf.append(ch);
     248      151831 :         Strm() >> ch;
     249      151831 :         if (Strm().IsEof())
     250             :         {
     251           1 :             ch = ' ';
     252           1 :             break;
     253             :         }
     254             :     }
     255       30382 :     if (aBuf.getLength() > 32)
     256             :         // See RTF spec v1.9.1, page 7
     257             :         // A control word's name cannot be longer than 32 letters.
     258           1 :         throw io::BufferSizeExceededException();
     259             : 
     260       30381 :     if (ch == '-')
     261             :     {
     262             :         // in case we'll have a parameter, that will be negative
     263         115 :         bNeg = true;
     264         115 :         Strm() >> ch;
     265         115 :         if (Strm().IsEof())
     266           0 :             return ERROR_EOF;
     267             :     }
     268       30381 :     if (isdigit(ch))
     269             :     {
     270       17057 :         OStringBuffer aParameter;
     271             : 
     272             :         // we have a parameter
     273       17057 :         bParam = true;
     274       72521 :         while(isdigit(ch))
     275             :         {
     276       38407 :             aParameter.append(ch);
     277       38407 :             Strm() >> ch;
     278       38407 :             if (Strm().IsEof())
     279             :             {
     280           0 :                 ch = ' ';
     281           0 :                 break;
     282             :             }
     283             :         }
     284       17057 :         nParam = aParameter.makeStringAndClear().toInt32();
     285       17057 :         if (bNeg)
     286         115 :             nParam = -nParam;
     287             :     }
     288       30381 :     if (ch != ' ')
     289       22259 :         Strm().SeekRel(-1);
     290       30381 :     OString aKeyword = aBuf.makeStringAndClear();
     291       30381 :     return dispatchKeyword(aKeyword, bParam, nParam);
     292             : }
     293             : 
     294       54504 : int RTFTokenizer::dispatchKeyword(OString& rKeyword, bool bParam, int nParam)
     295             : {
     296       54504 :     if (m_rImport.getState().nDestinationState == DESTINATION_SKIP)
     297        3254 :         return 0;
     298             :     /*SAL_INFO("writefilter", OSL_THIS_FUNC << ": keyword '\\" << rKeyword.getStr() <<
     299             :                "' with param? " << (bParam ? 1 : 0) <<" param val: '" << (bParam ? nParam : 0) << "'");*/
     300             :     RTFSymbol aSymbol;
     301       51250 :     aSymbol.sKeyword = rKeyword.getStr();
     302       51250 :     std::vector<RTFSymbol>::iterator low = std::lower_bound(m_aRTFControlWords.begin(), m_aRTFControlWords.end(), aSymbol);
     303       51250 :     int i = low - m_aRTFControlWords.begin();
     304       51250 :     if (low == m_aRTFControlWords.end() || aSymbol < *low)
     305             :     {
     306             :         SAL_INFO("writerfilter", OSL_THIS_FUNC << ": unknown keyword '\\" << rKeyword.getStr() << "'");
     307         210 :         RTFSkipDestination aSkip(m_rImport);
     308         210 :         aSkip.setParsed(false);
     309         210 :         return 0;
     310             :     }
     311             : 
     312             :     int ret;
     313       51040 :     switch (m_aRTFControlWords[i].nControlType)
     314             :     {
     315             :         case CONTROL_FLAG:
     316             :             // flags ignore any parameter by definition
     317        8420 :             ret = m_rImport.dispatchFlag(m_aRTFControlWords[i].nIndex);
     318        8420 :             if (ret)
     319           0 :                 return ret;
     320        8420 :             break;
     321             :         case CONTROL_DESTINATION:
     322             :             // same for destinations
     323        2962 :             ret = m_rImport.dispatchDestination(m_aRTFControlWords[i].nIndex);
     324        2962 :             if (ret)
     325           0 :                 return ret;
     326        2962 :             break;
     327             :         case CONTROL_SYMBOL:
     328             :             // and symbols
     329       24713 :             ret = m_rImport.dispatchSymbol(m_aRTFControlWords[i].nIndex);
     330       24713 :             if (ret)
     331           0 :                 return ret;
     332       24713 :             break;
     333             :         case CONTROL_TOGGLE:
     334         484 :             ret = m_rImport.dispatchToggle(m_aRTFControlWords[i].nIndex, bParam, nParam);
     335         484 :             if (ret)
     336           0 :                 return ret;
     337         484 :             break;
     338             :         case CONTROL_VALUE:
     339             :             // values require a parameter by definition
     340       14461 :             if (bParam) {
     341       14421 :                 ret = m_rImport.dispatchValue(m_aRTFControlWords[i].nIndex, nParam);
     342       14421 :                 if (ret)
     343           0 :                     return ret;
     344             :             }
     345       14461 :             break;
     346             :     }
     347             : 
     348       51040 :     return 0;
     349             : }
     350             : 
     351           2 : OUString RTFTokenizer::getPosition()
     352             : {
     353           2 :     OUStringBuffer aRet;
     354           2 :     aRet.append(m_nLineNumber + 1);
     355           2 :     aRet.append(",");
     356           2 :     aRet.append(sal_Int32(Strm().Tell() - m_nLineStartPos + 1));
     357           2 :     return aRet.makeStringAndClear();
     358             : }
     359             : 
     360             : } // namespace rtftok
     361          15 : } // namespace writerfilter
     362             : 
     363             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10