merged tag ooo/OOO330_m14
[LibreOffice.git] / sax / source / tools / fastserializer.cxx
blobb0318516b72c39e5538828fb7235bfe449003a4d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 #include "fastserializer.hxx"
29 #include <rtl/ustrbuf.hxx>
31 #include <com/sun/star/xml/Attribute.hpp>
32 #include <com/sun/star/xml/FastAttribute.hpp>
33 #include <com/sun/star/xml/sax/XFastAttributeList.hpp>
35 #include <string.h>
37 using ::rtl::OString;
38 using ::rtl::OUString;
39 using ::rtl::OUStringBuffer;
40 using ::rtl::OUStringToOString;
41 using ::com::sun::star::uno::Reference;
42 using ::com::sun::star::uno::RuntimeException;
43 using ::com::sun::star::uno::Sequence;
44 using ::com::sun::star::xml::FastAttribute;
45 using ::com::sun::star::xml::Attribute;
46 using ::com::sun::star::xml::sax::SAXException;
47 using ::com::sun::star::xml::sax::XFastAttributeList;
48 using ::com::sun::star::xml::sax::XFastTokenHandler;
49 using ::com::sun::star::xml::sax::XFastSerializer;
50 using ::com::sun::star::io::XOutputStream;
51 using ::com::sun::star::io::NotConnectedException;
52 using ::com::sun::star::io::IOException;
53 using ::com::sun::star::io::BufferSizeExceededException;
55 static Sequence< sal_Int8 > aClosingBracket((sal_Int8 *)">", 1);
56 static Sequence< sal_Int8 > aSlashAndClosingBracket((sal_Int8 *)"/>", 2);
57 static Sequence< sal_Int8 > aColon((sal_Int8 *)":", 1);
58 static Sequence< sal_Int8 > aOpeningBracket((sal_Int8 *)"<", 1);
59 static Sequence< sal_Int8 > aOpeningBracketAndSlash((sal_Int8 *)"</", 2);
60 static Sequence< sal_Int8 > aQuote((sal_Int8 *)"\"", 1);
61 static Sequence< sal_Int8 > aEqualSignAndQuote((sal_Int8 *)"=\"", 2);
62 static Sequence< sal_Int8 > aSpace((sal_Int8 *)" ", 1);
63 static Sequence< sal_Int8 > aXmlHeader((sal_Int8*) "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n", 56);
65 #define HAS_NAMESPACE(x) ((x & 0xffff0000) != 0)
66 #define NAMESPACE(x) (x >> 16)
67 #define TOKEN(x) (x & 0xffff)
69 namespace sax_fastparser {
70 FastSaxSerializer::FastSaxSerializer( ) : mxOutputStream(), mxFastTokenHandler(), maMarkStack() {}
71 FastSaxSerializer::~FastSaxSerializer() {}
73 void SAL_CALL FastSaxSerializer::startDocument( ) throw (SAXException, RuntimeException)
75 if (!mxOutputStream.is())
76 return;
77 writeBytes(aXmlHeader);
80 OUString FastSaxSerializer::escapeXml( const OUString& s )
82 ::rtl::OUStringBuffer sBuf( s.getLength() );
83 const sal_Unicode* pStr = s;
84 sal_Int32 nLen = s.getLength();
85 for( sal_Int32 i = 0; i < nLen; ++i)
87 sal_Unicode c = pStr[ i ];
88 switch( c )
90 case '<': sBuf.appendAscii( "&lt;" ); break;
91 case '>': sBuf.appendAscii( "&gt;" ); break;
92 case '&': sBuf.appendAscii( "&amp;" ); break;
93 case '\'': sBuf.appendAscii( "&apos;" ); break;
94 case '"': sBuf.appendAscii( "&quot;" ); break;
95 default: sBuf.append( c ); break;
98 return sBuf.makeStringAndClear();
101 void FastSaxSerializer::write( const OUString& s )
103 OString sOutput( OUStringToOString( s, RTL_TEXTENCODING_UTF8 ) );
104 writeBytes( Sequence< sal_Int8 >(
105 reinterpret_cast< const sal_Int8*>( sOutput.getStr() ),
106 sOutput.getLength() ) );
109 void SAL_CALL FastSaxSerializer::endDocument( ) throw (SAXException, RuntimeException)
111 if (!mxOutputStream.is())
112 return;
115 void SAL_CALL FastSaxSerializer::writeId( ::sal_Int32 nElement )
117 if( HAS_NAMESPACE( nElement ) ) {
118 writeBytes(mxFastTokenHandler->getUTF8Identifier(NAMESPACE(nElement)));
119 writeBytes(aColon);
120 writeBytes(mxFastTokenHandler->getUTF8Identifier(TOKEN(nElement)));
121 } else
122 writeBytes(mxFastTokenHandler->getUTF8Identifier(nElement));
125 void SAL_CALL FastSaxSerializer::startFastElement( ::sal_Int32 Element, const Reference< XFastAttributeList >& Attribs )
126 throw (SAXException, RuntimeException)
128 if (!mxOutputStream.is())
129 return;
131 writeBytes(aOpeningBracket);
133 writeId(Element);
134 writeFastAttributeList(Attribs);
136 writeBytes(aClosingBracket);
139 void SAL_CALL FastSaxSerializer::startUnknownElement( const OUString& Namespace, const OUString& Name, const Reference< XFastAttributeList >& Attribs )
140 throw (SAXException, RuntimeException)
142 if (!mxOutputStream.is())
143 return;
145 writeBytes(aOpeningBracket);
147 if (Namespace.getLength())
149 write(Namespace);
150 writeBytes(aColon);
153 write(Name);
155 writeFastAttributeList(Attribs);
157 writeBytes(aClosingBracket);
160 void SAL_CALL FastSaxSerializer::endFastElement( ::sal_Int32 Element )
161 throw (SAXException, RuntimeException)
163 if (!mxOutputStream.is())
164 return;
166 writeBytes(aOpeningBracketAndSlash);
168 writeId(Element);
170 writeBytes(aClosingBracket);
173 void SAL_CALL FastSaxSerializer::endUnknownElement( const OUString& Namespace, const OUString& Name )
174 throw (SAXException, RuntimeException)
176 if (!mxOutputStream.is())
177 return;
179 writeBytes(aOpeningBracketAndSlash);
181 if (Namespace.getLength())
183 write(Namespace);
184 writeBytes(aColon);
187 write(Name);
189 writeBytes(aClosingBracket);
192 void SAL_CALL FastSaxSerializer::singleFastElement( ::sal_Int32 Element, const Reference< XFastAttributeList >& Attribs )
193 throw (SAXException, RuntimeException)
195 if (!mxOutputStream.is())
196 return;
198 writeBytes(aOpeningBracket);
200 writeId(Element);
201 writeFastAttributeList(Attribs);
203 writeBytes(aSlashAndClosingBracket);
206 void SAL_CALL FastSaxSerializer::singleUnknownElement( const OUString& Namespace, const OUString& Name, const Reference< XFastAttributeList >& Attribs )
207 throw (SAXException, RuntimeException)
209 if (!mxOutputStream.is())
210 return;
212 writeBytes(aOpeningBracket);
214 if (Namespace.getLength())
216 write(Namespace);
217 writeBytes(aColon);
220 write(Name);
222 writeFastAttributeList(Attribs);
224 writeBytes(aSlashAndClosingBracket);
227 void SAL_CALL FastSaxSerializer::characters( const OUString& aChars )
228 throw (SAXException, RuntimeException)
230 if (!mxOutputStream.is())
231 return;
233 write( aChars );
236 void SAL_CALL FastSaxSerializer::setOutputStream( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >& xOutputStream )
237 throw (::com::sun::star::uno::RuntimeException)
239 mxOutputStream = xOutputStream;
242 void SAL_CALL FastSaxSerializer::setFastTokenHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >& xFastTokenHandler )
243 throw (::com::sun::star::uno::RuntimeException)
245 mxFastTokenHandler = xFastTokenHandler;
247 void FastSaxSerializer::writeFastAttributeList( const Reference< XFastAttributeList >& Attribs )
249 Sequence< Attribute > aAttrSeq = Attribs->getUnknownAttributes();
250 const Attribute *pAttr = aAttrSeq.getConstArray();
251 sal_Int32 nAttrLength = aAttrSeq.getLength();
252 for (sal_Int32 i = 0; i < nAttrLength; i++)
254 writeBytes(aSpace);
256 write(pAttr[i].Name);
257 writeBytes(aEqualSignAndQuote);
258 write(escapeXml(pAttr[i].Value));
259 writeBytes(aQuote);
262 Sequence< FastAttribute > aFastAttrSeq = Attribs->getFastAttributes();
263 const FastAttribute *pFastAttr = aFastAttrSeq.getConstArray();
264 sal_Int32 nFastAttrLength = aFastAttrSeq.getLength();
265 for (sal_Int32 j = 0; j < nFastAttrLength; j++)
267 writeBytes(aSpace);
269 sal_Int32 nToken = pFastAttr[j].Token;
270 writeId(nToken);
272 writeBytes(aEqualSignAndQuote);
274 write(escapeXml(Attribs->getValue(pFastAttr[j].Token)));
276 writeBytes(aQuote);
280 // XServiceInfo
281 OUString FastSaxSerializer::getImplementationName() throw (RuntimeException)
283 return OUString::createFromAscii( SERIALIZER_IMPLEMENTATION_NAME );
286 // XServiceInfo
287 sal_Bool FastSaxSerializer::supportsService(const OUString& ServiceName) throw (RuntimeException)
289 Sequence< OUString > aSNL = getSupportedServiceNames();
290 const OUString * pArray = aSNL.getConstArray();
292 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
293 if( pArray[i] == ServiceName )
294 return sal_True;
296 return sal_False;
299 // XServiceInfo
300 Sequence< OUString > FastSaxSerializer::getSupportedServiceNames(void) throw (RuntimeException)
302 Sequence<OUString> seq(1);
303 seq.getArray()[0] = OUString::createFromAscii( SERIALIZER_SERVICE_NAME );
304 return seq;
307 OUString FastSaxSerializer::getImplementationName_Static()
309 return OUString::createFromAscii( SERIALIZER_IMPLEMENTATION_NAME );
312 Sequence< OUString > FastSaxSerializer::getSupportedServiceNames_Static(void)
314 Sequence<OUString> aRet(1);
315 aRet.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(SERIALIZER_SERVICE_NAME) );
316 return aRet;
319 void FastSaxSerializer::mark()
321 maMarkStack.push( ForMerge() );
324 void FastSaxSerializer::mergeTopMarks( sax_fastparser::MergeMarksEnum eMergeType )
326 if ( maMarkStack.empty() )
327 return;
329 if ( maMarkStack.size() == 1 )
331 mxOutputStream->writeBytes( maMarkStack.top().getData() );
332 maMarkStack.pop();
333 return;
336 const Int8Sequence aMerge( maMarkStack.top().getData() );
337 maMarkStack.pop();
339 switch ( eMergeType )
341 case MERGE_MARKS_APPEND: maMarkStack.top().append( aMerge ); break;
342 case MERGE_MARKS_PREPEND: maMarkStack.top().prepend( aMerge ); break;
343 case MERGE_MARKS_POSTPONE: maMarkStack.top().postpone( aMerge ); break;
347 void FastSaxSerializer::writeBytes( const Sequence< ::sal_Int8 >& aData ) throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
349 if ( maMarkStack.empty() )
350 mxOutputStream->writeBytes( aData );
351 else
352 maMarkStack.top().append( aData );
355 FastSaxSerializer::Int8Sequence& FastSaxSerializer::ForMerge::getData()
357 merge( maData, maPostponed, true );
358 maPostponed.realloc( 0 );
360 return maData;
363 void FastSaxSerializer::ForMerge::prepend( const Int8Sequence &rWhat )
365 merge( maData, rWhat, false );
368 void FastSaxSerializer::ForMerge::append( const Int8Sequence &rWhat )
370 merge( maData, rWhat, true );
373 void FastSaxSerializer::ForMerge::postpone( const Int8Sequence &rWhat )
375 merge( maPostponed, rWhat, true );
378 void FastSaxSerializer::ForMerge::merge( Int8Sequence &rTop, const Int8Sequence &rMerge, bool bAppend )
380 sal_Int32 nMergeLen = rMerge.getLength();
381 if ( nMergeLen > 0 )
383 sal_Int32 nTopLen = rTop.getLength();
385 rTop.realloc( nTopLen + nMergeLen );
386 if ( bAppend )
388 // append the rMerge to the rTop
389 memcpy( rTop.getArray() + nTopLen, rMerge.getConstArray(), nMergeLen );
391 else
393 // prepend the rMerge to the rTop
394 memmove( rTop.getArray() + nMergeLen, rTop.getConstArray(), nTopLen );
395 memcpy( rTop.getArray(), rMerge.getConstArray(), nMergeLen );
400 } // namespace sax_fastparser