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

Generated by: LCOV version 1.10