1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: contexthandler2.cxx,v $
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,
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>
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())
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
];
98 case '<': sBuf
.appendAscii( "<" ); break;
99 case '>': sBuf
.appendAscii( ">" ); break;
100 case '&': sBuf
.appendAscii( "&" ); break;
101 case '\'': sBuf
.appendAscii( "'" ); break;
102 case '"': sBuf
.appendAscii( """ ); 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())
123 void SAL_CALL
FastSaxSerializer::writeId( ::sal_Int32 nElement
)
125 if( HAS_NAMESPACE( nElement
) ) {
126 writeBytes(mxFastTokenHandler
->getUTF8Identifier(NAMESPACE(nElement
)));
128 writeBytes(mxFastTokenHandler
->getUTF8Identifier(TOKEN(nElement
)));
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())
139 writeBytes(aOpeningBracket
);
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())
153 writeBytes(aOpeningBracket
);
155 if (Namespace
.getLength())
163 writeFastAttributeList(Attribs
);
165 writeBytes(aClosingBracket
);
168 void SAL_CALL
FastSaxSerializer::endFastElement( ::sal_Int32 Element
)
169 throw (SAXException
, RuntimeException
)
171 if (!mxOutputStream
.is())
174 writeBytes(aOpeningBracketAndSlash
);
178 writeBytes(aClosingBracket
);
181 void SAL_CALL
FastSaxSerializer::endUnknownElement( const OUString
& Namespace
, const OUString
& Name
)
182 throw (SAXException
, RuntimeException
)
184 if (!mxOutputStream
.is())
187 writeBytes(aOpeningBracketAndSlash
);
189 if (Namespace
.getLength())
197 writeBytes(aClosingBracket
);
200 void SAL_CALL
FastSaxSerializer::singleFastElement( ::sal_Int32 Element
, const Reference
< XFastAttributeList
>& Attribs
)
201 throw (SAXException
, RuntimeException
)
203 if (!mxOutputStream
.is())
206 writeBytes(aOpeningBracket
);
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())
220 writeBytes(aOpeningBracket
);
222 if (Namespace
.getLength())
230 writeFastAttributeList(Attribs
);
232 writeBytes(aSlashAndClosingBracket
);
235 void SAL_CALL
FastSaxSerializer::characters( const OUString
& aChars
)
236 throw (SAXException
, RuntimeException
)
238 if (!mxOutputStream
.is())
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
++)
264 write(pAttr
[i
].Name
);
265 writeBytes(aEqualSignAndQuote
);
266 write(escapeXml(pAttr
[i
].Value
));
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
++)
277 sal_Int32 nToken
= pFastAttr
[j
].Token
;
280 writeBytes(aEqualSignAndQuote
);
282 write(escapeXml(Attribs
->getValue(pFastAttr
[j
].Token
)));
289 OUString
FastSaxSerializer::getImplementationName() throw (RuntimeException
)
291 return OUString::createFromAscii( SERIALIZER_IMPLEMENTATION_NAME
);
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
)
308 Sequence
< OUString
> FastSaxSerializer::getSupportedServiceNames(void) throw (RuntimeException
)
310 Sequence
<OUString
> seq(1);
311 seq
.getArray()[0] = OUString::createFromAscii( SERIALIZER_SERVICE_NAME
);
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
) );
327 void FastSaxSerializer::mark()
329 maMarkStack
.push( ForMerge() );
332 void FastSaxSerializer::mergeTopMarks( sax_fastparser::MergeMarksEnum eMergeType
)
334 if ( maMarkStack
.empty() )
337 if ( maMarkStack
.size() == 1 )
339 mxOutputStream
->writeBytes( maMarkStack
.top().getData() );
344 const Int8Sequence
aMerge( maMarkStack
.top().getData() );
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
);
360 maMarkStack
.top().append( aData
);
363 FastSaxSerializer::Int8Sequence
& FastSaxSerializer::ForMerge::getData()
365 merge( maData
, maPostponed
, true );
366 maPostponed
.realloc( 0 );
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();
391 sal_Int32 nTopLen
= rTop
.getLength();
393 rTop
.realloc( nTopLen
+ nMergeLen
);
396 // append the rMerge to the rTop
397 memcpy( rTop
.getArray() + nTopLen
, rMerge
.getConstArray(), nMergeLen
);
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