LCOV - code coverage report
Current view: top level - sax/source/expatwrap - saxwriter.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 363 620 58.5 %
Date: 2015-06-13 12:38:46 Functions: 33 46 71.7 %
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             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <string.h>
      21             : 
      22             : #include <cassert>
      23             : #include <set>
      24             : #include <stack>
      25             : 
      26             : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
      27             : #include <com/sun/star/lang/XServiceInfo.hpp>
      28             : #include <com/sun/star/uno/XComponentContext.hpp>
      29             : #include <com/sun/star/util/XCloneable.hpp>
      30             : #include <com/sun/star/xml/sax/XParser.hpp>
      31             : #include <com/sun/star/xml/sax/SAXParseException.hpp>
      32             : #include <com/sun/star/xml/sax/SAXInvalidCharacterException.hpp>
      33             : #include <com/sun/star/xml/sax/XWriter.hpp>
      34             : 
      35             : #include <com/sun/star/io/XActiveDataSource.hpp>
      36             : 
      37             : #include <cppuhelper/weak.hxx>
      38             : #include <cppuhelper/implbase2.hxx>
      39             : #include <cppuhelper/supportsservice.hxx>
      40             : 
      41             : #include <osl/diagnose.h>
      42             : #include <rtl/ref.hxx>
      43             : #include <rtl/ustrbuf.hxx>
      44             : 
      45             : using namespace ::std;
      46             : using namespace ::osl;
      47             : using namespace ::cppu;
      48             : using namespace ::com::sun::star::uno;
      49             : using namespace ::com::sun::star::lang;
      50             : using namespace ::com::sun::star::xml::sax;
      51             : using namespace ::com::sun::star::util;
      52             : using namespace ::com::sun::star::io;
      53             : 
      54             : #include "xml2utf.hxx"
      55             : #include <boost/scoped_array.hpp>
      56             : 
      57             : #define LINEFEED 10
      58             : #define SEQUENCESIZE 1024
      59             : #define MAXCOLUMNCOUNT 72
      60             : 
      61             : /******
      62             : *
      63             : *
      64             : * Character conversion functions
      65             : *
      66             : *
      67             : *****/
      68             : 
      69             : namespace {
      70             : 
      71             : enum SaxInvalidCharacterError
      72             : {
      73             :     SAX_NONE,
      74             :     SAX_WARNING,
      75             :     SAX_ERROR
      76             : };
      77             : 
      78             : class SaxWriterHelper
      79             : {
      80             : #ifdef DBG_UTIL
      81             : public:
      82             :     ::std::stack<OUString> m_DebugStartedElements;
      83             : #endif
      84             : 
      85             : private:
      86             :     Reference< XOutputStream >  m_out;
      87             :     Sequence < sal_Int8 >       m_Sequence;
      88             :     sal_Int8*                   mp_Sequence;
      89             : 
      90             :     sal_Int32                   nLastLineFeedPos; // is negative after writing a sequence
      91             :     sal_uInt32                  nCurrentPos;
      92             :     bool                    m_bStartElementFinished;
      93             : 
      94             :     inline sal_uInt32 writeSequence() throw( SAXException );
      95             : 
      96             :     // use only if to insert the bytes more space in the sequence is needed and
      97             :     // so the sequence has to write out and reset rPos to 0
      98             :     // writes sequence only on overflow, sequence could be full on the end (rPos == SEQUENCESIZE)
      99             :     inline void AddBytes(sal_Int8* pTarget, sal_uInt32& rPos,
     100             :                 const sal_Int8* pBytes, sal_uInt32 nBytesCount) throw( SAXException );
     101             :     inline bool convertToXML(const sal_Unicode * pStr,
     102             :                         sal_Int32 nStrLen,
     103             :                         bool bDoNormalization,
     104             :                         bool bNormalizeWhitespace,
     105             :                         sal_Int8 *pTarget,
     106             :                         sal_uInt32& rPos) throw( SAXException );
     107             :     inline void FinishStartElement() throw( SAXException );
     108             : public:
     109        7025 :     explicit SaxWriterHelper(Reference< XOutputStream > m_TempOut)
     110             :         : m_out(m_TempOut)
     111             :         , m_Sequence(SEQUENCESIZE)
     112             :         , mp_Sequence(NULL)
     113             :         , nLastLineFeedPos(0)
     114             :         , nCurrentPos(0)
     115        7025 :         , m_bStartElementFinished(true)
     116             :     {
     117             :         OSL_ENSURE(SEQUENCESIZE > 50, "Sequence cache size to small");
     118        7025 :         mp_Sequence = m_Sequence.getArray();
     119        7025 :     }
     120        7023 :     ~SaxWriterHelper()
     121        7023 :     {
     122             :         OSL_ENSURE(!nCurrentPos, "cached Sequence not written");
     123             :         OSL_ENSURE(m_bStartElementFinished, "StartElement not complettly written");
     124        7023 :     }
     125             : 
     126             :     inline void insertIndentation(sal_uInt32 m_nLevel)  throw( SAXException );
     127             : 
     128             : // returns whether it works correct or invalid characters were in the string
     129             : // If there are invalid characters in the string it returns sal_False.
     130             : // Than the calling method has to throw the needed Exception.
     131             :     inline bool writeString(const OUString& rWriteOutString,
     132             :                         bool bDoNormalization,
     133             :                         bool bNormalizeWhitespace) throw( SAXException );
     134             : 
     135           0 :     sal_uInt32 GetLastColumnCount() const throw()
     136           0 :         { return (sal_uInt32)(nCurrentPos - nLastLineFeedPos); }
     137             : 
     138             :     inline void startDocument() throw( SAXException );
     139             : 
     140             : // returns whether it works correct or invalid characters were in the strings
     141             : // If there are invalid characters in one of the strings it returns sal_False.
     142             : // Than the calling method has to throw the needed Exception.
     143             :     inline SaxInvalidCharacterError startElement(const OUString& rName, const Reference< XAttributeList >& xAttribs) throw( SAXException );
     144             :     inline bool FinishEmptyElement() throw( SAXException );
     145             : 
     146             : // returns whether it works correct or invalid characters were in the string
     147             : // If there are invalid characters in the string it returns sal_False.
     148             : // Than the calling method has to throw the needed Exception.
     149             :     inline bool endElement(const OUString& rName) throw( SAXException );
     150             :     inline void endDocument() throw( SAXException );
     151             : 
     152             : // returns whether it works correct or invalid characters were in the strings
     153             : // If there are invalid characters in the string it returns sal_False.
     154             : // Than the calling method has to throw the needed Exception.
     155             :     inline bool processingInstruction(const OUString& rTarget, const OUString& rData) throw( SAXException );
     156             :     inline void startCDATA() throw( SAXException );
     157             :     inline void endCDATA() throw( SAXException );
     158             : 
     159             : // returns whether it works correct or invalid characters were in the strings
     160             : // If there are invalid characters in the string it returns sal_False.
     161             : // Than the calling method has to throw the needed Exception.
     162             :     inline bool comment(const OUString& rComment) throw( SAXException );
     163             : 
     164             :     inline void clearBuffer() throw( SAXException );
     165             : };
     166             : 
     167             : const sal_Bool g_bValidCharsBelow32[32] =
     168             : {
     169             : //  0 1 2 3 4 5 6 7
     170             :     0,0,0,0,0,0,0,0,  //0
     171             :     0,1,1,0,0,1,0,0,  //8
     172             :     0,0,0,0,0,0,0,0,  //16
     173             :     0,0,0,0,0,0,0,0
     174             : };
     175             : 
     176    16367510 : inline bool IsInvalidChar(const sal_Unicode aChar)
     177             : {
     178    16367510 :     bool bRet(false);
     179             :     // check first for the most common characters
     180    16367510 :     if( aChar < 32 || aChar >= 0xd800 )
     181        2792 :         bRet = ( (aChar < 32 && ! g_bValidCharsBelow32[aChar]) ||
     182        9128 :             aChar == 0xffff ||
     183        4564 :             aChar == 0xfffe );
     184    16367510 :     return bRet;
     185             : }
     186             : 
     187             : /********
     188             : * write through to the output stream
     189             : *
     190             : *****/
     191       22651 : inline sal_uInt32 SaxWriterHelper::writeSequence() throw( SAXException )
     192             : {
     193             :     try
     194             :     {
     195       22651 :         m_out->writeBytes( m_Sequence );
     196             :     }
     197           0 :     catch (const IOException & e)
     198             :     {
     199           0 :         Any a;
     200           0 :         a <<= e;
     201             :         throw SAXException(
     202             :             "IO exception during writing",
     203             :             Reference< XInterface > (),
     204           0 :             a );
     205             :     }
     206       22651 :     nLastLineFeedPos -= SEQUENCESIZE;
     207       22651 :     return 0;
     208             : }
     209             : 
     210          16 : inline void SaxWriterHelper::AddBytes(sal_Int8* pTarget, sal_uInt32& rPos,
     211             :                 const sal_Int8* pBytes, sal_uInt32 nBytesCount) throw( SAXException )
     212             : {
     213             :     OSL_ENSURE((rPos + nBytesCount) > SEQUENCESIZE, "wrong use of AddBytesMethod");
     214          16 :     sal_uInt32 nCount(SEQUENCESIZE - rPos);
     215          16 :     memcpy( &(pTarget[rPos]) , pBytes,  nCount);
     216             : 
     217             :     OSL_ENSURE(rPos + nCount == SEQUENCESIZE, "the position should be the at the end");
     218             : 
     219          16 :     rPos = writeSequence();
     220          16 :     sal_uInt32 nRestCount(nBytesCount - nCount);
     221          16 :     if ((rPos + nRestCount) <= SEQUENCESIZE)
     222             :     {
     223          16 :         memcpy( &(pTarget[rPos]), &pBytes[nCount], nRestCount);
     224          16 :         rPos += nRestCount;
     225             :     }
     226             :     else
     227           0 :         AddBytes(pTarget, rPos, &pBytes[nCount], nRestCount);
     228          16 : }
     229             : 
     230             : /** Converts an UTF16 string to UTF8 and does XML normalization
     231             : 
     232             :     @param pTarget
     233             :            Pointer to a piece of memory, to where the output should be written. The caller
     234             :            must call calcXMLByteLength on the same string, to ensure,
     235             :            that there is enough memory for converting.
     236             :  */
     237     1363820 : inline bool SaxWriterHelper::convertToXML( const sal_Unicode * pStr,
     238             :                         sal_Int32 nStrLen,
     239             :                         bool bDoNormalization,
     240             :                         bool bNormalizeWhitespace,
     241             :                         sal_Int8 *pTarget,
     242             :                         sal_uInt32& rPos ) throw( SAXException )
     243             : {
     244     1363820 :     bool bRet(true);
     245     1363820 :     sal_uInt32 nSurrogate = 0;
     246             : 
     247    17731330 :     for( sal_Int32 i = 0 ; i < nStrLen ; i ++ )
     248             :     {
     249    16367510 :         sal_uInt16 c = pStr[i];
     250    16367510 :         if (IsInvalidChar(c))
     251           0 :             bRet = false;
     252    16367510 :         else if( (c >= 0x0001) && (c <= 0x007F) )
     253             :         {
     254    32704458 :             if( bDoNormalization )
     255             :             {
     256     6528341 :                 switch( c )
     257             :                 {
     258             :                     case '&':  // resemble to &amp;
     259             :                     {
     260          40 :                         if ((rPos + 5) > SEQUENCESIZE)
     261           0 :                             AddBytes(pTarget, rPos, reinterpret_cast<sal_Int8 const *>("&amp;"), 5);
     262             :                         else
     263             :                         {
     264          40 :                             memcpy( &(pTarget[rPos]) , "&amp;", 5 );
     265          40 :                             rPos += 5;
     266             :                         }
     267             :                     }
     268          40 :                     break;
     269             :                     case '<':
     270             :                     {
     271         219 :                         if ((rPos + 4) > SEQUENCESIZE)
     272           1 :                             AddBytes(pTarget, rPos, reinterpret_cast<sal_Int8 const *>("&lt;"), 4);
     273             :                         else
     274             :                         {
     275         218 :                             memcpy( &(pTarget[rPos]) , "&lt;" , 4 );
     276         218 :                             rPos += 4;        // &lt;
     277             :                         }
     278             :                     }
     279         219 :                     break;
     280             :                     case '>':
     281             :                     {
     282         258 :                         if ((rPos + 4) > SEQUENCESIZE)
     283           0 :                             AddBytes(pTarget, rPos, reinterpret_cast<sal_Int8 const *>("&gt;"), 4);
     284             :                         else
     285             :                         {
     286         258 :                             memcpy( &(pTarget[rPos]) , "&gt;" , 4 );
     287         258 :                             rPos += 4;        // &gt;
     288             :                         }
     289             :                     }
     290         258 :                     break;
     291             :                     case 39:                 // 39 == '''
     292             :                     {
     293        3750 :                         if ((rPos + 6) > SEQUENCESIZE)
     294          12 :                             AddBytes(pTarget, rPos, reinterpret_cast<sal_Int8 const *>("&apos;"), 6);
     295             :                         else
     296             :                         {
     297        3738 :                             memcpy( &(pTarget[rPos]) , "&apos;" , 6 );
     298        3738 :                             rPos += 6;        // &apos;
     299             :                         }
     300             :                     }
     301        3750 :                     break;
     302             :                     case '"':
     303             :                     {
     304         350 :                         if ((rPos + 6) > SEQUENCESIZE)
     305           2 :                             AddBytes(pTarget, rPos, reinterpret_cast<sal_Int8 const *>("&quot;"), 6);
     306             :                         else
     307             :                         {
     308         348 :                             memcpy( &(pTarget[rPos]) , "&quot;" , 6 );
     309         348 :                             rPos += 6;        // &quot;
     310             :                         }
     311             :                     }
     312         350 :                     break;
     313             :                     case 13:
     314             :                     {
     315           0 :                         if ((rPos + 6) > SEQUENCESIZE)
     316           0 :                             AddBytes(pTarget, rPos, reinterpret_cast<sal_Int8 const *>("&#x0d;"), 6);
     317             :                         else
     318             :                         {
     319           0 :                             memcpy( &(pTarget[rPos]) , "&#x0d;" , 6 );
     320           0 :                             rPos += 6;
     321             :                         }
     322             :                     }
     323           0 :                     break;
     324             :                     case LINEFEED:
     325             :                     {
     326        1392 :                         if( bNormalizeWhitespace )
     327             :                         {
     328           5 :                             if ((rPos + 6) > SEQUENCESIZE)
     329           0 :                                 AddBytes(pTarget, rPos, reinterpret_cast<sal_Int8 const *>("&#x0a;"), 6);
     330             :                             else
     331             :                             {
     332           5 :                                 memcpy( &(pTarget[rPos]) , "&#x0a;" , 6 );
     333           5 :                                 rPos += 6;
     334             :                             }
     335             :                         }
     336             :                         else
     337             :                         {
     338        1387 :                             pTarget[rPos] = LINEFEED;
     339        1387 :                             nLastLineFeedPos = rPos;
     340        1387 :                             rPos ++;
     341             :                         }
     342             :                     }
     343        1392 :                     break;
     344             :                     case 9:
     345             :                     {
     346        1400 :                         if( bNormalizeWhitespace )
     347             :                         {
     348           0 :                             if ((rPos + 6) > SEQUENCESIZE)
     349           0 :                                 AddBytes(pTarget, rPos, reinterpret_cast<sal_Int8 const *>("&#x09;"), 6);
     350             :                             else
     351             :                             {
     352           0 :                                 memcpy( &(pTarget[rPos]) , "&#x09;" , 6 );
     353           0 :                                 rPos += 6;
     354             :                             }
     355             :                         }
     356             :                         else
     357             :                         {
     358        1400 :                             pTarget[rPos] = 9;
     359        1400 :                             rPos ++;
     360             :                         }
     361             :                     }
     362        1400 :                     break;
     363             :                     default:
     364             :                     {
     365     6520932 :                         pTarget[rPos] = (sal_Int8)c;
     366     6520932 :                         rPos ++;
     367             :                     }
     368     6520932 :                     break;
     369             :                 }
     370             :             }
     371             :             else
     372             :             {
     373     9823888 :                 pTarget[rPos] = (sal_Int8)c;
     374     9823888 :                 if ((sal_Int8)c == LINEFEED)
     375           0 :                     nLastLineFeedPos = rPos;
     376     9823888 :                 rPos ++;
     377             :             }
     378             :         }
     379       15281 :         else if( c >= 0xd800 && c < 0xdc00  )
     380             :         {
     381             :             // 1. surrogate: save (until 2. surrogate)
     382             :             OSL_ENSURE( nSurrogate == 0, "left-over Unicode surrogate" );
     383           0 :             nSurrogate = ( ( c & 0x03ff ) + 0x0040 );
     384             :         }
     385       15281 :         else if( c >= 0xdc00 && c < 0xe000 )
     386             :         {
     387             :             // 2. surrogate: write as UTF-8
     388             :             OSL_ENSURE( nSurrogate != 0, "lone 2nd Unicode surrogate" );
     389             : 
     390           0 :             nSurrogate = ( nSurrogate << 10 ) | ( c & 0x03ff );
     391           0 :             if( nSurrogate >= 0x00010000  &&  nSurrogate <= 0x0010FFFF )
     392             :             {
     393           0 :                 sal_Int8 aBytes[] = { sal_Int8(0xF0 | ((nSurrogate >> 18) & 0x0F)),
     394           0 :                                       sal_Int8(0x80 | ((nSurrogate >> 12) & 0x3F)),
     395           0 :                                       sal_Int8(0x80 | ((nSurrogate >>  6) & 0x3F)),
     396           0 :                                       sal_Int8(0x80 | ((nSurrogate >>  0) & 0x3F)) };
     397           0 :                 if ((rPos + 4) > SEQUENCESIZE)
     398           0 :                     AddBytes(pTarget, rPos, aBytes, 4);
     399             :                 else
     400             :                 {
     401           0 :                     pTarget[rPos] = aBytes[0];
     402           0 :                     rPos ++;
     403           0 :                     pTarget[rPos] = aBytes[1];
     404           0 :                     rPos ++;
     405           0 :                     pTarget[rPos] = aBytes[2];
     406           0 :                     rPos ++;
     407           0 :                     pTarget[rPos] = aBytes[3];
     408           0 :                     rPos ++;
     409           0 :                 }
     410             :             }
     411             :             else
     412             :             {
     413             :                 OSL_FAIL( "illegal Unicode character" );
     414           0 :                 bRet = false;
     415             :             }
     416             : 
     417             :             // reset surrogate
     418           0 :             nSurrogate = 0;
     419             :         }
     420       15281 :         else if( c > 0x07FF )
     421             :         {
     422             :             sal_Int8 aBytes[] = { sal_Int8(0xE0 | ((c >> 12) & 0x0F)),
     423       13787 :                                   sal_Int8(0x80 | ((c >>  6) & 0x3F)),
     424       27574 :                                   sal_Int8(0x80 | ((c >>  0) & 0x3F)) };
     425       13787 :             if ((rPos + 3) > SEQUENCESIZE)
     426           1 :                 AddBytes(pTarget, rPos, aBytes, 3);
     427             :             else
     428             :             {
     429       13786 :                 pTarget[rPos] = aBytes[0];
     430       13786 :                 rPos ++;
     431       13786 :                 pTarget[rPos] = aBytes[1];
     432       13786 :                 rPos ++;
     433       13786 :                 pTarget[rPos] = aBytes[2];
     434       13786 :                 rPos ++;
     435             :             }
     436             :         }
     437             :         else
     438             :         {
     439        1494 :             sal_Int8 aBytes[] = { sal_Int8(0xC0 | ((c >>  6) & 0x1F)),
     440        1494 :                                 sal_Int8(0x80 | ((c >>  0) & 0x3F)) };
     441        1494 :             if ((rPos + 2) > SEQUENCESIZE)
     442           0 :                 AddBytes(pTarget, rPos, aBytes, 2);
     443             :             else
     444             :             {
     445        1494 :                 pTarget[rPos] = aBytes[0];
     446        1494 :                 rPos ++;
     447        1494 :                 pTarget[rPos] = aBytes[1];
     448        1494 :                 rPos ++;
     449             :             }
     450             :         }
     451             :         OSL_ENSURE(rPos <= SEQUENCESIZE, "not reset current position");
     452    16367510 :         if (rPos == SEQUENCESIZE)
     453       13187 :             rPos = writeSequence();
     454             : 
     455             :         // reset left-over surrogate
     456    16367510 :         if( ( nSurrogate != 0 ) && !( c >= 0xd800 && c < 0xdc00 ) )
     457             :         {
     458             :             OSL_ENSURE( nSurrogate != 0, "left-over Unicode surrogate" );
     459           0 :             nSurrogate = 0;
     460           0 :             bRet = false;
     461             :         }
     462             :     }
     463     1363820 :     return bRet;
     464             : }
     465             : 
     466     1755755 : inline void SaxWriterHelper::FinishStartElement() throw( SAXException )
     467             : {
     468     1755755 :     if (!m_bStartElementFinished)
     469             :     {
     470      136568 :         mp_Sequence[nCurrentPos] = '>';
     471      136568 :         nCurrentPos++;
     472      136568 :         if (nCurrentPos == SEQUENCESIZE)
     473          93 :             nCurrentPos = writeSequence();
     474      136568 :         m_bStartElementFinished = true;
     475             :     }
     476     1755755 : }
     477             : 
     478        4723 : inline void SaxWriterHelper::insertIndentation(sal_uInt32 m_nLevel) throw( SAXException )
     479             : {
     480        4723 :     FinishStartElement();
     481        4723 :     if (m_nLevel > 0)
     482             :     {
     483        1583 :         if ((nCurrentPos + m_nLevel + 1) <= SEQUENCESIZE)
     484             :         {
     485        1583 :             mp_Sequence[nCurrentPos] = LINEFEED;
     486        1583 :             nLastLineFeedPos = nCurrentPos;
     487        1583 :             nCurrentPos++;
     488        1583 :             memset( &(mp_Sequence[nCurrentPos]) , 32 , m_nLevel );
     489        1583 :             nCurrentPos += m_nLevel;
     490        1583 :             if (nCurrentPos == SEQUENCESIZE)
     491           0 :                 nCurrentPos = writeSequence();
     492             :         }
     493             :         else
     494             :         {
     495           0 :             sal_uInt32 nCount(m_nLevel + 1);
     496           0 :             boost::scoped_array<sal_Int8> pBytes(new sal_Int8[nCount]);
     497           0 :             pBytes[0] = LINEFEED;
     498           0 :             memset( &(pBytes[1]), 32, m_nLevel );
     499           0 :             AddBytes(mp_Sequence, nCurrentPos, pBytes.get(), nCount);
     500           0 :             pBytes.reset();
     501           0 :             nLastLineFeedPos = nCurrentPos - nCount;
     502           0 :             if (nCurrentPos == SEQUENCESIZE)
     503           0 :                 nCurrentPos = writeSequence();
     504             :         }
     505             :     }
     506             :     else
     507             :     {
     508        3140 :         mp_Sequence[nCurrentPos] = LINEFEED;
     509        3140 :         nLastLineFeedPos = nCurrentPos;
     510        3140 :         nCurrentPos++;
     511        3140 :         if (nCurrentPos == SEQUENCESIZE)
     512           0 :             nCurrentPos = writeSequence();
     513             :     }
     514        4723 : }
     515             : 
     516     1363820 : inline bool SaxWriterHelper::writeString( const OUString& rWriteOutString,
     517             :                         bool bDoNormalization,
     518             :                         bool bNormalizeWhitespace ) throw( SAXException )
     519             : {
     520     1363820 :     FinishStartElement();
     521             :     return convertToXML(rWriteOutString.getStr(),
     522             :                     rWriteOutString.getLength(),
     523             :                     bDoNormalization,
     524             :                     bNormalizeWhitespace,
     525             :                     mp_Sequence,
     526     1363820 :                     nCurrentPos);
     527             : }
     528             : 
     529        7012 : inline void SaxWriterHelper::startDocument() throw( SAXException )
     530             : {
     531        7012 :     const char pc[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
     532        7012 :     const int nLen = strlen( pc );
     533        7012 :     if ((nCurrentPos + nLen) <= SEQUENCESIZE)
     534             :     {
     535        7012 :         memcpy( mp_Sequence, pc , nLen );
     536        7012 :         nCurrentPos += nLen;
     537             :     }
     538             :     else
     539             :     {
     540           0 :         AddBytes(mp_Sequence, nCurrentPos, reinterpret_cast<sal_Int8 const *>(pc), nLen);
     541             :     }
     542             :     OSL_ENSURE(nCurrentPos <= SEQUENCESIZE, "not reset current position");
     543        7012 :     if (nCurrentPos == SEQUENCESIZE)
     544           0 :         nCurrentPos = writeSequence();
     545        7012 :     mp_Sequence[nCurrentPos] = LINEFEED;
     546        7012 :     nCurrentPos++;
     547        7012 :     if (nCurrentPos == SEQUENCESIZE)
     548           0 :         nCurrentPos = writeSequence();
     549        7012 : }
     550             : 
     551      250629 : inline SaxInvalidCharacterError SaxWriterHelper::startElement(const OUString& rName, const Reference< XAttributeList >& xAttribs) throw( SAXException )
     552             : {
     553      250629 :     FinishStartElement();
     554             : 
     555             : #ifdef DBG_UTIL
     556             :     m_DebugStartedElements.push(rName);
     557             :     ::std::set<OUString> DebugAttributes;
     558             : #endif
     559             : 
     560      250629 :     mp_Sequence[nCurrentPos] = '<';
     561      250629 :     nCurrentPos++;
     562      250629 :     if (nCurrentPos == SEQUENCESIZE)
     563         472 :         nCurrentPos = writeSequence();
     564             : 
     565      250629 :     SaxInvalidCharacterError eRet(SAX_NONE);
     566      250629 :     if (!writeString(rName, false, false))
     567           0 :         eRet = SAX_ERROR;
     568             : 
     569      250629 :     sal_Int16 nAttribCount = xAttribs.is() ? static_cast<sal_Int16>(xAttribs->getLength()) : 0;
     570      708794 :     for(sal_Int16 i = 0 ; i < nAttribCount ; i++ )
     571             :     {
     572      458165 :         mp_Sequence[nCurrentPos] = ' ';
     573      458165 :         nCurrentPos++;
     574      458165 :         if (nCurrentPos == SEQUENCESIZE)
     575         354 :             nCurrentPos = writeSequence();
     576             : 
     577      458165 :         OUString const& rAttrName(xAttribs->getNameByIndex(i));
     578             : #ifdef DBG_UTIL
     579             :         // Well-formedness constraint: Unique Att Spec
     580             :         assert(DebugAttributes.find(rAttrName) == DebugAttributes.end());
     581             :         DebugAttributes.insert(rAttrName);
     582             : #endif
     583      458165 :         if (!writeString(rAttrName, false, false))
     584           0 :             eRet = SAX_ERROR;
     585             : 
     586      458165 :         mp_Sequence[nCurrentPos] = '=';
     587      458165 :         nCurrentPos++;
     588      458165 :         if (nCurrentPos == SEQUENCESIZE)
     589         448 :             nCurrentPos = writeSequence();
     590      458165 :         mp_Sequence[nCurrentPos] = '"';
     591      458165 :         nCurrentPos++;
     592      458165 :         if (nCurrentPos == SEQUENCESIZE)
     593         463 :             nCurrentPos = writeSequence();
     594             : 
     595      458165 :         if (!writeString(xAttribs->getValueByIndex( i ), true, true) &&
     596             :             !(eRet == SAX_ERROR))
     597           0 :             eRet = SAX_WARNING;
     598             : 
     599      458165 :         mp_Sequence[nCurrentPos] = '"';
     600      458165 :         nCurrentPos++;
     601      458165 :         if (nCurrentPos == SEQUENCESIZE)
     602         304 :             nCurrentPos = writeSequence();
     603      458165 :     }
     604             : 
     605      250629 :     m_bStartElementFinished = false;    // because the '>' character is not added,
     606             :                                             // because it is possible, that the "/>"
     607             :                                             // characters have to add
     608      250629 :     return eRet;
     609             : }
     610             : 
     611      250629 : inline bool SaxWriterHelper::FinishEmptyElement() throw( SAXException )
     612             : {
     613      250629 :     if (m_bStartElementFinished)
     614      136568 :         return false;
     615             : 
     616      114061 :     mp_Sequence[nCurrentPos] = '/';
     617      114061 :     nCurrentPos++;
     618      114061 :     if (nCurrentPos == SEQUENCESIZE)
     619          53 :         nCurrentPos = writeSequence();
     620      114061 :     mp_Sequence[nCurrentPos] = '>';
     621      114061 :     nCurrentPos++;
     622      114061 :     if (nCurrentPos == SEQUENCESIZE)
     623          38 :         nCurrentPos = writeSequence();
     624             : 
     625      114061 :     m_bStartElementFinished = true;
     626             : 
     627      114061 :     return true;
     628             : }
     629             : 
     630      136568 : inline bool SaxWriterHelper::endElement(const OUString& rName) throw( SAXException )
     631             : {
     632      136568 :     FinishStartElement();
     633             : 
     634      136568 :     mp_Sequence[nCurrentPos] = '<';
     635      136568 :     nCurrentPos++;
     636      136568 :     if (nCurrentPos == SEQUENCESIZE)
     637          55 :         nCurrentPos = writeSequence();
     638      136568 :     mp_Sequence[nCurrentPos] = '/';
     639      136568 :     nCurrentPos++;
     640      136568 :     if (nCurrentPos == SEQUENCESIZE)
     641          95 :         nCurrentPos = writeSequence();
     642             : 
     643      136568 :     bool bRet(writeString( rName, false, false));
     644             : 
     645      136568 :     mp_Sequence[nCurrentPos] = '>';
     646      136568 :     nCurrentPos++;
     647      136568 :     if (nCurrentPos == SEQUENCESIZE)
     648          61 :         nCurrentPos = writeSequence();
     649             : 
     650      136568 :     return bRet;
     651             : }
     652             : 
     653        7012 : inline void SaxWriterHelper::endDocument() throw( SAXException )
     654             : {
     655        7012 :     if (nCurrentPos > 0)
     656             :     {
     657        7012 :         m_Sequence.realloc(nCurrentPos);
     658        7012 :         nCurrentPos = writeSequence();
     659             :         //m_Sequence.realloc(SEQUENCESIZE);
     660             :     }
     661        7012 : }
     662             : 
     663           0 : inline void SaxWriterHelper::clearBuffer() throw( SAXException )
     664             : {
     665           0 :     FinishStartElement();
     666           0 :     if (nCurrentPos > 0)
     667             :     {
     668           0 :         m_Sequence.realloc(nCurrentPos);
     669           0 :         nCurrentPos = writeSequence();
     670           0 :         m_Sequence.realloc(SEQUENCESIZE);
     671             :         // Be sure to update the array pointer after the reallocation.
     672           0 :         mp_Sequence = m_Sequence.getArray();
     673             :     }
     674           0 : }
     675             : 
     676          12 : inline bool SaxWriterHelper::processingInstruction(const OUString& rTarget, const OUString& rData) throw( SAXException )
     677             : {
     678          12 :     FinishStartElement();
     679          12 :     mp_Sequence[nCurrentPos] = '<';
     680          12 :     nCurrentPos++;
     681          12 :     if (nCurrentPos == SEQUENCESIZE)
     682           0 :         nCurrentPos = writeSequence();
     683          12 :     mp_Sequence[nCurrentPos] = '?';
     684          12 :     nCurrentPos++;
     685          12 :     if (nCurrentPos == SEQUENCESIZE)
     686           0 :         nCurrentPos = writeSequence();
     687             : 
     688          12 :     bool bRet(writeString( rTarget, false, false ));
     689             : 
     690          12 :     mp_Sequence[nCurrentPos] = ' ';
     691          12 :     nCurrentPos++;
     692          12 :     if (nCurrentPos == SEQUENCESIZE)
     693           0 :         nCurrentPos = writeSequence();
     694             : 
     695          12 :     if (!writeString( rData, false, false ))
     696           0 :         bRet = false;
     697             : 
     698          12 :     mp_Sequence[nCurrentPos] = '?';
     699          12 :     nCurrentPos++;
     700          12 :     if (nCurrentPos == SEQUENCESIZE)
     701           0 :         nCurrentPos = writeSequence();
     702          12 :     mp_Sequence[nCurrentPos] = '>';
     703          12 :     nCurrentPos++;
     704          12 :     if (nCurrentPos == SEQUENCESIZE)
     705           0 :         nCurrentPos = writeSequence();
     706             : 
     707          12 :     return bRet;
     708             : }
     709             : 
     710           0 : inline void SaxWriterHelper::startCDATA() throw( SAXException )
     711             : {
     712           0 :     FinishStartElement();
     713           0 :     if ((nCurrentPos + 9) <= SEQUENCESIZE)
     714             :     {
     715           0 :         memcpy( &(mp_Sequence[nCurrentPos]), "<![CDATA[" , 9 );
     716           0 :         nCurrentPos += 9;
     717             :     }
     718             :     else
     719           0 :         AddBytes(mp_Sequence, nCurrentPos, reinterpret_cast<sal_Int8 const *>("<![CDATA["), 9);
     720           0 :     if (nCurrentPos == SEQUENCESIZE)
     721           0 :         nCurrentPos = writeSequence();
     722           0 : }
     723             : 
     724           0 : inline void SaxWriterHelper::endCDATA() throw( SAXException )
     725             : {
     726           0 :     FinishStartElement();
     727           0 :     if ((nCurrentPos + 3) <= SEQUENCESIZE)
     728             :     {
     729           0 :         memcpy( &(mp_Sequence[nCurrentPos]), "]]>" , 3 );
     730           0 :         nCurrentPos += 3;
     731             :     }
     732             :     else
     733           0 :         AddBytes(mp_Sequence, nCurrentPos, reinterpret_cast<sal_Int8 const *>("]]>"), 3);
     734           0 :     if (nCurrentPos == SEQUENCESIZE)
     735           0 :         nCurrentPos = writeSequence();
     736           0 : }
     737             : 
     738           3 : inline bool SaxWriterHelper::comment(const OUString& rComment) throw( SAXException )
     739             : {
     740           3 :     FinishStartElement();
     741           3 :     mp_Sequence[nCurrentPos] = '<';
     742           3 :     nCurrentPos++;
     743           3 :     if (nCurrentPos == SEQUENCESIZE)
     744           0 :         nCurrentPos = writeSequence();
     745           3 :     mp_Sequence[nCurrentPos] = '!';
     746           3 :     nCurrentPos++;
     747           3 :     if (nCurrentPos == SEQUENCESIZE)
     748           0 :         nCurrentPos = writeSequence();
     749           3 :     mp_Sequence[nCurrentPos] = '-';
     750           3 :     nCurrentPos++;
     751           3 :     if (nCurrentPos == SEQUENCESIZE)
     752           0 :         nCurrentPos = writeSequence();
     753           3 :     mp_Sequence[nCurrentPos] = '-';
     754           3 :     nCurrentPos++;
     755           3 :     if (nCurrentPos == SEQUENCESIZE)
     756           0 :         nCurrentPos = writeSequence();
     757             : 
     758           3 :     bool bRet(writeString( rComment, false, false));
     759             : 
     760           3 :     mp_Sequence[nCurrentPos] = '-';
     761           3 :     nCurrentPos++;
     762           3 :     if (nCurrentPos == SEQUENCESIZE)
     763           0 :         nCurrentPos = writeSequence();
     764           3 :     mp_Sequence[nCurrentPos] = '-';
     765           3 :     nCurrentPos++;
     766           3 :     if (nCurrentPos == SEQUENCESIZE)
     767           0 :         nCurrentPos = writeSequence();
     768           3 :     mp_Sequence[nCurrentPos] = '>';
     769           3 :     nCurrentPos++;
     770           3 :     if (nCurrentPos == SEQUENCESIZE)
     771           0 :         nCurrentPos = writeSequence();
     772             : 
     773           3 :     return bRet;
     774             : }
     775             : 
     776           0 : inline sal_Int32 calcXMLByteLength( const sal_Unicode *pStr, sal_Int32 nStrLen,
     777             :                                     bool bDoNormalization,
     778             :                                     bool bNormalizeWhitespace )
     779             : {
     780           0 :     sal_Int32 nOutputLength = 0;
     781           0 :     sal_uInt32 nSurrogate = 0;
     782             : 
     783           0 :     for( sal_Int32 i = 0 ; i < nStrLen ; i++ )
     784             :     {
     785           0 :         sal_uInt16 c = pStr[i];
     786           0 :         if( !IsInvalidChar(c) && (c >= 0x0001) && (c <= 0x007F) )
     787             :         {
     788           0 :             if( bDoNormalization )
     789             :             {
     790           0 :                 switch( c )
     791             :                 {
     792             :                 case '&':       // resemble to &amp;
     793           0 :                     nOutputLength +=5;
     794           0 :                     break;
     795             :                 case '<':       // &lt;
     796             :                 case '>':       // &gt;
     797           0 :                     nOutputLength +=4;
     798           0 :                     break;
     799             :                 case 39:        // 39 == ''', &apos;
     800             :                 case '"':       // &quot;
     801             :                 case 13:        // &#x0d;
     802           0 :                     nOutputLength += 6;
     803           0 :                     break;
     804             : 
     805             :                 case 10:        // &#x0a;
     806             :                 case 9:         // &#x09;
     807           0 :                     if( bNormalizeWhitespace )
     808             :                     {
     809           0 :                         nOutputLength += 6;
     810             :                     }
     811             :                     else
     812             :                     {
     813           0 :                         nOutputLength ++;
     814             :                     }
     815           0 :                     break;
     816             :                 default:
     817           0 :                     nOutputLength ++;
     818             :                 }
     819             :             }
     820             :             else
     821             :             {
     822           0 :                 nOutputLength ++;
     823             :             }
     824             :         }
     825           0 :         else if( c >= 0xd800 && c < 0xdc00  )
     826             :         {
     827             :             // save surrogate
     828           0 :             nSurrogate = ( ( c & 0x03ff ) + 0x0040 );
     829             :         }
     830           0 :         else if( c >= 0xdc00 && c < 0xe000 )
     831             :         {
     832             :             // 2. surrogate: write as UTF-8 (if range is OK
     833           0 :             nSurrogate = ( nSurrogate << 10 ) | ( c & 0x03ff );
     834           0 :             if( nSurrogate >= 0x00010000  &&  nSurrogate <= 0x0010FFFF )
     835           0 :                 nOutputLength += 4;
     836           0 :             nSurrogate = 0;
     837             :         }
     838           0 :         else if( c > 0x07FF )
     839             :         {
     840           0 :             nOutputLength += 3;
     841             :         }
     842             :         else
     843             :         {
     844           0 :             nOutputLength += 2;
     845             :         }
     846             : 
     847             :         // surrogate processing
     848           0 :         if( ( nSurrogate != 0 ) && !( c >= 0xd800 && c < 0xdc00 ) )
     849           0 :             nSurrogate = 0;
     850             :     }
     851             : 
     852           0 :     return nOutputLength;
     853             : }
     854             : 
     855             : /** returns position of first ascii 10 within the string, -1 when no 10 in string.
     856             :  */
     857           0 : static inline sal_Int32 getFirstLineBreak( const OUString & str ) throw ()
     858             : {
     859           0 :     const sal_Unicode *pSource = str.getStr();
     860           0 :     sal_Int32 nLen  = str.getLength();
     861             : 
     862           0 :     for( int n = 0; n < nLen ; n ++ )
     863             :     {
     864           0 :         if( LINEFEED == pSource[n] ) {
     865           0 :             return n;
     866             :         }
     867             :     }
     868           0 :     return -1;
     869             : }
     870             : 
     871             : class SAXWriter :
     872             :     public WeakImplHelper2<
     873             :             XWriter,
     874             :             XServiceInfo >
     875             : {
     876             : public:
     877        6286 :     SAXWriter()
     878             :         : m_pSaxWriterHelper(NULL)
     879             :         , m_bDocStarted(false)
     880             :         , m_bIsCDATA(false)
     881             :         , m_bForceLineBreak(false)
     882             :         , m_bAllowLineBreak(false)
     883        6286 :         , m_nLevel(0)
     884             :     {
     885        6286 :     }
     886       12568 :     virtual ~SAXWriter()
     887       12568 :     {
     888        6284 :         delete m_pSaxWriterHelper;
     889       12568 :     }
     890             : 
     891             : public: // XActiveDataSource
     892        7025 :     virtual void SAL_CALL setOutputStream(const Reference< XOutputStream > & aStream)
     893             :         throw (RuntimeException, std::exception) SAL_OVERRIDE
     894             :     {
     895             :         try
     896             :         {
     897             :             // temporary: set same stream again to clear buffer
     898        7025 :             if ( m_out == aStream && m_pSaxWriterHelper && m_bDocStarted )
     899           0 :                 m_pSaxWriterHelper->clearBuffer();
     900             :             else
     901             :             {
     902        7025 :                 m_out = aStream;
     903        7025 :                 delete m_pSaxWriterHelper;
     904        7025 :                 m_pSaxWriterHelper = new SaxWriterHelper(m_out);
     905        7025 :                 m_bDocStarted = false;
     906        7025 :                 m_nLevel = 0;
     907        7025 :                 m_bIsCDATA = false;
     908             :             }
     909             :         }
     910           0 :         catch (const SAXException& e)
     911             :         {
     912             :             throw css::lang::WrappedTargetRuntimeException(
     913             :                    e.Message,
     914             :                    static_cast < OWeakObject * > ( this ),
     915           0 :                    e.WrappedException);
     916             :         }
     917        7025 :     }
     918           0 :     virtual Reference< XOutputStream >  SAL_CALL getOutputStream()
     919             :         throw(RuntimeException, std::exception) SAL_OVERRIDE
     920             :     {
     921           0 :         return m_out;
     922             :     }
     923             : 
     924             : public: // XDocumentHandler
     925             :     virtual void SAL_CALL startDocument()
     926             :         throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     927             : 
     928             :     virtual void SAL_CALL endDocument()
     929             :         throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     930             : 
     931             :     virtual void SAL_CALL startElement(const OUString& aName,
     932             :                                        const Reference< XAttributeList > & xAttribs)
     933             :         throw (SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     934             : 
     935             :     virtual void SAL_CALL endElement(const OUString& aName)
     936             :         throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     937             : 
     938             :     virtual void SAL_CALL characters(const OUString& aChars)
     939             :         throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     940             : 
     941             :     virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces)
     942             :         throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     943             :     virtual void SAL_CALL processingInstruction(const OUString& aTarget,
     944             :                                                 const OUString& aData)
     945             :         throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     946             :     virtual void SAL_CALL setDocumentLocator(const Reference< XLocator > & xLocator)
     947             :         throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     948             : 
     949             : public: // XExtendedDocumentHandler
     950             :     virtual void SAL_CALL startCDATA() throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     951             :     virtual void SAL_CALL endCDATA() throw(SAXException,RuntimeException, std::exception) SAL_OVERRIDE;
     952             :     virtual void SAL_CALL comment(const OUString& sComment)
     953             :         throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     954             :     virtual void SAL_CALL unknown(const OUString& sString)
     955             :         throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
     956             :     virtual void SAL_CALL allowLineBreak()
     957             :         throw(SAXException,RuntimeException, std::exception) SAL_OVERRIDE;
     958             : 
     959             : public: // XServiceInfo
     960             :     OUString                     SAL_CALL getImplementationName() throw(std::exception) SAL_OVERRIDE;
     961             :     Sequence< OUString >         SAL_CALL getSupportedServiceNames() throw(std::exception) SAL_OVERRIDE;
     962             :     sal_Bool                    SAL_CALL supportsService(const OUString& ServiceName) throw(std::exception) SAL_OVERRIDE;
     963             : 
     964             : private:
     965             :     sal_Int32 getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurrence ) throw();
     966             : 
     967             :     Reference< XOutputStream >  m_out;
     968             :     SaxWriterHelper*            m_pSaxWriterHelper;
     969             : 
     970             :     // Status information
     971             :     bool m_bDocStarted : 1;
     972             :     bool m_bIsCDATA : 1;
     973             :     bool m_bForceLineBreak : 1;
     974             :     bool m_bAllowLineBreak : 1;
     975             :     sal_Int32 m_nLevel;
     976             : };
     977             : 
     978      447478 : sal_Int32 SAXWriter::getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurrence ) throw()
     979             : {
     980      447478 :     sal_Int32 nLength =-1;
     981      447478 :     if (m_pSaxWriterHelper)
     982             :     {
     983      452201 :         if ( m_bForceLineBreak ||
     984           0 :             (m_bAllowLineBreak &&
     985           0 :             ((nFirstLineBreakOccurrence + m_pSaxWriterHelper->GetLastColumnCount()) > MAXCOLUMNCOUNT)) )
     986        4723 :             nLength = m_nLevel;
     987             :     }
     988      447478 :     m_bForceLineBreak = false;
     989      447478 :     m_bAllowLineBreak = false;
     990      447478 :     return nLength;
     991             : }
     992             : 
     993           0 : static inline bool isFirstCharWhitespace( const sal_Unicode *p ) throw()
     994             : {
     995           0 :     return *p == ' ';
     996             : }
     997             : 
     998             : // XServiceInfo
     999           1 : OUString SAXWriter::getImplementationName() throw(std::exception)
    1000             : {
    1001           1 :     return OUString("com.sun.star.extensions.xml.sax.Writer");
    1002             : }
    1003             : 
    1004             : // XServiceInfo
    1005           0 : sal_Bool SAXWriter::supportsService(const OUString& ServiceName) throw(std::exception)
    1006             : {
    1007           0 :     return cppu::supportsService(this, ServiceName);
    1008             : }
    1009             : 
    1010             : // XServiceInfo
    1011           1 : Sequence< OUString > SAXWriter::getSupportedServiceNames() throw (std::exception)
    1012             : {
    1013           1 :     Sequence<OUString> seq(1);
    1014           1 :     seq[0] = "com.sun.star.xml.sax.Writer";
    1015           1 :     return seq;
    1016             : }
    1017             : 
    1018        7012 : void SAXWriter::startDocument()                     throw(SAXException, RuntimeException, std::exception )
    1019             : {
    1020        7012 :     if( m_bDocStarted || ! m_out.is() || !m_pSaxWriterHelper ) {
    1021           0 :         throw SAXException();
    1022             :     }
    1023        7012 :     m_bDocStarted = true;
    1024        7012 :     m_pSaxWriterHelper->startDocument();
    1025        7012 : }
    1026             : 
    1027             : 
    1028        7012 : void SAXWriter::endDocument()                   throw(SAXException, RuntimeException, std::exception)
    1029             : {
    1030        7012 :     if( ! m_bDocStarted )
    1031             :     {
    1032             :         throw SAXException(
    1033             :             "endDocument called before startDocument",
    1034           0 :             Reference< XInterface >() , Any() );
    1035             :     }
    1036        7012 :     if( m_nLevel ) {
    1037             :         throw SAXException(
    1038             :             "unexpected end of document",
    1039           0 :             Reference< XInterface >() , Any() );
    1040             :     }
    1041        7012 :     m_pSaxWriterHelper->endDocument();
    1042             :     try
    1043             :     {
    1044        7012 :         m_out->closeOutput();
    1045             :     }
    1046           0 :     catch (const IOException & e)
    1047             :     {
    1048           0 :         Any a;
    1049           0 :         a <<= e;
    1050             :         throw SAXException(
    1051             :             "IO exception during closing the IO Stream",
    1052             :             Reference< XInterface > (),
    1053           0 :             a );
    1054             :     }
    1055        7012 : }
    1056             : 
    1057             : 
    1058      250629 : void SAXWriter::startElement(const OUString& aName, const Reference< XAttributeList >& xAttribs)
    1059             :     throw(SAXException, RuntimeException, std::exception)
    1060             : {
    1061      250629 :     if( ! m_bDocStarted )
    1062             :     {
    1063           0 :         SAXException except;
    1064           0 :         except.Message = "startElement called before startDocument";
    1065           0 :         throw except;
    1066             :     }
    1067      250629 :     if( m_bIsCDATA )
    1068             :     {
    1069           0 :         SAXException except;
    1070           0 :         except.Message =  "startElement call not allowed with CDATA sections";
    1071           0 :         throw except;
    1072             :     }
    1073             : 
    1074      250629 :     sal_Int32 nLength(0);
    1075      250629 :     if (m_bAllowLineBreak)
    1076             :     {
    1077           0 :         sal_Int32 nAttribCount = xAttribs.is() ? xAttribs->getLength() : 0;
    1078             : 
    1079           0 :         nLength ++; // "<"
    1080             :         nLength += calcXMLByteLength( aName.getStr() , aName.getLength(),
    1081           0 :                                   false, false ); // the tag name
    1082             : 
    1083             :         sal_Int16 n;
    1084           0 :         for( n = 0 ; n < static_cast<sal_Int16>(nAttribCount) ; n ++ ) {
    1085           0 :             nLength ++; // " "
    1086           0 :             OUString tmp =  xAttribs->getNameByIndex( n );
    1087             : 
    1088           0 :             nLength += calcXMLByteLength( tmp.getStr() , tmp.getLength() , false, false );
    1089             : 
    1090           0 :             nLength += 2; // ="
    1091             : 
    1092           0 :             tmp = xAttribs->getValueByIndex( n );
    1093             : 
    1094           0 :             nLength += calcXMLByteLength( tmp.getStr(), tmp.getLength(), true, true );
    1095             : 
    1096           0 :             nLength += 1; // "
    1097           0 :         }
    1098             : 
    1099           0 :         nLength ++;  // '>'
    1100             :     }
    1101             : 
    1102             :     // Is there a new indentation necesarry ?
    1103      250629 :     sal_Int32 nPrefix(getIndentPrefixLength( nLength ));
    1104             : 
    1105             :     // write into sequence
    1106      250629 :     if( nPrefix >= 0 )
    1107        1573 :         m_pSaxWriterHelper->insertIndentation( nPrefix );
    1108             : 
    1109      250629 :     SaxInvalidCharacterError eRet(m_pSaxWriterHelper->startElement(aName, xAttribs));
    1110             : 
    1111      250629 :     m_nLevel++;
    1112             : 
    1113      250629 :     if (eRet == SAX_WARNING)
    1114             :     {
    1115           0 :         SAXInvalidCharacterException except;
    1116           0 :         except.Message = "Invalid character during XML-Export in a attribute value";
    1117           0 :         throw except;
    1118             :     }
    1119      250629 :     else if (eRet == SAX_ERROR)
    1120             :     {
    1121           0 :         SAXException except;
    1122           0 :         except.Message = "Invalid character during XML-Export";
    1123           0 :         throw except;
    1124             :     }
    1125      250629 : }
    1126             : 
    1127      250629 : void SAXWriter::endElement(const OUString& aName)   throw (SAXException, RuntimeException, std::exception)
    1128             : {
    1129      250629 :     if( ! m_bDocStarted ) {
    1130           0 :         throw SAXException ();
    1131             :     }
    1132      250629 :     m_nLevel --;
    1133             : 
    1134      250629 :     if( m_nLevel < 0 ) {
    1135           0 :         throw SAXException();
    1136             :     }
    1137      250629 :     bool bRet(true);
    1138             : 
    1139             :     // check here because Helper's endElement is not always called
    1140             : #ifdef DBG_UTIL
    1141             :     assert(!m_pSaxWriterHelper->m_DebugStartedElements.empty());
    1142             :     // Well-formedness constraint: Element Type Match
    1143             :     assert(aName == m_pSaxWriterHelper->m_DebugStartedElements.top());
    1144             :     m_pSaxWriterHelper->m_DebugStartedElements.pop();
    1145             : #endif
    1146             : 
    1147      250629 :     if( m_pSaxWriterHelper->FinishEmptyElement() )
    1148      114061 :         m_bForceLineBreak = false;
    1149             :     else
    1150             :     {
    1151             :         // only ascii chars allowed
    1152      136568 :         sal_Int32 nLength(0);
    1153      136568 :         if (m_bAllowLineBreak)
    1154           0 :             nLength = 3 + calcXMLByteLength( aName.getStr(), aName.getLength(), false, false );
    1155      136568 :         sal_Int32 nPrefix = getIndentPrefixLength( nLength );
    1156             : 
    1157      136568 :         if( nPrefix >= 0 )
    1158        3150 :             m_pSaxWriterHelper->insertIndentation( nPrefix );
    1159             : 
    1160      136568 :         bRet = m_pSaxWriterHelper->endElement(aName);
    1161             :     }
    1162             : 
    1163      250629 :     if (!bRet)
    1164             :     {
    1165           0 :         SAXException except;
    1166           0 :         except.Message = "Invalid character during XML-Export";
    1167           0 :         throw except;
    1168             :     }
    1169      250629 : }
    1170             : 
    1171       60371 : void SAXWriter::characters(const OUString& aChars)  throw(SAXException, RuntimeException, std::exception)
    1172             : {
    1173       60371 :     if( ! m_bDocStarted )
    1174             :     {
    1175           0 :         SAXException except;
    1176           0 :         except.Message = "characters method called before startDocument";
    1177           0 :         throw except;
    1178             :     }
    1179             : 
    1180       60371 :     bool bThrowException(false);
    1181       60371 :     if( !aChars.isEmpty() )
    1182             :     {
    1183       60254 :         if( m_bIsCDATA )
    1184           0 :             bThrowException = !m_pSaxWriterHelper->writeString( aChars, false, false );
    1185             :         else
    1186             :         {
    1187             :             // Note : nFirstLineBreakOccurrence is not exact, because we don't know, how
    1188             :             //        many 2 and 3 byte chars are inbetween. However this whole stuff
    1189             :             //        is eitherway for pretty printing only, so it does not need to be exact.
    1190       60254 :             sal_Int32 nLength(0);
    1191       60254 :             sal_Int32 nIndentPrefix(-1);
    1192       60254 :             if (m_bAllowLineBreak)
    1193             :             {
    1194           0 :                 sal_Int32 nFirstLineBreakOccurrence = getFirstLineBreak( aChars );
    1195             : 
    1196             :                 nLength = calcXMLByteLength( aChars.getStr(), aChars.getLength(),
    1197           0 :                                                ! m_bIsCDATA , false );
    1198             :                 nIndentPrefix = getIndentPrefixLength(
    1199           0 :                     nFirstLineBreakOccurrence >= 0 ? nFirstLineBreakOccurrence : nLength );
    1200             :             }
    1201             :             else
    1202       60254 :                 nIndentPrefix = getIndentPrefixLength(nLength);
    1203             : 
    1204             :             // insert indentation
    1205       60254 :             if( nIndentPrefix >= 0 )
    1206             :             {
    1207           0 :                 if( isFirstCharWhitespace( aChars.getStr() ) )
    1208           0 :                     m_pSaxWriterHelper->insertIndentation( nIndentPrefix - 1 );
    1209             :                 else
    1210           0 :                     m_pSaxWriterHelper->insertIndentation( nIndentPrefix );
    1211             :             }
    1212       60254 :             bThrowException = !m_pSaxWriterHelper->writeString(aChars, true , false);
    1213             :         }
    1214             :     }
    1215       60371 :     if (bThrowException)
    1216             :     {
    1217           0 :         SAXInvalidCharacterException except;
    1218           0 :         except.Message = "Invalid character during XML-Export";
    1219           0 :         throw except;
    1220             :     }
    1221       60371 : }
    1222             : 
    1223             : 
    1224       22610 : void SAXWriter::ignorableWhitespace(const OUString&) throw(SAXException, RuntimeException, std::exception)
    1225             : {
    1226       22610 :     if( ! m_bDocStarted )
    1227             :     {
    1228           0 :         throw SAXException ();
    1229             :     }
    1230             : 
    1231       22610 :     m_bForceLineBreak = true;
    1232       22610 : }
    1233             : 
    1234          12 : void SAXWriter::processingInstruction(const OUString& aTarget, const OUString& aData)
    1235             :     throw (SAXException, RuntimeException, std::exception)
    1236             : {
    1237          12 :     if( ! m_bDocStarted || m_bIsCDATA )
    1238             :     {
    1239           0 :         throw SAXException();
    1240             :     }
    1241             : 
    1242          12 :     sal_Int32 nLength(0);
    1243          12 :     if (m_bAllowLineBreak)
    1244             :     {
    1245           0 :         nLength = 2;  // "<?"
    1246           0 :         nLength += calcXMLByteLength( aTarget.getStr(), aTarget.getLength(), false, false );
    1247             : 
    1248           0 :         nLength += 1;  // " "
    1249             : 
    1250           0 :         nLength += calcXMLByteLength( aData.getStr(), aData.getLength(), false, false );
    1251             : 
    1252           0 :         nLength += 2; // "?>"
    1253             :     }
    1254             : 
    1255          12 :     sal_Int32 nPrefix = getIndentPrefixLength( nLength );
    1256             : 
    1257          12 :     if( nPrefix >= 0 )
    1258           0 :         m_pSaxWriterHelper->insertIndentation( nPrefix );
    1259             : 
    1260          12 :     if (!m_pSaxWriterHelper->processingInstruction(aTarget, aData))
    1261             :     {
    1262           0 :         SAXException except;
    1263           0 :         except.Message = "Invalid character during XML-Export";
    1264           0 :         throw except;
    1265             :     }
    1266          12 : }
    1267             : 
    1268             : 
    1269           0 : void SAXWriter::setDocumentLocator(const Reference< XLocator >&)
    1270             :         throw (SAXException, RuntimeException, std::exception)
    1271             : {
    1272             : 
    1273           0 : }
    1274             : 
    1275           0 : void SAXWriter::startCDATA() throw(SAXException, RuntimeException, std::exception)
    1276             : {
    1277           0 :     if( ! m_bDocStarted || m_bIsCDATA)
    1278             :     {
    1279           0 :         throw SAXException ();
    1280             :     }
    1281             : 
    1282           0 :     sal_Int32 nLength = 9;
    1283           0 :     sal_Int32 nPrefix = getIndentPrefixLength( nLength );
    1284           0 :     if( nPrefix >= 0 )
    1285           0 :         m_pSaxWriterHelper->insertIndentation( nPrefix );
    1286             : 
    1287           0 :     m_pSaxWriterHelper->startCDATA();
    1288             : 
    1289           0 :     m_bIsCDATA = true;
    1290           0 : }
    1291             : 
    1292           0 : void SAXWriter::endCDATA() throw (SAXException,RuntimeException, std::exception)
    1293             : {
    1294           0 :     if( ! m_bDocStarted || ! m_bIsCDATA)
    1295             :     {
    1296           0 :         SAXException except;
    1297           0 :         except.Message = "endCDATA was called without startCDATA";
    1298           0 :         throw except;
    1299             :     }
    1300             : 
    1301           0 :     sal_Int32 nLength = 3;
    1302           0 :     sal_Int32 nPrefix = getIndentPrefixLength( nLength );
    1303           0 :     if( nPrefix >= 0 )
    1304           0 :         m_pSaxWriterHelper->insertIndentation( nPrefix );
    1305             : 
    1306           0 :     m_pSaxWriterHelper->endCDATA();
    1307             : 
    1308           0 :     m_bIsCDATA = false;
    1309           0 : }
    1310             : 
    1311             : 
    1312           3 : void SAXWriter::comment(const OUString& sComment) throw(SAXException, RuntimeException, std::exception)
    1313             : {
    1314           3 :     if( ! m_bDocStarted || m_bIsCDATA )
    1315             :     {
    1316           0 :         throw SAXException();
    1317             :     }
    1318             : 
    1319           3 :     sal_Int32 nLength(0);
    1320           3 :     if (m_bAllowLineBreak)
    1321             :     {
    1322           0 :         nLength = 4; // "<!--"
    1323           0 :         nLength += calcXMLByteLength( sComment.getStr(), sComment.getLength(), false, false);
    1324             : 
    1325           0 :         nLength += 3;
    1326             :     }
    1327             : 
    1328           3 :     sal_Int32 nPrefix = getIndentPrefixLength( nLength );
    1329           3 :     if( nPrefix >= 0 )
    1330           0 :         m_pSaxWriterHelper->insertIndentation( nPrefix );
    1331             : 
    1332           3 :     if (!m_pSaxWriterHelper->comment(sComment))
    1333             :     {
    1334           0 :         SAXException except;
    1335           0 :         except.Message = "Invalid character during XML-Export";
    1336           0 :         throw except;
    1337             :     }
    1338           3 : }
    1339             : 
    1340             : 
    1341           0 : void SAXWriter::allowLineBreak( )   throw ( SAXException , RuntimeException, std::exception)
    1342             : {
    1343           0 :     if( ! m_bDocStarted || m_bAllowLineBreak ) {
    1344           0 :         throw SAXException();
    1345             :     }
    1346             : 
    1347           0 :      m_bAllowLineBreak = true;
    1348           0 : }
    1349             : 
    1350          12 : void SAXWriter::unknown(const OUString& sString) throw (SAXException, RuntimeException, std::exception)
    1351             : {
    1352             : 
    1353          12 :     if( ! m_bDocStarted )
    1354             :     {
    1355           0 :         throw SAXException ();
    1356             :     }
    1357          12 :     if( m_bIsCDATA )
    1358             :     {
    1359           0 :         throw SAXException();
    1360             :     }
    1361             : 
    1362          12 :     if( sString.startsWith( "<?xml" ) )
    1363          12 :         return;
    1364             : 
    1365          12 :     sal_Int32 nLength(0);
    1366          12 :     if (m_bAllowLineBreak)
    1367           0 :         nLength = calcXMLByteLength( sString.getStr(), sString.getLength(), false, false );
    1368             : 
    1369          12 :     sal_Int32 nPrefix = getIndentPrefixLength( nLength );
    1370          12 :     if( nPrefix >= 0 )
    1371           0 :         m_pSaxWriterHelper->insertIndentation( nPrefix );
    1372             : 
    1373          12 :     if (!m_pSaxWriterHelper->writeString( sString, false, false))
    1374             :     {
    1375           0 :         SAXException except;
    1376           0 :         except.Message = "Invalid character during XML-Export";
    1377           0 :         throw except;
    1378             :     }
    1379             : }
    1380             : 
    1381             : } // namespace
    1382             : 
    1383             : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
    1384        6286 : com_sun_star_extensions_xml_sax_Writer_get_implementation(
    1385             :     css::uno::XComponentContext *,
    1386             :     css::uno::Sequence<css::uno::Any> const &)
    1387             : {
    1388        6286 :     return cppu::acquire(new SAXWriter);
    1389             : }
    1390             : 
    1391             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11