Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : : #include <string.h>
20 : :
21 : : #include <com/sun/star/lang/XServiceInfo.hpp>
22 : : #include <com/sun/star/util/XCloneable.hpp>
23 : : #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
24 : : #include <com/sun/star/xml/sax/XParser.hpp>
25 : : #include <com/sun/star/xml/sax/SAXParseException.hpp>
26 : : #include <com/sun/star/xml/sax/SAXInvalidCharacterException.hpp>
27 : :
28 : : #include <com/sun/star/io/XActiveDataSource.hpp>
29 : :
30 : : #include <cppuhelper/factory.hxx>
31 : : #include <cppuhelper/weak.hxx>
32 : : #include <cppuhelper/implbase3.hxx>
33 : :
34 : : #include <rtl/strbuf.hxx>
35 : : #include <rtl/byteseq.hxx>
36 : : #include <rtl/ustrbuf.hxx>
37 : :
38 : : using namespace ::rtl;
39 : : using namespace ::std;
40 : : using namespace ::osl;
41 : : using namespace ::cppu;
42 : : using namespace ::com::sun::star::uno;
43 : : using namespace ::com::sun::star::lang;
44 : : using namespace ::com::sun::star::registry;
45 : : using namespace ::com::sun::star::xml::sax;
46 : : using namespace ::com::sun::star::util;
47 : : using namespace ::com::sun::star::io;
48 : :
49 : : #include "factory.hxx"
50 : : #include "xml2utf.hxx"
51 : :
52 : : #define LINEFEED 10
53 : : #define SEQUENCESIZE 1024
54 : : #define MAXCOLUMNCOUNT 72
55 : :
56 : : /******
57 : : *
58 : : *
59 : : * Character conversion functions
60 : : *
61 : : *
62 : : *****/
63 : :
64 : : namespace sax_expatwrap {
65 : :
66 : : enum SaxInvalidCharacterError
67 : : {
68 : : SAX_NONE,
69 : : SAX_WARNING,
70 : : SAX_ERROR
71 : : };
72 : :
73 : : class SaxWriterHelper
74 : : {
75 : : Reference< XOutputStream > m_out;
76 : : Sequence < sal_Int8 > m_Sequence;
77 : : sal_Int8* mp_Sequence;
78 : :
79 : : sal_Int32 nLastLineFeedPos; // is negative after writing a sequence
80 : : sal_uInt32 nCurrentPos;
81 : : sal_Bool m_bStartElementFinished;
82 : :
83 : :
84 : : inline sal_uInt32 writeSequence() throw( SAXException );
85 : :
86 : : // use only if to insert the bytes more space in the sequence is needed and
87 : : // so the sequence has to write out and reset rPos to 0
88 : : // writes sequence only on overflow, sequence could be full on the end (rPos == SEQUENCESIZE)
89 : : inline void AddBytes(sal_Int8* pTarget, sal_uInt32& rPos,
90 : : const sal_Int8* pBytes, sal_uInt32 nBytesCount) throw( SAXException );
91 : : inline sal_Bool convertToXML(const sal_Unicode * pStr,
92 : : sal_Int32 nStrLen,
93 : : sal_Bool bDoNormalization,
94 : : sal_Bool bNormalizeWhitespace,
95 : : sal_Int8 *pTarget,
96 : : sal_uInt32& rPos) throw( SAXException );
97 : : inline void FinishStartElement() throw( SAXException );
98 : : public:
99 : 2853 : SaxWriterHelper(Reference< XOutputStream > m_TempOut) :
100 : : m_out(m_TempOut),
101 : : m_Sequence(SEQUENCESIZE),
102 : : mp_Sequence(NULL),
103 : : nLastLineFeedPos(0),
104 : : nCurrentPos(0),
105 [ + - ]: 2853 : m_bStartElementFinished(sal_True)
106 : : {
107 : : OSL_ENSURE(SEQUENCESIZE > 50, "Sequence cache size to small");
108 [ + - ]: 2853 : mp_Sequence = m_Sequence.getArray();
109 : 2853 : }
110 : 2853 : ~SaxWriterHelper()
111 [ + - ]: 2853 : {
112 : : OSL_ENSURE(!nCurrentPos, "cached Sequence not written");
113 : : OSL_ENSURE(m_bStartElementFinished, "StartElement not complettly written");
114 : 2853 : }
115 : :
116 : : inline void insertIndentation(sal_uInt32 m_nLevel) throw( SAXException );
117 : :
118 : : // returns whether it works correct or invalid characters were in the string
119 : : // If there are invalid characters in the string it returns sal_False.
120 : : // Than the calling method has to throw the needed Exception.
121 : : inline sal_Bool writeString(const rtl::OUString& rWriteOutString,
122 : : sal_Bool bDoNormalization,
123 : : sal_Bool bNormalizeWhitespace) throw( SAXException );
124 : :
125 : 0 : sal_uInt32 GetLastColumnCount() const
126 : 0 : { return (sal_uInt32)(nCurrentPos - nLastLineFeedPos); }
127 : :
128 : : inline void startDocument() throw( SAXException );
129 : :
130 : : // returns whether it works correct or invalid characters were in the strings
131 : : // If there are invalid characters in one of the strings it returns sal_False.
132 : : // Than the calling method has to throw the needed Exception.
133 : : inline SaxInvalidCharacterError startElement(const rtl::OUString& rName, const Reference< XAttributeList >& xAttribs) throw( SAXException );
134 : : inline sal_Bool FinishEmptyElement() throw( SAXException );
135 : :
136 : : // returns whether it works correct or invalid characters were in the string
137 : : // If there are invalid characters in the string it returns sal_False.
138 : : // Than the calling method has to throw the needed Exception.
139 : : inline sal_Bool endElement(const rtl::OUString& rName) throw( SAXException );
140 : : inline void endDocument() throw( SAXException );
141 : :
142 : : // returns whether it works correct or invalid characters were in the strings
143 : : // If there are invalid characters in the string it returns sal_False.
144 : : // Than the calling method has to throw the needed Exception.
145 : : inline sal_Bool processingInstruction(const rtl::OUString& rTarget, const rtl::OUString& rData) throw( SAXException );
146 : : inline void startCDATA() throw( SAXException );
147 : : inline void endCDATA() throw( SAXException );
148 : :
149 : : // returns whether it works correct or invalid characters were in the strings
150 : : // If there are invalid characters in the string it returns sal_False.
151 : : // Than the calling method has to throw the needed Exception.
152 : : inline sal_Bool comment(const rtl::OUString& rComment) throw( SAXException );
153 : :
154 : : inline void clearBuffer() throw( SAXException );
155 : : };
156 : :
157 : : const sal_Bool g_bValidCharsBelow32[32] =
158 : : {
159 : : // 0 1 2 3 4 5 6 7
160 : : 0,0,0,0,0,0,0,0, //0
161 : : 0,1,1,0,0,1,0,0, //8
162 : : 0,0,0,0,0,0,0,0, //16
163 : : 0,0,0,0,0,0,0,0
164 : : };
165 : :
166 : 7109688 : inline sal_Bool IsInvalidChar(const sal_Unicode aChar)
167 : : {
168 : 7109688 : sal_Bool bRet(sal_False);
169 : : // check first for the most common characters
170 [ + + ][ - + ]: 7109688 : if( aChar < 32 || aChar >= 0xd800 )
171 : 18 : bRet = ( (aChar < 32 && ! g_bValidCharsBelow32[aChar]) ||
172 : : aChar == 0xffff ||
173 [ + - ][ + - ]: 18 : aChar == 0xfffe );
[ + - ][ - + ]
174 : 7109688 : return bRet;
175 : : }
176 : :
177 : : /********
178 : : * write through to the output stream
179 : : *
180 : : *****/
181 : 9636 : inline sal_uInt32 SaxWriterHelper::writeSequence() throw( SAXException )
182 : : {
183 : : try
184 : : {
185 [ + - ][ + - ]: 9636 : m_out->writeBytes( m_Sequence );
186 : : }
187 [ # # ]: 0 : catch (const IOException & e)
188 : : {
189 : 0 : Any a;
190 [ # # ]: 0 : a <<= e;
191 : : throw SAXException(
192 : : OUString("io exception during writing"),
193 : : Reference< XInterface > (),
194 [ # # ]: 0 : a );
195 : : }
196 : 9636 : nLastLineFeedPos -= SEQUENCESIZE;
197 : 9636 : return 0;
198 : : }
199 : :
200 : 6 : inline void SaxWriterHelper::AddBytes(sal_Int8* pTarget, sal_uInt32& rPos,
201 : : const sal_Int8* pBytes, sal_uInt32 nBytesCount) throw( SAXException )
202 : : {
203 : : OSL_ENSURE((rPos + nBytesCount) > SEQUENCESIZE, "wrong use of AddBytesMethod");
204 : 6 : sal_uInt32 nCount(SEQUENCESIZE - rPos);
205 : 6 : memcpy( &(pTarget[rPos]) , pBytes, nCount);
206 : :
207 : : OSL_ENSURE(rPos + nCount == SEQUENCESIZE, "the position should be the at the end");
208 : :
209 : 6 : rPos = writeSequence();
210 : 6 : sal_uInt32 nRestCount(nBytesCount - nCount);
211 [ + - ]: 6 : if ((rPos + nRestCount) <= SEQUENCESIZE)
212 : : {
213 : 6 : memcpy( &(pTarget[rPos]), &pBytes[nCount], nRestCount);
214 : 6 : rPos += nRestCount;
215 : : }
216 : : else
217 : 0 : AddBytes(pTarget, rPos, &pBytes[nCount], nRestCount);
218 : 6 : }
219 : :
220 : : /** Converts an UTF16 string to UTF8 and does XML normalization
221 : :
222 : : @param pTarget
223 : : Pointer to a piece of memory, to where the output should be written. The caller
224 : : must call calcXMLByteLength on the same string, to ensure,
225 : : that there is enough memory for converting.
226 : : */
227 : 559390 : inline sal_Bool SaxWriterHelper::convertToXML( const sal_Unicode * pStr,
228 : : sal_Int32 nStrLen,
229 : : sal_Bool bDoNormalization,
230 : : sal_Bool bNormalizeWhitespace,
231 : : sal_Int8 *pTarget,
232 : : sal_uInt32& rPos ) throw( SAXException )
233 : : {
234 : 559390 : sal_Bool bRet(sal_True);
235 : 559390 : sal_uInt32 nSurrogate = 0;
236 : :
237 [ + + ]: 7669078 : for( sal_Int32 i = 0 ; i < nStrLen ; i ++ )
238 : : {
239 : 7109688 : sal_uInt16 c = pStr[i];
240 [ - + ]: 7109688 : if (IsInvalidChar(c))
241 : 0 : bRet = sal_False;
242 [ + - ][ + + ]: 7109688 : else if( (c >= 0x0001) && (c <= 0x007F) )
243 : : {
244 [ + + ]: 14214012 : if( bDoNormalization )
245 : : {
246 [ - + + + : 2600491 : switch( c )
- - + -
+ ]
247 : : {
248 : : case '&': // resemble to &
249 : : {
250 [ # # ]: 0 : if ((rPos + 5) > SEQUENCESIZE)
251 : 0 : AddBytes(pTarget, rPos, (sal_Int8*)"&", 5);
252 : : else
253 : : {
254 : 0 : memcpy( &(pTarget[rPos]) , "&", 5 );
255 : 0 : rPos += 5;
256 : : }
257 : : }
258 : 0 : break;
259 : : case '<':
260 : : {
261 [ - + ]: 246 : if ((rPos + 4) > SEQUENCESIZE)
262 : 0 : AddBytes(pTarget, rPos, (sal_Int8*)"<", 4);
263 : : else
264 : : {
265 : 246 : memcpy( &(pTarget[rPos]) , "<" , 4 );
266 : 246 : rPos += 4; // <
267 : : }
268 : : }
269 : 246 : break;
270 : : case '>':
271 : : {
272 [ - + ]: 106 : if ((rPos + 4) > SEQUENCESIZE)
273 : 0 : AddBytes(pTarget, rPos, (sal_Int8*)">", 4);
274 : : else
275 : : {
276 : 106 : memcpy( &(pTarget[rPos]) , ">" , 4 );
277 : 106 : rPos += 4; // >
278 : : }
279 : : }
280 : 106 : break;
281 : : case 39: // 39 == '''
282 : : {
283 [ + + ]: 664 : if ((rPos + 6) > SEQUENCESIZE)
284 : 6 : AddBytes(pTarget, rPos, (sal_Int8*)"'", 6);
285 : : else
286 : : {
287 : 658 : memcpy( &(pTarget[rPos]) , "'" , 6 );
288 : 658 : rPos += 6; // '
289 : : }
290 : : }
291 : 664 : break;
292 : : case '"':
293 : : {
294 [ # # ]: 0 : if ((rPos + 6) > SEQUENCESIZE)
295 : 0 : AddBytes(pTarget, rPos, (sal_Int8*)""", 6);
296 : : else
297 : : {
298 : 0 : memcpy( &(pTarget[rPos]) , """ , 6 );
299 : 0 : rPos += 6; // "
300 : : }
301 : : }
302 : 0 : break;
303 : : case 13:
304 : : {
305 [ # # ]: 0 : if ((rPos + 6) > SEQUENCESIZE)
306 : 0 : AddBytes(pTarget, rPos, (sal_Int8*)"
", 6);
307 : : else
308 : : {
309 : 0 : memcpy( &(pTarget[rPos]) , "
" , 6 );
310 : 0 : rPos += 6;
311 : : }
312 : : }
313 : 0 : break;
314 : : case LINEFEED:
315 : : {
316 [ - + ]: 18 : if( bNormalizeWhitespace )
317 : : {
318 [ # # ]: 0 : if ((rPos + 6) > SEQUENCESIZE)
319 : 0 : AddBytes(pTarget, rPos, (sal_Int8*)"
" , 6);
320 : : else
321 : : {
322 : 0 : memcpy( &(pTarget[rPos]) , "
" , 6 );
323 : 0 : rPos += 6;
324 : : }
325 : : }
326 : : else
327 : : {
328 : 18 : pTarget[rPos] = LINEFEED;
329 : 18 : nLastLineFeedPos = rPos;
330 : 18 : rPos ++;
331 : : }
332 : : }
333 : 18 : break;
334 : : case 9:
335 : : {
336 [ # # ]: 0 : if( bNormalizeWhitespace )
337 : : {
338 [ # # ]: 0 : if ((rPos + 6) > SEQUENCESIZE)
339 : 0 : AddBytes(pTarget, rPos, (sal_Int8*)"	" , 6);
340 : : else
341 : : {
342 : 0 : memcpy( &(pTarget[rPos]) , "	" , 6 );
343 : 0 : rPos += 6;
344 : : }
345 : : }
346 : : else
347 : : {
348 : 0 : pTarget[rPos] = 9;
349 : 0 : rPos ++;
350 : : }
351 : : }
352 : 0 : break;
353 : : default:
354 : : {
355 : 2599457 : pTarget[rPos] = (sal_Int8)c;
356 : 2599457 : rPos ++;
357 : : }
358 : 2600491 : break;
359 : : }
360 : : }
361 : : else
362 : : {
363 : 4506515 : pTarget[rPos] = (sal_Int8)c;
364 [ - + ]: 4506515 : if ((sal_Int8)c == LINEFEED)
365 : 0 : nLastLineFeedPos = rPos;
366 : 4506515 : rPos ++;
367 : : }
368 : : }
369 [ - + ][ # # ]: 2682 : else if( c >= 0xd800 && c < 0xdc00 )
370 : : {
371 : : // 1. surrogate: save (until 2. surrogate)
372 : : OSL_ENSURE( nSurrogate == 0, "left-over Unicode surrogate" );
373 : 0 : nSurrogate = ( ( c & 0x03ff ) + 0x0040 );
374 : : }
375 [ - + ][ # # ]: 2682 : else if( c >= 0xdc00 && c < 0xe000 )
376 : : {
377 : : // 2. surrogate: write as UTF-8
378 : : OSL_ENSURE( nSurrogate != 0, "lone 2nd Unicode surrogate" );
379 : :
380 : 0 : nSurrogate = ( nSurrogate << 10 ) | ( c & 0x03ff );
381 [ # # ][ # # ]: 0 : if( nSurrogate >= 0x00010000 && nSurrogate <= 0x0010FFFF )
382 : : {
383 : : sal_Int8 aBytes[] = { sal_Int8(0xF0 | ((nSurrogate >> 18) & 0x0F)),
384 : : sal_Int8(0x80 | ((nSurrogate >> 12) & 0x3F)),
385 : : sal_Int8(0x80 | ((nSurrogate >> 6) & 0x3F)),
386 : 0 : sal_Int8(0x80 | ((nSurrogate >> 0) & 0x3F)) };
387 [ # # ]: 0 : if ((rPos + 4) > SEQUENCESIZE)
388 [ # # ]: 0 : AddBytes(pTarget, rPos, aBytes, 4);
389 : : else
390 : : {
391 : 0 : pTarget[rPos] = aBytes[0];
392 : 0 : rPos ++;
393 : 0 : pTarget[rPos] = aBytes[1];
394 : 0 : rPos ++;
395 : 0 : pTarget[rPos] = aBytes[2];
396 : 0 : rPos ++;
397 : 0 : pTarget[rPos] = aBytes[3];
398 : 0 : rPos ++;
399 : 0 : }
400 : : }
401 : : else
402 : : {
403 : : OSL_FAIL( "illegal Unicode character" );
404 : 0 : bRet = sal_False;
405 : : }
406 : :
407 : : // reset surrogate
408 : 0 : nSurrogate = 0;
409 : : }
410 [ + + ]: 2682 : else if( c > 0x07FF )
411 : : {
412 : : sal_Int8 aBytes[] = { sal_Int8(0xE0 | ((c >> 12) & 0x0F)),
413 : : sal_Int8(0x80 | ((c >> 6) & 0x3F)),
414 : 1552 : sal_Int8(0x80 | ((c >> 0) & 0x3F)) };
415 [ - + ]: 1552 : if ((rPos + 3) > SEQUENCESIZE)
416 [ # # ]: 0 : AddBytes(pTarget, rPos, aBytes, 3);
417 : : else
418 : : {
419 : 1552 : pTarget[rPos] = aBytes[0];
420 : 1552 : rPos ++;
421 : 1552 : pTarget[rPos] = aBytes[1];
422 : 1552 : rPos ++;
423 : 1552 : pTarget[rPos] = aBytes[2];
424 : 1552 : rPos ++;
425 : : }
426 : : }
427 : : else
428 : : {
429 : : sal_Int8 aBytes[] = { sal_Int8(0xC0 | ((c >> 6) & 0x1F)),
430 : 1130 : sal_Int8(0x80 | ((c >> 0) & 0x3F)) };
431 [ - + ]: 1130 : if ((rPos + 2) > SEQUENCESIZE)
432 [ # # ]: 0 : AddBytes(pTarget, rPos, aBytes, 2);
433 : : else
434 : : {
435 : 1130 : pTarget[rPos] = aBytes[0];
436 : 1130 : rPos ++;
437 : 1130 : pTarget[rPos] = aBytes[1];
438 : 1130 : rPos ++;
439 : : }
440 : : }
441 : : OSL_ENSURE(rPos <= SEQUENCESIZE, "not reset current position");
442 [ + + ]: 7109688 : if (rPos == SEQUENCESIZE)
443 : 6630 : rPos = writeSequence();
444 : :
445 : : // reset left-over surrogate
446 [ - + ][ # # ]: 7109688 : if( ( nSurrogate != 0 ) && !( c >= 0xd800 && c < 0xdc00 ) )
[ # # ]
447 : : {
448 : : OSL_ENSURE( nSurrogate != 0, "left-over Unicode surrogate" );
449 : 0 : nSurrogate = 0;
450 : 0 : bRet = sal_False;
451 : : }
452 : : }
453 : 559390 : return bRet;
454 : : }
455 : :
456 : 736290 : inline void SaxWriterHelper::FinishStartElement() throw( SAXException )
457 : : {
458 [ + + ]: 736290 : if (!m_bStartElementFinished)
459 : : {
460 : 81896 : mp_Sequence[nCurrentPos] = '>';
461 : 81896 : nCurrentPos++;
462 [ - + ]: 81896 : if (nCurrentPos == SEQUENCESIZE)
463 : 0 : nCurrentPos = writeSequence();
464 : 81896 : m_bStartElementFinished = sal_True;
465 : : }
466 : 736290 : }
467 : :
468 : 1910 : inline void SaxWriterHelper::insertIndentation(sal_uInt32 m_nLevel) throw( SAXException )
469 : : {
470 : 1910 : FinishStartElement();
471 [ + + ]: 1910 : if (m_nLevel > 0)
472 : : {
473 [ + - ]: 1200 : if ((nCurrentPos + m_nLevel + 1) <= SEQUENCESIZE)
474 : : {
475 : 1200 : mp_Sequence[nCurrentPos] = LINEFEED;
476 : 1200 : nLastLineFeedPos = nCurrentPos;
477 : 1200 : nCurrentPos++;
478 : 1200 : memset( &(mp_Sequence[nCurrentPos]) , 32 , m_nLevel );
479 : 1200 : nCurrentPos += m_nLevel;
480 [ - + ]: 1200 : if (nCurrentPos == SEQUENCESIZE)
481 : 0 : nCurrentPos = writeSequence();
482 : : }
483 : : else
484 : : {
485 : 0 : sal_uInt32 nCount(m_nLevel + 1);
486 : 0 : sal_Int8* pBytes = new sal_Int8[nCount];
487 : 0 : pBytes[0] = LINEFEED;
488 : 0 : memset( &(pBytes[1]), 32, m_nLevel );
489 : 0 : AddBytes(mp_Sequence, nCurrentPos, pBytes, nCount);
490 [ # # ]: 0 : delete[] pBytes;
491 : 0 : nLastLineFeedPos = nCurrentPos - nCount;
492 [ # # ]: 0 : if (nCurrentPos == SEQUENCESIZE)
493 : 0 : nCurrentPos = writeSequence();
494 : : }
495 : : }
496 : : else
497 : : {
498 : 710 : mp_Sequence[nCurrentPos] = LINEFEED;
499 : 710 : nLastLineFeedPos = nCurrentPos;
500 : 710 : nCurrentPos++;
501 [ - + ]: 710 : if (nCurrentPos == SEQUENCESIZE)
502 : 0 : nCurrentPos = writeSequence();
503 : : }
504 : 1910 : }
505 : :
506 : 559390 : inline sal_Bool SaxWriterHelper::writeString( const rtl::OUString& rWriteOutString,
507 : : sal_Bool bDoNormalization,
508 : : sal_Bool bNormalizeWhitespace ) throw( SAXException )
509 : : {
510 : 559390 : FinishStartElement();
511 : : return convertToXML(rWriteOutString.getStr(),
512 : : rWriteOutString.getLength(),
513 : : bDoNormalization,
514 : : bNormalizeWhitespace,
515 : : mp_Sequence,
516 : 559390 : nCurrentPos);
517 : : }
518 : :
519 : 2835 : inline void SaxWriterHelper::startDocument() throw( SAXException )
520 : : {
521 : 2835 : const char pc[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
522 : 2835 : const int nLen = strlen( pc );
523 [ + - ]: 2835 : if ((nCurrentPos + nLen) <= SEQUENCESIZE)
524 : : {
525 : 2835 : memcpy( mp_Sequence, pc , nLen );
526 : 2835 : nCurrentPos += nLen;
527 : : }
528 : : else
529 : : {
530 [ # # ]: 0 : AddBytes(mp_Sequence, nCurrentPos, (sal_Int8*)pc, nLen);
531 : : }
532 : : OSL_ENSURE(nCurrentPos <= SEQUENCESIZE, "not reset current position");
533 [ - + ]: 2835 : if (nCurrentPos == SEQUENCESIZE)
534 [ # # ]: 0 : nCurrentPos = writeSequence();
535 : 2835 : mp_Sequence[nCurrentPos] = LINEFEED;
536 : 2835 : nCurrentPos++;
537 [ - + ]: 2835 : if (nCurrentPos == SEQUENCESIZE)
538 [ # # ]: 0 : nCurrentPos = writeSequence();
539 : 2835 : }
540 : :
541 : 93094 : inline SaxInvalidCharacterError SaxWriterHelper::startElement(const rtl::OUString& rName, const Reference< XAttributeList >& xAttribs) throw( SAXException )
542 : : {
543 : 93094 : FinishStartElement();
544 : 93094 : mp_Sequence[nCurrentPos] = '<';
545 : 93094 : nCurrentPos++;
546 [ + + ]: 93094 : if (nCurrentPos == SEQUENCESIZE)
547 : 32 : nCurrentPos = writeSequence();
548 : :
549 : 93094 : SaxInvalidCharacterError eRet(SAX_NONE);
550 [ - + ]: 93094 : if (!writeString(rName, sal_False, sal_False))
551 : 0 : eRet = SAX_ERROR;
552 : :
553 [ + - ]: 93094 : sal_Int16 nAttribCount = xAttribs.is() ? static_cast<sal_Int16>(xAttribs->getLength()) : 0;
554 [ + + ]: 251952 : for(sal_Int16 i = 0 ; i < nAttribCount ; i++ )
555 : : {
556 : 158858 : mp_Sequence[nCurrentPos] = ' ';
557 : 158858 : nCurrentPos++;
558 [ + + ]: 158858 : if (nCurrentPos == SEQUENCESIZE)
559 : 28 : nCurrentPos = writeSequence();
560 : :
561 [ + - ][ - + ]: 158858 : if (!writeString(xAttribs->getNameByIndex( i ), sal_False, sal_False))
562 : 0 : eRet = SAX_ERROR;
563 : :
564 : 158858 : mp_Sequence[nCurrentPos] = '=';
565 : 158858 : nCurrentPos++;
566 [ + + ]: 158858 : if (nCurrentPos == SEQUENCESIZE)
567 : 32 : nCurrentPos = writeSequence();
568 : 158858 : mp_Sequence[nCurrentPos] = '"';
569 : 158858 : nCurrentPos++;
570 [ + + ]: 158858 : if (nCurrentPos == SEQUENCESIZE)
571 : 14 : nCurrentPos = writeSequence();
572 : :
573 [ + - ][ + - ]: 158858 : if (!writeString(xAttribs->getValueByIndex( i ), sal_True, sal_True) &&
[ + - ][ - + ]
[ # # ][ + - ]
[ - + # # ]
574 : : !(eRet == SAX_ERROR))
575 : 0 : eRet = SAX_WARNING;
576 : :
577 : 158858 : mp_Sequence[nCurrentPos] = '"';
578 : 158858 : nCurrentPos++;
579 [ + + ]: 158858 : if (nCurrentPos == SEQUENCESIZE)
580 : 24 : nCurrentPos = writeSequence();
581 : : }
582 : :
583 : 93094 : m_bStartElementFinished = sal_False; // because the '>' character is not added,
584 : : // because it is possible, that the "/>"
585 : : // characters have to add
586 : 93094 : return eRet;
587 : : }
588 : :
589 : 93094 : inline sal_Bool SaxWriterHelper::FinishEmptyElement() throw( SAXException )
590 : : {
591 [ + + ]: 93094 : if (m_bStartElementFinished)
592 : 81896 : return sal_False;
593 : :
594 : 11198 : mp_Sequence[nCurrentPos] = '/';
595 : 11198 : nCurrentPos++;
596 [ + + ]: 11198 : if (nCurrentPos == SEQUENCESIZE)
597 : 14 : nCurrentPos = writeSequence();
598 : 11198 : mp_Sequence[nCurrentPos] = '>';
599 : 11198 : nCurrentPos++;
600 [ + + ]: 11198 : if (nCurrentPos == SEQUENCESIZE)
601 : 6 : nCurrentPos = writeSequence();
602 : :
603 : 11198 : m_bStartElementFinished = sal_True;
604 : :
605 : 93094 : return sal_True;
606 : : }
607 : :
608 : 81896 : inline sal_Bool SaxWriterHelper::endElement(const rtl::OUString& rName) throw( SAXException )
609 : : {
610 : 81896 : FinishStartElement();
611 : 81896 : mp_Sequence[nCurrentPos] = '<';
612 : 81896 : nCurrentPos++;
613 [ + + ]: 81896 : if (nCurrentPos == SEQUENCESIZE)
614 : 5 : nCurrentPos = writeSequence();
615 : 81896 : mp_Sequence[nCurrentPos] = '/';
616 : 81896 : nCurrentPos++;
617 [ + + ]: 81896 : if (nCurrentPos == SEQUENCESIZE)
618 : 4 : nCurrentPos = writeSequence();
619 : :
620 : 81896 : sal_Bool bRet(writeString( rName, sal_False, sal_False));
621 : :
622 : 81896 : mp_Sequence[nCurrentPos] = '>';
623 : 81896 : nCurrentPos++;
624 [ + + ]: 81896 : if (nCurrentPos == SEQUENCESIZE)
625 : 6 : nCurrentPos = writeSequence();
626 : :
627 : 81896 : return bRet;
628 : : }
629 : :
630 : 2835 : inline void SaxWriterHelper::endDocument() throw( SAXException )
631 : : {
632 [ + - ]: 2835 : if (nCurrentPos > 0)
633 : : {
634 : 2835 : m_Sequence.realloc(nCurrentPos);
635 : 2835 : nCurrentPos = writeSequence();
636 : : //m_Sequence.realloc(SEQUENCESIZE);
637 : : }
638 : 2835 : }
639 : :
640 : 0 : inline void SaxWriterHelper::clearBuffer() throw( SAXException )
641 : : {
642 : 0 : FinishStartElement();
643 [ # # ]: 0 : if (nCurrentPos > 0)
644 : : {
645 : 0 : m_Sequence.realloc(nCurrentPos);
646 : 0 : nCurrentPos = writeSequence();
647 : 0 : m_Sequence.realloc(SEQUENCESIZE);
648 : : // Be sure to update the array pointer after the reallocation.
649 : 0 : mp_Sequence = m_Sequence.getArray();
650 : : }
651 : 0 : }
652 : :
653 : 0 : inline sal_Bool SaxWriterHelper::processingInstruction(const rtl::OUString& rTarget, const rtl::OUString& rData) throw( SAXException )
654 : : {
655 : 0 : FinishStartElement();
656 : 0 : mp_Sequence[nCurrentPos] = '<';
657 : 0 : nCurrentPos++;
658 [ # # ]: 0 : if (nCurrentPos == SEQUENCESIZE)
659 : 0 : nCurrentPos = writeSequence();
660 : 0 : mp_Sequence[nCurrentPos] = '?';
661 : 0 : nCurrentPos++;
662 [ # # ]: 0 : if (nCurrentPos == SEQUENCESIZE)
663 : 0 : nCurrentPos = writeSequence();
664 : :
665 : 0 : sal_Bool bRet(writeString( rTarget, sal_False, sal_False ));
666 : :
667 : 0 : mp_Sequence[nCurrentPos] = ' ';
668 : 0 : nCurrentPos++;
669 [ # # ]: 0 : if (nCurrentPos == SEQUENCESIZE)
670 : 0 : nCurrentPos = writeSequence();
671 : :
672 [ # # ]: 0 : if (!writeString( rData, sal_False, sal_False ))
673 : 0 : bRet = sal_False;
674 : :
675 : 0 : mp_Sequence[nCurrentPos] = '?';
676 : 0 : nCurrentPos++;
677 [ # # ]: 0 : if (nCurrentPos == SEQUENCESIZE)
678 : 0 : nCurrentPos = writeSequence();
679 : 0 : mp_Sequence[nCurrentPos] = '>';
680 : 0 : nCurrentPos++;
681 [ # # ]: 0 : if (nCurrentPos == SEQUENCESIZE)
682 : 0 : nCurrentPos = writeSequence();
683 : :
684 : 0 : return bRet;
685 : : }
686 : :
687 : 0 : inline void SaxWriterHelper::startCDATA() throw( SAXException )
688 : : {
689 : 0 : FinishStartElement();
690 [ # # ]: 0 : if ((nCurrentPos + 9) <= SEQUENCESIZE)
691 : : {
692 : 0 : memcpy( &(mp_Sequence[nCurrentPos]), "<![CDATA[" , 9 );
693 : 0 : nCurrentPos += 9;
694 : : }
695 : : else
696 : 0 : AddBytes(mp_Sequence, nCurrentPos, (sal_Int8*)"<![CDATA[" , 9);
697 [ # # ]: 0 : if (nCurrentPos == SEQUENCESIZE)
698 : 0 : nCurrentPos = writeSequence();
699 : 0 : }
700 : :
701 : 0 : inline void SaxWriterHelper::endCDATA() throw( SAXException )
702 : : {
703 : 0 : FinishStartElement();
704 [ # # ]: 0 : if ((nCurrentPos + 3) <= SEQUENCESIZE)
705 : : {
706 : 0 : memcpy( &(mp_Sequence[nCurrentPos]), "]]>" , 3 );
707 : 0 : nCurrentPos += 3;
708 : : }
709 : : else
710 : 0 : AddBytes(mp_Sequence, nCurrentPos, (sal_Int8*)"]]>" , 3);
711 [ # # ]: 0 : if (nCurrentPos == SEQUENCESIZE)
712 : 0 : nCurrentPos = writeSequence();
713 : 0 : }
714 : :
715 : 0 : inline sal_Bool SaxWriterHelper::comment(const rtl::OUString& rComment) throw( SAXException )
716 : : {
717 : 0 : FinishStartElement();
718 : 0 : mp_Sequence[nCurrentPos] = '<';
719 : 0 : nCurrentPos++;
720 [ # # ]: 0 : if (nCurrentPos == SEQUENCESIZE)
721 : 0 : nCurrentPos = writeSequence();
722 : 0 : mp_Sequence[nCurrentPos] = '!';
723 : 0 : nCurrentPos++;
724 [ # # ]: 0 : if (nCurrentPos == SEQUENCESIZE)
725 : 0 : nCurrentPos = writeSequence();
726 : 0 : mp_Sequence[nCurrentPos] = '-';
727 : 0 : nCurrentPos++;
728 [ # # ]: 0 : if (nCurrentPos == SEQUENCESIZE)
729 : 0 : nCurrentPos = writeSequence();
730 : 0 : mp_Sequence[nCurrentPos] = '-';
731 : 0 : nCurrentPos++;
732 [ # # ]: 0 : if (nCurrentPos == SEQUENCESIZE)
733 : 0 : nCurrentPos = writeSequence();
734 : :
735 : 0 : sal_Bool bRet(writeString( rComment, sal_False, sal_False));
736 : :
737 : 0 : mp_Sequence[nCurrentPos] = '-';
738 : 0 : nCurrentPos++;
739 [ # # ]: 0 : if (nCurrentPos == SEQUENCESIZE)
740 : 0 : nCurrentPos = writeSequence();
741 : 0 : mp_Sequence[nCurrentPos] = '-';
742 : 0 : nCurrentPos++;
743 [ # # ]: 0 : if (nCurrentPos == SEQUENCESIZE)
744 : 0 : nCurrentPos = writeSequence();
745 : 0 : mp_Sequence[nCurrentPos] = '>';
746 : 0 : nCurrentPos++;
747 [ # # ]: 0 : if (nCurrentPos == SEQUENCESIZE)
748 : 0 : nCurrentPos = writeSequence();
749 : :
750 : 0 : return bRet;
751 : : }
752 : :
753 : 0 : inline sal_Int32 calcXMLByteLength( const sal_Unicode *pStr, sal_Int32 nStrLen,
754 : : sal_Bool bDoNormalization,
755 : : sal_Bool bNormalizeWhitespace )
756 : : {
757 : 0 : sal_Int32 nOutputLength = 0;
758 : 0 : sal_uInt32 nSurrogate = 0;
759 : :
760 [ # # ]: 0 : for( sal_Int32 i = 0 ; i < nStrLen ; i++ )
761 : : {
762 : 0 : sal_uInt16 c = pStr[i];
763 [ # # ][ # # ]: 0 : if( !IsInvalidChar(c) && (c >= 0x0001) && (c <= 0x007F) )
[ # # ][ # # ]
764 : : {
765 [ # # ]: 0 : if( bDoNormalization )
766 : : {
767 [ # # # # : 0 : switch( c )
# ]
768 : : {
769 : : case '&': // resemble to &
770 : 0 : nOutputLength +=5;
771 : 0 : break;
772 : : case '<': // <
773 : : case '>': // >
774 : 0 : nOutputLength +=4;
775 : 0 : break;
776 : : case 39: // 39 == ''', '
777 : : case '"': // "
778 : : case 13: // 
779 : 0 : nOutputLength += 6;
780 : 0 : break;
781 : :
782 : : case 10: // 

783 : : case 9: // 	
784 [ # # ]: 0 : if( bNormalizeWhitespace )
785 : : {
786 : 0 : nOutputLength += 6; //
787 : : }
788 : : else
789 : : {
790 : 0 : nOutputLength ++;
791 : : }
792 : 0 : break;
793 : : default:
794 : 0 : nOutputLength ++;
795 : : }
796 : : }
797 : : else
798 : : {
799 : 0 : nOutputLength ++;
800 : : }
801 : : }
802 [ # # ][ # # ]: 0 : else if( c >= 0xd800 && c < 0xdc00 )
803 : : {
804 : : // save surrogate
805 : 0 : nSurrogate = ( ( c & 0x03ff ) + 0x0040 );
806 : : }
807 [ # # ][ # # ]: 0 : else if( c >= 0xdc00 && c < 0xe000 )
808 : : {
809 : : // 2. surrogate: write as UTF-8 (if range is OK
810 : 0 : nSurrogate = ( nSurrogate << 10 ) | ( c & 0x03ff );
811 [ # # ][ # # ]: 0 : if( nSurrogate >= 0x00010000 && nSurrogate <= 0x0010FFFF )
812 : 0 : nOutputLength += 4;
813 : 0 : nSurrogate = 0;
814 : : }
815 [ # # ]: 0 : else if( c > 0x07FF )
816 : : {
817 : 0 : nOutputLength += 3;
818 : : }
819 : : else
820 : : {
821 : 0 : nOutputLength += 2;
822 : : }
823 : :
824 : : // surrogate processing
825 [ # # ][ # # ]: 0 : if( ( nSurrogate != 0 ) && !( c >= 0xd800 && c < 0xdc00 ) )
[ # # ]
826 : 0 : nSurrogate = 0;
827 : : }
828 : :
829 : 0 : return nOutputLength;
830 : : }
831 : :
832 : : /** returns position of first ascii 10 within the string, -1 when no 10 in string.
833 : : */
834 : 0 : static inline sal_Int32 getFirstLineBreak( const OUString & str ) throw ()
835 : : {
836 : 0 : const sal_Unicode *pSource = str.getStr();
837 : 0 : sal_Int32 nLen = str.getLength();
838 : :
839 [ # # ]: 0 : for( int n = 0; n < nLen ; n ++ )
840 : : {
841 [ # # ]: 0 : if( LINEFEED == pSource[n] ) {
842 : 0 : return n;
843 : : }
844 : : }
845 : 0 : return -1;
846 : : }
847 : :
848 : : /** returns position of last ascii 10 within sequence, -1 when no 10 in string.
849 : : */
850 : : static inline sal_Int32 getLastLineBreak( const Sequence<sal_Int8> & seq) throw ()
851 : : {
852 : : const sal_Int8 *pSource = seq.getConstArray();
853 : : sal_Int32 nLen = seq.getLength();
854 : :
855 : : for( int n = nLen-1; n >= 0 ; n -- )
856 : : {
857 : : if( LINEFEED == pSource[n] ) {
858 : : return n;
859 : : }
860 : : }
861 : : return -1;
862 : : }
863 : :
864 : :
865 : : class SAXWriter :
866 : : public WeakImplHelper3<
867 : : XActiveDataSource,
868 : : XExtendedDocumentHandler,
869 : : XServiceInfo >
870 : : {
871 : : public:
872 : 2787 : SAXWriter( ) :
873 : : m_seqStartElement(),
874 : : mp_SaxWriterHelper( NULL ),
875 : : m_bForceLineBreak(sal_False),
876 [ + - ]: 2787 : m_bAllowLineBreak(sal_False)
877 : 2787 : {}
878 : 5574 : ~SAXWriter()
879 [ + - ]: 2787 : {
880 [ + - ][ + - ]: 2787 : delete mp_SaxWriterHelper;
881 [ - + ]: 5574 : }
882 : :
883 : : public: // XActiveDataSource
884 : 2853 : virtual void SAL_CALL setOutputStream(const Reference< XOutputStream > & aStream)
885 : : throw (RuntimeException)
886 : : {
887 : : // temporary: set same stream again to clear buffer
888 [ - + ][ # # ]: 2853 : if ( m_out == aStream && mp_SaxWriterHelper && m_bDocStarted )
[ # # ][ - + ]
889 : 0 : mp_SaxWriterHelper->clearBuffer();
890 : : else
891 : : {
892 : :
893 : 2853 : m_out = aStream;
894 [ + + ]: 2853 : delete mp_SaxWriterHelper;
895 [ + - ][ + - ]: 2853 : mp_SaxWriterHelper = new SaxWriterHelper(m_out);
896 : 2853 : m_bDocStarted = sal_False;
897 : 2853 : m_nLevel = 0;
898 : 2853 : m_bIsCDATA = sal_False;
899 : :
900 : : }
901 : 2853 : }
902 : 0 : virtual Reference< XOutputStream > SAL_CALL getOutputStream(void)
903 : : throw(RuntimeException)
904 : 0 : { return m_out; }
905 : :
906 : : public: // XDocumentHandler
907 : : virtual void SAL_CALL startDocument(void)
908 : : throw(SAXException, RuntimeException);
909 : :
910 : : virtual void SAL_CALL endDocument(void)
911 : : throw(SAXException, RuntimeException);
912 : :
913 : : virtual void SAL_CALL startElement(const OUString& aName,
914 : : const Reference< XAttributeList > & xAttribs)
915 : : throw (SAXException, RuntimeException);
916 : :
917 : : virtual void SAL_CALL endElement(const OUString& aName)
918 : : throw(SAXException, RuntimeException);
919 : :
920 : : virtual void SAL_CALL characters(const OUString& aChars)
921 : : throw(SAXException, RuntimeException);
922 : :
923 : : virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces)
924 : : throw(SAXException, RuntimeException);
925 : : virtual void SAL_CALL processingInstruction(const OUString& aTarget,
926 : : const OUString& aData)
927 : : throw(SAXException, RuntimeException);
928 : : virtual void SAL_CALL setDocumentLocator(const Reference< XLocator > & xLocator)
929 : : throw(SAXException, RuntimeException);
930 : :
931 : : public: // XExtendedDocumentHandler
932 : : virtual void SAL_CALL startCDATA(void) throw(SAXException, RuntimeException);
933 : : virtual void SAL_CALL endCDATA(void) throw(RuntimeException);
934 : : virtual void SAL_CALL comment(const OUString& sComment)
935 : : throw(SAXException, RuntimeException);
936 : : virtual void SAL_CALL unknown(const OUString& sString)
937 : : throw(SAXException, RuntimeException);
938 : : virtual void SAL_CALL allowLineBreak(void)
939 : : throw(SAXException,RuntimeException);
940 : :
941 : : public: // XServiceInfo
942 : : OUString SAL_CALL getImplementationName() throw();
943 : : Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw();
944 : : sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw();
945 : :
946 : : private:
947 : :
948 : : void writeSequence( const Sequence<sal_Int8> & seq );
949 : : sal_Int32 getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurrence ) throw();
950 : :
951 : : Reference< XOutputStream > m_out;
952 : : Sequence < sal_Int8 > m_seqStartElement;
953 : : SaxWriterHelper* mp_SaxWriterHelper;
954 : :
955 : : // Status information
956 : : sal_Bool m_bDocStarted : 1;
957 : : sal_Bool m_bIsCDATA : 1;
958 : : sal_Bool m_bForceLineBreak : 1;
959 : : sal_Bool m_bAllowLineBreak : 1;
960 : : sal_Int32 m_nLevel;
961 : : };
962 : :
963 : :
964 : : //--------------------------------------
965 : : // the extern interface
966 : : //---------------------------------------
967 : 2787 : Reference < XInterface > SAL_CALL SaxWriter_CreateInstance(
968 : : SAL_UNUSED_PARAMETER const Reference < XMultiServiceFactory > & )
969 : : throw (Exception)
970 : : {
971 [ + - ]: 2787 : SAXWriter *p = new SAXWriter;
972 : 2787 : return Reference< XInterface > ( (static_cast< OWeakObject * >(p)) );
973 : : }
974 : :
975 : 83 : OUString SaxWriter_getServiceName() throw()
976 : : {
977 : 83 : return OUString("com.sun.star.xml.sax.Writer");
978 : : }
979 : :
980 : 83 : OUString SaxWriter_getImplementationName() throw()
981 : : {
982 : 83 : return OUString("com.sun.star.extensions.xml.sax.Writer");
983 : : }
984 : :
985 : 83 : Sequence< OUString > SaxWriter_getSupportedServiceNames(void) throw()
986 : : {
987 : 83 : Sequence<OUString> aRet(1);
988 [ + - ]: 83 : aRet.getArray()[0] = SaxWriter_getServiceName();
989 : 83 : return aRet;
990 : : }
991 : :
992 : :
993 : 241674 : sal_Int32 SAXWriter::getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurrence ) throw()
994 : : {
995 : 241674 : sal_Int32 nLength =-1;
996 [ + - ]: 241674 : if (mp_SaxWriterHelper)
997 : : {
998 [ + + ]: 241674 : if ( m_bForceLineBreak ||
[ - + # # ]
[ + + ]
999 : : (m_bAllowLineBreak &&
1000 : 0 : ((nFirstLineBreakOccurrence + mp_SaxWriterHelper->GetLastColumnCount()) > MAXCOLUMNCOUNT)) )
1001 : 1910 : nLength = m_nLevel;
1002 : : }
1003 : 241674 : m_bForceLineBreak = sal_False;
1004 : 241674 : m_bAllowLineBreak = sal_False;
1005 : 241674 : return nLength;
1006 : : }
1007 : :
1008 : 0 : static inline sal_Bool isFirstCharWhitespace( const sal_Unicode *p ) throw()
1009 : : {
1010 : 0 : return *p == ' ';
1011 : : }
1012 : :
1013 : :
1014 : : // XServiceInfo
1015 : 0 : OUString SAXWriter::getImplementationName() throw()
1016 : : {
1017 : 0 : return SaxWriter_getImplementationName();
1018 : : }
1019 : :
1020 : : // XServiceInfo
1021 : 0 : sal_Bool SAXWriter::supportsService(const OUString& ServiceName) throw()
1022 : : {
1023 : 0 : Sequence< OUString > aSNL = getSupportedServiceNames();
1024 : 0 : const OUString * pArray = aSNL.getConstArray();
1025 : :
1026 [ # # ]: 0 : for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
1027 [ # # ]: 0 : if( pArray[i] == ServiceName )
1028 : 0 : return sal_True;
1029 : :
1030 [ # # ]: 0 : return sal_False;
1031 : : }
1032 : :
1033 : : // XServiceInfo
1034 : 0 : Sequence< OUString > SAXWriter::getSupportedServiceNames(void) throw ()
1035 : : {
1036 : 0 : Sequence<OUString> seq(1);
1037 [ # # ]: 0 : seq.getArray()[0] = SaxWriter_getServiceName();
1038 : 0 : return seq;
1039 : : }
1040 : :
1041 : :
1042 : :
1043 : 2835 : void SAXWriter::startDocument() throw(SAXException, RuntimeException )
1044 : : {
1045 [ + - ][ + - ]: 2835 : if( m_bDocStarted || ! m_out.is() || !mp_SaxWriterHelper ) {
[ - + ][ - + ]
1046 [ # # ]: 0 : throw SAXException();
1047 : : }
1048 : 2835 : m_bDocStarted = sal_True;
1049 : 2835 : mp_SaxWriterHelper->startDocument();
1050 : 2835 : }
1051 : :
1052 : :
1053 : 2835 : void SAXWriter::endDocument(void) throw(SAXException, RuntimeException)
1054 : : {
1055 [ - + ]: 2835 : if( ! m_bDocStarted )
1056 : : {
1057 : : throw SAXException(
1058 : : OUString("endDocument called before startDocument"),
1059 [ # # ]: 0 : Reference< XInterface >() , Any() );
1060 : : }
1061 [ - + ]: 2835 : if( m_nLevel ) {
1062 : : throw SAXException(
1063 : : OUString("unexpected end of document"),
1064 [ # # ]: 0 : Reference< XInterface >() , Any() );
1065 : : }
1066 : 2835 : mp_SaxWriterHelper->endDocument();
1067 : : try
1068 : : {
1069 [ + - ][ + - ]: 2835 : m_out->closeOutput();
1070 : : }
1071 [ # # ]: 0 : catch (const IOException & e)
1072 : : {
1073 : 0 : Any a;
1074 [ # # ]: 0 : a <<= e;
1075 : : throw SAXException(
1076 : : OUString("IO exception during closing the IO Stream"),
1077 : : Reference< XInterface > (),
1078 [ # # ]: 0 : a );
1079 : : }
1080 : 2835 : }
1081 : :
1082 : :
1083 : 93094 : void SAXWriter::startElement(const OUString& aName, const Reference< XAttributeList >& xAttribs)
1084 : : throw(SAXException, RuntimeException)
1085 : : {
1086 [ - + ]: 93094 : if( ! m_bDocStarted )
1087 : : {
1088 [ # # ]: 0 : SAXException except;
1089 : 0 : except.Message = OUString( "startElement called before startDocument" );
1090 [ # # ]: 0 : throw except;
1091 : : }
1092 [ - + ]: 93094 : if( m_bIsCDATA )
1093 : : {
1094 [ # # ]: 0 : SAXException except;
1095 : 0 : except.Message = OUString( "startElement call not allowed with CDATA sections" );
1096 [ # # ]: 0 : throw except;
1097 : : }
1098 : :
1099 : 93094 : sal_Int32 nLength(0);
1100 [ - + ]: 93094 : if (m_bAllowLineBreak)
1101 : : {
1102 [ # # ]: 0 : sal_Int32 nAttribCount = xAttribs.is() ? xAttribs->getLength() : 0;
1103 : :
1104 : 0 : nLength ++; // "<"
1105 : : nLength += calcXMLByteLength( aName.getStr() , aName.getLength(),
1106 : 0 : sal_False, sal_False ); // the tag name
1107 : :
1108 : : sal_Int16 n;
1109 [ # # ]: 0 : for( n = 0 ; n < static_cast<sal_Int16>(nAttribCount) ; n ++ ) {
1110 : 0 : nLength ++; // " "
1111 [ # # ][ # # ]: 0 : OUString tmp = xAttribs->getNameByIndex( n );
1112 : :
1113 : 0 : nLength += calcXMLByteLength( tmp.getStr() , tmp.getLength() , sal_False, sal_False );
1114 : :
1115 : 0 : nLength += 2; // ="
1116 : :
1117 [ # # ][ # # ]: 0 : tmp = xAttribs->getValueByIndex( n );
1118 : :
1119 : 0 : nLength += calcXMLByteLength( tmp.getStr(), tmp.getLength(), sal_True, sal_True );
1120 : :
1121 : 0 : nLength += 1; // "
1122 : 0 : }
1123 : :
1124 : 0 : nLength ++; // '>'
1125 : : }
1126 : :
1127 : : // Is there a new indentation necesarry ?
1128 : 93094 : sal_Int32 nPrefix(getIndentPrefixLength( nLength ));
1129 : :
1130 : : // write into sequence
1131 [ + + ]: 93094 : if( nPrefix >= 0 )
1132 : 1334 : mp_SaxWriterHelper->insertIndentation( nPrefix );
1133 : :
1134 : 93094 : SaxInvalidCharacterError eRet(mp_SaxWriterHelper->startElement(aName, xAttribs));
1135 : :
1136 : 93094 : m_nLevel++;
1137 : :
1138 [ - + ]: 93094 : if (eRet == SAX_WARNING)
1139 : : {
1140 [ # # ]: 0 : SAXInvalidCharacterException except;
1141 : 0 : except.Message = OUString( "Invalid charcter during XML-Export in a attribute value" );
1142 [ # # ]: 0 : throw except;
1143 : : }
1144 [ - + ]: 93094 : else if (eRet == SAX_ERROR)
1145 : : {
1146 [ # # ]: 0 : SAXException except;
1147 : 0 : except.Message = OUString( "Invalid charcter during XML-Export" );
1148 [ # # ]: 0 : throw except;
1149 : : }
1150 : 93094 : }
1151 : :
1152 : 93094 : void SAXWriter::endElement(const OUString& aName) throw (SAXException, RuntimeException)
1153 : : {
1154 [ - + ]: 93094 : if( ! m_bDocStarted ) {
1155 [ # # ]: 0 : throw SAXException ();
1156 : : }
1157 : 93094 : m_nLevel --;
1158 : :
1159 [ - + ]: 93094 : if( m_nLevel < 0 ) {
1160 [ # # ]: 0 : throw SAXException();
1161 : : }
1162 : 93094 : sal_Bool bRet(sal_True);
1163 : :
1164 [ + + ]: 93094 : if( mp_SaxWriterHelper->FinishEmptyElement() )
1165 : 11198 : m_bForceLineBreak = sal_False;
1166 : : else
1167 : : {
1168 : : // only ascii chars allowed
1169 : 81896 : sal_Int32 nLength(0);
1170 [ - + ]: 81896 : if (m_bAllowLineBreak)
1171 : 0 : nLength = 3 + calcXMLByteLength( aName.getStr(), aName.getLength(), sal_False, sal_False );
1172 : 81896 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1173 : :
1174 [ + + ]: 81896 : if( nPrefix >= 0 )
1175 : 576 : mp_SaxWriterHelper->insertIndentation( nPrefix );
1176 : :
1177 : 81896 : bRet = mp_SaxWriterHelper->endElement(aName);
1178 : : }
1179 : :
1180 [ - + ]: 93094 : if (!bRet)
1181 : : {
1182 [ # # ]: 0 : SAXException except;
1183 : 0 : except.Message = OUString( "Invalid charcter during XML-Export" );
1184 [ # # ]: 0 : throw except;
1185 : : }
1186 : 93094 : }
1187 : :
1188 : 66572 : void SAXWriter::characters(const OUString& aChars) throw(SAXException, RuntimeException)
1189 : : {
1190 [ - + ]: 66572 : if( ! m_bDocStarted )
1191 : : {
1192 [ # # ]: 0 : SAXException except;
1193 : 0 : except.Message = OUString( "characters method called before startDocument" );
1194 [ # # ]: 0 : throw except;
1195 : : }
1196 : :
1197 : 66572 : sal_Bool bThrowException(sal_False);
1198 [ + + ]: 66572 : if( !aChars.isEmpty() )
1199 : : {
1200 [ - + ]: 66550 : if( m_bIsCDATA )
1201 : 0 : bThrowException = !mp_SaxWriterHelper->writeString( aChars, sal_False, sal_False );
1202 : : else
1203 : : {
1204 : : // Note : nFirstLineBreakOccurrence is not exact, because we don't know, how
1205 : : // many 2 and 3 byte chars are inbetween. However this whole stuff
1206 : : // is eitherway for pretty printing only, so it does not need to be exact.
1207 : 66550 : sal_Int32 nLength(0);
1208 : 66550 : sal_Int32 nIndentPrefix(-1);
1209 [ - + ]: 66550 : if (m_bAllowLineBreak)
1210 : : {
1211 : 0 : sal_Int32 nFirstLineBreakOccurrence = getFirstLineBreak( aChars );
1212 : :
1213 : : nLength = calcXMLByteLength( aChars.getStr(), aChars.getLength(),
1214 : 0 : ! m_bIsCDATA , sal_False );
1215 : : nIndentPrefix = getIndentPrefixLength(
1216 [ # # ]: 0 : nFirstLineBreakOccurrence >= 0 ? nFirstLineBreakOccurrence : nLength );
1217 : : }
1218 : : else
1219 : 66550 : nIndentPrefix = getIndentPrefixLength(nLength);
1220 : :
1221 : : // insert indentation
1222 [ - + ]: 66550 : if( nIndentPrefix >= 0 )
1223 : : {
1224 [ # # ]: 0 : if( isFirstCharWhitespace( aChars.getStr() ) )
1225 : 0 : mp_SaxWriterHelper->insertIndentation( nIndentPrefix - 1 );
1226 : : else
1227 : 0 : mp_SaxWriterHelper->insertIndentation( nIndentPrefix );
1228 : : }
1229 : 66550 : bThrowException = !mp_SaxWriterHelper->writeString(aChars, sal_True , sal_False);
1230 : : }
1231 : : }
1232 [ - + ]: 66572 : if (bThrowException)
1233 : : {
1234 [ # # ]: 0 : SAXInvalidCharacterException except;
1235 : 0 : except.Message = OUString( "Invalid charcter during XML-Export" );
1236 [ # # ]: 0 : throw except;
1237 : : }
1238 : 66572 : }
1239 : :
1240 : :
1241 : 4038 : void SAXWriter::ignorableWhitespace(const OUString&) throw(SAXException, RuntimeException)
1242 : : {
1243 [ - + ]: 4038 : if( ! m_bDocStarted )
1244 : : {
1245 [ # # ]: 0 : throw SAXException ();
1246 : : }
1247 : :
1248 : 4038 : m_bForceLineBreak = sal_True;
1249 : 4038 : }
1250 : :
1251 : 0 : void SAXWriter::processingInstruction(const OUString& aTarget, const OUString& aData)
1252 : : throw (SAXException, RuntimeException)
1253 : : {
1254 [ # # ][ # # ]: 0 : if( ! m_bDocStarted || m_bIsCDATA )
1255 : : {
1256 [ # # ]: 0 : throw SAXException();
1257 : : }
1258 : :
1259 : 0 : sal_Int32 nLength(0);
1260 [ # # ]: 0 : if (m_bAllowLineBreak)
1261 : : {
1262 : 0 : nLength = 2; // "<?"
1263 : 0 : nLength += calcXMLByteLength( aTarget.getStr(), aTarget.getLength(), sal_False, sal_False );
1264 : :
1265 : 0 : nLength += 1; // " "
1266 : :
1267 : 0 : nLength += calcXMLByteLength( aData.getStr(), aData.getLength(), sal_False, sal_False );
1268 : :
1269 : 0 : nLength += 2; // "?>"
1270 : : }
1271 : :
1272 : 0 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1273 : :
1274 [ # # ]: 0 : if( nPrefix >= 0 )
1275 : 0 : mp_SaxWriterHelper->insertIndentation( nPrefix );
1276 : :
1277 [ # # ]: 0 : if (!mp_SaxWriterHelper->processingInstruction(aTarget, aData))
1278 : : {
1279 [ # # ]: 0 : SAXException except;
1280 : 0 : except.Message = OUString( "Invalid charcter during XML-Export" );
1281 [ # # ]: 0 : throw except;
1282 : : }
1283 : 0 : }
1284 : :
1285 : :
1286 : 0 : void SAXWriter::setDocumentLocator(const Reference< XLocator >&)
1287 : : throw (SAXException, RuntimeException)
1288 : : {
1289 : :
1290 : 0 : }
1291 : :
1292 : 0 : void SAXWriter::startCDATA(void) throw(SAXException, RuntimeException)
1293 : : {
1294 [ # # ][ # # ]: 0 : if( ! m_bDocStarted || m_bIsCDATA)
1295 : : {
1296 [ # # ]: 0 : throw SAXException ();
1297 : : }
1298 : :
1299 : 0 : sal_Int32 nLength = 9;
1300 : 0 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1301 [ # # ]: 0 : if( nPrefix >= 0 )
1302 : 0 : mp_SaxWriterHelper->insertIndentation( nPrefix );
1303 : :
1304 : 0 : mp_SaxWriterHelper->startCDATA();
1305 : :
1306 : 0 : m_bIsCDATA = sal_True;
1307 : 0 : }
1308 : :
1309 : 0 : void SAXWriter::endCDATA(void) throw (RuntimeException)
1310 : : {
1311 [ # # ]: 0 : if( ! m_bDocStarted | ! m_bIsCDATA)
1312 : : {
1313 [ # # ]: 0 : SAXException except;
1314 : 0 : except.Message = OUString( "endCDATA was called without startCDATA" );
1315 [ # # ]: 0 : throw except;
1316 : : }
1317 : :
1318 : 0 : sal_Int32 nLength = 3;
1319 : 0 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1320 [ # # ]: 0 : if( nPrefix >= 0 )
1321 : 0 : mp_SaxWriterHelper->insertIndentation( nPrefix );
1322 : :
1323 : 0 : mp_SaxWriterHelper->endCDATA();
1324 : :
1325 : 0 : m_bIsCDATA = sal_False;
1326 : 0 : }
1327 : :
1328 : :
1329 : 0 : void SAXWriter::comment(const OUString& sComment) throw(SAXException, RuntimeException)
1330 : : {
1331 [ # # ][ # # ]: 0 : if( ! m_bDocStarted || m_bIsCDATA )
1332 : : {
1333 [ # # ]: 0 : throw SAXException();
1334 : : }
1335 : :
1336 : 0 : sal_Int32 nLength(0);
1337 [ # # ]: 0 : if (m_bAllowLineBreak)
1338 : : {
1339 : 0 : nLength = 4; // "<!--"
1340 : 0 : nLength += calcXMLByteLength( sComment.getStr(), sComment.getLength(), sal_False, sal_False);
1341 : :
1342 : 0 : nLength += 3;
1343 : : }
1344 : :
1345 : 0 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1346 [ # # ]: 0 : if( nPrefix >= 0 )
1347 : 0 : mp_SaxWriterHelper->insertIndentation( nPrefix );
1348 : :
1349 [ # # ]: 0 : if (!mp_SaxWriterHelper->comment(sComment))
1350 : : {
1351 [ # # ]: 0 : SAXException except;
1352 : 0 : except.Message = OUString( "Invalid charcter during XML-Export" );
1353 [ # # ]: 0 : throw except;
1354 : : }
1355 : 0 : }
1356 : :
1357 : :
1358 : 0 : void SAXWriter::allowLineBreak( ) throw ( SAXException , RuntimeException)
1359 : : {
1360 [ # # ][ # # ]: 0 : if( ! m_bDocStarted || m_bAllowLineBreak ) {
1361 [ # # ]: 0 : throw SAXException();
1362 : : }
1363 : :
1364 : 0 : m_bAllowLineBreak = sal_True;
1365 : 0 : }
1366 : :
1367 : 134 : void SAXWriter::unknown(const OUString& sString) throw (SAXException, RuntimeException)
1368 : : {
1369 : :
1370 [ - + ]: 134 : if( ! m_bDocStarted )
1371 : : {
1372 [ # # ]: 0 : throw SAXException ();
1373 : : }
1374 [ - + ]: 134 : if( m_bIsCDATA )
1375 : : {
1376 [ # # ]: 0 : throw SAXException();
1377 : : }
1378 : :
1379 [ - + ]: 134 : if( sString.matchAsciiL( "<?xml", 5 ) )
1380 : 134 : return;
1381 : :
1382 : 134 : sal_Int32 nLength(0);
1383 [ - + ]: 134 : if (m_bAllowLineBreak)
1384 : 0 : nLength = calcXMLByteLength( sString.getStr(), sString.getLength(), sal_False, sal_False );
1385 : :
1386 : 134 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1387 [ - + ]: 134 : if( nPrefix >= 0 )
1388 : 0 : mp_SaxWriterHelper->insertIndentation( nPrefix );
1389 : :
1390 [ - + ]: 134 : if (!mp_SaxWriterHelper->writeString( sString, sal_False, sal_False))
1391 : : {
1392 [ # # ]: 0 : SAXException except;
1393 : 0 : except.Message = OUString( "Invalid charcter during XML-Export" );
1394 [ # # ]: 0 : throw except;
1395 : : }
1396 : : }
1397 : :
1398 : : }
1399 : :
1400 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|