LCOV - code coverage report
Current view: top level - sax/source/expatwrap - saxwriter.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 618 0.0 %
Date: 2014-04-14 Functions: 0 46 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * 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           0 :     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           0 :         m_bStartElementFinished(true)
     116             :     {
     117             :         OSL_ENSURE(SEQUENCESIZE > 50, "Sequence cache size to small");
     118           0 :         mp_Sequence = m_Sequence.getArray();
     119           0 :     }
     120           0 :     ~SaxWriterHelper()
     121           0 :     {
     122             :         OSL_ENSURE(!nCurrentPos, "cached Sequence not written");
     123             :         OSL_ENSURE(m_bStartElementFinished, "StartElement not complettly written");
     124           0 :     }
     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           0 : inline bool IsInvalidChar(const sal_Unicode aChar)
     177             : {
     178           0 :     bool bRet(false);
     179             :     // check first for the most common characters
     180           0 :     if( aChar < 32 || aChar >= 0xd800 )
     181           0 :         bRet = ( (aChar < 32 && ! g_bValidCharsBelow32[aChar]) ||
     182           0 :             aChar == 0xffff ||
     183           0 :             aChar == 0xfffe );
     184           0 :     return bRet;
     185             : }
     186             : 
     187             : /********
     188             : * write through to the output stream
     189             : *
     190             : *****/
     191           0 : inline sal_uInt32 SaxWriterHelper::writeSequence() throw( SAXException )
     192             : {
     193             :     try
     194             :     {
     195           0 :         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           0 :     nLastLineFeedPos -= SEQUENCESIZE;
     207           0 :     return 0;
     208             : }
     209             : 
     210           0 : 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           0 :     sal_uInt32 nCount(SEQUENCESIZE - rPos);
     215           0 :     memcpy( &(pTarget[rPos]) , pBytes,  nCount);
     216             : 
     217             :     OSL_ENSURE(rPos + nCount == SEQUENCESIZE, "the position should be the at the end");
     218             : 
     219           0 :     rPos = writeSequence();
     220           0 :     sal_uInt32 nRestCount(nBytesCount - nCount);
     221           0 :     if ((rPos + nRestCount) <= SEQUENCESIZE)
     222             :     {
     223           0 :         memcpy( &(pTarget[rPos]), &pBytes[nCount], nRestCount);
     224           0 :         rPos += nRestCount;
     225             :     }
     226             :     else
     227           0 :         AddBytes(pTarget, rPos, &pBytes[nCount], nRestCount);
     228           0 : }
     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           0 : 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           0 :     bool bRet(true);
     245           0 :     sal_uInt32 nSurrogate = 0;
     246             : 
     247           0 :     for( sal_Int32 i = 0 ; i < nStrLen ; i ++ )
     248             :     {
     249           0 :         sal_uInt16 c = pStr[i];
     250           0 :         if (IsInvalidChar(c))
     251           0 :             bRet = false;
     252           0 :         else if( (c >= 0x0001) && (c <= 0x007F) )
     253             :         {
     254           0 :             if( bDoNormalization )
     255             :             {
     256           0 :                 switch( c )
     257             :                 {
     258             :                     case '&':  // resemble to &amp;
     259             :                     {
     260           0 :                         if ((rPos + 5) > SEQUENCESIZE)
     261           0 :                             AddBytes(pTarget, rPos, (sal_Int8*)"&amp;", 5);
     262             :                         else
     263             :                         {
     264           0 :                             memcpy( &(pTarget[rPos]) , "&amp;", 5 );
     265           0 :                             rPos += 5;
     266             :                         }
     267             :                     }
     268           0 :                     break;
     269             :                     case '<':
     270             :                     {
     271           0 :                         if ((rPos + 4) > SEQUENCESIZE)
     272           0 :                             AddBytes(pTarget, rPos, (sal_Int8*)"&lt;", 4);
     273             :                         else
     274             :                         {
     275           0 :                             memcpy( &(pTarget[rPos]) , "&lt;" , 4 );
     276           0 :                             rPos += 4;        // &lt;
     277             :                         }
     278             :                     }
     279           0 :                     break;
     280             :                     case '>':
     281             :                     {
     282           0 :                         if ((rPos + 4) > SEQUENCESIZE)
     283           0 :                             AddBytes(pTarget, rPos, (sal_Int8*)"&gt;", 4);
     284             :                         else
     285             :                         {
     286           0 :                             memcpy( &(pTarget[rPos]) , "&gt;" , 4 );
     287           0 :                             rPos += 4;        // &gt;
     288             :                         }
     289             :                     }
     290           0 :                     break;
     291             :                     case 39:                 // 39 == '''
     292             :                     {
     293           0 :                         if ((rPos + 6) > SEQUENCESIZE)
     294           0 :                             AddBytes(pTarget, rPos, (sal_Int8*)"&apos;", 6);
     295             :                         else
     296             :                         {
     297           0 :                             memcpy( &(pTarget[rPos]) , "&apos;" , 6 );
     298           0 :                             rPos += 6;        // &apos;
     299             :                         }
     300             :                     }
     301           0 :                     break;
     302             :                     case '"':
     303             :                     {
     304           0 :                         if ((rPos + 6) > SEQUENCESIZE)
     305           0 :                             AddBytes(pTarget, rPos, (sal_Int8*)"&quot;", 6);
     306             :                         else
     307             :                         {
     308           0 :                             memcpy( &(pTarget[rPos]) , "&quot;" , 6 );
     309           0 :                             rPos += 6;        // &quot;
     310             :                         }
     311             :                     }
     312           0 :                     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           0 :                         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           0 :                             pTarget[rPos] = LINEFEED;
     339           0 :                             nLastLineFeedPos = rPos;
     340           0 :                             rPos ++;
     341             :                         }
     342             :                     }
     343           0 :                     break;
     344             :                     case 9:
     345             :                     {
     346           0 :                         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           0 :                             pTarget[rPos] = 9;
     359           0 :                             rPos ++;
     360             :                         }
     361             :                     }
     362           0 :                     break;
     363             :                     default:
     364             :                     {
     365           0 :                         pTarget[rPos] = (sal_Int8)c;
     366           0 :                         rPos ++;
     367             :                     }
     368           0 :                     break;
     369             :                 }
     370             :             }
     371             :             else
     372             :             {
     373           0 :                 pTarget[rPos] = (sal_Int8)c;
     374           0 :                 if ((sal_Int8)c == LINEFEED)
     375           0 :                     nLastLineFeedPos = rPos;
     376           0 :                 rPos ++;
     377             :             }
     378             :         }
     379           0 :         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           0 :         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           0 :         else if( c > 0x07FF )
     421             :         {
     422             :             sal_Int8 aBytes[] = { sal_Int8(0xE0 | ((c >> 12) & 0x0F)),
     423           0 :                                   sal_Int8(0x80 | ((c >>  6) & 0x3F)),
     424           0 :                                   sal_Int8(0x80 | ((c >>  0) & 0x3F)) };
     425           0 :             if ((rPos + 3) > SEQUENCESIZE)
     426           0 :                 AddBytes(pTarget, rPos, aBytes, 3);
     427             :             else
     428             :             {
     429           0 :                 pTarget[rPos] = aBytes[0];
     430           0 :                 rPos ++;
     431           0 :                 pTarget[rPos] = aBytes[1];
     432           0 :                 rPos ++;
     433           0 :                 pTarget[rPos] = aBytes[2];
     434           0 :                 rPos ++;
     435             :             }
     436             :         }
     437             :         else
     438             :         {
     439           0 :             sal_Int8 aBytes[] = { sal_Int8(0xC0 | ((c >>  6) & 0x1F)),
     440           0 :                                 sal_Int8(0x80 | ((c >>  0) & 0x3F)) };
     441           0 :             if ((rPos + 2) > SEQUENCESIZE)
     442           0 :                 AddBytes(pTarget, rPos, aBytes, 2);
     443             :             else
     444             :             {
     445           0 :                 pTarget[rPos] = aBytes[0];
     446           0 :                 rPos ++;
     447           0 :                 pTarget[rPos] = aBytes[1];
     448           0 :                 rPos ++;
     449             :             }
     450             :         }
     451             :         OSL_ENSURE(rPos <= SEQUENCESIZE, "not reset current position");
     452           0 :         if (rPos == SEQUENCESIZE)
     453           0 :             rPos = writeSequence();
     454             : 
     455             :         // reset left-over surrogate
     456           0 :         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           0 :     return bRet;
     464             : }
     465             : 
     466           0 : inline void SaxWriterHelper::FinishStartElement() throw( SAXException )
     467             : {
     468           0 :     if (!m_bStartElementFinished)
     469             :     {
     470           0 :         mp_Sequence[nCurrentPos] = '>';
     471           0 :         nCurrentPos++;
     472           0 :         if (nCurrentPos == SEQUENCESIZE)
     473           0 :             nCurrentPos = writeSequence();
     474           0 :         m_bStartElementFinished = true;
     475             :     }
     476           0 : }
     477             : 
     478           0 : inline void SaxWriterHelper::insertIndentation(sal_uInt32 m_nLevel) throw( SAXException )
     479             : {
     480           0 :     FinishStartElement();
     481           0 :     if (m_nLevel > 0)
     482             :     {
     483           0 :         if ((nCurrentPos + m_nLevel + 1) <= SEQUENCESIZE)
     484             :         {
     485           0 :             mp_Sequence[nCurrentPos] = LINEFEED;
     486           0 :             nLastLineFeedPos = nCurrentPos;
     487           0 :             nCurrentPos++;
     488           0 :             memset( &(mp_Sequence[nCurrentPos]) , 32 , m_nLevel );
     489           0 :             nCurrentPos += m_nLevel;
     490           0 :             if (nCurrentPos == SEQUENCESIZE)
     491           0 :                 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           0 :         mp_Sequence[nCurrentPos] = LINEFEED;
     509           0 :         nLastLineFeedPos = nCurrentPos;
     510           0 :         nCurrentPos++;
     511           0 :         if (nCurrentPos == SEQUENCESIZE)
     512           0 :             nCurrentPos = writeSequence();
     513             :     }
     514           0 : }
     515             : 
     516           0 : inline bool SaxWriterHelper::writeString( const OUString& rWriteOutString,
     517             :                         bool bDoNormalization,
     518             :                         bool bNormalizeWhitespace ) throw( SAXException )
     519             : {
     520           0 :     FinishStartElement();
     521             :     return convertToXML(rWriteOutString.getStr(),
     522             :                     rWriteOutString.getLength(),
     523             :                     bDoNormalization,
     524             :                     bNormalizeWhitespace,
     525             :                     mp_Sequence,
     526           0 :                     nCurrentPos);
     527             : }
     528             : 
     529           0 : inline void SaxWriterHelper::startDocument() throw( SAXException )
     530             : {
     531           0 :     const char pc[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
     532           0 :     const int nLen = strlen( pc );
     533           0 :     if ((nCurrentPos + nLen) <= SEQUENCESIZE)
     534             :     {
     535           0 :         memcpy( mp_Sequence, pc , nLen );
     536           0 :         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           0 :     if (nCurrentPos == SEQUENCESIZE)
     544           0 :         nCurrentPos = writeSequence();
     545           0 :     mp_Sequence[nCurrentPos] = LINEFEED;
     546           0 :     nCurrentPos++;
     547           0 :     if (nCurrentPos == SEQUENCESIZE)
     548           0 :         nCurrentPos = writeSequence();
     549           0 : }
     550             : 
     551           0 : inline SaxInvalidCharacterError SaxWriterHelper::startElement(const OUString& rName, const Reference< XAttributeList >& xAttribs) throw( SAXException )
     552             : {
     553           0 :     FinishStartElement();
     554             : 
     555             : #ifdef DBG_UTIL
     556             :     m_DebugStartedElements.push(rName);
     557             :     ::std::set<OUString> DebugAttributes;
     558             : #endif
     559             : 
     560           0 :     mp_Sequence[nCurrentPos] = '<';
     561           0 :     nCurrentPos++;
     562           0 :     if (nCurrentPos == SEQUENCESIZE)
     563           0 :         nCurrentPos = writeSequence();
     564             : 
     565           0 :     SaxInvalidCharacterError eRet(SAX_NONE);
     566           0 :     if (!writeString(rName, false, false))
     567           0 :         eRet = SAX_ERROR;
     568             : 
     569           0 :     sal_Int16 nAttribCount = xAttribs.is() ? static_cast<sal_Int16>(xAttribs->getLength()) : 0;
     570           0 :     for(sal_Int16 i = 0 ; i < nAttribCount ; i++ )
     571             :     {
     572           0 :         mp_Sequence[nCurrentPos] = ' ';
     573           0 :         nCurrentPos++;
     574           0 :         if (nCurrentPos == SEQUENCESIZE)
     575           0 :             nCurrentPos = writeSequence();
     576             : 
     577           0 :         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           0 :         if (!writeString(rAttrName, false, false))
     584           0 :             eRet = SAX_ERROR;
     585             : 
     586           0 :         mp_Sequence[nCurrentPos] = '=';
     587           0 :         nCurrentPos++;
     588           0 :         if (nCurrentPos == SEQUENCESIZE)
     589           0 :             nCurrentPos = writeSequence();
     590           0 :         mp_Sequence[nCurrentPos] = '"';
     591           0 :         nCurrentPos++;
     592           0 :         if (nCurrentPos == SEQUENCESIZE)
     593           0 :             nCurrentPos = writeSequence();
     594             : 
     595           0 :         if (!writeString(xAttribs->getValueByIndex( i ), true, true) &&
     596             :             !(eRet == SAX_ERROR))
     597           0 :             eRet = SAX_WARNING;
     598             : 
     599           0 :         mp_Sequence[nCurrentPos] = '"';
     600           0 :         nCurrentPos++;
     601           0 :         if (nCurrentPos == SEQUENCESIZE)
     602           0 :             nCurrentPos = writeSequence();
     603           0 :     }
     604             : 
     605           0 :     m_bStartElementFinished = false;    // because the '>' character is not added,
     606             :                                             // because it is possible, that the "/>"
     607             :                                             // characters have to add
     608           0 :     return eRet;
     609             : }
     610             : 
     611           0 : inline bool SaxWriterHelper::FinishEmptyElement() throw( SAXException )
     612             : {
     613           0 :     if (m_bStartElementFinished)
     614           0 :         return false;
     615             : 
     616           0 :     mp_Sequence[nCurrentPos] = '/';
     617           0 :     nCurrentPos++;
     618           0 :     if (nCurrentPos == SEQUENCESIZE)
     619           0 :         nCurrentPos = writeSequence();
     620           0 :     mp_Sequence[nCurrentPos] = '>';
     621           0 :     nCurrentPos++;
     622           0 :     if (nCurrentPos == SEQUENCESIZE)
     623           0 :         nCurrentPos = writeSequence();
     624             : 
     625           0 :     m_bStartElementFinished = true;
     626             : 
     627           0 :     return true;
     628             : }
     629             : 
     630           0 : inline bool SaxWriterHelper::endElement(const OUString& rName) throw( SAXException )
     631             : {
     632           0 :     FinishStartElement();
     633             : 
     634           0 :     mp_Sequence[nCurrentPos] = '<';
     635           0 :     nCurrentPos++;
     636           0 :     if (nCurrentPos == SEQUENCESIZE)
     637           0 :         nCurrentPos = writeSequence();
     638           0 :     mp_Sequence[nCurrentPos] = '/';
     639           0 :     nCurrentPos++;
     640           0 :     if (nCurrentPos == SEQUENCESIZE)
     641           0 :         nCurrentPos = writeSequence();
     642             : 
     643           0 :     bool bRet(writeString( rName, false, false));
     644             : 
     645           0 :     mp_Sequence[nCurrentPos] = '>';
     646           0 :     nCurrentPos++;
     647           0 :     if (nCurrentPos == SEQUENCESIZE)
     648           0 :         nCurrentPos = writeSequence();
     649             : 
     650           0 :     return bRet;
     651             : }
     652             : 
     653           0 : inline void SaxWriterHelper::endDocument() throw( SAXException )
     654             : {
     655           0 :     if (nCurrentPos > 0)
     656             :     {
     657           0 :         m_Sequence.realloc(nCurrentPos);
     658           0 :         nCurrentPos = writeSequence();
     659             :         //m_Sequence.realloc(SEQUENCESIZE);
     660             :     }
     661           0 : }
     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           0 : inline bool SaxWriterHelper::processingInstruction(const OUString& rTarget, const OUString& rData) throw( SAXException )
     677             : {
     678           0 :     FinishStartElement();
     679           0 :     mp_Sequence[nCurrentPos] = '<';
     680           0 :     nCurrentPos++;
     681           0 :     if (nCurrentPos == SEQUENCESIZE)
     682           0 :         nCurrentPos = writeSequence();
     683           0 :     mp_Sequence[nCurrentPos] = '?';
     684           0 :     nCurrentPos++;
     685           0 :     if (nCurrentPos == SEQUENCESIZE)
     686           0 :         nCurrentPos = writeSequence();
     687             : 
     688           0 :     bool bRet(writeString( rTarget, false, false ));
     689             : 
     690           0 :     mp_Sequence[nCurrentPos] = ' ';
     691           0 :     nCurrentPos++;
     692           0 :     if (nCurrentPos == SEQUENCESIZE)
     693           0 :         nCurrentPos = writeSequence();
     694             : 
     695           0 :     if (!writeString( rData, false, false ))
     696           0 :         bRet = false;
     697             : 
     698           0 :     mp_Sequence[nCurrentPos] = '?';
     699           0 :     nCurrentPos++;
     700           0 :     if (nCurrentPos == SEQUENCESIZE)
     701           0 :         nCurrentPos = writeSequence();
     702           0 :     mp_Sequence[nCurrentPos] = '>';
     703           0 :     nCurrentPos++;
     704           0 :     if (nCurrentPos == SEQUENCESIZE)
     705           0 :         nCurrentPos = writeSequence();
     706             : 
     707           0 :     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           0 : inline bool SaxWriterHelper::comment(const OUString& rComment) throw( SAXException )
     739             : {
     740           0 :     FinishStartElement();
     741           0 :     mp_Sequence[nCurrentPos] = '<';
     742           0 :     nCurrentPos++;
     743           0 :     if (nCurrentPos == SEQUENCESIZE)
     744           0 :         nCurrentPos = writeSequence();
     745           0 :     mp_Sequence[nCurrentPos] = '!';
     746           0 :     nCurrentPos++;
     747           0 :     if (nCurrentPos == SEQUENCESIZE)
     748           0 :         nCurrentPos = writeSequence();
     749           0 :     mp_Sequence[nCurrentPos] = '-';
     750           0 :     nCurrentPos++;
     751           0 :     if (nCurrentPos == SEQUENCESIZE)
     752           0 :         nCurrentPos = writeSequence();
     753           0 :     mp_Sequence[nCurrentPos] = '-';
     754           0 :     nCurrentPos++;
     755           0 :     if (nCurrentPos == SEQUENCESIZE)
     756           0 :         nCurrentPos = writeSequence();
     757             : 
     758           0 :     bool bRet(writeString( rComment, false, false));
     759             : 
     760           0 :     mp_Sequence[nCurrentPos] = '-';
     761           0 :     nCurrentPos++;
     762           0 :     if (nCurrentPos == SEQUENCESIZE)
     763           0 :         nCurrentPos = writeSequence();
     764           0 :     mp_Sequence[nCurrentPos] = '-';
     765           0 :     nCurrentPos++;
     766           0 :     if (nCurrentPos == SEQUENCESIZE)
     767           0 :         nCurrentPos = writeSequence();
     768           0 :     mp_Sequence[nCurrentPos] = '>';
     769           0 :     nCurrentPos++;
     770           0 :     if (nCurrentPos == SEQUENCESIZE)
     771           0 :         nCurrentPos = writeSequence();
     772             : 
     773           0 :     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           0 :     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           0 :         , m_nLevel(0)
     885             :     {
     886           0 :     }
     887           0 :     virtual ~SAXWriter()
     888           0 :     {
     889           0 :         delete m_pSaxWriterHelper;
     890           0 :     }
     891             : 
     892             : public: // XActiveDataSource
     893           0 :     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           0 :                 if ( m_out == aStream && m_pSaxWriterHelper && m_bDocStarted )
     898           0 :                     m_pSaxWriterHelper->clearBuffer();
     899             :                 else
     900             :                 {
     901             : 
     902           0 :                 m_out = aStream;
     903           0 :                 delete m_pSaxWriterHelper;
     904           0 :                 m_pSaxWriterHelper = new SaxWriterHelper(m_out);
     905           0 :                 m_bDocStarted = false;
     906           0 :                 m_nLevel = 0;
     907           0 :                 m_bIsCDATA = false;
     908             : 
     909             :                 }
     910           0 :             }
     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           0 : sal_Int32 SAXWriter::getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurrence ) throw()
     971             : {
     972           0 :     sal_Int32 nLength =-1;
     973           0 :     if (m_pSaxWriterHelper)
     974             :     {
     975           0 :         if ( m_bForceLineBreak ||
     976           0 :             (m_bAllowLineBreak &&
     977           0 :             ((nFirstLineBreakOccurrence + m_pSaxWriterHelper->GetLastColumnCount()) > MAXCOLUMNCOUNT)) )
     978           0 :             nLength = m_nLevel;
     979             :     }
     980           0 :     m_bForceLineBreak = false;
     981           0 :     m_bAllowLineBreak = false;
     982           0 :     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           0 : void SAXWriter::startDocument()                     throw(SAXException, RuntimeException, std::exception )
    1011             : {
    1012           0 :     if( m_bDocStarted || ! m_out.is() || !m_pSaxWriterHelper ) {
    1013           0 :         throw SAXException();
    1014             :     }
    1015           0 :     m_bDocStarted = true;
    1016           0 :     m_pSaxWriterHelper->startDocument();
    1017           0 : }
    1018             : 
    1019             : 
    1020           0 : void SAXWriter::endDocument(void)                   throw(SAXException, RuntimeException, std::exception)
    1021             : {
    1022           0 :     if( ! m_bDocStarted )
    1023             :     {
    1024             :         throw SAXException(
    1025             :             OUString("endDocument called before startDocument"),
    1026           0 :             Reference< XInterface >() , Any() );
    1027             :     }
    1028           0 :     if( m_nLevel ) {
    1029             :         throw SAXException(
    1030             :             OUString("unexpected end of document"),
    1031           0 :             Reference< XInterface >() , Any() );
    1032             :     }
    1033           0 :     m_pSaxWriterHelper->endDocument();
    1034             :     try
    1035             :     {
    1036           0 :         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           0 : }
    1048             : 
    1049             : 
    1050           0 : void SAXWriter::startElement(const OUString& aName, const Reference< XAttributeList >& xAttribs)
    1051             :     throw(SAXException, RuntimeException, std::exception)
    1052             : {
    1053           0 :     if( ! m_bDocStarted )
    1054             :     {
    1055           0 :         SAXException except;
    1056           0 :         except.Message = "startElement called before startDocument";
    1057           0 :         throw except;
    1058             :     }
    1059           0 :     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           0 :     sal_Int32 nLength(0);
    1067           0 :     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           0 :     sal_Int32 nPrefix(getIndentPrefixLength( nLength ));
    1096             : 
    1097             :     // write into sequence
    1098           0 :     if( nPrefix >= 0 )
    1099           0 :         m_pSaxWriterHelper->insertIndentation( nPrefix );
    1100             : 
    1101           0 :     SaxInvalidCharacterError eRet(m_pSaxWriterHelper->startElement(aName, xAttribs));
    1102             : 
    1103           0 :     m_nLevel++;
    1104             : 
    1105           0 :     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           0 :     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           0 : }
    1118             : 
    1119           0 : void SAXWriter::endElement(const OUString& aName)   throw (SAXException, RuntimeException, std::exception)
    1120             : {
    1121           0 :     if( ! m_bDocStarted ) {
    1122           0 :         throw SAXException ();
    1123             :     }
    1124           0 :     m_nLevel --;
    1125             : 
    1126           0 :     if( m_nLevel < 0 ) {
    1127           0 :         throw SAXException();
    1128             :     }
    1129           0 :     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           0 :     if( m_pSaxWriterHelper->FinishEmptyElement() )
    1140           0 :         m_bForceLineBreak = false;
    1141             :     else
    1142             :     {
    1143             :         // only ascii chars allowed
    1144           0 :         sal_Int32 nLength(0);
    1145           0 :         if (m_bAllowLineBreak)
    1146           0 :             nLength = 3 + calcXMLByteLength( aName.getStr(), aName.getLength(), false, false );
    1147           0 :         sal_Int32 nPrefix = getIndentPrefixLength( nLength );
    1148             : 
    1149           0 :         if( nPrefix >= 0 )
    1150           0 :             m_pSaxWriterHelper->insertIndentation( nPrefix );
    1151             : 
    1152           0 :         bRet = m_pSaxWriterHelper->endElement(aName);
    1153             :     }
    1154             : 
    1155           0 :     if (!bRet)
    1156             :     {
    1157           0 :         SAXException except;
    1158           0 :         except.Message = "Invalid character during XML-Export";
    1159           0 :         throw except;
    1160             :     }
    1161           0 : }
    1162             : 
    1163           0 : void SAXWriter::characters(const OUString& aChars)  throw(SAXException, RuntimeException, std::exception)
    1164             : {
    1165           0 :     if( ! m_bDocStarted )
    1166             :     {
    1167           0 :         SAXException except;
    1168           0 :         except.Message = "characters method called before startDocument";
    1169           0 :         throw except;
    1170             :     }
    1171             : 
    1172           0 :     bool bThrowException(false);
    1173           0 :     if( !aChars.isEmpty() )
    1174             :     {
    1175           0 :         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           0 :             sal_Int32 nLength(0);
    1183           0 :             sal_Int32 nIndentPrefix(-1);
    1184           0 :             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           0 :                 nIndentPrefix = getIndentPrefixLength(nLength);
    1195             : 
    1196             :             // insert indentation
    1197           0 :             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           0 :             bThrowException = !m_pSaxWriterHelper->writeString(aChars, true , false);
    1205             :         }
    1206             :     }
    1207           0 :     if (bThrowException)
    1208             :     {
    1209           0 :         SAXInvalidCharacterException except;
    1210           0 :         except.Message = "Invalid character during XML-Export";
    1211           0 :         throw except;
    1212             :     }
    1213           0 : }
    1214             : 
    1215             : 
    1216           0 : void SAXWriter::ignorableWhitespace(const OUString&) throw(SAXException, RuntimeException, std::exception)
    1217             : {
    1218           0 :     if( ! m_bDocStarted )
    1219             :     {
    1220           0 :         throw SAXException ();
    1221             :     }
    1222             : 
    1223           0 :     m_bForceLineBreak = true;
    1224           0 : }
    1225             : 
    1226           0 : void SAXWriter::processingInstruction(const OUString& aTarget, const OUString& aData)
    1227             :     throw (SAXException, RuntimeException, std::exception)
    1228             : {
    1229           0 :     if( ! m_bDocStarted || m_bIsCDATA )
    1230             :     {
    1231           0 :         throw SAXException();
    1232             :     }
    1233             : 
    1234           0 :     sal_Int32 nLength(0);
    1235           0 :     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           0 :     sal_Int32 nPrefix = getIndentPrefixLength( nLength );
    1248             : 
    1249           0 :     if( nPrefix >= 0 )
    1250           0 :         m_pSaxWriterHelper->insertIndentation( nPrefix );
    1251             : 
    1252           0 :     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           0 : }
    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           0 : void SAXWriter::comment(const OUString& sComment) throw(SAXException, RuntimeException, std::exception)
    1305             : {
    1306           0 :     if( ! m_bDocStarted || m_bIsCDATA )
    1307             :     {
    1308           0 :         throw SAXException();
    1309             :     }
    1310             : 
    1311           0 :     sal_Int32 nLength(0);
    1312           0 :     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           0 :     sal_Int32 nPrefix = getIndentPrefixLength( nLength );
    1321           0 :     if( nPrefix >= 0 )
    1322           0 :         m_pSaxWriterHelper->insertIndentation( nPrefix );
    1323             : 
    1324           0 :     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           0 : }
    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           0 : void SAXWriter::unknown(const OUString& sString) throw (SAXException, RuntimeException, std::exception)
    1343             : {
    1344             : 
    1345           0 :     if( ! m_bDocStarted )
    1346             :     {
    1347           0 :         throw SAXException ();
    1348             :     }
    1349           0 :     if( m_bIsCDATA )
    1350             :     {
    1351           0 :         throw SAXException();
    1352             :     }
    1353             : 
    1354           0 :     if( sString.matchAsciiL( "<?xml", 5 ) )
    1355           0 :         return;
    1356             : 
    1357           0 :     sal_Int32 nLength(0);
    1358           0 :     if (m_bAllowLineBreak)
    1359           0 :         nLength = calcXMLByteLength( sString.getStr(), sString.getLength(), false, false );
    1360             : 
    1361           0 :     sal_Int32 nPrefix = getIndentPrefixLength( nLength );
    1362           0 :     if( nPrefix >= 0 )
    1363           0 :         m_pSaxWriterHelper->insertIndentation( nPrefix );
    1364             : 
    1365           0 :     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           0 : com_sun_star_extensions_xml_sax_Writer_get_implementation(
    1377             :     css::uno::XComponentContext *,
    1378             :     css::uno::Sequence<css::uno::Any> const &)
    1379             : {
    1380           0 :     return cppu::acquire(new SAXWriter);
    1381             : }
    1382             : 
    1383             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10