diff options
Diffstat (limited to 'sax/source/tools/fastserializer.cxx')
-rw-r--r-- | sax/source/tools/fastserializer.cxx | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/sax/source/tools/fastserializer.cxx b/sax/source/tools/fastserializer.cxx new file mode 100644 index 000000000000..4603ceed3343 --- /dev/null +++ b/sax/source/tools/fastserializer.cxx @@ -0,0 +1,388 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: contexthandler2.cxx,v $ + * + * $Revision: 1.1.2.2 $ + * + * last change: $Author: dr $ $Date: 2008/02/11 10:43:07 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "fastserializer.hxx" +#include <rtl/ustrbuf.hxx> + +#include <com/sun/star/xml/Attribute.hpp> +#include <com/sun/star/xml/FastAttribute.hpp> +#include <com/sun/star/xml/sax/XFastAttributeList.hpp> + +#include <string.h> + +using ::rtl::OString; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::rtl::OUStringToOString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::xml::FastAttribute; +using ::com::sun::star::xml::Attribute; +using ::com::sun::star::xml::sax::SAXException; +using ::com::sun::star::xml::sax::XFastAttributeList; +using ::com::sun::star::xml::sax::XFastTokenHandler; +using ::com::sun::star::xml::sax::XFastSerializer; +using ::com::sun::star::io::XOutputStream; +using ::com::sun::star::io::NotConnectedException; +using ::com::sun::star::io::IOException; +using ::com::sun::star::io::BufferSizeExceededException; + +static Sequence< sal_Int8 > aClosingBracket((sal_Int8 *)">", 1); +static Sequence< sal_Int8 > aSlashAndClosingBracket((sal_Int8 *)"/>", 2); +static Sequence< sal_Int8 > aColon((sal_Int8 *)":", 1); +static Sequence< sal_Int8 > aOpeningBracket((sal_Int8 *)"<", 1); +static Sequence< sal_Int8 > aOpeningBracketAndSlash((sal_Int8 *)"</", 2); +static Sequence< sal_Int8 > aQuote((sal_Int8 *)"\"", 1); +static Sequence< sal_Int8 > aEqualSignAndQuote((sal_Int8 *)"=\"", 2); +static Sequence< sal_Int8 > aSpace((sal_Int8 *)" ", 1); +static Sequence< sal_Int8 > aXmlHeader((sal_Int8*) "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n", 56); + +#define HAS_NAMESPACE(x) ((x & 0xffff0000) != 0) +#define NAMESPACE(x) (x >> 16) +#define TOKEN(x) (x & 0xffff) + +namespace sax_fastparser { + FastSaxSerializer::FastSaxSerializer( ) : mxOutputStream(), mxFastTokenHandler(), maMarkStack() {} + FastSaxSerializer::~FastSaxSerializer() {} + + void SAL_CALL FastSaxSerializer::startDocument( ) throw (SAXException, RuntimeException) + { + if (!mxOutputStream.is()) + return; + writeBytes(aXmlHeader); + } + + OUString FastSaxSerializer::escapeXml( const OUString& s ) + { + ::rtl::OUStringBuffer sBuf( s.getLength() ); + const sal_Unicode* pStr = s; + sal_Int32 nLen = s.getLength(); + for( sal_Int32 i = 0; i < nLen; ++i) + { + sal_Unicode c = pStr[ i ]; + switch( c ) + { + case '<': sBuf.appendAscii( "<" ); break; + case '>': sBuf.appendAscii( ">" ); break; + case '&': sBuf.appendAscii( "&" ); break; + case '\'': sBuf.appendAscii( "'" ); break; + case '"': sBuf.appendAscii( """ ); break; + default: sBuf.append( c ); break; + } + } + return sBuf.makeStringAndClear(); + } + + void FastSaxSerializer::write( const OUString& s ) + { + OString sOutput( OUStringToOString( s, RTL_TEXTENCODING_UTF8 ) ); + writeBytes( Sequence< sal_Int8 >( + reinterpret_cast< const sal_Int8*>( sOutput.getStr() ), + sOutput.getLength() ) ); + } + + void SAL_CALL FastSaxSerializer::endDocument( ) throw (SAXException, RuntimeException) + { + if (!mxOutputStream.is()) + return; + } + + void SAL_CALL FastSaxSerializer::writeId( ::sal_Int32 nElement ) + { + if( HAS_NAMESPACE( nElement ) ) { + writeBytes(mxFastTokenHandler->getUTF8Identifier(NAMESPACE(nElement))); + writeBytes(aColon); + writeBytes(mxFastTokenHandler->getUTF8Identifier(TOKEN(nElement))); + } else + writeBytes(mxFastTokenHandler->getUTF8Identifier(nElement)); + } + + void SAL_CALL FastSaxSerializer::startFastElement( ::sal_Int32 Element, const Reference< XFastAttributeList >& Attribs ) + throw (SAXException, RuntimeException) + { + if (!mxOutputStream.is()) + return; + + writeBytes(aOpeningBracket); + + writeId(Element); + writeFastAttributeList(Attribs); + + writeBytes(aClosingBracket); + } + + void SAL_CALL FastSaxSerializer::startUnknownElement( const OUString& Namespace, const OUString& Name, const Reference< XFastAttributeList >& Attribs ) + throw (SAXException, RuntimeException) + { + if (!mxOutputStream.is()) + return; + + writeBytes(aOpeningBracket); + + if (Namespace.getLength()) + { + write(Namespace); + writeBytes(aColon); + } + + write(Name); + + writeFastAttributeList(Attribs); + + writeBytes(aClosingBracket); + } + + void SAL_CALL FastSaxSerializer::endFastElement( ::sal_Int32 Element ) + throw (SAXException, RuntimeException) + { + if (!mxOutputStream.is()) + return; + + writeBytes(aOpeningBracketAndSlash); + + writeId(Element); + + writeBytes(aClosingBracket); + } + + void SAL_CALL FastSaxSerializer::endUnknownElement( const OUString& Namespace, const OUString& Name ) + throw (SAXException, RuntimeException) + { + if (!mxOutputStream.is()) + return; + + writeBytes(aOpeningBracketAndSlash); + + if (Namespace.getLength()) + { + write(Namespace); + writeBytes(aColon); + } + + write(Name); + + writeBytes(aClosingBracket); + } + + void SAL_CALL FastSaxSerializer::singleFastElement( ::sal_Int32 Element, const Reference< XFastAttributeList >& Attribs ) + throw (SAXException, RuntimeException) + { + if (!mxOutputStream.is()) + return; + + writeBytes(aOpeningBracket); + + writeId(Element); + writeFastAttributeList(Attribs); + + writeBytes(aSlashAndClosingBracket); + } + + void SAL_CALL FastSaxSerializer::singleUnknownElement( const OUString& Namespace, const OUString& Name, const Reference< XFastAttributeList >& Attribs ) + throw (SAXException, RuntimeException) + { + if (!mxOutputStream.is()) + return; + + writeBytes(aOpeningBracket); + + if (Namespace.getLength()) + { + write(Namespace); + writeBytes(aColon); + } + + write(Name); + + writeFastAttributeList(Attribs); + + writeBytes(aSlashAndClosingBracket); + } + + void SAL_CALL FastSaxSerializer::characters( const OUString& aChars ) + throw (SAXException, RuntimeException) + { + if (!mxOutputStream.is()) + return; + + write( aChars ); + } + + void SAL_CALL FastSaxSerializer::setOutputStream( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >& xOutputStream ) + throw (::com::sun::star::uno::RuntimeException) + { + mxOutputStream = xOutputStream; + } + + void SAL_CALL FastSaxSerializer::setFastTokenHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >& xFastTokenHandler ) + throw (::com::sun::star::uno::RuntimeException) + { + mxFastTokenHandler = xFastTokenHandler; + } + void FastSaxSerializer::writeFastAttributeList( const Reference< XFastAttributeList >& Attribs ) + { + Sequence< Attribute > aAttrSeq = Attribs->getUnknownAttributes(); + const Attribute *pAttr = aAttrSeq.getConstArray(); + sal_Int32 nAttrLength = aAttrSeq.getLength(); + for (sal_Int32 i = 0; i < nAttrLength; i++) + { + writeBytes(aSpace); + + write(pAttr[i].Name); + writeBytes(aEqualSignAndQuote); + write(escapeXml(pAttr[i].Value)); + writeBytes(aQuote); + } + + Sequence< FastAttribute > aFastAttrSeq = Attribs->getFastAttributes(); + const FastAttribute *pFastAttr = aFastAttrSeq.getConstArray(); + sal_Int32 nFastAttrLength = aFastAttrSeq.getLength(); + for (sal_Int32 j = 0; j < nFastAttrLength; j++) + { + writeBytes(aSpace); + + sal_Int32 nToken = pFastAttr[j].Token; + writeId(nToken); + + writeBytes(aEqualSignAndQuote); + + write(escapeXml(Attribs->getValue(pFastAttr[j].Token))); + + writeBytes(aQuote); + } + } + + // XServiceInfo + OUString FastSaxSerializer::getImplementationName() throw (RuntimeException) + { + return OUString::createFromAscii( SERIALIZER_IMPLEMENTATION_NAME ); + } + + // XServiceInfo + sal_Bool FastSaxSerializer::supportsService(const OUString& ServiceName) throw (RuntimeException) + { + Sequence< OUString > aSNL = getSupportedServiceNames(); + const OUString * pArray = aSNL.getConstArray(); + + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return sal_True; + + return sal_False; + } + + // XServiceInfo + Sequence< OUString > FastSaxSerializer::getSupportedServiceNames(void) throw (RuntimeException) + { + Sequence<OUString> seq(1); + seq.getArray()[0] = OUString::createFromAscii( SERIALIZER_SERVICE_NAME ); + return seq; + } + + OUString FastSaxSerializer::getImplementationName_Static() + { + return OUString::createFromAscii( SERIALIZER_IMPLEMENTATION_NAME ); + } + + Sequence< OUString > FastSaxSerializer::getSupportedServiceNames_Static(void) + { + Sequence<OUString> aRet(1); + aRet.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(SERIALIZER_SERVICE_NAME) ); + return aRet; + } + + void FastSaxSerializer::mark() + { + maMarkStack.push( Int8Sequence() ); + } + + void FastSaxSerializer::mergeTopMarks( bool bPrepend ) + { + if ( maMarkStack.empty() ) + return; + + if ( maMarkStack.size() == 1 ) + { + mxOutputStream->writeBytes( maMarkStack.top() ); + maMarkStack.pop(); + } + else + { + const Int8Sequence aMerge( maMarkStack.top() ); + maMarkStack.pop(); + + sal_Int32 nMergeLen = aMerge.getLength(); + if ( nMergeLen > 0 ) + { + Int8Sequence &rTop = maMarkStack.top(); + sal_Int32 nTopLen = rTop.getLength(); + + rTop.realloc( nTopLen + nMergeLen ); + if ( bPrepend ) + { + // prepend the aMerge to the rTop + memmove( rTop.getArray() + nMergeLen, rTop.getConstArray(), nTopLen ); + memcpy( rTop.getArray(), aMerge.getConstArray(), nMergeLen ); + } + else + { + // append the aMerge to the rTop + memcpy( rTop.getArray() + nTopLen, aMerge.getConstArray(), nMergeLen ); + } + } + } + } + + void FastSaxSerializer::writeBytes( const Sequence< ::sal_Int8 >& aData ) throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException ) + { + if ( maMarkStack.empty() ) + mxOutputStream->writeBytes( aData ); + else + { + sal_Int32 nDataLen = aData.getLength(); + if ( nDataLen > 0 ) + { + Int8Sequence &rTop = maMarkStack.top(); + sal_Int32 nTopLen = rTop.getLength(); + + rTop.realloc( nTopLen + nDataLen ); + memcpy( rTop.getArray() + nTopLen, aData.getConstArray(), nDataLen ); + } + } + } + +} // namespace sax_fastparser + |