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

Generated by: LCOV version 1.10