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/XParser.hpp>
24 : #include <com/sun/star/xml/sax/SAXParseException.hpp>
25 : #include <com/sun/star/xml/sax/SAXInvalidCharacterException.hpp>
26 : #include <com/sun/star/xml/sax/XWriter.hpp>
27 :
28 : #include <com/sun/star/io/XActiveDataSource.hpp>
29 :
30 : #include <cppuhelper/factory.hxx>
31 : #include <cppuhelper/weak.hxx>
32 : #include <cppuhelper/implbase2.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 1584 : 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 1584 : m_bStartElementFinished(sal_True)
106 : {
107 : OSL_ENSURE(SEQUENCESIZE > 50, "Sequence cache size to small");
108 1584 : mp_Sequence = m_Sequence.getArray();
109 1584 : }
110 1584 : ~SaxWriterHelper()
111 1584 : {
112 : OSL_ENSURE(!nCurrentPos, "cached Sequence not written");
113 : OSL_ENSURE(m_bStartElementFinished, "StartElement not complettly written");
114 1584 : }
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 3749215 : inline sal_Bool IsInvalidChar(const sal_Unicode aChar)
167 : {
168 3749215 : sal_Bool bRet(sal_False);
169 : // check first for the most common characters
170 3749215 : if( aChar < 32 || aChar >= 0xd800 )
171 0 : bRet = ( (aChar < 32 && ! g_bValidCharsBelow32[aChar]) ||
172 : aChar == 0xffff ||
173 0 : aChar == 0xfffe );
174 3749215 : return bRet;
175 : }
176 :
177 : /********
178 : * write through to the output stream
179 : *
180 : *****/
181 5036 : inline sal_uInt32 SaxWriterHelper::writeSequence() throw( SAXException )
182 : {
183 : try
184 : {
185 5036 : 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 5036 : nLastLineFeedPos -= SEQUENCESIZE;
197 5036 : return 0;
198 : }
199 :
200 2 : 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 2 : sal_uInt32 nCount(SEQUENCESIZE - rPos);
205 2 : memcpy( &(pTarget[rPos]) , pBytes, nCount);
206 :
207 : OSL_ENSURE(rPos + nCount == SEQUENCESIZE, "the position should be the at the end");
208 :
209 2 : rPos = writeSequence();
210 2 : sal_uInt32 nRestCount(nBytesCount - nCount);
211 2 : if ((rPos + nRestCount) <= SEQUENCESIZE)
212 : {
213 2 : memcpy( &(pTarget[rPos]), &pBytes[nCount], nRestCount);
214 2 : rPos += nRestCount;
215 : }
216 : else
217 0 : AddBytes(pTarget, rPos, &pBytes[nCount], nRestCount);
218 2 : }
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 309820 : 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 309820 : sal_Bool bRet(sal_True);
235 309820 : sal_uInt32 nSurrogate = 0;
236 :
237 4059035 : for( sal_Int32 i = 0 ; i < nStrLen ; i ++ )
238 : {
239 3749215 : sal_uInt16 c = pStr[i];
240 3749215 : if (IsInvalidChar(c))
241 0 : bRet = sal_False;
242 3749215 : else if( (c >= 0x0001) && (c <= 0x007F) )
243 : {
244 7495230 : if( bDoNormalization )
245 : {
246 1315466 : 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 160 : if ((rPos + 4) > SEQUENCESIZE)
262 0 : AddBytes(pTarget, rPos, (sal_Int8*)"<", 4);
263 : else
264 : {
265 160 : memcpy( &(pTarget[rPos]) , "<" , 4 );
266 160 : rPos += 4; // <
267 : }
268 : }
269 160 : break;
270 : case '>':
271 : {
272 68 : if ((rPos + 4) > SEQUENCESIZE)
273 0 : AddBytes(pTarget, rPos, (sal_Int8*)">", 4);
274 : else
275 : {
276 68 : memcpy( &(pTarget[rPos]) , ">" , 4 );
277 68 : rPos += 4; // >
278 : }
279 : }
280 68 : break;
281 : case 39: // 39 == '''
282 : {
283 176 : if ((rPos + 6) > SEQUENCESIZE)
284 2 : AddBytes(pTarget, rPos, (sal_Int8*)"'", 6);
285 : else
286 : {
287 174 : memcpy( &(pTarget[rPos]) , "'" , 6 );
288 174 : rPos += 6; // '
289 : }
290 : }
291 176 : 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 0 : 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 0 : pTarget[rPos] = LINEFEED;
329 0 : nLastLineFeedPos = rPos;
330 0 : rPos ++;
331 : }
332 : }
333 0 : 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 1315062 : pTarget[rPos] = (sal_Int8)c;
356 1315062 : rPos ++;
357 : }
358 1315062 : break;
359 : }
360 : }
361 : else
362 : {
363 2432149 : pTarget[rPos] = (sal_Int8)c;
364 2432149 : if ((sal_Int8)c == LINEFEED)
365 0 : nLastLineFeedPos = rPos;
366 2432149 : rPos ++;
367 : }
368 : }
369 1600 : 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 1600 : 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 1600 : else if( c > 0x07FF )
411 : {
412 : sal_Int8 aBytes[] = { sal_Int8(0xE0 | ((c >> 12) & 0x0F)),
413 : sal_Int8(0x80 | ((c >> 6) & 0x3F)),
414 848 : sal_Int8(0x80 | ((c >> 0) & 0x3F)) };
415 848 : if ((rPos + 3) > SEQUENCESIZE)
416 0 : AddBytes(pTarget, rPos, aBytes, 3);
417 : else
418 : {
419 848 : pTarget[rPos] = aBytes[0];
420 848 : rPos ++;
421 848 : pTarget[rPos] = aBytes[1];
422 848 : rPos ++;
423 848 : pTarget[rPos] = aBytes[2];
424 848 : rPos ++;
425 : }
426 : }
427 : else
428 : {
429 : sal_Int8 aBytes[] = { sal_Int8(0xC0 | ((c >> 6) & 0x1F)),
430 752 : sal_Int8(0x80 | ((c >> 0) & 0x3F)) };
431 752 : if ((rPos + 2) > SEQUENCESIZE)
432 0 : AddBytes(pTarget, rPos, aBytes, 2);
433 : else
434 : {
435 752 : pTarget[rPos] = aBytes[0];
436 752 : rPos ++;
437 752 : pTarget[rPos] = aBytes[1];
438 752 : rPos ++;
439 : }
440 : }
441 : OSL_ENSURE(rPos <= SEQUENCESIZE, "not reset current position");
442 3749215 : if (rPos == SEQUENCESIZE)
443 3661 : rPos = writeSequence();
444 :
445 : // reset left-over surrogate
446 3749215 : 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 309820 : return bRet;
454 : }
455 :
456 412412 : inline void SaxWriterHelper::FinishStartElement() throw( SAXException )
457 : {
458 412412 : if (!m_bStartElementFinished)
459 : {
460 50184 : mp_Sequence[nCurrentPos] = '>';
461 50184 : nCurrentPos++;
462 50184 : if (nCurrentPos == SEQUENCESIZE)
463 0 : nCurrentPos = writeSequence();
464 50184 : m_bStartElementFinished = sal_True;
465 : }
466 412412 : }
467 :
468 314 : inline void SaxWriterHelper::insertIndentation(sal_uInt32 m_nLevel) throw( SAXException )
469 : {
470 314 : FinishStartElement();
471 314 : if (m_nLevel > 0)
472 : {
473 144 : if ((nCurrentPos + m_nLevel + 1) <= SEQUENCESIZE)
474 : {
475 144 : mp_Sequence[nCurrentPos] = LINEFEED;
476 144 : nLastLineFeedPos = nCurrentPos;
477 144 : nCurrentPos++;
478 144 : memset( &(mp_Sequence[nCurrentPos]) , 32 , m_nLevel );
479 144 : nCurrentPos += m_nLevel;
480 144 : 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 170 : mp_Sequence[nCurrentPos] = LINEFEED;
499 170 : nLastLineFeedPos = nCurrentPos;
500 170 : nCurrentPos++;
501 170 : if (nCurrentPos == SEQUENCESIZE)
502 0 : nCurrentPos = writeSequence();
503 : }
504 314 : }
505 :
506 309820 : inline sal_Bool SaxWriterHelper::writeString( const rtl::OUString& rWriteOutString,
507 : sal_Bool bDoNormalization,
508 : sal_Bool bNormalizeWhitespace ) throw( SAXException )
509 : {
510 309820 : FinishStartElement();
511 : return convertToXML(rWriteOutString.getStr(),
512 : rWriteOutString.getLength(),
513 : bDoNormalization,
514 : bNormalizeWhitespace,
515 : mp_Sequence,
516 309820 : nCurrentPos);
517 : }
518 :
519 1338 : inline void SaxWriterHelper::startDocument() throw( SAXException )
520 : {
521 1338 : const char pc[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
522 1338 : const int nLen = strlen( pc );
523 1338 : if ((nCurrentPos + nLen) <= SEQUENCESIZE)
524 : {
525 1338 : memcpy( mp_Sequence, pc , nLen );
526 1338 : 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 1338 : if (nCurrentPos == SEQUENCESIZE)
534 0 : nCurrentPos = writeSequence();
535 1338 : mp_Sequence[nCurrentPos] = LINEFEED;
536 1338 : nCurrentPos++;
537 1338 : if (nCurrentPos == SEQUENCESIZE)
538 0 : nCurrentPos = writeSequence();
539 1338 : }
540 :
541 52086 : inline SaxInvalidCharacterError SaxWriterHelper::startElement(const rtl::OUString& rName, const Reference< XAttributeList >& xAttribs) throw( SAXException )
542 : {
543 52086 : FinishStartElement();
544 52086 : mp_Sequence[nCurrentPos] = '<';
545 52086 : nCurrentPos++;
546 52086 : if (nCurrentPos == SEQUENCESIZE)
547 16 : nCurrentPos = writeSequence();
548 :
549 52086 : SaxInvalidCharacterError eRet(SAX_NONE);
550 52086 : if (!writeString(rName, sal_False, sal_False))
551 0 : eRet = SAX_ERROR;
552 :
553 52086 : sal_Int16 nAttribCount = xAttribs.is() ? static_cast<sal_Int16>(xAttribs->getLength()) : 0;
554 135706 : for(sal_Int16 i = 0 ; i < nAttribCount ; i++ )
555 : {
556 83620 : mp_Sequence[nCurrentPos] = ' ';
557 83620 : nCurrentPos++;
558 83620 : if (nCurrentPos == SEQUENCESIZE)
559 7 : nCurrentPos = writeSequence();
560 :
561 83620 : if (!writeString(xAttribs->getNameByIndex( i ), sal_False, sal_False))
562 0 : eRet = SAX_ERROR;
563 :
564 83620 : mp_Sequence[nCurrentPos] = '=';
565 83620 : nCurrentPos++;
566 83620 : if (nCurrentPos == SEQUENCESIZE)
567 6 : nCurrentPos = writeSequence();
568 83620 : mp_Sequence[nCurrentPos] = '"';
569 83620 : nCurrentPos++;
570 83620 : if (nCurrentPos == SEQUENCESIZE)
571 0 : nCurrentPos = writeSequence();
572 :
573 83620 : if (!writeString(xAttribs->getValueByIndex( i ), sal_True, sal_True) &&
574 : !(eRet == SAX_ERROR))
575 0 : eRet = SAX_WARNING;
576 :
577 83620 : mp_Sequence[nCurrentPos] = '"';
578 83620 : nCurrentPos++;
579 83620 : if (nCurrentPos == SEQUENCESIZE)
580 4 : nCurrentPos = writeSequence();
581 : }
582 :
583 52086 : m_bStartElementFinished = sal_False; // because the '>' character is not added,
584 : // because it is possible, that the "/>"
585 : // characters have to add
586 52086 : return eRet;
587 : }
588 :
589 52086 : inline sal_Bool SaxWriterHelper::FinishEmptyElement() throw( SAXException )
590 : {
591 52086 : if (m_bStartElementFinished)
592 50184 : return sal_False;
593 :
594 1902 : mp_Sequence[nCurrentPos] = '/';
595 1902 : nCurrentPos++;
596 1902 : if (nCurrentPos == SEQUENCESIZE)
597 2 : nCurrentPos = writeSequence();
598 1902 : mp_Sequence[nCurrentPos] = '>';
599 1902 : nCurrentPos++;
600 1902 : if (nCurrentPos == SEQUENCESIZE)
601 0 : nCurrentPos = writeSequence();
602 :
603 1902 : m_bStartElementFinished = sal_True;
604 :
605 1902 : return sal_True;
606 : }
607 :
608 50184 : inline sal_Bool SaxWriterHelper::endElement(const rtl::OUString& rName) throw( SAXException )
609 : {
610 50184 : FinishStartElement();
611 50184 : mp_Sequence[nCurrentPos] = '<';
612 50184 : nCurrentPos++;
613 50184 : if (nCurrentPos == SEQUENCESIZE)
614 0 : nCurrentPos = writeSequence();
615 50184 : mp_Sequence[nCurrentPos] = '/';
616 50184 : nCurrentPos++;
617 50184 : if (nCurrentPos == SEQUENCESIZE)
618 0 : nCurrentPos = writeSequence();
619 :
620 50184 : sal_Bool bRet(writeString( rName, sal_False, sal_False));
621 :
622 50184 : mp_Sequence[nCurrentPos] = '>';
623 50184 : nCurrentPos++;
624 50184 : if (nCurrentPos == SEQUENCESIZE)
625 0 : nCurrentPos = writeSequence();
626 :
627 50184 : return bRet;
628 : }
629 :
630 1338 : inline void SaxWriterHelper::endDocument() throw( SAXException )
631 : {
632 1338 : if (nCurrentPos > 0)
633 : {
634 1338 : m_Sequence.realloc(nCurrentPos);
635 1338 : nCurrentPos = writeSequence();
636 : //m_Sequence.realloc(SEQUENCESIZE);
637 : }
638 1338 : }
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 8 : inline sal_Bool SaxWriterHelper::comment(const rtl::OUString& rComment) throw( SAXException )
716 : {
717 8 : FinishStartElement();
718 8 : mp_Sequence[nCurrentPos] = '<';
719 8 : nCurrentPos++;
720 8 : if (nCurrentPos == SEQUENCESIZE)
721 0 : nCurrentPos = writeSequence();
722 8 : mp_Sequence[nCurrentPos] = '!';
723 8 : nCurrentPos++;
724 8 : if (nCurrentPos == SEQUENCESIZE)
725 0 : nCurrentPos = writeSequence();
726 8 : mp_Sequence[nCurrentPos] = '-';
727 8 : nCurrentPos++;
728 8 : if (nCurrentPos == SEQUENCESIZE)
729 0 : nCurrentPos = writeSequence();
730 8 : mp_Sequence[nCurrentPos] = '-';
731 8 : nCurrentPos++;
732 8 : if (nCurrentPos == SEQUENCESIZE)
733 0 : nCurrentPos = writeSequence();
734 :
735 8 : sal_Bool bRet(writeString( rComment, sal_False, sal_False));
736 :
737 8 : mp_Sequence[nCurrentPos] = '-';
738 8 : nCurrentPos++;
739 8 : if (nCurrentPos == SEQUENCESIZE)
740 0 : nCurrentPos = writeSequence();
741 8 : mp_Sequence[nCurrentPos] = '-';
742 8 : nCurrentPos++;
743 8 : if (nCurrentPos == SEQUENCESIZE)
744 0 : nCurrentPos = writeSequence();
745 8 : mp_Sequence[nCurrentPos] = '>';
746 8 : nCurrentPos++;
747 8 : if (nCurrentPos == SEQUENCESIZE)
748 0 : nCurrentPos = writeSequence();
749 :
750 8 : 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 WeakImplHelper2<
867 : XWriter,
868 : XServiceInfo >
869 : {
870 : public:
871 1408 : SAXWriter( ) :
872 : m_seqStartElement(),
873 : mp_SaxWriterHelper( NULL ),
874 : m_bForceLineBreak(sal_False),
875 1408 : m_bAllowLineBreak(sal_False)
876 1408 : {}
877 2816 : ~SAXWriter()
878 2816 : {
879 1408 : delete mp_SaxWriterHelper;
880 2816 : }
881 :
882 : public: // XActiveDataSource
883 1584 : virtual void SAL_CALL setOutputStream(const Reference< XOutputStream > & aStream)
884 : throw (RuntimeException)
885 : {
886 : // temporary: set same stream again to clear buffer
887 1584 : if ( m_out == aStream && mp_SaxWriterHelper && m_bDocStarted )
888 0 : mp_SaxWriterHelper->clearBuffer();
889 : else
890 : {
891 :
892 1584 : m_out = aStream;
893 1584 : delete mp_SaxWriterHelper;
894 1584 : mp_SaxWriterHelper = new SaxWriterHelper(m_out);
895 1584 : m_bDocStarted = sal_False;
896 1584 : m_nLevel = 0;
897 1584 : m_bIsCDATA = sal_False;
898 :
899 : }
900 1584 : }
901 0 : virtual Reference< XOutputStream > SAL_CALL getOutputStream(void)
902 : throw(RuntimeException)
903 0 : { return m_out; }
904 :
905 : public: // XDocumentHandler
906 : virtual void SAL_CALL startDocument(void)
907 : throw(SAXException, RuntimeException);
908 :
909 : virtual void SAL_CALL endDocument(void)
910 : throw(SAXException, RuntimeException);
911 :
912 : virtual void SAL_CALL startElement(const OUString& aName,
913 : const Reference< XAttributeList > & xAttribs)
914 : throw (SAXException, RuntimeException);
915 :
916 : virtual void SAL_CALL endElement(const OUString& aName)
917 : throw(SAXException, RuntimeException);
918 :
919 : virtual void SAL_CALL characters(const OUString& aChars)
920 : throw(SAXException, RuntimeException);
921 :
922 : virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces)
923 : throw(SAXException, RuntimeException);
924 : virtual void SAL_CALL processingInstruction(const OUString& aTarget,
925 : const OUString& aData)
926 : throw(SAXException, RuntimeException);
927 : virtual void SAL_CALL setDocumentLocator(const Reference< XLocator > & xLocator)
928 : throw(SAXException, RuntimeException);
929 :
930 : public: // XExtendedDocumentHandler
931 : virtual void SAL_CALL startCDATA(void) throw(SAXException, RuntimeException);
932 : virtual void SAL_CALL endCDATA(void) throw(RuntimeException);
933 : virtual void SAL_CALL comment(const OUString& sComment)
934 : throw(SAXException, RuntimeException);
935 : virtual void SAL_CALL unknown(const OUString& sString)
936 : throw(SAXException, RuntimeException);
937 : virtual void SAL_CALL allowLineBreak(void)
938 : throw(SAXException,RuntimeException);
939 :
940 : public: // XServiceInfo
941 : OUString SAL_CALL getImplementationName() throw();
942 : Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw();
943 : sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw();
944 :
945 : private:
946 :
947 : void writeSequence( const Sequence<sal_Int8> & seq );
948 : sal_Int32 getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurrence ) throw();
949 :
950 : Reference< XOutputStream > m_out;
951 : Sequence < sal_Int8 > m_seqStartElement;
952 : SaxWriterHelper* mp_SaxWriterHelper;
953 :
954 : // Status information
955 : sal_Bool m_bDocStarted : 1;
956 : sal_Bool m_bIsCDATA : 1;
957 : sal_Bool m_bForceLineBreak : 1;
958 : sal_Bool m_bAllowLineBreak : 1;
959 : sal_Int32 m_nLevel;
960 : };
961 :
962 :
963 : //--------------------------------------
964 : // the extern interface
965 : //---------------------------------------
966 1408 : Reference < XInterface > SAL_CALL SaxWriter_CreateInstance(
967 : SAL_UNUSED_PARAMETER const Reference < XMultiServiceFactory > & )
968 : throw (Exception)
969 : {
970 1408 : SAXWriter *p = new SAXWriter;
971 1408 : return Reference< XInterface > ( (static_cast< OWeakObject * >(p)) );
972 : }
973 :
974 14 : OUString SaxWriter_getServiceName() throw()
975 : {
976 14 : return OUString("com.sun.star.xml.sax.Writer");
977 : }
978 :
979 14 : OUString SaxWriter_getImplementationName() throw()
980 : {
981 14 : return OUString("com.sun.star.extensions.xml.sax.Writer");
982 : }
983 :
984 14 : Sequence< OUString > SaxWriter_getSupportedServiceNames(void) throw()
985 : {
986 14 : Sequence<OUString> aRet(1);
987 14 : aRet.getArray()[0] = SaxWriter_getServiceName();
988 14 : return aRet;
989 : }
990 :
991 :
992 142580 : sal_Int32 SAXWriter::getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurrence ) throw()
993 : {
994 142580 : sal_Int32 nLength =-1;
995 142580 : if (mp_SaxWriterHelper)
996 : {
997 142580 : if ( m_bForceLineBreak ||
998 : (m_bAllowLineBreak &&
999 0 : ((nFirstLineBreakOccurrence + mp_SaxWriterHelper->GetLastColumnCount()) > MAXCOLUMNCOUNT)) )
1000 314 : nLength = m_nLevel;
1001 : }
1002 142580 : m_bForceLineBreak = sal_False;
1003 142580 : m_bAllowLineBreak = sal_False;
1004 142580 : return nLength;
1005 : }
1006 :
1007 0 : static inline sal_Bool isFirstCharWhitespace( const sal_Unicode *p ) throw()
1008 : {
1009 0 : return *p == ' ';
1010 : }
1011 :
1012 :
1013 : // XServiceInfo
1014 0 : OUString SAXWriter::getImplementationName() throw()
1015 : {
1016 0 : return SaxWriter_getImplementationName();
1017 : }
1018 :
1019 : // XServiceInfo
1020 0 : sal_Bool SAXWriter::supportsService(const OUString& ServiceName) throw()
1021 : {
1022 0 : Sequence< OUString > aSNL = getSupportedServiceNames();
1023 0 : const OUString * pArray = aSNL.getConstArray();
1024 :
1025 0 : for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
1026 0 : if( pArray[i] == ServiceName )
1027 0 : return sal_True;
1028 :
1029 0 : return sal_False;
1030 : }
1031 :
1032 : // XServiceInfo
1033 0 : Sequence< OUString > SAXWriter::getSupportedServiceNames(void) throw ()
1034 : {
1035 0 : Sequence<OUString> seq(1);
1036 0 : seq.getArray()[0] = SaxWriter_getServiceName();
1037 0 : return seq;
1038 : }
1039 :
1040 :
1041 :
1042 1338 : void SAXWriter::startDocument() throw(SAXException, RuntimeException )
1043 : {
1044 1338 : if( m_bDocStarted || ! m_out.is() || !mp_SaxWriterHelper ) {
1045 0 : throw SAXException();
1046 : }
1047 1338 : m_bDocStarted = sal_True;
1048 1338 : mp_SaxWriterHelper->startDocument();
1049 1338 : }
1050 :
1051 :
1052 1338 : void SAXWriter::endDocument(void) throw(SAXException, RuntimeException)
1053 : {
1054 1338 : if( ! m_bDocStarted )
1055 : {
1056 : throw SAXException(
1057 : OUString("endDocument called before startDocument"),
1058 0 : Reference< XInterface >() , Any() );
1059 : }
1060 1338 : if( m_nLevel ) {
1061 : throw SAXException(
1062 : OUString("unexpected end of document"),
1063 0 : Reference< XInterface >() , Any() );
1064 : }
1065 1338 : mp_SaxWriterHelper->endDocument();
1066 : try
1067 : {
1068 1338 : m_out->closeOutput();
1069 : }
1070 0 : catch (const IOException & e)
1071 : {
1072 0 : Any a;
1073 0 : a <<= e;
1074 : throw SAXException(
1075 : OUString("IO exception during closing the IO Stream"),
1076 : Reference< XInterface > (),
1077 0 : a );
1078 : }
1079 1338 : }
1080 :
1081 :
1082 52086 : void SAXWriter::startElement(const OUString& aName, const Reference< XAttributeList >& xAttribs)
1083 : throw(SAXException, RuntimeException)
1084 : {
1085 52086 : if( ! m_bDocStarted )
1086 : {
1087 0 : SAXException except;
1088 0 : except.Message = OUString( "startElement called before startDocument" );
1089 0 : throw except;
1090 : }
1091 52086 : if( m_bIsCDATA )
1092 : {
1093 0 : SAXException except;
1094 0 : except.Message = OUString( "startElement call not allowed with CDATA sections" );
1095 0 : throw except;
1096 : }
1097 :
1098 52086 : sal_Int32 nLength(0);
1099 52086 : if (m_bAllowLineBreak)
1100 : {
1101 0 : sal_Int32 nAttribCount = xAttribs.is() ? xAttribs->getLength() : 0;
1102 :
1103 0 : nLength ++; // "<"
1104 : nLength += calcXMLByteLength( aName.getStr() , aName.getLength(),
1105 0 : sal_False, sal_False ); // the tag name
1106 :
1107 : sal_Int16 n;
1108 0 : for( n = 0 ; n < static_cast<sal_Int16>(nAttribCount) ; n ++ ) {
1109 0 : nLength ++; // " "
1110 0 : OUString tmp = xAttribs->getNameByIndex( n );
1111 :
1112 0 : nLength += calcXMLByteLength( tmp.getStr() , tmp.getLength() , sal_False, sal_False );
1113 :
1114 0 : nLength += 2; // ="
1115 :
1116 0 : tmp = xAttribs->getValueByIndex( n );
1117 :
1118 0 : nLength += calcXMLByteLength( tmp.getStr(), tmp.getLength(), sal_True, sal_True );
1119 :
1120 0 : nLength += 1; // "
1121 0 : }
1122 :
1123 0 : nLength ++; // '>'
1124 : }
1125 :
1126 : // Is there a new indentation necesarry ?
1127 52086 : sal_Int32 nPrefix(getIndentPrefixLength( nLength ));
1128 :
1129 : // write into sequence
1130 52086 : if( nPrefix >= 0 )
1131 128 : mp_SaxWriterHelper->insertIndentation( nPrefix );
1132 :
1133 52086 : SaxInvalidCharacterError eRet(mp_SaxWriterHelper->startElement(aName, xAttribs));
1134 :
1135 52086 : m_nLevel++;
1136 :
1137 52086 : if (eRet == SAX_WARNING)
1138 : {
1139 0 : SAXInvalidCharacterException except;
1140 0 : except.Message = OUString( "Invalid charcter during XML-Export in a attribute value" );
1141 0 : throw except;
1142 : }
1143 52086 : else if (eRet == SAX_ERROR)
1144 : {
1145 0 : SAXException except;
1146 0 : except.Message = OUString( "Invalid charcter during XML-Export" );
1147 0 : throw except;
1148 : }
1149 52086 : }
1150 :
1151 52086 : void SAXWriter::endElement(const OUString& aName) throw (SAXException, RuntimeException)
1152 : {
1153 52086 : if( ! m_bDocStarted ) {
1154 0 : throw SAXException ();
1155 : }
1156 52086 : m_nLevel --;
1157 :
1158 52086 : if( m_nLevel < 0 ) {
1159 0 : throw SAXException();
1160 : }
1161 52086 : sal_Bool bRet(sal_True);
1162 :
1163 52086 : if( mp_SaxWriterHelper->FinishEmptyElement() )
1164 1902 : m_bForceLineBreak = sal_False;
1165 : else
1166 : {
1167 : // only ascii chars allowed
1168 50184 : sal_Int32 nLength(0);
1169 50184 : if (m_bAllowLineBreak)
1170 0 : nLength = 3 + calcXMLByteLength( aName.getStr(), aName.getLength(), sal_False, sal_False );
1171 50184 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1172 :
1173 50184 : if( nPrefix >= 0 )
1174 186 : mp_SaxWriterHelper->insertIndentation( nPrefix );
1175 :
1176 50184 : bRet = mp_SaxWriterHelper->endElement(aName);
1177 : }
1178 :
1179 52086 : if (!bRet)
1180 : {
1181 0 : SAXException except;
1182 0 : except.Message = OUString( "Invalid charcter during XML-Export" );
1183 0 : throw except;
1184 : }
1185 52086 : }
1186 :
1187 40302 : void SAXWriter::characters(const OUString& aChars) throw(SAXException, RuntimeException)
1188 : {
1189 40302 : if( ! m_bDocStarted )
1190 : {
1191 0 : SAXException except;
1192 0 : except.Message = OUString( "characters method called before startDocument" );
1193 0 : throw except;
1194 : }
1195 :
1196 40302 : sal_Bool bThrowException(sal_False);
1197 40302 : if( !aChars.isEmpty() )
1198 : {
1199 40302 : if( m_bIsCDATA )
1200 0 : bThrowException = !mp_SaxWriterHelper->writeString( aChars, sal_False, sal_False );
1201 : else
1202 : {
1203 : // Note : nFirstLineBreakOccurrence is not exact, because we don't know, how
1204 : // many 2 and 3 byte chars are inbetween. However this whole stuff
1205 : // is eitherway for pretty printing only, so it does not need to be exact.
1206 40302 : sal_Int32 nLength(0);
1207 40302 : sal_Int32 nIndentPrefix(-1);
1208 40302 : if (m_bAllowLineBreak)
1209 : {
1210 0 : sal_Int32 nFirstLineBreakOccurrence = getFirstLineBreak( aChars );
1211 :
1212 : nLength = calcXMLByteLength( aChars.getStr(), aChars.getLength(),
1213 0 : ! m_bIsCDATA , sal_False );
1214 : nIndentPrefix = getIndentPrefixLength(
1215 0 : nFirstLineBreakOccurrence >= 0 ? nFirstLineBreakOccurrence : nLength );
1216 : }
1217 : else
1218 40302 : nIndentPrefix = getIndentPrefixLength(nLength);
1219 :
1220 : // insert indentation
1221 40302 : if( nIndentPrefix >= 0 )
1222 : {
1223 0 : if( isFirstCharWhitespace( aChars.getStr() ) )
1224 0 : mp_SaxWriterHelper->insertIndentation( nIndentPrefix - 1 );
1225 : else
1226 0 : mp_SaxWriterHelper->insertIndentation( nIndentPrefix );
1227 : }
1228 40302 : bThrowException = !mp_SaxWriterHelper->writeString(aChars, sal_True , sal_False);
1229 : }
1230 : }
1231 40302 : if (bThrowException)
1232 : {
1233 0 : SAXInvalidCharacterException except;
1234 0 : except.Message = OUString( "Invalid charcter during XML-Export" );
1235 0 : throw except;
1236 : }
1237 40302 : }
1238 :
1239 :
1240 1136 : void SAXWriter::ignorableWhitespace(const OUString&) throw(SAXException, RuntimeException)
1241 : {
1242 1136 : if( ! m_bDocStarted )
1243 : {
1244 0 : throw SAXException ();
1245 : }
1246 :
1247 1136 : m_bForceLineBreak = sal_True;
1248 1136 : }
1249 :
1250 0 : void SAXWriter::processingInstruction(const OUString& aTarget, const OUString& aData)
1251 : throw (SAXException, RuntimeException)
1252 : {
1253 0 : if( ! m_bDocStarted || m_bIsCDATA )
1254 : {
1255 0 : throw SAXException();
1256 : }
1257 :
1258 0 : sal_Int32 nLength(0);
1259 0 : if (m_bAllowLineBreak)
1260 : {
1261 0 : nLength = 2; // "<?"
1262 0 : nLength += calcXMLByteLength( aTarget.getStr(), aTarget.getLength(), sal_False, sal_False );
1263 :
1264 0 : nLength += 1; // " "
1265 :
1266 0 : nLength += calcXMLByteLength( aData.getStr(), aData.getLength(), sal_False, sal_False );
1267 :
1268 0 : nLength += 2; // "?>"
1269 : }
1270 :
1271 0 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1272 :
1273 0 : if( nPrefix >= 0 )
1274 0 : mp_SaxWriterHelper->insertIndentation( nPrefix );
1275 :
1276 0 : if (!mp_SaxWriterHelper->processingInstruction(aTarget, aData))
1277 : {
1278 0 : SAXException except;
1279 0 : except.Message = OUString( "Invalid charcter during XML-Export" );
1280 0 : throw except;
1281 : }
1282 0 : }
1283 :
1284 :
1285 0 : void SAXWriter::setDocumentLocator(const Reference< XLocator >&)
1286 : throw (SAXException, RuntimeException)
1287 : {
1288 :
1289 0 : }
1290 :
1291 0 : void SAXWriter::startCDATA(void) throw(SAXException, RuntimeException)
1292 : {
1293 0 : if( ! m_bDocStarted || m_bIsCDATA)
1294 : {
1295 0 : throw SAXException ();
1296 : }
1297 :
1298 0 : sal_Int32 nLength = 9;
1299 0 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1300 0 : if( nPrefix >= 0 )
1301 0 : mp_SaxWriterHelper->insertIndentation( nPrefix );
1302 :
1303 0 : mp_SaxWriterHelper->startCDATA();
1304 :
1305 0 : m_bIsCDATA = sal_True;
1306 0 : }
1307 :
1308 0 : void SAXWriter::endCDATA(void) throw (RuntimeException)
1309 : {
1310 0 : if( ! m_bDocStarted || ! m_bIsCDATA)
1311 : {
1312 0 : SAXException except;
1313 0 : except.Message = OUString( "endCDATA was called without startCDATA" );
1314 0 : throw except;
1315 : }
1316 :
1317 0 : sal_Int32 nLength = 3;
1318 0 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1319 0 : if( nPrefix >= 0 )
1320 0 : mp_SaxWriterHelper->insertIndentation( nPrefix );
1321 :
1322 0 : mp_SaxWriterHelper->endCDATA();
1323 :
1324 0 : m_bIsCDATA = sal_False;
1325 0 : }
1326 :
1327 :
1328 8 : void SAXWriter::comment(const OUString& sComment) throw(SAXException, RuntimeException)
1329 : {
1330 8 : if( ! m_bDocStarted || m_bIsCDATA )
1331 : {
1332 0 : throw SAXException();
1333 : }
1334 :
1335 8 : sal_Int32 nLength(0);
1336 8 : if (m_bAllowLineBreak)
1337 : {
1338 0 : nLength = 4; // "<!--"
1339 0 : nLength += calcXMLByteLength( sComment.getStr(), sComment.getLength(), sal_False, sal_False);
1340 :
1341 0 : nLength += 3;
1342 : }
1343 :
1344 8 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1345 8 : if( nPrefix >= 0 )
1346 0 : mp_SaxWriterHelper->insertIndentation( nPrefix );
1347 :
1348 8 : if (!mp_SaxWriterHelper->comment(sComment))
1349 : {
1350 0 : SAXException except;
1351 0 : except.Message = OUString( "Invalid charcter during XML-Export" );
1352 0 : throw except;
1353 : }
1354 8 : }
1355 :
1356 :
1357 0 : void SAXWriter::allowLineBreak( ) throw ( SAXException , RuntimeException)
1358 : {
1359 0 : if( ! m_bDocStarted || m_bAllowLineBreak ) {
1360 0 : throw SAXException();
1361 : }
1362 :
1363 0 : m_bAllowLineBreak = sal_True;
1364 0 : }
1365 :
1366 0 : void SAXWriter::unknown(const OUString& sString) throw (SAXException, RuntimeException)
1367 : {
1368 :
1369 0 : if( ! m_bDocStarted )
1370 : {
1371 0 : throw SAXException ();
1372 : }
1373 0 : if( m_bIsCDATA )
1374 : {
1375 0 : throw SAXException();
1376 : }
1377 :
1378 0 : if( sString.matchAsciiL( "<?xml", 5 ) )
1379 0 : return;
1380 :
1381 0 : sal_Int32 nLength(0);
1382 0 : if (m_bAllowLineBreak)
1383 0 : nLength = calcXMLByteLength( sString.getStr(), sString.getLength(), sal_False, sal_False );
1384 :
1385 0 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1386 0 : if( nPrefix >= 0 )
1387 0 : mp_SaxWriterHelper->insertIndentation( nPrefix );
1388 :
1389 0 : if (!mp_SaxWriterHelper->writeString( sString, sal_False, sal_False))
1390 : {
1391 0 : SAXException except;
1392 0 : except.Message = OUString( "Invalid charcter during XML-Export" );
1393 0 : throw except;
1394 : }
1395 : }
1396 :
1397 : }
1398 :
1399 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|