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