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>
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())
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
];
90 case '<': sBuf
.appendAscii( "<" ); break;
91 case '>': sBuf
.appendAscii( ">" ); break;
92 case '&': sBuf
.appendAscii( "&" ); break;
93 case '\'': sBuf
.appendAscii( "'" ); break;
94 case '"': sBuf
.appendAscii( """ ); 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())
115 void SAL_CALL
FastSaxSerializer::writeId( ::sal_Int32 nElement
)
117 if( HAS_NAMESPACE( nElement
) ) {
118 writeBytes(mxFastTokenHandler
->getUTF8Identifier(NAMESPACE(nElement
)));
120 writeBytes(mxFastTokenHandler
->getUTF8Identifier(TOKEN(nElement
)));
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())
131 writeBytes(aOpeningBracket
);
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())
145 writeBytes(aOpeningBracket
);
147 if (Namespace
.getLength())
155 writeFastAttributeList(Attribs
);
157 writeBytes(aClosingBracket
);
160 void SAL_CALL
FastSaxSerializer::endFastElement( ::sal_Int32 Element
)
161 throw (SAXException
, RuntimeException
)
163 if (!mxOutputStream
.is())
166 writeBytes(aOpeningBracketAndSlash
);
170 writeBytes(aClosingBracket
);
173 void SAL_CALL
FastSaxSerializer::endUnknownElement( const OUString
& Namespace
, const OUString
& Name
)
174 throw (SAXException
, RuntimeException
)
176 if (!mxOutputStream
.is())
179 writeBytes(aOpeningBracketAndSlash
);
181 if (Namespace
.getLength())
189 writeBytes(aClosingBracket
);
192 void SAL_CALL
FastSaxSerializer::singleFastElement( ::sal_Int32 Element
, const Reference
< XFastAttributeList
>& Attribs
)
193 throw (SAXException
, RuntimeException
)
195 if (!mxOutputStream
.is())
198 writeBytes(aOpeningBracket
);
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())
212 writeBytes(aOpeningBracket
);
214 if (Namespace
.getLength())
222 writeFastAttributeList(Attribs
);
224 writeBytes(aSlashAndClosingBracket
);
227 void SAL_CALL
FastSaxSerializer::characters( const OUString
& aChars
)
228 throw (SAXException
, RuntimeException
)
230 if (!mxOutputStream
.is())
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
++)
256 write(pAttr
[i
].Name
);
257 writeBytes(aEqualSignAndQuote
);
258 write(escapeXml(pAttr
[i
].Value
));
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
++)
269 sal_Int32 nToken
= pFastAttr
[j
].Token
;
272 writeBytes(aEqualSignAndQuote
);
274 write(escapeXml(Attribs
->getValue(pFastAttr
[j
].Token
)));
281 OUString
FastSaxSerializer::getImplementationName() throw (RuntimeException
)
283 return OUString::createFromAscii( SERIALIZER_IMPLEMENTATION_NAME
);
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
)
300 Sequence
< OUString
> FastSaxSerializer::getSupportedServiceNames(void) throw (RuntimeException
)
302 Sequence
<OUString
> seq(1);
303 seq
.getArray()[0] = OUString::createFromAscii( SERIALIZER_SERVICE_NAME
);
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
) );
319 void FastSaxSerializer::mark()
321 maMarkStack
.push( ForMerge() );
324 void FastSaxSerializer::mergeTopMarks( sax_fastparser::MergeMarksEnum eMergeType
)
326 if ( maMarkStack
.empty() )
329 if ( maMarkStack
.size() == 1 )
331 mxOutputStream
->writeBytes( maMarkStack
.top().getData() );
336 const Int8Sequence
aMerge( maMarkStack
.top().getData() );
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
);
352 maMarkStack
.top().append( aData
);
355 FastSaxSerializer::Int8Sequence
& FastSaxSerializer::ForMerge::getData()
357 merge( maData
, maPostponed
, true );
358 maPostponed
.realloc( 0 );
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();
383 sal_Int32 nTopLen
= rTop
.getLength();
385 rTop
.realloc( nTopLen
+ nMergeLen
);
388 // append the rMerge to the rTop
389 memcpy( rTop
.getArray() + nTopLen
, rMerge
.getConstArray(), nMergeLen
);
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