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

Generated by: LCOV version 1.10