LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sax/source/expatwrap - saxwriter.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 325 632 51.4 %
Date: 2013-07-09 Functions: 32 49 65.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10