Update ooo320-m1
[ooovba.git] / sax / source / tools / fastserializer.cxx
blob1782e7902c331304995511884c39f3d68938648f
1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: contexthandler2.cxx,v $
7 * $Revision: 1.1.2.2 $
9 * last change: $Author: dr $ $Date: 2008/02/11 10:43:07 $
11 * The Contents of this file are made available subject to
12 * the terms of GNU Lesser General Public License Version 2.1.
15 * GNU Lesser General Public License Version 2.1
16 * =============================================
17 * Copyright 2005 by Sun Microsystems, Inc.
18 * 901 San Antonio Road, Palo Alto, CA 94303, USA
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License version 2.1, as published by the Free Software Foundation.
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
32 * MA 02111-1307 USA
34 ************************************************************************/
36 #include "fastserializer.hxx"
37 #include <rtl/ustrbuf.hxx>
39 #include <com/sun/star/xml/Attribute.hpp>
40 #include <com/sun/star/xml/FastAttribute.hpp>
41 #include <com/sun/star/xml/sax/XFastAttributeList.hpp>
43 #include <string.h>
45 using ::rtl::OString;
46 using ::rtl::OUString;
47 using ::rtl::OUStringBuffer;
48 using ::rtl::OUStringToOString;
49 using ::com::sun::star::uno::Reference;
50 using ::com::sun::star::uno::RuntimeException;
51 using ::com::sun::star::uno::Sequence;
52 using ::com::sun::star::xml::FastAttribute;
53 using ::com::sun::star::xml::Attribute;
54 using ::com::sun::star::xml::sax::SAXException;
55 using ::com::sun::star::xml::sax::XFastAttributeList;
56 using ::com::sun::star::xml::sax::XFastTokenHandler;
57 using ::com::sun::star::xml::sax::XFastSerializer;
58 using ::com::sun::star::io::XOutputStream;
59 using ::com::sun::star::io::NotConnectedException;
60 using ::com::sun::star::io::IOException;
61 using ::com::sun::star::io::BufferSizeExceededException;
63 static Sequence< sal_Int8 > aClosingBracket((sal_Int8 *)">", 1);
64 static Sequence< sal_Int8 > aSlashAndClosingBracket((sal_Int8 *)"/>", 2);
65 static Sequence< sal_Int8 > aColon((sal_Int8 *)":", 1);
66 static Sequence< sal_Int8 > aOpeningBracket((sal_Int8 *)"<", 1);
67 static Sequence< sal_Int8 > aOpeningBracketAndSlash((sal_Int8 *)"</", 2);
68 static Sequence< sal_Int8 > aQuote((sal_Int8 *)"\"", 1);
69 static Sequence< sal_Int8 > aEqualSignAndQuote((sal_Int8 *)"=\"", 2);
70 static Sequence< sal_Int8 > aSpace((sal_Int8 *)" ", 1);
71 static Sequence< sal_Int8 > aXmlHeader((sal_Int8*) "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n", 56);
73 #define HAS_NAMESPACE(x) ((x & 0xffff0000) != 0)
74 #define NAMESPACE(x) (x >> 16)
75 #define TOKEN(x) (x & 0xffff)
77 namespace sax_fastparser {
78 FastSaxSerializer::FastSaxSerializer( ) : mxOutputStream(), mxFastTokenHandler(), maMarkStack() {}
79 FastSaxSerializer::~FastSaxSerializer() {}
81 void SAL_CALL FastSaxSerializer::startDocument( ) throw (SAXException, RuntimeException)
83 if (!mxOutputStream.is())
84 return;
85 writeBytes(aXmlHeader);
88 OUString FastSaxSerializer::escapeXml( const OUString& s )
90 ::rtl::OUStringBuffer sBuf( s.getLength() );
91 const sal_Unicode* pStr = s;
92 sal_Int32 nLen = s.getLength();
93 for( sal_Int32 i = 0; i < nLen; ++i)
95 sal_Unicode c = pStr[ i ];
96 switch( c )
98 case '<': sBuf.appendAscii( "&lt;" ); break;
99 case '>': sBuf.appendAscii( "&gt;" ); break;
100 case '&': sBuf.appendAscii( "&amp;" ); break;
101 case '\'': sBuf.appendAscii( "&apos;" ); break;
102 case '"': sBuf.appendAscii( "&quot;" ); break;
103 default: sBuf.append( c ); break;
106 return sBuf.makeStringAndClear();
109 void FastSaxSerializer::write( const OUString& s )
111 OString sOutput( OUStringToOString( s, RTL_TEXTENCODING_UTF8 ) );
112 writeBytes( Sequence< sal_Int8 >(
113 reinterpret_cast< const sal_Int8*>( sOutput.getStr() ),
114 sOutput.getLength() ) );
117 void SAL_CALL FastSaxSerializer::endDocument( ) throw (SAXException, RuntimeException)
119 if (!mxOutputStream.is())
120 return;
123 void SAL_CALL FastSaxSerializer::writeId( ::sal_Int32 nElement )
125 if( HAS_NAMESPACE( nElement ) ) {
126 writeBytes(mxFastTokenHandler->getUTF8Identifier(NAMESPACE(nElement)));
127 writeBytes(aColon);
128 writeBytes(mxFastTokenHandler->getUTF8Identifier(TOKEN(nElement)));
129 } else
130 writeBytes(mxFastTokenHandler->getUTF8Identifier(nElement));
133 void SAL_CALL FastSaxSerializer::startFastElement( ::sal_Int32 Element, const Reference< XFastAttributeList >& Attribs )
134 throw (SAXException, RuntimeException)
136 if (!mxOutputStream.is())
137 return;
139 writeBytes(aOpeningBracket);
141 writeId(Element);
142 writeFastAttributeList(Attribs);
144 writeBytes(aClosingBracket);
147 void SAL_CALL FastSaxSerializer::startUnknownElement( const OUString& Namespace, const OUString& Name, const Reference< XFastAttributeList >& Attribs )
148 throw (SAXException, RuntimeException)
150 if (!mxOutputStream.is())
151 return;
153 writeBytes(aOpeningBracket);
155 if (Namespace.getLength())
157 write(Namespace);
158 writeBytes(aColon);
161 write(Name);
163 writeFastAttributeList(Attribs);
165 writeBytes(aClosingBracket);
168 void SAL_CALL FastSaxSerializer::endFastElement( ::sal_Int32 Element )
169 throw (SAXException, RuntimeException)
171 if (!mxOutputStream.is())
172 return;
174 writeBytes(aOpeningBracketAndSlash);
176 writeId(Element);
178 writeBytes(aClosingBracket);
181 void SAL_CALL FastSaxSerializer::endUnknownElement( const OUString& Namespace, const OUString& Name )
182 throw (SAXException, RuntimeException)
184 if (!mxOutputStream.is())
185 return;
187 writeBytes(aOpeningBracketAndSlash);
189 if (Namespace.getLength())
191 write(Namespace);
192 writeBytes(aColon);
195 write(Name);
197 writeBytes(aClosingBracket);
200 void SAL_CALL FastSaxSerializer::singleFastElement( ::sal_Int32 Element, const Reference< XFastAttributeList >& Attribs )
201 throw (SAXException, RuntimeException)
203 if (!mxOutputStream.is())
204 return;
206 writeBytes(aOpeningBracket);
208 writeId(Element);
209 writeFastAttributeList(Attribs);
211 writeBytes(aSlashAndClosingBracket);
214 void SAL_CALL FastSaxSerializer::singleUnknownElement( const OUString& Namespace, const OUString& Name, const Reference< XFastAttributeList >& Attribs )
215 throw (SAXException, RuntimeException)
217 if (!mxOutputStream.is())
218 return;
220 writeBytes(aOpeningBracket);
222 if (Namespace.getLength())
224 write(Namespace);
225 writeBytes(aColon);
228 write(Name);
230 writeFastAttributeList(Attribs);
232 writeBytes(aSlashAndClosingBracket);
235 void SAL_CALL FastSaxSerializer::characters( const OUString& aChars )
236 throw (SAXException, RuntimeException)
238 if (!mxOutputStream.is())
239 return;
241 write( aChars );
244 void SAL_CALL FastSaxSerializer::setOutputStream( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >& xOutputStream )
245 throw (::com::sun::star::uno::RuntimeException)
247 mxOutputStream = xOutputStream;
250 void SAL_CALL FastSaxSerializer::setFastTokenHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >& xFastTokenHandler )
251 throw (::com::sun::star::uno::RuntimeException)
253 mxFastTokenHandler = xFastTokenHandler;
255 void FastSaxSerializer::writeFastAttributeList( const Reference< XFastAttributeList >& Attribs )
257 Sequence< Attribute > aAttrSeq = Attribs->getUnknownAttributes();
258 const Attribute *pAttr = aAttrSeq.getConstArray();
259 sal_Int32 nAttrLength = aAttrSeq.getLength();
260 for (sal_Int32 i = 0; i < nAttrLength; i++)
262 writeBytes(aSpace);
264 write(pAttr[i].Name);
265 writeBytes(aEqualSignAndQuote);
266 write(escapeXml(pAttr[i].Value));
267 writeBytes(aQuote);
270 Sequence< FastAttribute > aFastAttrSeq = Attribs->getFastAttributes();
271 const FastAttribute *pFastAttr = aFastAttrSeq.getConstArray();
272 sal_Int32 nFastAttrLength = aFastAttrSeq.getLength();
273 for (sal_Int32 j = 0; j < nFastAttrLength; j++)
275 writeBytes(aSpace);
277 sal_Int32 nToken = pFastAttr[j].Token;
278 writeId(nToken);
280 writeBytes(aEqualSignAndQuote);
282 write(escapeXml(Attribs->getValue(pFastAttr[j].Token)));
284 writeBytes(aQuote);
288 // XServiceInfo
289 OUString FastSaxSerializer::getImplementationName() throw (RuntimeException)
291 return OUString::createFromAscii( SERIALIZER_IMPLEMENTATION_NAME );
294 // XServiceInfo
295 sal_Bool FastSaxSerializer::supportsService(const OUString& ServiceName) throw (RuntimeException)
297 Sequence< OUString > aSNL = getSupportedServiceNames();
298 const OUString * pArray = aSNL.getConstArray();
300 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
301 if( pArray[i] == ServiceName )
302 return sal_True;
304 return sal_False;
307 // XServiceInfo
308 Sequence< OUString > FastSaxSerializer::getSupportedServiceNames(void) throw (RuntimeException)
310 Sequence<OUString> seq(1);
311 seq.getArray()[0] = OUString::createFromAscii( SERIALIZER_SERVICE_NAME );
312 return seq;
315 OUString FastSaxSerializer::getImplementationName_Static()
317 return OUString::createFromAscii( SERIALIZER_IMPLEMENTATION_NAME );
320 Sequence< OUString > FastSaxSerializer::getSupportedServiceNames_Static(void)
322 Sequence<OUString> aRet(1);
323 aRet.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(SERIALIZER_SERVICE_NAME) );
324 return aRet;
327 void FastSaxSerializer::mark()
329 maMarkStack.push( ForMerge() );
332 void FastSaxSerializer::mergeTopMarks( sax_fastparser::MergeMarksEnum eMergeType )
334 if ( maMarkStack.empty() )
335 return;
337 if ( maMarkStack.size() == 1 )
339 mxOutputStream->writeBytes( maMarkStack.top().getData() );
340 maMarkStack.pop();
341 return;
344 const Int8Sequence aMerge( maMarkStack.top().getData() );
345 maMarkStack.pop();
347 switch ( eMergeType )
349 case MERGE_MARKS_APPEND: maMarkStack.top().append( aMerge ); break;
350 case MERGE_MARKS_PREPEND: maMarkStack.top().prepend( aMerge ); break;
351 case MERGE_MARKS_POSTPONE: maMarkStack.top().postpone( aMerge ); break;
355 void FastSaxSerializer::writeBytes( const Sequence< ::sal_Int8 >& aData ) throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
357 if ( maMarkStack.empty() )
358 mxOutputStream->writeBytes( aData );
359 else
360 maMarkStack.top().append( aData );
363 FastSaxSerializer::Int8Sequence& FastSaxSerializer::ForMerge::getData()
365 merge( maData, maPostponed, true );
366 maPostponed.realloc( 0 );
368 return maData;
371 void FastSaxSerializer::ForMerge::prepend( const Int8Sequence &rWhat )
373 merge( maData, rWhat, false );
376 void FastSaxSerializer::ForMerge::append( const Int8Sequence &rWhat )
378 merge( maData, rWhat, true );
381 void FastSaxSerializer::ForMerge::postpone( const Int8Sequence &rWhat )
383 merge( maPostponed, rWhat, true );
386 void FastSaxSerializer::ForMerge::merge( Int8Sequence &rTop, const Int8Sequence &rMerge, bool bAppend )
388 sal_Int32 nMergeLen = rMerge.getLength();
389 if ( nMergeLen > 0 )
391 sal_Int32 nTopLen = rTop.getLength();
393 rTop.realloc( nTopLen + nMergeLen );
394 if ( bAppend )
396 // append the rMerge to the rTop
397 memcpy( rTop.getArray() + nTopLen, rMerge.getConstArray(), nMergeLen );
399 else
401 // prepend the rMerge to the rTop
402 memmove( rTop.getArray() + nMergeLen, rTop.getConstArray(), nTopLen );
403 memcpy( rTop.getArray(), rMerge.getConstArray(), nMergeLen );
408 } // namespace sax_fastparser