summaryrefslogtreecommitdiff
path: root/sax
diff options
context:
space:
mode:
Diffstat (limited to 'sax')
-rw-r--r--sax/inc/sax/dllapi.h39
-rw-r--r--sax/inc/sax/fastattribs.hxx91
-rw-r--r--sax/inc/sax/fshelper.hxx118
-rw-r--r--sax/inc/sax/parser/saxparser.hxx150
-rw-r--r--sax/inc/sax/tools/attributemap.hxx70
-rw-r--r--sax/inc/sax/tools/converter.hxx208
-rw-r--r--sax/inc/sax/tools/saxobject.hxx50
-rw-r--r--sax/inc/sax/tools/tokenmap.hxx65
-rw-r--r--sax/inc/xml2utf.hxx147
-rw-r--r--sax/prj/build.lst6
-rw-r--r--sax/prj/d.lst13
-rw-r--r--sax/qa/cppunit/makefile.mk71
-rw-r--r--sax/qa/cppunit/test_converter.cxx244
-rw-r--r--sax/qa/cppunit/version.map34
-rw-r--r--sax/source/expatwrap/attrlistimpl.cxx168
-rw-r--r--sax/source/expatwrap/attrlistimpl.hxx85
-rw-r--r--sax/source/expatwrap/factory.hxx34
-rw-r--r--sax/source/expatwrap/makefile.mk76
-rw-r--r--sax/source/expatwrap/sax_expat.cxx1107
-rw-r--r--sax/source/expatwrap/saxwriter.cxx1454
-rw-r--r--sax/source/expatwrap/xml2utf.cxx570
-rw-r--r--sax/source/fastparser/facreg.cxx106
-rw-r--r--sax/source/fastparser/fastparser.cxx953
-rw-r--r--sax/source/fastparser/fastparser.hxx164
-rw-r--r--sax/source/fastparser/makefile.mk74
-rw-r--r--sax/source/tools/converter.cxx2098
-rw-r--r--sax/source/tools/fastattribs.cxx168
-rw-r--r--sax/source/tools/fastserializer.cxx401
-rw-r--r--sax/source/tools/fastserializer.hxx161
-rw-r--r--sax/source/tools/fshelper.cxx201
-rw-r--r--sax/source/tools/makefile.mk67
-rw-r--r--sax/test/makefile.mk62
-rw-r--r--sax/test/sax/exports.dxp3
-rw-r--r--sax/test/sax/factory.hxx89
-rw-r--r--sax/test/sax/makefile.mk61
-rw-r--r--sax/test/sax/testsax.cxx870
-rw-r--r--sax/test/sax/testwriter.cxx698
-rw-r--r--sax/test/saxdemo.cxx651
-rw-r--r--sax/test/testcomponent.cxx230
-rw-r--r--sax/util/makefile.mk68
-rw-r--r--sax/util/makefile.pmk30
41 files changed, 11955 insertions, 0 deletions
diff --git a/sax/inc/sax/dllapi.h b/sax/inc/sax/dllapi.h
new file mode 100644
index 000000000000..e9aca11fb0bd
--- /dev/null
+++ b/sax/inc/sax/dllapi.h
@@ -0,0 +1,39 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SAX_DLLAPI_H
+#define INCLUDED_SAX_DLLAPI_H
+
+#include "sal/types.h"
+
+#if defined SAX_DLLIMPLEMENTATION
+#define SAX_DLLPUBLIC SAL_DLLPUBLIC_EXPORT
+#else
+#define SAX_DLLPUBLIC SAL_DLLPUBLIC_IMPORT
+#endif
+
+#endif
diff --git a/sax/inc/sax/fastattribs.hxx b/sax/inc/sax/fastattribs.hxx
new file mode 100644
index 000000000000..9a968982d39e
--- /dev/null
+++ b/sax/inc/sax/fastattribs.hxx
@@ -0,0 +1,91 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SAX_FASTATTRIBS_HXX_
+#define _SAX_FASTATTRIBS_HXX_
+
+#include <com/sun/star/xml/sax/XFastAttributeList.hpp>
+#include <com/sun/star/xml/sax/XFastTokenHandler.hpp>
+#include <com/sun/star/xml/Attribute.hpp>
+#include <com/sun/star/xml/FastAttribute.hpp>
+
+#include <cppuhelper/implbase1.hxx>
+#include "sax/dllapi.h"
+
+#include <map>
+#include <vector>
+
+namespace sax_fastparser
+{
+
+struct UnknownAttribute
+{
+ ::rtl::OUString maNamespaceURL;
+ ::rtl::OString maName;
+ ::rtl::OString maValue;
+
+ UnknownAttribute( const ::rtl::OUString& rNamespaceURL, const ::rtl::OString& rName, const ::rtl::OString& rValue );
+
+ UnknownAttribute( const ::rtl::OString& rName, const ::rtl::OString& rValue );
+
+ void FillAttribute( ::com::sun::star::xml::Attribute* pAttrib ) const;
+};
+
+typedef std::map< sal_Int32, ::rtl::OString > FastAttributeMap;
+typedef std::vector< UnknownAttribute > UnknownAttributeList;
+
+class SAX_DLLPUBLIC FastAttributeList : public ::cppu::WeakImplHelper1< ::com::sun::star::xml::sax::XFastAttributeList >
+{
+public:
+ FastAttributeList( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >& xTokenHandler );
+ virtual ~FastAttributeList();
+
+ void clear();
+ void add( sal_Int32 nToken, const ::rtl::OString& rValue );
+ void addUnknown( const ::rtl::OUString& rNamespaceURL, const ::rtl::OString& rName, const ::rtl::OString& rValue );
+ void addUnknown( const ::rtl::OString& rName, const ::rtl::OString& rValue );
+
+ // XFastAttributeList
+ virtual ::sal_Bool SAL_CALL hasAttribute( ::sal_Int32 Token ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::sal_Int32 SAL_CALL getValueToken( ::sal_Int32 Token ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual ::sal_Int32 SAL_CALL getOptionalValueToken( ::sal_Int32 Token, ::sal_Int32 Default ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getValue( ::sal_Int32 Token ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getOptionalValue( ::sal_Int32 Token ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::xml::Attribute > SAL_CALL getUnknownAttributes( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::xml::FastAttribute > SAL_CALL getFastAttributes() throw (::com::sun::star::uno::RuntimeException);
+
+private:
+ FastAttributeMap maAttributes;
+ UnknownAttributeList maUnknownAttributes;
+ FastAttributeMap::iterator maLastIter;
+ ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler > mxTokenHandler;
+
+};
+
+}
+
+#endif
diff --git a/sax/inc/sax/fshelper.hxx b/sax/inc/sax/fshelper.hxx
new file mode 100644
index 000000000000..f816e3edc1c3
--- /dev/null
+++ b/sax/inc/sax/fshelper.hxx
@@ -0,0 +1,118 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SAX_FS_HELPER_HXX_
+#define _SAX_FS_HELPER_HXX_
+
+#include <com/sun/star/uno/XReference.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/xml/sax/XFastTokenHandler.hpp>
+#include <stdarg.h>
+#include <boost/shared_ptr.hpp>
+#include <sax/fastattribs.hxx>
+#include "sax/dllapi.h"
+
+#define FSNS(namespc, element) ((namespc << 16) | element)
+const sal_Int32 FSEND = -1; // same as XML_TOKEN_INVALID
+
+namespace sax_fastparser {
+
+enum MergeMarksEnum { MERGE_MARKS_APPEND = 0, MERGE_MARKS_PREPEND = 1, MERGE_MARKS_POSTPONE = 2 };
+
+typedef ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList > XFastAttributeListRef;
+
+class FastSaxSerializer;
+
+class SAX_DLLPUBLIC FastSerializerHelper
+{
+public:
+
+ FastSerializerHelper( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >& xOutputStream );
+
+ ~FastSerializerHelper();
+
+ void startElement(const char* elementName, ...);
+ void singleElement(const char* elementName, ...);
+ void endElement(const char* elementName);
+
+ void startElementV(sal_Int32 elementTokenId, va_list args);
+ void singleElementV(sal_Int32 elementTokenId, va_list args);
+
+ inline void startElement(sal_Int32 elementTokenId, ...)
+ { va_list args; va_start( args, elementTokenId ); startElementV( elementTokenId, args ); va_end( args ); }
+ inline void singleElement(sal_Int32 elementTokenId, ...)
+ { va_list args; va_start( args, elementTokenId ); singleElementV( elementTokenId, args ); va_end( args ); }
+ inline void startElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, ...)
+ { va_list args; va_start( args, elementTokenId ); startElementV( FSNS( namespaceTokenId, elementTokenId), args ); va_end( args ); }
+ inline void singleElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, ...)
+ { va_list args; va_start( args, elementTokenId ); singleElementV( FSNS( namespaceTokenId, elementTokenId), args ); va_end( args ); }
+ void endElement(sal_Int32 elementTokenId);
+ inline void endElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId)
+ { endElement( FSNS( namespaceTokenId, elementTokenId ) ); }
+
+ void singleElement(const char* elementName, XFastAttributeListRef xAttrList);
+ inline void singleElement(sal_Int32 elementTokenId, XFastAttributeListRef xAttrList)
+ { singleElementV(elementTokenId, xAttrList); }
+ void singleElementV(sal_Int32 elementTokenId, XFastAttributeListRef xAttrList);
+ inline void singleElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, XFastAttributeListRef xAttrList)
+ { singleElementV(FSNS( namespaceTokenId, elementTokenId), xAttrList); }
+
+ void startElementV(sal_Int32 elementTokenId, XFastAttributeListRef xAttrList);
+ inline void startElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, XFastAttributeListRef xAttrList)
+ { startElementV( FSNS( namespaceTokenId, elementTokenId ), xAttrList ); }
+
+ FastSerializerHelper* write(const char* value);
+ FastSerializerHelper* write(const rtl::OUString& value);
+ FastSerializerHelper* write(sal_Int32 value);
+ FastSerializerHelper* write(sal_Int64 value);
+ FastSerializerHelper* write(float value);
+ FastSerializerHelper* write(double value);
+
+ FastSerializerHelper* writeEscaped(const char* value);
+ FastSerializerHelper* writeEscaped(const rtl::OUString& value);
+
+ FastSerializerHelper* writeId(sal_Int32 tokenId);
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > getOutputStream();
+
+ FastAttributeList *createAttrList();
+
+ void mark();
+ void mergeTopMarks( MergeMarksEnum eMergeType = MERGE_MARKS_APPEND );
+
+private:
+
+ FastSaxSerializer* mpSerializer;
+ com::sun::star::uno::Reference<com::sun::star::xml::sax::XFastTokenHandler> mxTokenHandler;
+
+};
+
+typedef boost::shared_ptr< FastSerializerHelper > FSHelperPtr;
+
+}
+
+#endif // _SAX_FS_HELPER_HXX_
diff --git a/sax/inc/sax/parser/saxparser.hxx b/sax/inc/sax/parser/saxparser.hxx
new file mode 100644
index 000000000000..dde71accd680
--- /dev/null
+++ b/sax/inc/sax/parser/saxparser.hxx
@@ -0,0 +1,150 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SAX_SAXPARSER_HXX_
+#define _SAX_SAXPARSER_HXX_
+
+#include "sax/dllapi.h"
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#include <com/sun/star/xml/sax/SAXException.hpp>
+#include <rtl/ref.hxx>
+
+#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
+#include <boost/shared_ptr.hpp>
+#endif
+
+#include <map>
+#include <memory>
+#include "sax/tools/saxobject.hxx"
+#include "sax/tools/attributemap.hxx"
+
+#include <boost/scoped_ptr.hpp>
+
+namespace sax
+{
+
+// --------------------------------------------------------------------
+
+class SaxParser;
+class SaxContext;
+
+typedef rtl::Reference< SaxParser > SaxParserRef;
+typedef rtl::Reference< SaxContext > SaxContextRef;
+
+/** base class for each implementation that handles all sax calls for an element */
+class SAX_DLLPUBLIC SaxContext : public SaxObject
+{
+public:
+ SaxContext( const SaxParserRef& xParser );
+ virtual ~SaxContext();
+
+ /** receives notification of the beginning of an element .
+ */
+ virtual void StartElement( sal_uInt32 aElementToken, const AttributeMap& rAttributes );
+
+ /** receives notification of character data.
+ */
+ virtual void Characters( const sal_Char *pCharacters, sal_uInt32 nLength );
+
+ /** receives notification of the end of an element.
+ */
+ virtual void EndElement( sal_uInt32 aElementToken );
+
+ /** is called by the SaxParser for each child element inside this instances element */
+ virtual SaxContextRef CreateContext( sal_uInt32 aElementToken, const AttributeMap& rAttributes );
+
+ const SaxParserRef& getParser() const { return mxParser; }
+private:
+ SaxParserRef mxParser;
+};
+
+// --------------------------------------------------------------------
+
+class SaxParserImpl;
+
+/** base class for loading a single xml stream. Derived classes must call
+ parseStream to start parsing and are notified through virtual methods
+ for sax events. */
+class SAX_DLLPUBLIC SaxParser : public SaxObject
+{
+public:
+ SaxParser();
+ virtual ~SaxParser();
+
+ /** returns the unicode representation of a token from the xml stream
+ that was unknown to the SaxTokenMap from the derived class. */
+ rtl::OUString GetCustomToken( sal_uInt32 nToken );
+
+ /** returns the unicode representation of a namespace from the xml stream
+ that was unknown to the SaxTokenMap from the derived class. */
+ rtl::OUString GetCustomNamespace( sal_uInt32 nToken );
+
+ /** returns the system id of the currently parsed stream */
+ const rtl::OUString& GetSystemId() const;
+
+ /** starts parsing of the source xml stream provided in the given sax InputSource */
+ virtual void parseStream( const ::com::sun::star::xml::sax::InputSource& rInputSource ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+
+ /** is called once when parsing of the xml stream starts */
+ virtual void StartDocument();
+
+ /** is called once for each element in the xml stream.
+ Default implementation calls StartElement() on the topmost contex. */
+ virtual void StartElement( sal_uInt32 aElementToken, const AttributeMap& rAttributes );
+
+ /** is called for characters betwen elements in the xml stream.
+ Default implementation calls Characters() on the topmost contex.
+ @param pCharacters The characters in utf-8 encoding
+ @param nLength the size in bytes of the utf-8 string
+ */
+ virtual void Characters( const sal_Char *pCharacters, sal_uInt32 nLength );
+
+ /** is called once at the end of each element in the xml stream.
+ Default implementation calls EndElement() on the topmost contex. */
+ virtual void EndElement( sal_uInt32 aElementToken );
+
+ /** is called once after parsing the xml stream is finished */
+ virtual void EndDocument();
+
+ /** is called once for each element in the xml stream and before StartElement() is called.
+ Default implementation calls CreateContext at the topmost context.
+ Returned contexts are pushed on a stack and removed after the corresponding EndElement call. */
+ virtual SaxContextRef CreateContext( sal_uInt32 aElementToken, const AttributeMap& rAttributes );
+
+ /** must be implemented from derived classes. The returned SaxTokenMap is used to convert
+ element names and attribute names and values to tokens. */
+ virtual const SaxTokenMapRef& getTokenMap() = 0;
+
+private:
+ void AddNamespace( sal_uInt32 nNamespaceId, sal_uInt32 nNamespaceURIToken );
+
+ boost::scoped_ptr< SaxParserImpl > mpImpl;
+};
+
+}
+
+#endif // _SAX_SAXPARSER_HXX_
diff --git a/sax/inc/sax/tools/attributemap.hxx b/sax/inc/sax/tools/attributemap.hxx
new file mode 100644
index 000000000000..ea8f55a9b626
--- /dev/null
+++ b/sax/inc/sax/tools/attributemap.hxx
@@ -0,0 +1,70 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SAX_ATTRIBUTEMAP_HXX_
+#define _SAX_ATTRIBUTEMAP_HXX_
+
+#include "sax/dllapi.h"
+
+#include <map>
+#include "sax/tools/tokenmap.hxx"
+
+namespace sax
+{
+ class SaxTokenMap;
+
+ typedef std::map< sal_uInt32, rtl::OString > AttributeMapBase;
+
+ /** a map for a set of xml attributes, identified with integer tokens.
+ Attribute values are stored in utf-8 encoding. */
+ class SAX_DLLPUBLIC AttributeMap : public AttributeMapBase
+ {
+ public:
+ AttributeMap( const SaxTokenMap& rTokenMap );
+ ~AttributeMap();
+
+ /** returns a unicode string, if the token does not exists the string is empty */
+ ::rtl::OUString getString( SaxToken nToken ) const;
+
+ /** returns true if the attribute with the token nToken is part of this map */
+ bool has( SaxToken nToken ) const;
+
+ /** converts the attribute with the token nToken to sal_Int32 or returns
+ nDefault if this attribute does not exists */
+ sal_Int32 getInt32( SaxToken nToken, sal_Int32 nDefault = 0 ) const;
+
+ /** converts the attribute with the token nToken to a token or returns
+ nDefault if this attribute does not exists */
+ sal_uInt32 getToken( SaxToken nToken, SaxToken nDefault ) const;
+
+ private:
+ const SaxTokenMap& mrTokenMap;
+ };
+
+}
+
+#endif // _SAX_ATTRIBUTEMAP_HXX_
diff --git a/sax/inc/sax/tools/converter.hxx b/sax/inc/sax/tools/converter.hxx
new file mode 100644
index 000000000000..4b65c1dc83b2
--- /dev/null
+++ b/sax/inc/sax/tools/converter.hxx
@@ -0,0 +1,208 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SAX_CONVERTER_HXX
+#define _SAX_CONVERTER_HXX
+
+#include "sax/dllapi.h"
+
+#include <sal/types.h>
+
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/util/MeasureUnit.hpp>
+
+
+namespace rtl
+{
+class OUString;
+class OUStringBuffer;
+}
+
+namespace com { namespace sun { namespace star {
+ namespace util {
+ struct Date;
+ struct DateTime;
+ struct Duration;
+ }
+} } }
+
+namespace sax {
+
+/** the Converter converts values of various types from
+ their internal represantation to the textual form used in xml
+ and back.
+
+ All unit types are expressed as com::sun::star::util::MeasureUnit
+*/
+
+
+class SAX_DLLPUBLIC Converter
+{
+public:
+ /** convert string to measure using optional min and max values*/
+ static bool convertMeasure( sal_Int32& rValue,
+ const ::rtl::OUString& rString,
+ sal_Int16 nTargetUnit = ::com::sun::star::util::MeasureUnit::MM_100TH,
+ sal_Int32 nMin = SAL_MIN_INT32,
+ sal_Int32 nMax = SAL_MAX_INT32 );
+
+ /** convert measure to string */
+ static void convertMeasure( ::rtl::OUStringBuffer& rBuffer,
+ sal_Int32 nMeasure,
+ sal_Int16 SourceUnit = ::com::sun::star::util::MeasureUnit::MM_100TH,
+ sal_Int16 nTargetUnit = ::com::sun::star::util::MeasureUnit::INCH );
+
+ /** convert string to boolean */
+ static bool convertBool( bool& rBool,
+ const ::rtl::OUString& rString );
+
+ /** convert boolean to string */
+ static void convertBool( ::rtl::OUStringBuffer& rBuffer,
+ bool bValue );
+
+ /** convert string to percent */
+ static bool convertPercent( sal_Int32& rValue,
+ const ::rtl::OUString& rString );
+
+ /** convert percent to string */
+ static void convertPercent( ::rtl::OUStringBuffer& rBuffer,
+ sal_Int32 nValue );
+
+ /** convert string to pixel measure unite */
+ static bool convertMeasurePx( sal_Int32& rValue,
+ const ::rtl::OUString& rString );
+
+ /** convert pixel measure unit to string */
+ static void convertMeasurePx( ::rtl::OUStringBuffer& rBuffer,
+ sal_Int32 nValue );
+
+ /** convert string to color */
+ static bool convertColor( sal_Int32& rColor,
+ const ::rtl::OUString&rValue );
+
+ /** convert color to string */
+ static void convertColor( ::rtl::OUStringBuffer &rBuffer,
+ sal_Int32 nColor );
+
+ /** convert number to string */
+ static void convertNumber( ::rtl::OUStringBuffer& rBuffer,
+ sal_Int32 nNumber );
+
+ /** convert string to number with optional min and max values */
+ static bool convertNumber( sal_Int32& rValue,
+ const ::rtl::OUString& rString,
+ sal_Int32 nMin = SAL_MIN_INT32,
+ sal_Int32 nMax = SAL_MAX_INT32 );
+
+ /** convert double number to string (using ::rtl::math) and
+ DO convert from source unit to target unit */
+ static void convertDouble( ::rtl::OUStringBuffer& rBuffer,
+ double fNumber,
+ bool bWriteUnits,
+ sal_Int16 nSourceUnit,
+ sal_Int16 nTargetUnit );
+
+ /** convert double number to string (using ::rtl::math) without unit conversion */
+ static void convertDouble( ::rtl::OUStringBuffer& rBuffer, double fNumber);
+
+ /** convert string to double number (using ::rtl::math) and DO convert from
+ source unit to target unit. */
+ static bool convertDouble( double& rValue,
+ const ::rtl::OUString& rString,
+ sal_Int16 nSourceUnit,
+ sal_Int16 nTargetUnit );
+
+ /** convert string to double number (using ::rtl::math) without unit conversion */
+ static bool convertDouble(double& rValue, const ::rtl::OUString& rString);
+
+ /** convert string to double number (using ::rtl::math) with unit conversion */
+ static bool convertDouble(double& rValue, const ::rtl::OUString& rString, sal_Int16 nTargetUnit );
+
+ /** convert double to ISO "duration" string; negative durations allowed */
+ static void convertDuration(::rtl::OUStringBuffer& rBuffer,
+ const double fTime);
+
+ /** convert util::Duration to ISO "duration" string */
+ static void convertDuration(::rtl::OUStringBuffer& rBuffer,
+ const ::com::sun::star::util::Duration& rDuration);
+
+ /** convert ISO "duration" string to double; negative durations allowed */
+ static bool convertDuration(double & rfTime,
+ const ::rtl::OUString& rString);
+
+ /** convert ISO "duration" string to util::Duration */
+ static bool convertDuration(::com::sun::star::util::Duration& rDuration,
+ const ::rtl::OUString& rString);
+
+ /** convert util::Date to ISO "date" string */
+ static void convertDate( ::rtl::OUStringBuffer& rBuffer,
+ const com::sun::star::util::Date& rDate );
+
+ /** convert util::DateTime to ISO "date" or "dateTime" string */
+ static void convertDateTime( ::rtl::OUStringBuffer& rBuffer,
+ const com::sun::star::util::DateTime& rDateTime,
+ bool bAddTimeIf0AM = false );
+
+ /** convert ISO "date" or "dateTime" string to util::DateTime */
+ static bool convertDateTime( com::sun::star::util::DateTime& rDateTime,
+ const ::rtl::OUString& rString );
+
+ /** convert ISO "date" or "dateTime" string to util::DateTime or
+ util::Date */
+ static bool convertDateOrDateTime(
+ com::sun::star::util::Date & rDate,
+ com::sun::star::util::DateTime & rDateTime,
+ bool & rbDateTime,
+ const ::rtl::OUString & rString );
+
+ /** gets the position of the first comma after npos in the string
+ rStr. Commas inside '"' pairs are not matched */
+ static sal_Int32 indexOfComma( const ::rtl::OUString& rStr,
+ sal_Int32 nPos );
+
+ /** encodes the given byte sequence into Base64 */
+ static void encodeBase64(rtl::OUStringBuffer& aStrBuffer, const com::sun::star::uno::Sequence<sal_Int8>& aPass);
+
+ // Decode a base 64 encoded string into a sequence of bytes. The first
+ // version can be used for attribute values only, bacause it does not
+ // return any chars left from conversion.
+ // For text submitted throgh the SAX characters call, the later method
+ // must be used!
+ static void decodeBase64(com::sun::star::uno::Sequence<sal_Int8>& aPass, const rtl::OUString& sBuffer);
+
+ static sal_Int32 decodeBase64SomeChars(com::sun::star::uno::Sequence<sal_Int8>& aPass, const rtl::OUString& sBuffer);
+
+ static void clearUndefinedChars(rtl::OUString& rTarget, const rtl::OUString& rSource);
+
+ static double GetConversionFactor(::rtl::OUStringBuffer& rUnit, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit);
+ static sal_Int16 GetUnitFromString(const ::rtl::OUString& rString, sal_Int16 nDefaultUnit);
+
+};
+
+}
+
+#endif // _SAX_CONVERTER_HXX
diff --git a/sax/inc/sax/tools/saxobject.hxx b/sax/inc/sax/tools/saxobject.hxx
new file mode 100644
index 000000000000..56b901d9579f
--- /dev/null
+++ b/sax/inc/sax/tools/saxobject.hxx
@@ -0,0 +1,50 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SAX_OBJECT_HXX_
+#define _SAX_OBJECT_HXX_
+
+#include <sal/types.h>
+#include "sax/dllapi.h"
+
+namespace sax
+{
+
+ /** simple base class to allow refcounting with rtl::Reference or css::uno::Reference */
+ class SAX_DLLPUBLIC SaxObject
+ {
+ public:
+ SaxObject();
+ virtual ~SaxObject();
+ virtual void SAL_CALL acquire() throw ();
+ virtual void SAL_CALL release() throw ();
+ private:
+ sal_uInt32 mnRefCount;
+ };
+}
+
+#endif // _SAX_OBJECT_HXX_
diff --git a/sax/inc/sax/tools/tokenmap.hxx b/sax/inc/sax/tools/tokenmap.hxx
new file mode 100644
index 000000000000..42add0690e9a
--- /dev/null
+++ b/sax/inc/sax/tools/tokenmap.hxx
@@ -0,0 +1,65 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SAX_TOKENMAP_HXX_
+#define _SAX_TOKENMAP_HXX_
+
+#include <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+#include "sax/dllapi.h"
+#include "sax/tools/saxobject.hxx"
+
+namespace sax
+{
+ /** type for a token identifier */
+ typedef sal_uInt32 SaxToken;
+
+ /** this class maps a set of ascii/utf-8 strings to token identifier */
+ class SAX_DLLPUBLIC SaxTokenMap : public SaxObject
+ {
+ public:
+ /** constant do indicate an unknown token */
+ const static SaxToken InvalidToken = (SaxToken)-1;
+
+ /** returns the token identifier for the given ascii string or SaxTokenMap::InvalidToken */
+ virtual SaxToken GetToken( const sal_Char* pChar, sal_uInt32 nLength = 0 ) const = 0;
+
+ /** returns the token identifier for the given unicode string or SaxTokenMap::InvalidToken */
+ virtual SaxToken GetToken( const ::rtl::OUString& rToken ) const = 0;
+
+ /** returns the unicode string for the given token identifier */
+ virtual const ::rtl::OUString& GetToken( SaxToken nToken ) const = 0;
+
+ /** returns if the given unicode string equals the given token identifier */
+ bool IsToken( const ::rtl::OUString& rToken, SaxToken nToken ) const { return GetToken( rToken ) == nToken; }
+ };
+
+ /** reference type to a SaxTokenMap */
+ typedef rtl::Reference< SaxTokenMap > SaxTokenMapRef;
+}
+
+#endif // _SAX_TOKENMAP_HXX_
diff --git a/sax/inc/xml2utf.hxx b/sax/inc/xml2utf.hxx
new file mode 100644
index 000000000000..1a0640f5a687
--- /dev/null
+++ b/sax/inc/xml2utf.hxx
@@ -0,0 +1,147 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// TODO: Woher?
+#define Max( a, b ) (((a)>(b)) ? (a) : (b) )
+#define Min( a, b ) (((a)<(b)) ? (a) : (b) )
+
+/*
+*
+* Text2UnicodeConverter
+*
+**/
+namespace sax_expatwrap {
+
+class Text2UnicodeConverter
+{
+
+public:
+ Text2UnicodeConverter( const ::rtl::OString & sEncoding );
+ ~Text2UnicodeConverter();
+
+ ::com::sun::star::uno::Sequence < sal_Unicode > convert( const ::com::sun::star::uno::Sequence<sal_Int8> & );
+ sal_Bool canContinue() { return m_bCanContinue; }
+
+private:
+ void init( rtl_TextEncoding encoding );
+
+ rtl_TextToUnicodeConverter m_convText2Unicode;
+ rtl_TextToUnicodeContext m_contextText2Unicode;
+ sal_Bool m_bCanContinue;
+ sal_Bool m_bInitialized;
+ rtl_TextEncoding m_rtlEncoding;
+ ::com::sun::star::uno::Sequence<sal_Int8> m_seqSource;
+};
+
+/*----------------------------------------
+*
+* Unicode2TextConverter
+*
+**-----------------------------------------*/
+class Unicode2TextConverter
+{
+public:
+ Unicode2TextConverter( rtl_TextEncoding encoding );
+ ~Unicode2TextConverter();
+
+ inline ::com::sun::star::uno::Sequence<sal_Int8> convert( const ::rtl::OUString &s )
+ {
+ return convert( s.getStr() , s.getLength() );
+ }
+ ::com::sun::star::uno::Sequence<sal_Int8> convert( const sal_Unicode * , sal_Int32 nLength );
+ sal_Bool canContinue() { return m_bCanContinue; }
+
+private:
+ void init( rtl_TextEncoding encoding );
+
+ rtl_UnicodeToTextConverter m_convUnicode2Text;
+ rtl_UnicodeToTextContext m_contextUnicode2Text;
+ sal_Bool m_bCanContinue;
+ sal_Bool m_bInitialized;
+ rtl_TextEncoding m_rtlEncoding;
+ ::com::sun::star::uno::Sequence<sal_Unicode> m_seqSource;
+};
+
+
+
+/*----------------------------------------
+*
+* XMLFile2UTFConverter
+*
+**-----------------------------------------*/
+class XMLFile2UTFConverter
+{
+public:
+ XMLFile2UTFConverter( ):
+ m_bStarted( sal_False ),
+ m_pText2Unicode( 0 ),
+ m_pUnicode2Text( 0 )
+ {}
+
+ ~XMLFile2UTFConverter();
+
+ void setInputStream( ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > &r ) { m_in = r; }
+ void setEncoding( const ::rtl::OString &s ) { m_sEncoding = s; }
+
+
+
+ // @param nMaxToRead The number of chars, that should be read. Note that this is no exact number. There
+ // may be returned less or more bytes than ordered.
+ sal_Int32 readAndConvert( ::com::sun::star::uno::Sequence<sal_Int8> &seq , sal_Int32 nMaxToRead )
+ throw ( ::com::sun::star::io::IOException,
+ ::com::sun::star::io::NotConnectedException ,
+ ::com::sun::star::io::BufferSizeExceededException ,
+ ::com::sun::star::uno::RuntimeException );
+
+private:
+
+ // Called only on first Sequence of bytes. Tries to figure out file format and encoding information.
+ // @return TRUE, when encoding information could be retrieved
+ // @return FALSE, when no encoding information was found in file
+ sal_Bool scanForEncoding( ::com::sun::star::uno::Sequence<sal_Int8> &seq );
+
+ // Called only on first Sequence of bytes. Tries to figure out
+ // if enough data is available to scan encoding
+ // @return TRUE, when encoding is retrievable
+ // @return FALSE, when more data is needed
+ sal_Bool isEncodingRecognizable( const ::com::sun::star::uno::Sequence< sal_Int8 > & seq );
+
+ // When encoding attribute is within the text (in the first line), it is removed.
+ void removeEncoding( ::com::sun::star::uno::Sequence<sal_Int8> &seq );
+
+ // Initializes decoding depending on m_sEncoding setting
+ void initializeDecoding();
+private:
+ ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > m_in;
+
+ sal_Bool m_bStarted;
+ ::rtl::OString m_sEncoding;
+
+ Text2UnicodeConverter *m_pText2Unicode;
+ Unicode2TextConverter *m_pUnicode2Text;
+};
+}
diff --git a/sax/prj/build.lst b/sax/prj/build.lst
new file mode 100644
index 000000000000..653d77ce9e25
--- /dev/null
+++ b/sax/prj/build.lst
@@ -0,0 +1,6 @@
+ax sax : offapi cppuhelper EXPAT:expat comphelper NULL
+ax sax usr1 - all ax_mkout NULL
+ax sax\source\expatwrap nmake - all ax_expatwrap NULL
+ax sax\source\tools nmake - all ax_tools NULL
+ax sax\source\fastparser nmake - all ax_fastparser ax_expatwrap ax_tools NULL
+ax sax\qa\cppunit nmake - all ax_qa_cppunit ax_tools NULL
diff --git a/sax/prj/d.lst b/sax/prj/d.lst
new file mode 100644
index 000000000000..87f01348163c
--- /dev/null
+++ b/sax/prj/d.lst
@@ -0,0 +1,13 @@
+..\%__SRC%\bin\*.dll %_DEST%\bin%_EXT%\*.dll
+..\%__SRC%\lib\*.so %_DEST%\lib%_EXT%\*.so
+..\%__SRC%\lib\*.dylib %_DEST%\lib%_EXT%\*.dylib
+..\%__SRC%\lib\*.lib %_DEST%\lib%_EXT%\*.lib
+
+mkdir: %_DEST%\inc%_EXT%\sax
+mkdir: %_DEST%\inc%_EXT%\sax\tools
+..\inc\sax\dllapi.h %_DEST%\inc%_EXT%\sax\dllapi.h
+..\inc\sax\fshelper.hxx %_DEST%\inc%_EXT%\sax\fshelper.hxx
+..\inc\sax\fastattribs.hxx %_DEST%\inc%_EXT%\sax\fastattribs.hxx
+..\inc\sax\tools\converter.hxx %_DEST%\inc%_EXT%\sax\tools\converter.hxx
+
+dos: sh -c "if test %OS% = MACOSX; then macosx-create-bundle %_DEST%\lib%_EXT%\*.dylib; fi"
diff --git a/sax/qa/cppunit/makefile.mk b/sax/qa/cppunit/makefile.mk
new file mode 100644
index 000000000000..e06eca25a737
--- /dev/null
+++ b/sax/qa/cppunit/makefile.mk
@@ -0,0 +1,71 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=../..
+PRJNAME=sax
+TARGET=qa_cppunit
+
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+CFLAGSCXX += $(CPPUNIT_CFLAGS)
+DLLPRE = # no leading "lib" on .so files
+
+# --- Libs ---------------------------------------------------------
+
+SHL1OBJS= \
+ $(SLO)/test_converter.obj \
+
+
+SHL1STDLIBS= \
+ $(SAXLIB) \
+ $(SALLIB) \
+ $(CPPUNITLIB) \
+
+
+SHL1TARGET= test_converter
+SHL1RPATH = NONE
+SHL1IMPLIB= i$(SHL1TARGET)
+# SHL1DEF= $(MISC)/$(SHL1TARGET).def
+DEF1NAME=$(SHL1TARGET)
+# DEF1EXPORTFILE= export.exp
+SHL1VERSIONMAP= version.map
+
+# --- All object files ---------------------------------------------
+
+SLOFILES= \
+ $(SHL1OBJS) \
+
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+.INCLUDE : _cppunit.mk
+
diff --git a/sax/qa/cppunit/test_converter.cxx b/sax/qa/cppunit/test_converter.cxx
new file mode 100644
index 000000000000..1ea781afff95
--- /dev/null
+++ b/sax/qa/cppunit/test_converter.cxx
@@ -0,0 +1,244 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <rtl/ustrbuf.hxx>
+
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/Duration.hpp>
+
+#include "sax/tools/converter.hxx"
+
+
+using namespace ::com::sun::star;
+using sax::Converter;
+
+
+namespace {
+
+class ConverterTest
+ : public ::CppUnit::TestFixture
+{
+public:
+ virtual void setUp();
+ virtual void tearDown();
+
+ void testDuration();
+ void testDateTime();
+
+ CPPUNIT_TEST_SUITE(ConverterTest);
+ CPPUNIT_TEST(testDuration);
+ CPPUNIT_TEST(testDateTime);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+};
+
+void ConverterTest::setUp()
+{
+}
+
+void ConverterTest::tearDown()
+{
+}
+
+static bool eqDuration(util::Duration a, util::Duration b) {
+ return a.Years == b.Years && a.Months == b.Months && a.Days == b.Days
+ && a.Hours == b.Hours && a.Minutes == b.Minutes
+ && a.Seconds == b.Seconds
+ && a.MilliSeconds == b.MilliSeconds
+ && a.Negative == b.Negative;
+}
+
+static void doTest(util::Duration const & rid, char const*const pis,
+ char const*const i_pos = 0)
+{
+ char const*const pos((i_pos) ? i_pos : pis);
+ util::Duration od;
+ ::rtl::OUString is(::rtl::OUString::createFromAscii(pis));
+ bool bSuccess = Converter::convertDuration(od, is);
+ OSL_TRACE("%d %dY %dM %dD %dH %dM %dS %dm",
+ od.Negative, od.Years, od.Months, od.Days,
+ od.Hours, od.Minutes, od.Seconds, od.MilliSeconds);
+ CPPUNIT_ASSERT(bSuccess);
+ CPPUNIT_ASSERT(eqDuration(rid, od));
+ ::rtl::OUStringBuffer buf;
+ Converter::convertDuration(buf, od);
+ OSL_TRACE(
+ ::rtl::OUStringToOString(buf.getStr(), RTL_TEXTENCODING_UTF8));
+ CPPUNIT_ASSERT(buf.makeStringAndClear().equalsAscii(pos));
+}
+
+static void doTestDurationF(char const*const pis)
+{
+ util::Duration od;
+ bool bSuccess = Converter::convertDuration(od,
+ ::rtl::OUString::createFromAscii(pis));
+ OSL_TRACE("%d %dY %dM %dD %dH %dM %dS %dH",
+ od.Negative, od.Years, od.Months, od.Days,
+ od.Hours, od.Minutes, od.Seconds, od.MilliSeconds);
+ CPPUNIT_ASSERT(!bSuccess);
+}
+
+void ConverterTest::testDuration()
+{
+ OSL_TRACE("\nSAX CONVERTER TEST BEGIN\n");
+ doTest( util::Duration(false, 1, 0, 0, 0, 0, 0, 0), "P1Y" );
+ doTest( util::Duration(false, 0, 42, 0, 0, 0, 0, 0), "P42M" );
+ doTest( util::Duration(false, 0, 0, 111, 0, 0, 0, 0), "P111D" );
+ doTest( util::Duration(false, 0, 0, 0, 52, 0, 0, 0), "PT52H" );
+ doTest( util::Duration(false, 0, 0, 0, 0, 717, 0, 0), "PT717M" );
+ doTest( util::Duration(false, 0, 0, 0, 0, 0, 121, 0), "PT121S" );
+ doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 190), "PT0.19S" );
+ doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 90), "PT0.09S" );
+ doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 9), "PT0.009S" );
+ doTest( util::Duration(false, 0, 0, 0, 0, 0, 9, 999),
+ "PT9.999999999999999999999999999999S", "PT9.999S" );
+ doTest( util::Duration(true , 0, 0, 9999, 0, 0, 0, 0), "-P9999D" );
+ doTest( util::Duration(true , 7, 6, 5, 4, 3, 2, 10),
+ "-P7Y6M5DT4H3M2.01S" );
+ doTest( util::Duration(false, 0, 6, 0, 0, 3, 0, 0), "P6MT3M" );
+ doTest( util::Duration(false, 0, 0, 0, 0, 0, 0, 0), "P0D" );
+ doTestDurationF("1Y1M"); // invalid: no ^P
+ doTestDurationF("P-1Y1M"); // invalid: - after P
+ doTestDurationF("P1M1Y"); // invalid: Y after M
+ doTestDurationF("PT1Y"); // invalid: Y after T
+ doTestDurationF("P1Y1M1M"); // invalid: M twice, no T
+ doTestDurationF("P1YT1MT1M"); // invalid: T twice
+ doTestDurationF("P1YT"); // invalid: T but no H,M,S
+ doTestDurationF("P99999999999Y"); // cannot parse so many Ys
+ doTestDurationF("PT.1S"); // invalid: no 0 preceding .
+ doTestDurationF("PT5M.134S"); // invalid: no 0 preceding .
+ doTestDurationF("PT1.S"); // invalid: no digit following .
+ OSL_TRACE("\nSAX CONVERTER TEST END\n");
+}
+
+
+static bool eqDateTime(util::DateTime a, util::DateTime b) {
+ return a.Year == b.Year && a.Month == b.Month && a.Day == b.Day
+ && a.Hours == b.Hours && a.Minutes == b.Minutes
+ && a.Seconds == b.Seconds
+ && a.HundredthSeconds == b.HundredthSeconds;
+}
+
+static void doTest(util::DateTime const & rdt, char const*const pis,
+ char const*const i_pos = 0)
+{
+ char const*const pos((i_pos) ? i_pos : pis);
+ ::rtl::OUString is(::rtl::OUString::createFromAscii(pis));
+ util::DateTime odt;
+ bool bSuccess( Converter::convertDateTime(odt, is) );
+ OSL_TRACE("Y:%d M:%d D:%d H:%d M:%d S:%d H:%d",
+ odt.Year, odt.Month, odt.Day,
+ odt.Hours, odt.Minutes, odt.Seconds, odt.HundredthSeconds);
+ CPPUNIT_ASSERT(bSuccess);
+ CPPUNIT_ASSERT(eqDateTime(rdt, odt));
+ ::rtl::OUStringBuffer buf;
+ Converter::convertDateTime(buf, odt, true);
+ OSL_TRACE(
+ ::rtl::OUStringToOString(buf.getStr(), RTL_TEXTENCODING_UTF8));
+ CPPUNIT_ASSERT(buf.makeStringAndClear().equalsAscii(pos));
+}
+
+static void doTestDateTimeF(char const*const pis)
+{
+ util::DateTime odt;
+ bool bSuccess = Converter::convertDateTime(odt,
+ ::rtl::OUString::createFromAscii(pis));
+ OSL_TRACE("Y:%d M:%d D:%d H:%dH M:%d S:%d H:%d",
+ odt.Year, odt.Month, odt.Day,
+ odt.Hours, odt.Minutes, odt.Seconds, odt.HundredthSeconds);
+ CPPUNIT_ASSERT(!bSuccess);
+}
+
+void ConverterTest::testDateTime()
+{
+ OSL_TRACE("\nSAX CONVERTER TEST BEGIN\n");
+ doTest( util::DateTime(0, 0, 0, 0, 1, 1, 1), "0001-01-01T00:00:00" );
+ doTest( util::DateTime(0, 0, 0, 0, 1, 1, 1),
+ "0001-01-01T00:00:00Z", "0001-01-01T00:00:00" );
+// doTest( util::DateTime(0, 0, 0, 0, 1, 1, -1), "-0001-01-01T00:00:00" );
+// doTest( util::DateTime(0, 0, 0, 0, 1, 1, -1), "-0001-01-01T00:00:00Z" );
+ doTest( util::DateTime(0, 0, 0, 0, 1, 1, 1),
+ "0001-01-01T00:00:00-00:00", "0001-01-01T00:00:00" );
+ doTest( util::DateTime(0, 0, 0, 0, 1, 1, 1),
+ "0001-01-01T00:00:00+00:00", "0001-01-01T00:00:00" );
+ doTest( util::DateTime(0, 0, 0, 0, 2, 1, 1)/*(0, 0, 12, 0, 2, 1, 1)*/,
+ "0001-01-02T00:00:00-12:00", "0001-01-02T00:00:00" );
+// "0001-02-01T12:00:00" );
+ doTest( util::DateTime(0, 0, 0, 0, 2, 1, 1)/*(0, 0, 12, 0, 1, 1, 1)*/,
+ "0001-01-02T00:00:00+12:00", "0001-01-02T00:00:00" );
+// "0001-01-01T12:00:00" );
+ doTest( util::DateTime(99, 59, 59, 23, 31, 12, 9999),
+ "9999-12-31T23:59:59.99" );
+ doTest( util::DateTime(99, 59, 59, 23, 31, 12, 9999),
+ "9999-12-31T23:59:59.99Z", "9999-12-31T23:59:59.99" );
+ doTest( util::DateTime(99, 59, 59, 23, 31, 12, 9999),
+ "9999-12-31T23:59:59.9999999999999999999999999999999999999",
+ "9999-12-31T23:59:59.99" );
+ doTest( util::DateTime(99, 59, 59, 23, 31, 12, 9999),
+ "9999-12-31T23:59:59.9999999999999999999999999999999999999Z",
+ "9999-12-31T23:59:59.99" );
+ doTest( util::DateTime(0, 0, 0, 24, 1, 1, 333)
+ /*(0, 0, 0, 0, 2, 1, 333)*/,
+ "0333-01-01T24:00:00"/*, "0333-01-02T00:00:00"*/ );
+ doTestDateTimeF( "+0001-01-01T00:00:00" ); // invalid: ^+
+ doTestDateTimeF( "1-01-01T00:00:00" ); // invalid: < 4 Y
+ doTestDateTimeF( "0001-1-01T00:00:00" ); // invalid: < 2 M
+ doTestDateTimeF( "0001-01-1T00:00:00" ); // invalid: < 2 D
+ doTestDateTimeF( "0001-01-01T0:00:00" ); // invalid: < 2 H
+ doTestDateTimeF( "0001-01-01T00:0:00" ); // invalid: < 2 M
+ doTestDateTimeF( "0001-01-01T00:00:0" ); // invalid: < 2 S
+ doTestDateTimeF( "0001-01-01T00:00:00." ); // invalid: .$
+ doTestDateTimeF( "0001-01-01T00:00:00+1:00" ); // invalid: < 2 TZ H
+ doTestDateTimeF( "0001-01-01T00:00:00+00:1" ); // invalid: < 2 TZ M
+ doTestDateTimeF( "0001-13-01T00:00:00" ); // invalid: M > 12
+ doTestDateTimeF( "0001-01-32T00:00:00" ); // invalid: D > 31
+ doTestDateTimeF( "0001-01-01T25:00:00" ); // invalid: H > 24
+ doTestDateTimeF( "0001-01-01T00:60:00" ); // invalid: H > 59
+ doTestDateTimeF( "0001-01-01T00:00:60" ); // invalid: S > 59
+ doTestDateTimeF( "0001-01-01T24:01:00" ); // invalid: H=24, but M != 0
+ doTestDateTimeF( "0001-01-01T24:00:01" ); // invalid: H=24, but S != 0
+ doTestDateTimeF( "0001-01-01T24:00:00.1" ); // invalid: H=24, but H != 0
+ doTestDateTimeF( "0001-01-02T00:00:00+15:00" ); // invalid: TZ > +14:00
+ doTestDateTimeF( "0001-01-02T00:00:00+14:01" ); // invalid: TZ > +14:00
+ doTestDateTimeF( "0001-01-02T00:00:00-15:00" ); // invalid: TZ < -14:00
+ doTestDateTimeF( "0001-01-02T00:00:00-14:01" ); // invalid: TZ < -14:00
+ OSL_TRACE("\nSAX CONVERTER TEST END\n");
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ConverterTest);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
diff --git a/sax/qa/cppunit/version.map b/sax/qa/cppunit/version.map
new file mode 100644
index 000000000000..3308588ef6f8
--- /dev/null
+++ b/sax/qa/cppunit/version.map
@@ -0,0 +1,34 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+UDK_3_0_0 {
+ global:
+ cppunitTestPlugIn;
+
+ local:
+ *;
+};
diff --git a/sax/source/expatwrap/attrlistimpl.cxx b/sax/source/expatwrap/attrlistimpl.cxx
new file mode 100644
index 000000000000..114eb653f648
--- /dev/null
+++ b/sax/source/expatwrap/attrlistimpl.cxx
@@ -0,0 +1,168 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "attrlistimpl.hxx"
+
+#include <vector>
+
+#include <cppuhelper/weak.hxx>
+
+using namespace ::std;
+using namespace ::rtl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::xml::sax;
+
+
+namespace sax_expatwrap {
+struct TagAttribute
+{
+ TagAttribute()
+ {}
+ TagAttribute( const OUString &aName, const OUString &aType , const OUString &aValue )
+ {
+ this->sName = aName;
+ this->sType = aType;
+ this->sValue = aValue;
+ }
+
+ OUString sName;
+ OUString sType;
+ OUString sValue;
+};
+
+struct AttributeList_impl
+{
+ AttributeList_impl()
+ {
+ // performance improvement during adding
+ vecAttribute.reserve(20);
+ }
+ vector<struct TagAttribute> vecAttribute;
+};
+
+
+
+sal_Int16 AttributeList::getLength(void) throw (RuntimeException)
+{
+ return static_cast<sal_Int16>(m_pImpl->vecAttribute.size());
+}
+
+
+AttributeList::AttributeList( const AttributeList &r ) :
+ cppu::WeakImplHelper2<XAttributeList, XCloneable>()
+{
+ m_pImpl = new AttributeList_impl;
+ *m_pImpl = *(r.m_pImpl);
+}
+
+OUString AttributeList::getNameByIndex(sal_Int16 i) throw (RuntimeException)
+{
+ if( std::vector< TagAttribute >::size_type(i) < m_pImpl->vecAttribute.size() ) {
+ return m_pImpl->vecAttribute[i].sName;
+ }
+ return OUString();
+}
+
+
+OUString AttributeList::getTypeByIndex(sal_Int16 i) throw (RuntimeException)
+{
+ if( std::vector< TagAttribute >::size_type(i) < m_pImpl->vecAttribute.size() ) {
+ return m_pImpl->vecAttribute[i].sType;
+ }
+ return OUString();
+}
+
+OUString AttributeList::getValueByIndex(sal_Int16 i) throw (RuntimeException)
+{
+ if( std::vector< TagAttribute >::size_type(i) < m_pImpl->vecAttribute.size() ) {
+ return m_pImpl->vecAttribute[i].sValue;
+ }
+ return OUString();
+
+}
+
+OUString AttributeList::getTypeByName( const OUString& sName ) throw (RuntimeException)
+{
+ vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin();
+
+ for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
+ if( (*ii).sName == sName ) {
+ return (*ii).sType;
+ }
+ }
+ return OUString();
+}
+
+OUString AttributeList::getValueByName(const OUString& sName) throw (RuntimeException)
+{
+ vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin();
+
+ for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
+ if( (*ii).sName == sName ) {
+ return (*ii).sValue;
+ }
+ }
+ return OUString();
+}
+
+
+Reference< XCloneable > AttributeList::createClone() throw (RuntimeException)
+{
+ AttributeList *p = new AttributeList( *this );
+ return Reference< XCloneable > ( (XCloneable * ) p );
+}
+
+
+
+AttributeList::AttributeList()
+{
+ m_pImpl = new AttributeList_impl;
+}
+
+
+
+AttributeList::~AttributeList()
+{
+ delete m_pImpl;
+}
+
+
+void AttributeList::addAttribute( const OUString &sName ,
+ const OUString &sType ,
+ const OUString &sValue )
+{
+ m_pImpl->vecAttribute.push_back( TagAttribute( sName , sType , sValue ) );
+}
+
+void AttributeList::clear()
+{
+ m_pImpl->vecAttribute.clear();
+}
+
+}
diff --git a/sax/source/expatwrap/attrlistimpl.hxx b/sax/source/expatwrap/attrlistimpl.hxx
new file mode 100644
index 000000000000..aaf6cf84b359
--- /dev/null
+++ b/sax/source/expatwrap/attrlistimpl.hxx
@@ -0,0 +1,85 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SAX_ATTRLISTIMPL_HXX
+#define _SAX_ATTRLISTIMPL_HXX
+
+#include "sal/config.h"
+//#include "sax/saxdllapi.h"
+
+#include <cppuhelper/implbase2.hxx>
+
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+
+namespace sax_expatwrap
+{
+
+struct AttributeList_impl;
+
+//FIXME
+class /*SAX_DLLPUBLIC*/ AttributeList :
+ public ::cppu::WeakImplHelper2<
+ ::com::sun::star::xml::sax::XAttributeList,
+ ::com::sun::star::util::XCloneable >
+{
+public:
+ AttributeList();
+ AttributeList( const AttributeList & );
+ virtual ~AttributeList();
+
+ void addAttribute( const ::rtl::OUString &sName ,
+ const ::rtl::OUString &sType , const ::rtl::OUString &sValue );
+ void clear();
+public:
+ // XAttributeList
+ virtual sal_Int16 SAL_CALL getLength(void)
+ throw(::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getNameByIndex(sal_Int16 i)
+ throw(::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getTypeByIndex(sal_Int16 i)
+ throw(::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getTypeByName(const ::rtl::OUString& aName)
+ throw(::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getValueByIndex(sal_Int16 i)
+ throw(::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getValueByName(const ::rtl::OUString& aName)
+ throw( ::com::sun::star::uno::RuntimeException);
+
+ // XCloneable
+ virtual ::com::sun::star::uno::Reference< XCloneable > SAL_CALL
+ createClone() throw(::com::sun::star::uno::RuntimeException);
+
+private:
+ struct AttributeList_impl *m_pImpl;
+};
+
+}
+
+#endif
+
diff --git a/sax/source/expatwrap/factory.hxx b/sax/source/expatwrap/factory.hxx
new file mode 100644
index 000000000000..c6a566781044
--- /dev/null
+++ b/sax/source/expatwrap/factory.hxx
@@ -0,0 +1,34 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+namespace sax_expatwrap {
+Reference< XInterface > SAL_CALL SaxWriter_CreateInstance(
+ const Reference< XMultiServiceFactory > & rSMgr ) throw (Exception);
+OUString SaxWriter_getServiceName() throw();
+OUString SaxWriter_getImplementationName() throw();
+Sequence< OUString > SaxWriter_getSupportedServiceNames(void) throw();
+}
+
diff --git a/sax/source/expatwrap/makefile.mk b/sax/source/expatwrap/makefile.mk
new file mode 100644
index 000000000000..bcb73b0443ac
--- /dev/null
+++ b/sax/source/expatwrap/makefile.mk
@@ -0,0 +1,76 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+PRJ=..$/..
+
+PRJNAME=sax
+TARGET=sax.uno
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+DLLPRE =
+
+.IF "$(SYSTEM_ZLIB)" == "YES"
+CFLAGS+=-DSYSTEM_ZLIB
+.ENDIF
+
+.IF "$(SYSTEM_EXPAT)" == "YES"
+CFLAGS+=-DSYSTEM_EXPAT
+.ELSE
+CFLAGS += -DXML_UNICODE
+.ENDIF
+
+#-----------------------------------------------------------
+
+SLOFILES =\
+ $(SLO)$/xml2utf.obj\
+ $(SLO)$/attrlistimpl.obj\
+ $(SLO)$/sax_expat.obj \
+ $(SLO)$/saxwriter.obj
+
+SHL1TARGET= $(TARGET)
+SHL1IMPLIB= i$(TARGET)
+
+SHL1STDLIBS= \
+ $(SALLIB) \
+ $(CPPULIB) \
+ $(CPPUHELPERLIB)\
+ $(EXPAT3RDLIB)
+
+SHL1DEPN=
+SHL1VERSIONMAP= $(SOLARENV)$/src$/component.map
+SHL1LIBS= $(SLB)$/$(TARGET).lib
+SHL1DEF= $(MISC)$/$(SHL1TARGET).def
+DEF1NAME= $(SHL1TARGET)
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+
+
diff --git a/sax/source/expatwrap/sax_expat.cxx b/sax/source/expatwrap/sax_expat.cxx
new file mode 100644
index 000000000000..4ffebfa3590d
--- /dev/null
+++ b/sax/source/expatwrap/sax_expat.cxx
@@ -0,0 +1,1107 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+#include <sal/alloca.h>
+#include <vector>
+
+#include <osl/diagnose.h>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
+#include <com/sun/star/xml/sax/XParser.hpp>
+#include <com/sun/star/xml/sax/SAXParseException.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/weak.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <cppuhelper/implbase2.hxx>
+
+#include <expat.h>
+
+using namespace ::rtl;
+using namespace ::std;
+using namespace ::osl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::registry;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::io;
+
+#include "factory.hxx"
+#include "attrlistimpl.hxx"
+#include "xml2utf.hxx"
+
+namespace sax_expatwrap {
+
+// Useful macros for correct String conversion depending on the choosen expat-mode
+#ifdef XML_UNICODE
+OUString XmlNChar2OUString( const XML_Char *p , int nLen )
+{
+ if( p ) {
+ if( sizeof( sal_Unicode ) == sizeof( XML_Char ) )
+ {
+ return OUString( (sal_Unicode*)p,nLen);
+ }
+ else
+ {
+ sal_Unicode *pWchar = (sal_Unicode *)alloca( sizeof( sal_Unicode ) * nLen );
+ for( int n = 0 ; n < nLen ; n++ ) {
+ pWchar[n] = (sal_Unicode) p[n];
+ }
+ return OUString( pWchar , nLen );
+ }
+ }
+ else {
+ return OUString();
+ }
+}
+
+OUString XmlChar2OUString( const XML_Char *p )
+{
+ if( p ) {
+ int nLen;
+ for( nLen = 0 ; p[nLen] ; nLen ++ )
+ ;
+ return XmlNChar2OUString( p , nLen );
+ }
+ else return OUString();
+}
+
+
+#define XML_CHAR_TO_OUSTRING(x) XmlChar2OUString(x)
+#define XML_CHAR_N_TO_USTRING(x,n) XmlNChar2OUString(x,n)
+#else
+#define XML_CHAR_TO_OUSTRING(x) OUString(x , strlen( x ), RTL_TEXTENCODING_UTF8)
+#define XML_CHAR_N_TO_USTRING(x,n) OUString(x,n, RTL_TEXTENCODING_UTF8 )
+#endif
+
+
+/*
+* The following macro encapsulates any call to an event handler.
+* It ensures, that exceptions thrown by the event handler are
+* treated properly.
+*/
+#define CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pThis,call) \
+ if( ! pThis->bExceptionWasThrown ) { \
+ try {\
+ pThis->call;\
+ }\
+ catch( SAXParseException &e ) {\
+ pThis->callErrorHandler( pThis , e );\
+ }\
+ catch( SAXException &e ) {\
+ pThis->callErrorHandler( pThis , SAXParseException(\
+ e.Message, \
+ e.Context, \
+ e.WrappedException,\
+ pThis->rDocumentLocator->getPublicId(),\
+ pThis->rDocumentLocator->getSystemId(),\
+ pThis->rDocumentLocator->getLineNumber(),\
+ pThis->rDocumentLocator->getColumnNumber()\
+ ) );\
+ }\
+ catch( com::sun::star::uno::RuntimeException &e ) {\
+ pThis->bExceptionWasThrown = sal_True; \
+ pThis->bRTExceptionWasThrown = sal_True; \
+ pImpl->rtexception = e; \
+ }\
+ }\
+ ((void)0)
+
+#define IMPLEMENTATION_NAME "com.sun.star.comp.extensions.xml.sax.ParserExpat"
+#define SERVICE_NAME "com.sun.star.xml.sax.Parser"
+
+class SaxExpatParser_Impl;
+
+
+// This class implements the external Parser interface
+class SaxExpatParser :
+ public WeakImplHelper2<
+ XParser,
+ XServiceInfo
+ >
+{
+
+public:
+ SaxExpatParser();
+ ~SaxExpatParser();
+
+public:
+
+ // The implementation details
+ static Sequence< OUString > getSupportedServiceNames_Static(void) throw ();
+
+public:
+ // The SAX-Parser-Interface
+ virtual void SAL_CALL parseStream( const InputSource& structSource)
+ throw ( SAXException,
+ IOException,
+ RuntimeException);
+ virtual void SAL_CALL setDocumentHandler(const Reference< XDocumentHandler > & xHandler)
+ throw (RuntimeException);
+
+ virtual void SAL_CALL setErrorHandler(const Reference< XErrorHandler > & xHandler)
+ throw (RuntimeException);
+ virtual void SAL_CALL setDTDHandler(const Reference < XDTDHandler > & xHandler)
+ throw (RuntimeException);
+ virtual void SAL_CALL setEntityResolver(const Reference< XEntityResolver >& xResolver)
+ throw (RuntimeException);
+
+ virtual void SAL_CALL setLocale( const Locale &locale ) throw (RuntimeException);
+
+public: // XServiceInfo
+ OUString SAL_CALL getImplementationName() throw ();
+ Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw ();
+ sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw ();
+
+private:
+
+ SaxExpatParser_Impl *m_pImpl;
+
+};
+
+//--------------------------------------
+// the extern interface
+//---------------------------------------
+Reference< XInterface > SAL_CALL SaxExpatParser_CreateInstance(
+ const Reference< XMultiServiceFactory > & ) throw(Exception)
+{
+ SaxExpatParser *p = new SaxExpatParser;
+
+ return Reference< XInterface > ( (OWeakObject * ) p );
+}
+
+
+
+Sequence< OUString > SaxExpatParser::getSupportedServiceNames_Static(void) throw ()
+{
+ Sequence<OUString> aRet(1);
+ aRet.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(SERVICE_NAME) );
+ return aRet;
+}
+
+
+//---------------------------------------------
+// the implementation part
+//---------------------------------------------
+
+
+// Entity binds all information neede for a single file
+struct Entity
+{
+ InputSource structSource;
+ XML_Parser pParser;
+ XMLFile2UTFConverter converter;
+};
+
+
+class SaxExpatParser_Impl
+{
+public: // module scope
+ Mutex aMutex;
+
+ Reference< XDocumentHandler > rDocumentHandler;
+ Reference< XExtendedDocumentHandler > rExtendedDocumentHandler;
+
+ Reference< XErrorHandler > rErrorHandler;
+ Reference< XDTDHandler > rDTDHandler;
+ Reference< XEntityResolver > rEntityResolver;
+ Reference < XLocator > rDocumentLocator;
+
+
+ Reference < XAttributeList > rAttrList;
+ AttributeList *pAttrList;
+
+ // External entity stack
+ vector<struct Entity> vecEntity;
+ void pushEntity( const struct Entity &entity )
+ { vecEntity.push_back( entity ); }
+ void popEntity()
+ { vecEntity.pop_back( ); }
+ struct Entity &getEntity()
+ { return vecEntity.back(); }
+
+
+ // Exception cannot be thrown through the C-XmlParser (possible resource leaks),
+ // therefor the exception must be saved somewhere.
+ SAXParseException exception;
+ RuntimeException rtexception;
+ sal_Bool bExceptionWasThrown;
+ sal_Bool bRTExceptionWasThrown;
+
+ Locale locale;
+
+public:
+ // the C-Callbacks for the expat parser
+ void static callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts);
+ void static callbackEndElement(void *userData, const XML_Char *name);
+ void static callbackCharacters( void *userData , const XML_Char *s , int nLen );
+ void static callbackProcessingInstruction( void *userData ,
+ const XML_Char *sTarget ,
+ const XML_Char *sData );
+
+ void static callbackUnparsedEntityDecl( void *userData ,
+ const XML_Char *entityName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId,
+ const XML_Char *notationName);
+
+ void static callbackNotationDecl( void *userData,
+ const XML_Char *notationName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId);
+
+ int static callbackExternalEntityRef( XML_Parser parser,
+ const XML_Char *openEntityNames,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId);
+
+ int static callbackUnknownEncoding(void *encodingHandlerData,
+ const XML_Char *name,
+ XML_Encoding *info);
+
+ void static callbackDefault( void *userData, const XML_Char *s, int len);
+
+ void static callbackStartCDATA( void *userData );
+ void static callbackEndCDATA( void *userData );
+ void static callbackComment( void *userData , const XML_Char *s );
+ void static callErrorHandler( SaxExpatParser_Impl *pImpl , const SAXParseException &e );
+
+public:
+ void parse();
+};
+
+extern "C"
+{
+ static void call_callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts)
+ {
+ SaxExpatParser_Impl::callbackStartElement(userData,name,atts);
+ }
+ static void call_callbackEndElement(void *userData, const XML_Char *name)
+ {
+ SaxExpatParser_Impl::callbackEndElement(userData,name);
+ }
+ static void call_callbackCharacters( void *userData , const XML_Char *s , int nLen )
+ {
+ SaxExpatParser_Impl::callbackCharacters(userData,s,nLen);
+ }
+ static void call_callbackProcessingInstruction(void *userData,const XML_Char *sTarget,const XML_Char *sData )
+ {
+ SaxExpatParser_Impl::callbackProcessingInstruction(userData,sTarget,sData );
+ }
+ static void call_callbackUnparsedEntityDecl(void *userData ,
+ const XML_Char *entityName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId,
+ const XML_Char *notationName)
+ {
+ SaxExpatParser_Impl::callbackUnparsedEntityDecl(userData,entityName,base,systemId,publicId,notationName);
+ }
+ static void call_callbackNotationDecl(void *userData,
+ const XML_Char *notationName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId)
+ {
+ SaxExpatParser_Impl::callbackNotationDecl(userData,notationName,base,systemId,publicId);
+ }
+ static int call_callbackExternalEntityRef(XML_Parser parser,
+ const XML_Char *openEntityNames,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId)
+ {
+ return SaxExpatParser_Impl::callbackExternalEntityRef(parser,openEntityNames,base,systemId,publicId);
+ }
+ static int call_callbackUnknownEncoding(void *encodingHandlerData,
+ const XML_Char *name,
+ XML_Encoding *info)
+ {
+ return SaxExpatParser_Impl::callbackUnknownEncoding(encodingHandlerData,name,info);
+ }
+ static void call_callbackDefault( void *userData, const XML_Char *s, int len)
+ {
+ SaxExpatParser_Impl::callbackDefault(userData,s,len);
+ }
+ static void call_callbackStartCDATA( void *userData )
+ {
+ SaxExpatParser_Impl::callbackStartCDATA(userData);
+ }
+ static void call_callbackEndCDATA( void *userData )
+ {
+ SaxExpatParser_Impl::callbackEndCDATA(userData);
+ }
+ static void call_callbackComment( void *userData , const XML_Char *s )
+ {
+ SaxExpatParser_Impl::callbackComment(userData,s);
+ }
+}
+
+
+//---------------------------------------------
+// LocatorImpl
+//---------------------------------------------
+class LocatorImpl :
+ public WeakImplHelper2< XLocator, com::sun::star::io::XSeekable >
+ // should use a different interface for stream positions!
+{
+public:
+ LocatorImpl( SaxExpatParser_Impl *p )
+ {
+ m_pParser = p;
+ }
+
+public: //XLocator
+ virtual sal_Int32 SAL_CALL getColumnNumber(void) throw ()
+ {
+ return XML_GetCurrentColumnNumber( m_pParser->getEntity().pParser );
+ }
+ virtual sal_Int32 SAL_CALL getLineNumber(void) throw ()
+ {
+ return XML_GetCurrentLineNumber( m_pParser->getEntity().pParser );
+ }
+ virtual OUString SAL_CALL getPublicId(void) throw ()
+ {
+ return m_pParser->getEntity().structSource.sPublicId;
+ }
+ virtual OUString SAL_CALL getSystemId(void) throw ()
+ {
+ return m_pParser->getEntity().structSource.sSystemId;
+ }
+
+ // XSeekable (only for getPosition)
+
+ virtual void SAL_CALL seek( sal_Int64 ) throw()
+ {
+ }
+ virtual sal_Int64 SAL_CALL getPosition() throw()
+ {
+ return XML_GetCurrentByteIndex( m_pParser->getEntity().pParser );
+ }
+ virtual ::sal_Int64 SAL_CALL getLength() throw()
+ {
+ return 0;
+ }
+
+private:
+
+ SaxExpatParser_Impl *m_pParser;
+};
+
+
+
+
+SaxExpatParser::SaxExpatParser( )
+{
+ m_pImpl = new SaxExpatParser_Impl;
+
+ LocatorImpl *pLoc = new LocatorImpl( m_pImpl );
+ m_pImpl->rDocumentLocator = Reference< XLocator > ( pLoc );
+
+ // performance-Improvment. Reference is needed when calling the startTag callback.
+ // Handing out the same object with every call is allowed (see sax-specification)
+ m_pImpl->pAttrList = new AttributeList;
+ m_pImpl->rAttrList = Reference< XAttributeList > ( m_pImpl->pAttrList );
+
+ m_pImpl->bExceptionWasThrown = sal_False;
+ m_pImpl->bRTExceptionWasThrown = sal_False;
+}
+
+SaxExpatParser::~SaxExpatParser()
+{
+ delete m_pImpl;
+}
+
+
+/***************
+*
+* parseStream does Parser-startup initializations. The SaxExpatParser_Impl::parse() method does
+* the file-specific initialization work. (During a parser run, external files may be opened)
+*
+****************/
+void SaxExpatParser::parseStream( const InputSource& structSource)
+ throw (SAXException,
+ IOException,
+ RuntimeException)
+{
+ // Only one text at one time
+ MutexGuard guard( m_pImpl->aMutex );
+
+
+ struct Entity entity;
+ entity.structSource = structSource;
+
+ if( ! entity.structSource.aInputStream.is() )
+ {
+ throw SAXException( OUString::createFromAscii( "No input source" ) ,
+ Reference< XInterface > () , Any() );
+ }
+
+ entity.converter.setInputStream( entity.structSource.aInputStream );
+ if( entity.structSource.sEncoding.getLength() )
+ {
+ entity.converter.setEncoding(
+ OUStringToOString( entity.structSource.sEncoding , RTL_TEXTENCODING_ASCII_US ) );
+ }
+
+ // create parser with proper encoding
+ entity.pParser = XML_ParserCreate( 0 );
+ if( ! entity.pParser )
+ {
+ throw SAXException( OUString::createFromAscii( "Couldn't create parser" ) ,
+ Reference< XInterface > (), Any() );
+ }
+
+ // set all necessary C-Callbacks
+ XML_SetUserData( entity.pParser , m_pImpl );
+ XML_SetElementHandler( entity.pParser ,
+ call_callbackStartElement ,
+ call_callbackEndElement );
+ XML_SetCharacterDataHandler( entity.pParser , call_callbackCharacters );
+ XML_SetProcessingInstructionHandler(entity.pParser ,
+ call_callbackProcessingInstruction );
+ XML_SetUnparsedEntityDeclHandler( entity.pParser,
+ call_callbackUnparsedEntityDecl );
+ XML_SetNotationDeclHandler( entity.pParser, call_callbackNotationDecl );
+ XML_SetExternalEntityRefHandler( entity.pParser,
+ call_callbackExternalEntityRef);
+ XML_SetUnknownEncodingHandler( entity.pParser, call_callbackUnknownEncoding ,0);
+
+ if( m_pImpl->rExtendedDocumentHandler.is() ) {
+
+ // These handlers just delegate calls to the ExtendedHandler. If no extended handler is
+ // given, these callbacks can be ignored
+ XML_SetDefaultHandlerExpand( entity.pParser, call_callbackDefault );
+ XML_SetCommentHandler( entity.pParser, call_callbackComment );
+ XML_SetCdataSectionHandler( entity.pParser ,
+ call_callbackStartCDATA ,
+ call_callbackEndCDATA );
+ }
+
+
+ m_pImpl->exception = SAXParseException();
+ m_pImpl->pushEntity( entity );
+ try
+ {
+ // start the document
+ if( m_pImpl->rDocumentHandler.is() ) {
+ m_pImpl->rDocumentHandler->setDocumentLocator( m_pImpl->rDocumentLocator );
+ m_pImpl->rDocumentHandler->startDocument();
+ }
+
+ m_pImpl->parse();
+
+ // finish document
+ if( m_pImpl->rDocumentHandler.is() ) {
+ m_pImpl->rDocumentHandler->endDocument();
+ }
+ }
+// catch( SAXParseException &e )
+// {
+// m_pImpl->popEntity();
+// XML_ParserFree( entity.pParser );
+// Any aAny;
+// aAny <<= e;
+// throw SAXException( e.Message, e.Context, aAny );
+// }
+ catch( SAXException & )
+ {
+ m_pImpl->popEntity();
+ XML_ParserFree( entity.pParser );
+ throw;
+ }
+ catch( IOException & )
+ {
+ m_pImpl->popEntity();
+ XML_ParserFree( entity.pParser );
+ throw;
+ }
+ catch( RuntimeException & )
+ {
+ m_pImpl->popEntity();
+ XML_ParserFree( entity.pParser );
+ throw;
+ }
+
+ m_pImpl->popEntity();
+ XML_ParserFree( entity.pParser );
+}
+
+void SaxExpatParser::setDocumentHandler(const Reference< XDocumentHandler > & xHandler)
+ throw (RuntimeException)
+{
+ m_pImpl->rDocumentHandler = xHandler;
+ m_pImpl->rExtendedDocumentHandler =
+ Reference< XExtendedDocumentHandler >( xHandler , UNO_QUERY );
+}
+
+void SaxExpatParser::setErrorHandler(const Reference< XErrorHandler > & xHandler)
+ throw (RuntimeException)
+{
+ m_pImpl->rErrorHandler = xHandler;
+}
+
+void SaxExpatParser::setDTDHandler(const Reference< XDTDHandler > & xHandler)
+ throw (RuntimeException)
+{
+ m_pImpl->rDTDHandler = xHandler;
+}
+
+void SaxExpatParser::setEntityResolver(const Reference < XEntityResolver > & xResolver)
+ throw (RuntimeException)
+{
+ m_pImpl->rEntityResolver = xResolver;
+}
+
+
+void SaxExpatParser::setLocale( const Locale & locale ) throw (RuntimeException)
+{
+ m_pImpl->locale = locale;
+}
+
+// XServiceInfo
+OUString SaxExpatParser::getImplementationName() throw ()
+{
+ return OUString::createFromAscii( IMPLEMENTATION_NAME );
+}
+
+// XServiceInfo
+sal_Bool SaxExpatParser::supportsService(const OUString& ServiceName) throw ()
+{
+ 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 > SaxExpatParser::getSupportedServiceNames(void) throw ()
+{
+
+ Sequence<OUString> seq(1);
+ seq.getArray()[0] = OUString::createFromAscii( SERVICE_NAME );
+ return seq;
+}
+
+
+/*---------------------------------------
+*
+* Helper functions and classes
+*
+*
+*-------------------------------------------*/
+OUString getErrorMessage( XML_Error xmlE, OUString sSystemId , sal_Int32 nLine )
+{
+ OUString Message;
+ if( XML_ERROR_NONE == xmlE ) {
+ Message = OUString::createFromAscii( "No" );
+ }
+ else if( XML_ERROR_NO_MEMORY == xmlE ) {
+ Message = OUString::createFromAscii( "no memory" );
+ }
+ else if( XML_ERROR_SYNTAX == xmlE ) {
+ Message = OUString::createFromAscii( "syntax" );
+ }
+ else if( XML_ERROR_NO_ELEMENTS == xmlE ) {
+ Message = OUString::createFromAscii( "no elements" );
+ }
+ else if( XML_ERROR_INVALID_TOKEN == xmlE ) {
+ Message = OUString::createFromAscii( "invalid token" );
+ }
+ else if( XML_ERROR_UNCLOSED_TOKEN == xmlE ) {
+ Message = OUString::createFromAscii( "unclosed token" );
+ }
+ else if( XML_ERROR_PARTIAL_CHAR == xmlE ) {
+ Message = OUString::createFromAscii( "partial char" );
+ }
+ else if( XML_ERROR_TAG_MISMATCH == xmlE ) {
+ Message = OUString::createFromAscii( "tag mismatch" );
+ }
+ else if( XML_ERROR_DUPLICATE_ATTRIBUTE == xmlE ) {
+ Message = OUString::createFromAscii( "duplicate attribute" );
+ }
+ else if( XML_ERROR_JUNK_AFTER_DOC_ELEMENT == xmlE ) {
+ Message = OUString::createFromAscii( "junk after doc element" );
+ }
+ else if( XML_ERROR_PARAM_ENTITY_REF == xmlE ) {
+ Message = OUString::createFromAscii( "parameter entity reference" );
+ }
+ else if( XML_ERROR_UNDEFINED_ENTITY == xmlE ) {
+ Message = OUString::createFromAscii( "undefined entity" );
+ }
+ else if( XML_ERROR_RECURSIVE_ENTITY_REF == xmlE ) {
+ Message = OUString::createFromAscii( "recursive entity reference" );
+ }
+ else if( XML_ERROR_ASYNC_ENTITY == xmlE ) {
+ Message = OUString::createFromAscii( "async entity" );
+ }
+ else if( XML_ERROR_BAD_CHAR_REF == xmlE ) {
+ Message = OUString::createFromAscii( "bad char reference" );
+ }
+ else if( XML_ERROR_BINARY_ENTITY_REF == xmlE ) {
+ Message = OUString::createFromAscii( "binary entity reference" );
+ }
+ else if( XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF == xmlE ) {
+ Message = OUString::createFromAscii( "attribute external entity reference" );
+ }
+ else if( XML_ERROR_MISPLACED_XML_PI == xmlE ) {
+ Message = OUString::createFromAscii( "misplaced xml processing instruction" );
+ }
+ else if( XML_ERROR_UNKNOWN_ENCODING == xmlE ) {
+ Message = OUString::createFromAscii( "unknown encoding" );
+ }
+ else if( XML_ERROR_INCORRECT_ENCODING == xmlE ) {
+ Message = OUString::createFromAscii( "incorrect encoding" );
+ }
+ else if( XML_ERROR_UNCLOSED_CDATA_SECTION == xmlE ) {
+ Message = OUString::createFromAscii( "unclosed cdata section" );
+ }
+ else if( XML_ERROR_EXTERNAL_ENTITY_HANDLING == xmlE ) {
+ Message = OUString::createFromAscii( "external entity reference" );
+ }
+ else if( XML_ERROR_NOT_STANDALONE == xmlE ) {
+ Message = OUString::createFromAscii( "not standalone" );
+ }
+
+ OUString str = OUString::createFromAscii( "[" );
+ str += sSystemId;
+ str += OUString::createFromAscii( " line " );
+ str += OUString::valueOf( nLine );
+ str += OUString::createFromAscii( "]: " );
+ str += Message;
+ str += OUString::createFromAscii( "error" );
+
+ return str;
+}
+
+
+// starts parsing with actual parser !
+void SaxExpatParser_Impl::parse( )
+{
+ const int nBufSize = 16*1024;
+
+ int nRead = nBufSize;
+ Sequence< sal_Int8 > seqOut(nBufSize);
+
+ while( nRead ) {
+ nRead = getEntity().converter.readAndConvert( seqOut , nBufSize );
+
+ if( ! nRead ) {
+ XML_Parse( getEntity().pParser ,
+ ( const char * ) seqOut.getArray() ,
+ 0 ,
+ 1 );
+ break;
+ }
+
+ sal_Bool bContinue = ( XML_Parse( getEntity().pParser ,
+ (const char *) seqOut.getArray(),
+ nRead,
+ 0 ) != 0 );
+
+ if( ! bContinue || this->bExceptionWasThrown ) {
+
+ if ( this->bRTExceptionWasThrown )
+ throw rtexception;
+
+ // Error during parsing !
+ XML_Error xmlE = XML_GetErrorCode( getEntity().pParser );
+ OUString sSystemId = rDocumentLocator->getSystemId();
+ sal_Int32 nLine = rDocumentLocator->getLineNumber();
+
+ SAXParseException aExcept(
+ getErrorMessage(xmlE , sSystemId, nLine) ,
+ Reference< XInterface >(),
+ Any( &exception , getCppuType( &exception) ),
+ rDocumentLocator->getPublicId(),
+ rDocumentLocator->getSystemId(),
+ rDocumentLocator->getLineNumber(),
+ rDocumentLocator->getColumnNumber()
+ );
+
+ if( rErrorHandler.is() ) {
+
+ // error handler is set, so the handler may throw the exception
+ Any a;
+ a <<= aExcept;
+ rErrorHandler->fatalError( a );
+ }
+
+ // Error handler has not thrown an exception, but parsing cannot go on,
+ // so an exception MUST be thrown.
+ throw aExcept;
+ } // if( ! bContinue )
+ } // while
+}
+
+//------------------------------------------
+//
+// The C-Callbacks
+//
+//-----------------------------------------
+void SaxExpatParser_Impl::callbackStartElement( void *pvThis ,
+ const XML_Char *pwName ,
+ const XML_Char **awAttributes )
+{
+ // in case of two concurrent threads, there is only the danger of an leak,
+ // which is neglectable for one string
+ static OUString g_CDATA( RTL_CONSTASCII_USTRINGPARAM( "CDATA" ) );
+
+ SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
+
+ if( pImpl->rDocumentHandler.is() ) {
+
+ int i = 0;
+ pImpl->pAttrList->clear();
+
+ while( awAttributes[i] ) {
+ OSL_ASSERT( awAttributes[i+1] );
+ pImpl->pAttrList->addAttribute(
+ XML_CHAR_TO_OUSTRING( awAttributes[i] ) ,
+ g_CDATA , // expat doesn't know types
+ XML_CHAR_TO_OUSTRING( awAttributes[i+1] ) );
+ i +=2;
+ }
+
+ CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
+ pImpl ,
+ rDocumentHandler->startElement( XML_CHAR_TO_OUSTRING( pwName ) ,
+ pImpl->rAttrList ) );
+ }
+}
+
+void SaxExpatParser_Impl::callbackEndElement( void *pvThis , const XML_Char *pwName )
+{
+ SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
+
+ if( pImpl->rDocumentHandler.is() ) {
+ CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
+ rDocumentHandler->endElement( XML_CHAR_TO_OUSTRING( pwName ) ) );
+ }
+}
+
+
+void SaxExpatParser_Impl::callbackCharacters( void *pvThis , const XML_Char *s , int nLen )
+{
+ SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
+
+ if( pImpl->rDocumentHandler.is() ) {
+ CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl ,
+ rDocumentHandler->characters( XML_CHAR_N_TO_USTRING(s,nLen) ) );
+ }
+}
+
+void SaxExpatParser_Impl::callbackProcessingInstruction( void *pvThis,
+ const XML_Char *sTarget ,
+ const XML_Char *sData )
+{
+ SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
+ if( pImpl->rDocumentHandler.is() ) {
+ CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
+ pImpl ,
+ rDocumentHandler->processingInstruction( XML_CHAR_TO_OUSTRING( sTarget ),
+ XML_CHAR_TO_OUSTRING( sData ) ) );
+ }
+}
+
+
+void SaxExpatParser_Impl::callbackUnparsedEntityDecl(void *pvThis ,
+ const XML_Char *entityName,
+ const XML_Char * /*base*/,
+ const XML_Char *systemId,
+ const XML_Char *publicId,
+ const XML_Char *notationName)
+{
+ SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
+ if( pImpl->rDTDHandler.is() ) {
+ CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
+ pImpl ,
+ rDTDHandler->unparsedEntityDecl(
+ XML_CHAR_TO_OUSTRING( entityName ),
+ XML_CHAR_TO_OUSTRING( publicId ) ,
+ XML_CHAR_TO_OUSTRING( systemId ) ,
+ XML_CHAR_TO_OUSTRING( notationName ) ) );
+ }
+}
+
+void SaxExpatParser_Impl::callbackNotationDecl( void *pvThis,
+ const XML_Char *notationName,
+ const XML_Char * /*base*/,
+ const XML_Char *systemId,
+ const XML_Char *publicId)
+{
+ SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
+ if( pImpl->rDTDHandler.is() ) {
+ CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
+ rDTDHandler->notationDecl( XML_CHAR_TO_OUSTRING( notationName ) ,
+ XML_CHAR_TO_OUSTRING( publicId ) ,
+ XML_CHAR_TO_OUSTRING( systemId ) ) );
+ }
+
+}
+
+
+
+int SaxExpatParser_Impl::callbackExternalEntityRef( XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char * /*base*/,
+ const XML_Char *systemId,
+ const XML_Char *publicId)
+{
+ sal_Bool bOK = sal_True;
+ InputSource source;
+ SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)XML_GetUserData( parser ));
+
+ struct Entity entity;
+
+ if( pImpl->rEntityResolver.is() ) {
+ try
+ {
+ entity.structSource = pImpl->rEntityResolver->resolveEntity(
+ XML_CHAR_TO_OUSTRING( publicId ) ,
+ XML_CHAR_TO_OUSTRING( systemId ) );
+ }
+ catch( SAXParseException & e )
+ {
+ pImpl->exception = e;
+ bOK = sal_False;
+ }
+ catch( SAXException & e )
+ {
+ pImpl->exception = SAXParseException(
+ e.Message , e.Context , e.WrappedException ,
+ pImpl->rDocumentLocator->getPublicId(),
+ pImpl->rDocumentLocator->getSystemId(),
+ pImpl->rDocumentLocator->getLineNumber(),
+ pImpl->rDocumentLocator->getColumnNumber() );
+ bOK = sal_False;
+ }
+ }
+
+ if( entity.structSource.aInputStream.is() ) {
+ entity.pParser = XML_ExternalEntityParserCreate( parser , context, 0 );
+ if( ! entity.pParser )
+ {
+ return sal_False;
+ }
+
+ entity.converter.setInputStream( entity.structSource.aInputStream );
+ pImpl->pushEntity( entity );
+ try
+ {
+ pImpl->parse();
+ }
+ catch( SAXParseException & e )
+ {
+ pImpl->exception = e;
+ bOK = sal_False;
+ }
+ catch( IOException &e )
+ {
+ pImpl->exception.WrappedException <<= e;
+ bOK = sal_False;
+ }
+ catch( RuntimeException &e )
+ {
+ pImpl->exception.WrappedException <<=e;
+ bOK = sal_False;
+ }
+
+ pImpl->popEntity();
+
+ XML_ParserFree( entity.pParser );
+ }
+
+ return bOK;
+}
+
+int SaxExpatParser_Impl::callbackUnknownEncoding(void * /*encodingHandlerData*/,
+ const XML_Char * /*name*/,
+ XML_Encoding * /*info*/)
+{
+ return 0;
+}
+
+void SaxExpatParser_Impl::callbackDefault( void *pvThis, const XML_Char *s, int len)
+{
+ SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
+
+ CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
+ rExtendedDocumentHandler->unknown( XML_CHAR_N_TO_USTRING( s ,len) ) );
+}
+
+void SaxExpatParser_Impl::callbackComment( void *pvThis , const XML_Char *s )
+{
+ SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
+ CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
+ rExtendedDocumentHandler->comment( XML_CHAR_TO_OUSTRING( s ) ) );
+}
+
+void SaxExpatParser_Impl::callbackStartCDATA( void *pvThis )
+{
+ SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
+
+ CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl, rExtendedDocumentHandler->startCDATA() );
+}
+
+
+void SaxExpatParser_Impl::callErrorHandler( SaxExpatParser_Impl *pImpl ,
+ const SAXParseException & e )
+{
+ try
+ {
+ if( pImpl->rErrorHandler.is() ) {
+ Any a;
+ a <<= e;
+ pImpl->rErrorHandler->error( a );
+ }
+ else {
+ pImpl->exception = e;
+ pImpl->bExceptionWasThrown = sal_True;
+ }
+ }
+ catch( SAXParseException & ex ) {
+ pImpl->exception = ex;
+ pImpl->bExceptionWasThrown = sal_True;
+ }
+ catch( SAXException & ex ) {
+ pImpl->exception = SAXParseException(
+ ex.Message,
+ ex.Context,
+ ex.WrappedException,
+ pImpl->rDocumentLocator->getPublicId(),
+ pImpl->rDocumentLocator->getSystemId(),
+ pImpl->rDocumentLocator->getLineNumber(),
+ pImpl->rDocumentLocator->getColumnNumber()
+ );
+ pImpl->bExceptionWasThrown = sal_True;
+ }
+}
+
+void SaxExpatParser_Impl::callbackEndCDATA( void *pvThis )
+{
+ SaxExpatParser_Impl *pImpl = ((SaxExpatParser_Impl*)pvThis);
+
+ CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pImpl,rExtendedDocumentHandler->endCDATA() );
+}
+
+}
+using namespace sax_expatwrap;
+
+extern "C"
+{
+
+void SAL_CALL component_getImplementationEnvironment(
+ const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ )
+{
+ *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
+}
+
+
+sal_Bool SAL_CALL component_writeInfo(
+ void * /*pServiceManager*/, void * pRegistryKey )
+{
+ if (pRegistryKey)
+ {
+ try
+ {
+ Reference< XRegistryKey > xKey(
+ reinterpret_cast< XRegistryKey * >( pRegistryKey ) );
+
+ Reference< XRegistryKey > xNewKey = xKey->createKey(
+ OUString::createFromAscii( "/" IMPLEMENTATION_NAME "/UNO/SERVICES" ) );
+ xNewKey->createKey( OUString::createFromAscii( SERVICE_NAME ) );
+
+ xNewKey = xKey->createKey( OUString::createFromAscii("/") +
+ SaxWriter_getImplementationName()+
+ OUString::createFromAscii( "/UNO/SERVICES" ) );
+ xNewKey->createKey( SaxWriter_getServiceName() );
+
+ return sal_True;
+ }
+ catch (InvalidRegistryException &)
+ {
+ OSL_ENSURE( sal_False, "### InvalidRegistryException!" );
+ }
+ }
+ return sal_False;
+}
+
+
+void * SAL_CALL component_getFactory(
+ const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ )
+{
+ void * pRet = 0;
+
+ if (pServiceManager )
+ {
+ Reference< XSingleServiceFactory > xRet;
+ Reference< XMultiServiceFactory > xSMgr =
+ reinterpret_cast< XMultiServiceFactory * > ( pServiceManager );
+
+ OUString aImplementationName = OUString::createFromAscii( pImplName );
+
+ if (aImplementationName ==
+ OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) ) )
+ {
+ xRet = createSingleFactory( xSMgr, aImplementationName,
+ SaxExpatParser_CreateInstance,
+ SaxExpatParser::getSupportedServiceNames_Static() );
+ }
+ else if ( aImplementationName == SaxWriter_getImplementationName() )
+ {
+ xRet = createSingleFactory( xSMgr, aImplementationName,
+ SaxWriter_CreateInstance,
+ SaxWriter_getSupportedServiceNames() );
+ }
+
+ if (xRet.is())
+ {
+ xRet->acquire();
+ pRet = xRet.get();
+ }
+ }
+
+ return pRet;
+}
+
+
+}
+
diff --git a/sax/source/expatwrap/saxwriter.cxx b/sax/source/expatwrap/saxwriter.cxx
new file mode 100644
index 000000000000..92d53700aa86
--- /dev/null
+++ b/sax/source/expatwrap/saxwriter.cxx
@@ -0,0 +1,1454 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include <string.h>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
+#include <com/sun/star/xml/sax/XParser.hpp>
+#include <com/sun/star/xml/sax/SAXParseException.hpp>
+#include <com/sun/star/xml/sax/SAXInvalidCharacterException.hpp>
+
+#include <com/sun/star/io/XActiveDataSource.hpp>
+
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/weak.hxx>
+#include <cppuhelper/implbase3.hxx>
+
+#include <rtl/strbuf.hxx>
+#include <rtl/byteseq.hxx>
+#include <rtl/ustrbuf.hxx>
+
+using namespace ::rtl;
+using namespace ::std;
+using namespace ::osl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::registry;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::io;
+
+#include "factory.hxx"
+#include "xml2utf.hxx"
+
+#define LINEFEED 10
+#define SEQUENCESIZE 1024
+#define MAXCOLUMNCOUNT 72
+
+/******
+*
+*
+* Character conversion functions
+*
+*
+*****/
+
+namespace sax_expatwrap {
+/*****
+*
+* Calculates the length of the sequence after conversion, but the conversion is not done.
+* .g. &<>"' plus some more are
+* special characters in XML that need to be transformed
+*
+* @param bConvertAll For Attributes it is necessary to convert every symbol (including line feed and tab)
+* Set this to true, if you want to perform this special conversion
+* @return The returned value is equal to the length of the incoming sequence, when no
++ conversion is necessary, otherwise it is larger than the length of the sequence.
+****/
+// inline sal_Int32 CalcXMLLen( const Sequence<sal_Int8> & seq , sal_Bool bConvertAll ) throw()
+// {
+// sal_Int32 nLen = 0;
+// const sal_Int8 *pArray = seq.getConstArray();
+
+// for( int i = 0 ; i < seq.getLength() ; i ++ ) {
+
+// sal_Int8 c = pArray[i];
+// switch( c )
+// {
+// case '&': // resemble to &amp;
+// nLen +=5;
+// break;
+// case '<': // &lt;
+// case '>': // &gt;
+// nLen +=4;
+// break;
+// case 39: // 39 == ''', &apos;
+// case '"': // &quot;
+// case 13: // &#x0d;
+// nLen += 6;
+// break;
+
+// case 10: // &#x0a;
+// case 9: // &#x09;
+// if( bConvertAll )
+// {
+// nLen += 6; //
+// }
+// break;
+// default:
+// nLen ++;
+// }
+// }
+
+// return nLen;
+// }
+
+enum SaxInvalidCharacterError
+{
+ SAX_NONE,
+ SAX_WARNING,
+ SAX_ERROR
+};
+
+class SaxWriterHelper
+{
+ Reference< XOutputStream > m_out;
+ Sequence < sal_Int8 > m_Sequence;
+ sal_Int8* mp_Sequence;
+
+ sal_Int32 nLastLineFeedPos; // is negative after writing a sequence
+ sal_uInt32 nCurrentPos;
+ sal_Bool m_bStartElementFinished;
+
+
+ inline sal_uInt32 writeSequence() throw( SAXException );
+
+ // use only if to insert the bytes more space in the sequence is needed and
+ // so the sequence has to write out and reset rPos to 0
+ // writes sequence only on overflow, sequence could be full on the end (rPos == SEQUENCESIZE)
+ inline void AddBytes(sal_Int8* pTarget, sal_uInt32& rPos,
+ const sal_Int8* pBytes, sal_uInt32 nBytesCount) throw( SAXException );
+ inline sal_Bool convertToXML(const sal_Unicode * pStr,
+ sal_Int32 nStrLen,
+ sal_Bool bDoNormalization,
+ sal_Bool bNormalizeWhitespace,
+ sal_Int8 *pTarget,
+ sal_uInt32& rPos) throw( SAXException );
+ inline void FinishStartElement() throw( SAXException );
+public:
+ SaxWriterHelper(Reference< XOutputStream > m_TempOut) :
+ m_out(m_TempOut),
+ m_Sequence(SEQUENCESIZE),
+ mp_Sequence(NULL),
+ nLastLineFeedPos(0),
+ nCurrentPos(0),
+ m_bStartElementFinished(sal_True)
+ {
+ OSL_ENSURE(SEQUENCESIZE > 50, "Sequence cache size to small");
+ mp_Sequence = m_Sequence.getArray();
+ }
+ ~SaxWriterHelper()
+ {
+ OSL_ENSURE(!nCurrentPos, "cached Sequence not written");
+ OSL_ENSURE(m_bStartElementFinished, "StartElement not complettly written");
+ }
+
+ inline void insertIndentation(sal_uInt32 m_nLevel) throw( SAXException );
+
+// returns whether it works correct or invalid characters were in the string
+// If there are invalid characters in the string it returns sal_False.
+// Than the calling method has to throw the needed Exception.
+ inline sal_Bool writeString(const rtl::OUString& rWriteOutString,
+ sal_Bool bDoNormalization,
+ sal_Bool bNormalizeWhitespace) throw( SAXException );
+
+ sal_uInt32 GetLastColumnCount() { return (sal_uInt32)(nCurrentPos - nLastLineFeedPos); }
+
+ inline void startDocument() throw( SAXException );
+
+// returns whether it works correct or invalid characters were in the strings
+// If there are invalid characters in one of the strings it returns sal_False.
+// Than the calling method has to throw the needed Exception.
+ inline SaxInvalidCharacterError startElement(const rtl::OUString& rName, const Reference< XAttributeList >& xAttribs) throw( SAXException );
+ inline sal_Bool FinishEmptyElement() throw( SAXException );
+
+// returns whether it works correct or invalid characters were in the string
+// If there are invalid characters in the string it returns sal_False.
+// Than the calling method has to throw the needed Exception.
+ inline sal_Bool endElement(const rtl::OUString& rName) throw( SAXException );
+ inline void endDocument() throw( SAXException );
+
+// returns whether it works correct or invalid characters were in the strings
+// If there are invalid characters in the string it returns sal_False.
+// Than the calling method has to throw the needed Exception.
+ inline sal_Bool processingInstruction(const rtl::OUString& rTarget, const rtl::OUString& rData) throw( SAXException );
+ inline void startCDATA() throw( SAXException );
+ inline void endCDATA() throw( SAXException );
+
+// returns whether it works correct or invalid characters were in the strings
+// If there are invalid characters in the string it returns sal_False.
+// Than the calling method has to throw the needed Exception.
+ inline sal_Bool comment(const rtl::OUString& rComment) throw( SAXException );
+
+ inline void clearBuffer() throw( SAXException );
+};
+
+const sal_Bool g_bValidCharsBelow32[32] =
+{
+// 0 1 2 3 4 5 6 7
+ 0,0,0,0,0,0,0,0, //0
+ 0,1,1,0,0,1,0,0, //8
+ 0,0,0,0,0,0,0,0, //16
+ 0,0,0,0,0,0,0,0
+};
+
+inline sal_Bool IsInvalidChar(const sal_Unicode aChar)
+{
+ sal_Bool bRet(sal_False);
+ // check first for the most common characters
+ if( aChar < 32 || aChar >= 0xd800 )
+ bRet = ( (aChar < 32 && ! g_bValidCharsBelow32[aChar]) ||
+ aChar == 0xffff ||
+ aChar == 0xfffe );
+ return bRet;
+}
+
+/********
+* write through to the output stream
+*
+*****/
+inline sal_uInt32 SaxWriterHelper::writeSequence() throw( SAXException )
+{
+ try
+ {
+ m_out->writeBytes( m_Sequence );
+ }
+ catch( IOException & e )
+ {
+ Any a;
+ a <<= e;
+ throw SAXException(
+ OUString::createFromAscii( "io exception during writing" ),
+ Reference< XInterface > (),
+ a );
+ }
+ nLastLineFeedPos -= SEQUENCESIZE;
+ return 0;
+}
+
+inline void SaxWriterHelper::AddBytes(sal_Int8* pTarget, sal_uInt32& rPos,
+ const sal_Int8* pBytes, sal_uInt32 nBytesCount) throw( SAXException )
+{
+ OSL_ENSURE((rPos + nBytesCount) > SEQUENCESIZE, "wrong use of AddBytesMethod");
+ sal_uInt32 nCount(SEQUENCESIZE - rPos);
+ memcpy( &(pTarget[rPos]) , pBytes, nCount);
+
+ OSL_ENSURE(rPos + nCount == SEQUENCESIZE, "the position should be the at the end");
+
+ rPos = writeSequence();
+ sal_uInt32 nRestCount(nBytesCount - nCount);
+ if ((rPos + nRestCount) <= SEQUENCESIZE)
+ {
+ memcpy( &(pTarget[rPos]), &pBytes[nCount], nRestCount);
+ rPos += nRestCount;
+ }
+ else
+ AddBytes(pTarget, rPos, &pBytes[nCount], nRestCount);
+}
+
+/** Converts an UTF16 string to UTF8 and does XML normalization
+
+ @param pTarget
+ Pointer to a piece of memory, to where the output should be written. The caller
+ must call calcXMLByteLength on the same string, to ensure,
+ that there is enough memory for converting.
+ */
+inline sal_Bool SaxWriterHelper::convertToXML( const sal_Unicode * pStr,
+ sal_Int32 nStrLen,
+ sal_Bool bDoNormalization,
+ sal_Bool bNormalizeWhitespace,
+ sal_Int8 *pTarget,
+ sal_uInt32& rPos ) throw( SAXException )
+{
+ sal_Bool bRet(sal_True);
+ sal_uInt32 nSurrogate = 0;
+
+ for( sal_Int32 i = 0 ; i < nStrLen ; i ++ )
+ {
+ sal_uInt16 c = pStr[i];
+ if (IsInvalidChar(c))
+ bRet = sal_False;
+ else if( (c >= 0x0001) && (c <= 0x007F) )
+ {
+ if( bDoNormalization )
+ {
+ switch( c )
+ {
+ case '&': // resemble to &amp;
+ {
+ if ((rPos + 5) > SEQUENCESIZE)
+ AddBytes(pTarget, rPos, (sal_Int8*)"&amp;", 5);
+ else
+ {
+ memcpy( &(pTarget[rPos]) , "&amp;", 5 );
+ rPos += 5;
+ }
+ }
+ break;
+ case '<':
+ {
+ if ((rPos + 4) > SEQUENCESIZE)
+ AddBytes(pTarget, rPos, (sal_Int8*)"&lt;", 4);
+ else
+ {
+ memcpy( &(pTarget[rPos]) , "&lt;" , 4 );
+ rPos += 4; // &lt;
+ }
+ }
+ break;
+ case '>':
+ {
+ if ((rPos + 4) > SEQUENCESIZE)
+ AddBytes(pTarget, rPos, (sal_Int8*)"&gt;", 4);
+ else
+ {
+ memcpy( &(pTarget[rPos]) , "&gt;" , 4 );
+ rPos += 4; // &gt;
+ }
+ }
+ break;
+ case 39: // 39 == '''
+ {
+ if ((rPos + 6) > SEQUENCESIZE)
+ AddBytes(pTarget, rPos, (sal_Int8*)"&apos;", 6);
+ else
+ {
+ memcpy( &(pTarget[rPos]) , "&apos;" , 6 );
+ rPos += 6; // &apos;
+ }
+ }
+ break;
+ case '"':
+ {
+ if ((rPos + 6) > SEQUENCESIZE)
+ AddBytes(pTarget, rPos, (sal_Int8*)"&quot;", 6);
+ else
+ {
+ memcpy( &(pTarget[rPos]) , "&quot;" , 6 );
+ rPos += 6; // &quot;
+ }
+ }
+ break;
+ case 13:
+ {
+ if ((rPos + 6) > SEQUENCESIZE)
+ AddBytes(pTarget, rPos, (sal_Int8*)"&#x0d;", 6);
+ else
+ {
+ memcpy( &(pTarget[rPos]) , "&#x0d;" , 6 );
+ rPos += 6;
+ }
+ }
+ break;
+ case LINEFEED:
+ {
+ if( bNormalizeWhitespace )
+ {
+ if ((rPos + 6) > SEQUENCESIZE)
+ AddBytes(pTarget, rPos, (sal_Int8*)"&#x0a;" , 6);
+ else
+ {
+ memcpy( &(pTarget[rPos]) , "&#x0a;" , 6 );
+ rPos += 6;
+ }
+ }
+ else
+ {
+ pTarget[rPos] = LINEFEED;
+ nLastLineFeedPos = rPos;
+ rPos ++;
+ }
+ }
+ break;
+ case 9:
+ {
+ if( bNormalizeWhitespace )
+ {
+ if ((rPos + 6) > SEQUENCESIZE)
+ AddBytes(pTarget, rPos, (sal_Int8*)"&#x09;" , 6);
+ else
+ {
+ memcpy( &(pTarget[rPos]) , "&#x09;" , 6 );
+ rPos += 6;
+ }
+ }
+ else
+ {
+ pTarget[rPos] = 9;
+ rPos ++;
+ }
+ }
+ break;
+ default:
+ {
+ pTarget[rPos] = (sal_Int8)c;
+ rPos ++;
+ }
+ break;
+ }
+ }
+ else
+ {
+ pTarget[rPos] = (sal_Int8)c;
+ if ((sal_Int8)c == LINEFEED)
+ nLastLineFeedPos = rPos;
+ rPos ++;
+ }
+ }
+ else if( c >= 0xd800 && c < 0xdc00 )
+ {
+ // 1. surrogate: save (until 2. surrogate)
+ OSL_ENSURE( nSurrogate == 0, "left-over Unicode surrogate" );
+ nSurrogate = ( ( c & 0x03ff ) + 0x0040 );
+ }
+ else if( c >= 0xdc00 && c < 0xe000 )
+ {
+ // 2. surrogate: write as UTF-8
+ OSL_ENSURE( nSurrogate != 0, "lone 2nd Unicode surrogate" );
+
+ nSurrogate = ( nSurrogate << 10 ) | ( c & 0x03ff );
+ if( nSurrogate >= 0x00010000 && nSurrogate <= 0x0010FFFF )
+ {
+ sal_Int8 aBytes[] = { sal_Int8(0xF0 | ((nSurrogate >> 18) & 0x0F)),
+ sal_Int8(0x80 | ((nSurrogate >> 12) & 0x3F)),
+ sal_Int8(0x80 | ((nSurrogate >> 6) & 0x3F)),
+ sal_Int8(0x80 | ((nSurrogate >> 0) & 0x3F)) };
+ if ((rPos + 4) > SEQUENCESIZE)
+ AddBytes(pTarget, rPos, aBytes, 4);
+ else
+ {
+ pTarget[rPos] = aBytes[0];
+ rPos ++;
+ pTarget[rPos] = aBytes[1];
+ rPos ++;
+ pTarget[rPos] = aBytes[2];
+ rPos ++;
+ pTarget[rPos] = aBytes[3];
+ rPos ++;
+ }
+ }
+ else
+ {
+ OSL_ENSURE( false, "illegal Unicode character" );
+ bRet = sal_False;
+ }
+
+ // reset surrogate
+ nSurrogate = 0;
+ }
+ else if( c > 0x07FF )
+ {
+ sal_Int8 aBytes[] = { sal_Int8(0xE0 | ((c >> 12) & 0x0F)),
+ sal_Int8(0x80 | ((c >> 6) & 0x3F)),
+ sal_Int8(0x80 | ((c >> 0) & 0x3F)) };
+ if ((rPos + 3) > SEQUENCESIZE)
+ AddBytes(pTarget, rPos, aBytes, 3);
+ else
+ {
+ pTarget[rPos] = aBytes[0];
+ rPos ++;
+ pTarget[rPos] = aBytes[1];
+ rPos ++;
+ pTarget[rPos] = aBytes[2];
+ rPos ++;
+ }
+ }
+ else
+ {
+ sal_Int8 aBytes[] = { sal_Int8(0xC0 | ((c >> 6) & 0x1F)),
+ sal_Int8(0x80 | ((c >> 0) & 0x3F)) };
+ if ((rPos + 2) > SEQUENCESIZE)
+ AddBytes(pTarget, rPos, aBytes, 2);
+ else
+ {
+ pTarget[rPos] = aBytes[0];
+ rPos ++;
+ pTarget[rPos] = aBytes[1];
+ rPos ++;
+ }
+ }
+ OSL_ENSURE(rPos <= SEQUENCESIZE, "not reset current position");
+ if (rPos == SEQUENCESIZE)
+ rPos = writeSequence();
+
+ // reset left-over surrogate
+ if( ( nSurrogate != 0 ) && !( c >= 0xd800 && c < 0xdc00 ) )
+ {
+ OSL_ENSURE( nSurrogate != 0, "left-over Unicode surrogate" );
+ nSurrogate = 0;
+ bRet = sal_False;
+ }
+ }
+ return bRet;
+}
+
+inline void SaxWriterHelper::FinishStartElement() throw( SAXException )
+{
+ if (!m_bStartElementFinished)
+ {
+ mp_Sequence[nCurrentPos] = '>';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+ m_bStartElementFinished = sal_True;
+ }
+}
+
+inline void SaxWriterHelper::insertIndentation(sal_uInt32 m_nLevel) throw( SAXException )
+{
+ FinishStartElement();
+ if (m_nLevel > 0)
+ {
+ if ((nCurrentPos + m_nLevel + 1) <= SEQUENCESIZE)
+ {
+ mp_Sequence[nCurrentPos] = LINEFEED;
+ nLastLineFeedPos = nCurrentPos;
+ nCurrentPos++;
+ memset( &(mp_Sequence[nCurrentPos]) , 32 , m_nLevel );
+ nCurrentPos += m_nLevel;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+ }
+ else
+ {
+ sal_uInt32 nCount(m_nLevel + 1);
+ sal_Int8* pBytes = new sal_Int8[nCount];
+ pBytes[0] = LINEFEED;
+ memset( &(pBytes[1]), 32, m_nLevel );
+ AddBytes(mp_Sequence, nCurrentPos, pBytes, nCount);
+ delete[] pBytes;
+ nLastLineFeedPos = nCurrentPos - nCount;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+ }
+ }
+ else
+ {
+ mp_Sequence[nCurrentPos] = LINEFEED;
+ nLastLineFeedPos = nCurrentPos;
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+ }
+}
+
+inline sal_Bool SaxWriterHelper::writeString( const rtl::OUString& rWriteOutString,
+ sal_Bool bDoNormalization,
+ sal_Bool bNormalizeWhitespace ) throw( SAXException )
+{
+ FinishStartElement();
+ return convertToXML(rWriteOutString.getStr(),
+ rWriteOutString.getLength(),
+ bDoNormalization,
+ bNormalizeWhitespace,
+ mp_Sequence,
+ nCurrentPos);
+}
+
+inline void SaxWriterHelper::startDocument() throw( SAXException )
+{
+ const char pc[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+ const int nLen = strlen( pc );
+ if ((nCurrentPos + nLen) <= SEQUENCESIZE)
+ {
+ memcpy( mp_Sequence, pc , nLen );
+ nCurrentPos += nLen;
+ }
+ else
+ {
+ AddBytes(mp_Sequence, nCurrentPos, (sal_Int8*)pc, nLen);
+ }
+ OSL_ENSURE(nCurrentPos <= SEQUENCESIZE, "not reset current position");
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+ mp_Sequence[nCurrentPos] = LINEFEED;
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+}
+
+inline SaxInvalidCharacterError SaxWriterHelper::startElement(const rtl::OUString& rName, const Reference< XAttributeList >& xAttribs) throw( SAXException )
+{
+ FinishStartElement();
+ mp_Sequence[nCurrentPos] = '<';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+
+ SaxInvalidCharacterError eRet(SAX_NONE);
+ if (!writeString(rName, sal_False, sal_False))
+ eRet = SAX_ERROR;
+
+ sal_Int16 nAttribCount = xAttribs.is() ? static_cast<sal_Int16>(xAttribs->getLength()) : 0;
+ for(sal_Int16 i = 0 ; i < nAttribCount ; i++ )
+ {
+ mp_Sequence[nCurrentPos] = ' ';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+
+ if (!writeString(xAttribs->getNameByIndex( i ), sal_False, sal_False))
+ eRet = SAX_ERROR;
+
+ mp_Sequence[nCurrentPos] = '=';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+ mp_Sequence[nCurrentPos] = '"';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+
+ if (!writeString(xAttribs->getValueByIndex( i ), sal_True, sal_True) &&
+ !(eRet == SAX_ERROR))
+ eRet = SAX_WARNING;
+
+ mp_Sequence[nCurrentPos] = '"';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+ }
+
+ m_bStartElementFinished = sal_False; // because the '>' character is not added,
+ // because it is possible, that the "/>"
+ // characters have to add
+ return eRet;
+}
+
+inline sal_Bool SaxWriterHelper::FinishEmptyElement() throw( SAXException )
+{
+ if (m_bStartElementFinished)
+ return sal_False;
+
+ mp_Sequence[nCurrentPos] = '/';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+ mp_Sequence[nCurrentPos] = '>';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+
+ m_bStartElementFinished = sal_True;
+
+ return sal_True;
+}
+
+inline sal_Bool SaxWriterHelper::endElement(const rtl::OUString& rName) throw( SAXException )
+{
+ FinishStartElement();
+ mp_Sequence[nCurrentPos] = '<';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+ mp_Sequence[nCurrentPos] = '/';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+
+ sal_Bool bRet(writeString( rName, sal_False, sal_False));
+
+ mp_Sequence[nCurrentPos] = '>';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+
+ return bRet;
+}
+
+inline void SaxWriterHelper::endDocument() throw( SAXException )
+{
+ if (nCurrentPos > 0)
+ {
+ m_Sequence.realloc(nCurrentPos);
+ nCurrentPos = writeSequence();
+ //m_Sequence.realloc(SEQUENCESIZE);
+ }
+}
+
+inline void SaxWriterHelper::clearBuffer() throw( SAXException )
+{
+ FinishStartElement();
+ if (nCurrentPos > 0)
+ {
+ m_Sequence.realloc(nCurrentPos);
+ nCurrentPos = writeSequence();
+ m_Sequence.realloc(SEQUENCESIZE);
+ // Be sure to update the array pointer after the reallocation.
+ mp_Sequence = m_Sequence.getArray();
+ }
+}
+
+inline sal_Bool SaxWriterHelper::processingInstruction(const rtl::OUString& rTarget, const rtl::OUString& rData) throw( SAXException )
+{
+ FinishStartElement();
+ mp_Sequence[nCurrentPos] = '<';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+ mp_Sequence[nCurrentPos] = '?';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+
+ sal_Bool bRet(writeString( rTarget, sal_False, sal_False ));
+
+ mp_Sequence[nCurrentPos] = ' ';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+
+ if (!writeString( rData, sal_False, sal_False ))
+ bRet = sal_False;
+
+ mp_Sequence[nCurrentPos] = '?';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+ mp_Sequence[nCurrentPos] = '>';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+
+ return bRet;
+}
+
+inline void SaxWriterHelper::startCDATA() throw( SAXException )
+{
+ FinishStartElement();
+ if ((nCurrentPos + 9) <= SEQUENCESIZE)
+ {
+ memcpy( &(mp_Sequence[nCurrentPos]), "<![CDATA[" , 9 );
+ nCurrentPos += 9;
+ }
+ else
+ AddBytes(mp_Sequence, nCurrentPos, (sal_Int8*)"<![CDATA[" , 9);
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+}
+
+inline void SaxWriterHelper::endCDATA() throw( SAXException )
+{
+ FinishStartElement();
+ if ((nCurrentPos + 3) <= SEQUENCESIZE)
+ {
+ memcpy( &(mp_Sequence[nCurrentPos]), "]]>" , 3 );
+ nCurrentPos += 3;
+ }
+ else
+ AddBytes(mp_Sequence, nCurrentPos, (sal_Int8*)"]]>" , 3);
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+}
+
+inline sal_Bool SaxWriterHelper::comment(const rtl::OUString& rComment) throw( SAXException )
+{
+ FinishStartElement();
+ mp_Sequence[nCurrentPos] = '<';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+ mp_Sequence[nCurrentPos] = '!';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+ mp_Sequence[nCurrentPos] = '-';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+ mp_Sequence[nCurrentPos] = '-';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+
+ sal_Bool bRet(writeString( rComment, sal_False, sal_False));
+
+ mp_Sequence[nCurrentPos] = '-';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+ mp_Sequence[nCurrentPos] = '-';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+ mp_Sequence[nCurrentPos] = '>';
+ nCurrentPos++;
+ if (nCurrentPos == SEQUENCESIZE)
+ nCurrentPos = writeSequence();
+
+ return bRet;
+}
+
+inline sal_Int32 calcXMLByteLength( const sal_Unicode *pStr, sal_Int32 nStrLen,
+ sal_Bool bDoNormalization,
+ sal_Bool bNormalizeWhitespace )
+{
+ sal_Int32 nOutputLength = 0;
+ sal_uInt32 nSurrogate = 0;
+
+ for( sal_Int32 i = 0 ; i < nStrLen ; i++ )
+ {
+ sal_uInt16 c = pStr[i];
+ if( !IsInvalidChar(c) && (c >= 0x0001) && (c <= 0x007F) )
+ {
+ if( bDoNormalization )
+ {
+ switch( c )
+ {
+ case '&': // resemble to &amp;
+ nOutputLength +=5;
+ break;
+ case '<': // &lt;
+ case '>': // &gt;
+ nOutputLength +=4;
+ break;
+ case 39: // 39 == ''', &apos;
+ case '"': // &quot;
+ case 13: // &#x0d;
+ nOutputLength += 6;
+ break;
+
+ case 10: // &#x0a;
+ case 9: // &#x09;
+ if( bNormalizeWhitespace )
+ {
+ nOutputLength += 6; //
+ }
+ else
+ {
+ nOutputLength ++;
+ }
+ break;
+ default:
+ nOutputLength ++;
+ }
+ }
+ else
+ {
+ nOutputLength ++;
+ }
+ }
+ else if( c >= 0xd800 && c < 0xdc00 )
+ {
+ // save surrogate
+ nSurrogate = ( ( c & 0x03ff ) + 0x0040 );
+ }
+ else if( c >= 0xdc00 && c < 0xe000 )
+ {
+ // 2. surrogate: write as UTF-8 (if range is OK
+ nSurrogate = ( nSurrogate << 10 ) | ( c & 0x03ff );
+ if( nSurrogate >= 0x00010000 && nSurrogate <= 0x0010FFFF )
+ nOutputLength += 4;
+ nSurrogate = 0;
+ }
+ else if( c > 0x07FF )
+ {
+ nOutputLength += 3;
+ }
+ else
+ {
+ nOutputLength += 2;
+ }
+
+ // surrogate processing
+ if( ( nSurrogate != 0 ) && !( c >= 0xd800 && c < 0xdc00 ) )
+ nSurrogate = 0;
+ }
+
+ return nOutputLength;
+}
+
+/** returns position of first ascii 10 within the string, -1 when no 10 in string.
+ */
+static inline sal_Int32 getFirstLineBreak( const OUString & str ) throw ()
+{
+ const sal_Unicode *pSource = str.getStr();
+ sal_Int32 nLen = str.getLength();
+
+ for( int n = 0; n < nLen ; n ++ )
+ {
+ if( LINEFEED == pSource[n] ) {
+ return n;
+ }
+ }
+ return -1;
+}
+
+/** returns position of last ascii 10 within sequence, -1 when no 10 in string.
+ */
+static inline sal_Int32 getLastLineBreak( const Sequence<sal_Int8> & seq) throw ()
+{
+ const sal_Int8 *pSource = seq.getConstArray();
+ sal_Int32 nLen = seq.getLength();
+
+ for( int n = nLen-1; n >= 0 ; n -- )
+ {
+ if( LINEFEED == pSource[n] ) {
+ return n;
+ }
+ }
+ return -1;
+}
+
+
+class SAXWriter :
+ public WeakImplHelper3<
+ XActiveDataSource,
+ XExtendedDocumentHandler,
+ XServiceInfo >
+{
+public:
+ SAXWriter( ) :
+ m_seqStartElement(),
+ mp_SaxWriterHelper( NULL ),
+ m_bForceLineBreak(sal_False),
+ m_bAllowLineBreak(sal_False)
+ {}
+ ~SAXWriter()
+ {
+ delete mp_SaxWriterHelper;
+ }
+
+public: // XActiveDataSource
+ virtual void SAL_CALL setOutputStream(const Reference< XOutputStream > & aStream)
+ throw (RuntimeException)
+ {
+ // temporary: set same stream again to clear buffer
+ if ( m_out == aStream && mp_SaxWriterHelper && m_bDocStarted )
+ mp_SaxWriterHelper->clearBuffer();
+ else
+ {
+
+ m_out = aStream;
+ delete mp_SaxWriterHelper;
+ mp_SaxWriterHelper = new SaxWriterHelper(m_out);
+ m_bDocStarted = sal_False;
+ m_nLevel = 0;
+ m_bIsCDATA = sal_False;
+
+ }
+ }
+ virtual Reference< XOutputStream > SAL_CALL getOutputStream(void)
+ throw(RuntimeException)
+ { return m_out; }
+
+public: // XDocumentHandler
+ virtual void SAL_CALL startDocument(void)
+ throw(SAXException, RuntimeException);
+
+ virtual void SAL_CALL endDocument(void)
+ throw(SAXException, RuntimeException);
+
+ virtual void SAL_CALL startElement(const OUString& aName,
+ const Reference< XAttributeList > & xAttribs)
+ throw (SAXException, RuntimeException);
+
+ virtual void SAL_CALL endElement(const OUString& aName)
+ throw(SAXException, RuntimeException);
+
+ virtual void SAL_CALL characters(const OUString& aChars)
+ throw(SAXException, RuntimeException);
+
+ virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces)
+ throw(SAXException, RuntimeException);
+ virtual void SAL_CALL processingInstruction(const OUString& aTarget,
+ const OUString& aData)
+ throw(SAXException, RuntimeException);
+ virtual void SAL_CALL setDocumentLocator(const Reference< XLocator > & xLocator)
+ throw(SAXException, RuntimeException);
+
+public: // XExtendedDocumentHandler
+ virtual void SAL_CALL startCDATA(void) throw(SAXException, RuntimeException);
+ virtual void SAL_CALL endCDATA(void) throw(RuntimeException);
+ virtual void SAL_CALL comment(const OUString& sComment)
+ throw(SAXException, RuntimeException);
+ virtual void SAL_CALL unknown(const OUString& sString)
+ throw(SAXException, RuntimeException);
+ virtual void SAL_CALL allowLineBreak(void)
+ throw(SAXException,RuntimeException);
+
+public: // XServiceInfo
+ OUString SAL_CALL getImplementationName() throw();
+ Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw();
+ sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw();
+
+private:
+
+ void writeSequence( const Sequence<sal_Int8> & seq );
+ sal_Int32 getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurence ) throw();
+
+ Reference< XOutputStream > m_out;
+ Sequence < sal_Int8 > m_seqStartElement;
+ SaxWriterHelper* mp_SaxWriterHelper;
+
+ // Status information
+ sal_Bool m_bDocStarted : 1;
+ sal_Bool m_bIsCDATA : 1;
+ sal_Bool m_bForceLineBreak : 1;
+ sal_Bool m_bAllowLineBreak : 1;
+ sal_Int32 m_nLevel;
+};
+
+
+//--------------------------------------
+// the extern interface
+//---------------------------------------
+Reference < XInterface > SAL_CALL SaxWriter_CreateInstance(
+ const Reference < XMultiServiceFactory > & )
+ throw (Exception)
+{
+ SAXWriter *p = new SAXWriter;
+ return Reference< XInterface > ( SAL_STATIC_CAST(OWeakObject *, p ) );
+}
+
+OUString SaxWriter_getServiceName() throw()
+{
+ return OUString::createFromAscii( "com.sun.star.xml.sax.Writer" );
+}
+
+OUString SaxWriter_getImplementationName() throw()
+{
+ return OUString::createFromAscii( "com.sun.star.extensions.xml.sax.Writer" );
+}
+
+Sequence< OUString > SaxWriter_getSupportedServiceNames(void) throw()
+{
+ Sequence<OUString> aRet(1);
+ aRet.getArray()[0] = SaxWriter_getServiceName();
+ return aRet;
+}
+
+
+sal_Int32 SAXWriter::getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurence ) throw()
+{
+ sal_Int32 nLength =-1;
+ if (mp_SaxWriterHelper)
+ {
+ if ( m_bForceLineBreak ||
+ (m_bAllowLineBreak &&
+ ((nFirstLineBreakOccurence + mp_SaxWriterHelper->GetLastColumnCount()) > MAXCOLUMNCOUNT)) )
+ nLength = m_nLevel;
+ }
+ m_bForceLineBreak = sal_False;
+ m_bAllowLineBreak = sal_False;
+ return nLength;
+}
+
+static inline sal_Bool isFirstCharWhitespace( const sal_Unicode *p ) throw()
+{
+ return *p == ' ';
+}
+
+
+// XServiceInfo
+OUString SAXWriter::getImplementationName() throw()
+{
+ return SaxWriter_getImplementationName();
+}
+
+// XServiceInfo
+sal_Bool SAXWriter::supportsService(const OUString& ServiceName) throw()
+{
+ 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 > SAXWriter::getSupportedServiceNames(void) throw ()
+{
+ Sequence<OUString> seq(1);
+ seq.getArray()[0] = SaxWriter_getServiceName();
+ return seq;
+}
+
+
+
+void SAXWriter::startDocument() throw(SAXException, RuntimeException )
+{
+ if( m_bDocStarted || ! m_out.is() || !mp_SaxWriterHelper ) {
+ throw SAXException();
+ }
+ m_bDocStarted = sal_True;
+ mp_SaxWriterHelper->startDocument();
+}
+
+
+void SAXWriter::endDocument(void) throw(SAXException, RuntimeException)
+{
+ if( ! m_bDocStarted )
+ {
+ throw SAXException(
+ OUString::createFromAscii( "endDocument called before startDocument" ),
+ Reference< XInterface >() , Any() );
+ }
+ if( m_nLevel ) {
+ throw SAXException(
+ OUString::createFromAscii( "unexpected end of document" ),
+ Reference< XInterface >() , Any() );
+ }
+ mp_SaxWriterHelper->endDocument();
+ try
+ {
+ m_out->closeOutput();
+ }
+ catch( IOException & e )
+ {
+ Any a;
+ a <<= e;
+ throw SAXException(
+ OUString::createFromAscii( "IO exception during closing the IO Stream" ),
+ Reference< XInterface > (),
+ a );
+ }
+}
+
+
+void SAXWriter::startElement(const OUString& aName, const Reference< XAttributeList >& xAttribs)
+ throw(SAXException, RuntimeException)
+{
+ if( ! m_bDocStarted )
+ {
+ SAXException except;
+ except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "startElement called before startDocument" ));
+ throw except;
+ }
+ if( m_bIsCDATA )
+ {
+ SAXException except;
+ except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "startElement call not allowed with CDATA sections" ));
+ throw except;
+ }
+
+ sal_Int32 nLength(0);
+ if (m_bAllowLineBreak)
+ {
+ sal_Int32 nAttribCount = xAttribs.is() ? xAttribs->getLength() : 0;
+
+ nLength ++; // "<"
+ nLength += calcXMLByteLength( aName.getStr() , aName.getLength(),
+ sal_False, sal_False ); // the tag name
+
+ sal_Int16 n;
+ for( n = 0 ; n < static_cast<sal_Int16>(nAttribCount) ; n ++ ) {
+ nLength ++; // " "
+ OUString tmp = xAttribs->getNameByIndex( n );
+
+ nLength += calcXMLByteLength( tmp.getStr() , tmp.getLength() , sal_False, sal_False );
+
+ nLength += 2; // ="
+
+ tmp = xAttribs->getValueByIndex( n );
+
+ nLength += calcXMLByteLength( tmp.getStr(), tmp.getLength(), sal_True, sal_True );
+
+ nLength += 1; // "
+ }
+
+ nLength ++; // '>'
+ }
+
+ // Is there a new indentation necesarry ?
+ sal_Int32 nPrefix(getIndentPrefixLength( nLength ));
+
+ // write into sequence
+ if( nPrefix >= 0 )
+ mp_SaxWriterHelper->insertIndentation( nPrefix );
+
+ SaxInvalidCharacterError eRet(mp_SaxWriterHelper->startElement(aName, xAttribs));
+
+ m_nLevel++;
+
+ if (eRet == SAX_WARNING)
+ {
+ SAXInvalidCharacterException except;
+ except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export in a attribute value" ) );
+ throw except;
+ }
+ else if (eRet == SAX_ERROR)
+ {
+ SAXException except;
+ except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) );
+ throw except;
+ }
+}
+
+void SAXWriter::endElement(const OUString& aName) throw (SAXException, RuntimeException)
+{
+ if( ! m_bDocStarted ) {
+ throw SAXException ();
+ }
+ m_nLevel --;
+
+ if( m_nLevel < 0 ) {
+ throw SAXException();
+ }
+ sal_Bool bRet(sal_True);
+
+ if( mp_SaxWriterHelper->FinishEmptyElement() )
+ m_bForceLineBreak = sal_False;
+ else
+ {
+ // only ascii chars allowed
+ sal_Int32 nLength(0);
+ if (m_bAllowLineBreak)
+ nLength = 3 + calcXMLByteLength( aName.getStr(), aName.getLength(), sal_False, sal_False );
+ sal_Int32 nPrefix = getIndentPrefixLength( nLength );
+
+ if( nPrefix >= 0 )
+ mp_SaxWriterHelper->insertIndentation( nPrefix );
+
+ bRet = mp_SaxWriterHelper->endElement(aName);
+ }
+
+ if (!bRet)
+ {
+ SAXException except;
+ except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) );
+ throw except;
+ }
+}
+
+void SAXWriter::characters(const OUString& aChars) throw(SAXException, RuntimeException)
+{
+ if( ! m_bDocStarted )
+ {
+ SAXException except;
+ except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "characters method called before startDocument" ) );
+ throw except;
+ }
+
+ sal_Bool bThrowException(sal_False);
+ if( aChars.getLength() )
+ {
+ if( m_bIsCDATA )
+ bThrowException = !mp_SaxWriterHelper->writeString( aChars, sal_False, sal_False );
+ else
+ {
+ // Note : nFirstLineBreakOccurence is not exact, because we don't know, how
+ // many 2 and 3 byte chars are inbetween. However this whole stuff
+ // is eitherway for pretty printing only, so it does not need to be exact.
+ sal_Int32 nLength(0);
+ sal_Int32 nIndentPrefix(-1);
+ if (m_bAllowLineBreak)
+ {
+ sal_Int32 nFirstLineBreakOccurence = getFirstLineBreak( aChars );
+
+ nLength = calcXMLByteLength( aChars.getStr(), aChars.getLength(),
+ ! m_bIsCDATA , sal_False );
+ nIndentPrefix = getIndentPrefixLength(
+ nFirstLineBreakOccurence >= 0 ? nFirstLineBreakOccurence : nLength );
+ }
+ else
+ nIndentPrefix = getIndentPrefixLength(nLength);
+
+ // insert indentation
+ if( nIndentPrefix >= 0 )
+ {
+ if( isFirstCharWhitespace( aChars.getStr() ) )
+ mp_SaxWriterHelper->insertIndentation( nIndentPrefix - 1 );
+ else
+ mp_SaxWriterHelper->insertIndentation( nIndentPrefix );
+ }
+ bThrowException = !mp_SaxWriterHelper->writeString(aChars, sal_True , sal_False);
+ }
+ }
+ if (bThrowException)
+ {
+ SAXInvalidCharacterException except;
+ except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) );
+ throw except;
+ }
+}
+
+
+void SAXWriter::ignorableWhitespace(const OUString&) throw(SAXException, RuntimeException)
+{
+ if( ! m_bDocStarted )
+ {
+ throw SAXException ();
+ }
+
+ m_bForceLineBreak = sal_True;
+}
+
+void SAXWriter::processingInstruction(const OUString& aTarget, const OUString& aData)
+ throw (SAXException, RuntimeException)
+{
+ if( ! m_bDocStarted || m_bIsCDATA )
+ {
+ throw SAXException();
+ }
+
+ sal_Int32 nLength(0);
+ if (m_bAllowLineBreak)
+ {
+ nLength = 2; // "<?"
+ nLength += calcXMLByteLength( aTarget.getStr(), aTarget.getLength(), sal_False, sal_False );
+
+ nLength += 1; // " "
+
+ nLength += calcXMLByteLength( aData.getStr(), aData.getLength(), sal_False, sal_False );
+
+ nLength += 2; // "?>"
+ }
+
+ sal_Int32 nPrefix = getIndentPrefixLength( nLength );
+
+ if( nPrefix >= 0 )
+ mp_SaxWriterHelper->insertIndentation( nPrefix );
+
+ if (!mp_SaxWriterHelper->processingInstruction(aTarget, aData))
+ {
+ SAXException except;
+ except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) );
+ throw except;
+ }
+}
+
+
+void SAXWriter::setDocumentLocator(const Reference< XLocator >&)
+ throw (SAXException, RuntimeException)
+{
+
+}
+
+void SAXWriter::startCDATA(void) throw(SAXException, RuntimeException)
+{
+ if( ! m_bDocStarted || m_bIsCDATA)
+ {
+ throw SAXException ();
+ }
+
+ sal_Int32 nLength = 9;
+ sal_Int32 nPrefix = getIndentPrefixLength( nLength );
+ if( nPrefix >= 0 )
+ mp_SaxWriterHelper->insertIndentation( nPrefix );
+
+ mp_SaxWriterHelper->startCDATA();
+
+ m_bIsCDATA = sal_True;
+}
+
+void SAXWriter::endCDATA(void) throw (RuntimeException)
+{
+ if( ! m_bDocStarted | ! m_bIsCDATA)
+ {
+ SAXException except;
+ except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "endCDATA was called without startCDATA" ) );
+ throw except;
+ }
+
+ sal_Int32 nLength = 3;
+ sal_Int32 nPrefix = getIndentPrefixLength( nLength );
+ if( nPrefix >= 0 )
+ mp_SaxWriterHelper->insertIndentation( nPrefix );
+
+ mp_SaxWriterHelper->endCDATA();
+
+ m_bIsCDATA = sal_False;
+}
+
+
+void SAXWriter::comment(const OUString& sComment) throw(SAXException, RuntimeException)
+{
+ if( ! m_bDocStarted || m_bIsCDATA )
+ {
+ throw SAXException();
+ }
+
+ sal_Int32 nLength(0);
+ if (m_bAllowLineBreak)
+ {
+ nLength = 4; // "<!--"
+ nLength += calcXMLByteLength( sComment.getStr(), sComment.getLength(), sal_False, sal_False);
+
+ nLength += 3;
+ }
+
+ sal_Int32 nPrefix = getIndentPrefixLength( nLength );
+ if( nPrefix >= 0 )
+ mp_SaxWriterHelper->insertIndentation( nPrefix );
+
+ if (!mp_SaxWriterHelper->comment(sComment))
+ {
+ SAXException except;
+ except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) );
+ throw except;
+ }
+}
+
+
+void SAXWriter::allowLineBreak( ) throw ( SAXException , RuntimeException)
+{
+ if( ! m_bDocStarted || m_bAllowLineBreak ) {
+ throw SAXException();
+ }
+
+ m_bAllowLineBreak = sal_True;
+}
+
+void SAXWriter::unknown(const OUString& sString) throw (SAXException, RuntimeException)
+{
+
+ if( ! m_bDocStarted )
+ {
+ throw SAXException ();
+ }
+ if( m_bIsCDATA )
+ {
+ throw SAXException();
+ }
+
+ if( sString.matchAsciiL( "<?xml", 5 ) )
+ return;
+
+ sal_Int32 nLength(0);
+ if (m_bAllowLineBreak)
+ nLength = calcXMLByteLength( sString.getStr(), sString.getLength(), sal_False, sal_False );
+
+ sal_Int32 nPrefix = getIndentPrefixLength( nLength );
+ if( nPrefix >= 0 )
+ mp_SaxWriterHelper->insertIndentation( nPrefix );
+
+ if (!mp_SaxWriterHelper->writeString( sString, sal_False, sal_False))
+ {
+ SAXException except;
+ except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) );
+ throw except;
+ }
+}
+
+}
+
diff --git a/sax/source/expatwrap/xml2utf.cxx b/sax/source/expatwrap/xml2utf.cxx
new file mode 100644
index 000000000000..bbd72b2a0d8b
--- /dev/null
+++ b/sax/source/expatwrap/xml2utf.cxx
@@ -0,0 +1,570 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include <string.h>
+
+#include <sal/types.h>
+
+#include <rtl/textenc.h>
+#include <rtl/tencinfo.h>
+
+
+#include <com/sun/star/io/XInputStream.hpp>
+
+using namespace rtl;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+
+#include "xml2utf.hxx"
+
+namespace sax_expatwrap {
+
+sal_Int32 XMLFile2UTFConverter::readAndConvert( Sequence<sal_Int8> &seq , sal_Int32 nMaxToRead )
+ throw ( IOException, NotConnectedException , BufferSizeExceededException , RuntimeException )
+{
+
+ Sequence<sal_Int8> seqIn;
+
+ if( ! m_in.is() ) {
+ throw NotConnectedException();
+ }
+ if( ! m_bStarted ) {
+ nMaxToRead = Max( 512 , nMaxToRead ); // it should be possible to find the encoding attribute
+ // within the first 512 bytes == 128 chars in UCS-4
+ }
+
+ sal_Int32 nRead;
+ Sequence< sal_Int8 > seqStart;
+ while( sal_True )
+ {
+ nRead = m_in->readSomeBytes( seq , nMaxToRead );
+
+ if( nRead + seqStart.getLength())
+ {
+ // if nRead is 0, the file is already eof.
+ if( ! m_bStarted && nRead )
+ {
+ // ensure that enough data is available to parse encoding
+ if( seqStart.getLength() )
+ {
+ // prefix with what we had so far.
+ sal_Int32 nLength = seq.getLength();
+ seq.realloc( seqStart.getLength() + nLength );
+
+ memmove (seq.getArray() + seqStart.getLength(),
+ seq.getConstArray(),
+ nLength);
+ memcpy (seq.getArray(),
+ seqStart.getConstArray(),
+ seqStart.getLength());
+ }
+
+ // autodetection with the first bytes
+ if( ! isEncodingRecognizable( seq ) )
+ {
+ // remember what we have so far.
+ seqStart = seq;
+
+ // read more !
+ continue;
+ }
+ if( scanForEncoding( seq ) || m_sEncoding.getLength() ) {
+ // initialize decoding
+ initializeDecoding();
+ }
+ nRead = seq.getLength();
+ seqStart = Sequence < sal_Int8 > ();
+ }
+
+ // do the encoding
+ if( m_pText2Unicode && m_pUnicode2Text &&
+ m_pText2Unicode->canContinue() && m_pUnicode2Text->canContinue() ) {
+
+ Sequence<sal_Unicode> seqUnicode = m_pText2Unicode->convert( seq );
+ seq = m_pUnicode2Text->convert( seqUnicode.getConstArray(), seqUnicode.getLength() );
+ }
+
+ if( ! m_bStarted )
+ {
+ // it must now be ensured, that no encoding attribute exist anymore
+ // ( otherwise the expat-Parser will crash )
+ // This must be done after decoding !
+ // ( e.g. Files decoded in ucs-4 cannot be read properly )
+ m_bStarted = sal_True;
+ removeEncoding( seq );
+ }
+ nRead = seq.getLength();
+ }
+
+ break;
+ }
+ return nRead;
+}
+
+
+XMLFile2UTFConverter::~XMLFile2UTFConverter()
+{
+ if( m_pText2Unicode )
+ delete m_pText2Unicode;
+ if( m_pUnicode2Text )
+ delete m_pUnicode2Text;
+}
+
+
+void XMLFile2UTFConverter::removeEncoding( Sequence<sal_Int8> &seq )
+{
+ const sal_Int8 *pSource = seq.getArray();
+ if( ! strncmp( (const char * ) pSource , "<?xml" , 4) )
+ {
+
+ // scan for encoding
+ OString str( (sal_Char * ) pSource , seq.getLength() );
+
+ // cut sequence to first line break
+ // find first line break;
+ int nMax = str.indexOf( 10 );
+ if( nMax >= 0 )
+ {
+ str = str.copy( 0 , nMax );
+ }
+
+ int nFound = str.indexOf( " encoding" );
+ if( nFound >= 0 ) {
+ int nStop;
+ int nStart = str.indexOf( "\"" , nFound );
+ if( nStart < 0 || str.indexOf( "'" , nFound ) < nStart )
+ {
+ nStart = str.indexOf( "'" , nFound );
+ nStop = str.indexOf( "'" , nStart +1 );
+ }
+ else
+ {
+ nStop = str.indexOf( "\"" , nStart +1);
+ }
+
+ if( nStart >= 0 && nStop >= 0 && nStart+1 < nStop )
+ {
+ // remove encoding tag from file
+ memmove( &( seq.getArray()[nFound] ) ,
+ &( seq.getArray()[nStop+1]) ,
+ seq.getLength() - nStop -1);
+ seq.realloc( seq.getLength() - ( nStop+1 - nFound ) );
+// str = String( (char * ) seq.getArray() , seq.getLen() );
+ }
+ }
+ }
+}
+
+// Checks, if enough data has been accumulated to recognize the encoding
+sal_Bool XMLFile2UTFConverter::isEncodingRecognizable( const Sequence< sal_Int8 > &seq)
+{
+ const sal_Int8 *pSource = seq.getConstArray();
+ sal_Bool bCheckIfFirstClosingBracketExsists = sal_False;
+
+ if( seq.getLength() < 8 ) {
+ // no recognition possible, when less than 8 bytes are available
+ return sal_False;
+ }
+
+ if( ! strncmp( (const char * ) pSource , "<?xml" , 4 ) ) {
+ // scan if the <?xml tag finishes within this buffer
+ bCheckIfFirstClosingBracketExsists = sal_True;
+ }
+ else if( ('<' == pSource[0] || '<' == pSource[2] ) &&
+ ( ('?' == pSource[4] || '?' == pSource[6] ) ) )
+ {
+ // check for utf-16
+ bCheckIfFirstClosingBracketExsists = sal_True;
+ }
+ else if( ( '<' == pSource[1] || '<' == pSource[3] ) &&
+ ( '?' == pSource[5] || '?' == pSource[7] ) )
+ {
+ // check for
+ bCheckIfFirstClosingBracketExsists = sal_True;
+ }
+
+ if( bCheckIfFirstClosingBracketExsists )
+ {
+ for( sal_Int32 i = 0; i < seq.getLength() ; i ++ )
+ {
+ // whole <?xml tag is valid
+ if( '>' == pSource[ i ] )
+ {
+ return sal_True;
+ }
+ }
+ return sal_False;
+ }
+
+ // No <? tag in front, no need for a bigger buffer
+ return sal_True;
+}
+
+sal_Bool XMLFile2UTFConverter::scanForEncoding( Sequence< sal_Int8 > &seq )
+{
+ const sal_uInt8 *pSource = reinterpret_cast<const sal_uInt8*>( seq.getConstArray() );
+ sal_Bool bReturn = sal_True;
+
+ if( seq.getLength() < 4 ) {
+ // no recognition possible, when less than 4 bytes are available
+ return sal_False;
+ }
+
+ // first level : detect possible file formats
+ if( ! strncmp( (const char * ) pSource , "<?xml" , 4 ) ) {
+
+ // scan for encoding
+ OString str( (const sal_Char *) pSource , seq.getLength() );
+
+ // cut sequence to first line break
+ //find first line break;
+ int nMax = str.indexOf( 10 );
+ if( nMax >= 0 )
+ {
+ str = str.copy( 0 , nMax );
+ }
+
+ int nFound = str.indexOf( " encoding" );
+ if( nFound < str.getLength() ) {
+ int nStop;
+ int nStart = str.indexOf( "\"" , nFound );
+ if( nStart < 0 || str.indexOf( "'" , nFound ) < nStart )
+ {
+ nStart = str.indexOf( "'" , nFound );
+ nStop = str.indexOf( "'" , nStart +1 );
+ }
+ else
+ {
+ nStop = str.indexOf( "\"" , nStart +1);
+ }
+ if( nStart >= 0 && nStop >= 0 && nStart+1 < nStop )
+ {
+ // encoding found finally
+ m_sEncoding = str.copy( nStart+1 , nStop - nStart - 1 );
+ }
+ }
+ }
+ else if( 0xFE == pSource[0] &&
+ 0xFF == pSource[1] ) {
+ // UTF-16 big endian
+ // conversion is done so that encoding information can be easily extracted
+ m_sEncoding = "utf-16";
+ }
+ else if( 0xFF == pSource[0] &&
+ 0xFE == pSource[1] ) {
+ // UTF-16 little endian
+ // conversion is done so that encoding information can be easily extracted
+ m_sEncoding = "utf-16";
+ }
+ else if( 0x00 == pSource[0] && 0x3c == pSource[1] && 0x00 == pSource[2] && 0x3f == pSource[3] ) {
+ // UTF-16 big endian without byte order mark (this is (strictly speaking) an error.)
+ // The byte order mark is simply added
+
+ // simply add the byte order mark !
+ seq.realloc( seq.getLength() + 2 );
+ memmove( &( seq.getArray()[2] ) , seq.getArray() , seq.getLength() - 2 );
+ ((sal_uInt8*)seq.getArray())[0] = 0xFE;
+ ((sal_uInt8*)seq.getArray())[1] = 0xFF;
+
+ m_sEncoding = "utf-16";
+ }
+ else if( 0x3c == pSource[0] && 0x00 == pSource[1] && 0x3f == pSource[2] && 0x00 == pSource[3] ) {
+ // UTF-16 little endian without byte order mark (this is (strictly speaking) an error.)
+ // The byte order mark is simply added
+
+ seq.realloc( seq.getLength() + 2 );
+ memmove( &( seq.getArray()[2] ) , seq.getArray() , seq.getLength() - 2 );
+ ((sal_uInt8*)seq.getArray())[0] = 0xFF;
+ ((sal_uInt8*)seq.getArray())[1] = 0xFE;
+
+ m_sEncoding = "utf-16";
+ }
+ else if( 0xEF == pSource[0] &&
+ 0xBB == pSource[1] &&
+ 0xBF == pSource[2] )
+ {
+ // UTF-8 BOM (byte order mark); signifies utf-8, and not byte order
+ // The BOM is removed.
+ memmove( seq.getArray(), &( seq.getArray()[3] ), seq.getLength()-3 );
+ seq.realloc( seq.getLength() - 3 );
+ m_sEncoding = "utf-8";
+ }
+ else if( 0x00 == pSource[0] && 0x00 == pSource[1] && 0x00 == pSource[2] && 0x3c == pSource[3] ) {
+ // UCS-4 big endian
+ m_sEncoding = "ucs-4";
+ }
+ else if( 0x3c == pSource[0] && 0x00 == pSource[1] && 0x00 == pSource[2] && 0x00 == pSource[3] ) {
+ // UCS-4 little endian
+ m_sEncoding = "ucs-4";
+ }
+ else if( 0x4c == pSource[0] && 0x6f == pSource[1] &&
+ 0xa7 == static_cast<unsigned char> (pSource[2]) &&
+ 0x94 == static_cast<unsigned char> (pSource[3]) ) {
+ // EBCDIC
+ bReturn = sal_False; // must be extended
+ }
+ else {
+ // other
+ // UTF8 is directly recognized by the parser.
+ bReturn = sal_False;
+ }
+
+ return bReturn;
+}
+
+void XMLFile2UTFConverter::initializeDecoding()
+{
+
+ if( m_sEncoding.getLength() )
+ {
+ rtl_TextEncoding encoding = rtl_getTextEncodingFromMimeCharset( m_sEncoding.getStr() );
+ if( encoding != RTL_TEXTENCODING_UTF8 )
+ {
+ m_pText2Unicode = new Text2UnicodeConverter( m_sEncoding );
+ m_pUnicode2Text = new Unicode2TextConverter( RTL_TEXTENCODING_UTF8 );
+ }
+ }
+}
+
+
+//----------------------------------------------
+//
+// Text2UnicodeConverter
+//
+//----------------------------------------------
+Text2UnicodeConverter::Text2UnicodeConverter( const OString &sEncoding )
+{
+ rtl_TextEncoding encoding = rtl_getTextEncodingFromMimeCharset( sEncoding.getStr() );
+ if( RTL_TEXTENCODING_DONTKNOW == encoding )
+ {
+ m_bCanContinue = sal_False;
+ m_bInitialized = sal_False;
+ }
+ else
+ {
+ init( encoding );
+ }
+}
+
+Text2UnicodeConverter::~Text2UnicodeConverter()
+{
+ if( m_bInitialized )
+ {
+ rtl_destroyTextToUnicodeContext( m_convText2Unicode , m_contextText2Unicode );
+ rtl_destroyUnicodeToTextConverter( m_convText2Unicode );
+ }
+}
+
+void Text2UnicodeConverter::init( rtl_TextEncoding encoding )
+{
+ m_bCanContinue = sal_True;
+ m_bInitialized = sal_True;
+
+ m_convText2Unicode = rtl_createTextToUnicodeConverter(encoding);
+ m_contextText2Unicode = rtl_createTextToUnicodeContext( m_convText2Unicode );
+ m_rtlEncoding = encoding;
+}
+
+
+Sequence<sal_Unicode> Text2UnicodeConverter::convert( const Sequence<sal_Int8> &seqText )
+{
+ sal_uInt32 uiInfo;
+ sal_Size nSrcCvtBytes = 0;
+ sal_Size nTargetCount = 0;
+ sal_Size nSourceCount = 0;
+
+ // the whole source size
+ sal_Int32 nSourceSize = seqText.getLength() + m_seqSource.getLength();
+ Sequence<sal_Unicode> seqUnicode ( nSourceSize );
+
+ const sal_Int8 *pbSource = seqText.getConstArray();
+ sal_Int8 *pbTempMem = 0;
+
+ if( m_seqSource.getLength() ) {
+ // put old rest and new byte sequence into one array
+ pbTempMem = new sal_Int8[ nSourceSize ];
+ memcpy( pbTempMem , m_seqSource.getConstArray() , m_seqSource.getLength() );
+ memcpy( &(pbTempMem[ m_seqSource.getLength() ]) , seqText.getConstArray() , seqText.getLength() );
+ pbSource = pbTempMem;
+
+ // set to zero again
+ m_seqSource = Sequence< sal_Int8 >();
+ }
+
+ while( sal_True ) {
+
+ /* All invalid characters are transformed to the unicode undefined char */
+ nTargetCount += rtl_convertTextToUnicode(
+ m_convText2Unicode,
+ m_contextText2Unicode,
+ ( const sal_Char * ) &( pbSource[nSourceCount] ),
+ nSourceSize - nSourceCount ,
+ &( seqUnicode.getArray()[ nTargetCount ] ),
+ seqUnicode.getLength() - nTargetCount,
+ RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT |
+ RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
+ RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT,
+ &uiInfo,
+ &nSrcCvtBytes );
+ nSourceCount += nSrcCvtBytes;
+
+ if( uiInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL ) {
+ // save necessary bytes for next conversion
+ seqUnicode.realloc( seqUnicode.getLength() * 2 );
+ continue;
+ }
+ break;
+ }
+ if( uiInfo & RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL ) {
+ m_seqSource.realloc( nSourceSize - nSourceCount );
+ memcpy( m_seqSource.getArray() , &(pbSource[nSourceCount]) , nSourceSize-nSourceCount );
+ }
+
+
+ if( pbTempMem ) {
+ delete [] pbTempMem;
+ }
+
+ // set to correct unicode size
+ seqUnicode.realloc( nTargetCount );
+
+ return seqUnicode;
+}
+
+
+
+//----------------------------------------------
+//
+// Unicode2TextConverter
+//
+//----------------------------------------------
+Unicode2TextConverter::Unicode2TextConverter( rtl_TextEncoding encoding )
+{
+ init( encoding );
+}
+
+
+Unicode2TextConverter::~Unicode2TextConverter()
+{
+ if( m_bInitialized ) {
+ rtl_destroyUnicodeToTextContext( m_convUnicode2Text , m_contextUnicode2Text );
+ rtl_destroyUnicodeToTextConverter( m_convUnicode2Text );
+ }
+}
+
+
+Sequence<sal_Int8> Unicode2TextConverter::convert(const sal_Unicode *puSource , sal_Int32 nSourceSize)
+{
+ sal_Unicode *puTempMem = 0;
+
+ if( m_seqSource.getLength() ) {
+ // For surrogates !
+ // put old rest and new byte sequence into one array
+ // In general when surrogates are used, they should be rarely
+ // cut off between two convert()-calls. So this code is used
+ // rarely and the extra copy is acceptable.
+ puTempMem = new sal_Unicode[ nSourceSize + m_seqSource.getLength()];
+ memcpy( puTempMem ,
+ m_seqSource.getConstArray() ,
+ m_seqSource.getLength() * sizeof( sal_Unicode ) );
+ memcpy(
+ &(puTempMem[ m_seqSource.getLength() ]) ,
+ puSource ,
+ nSourceSize*sizeof( sal_Unicode ) );
+ puSource = puTempMem;
+ nSourceSize += m_seqSource.getLength();
+
+ m_seqSource = Sequence< sal_Unicode > ();
+ }
+
+
+ sal_Size nTargetCount = 0;
+ sal_Size nSourceCount = 0;
+
+ sal_uInt32 uiInfo;
+ sal_Size nSrcCvtChars;
+
+ // take nSourceSize * 3 as preference
+ // this is an upper boundary for converting to utf8,
+ // which most often used as the target.
+ sal_Int32 nSeqSize = nSourceSize * 3;
+
+ Sequence<sal_Int8> seqText( nSeqSize );
+ sal_Char *pTarget = (sal_Char *) seqText.getArray();
+ while( sal_True ) {
+
+ nTargetCount += rtl_convertUnicodeToText(
+ m_convUnicode2Text,
+ m_contextUnicode2Text,
+ &( puSource[nSourceCount] ),
+ nSourceSize - nSourceCount ,
+ &( pTarget[nTargetCount] ),
+ nSeqSize - nTargetCount,
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_DEFAULT |
+ RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT ,
+ &uiInfo,
+ &nSrcCvtChars);
+ nSourceCount += nSrcCvtChars;
+
+ if( uiInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL ) {
+ nSeqSize = nSeqSize *2;
+ seqText.realloc( nSeqSize ); // double array size
+ pTarget = ( sal_Char * ) seqText.getArray();
+ continue;
+ }
+ break;
+ }
+
+ // for surrogates
+ if( uiInfo & RTL_UNICODETOTEXT_INFO_SRCBUFFERTOSMALL ) {
+ m_seqSource.realloc( nSourceSize - nSourceCount );
+ memcpy( m_seqSource.getArray() ,
+ &(puSource[nSourceCount]),
+ (nSourceSize - nSourceCount) * sizeof( sal_Unicode ) );
+ }
+
+ if( puTempMem ) {
+ delete [] puTempMem;
+ }
+
+ // reduce the size of the buffer (fast, no copy necessary)
+ seqText.realloc( nTargetCount );
+
+ return seqText;
+}
+
+void Unicode2TextConverter::init( rtl_TextEncoding encoding )
+{
+ m_bCanContinue = sal_True;
+ m_bInitialized = sal_True;
+
+ m_convUnicode2Text = rtl_createUnicodeToTextConverter( encoding );
+ m_contextUnicode2Text = rtl_createUnicodeToTextContext( m_convUnicode2Text );
+ m_rtlEncoding = encoding;
+};
+
+
+}
diff --git a/sax/source/fastparser/facreg.cxx b/sax/source/fastparser/facreg.cxx
new file mode 100644
index 000000000000..1916a9740f1a
--- /dev/null
+++ b/sax/source/fastparser/facreg.cxx
@@ -0,0 +1,106 @@
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/weak.hxx>
+#include <cppuhelper/implbase2.hxx>
+
+#include "../tools/fastserializer.hxx"
+#include "fastparser.hxx"
+
+using namespace sax_fastparser;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::registry;
+using ::rtl::OUString;
+using namespace ::com::sun::star::lang;
+
+namespace sax_fastparser
+{
+
+//--------------------------------------
+// the extern interface
+//---------------------------------------
+Reference< XInterface > SAL_CALL FastSaxParser_CreateInstance( const Reference< XMultiServiceFactory > & ) throw(Exception)
+{
+ FastSaxParser *p = new FastSaxParser;
+ return Reference< XInterface > ( (OWeakObject * ) p );
+}
+
+Reference< XInterface > SAL_CALL FastSaxSerializer_CreateInstance( const Reference< XMultiServiceFactory > & ) throw(Exception)
+{
+ FastSaxSerializer *p = new FastSaxSerializer;
+ return Reference< XInterface > ( (OWeakObject * ) p );
+}
+}
+
+extern "C"
+{
+
+void SAL_CALL component_getImplementationEnvironment(
+ const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ )
+{
+ *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
+}
+
+
+sal_Bool SAL_CALL component_writeInfo(
+ void * /*pServiceManager*/, void * pRegistryKey )
+{
+ if (pRegistryKey)
+ {
+ try
+ {
+ Reference< XRegistryKey > xKey( reinterpret_cast< XRegistryKey * >( pRegistryKey ) );
+
+ Reference< XRegistryKey > xNewKey( xKey->createKey(
+ OUString::createFromAscii( "/" PARSER_IMPLEMENTATION_NAME "/UNO/SERVICES" ) ) );
+ xNewKey->createKey( OUString::createFromAscii( PARSER_SERVICE_NAME ) );
+
+ Reference< XRegistryKey > xNewKey1( xKey->createKey(
+ OUString::createFromAscii( "/" SERIALIZER_IMPLEMENTATION_NAME "/UNO/SERVICES" ) ) );
+ xNewKey1->createKey( OUString::createFromAscii( SERIALIZER_SERVICE_NAME ) );
+
+ return sal_True;
+ }
+ catch (InvalidRegistryException &)
+ {
+ OSL_ENSURE( sal_False, "### InvalidRegistryException!" );
+ }
+ }
+ return sal_False;
+}
+
+void * SAL_CALL component_getFactory( const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ )
+{
+ void * pRet = 0;
+
+ if (pServiceManager )
+ {
+ Reference< XSingleServiceFactory > xRet;
+ Reference< XMultiServiceFactory > xSMgr( reinterpret_cast< XMultiServiceFactory * > ( pServiceManager ) );
+
+ OUString aImplementationName( OUString::createFromAscii( pImplName ) );
+
+ if (aImplementationName == OUString( RTL_CONSTASCII_USTRINGPARAM( PARSER_IMPLEMENTATION_NAME ) ) )
+ {
+ xRet = createSingleFactory( xSMgr, aImplementationName,
+ FastSaxParser_CreateInstance,
+ FastSaxParser::getSupportedServiceNames_Static() );
+ }
+ else if (aImplementationName == OUString( RTL_CONSTASCII_USTRINGPARAM( SERIALIZER_IMPLEMENTATION_NAME ) ) )
+ {
+ xRet = createSingleFactory( xSMgr, aImplementationName,
+ FastSaxSerializer_CreateInstance,
+ FastSaxSerializer::getSupportedServiceNames_Static() );
+ }
+
+ if (xRet.is())
+ {
+ xRet->acquire();
+ pRet = xRet.get();
+ }
+ }
+
+ return pRet;
+}
+
+
+}
diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx
new file mode 100644
index 000000000000..1a4cc9278e1e
--- /dev/null
+++ b/sax/source/fastparser/fastparser.cxx
@@ -0,0 +1,953 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+//#include <stdlib.h>
+//#include <sal/alloca.h>
+
+#include <boost/scoped_ptr.hpp>
+
+#include <osl/diagnose.h>
+#include <rtl/ustrbuf.hxx>
+
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/xml/sax/XFastContextHandler.hpp>
+#include <com/sun/star/xml/sax/SAXParseException.hpp>
+#include <com/sun/star/xml/sax/FastToken.hpp>
+
+#include "fastparser.hxx"
+
+#include <string.h>
+
+using ::rtl::OString;
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+using namespace ::std;
+using namespace ::osl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::xml::sax;
+//using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::io;
+
+namespace sax_fastparser {
+
+// --------------------------------------------------------------------
+
+struct SaxContextImpl
+{
+ Reference< XFastContextHandler > mxContext;
+ sal_uInt32 mnNamespaceCount;
+ sal_Int32 mnElementToken;
+ OUString maNamespace;
+ OUString maElementName;
+
+ SaxContextImpl() { mnNamespaceCount = 0; mnElementToken = 0; }
+ SaxContextImpl( const SaxContextImplPtr& p ) { mnNamespaceCount = p->mnNamespaceCount; mnElementToken = p->mnElementToken; maNamespace = p->maNamespace; }
+};
+
+// --------------------------------------------------------------------
+
+struct NamespaceDefine
+{
+ OString maPrefix;
+ sal_Int32 mnToken;
+ OUString maNamespaceURL;
+
+ NamespaceDefine( const OString& rPrefix, sal_Int32 nToken, const OUString& rNamespaceURL ) : maPrefix( rPrefix ), mnToken( nToken ), maNamespaceURL( rNamespaceURL ) {}
+};
+
+// --------------------------------------------------------------------
+// FastLocatorImpl
+// --------------------------------------------------------------------
+
+class FastSaxParser;
+
+class FastLocatorImpl : public WeakImplHelper1< XLocator >
+{
+public:
+ FastLocatorImpl( FastSaxParser *p ) : mpParser(p) {}
+
+ void dispose() { mpParser = 0; }
+ void checkDispose() throw (RuntimeException) { if( !mpParser ) throw DisposedException(); }
+
+ //XLocator
+ virtual sal_Int32 SAL_CALL getColumnNumber(void) throw (RuntimeException);
+ virtual sal_Int32 SAL_CALL getLineNumber(void) throw (RuntimeException);
+ virtual OUString SAL_CALL getPublicId(void) throw (RuntimeException);
+ virtual OUString SAL_CALL getSystemId(void) throw (RuntimeException);
+
+private:
+ FastSaxParser *mpParser;
+};
+
+// --------------------------------------------------------------------
+// FastSaxParser
+// --------------------------------------------------------------------
+
+//---------------------------------------------
+// the implementation part
+//---------------------------------------------
+
+extern "C" {
+
+static void call_callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts)
+{
+ FastSaxParser* pFastParser = reinterpret_cast< FastSaxParser* >( userData );
+ pFastParser->callbackStartElement( name, atts );
+}
+
+static void call_callbackEndElement(void *userData, const XML_Char *name)
+{
+ FastSaxParser* pFastParser = reinterpret_cast< FastSaxParser* >( userData );
+ pFastParser->callbackEndElement( name );
+}
+
+static void call_callbackCharacters( void *userData , const XML_Char *s , int nLen )
+{
+ FastSaxParser* pFastParser = reinterpret_cast< FastSaxParser* >( userData );
+ pFastParser->callbackCharacters( s, nLen );
+}
+
+static int call_callbackExternalEntityRef( XML_Parser parser,
+ const XML_Char *openEntityNames, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId )
+{
+ FastSaxParser* pFastParser = reinterpret_cast< FastSaxParser* >( XML_GetUserData( parser ) );
+ return pFastParser->callbackExternalEntityRef( parser, openEntityNames, base, systemId, publicId );
+}
+
+} // extern "C"
+
+// --------------------------------------------------------------------
+// FastLocatorImpl implementation
+// --------------------------------------------------------------------
+
+sal_Int32 SAL_CALL FastLocatorImpl::getColumnNumber(void) throw (RuntimeException)
+{
+ checkDispose();
+ return XML_GetCurrentColumnNumber( mpParser->getEntity().mpParser );
+}
+
+// --------------------------------------------------------------------
+
+sal_Int32 SAL_CALL FastLocatorImpl::getLineNumber(void) throw (RuntimeException)
+{
+ checkDispose();
+ return XML_GetCurrentLineNumber( mpParser->getEntity().mpParser );
+}
+
+// --------------------------------------------------------------------
+
+OUString SAL_CALL FastLocatorImpl::getPublicId(void) throw (RuntimeException)
+{
+ checkDispose();
+ return mpParser->getEntity().maStructSource.sPublicId;
+}
+// --------------------------------------------------------------------
+
+OUString SAL_CALL FastLocatorImpl::getSystemId(void) throw (RuntimeException)
+{
+ checkDispose();
+ return mpParser->getEntity().maStructSource.sSystemId;
+}
+
+// --------------------------------------------------------------------
+
+ParserData::ParserData()
+{
+}
+
+ParserData::~ParserData()
+{
+}
+
+// --------------------------------------------------------------------
+
+Entity::Entity( const ParserData& rData ) :
+ ParserData( rData )
+{
+ // performance-Improvment. Reference is needed when calling the startTag callback.
+ // Handing out the same object with every call is allowed (see sax-specification)
+ mxAttributes.set( new FastAttributeList( mxTokenHandler ) );
+}
+
+Entity::~Entity()
+{
+}
+
+// --------------------------------------------------------------------
+// FastSaxParser implementation
+// --------------------------------------------------------------------
+
+FastSaxParser::FastSaxParser()
+{
+ mxDocumentLocator.set( new FastLocatorImpl( this ) );
+}
+
+// --------------------------------------------------------------------
+
+FastSaxParser::~FastSaxParser()
+{
+ if( mxDocumentLocator.is() )
+ mxDocumentLocator->dispose();
+}
+
+// --------------------------------------------------------------------
+
+void FastSaxParser::pushContext()
+{
+ Entity& rEntity = getEntity();
+ if( rEntity.maContextStack.empty() )
+ {
+ rEntity.maContextStack.push( SaxContextImplPtr( new SaxContextImpl ) );
+ DefineNamespace( OString("xml"), "http://www.w3.org/XML/1998/namespace");
+ }
+ else
+ {
+ rEntity.maContextStack.push( SaxContextImplPtr( new SaxContextImpl( rEntity.maContextStack.top() ) ) );
+ }
+}
+
+// --------------------------------------------------------------------
+
+void FastSaxParser::popContext()
+{
+ Entity& rEntity = getEntity();
+ OSL_ENSURE( !rEntity.maContextStack.empty(), "sax::FastSaxParser::popContext(), pop without push?" );
+ if( !rEntity.maContextStack.empty() )
+ rEntity.maContextStack.pop();
+}
+
+// --------------------------------------------------------------------
+
+void FastSaxParser::DefineNamespace( const OString& rPrefix, const sal_Char* pNamespaceURL )
+{
+ Entity& rEntity = getEntity();
+ OSL_ENSURE( !rEntity.maContextStack.empty(), "sax::FastSaxParser::DefineNamespace(), I need a context!" );
+ if( !rEntity.maContextStack.empty() )
+ {
+ sal_uInt32 nOffset = rEntity.maContextStack.top()->mnNamespaceCount++;
+
+ if( rEntity.maNamespaceDefines.size() <= nOffset )
+ rEntity.maNamespaceDefines.resize( rEntity.maNamespaceDefines.size() + 64 );
+
+ const OUString aNamespaceURL( pNamespaceURL, strlen( pNamespaceURL ), RTL_TEXTENCODING_UTF8 );
+ rEntity.maNamespaceDefines[nOffset].reset( new NamespaceDefine( rPrefix, GetNamespaceToken( aNamespaceURL ), aNamespaceURL ) );
+ }
+}
+
+// --------------------------------------------------------------------
+
+sal_Int32 FastSaxParser::GetToken( const OString& rToken )
+{
+ Sequence< sal_Int8 > aSeq( (sal_Int8*)rToken.getStr(), rToken.getLength() );
+
+ return getEntity().mxTokenHandler->getTokenFromUTF8( aSeq );
+}
+
+sal_Int32 FastSaxParser::GetToken( const sal_Char* pToken, sal_Int32 nLen /* = 0 */ )
+{
+ if( !nLen )
+ nLen = strlen( pToken );
+
+ Sequence< sal_Int8 > aSeq( (sal_Int8*)pToken, nLen );
+
+ return getEntity().mxTokenHandler->getTokenFromUTF8( aSeq );
+}
+
+// --------------------------------------------------------------------
+
+sal_Int32 FastSaxParser::GetTokenWithPrefix( const OString& rPrefix, const OString& rName ) throw (SAXException)
+{
+ sal_Int32 nNamespaceToken = FastToken::DONTKNOW;
+
+ Entity& rEntity = getEntity();
+ sal_uInt32 nNamespace = rEntity.maContextStack.top()->mnNamespaceCount;
+ while( nNamespace-- )
+ {
+ if( rEntity.maNamespaceDefines[nNamespace]->maPrefix == rPrefix )
+ {
+ nNamespaceToken = rEntity.maNamespaceDefines[nNamespace]->mnToken;
+ break;
+ }
+
+ if( !nNamespace )
+ throw SAXException(); // prefix that has no defined namespace url
+ }
+
+ if( nNamespaceToken != FastToken::DONTKNOW )
+ {
+ sal_Int32 nNameToken = GetToken( rName.getStr(), rName.getLength() );
+ if( nNameToken != FastToken::DONTKNOW )
+ return nNamespaceToken | nNameToken;
+ }
+
+ return FastToken::DONTKNOW;
+}
+
+sal_Int32 FastSaxParser::GetTokenWithPrefix( const sal_Char*pPrefix, int nPrefixLen, const sal_Char* pName, int nNameLen ) throw (SAXException)
+{
+ sal_Int32 nNamespaceToken = FastToken::DONTKNOW;
+
+ Entity& rEntity = getEntity();
+ sal_uInt32 nNamespace = rEntity.maContextStack.top()->mnNamespaceCount;
+ while( nNamespace-- )
+ {
+ const OString& rPrefix( rEntity.maNamespaceDefines[nNamespace]->maPrefix );
+ if( (rPrefix.getLength() == nPrefixLen) &&
+ (strncmp( rPrefix.getStr(), pPrefix, nPrefixLen ) == 0 ) )
+ {
+ nNamespaceToken = rEntity.maNamespaceDefines[nNamespace]->mnToken;
+ break;
+ }
+
+ if( !nNamespace )
+ throw SAXException(); // prefix that has no defined namespace url
+ }
+
+ if( nNamespaceToken != FastToken::DONTKNOW )
+ {
+ sal_Int32 nNameToken = GetToken( pName, nNameLen );
+ if( nNameToken != FastToken::DONTKNOW )
+ return nNamespaceToken | nNameToken;
+ }
+
+ return FastToken::DONTKNOW;
+}
+
+// --------------------------------------------------------------------
+
+sal_Int32 FastSaxParser::GetNamespaceToken( const OUString& rNamespaceURL )
+{
+ NamespaceMap::iterator aIter( maNamespaceMap.find( rNamespaceURL ) );
+ if( aIter != maNamespaceMap.end() )
+ return (*aIter).second;
+ else
+ return FastToken::DONTKNOW;
+}
+
+// --------------------------------------------------------------------
+
+OUString FastSaxParser::GetNamespaceURL( const OString& rPrefix ) throw (SAXException)
+{
+ Entity& rEntity = getEntity();
+ if( !rEntity.maContextStack.empty() )
+ {
+ sal_uInt32 nNamespace = rEntity.maContextStack.top()->mnNamespaceCount;
+ while( nNamespace-- )
+ if( rEntity.maNamespaceDefines[nNamespace]->maPrefix == rPrefix )
+ return rEntity.maNamespaceDefines[nNamespace]->maNamespaceURL;
+ }
+
+ throw SAXException(); // prefix that has no defined namespace url
+}
+
+OUString FastSaxParser::GetNamespaceURL( const sal_Char*pPrefix, int nPrefixLen ) throw(SAXException)
+{
+ Entity& rEntity = getEntity();
+ if( pPrefix && !rEntity.maContextStack.empty() )
+ {
+ sal_uInt32 nNamespace = rEntity.maContextStack.top()->mnNamespaceCount;
+ while( nNamespace-- )
+ {
+ const OString& rPrefix( rEntity.maNamespaceDefines[nNamespace]->maPrefix );
+ if( (rPrefix.getLength() == nPrefixLen) &&
+ (strncmp( rPrefix.getStr(), pPrefix, nPrefixLen ) == 0 ) )
+ {
+ return rEntity.maNamespaceDefines[nNamespace]->maNamespaceURL;
+ }
+ }
+ }
+
+ throw SAXException(); // prefix that has no defined namespace url
+}
+
+// --------------------------------------------------------------------
+
+sal_Int32 FastSaxParser::GetTokenWithNamespaceURL( const OUString& rNamespaceURL, const sal_Char* pName, int nNameLen )
+{
+ sal_Int32 nNamespaceToken = GetNamespaceToken( rNamespaceURL );
+
+ if( nNamespaceToken != FastToken::DONTKNOW )
+ {
+ sal_Int32 nNameToken = GetToken( pName, nNameLen );
+ if( nNameToken != FastToken::DONTKNOW )
+ return nNamespaceToken | nNameToken;
+ }
+
+ return FastToken::DONTKNOW;
+}
+
+// --------------------------------------------------------------------
+
+void FastSaxParser::splitName( const XML_Char *pwName, const XML_Char *&rpPrefix, sal_Int32 &rPrefixLen, const XML_Char *&rpName, sal_Int32 &rNameLen )
+{
+ XML_Char *p;
+ for( p = const_cast< XML_Char* >( pwName ), rNameLen = 0, rPrefixLen = 0; *p; p++ )
+ {
+ if( *p == ':' )
+ {
+ rPrefixLen = p - pwName;
+ rNameLen = 0;
+ }
+ else
+ {
+ rNameLen++;
+ }
+ }
+ if( rPrefixLen )
+ {
+ rpPrefix = pwName;
+ rpName = &pwName[ rPrefixLen + 1 ];
+ }
+ else
+ {
+ rpPrefix = 0;
+ rpName = pwName;
+ }
+}
+
+/***************
+*
+* parseStream does Parser-startup initializations. The FastSaxParser::parse() method does
+* the file-specific initialization work. (During a parser run, external files may be opened)
+*
+****************/
+void FastSaxParser::parseStream( const InputSource& maStructSource) throw (SAXException, IOException, RuntimeException)
+{
+ // Only one text at one time
+ MutexGuard guard( maMutex );
+
+ Entity entity( maData );
+ entity.maStructSource = maStructSource;
+
+ if( !entity.maStructSource.aInputStream.is() )
+ throw SAXException( OUString( RTL_CONSTASCII_USTRINGPARAM( "No input source" ) ), Reference< XInterface >(), Any() );
+
+ entity.maConverter.setInputStream( entity.maStructSource.aInputStream );
+ if( entity.maStructSource.sEncoding.getLength() )
+ entity.maConverter.setEncoding( OUStringToOString( entity.maStructSource.sEncoding, RTL_TEXTENCODING_ASCII_US ) );
+
+ // create parser with proper encoding
+ entity.mpParser = XML_ParserCreate( 0 );
+ if( !entity.mpParser )
+ throw SAXException( OUString( RTL_CONSTASCII_USTRINGPARAM( "Couldn't create parser" ) ), Reference< XInterface >(), Any() );
+
+ // set all necessary C-Callbacks
+ XML_SetUserData( entity.mpParser, this );
+ XML_SetElementHandler( entity.mpParser, call_callbackStartElement, call_callbackEndElement );
+ XML_SetCharacterDataHandler( entity.mpParser, call_callbackCharacters );
+ XML_SetExternalEntityRefHandler( entity.mpParser, call_callbackExternalEntityRef );
+
+ pushEntity( entity );
+ try
+ {
+ // start the document
+ if( entity.mxDocumentHandler.is() )
+ {
+ Reference< XLocator > xLoc( mxDocumentLocator.get() );
+ entity.mxDocumentHandler->setDocumentLocator( xLoc );
+ entity.mxDocumentHandler->startDocument();
+ }
+
+ parse();
+
+ // finish document
+ if( entity.mxDocumentHandler.is() )
+ {
+ entity.mxDocumentHandler->endDocument();
+ }
+ }
+ catch( SAXException & )
+ {
+ popEntity();
+ XML_ParserFree( entity.mpParser );
+ throw;
+ }
+ catch( IOException & )
+ {
+ popEntity();
+ XML_ParserFree( entity.mpParser );
+ throw;
+ }
+ catch( RuntimeException & )
+ {
+ popEntity();
+ XML_ParserFree( entity.mpParser );
+ throw;
+ }
+
+ popEntity();
+ XML_ParserFree( entity.mpParser );
+}
+
+void FastSaxParser::setFastDocumentHandler( const Reference< XFastDocumentHandler >& Handler ) throw (RuntimeException)
+{
+ maData.mxDocumentHandler = Handler;
+}
+
+void SAL_CALL FastSaxParser::setTokenHandler( const Reference< XFastTokenHandler >& Handler ) throw (RuntimeException)
+{
+ maData.mxTokenHandler = Handler;
+}
+
+void SAL_CALL FastSaxParser::registerNamespace( const OUString& NamespaceURL, sal_Int32 NamespaceToken ) throw (IllegalArgumentException, RuntimeException)
+{
+ if( NamespaceToken >= FastToken::NAMESPACE )
+ {
+ if( GetNamespaceToken( NamespaceURL ) == FastToken::DONTKNOW )
+ {
+ maNamespaceMap[ NamespaceURL ] = NamespaceToken;
+ return;
+ }
+ }
+ throw IllegalArgumentException();
+}
+
+void FastSaxParser::setErrorHandler(const Reference< XErrorHandler > & Handler) throw (RuntimeException)
+{
+ maData.mxErrorHandler = Handler;
+}
+
+void FastSaxParser::setEntityResolver(const Reference < XEntityResolver > & Resolver) throw (RuntimeException)
+{
+ maData.mxEntityResolver = Resolver;
+}
+
+void FastSaxParser::setLocale( const Locale & Locale ) throw (RuntimeException)
+{
+ maData.maLocale = Locale;
+}
+
+Sequence< OUString > FastSaxParser::getSupportedServiceNames_Static(void)
+{
+ Sequence<OUString> aRet(1);
+ aRet.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(PARSER_SERVICE_NAME) );
+ return aRet;
+}
+
+// XServiceInfo
+OUString FastSaxParser::getImplementationName() throw (RuntimeException)
+{
+ return OUString::createFromAscii( PARSER_IMPLEMENTATION_NAME );
+}
+
+// XServiceInfo
+sal_Bool FastSaxParser::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 > FastSaxParser::getSupportedServiceNames(void) throw (RuntimeException)
+{
+
+ Sequence<OUString> seq(1);
+ seq.getArray()[0] = OUString::createFromAscii( PARSER_SERVICE_NAME );
+ return seq;
+}
+
+
+/*---------------------------------------
+*
+* Helper functions and classes
+*
+*-------------------------------------------*/
+
+namespace {
+
+OUString lclGetErrorMessage( XML_Error xmlE, const OUString& sSystemId, sal_Int32 nLine )
+{
+ const sal_Char* pMessage = "";
+ switch( xmlE )
+ {
+ case XML_ERROR_NONE: pMessage = "No"; break;
+ case XML_ERROR_NO_MEMORY: pMessage = "no memory"; break;
+ case XML_ERROR_SYNTAX: pMessage = "syntax"; break;
+ case XML_ERROR_NO_ELEMENTS: pMessage = "no elements"; break;
+ case XML_ERROR_INVALID_TOKEN: pMessage = "invalid token"; break;
+ case XML_ERROR_UNCLOSED_TOKEN: pMessage = "unclosed token"; break;
+ case XML_ERROR_PARTIAL_CHAR: pMessage = "partial char"; break;
+ case XML_ERROR_TAG_MISMATCH: pMessage = "tag mismatch"; break;
+ case XML_ERROR_DUPLICATE_ATTRIBUTE: pMessage = "duplicate attribute"; break;
+ case XML_ERROR_JUNK_AFTER_DOC_ELEMENT: pMessage = "junk after doc element"; break;
+ case XML_ERROR_PARAM_ENTITY_REF: pMessage = "parameter entity reference"; break;
+ case XML_ERROR_UNDEFINED_ENTITY: pMessage = "undefined entity"; break;
+ case XML_ERROR_RECURSIVE_ENTITY_REF: pMessage = "recursive entity reference"; break;
+ case XML_ERROR_ASYNC_ENTITY: pMessage = "async entity"; break;
+ case XML_ERROR_BAD_CHAR_REF: pMessage = "bad char reference"; break;
+ case XML_ERROR_BINARY_ENTITY_REF: pMessage = "binary entity reference"; break;
+ case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF: pMessage = "attribute external entity reference"; break;
+ case XML_ERROR_MISPLACED_XML_PI: pMessage = "misplaced xml processing instruction"; break;
+ case XML_ERROR_UNKNOWN_ENCODING: pMessage = "unknown encoding"; break;
+ case XML_ERROR_INCORRECT_ENCODING: pMessage = "incorrect encoding"; break;
+ case XML_ERROR_UNCLOSED_CDATA_SECTION: pMessage = "unclosed cdata section"; break;
+ case XML_ERROR_EXTERNAL_ENTITY_HANDLING: pMessage = "external entity reference"; break;
+ case XML_ERROR_NOT_STANDALONE: pMessage = "not standalone"; break;
+ default:;
+ }
+
+ OUStringBuffer aBuffer( sal_Unicode( '[' ) );
+ aBuffer.append( sSystemId );
+ aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( " line " ) );
+ aBuffer.append( nLine );
+ aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "]: " ) );
+ aBuffer.appendAscii( pMessage );
+ aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( " error" ) );
+ return aBuffer.makeStringAndClear();
+}
+
+} // namespace
+
+// starts parsing with actual parser !
+void FastSaxParser::parse()
+{
+ const int BUFFER_SIZE = 16 * 1024;
+ Sequence< sal_Int8 > seqOut( BUFFER_SIZE );
+
+ Entity& rEntity = getEntity();
+ int nRead = 0;
+ do
+ {
+ nRead = rEntity.maConverter.readAndConvert( seqOut, BUFFER_SIZE );
+ if( nRead <= 0 )
+ {
+ XML_Parse( rEntity.mpParser, (const char*) seqOut.getConstArray(), 0, 1 );
+ break;
+ }
+
+ bool bContinue = XML_Parse( rEntity.mpParser, (const char*) seqOut.getConstArray(), nRead, 0 ) != 0;
+ // callbacks used inside XML_Parse may have caught an exception
+ if( !bContinue || rEntity.maSavedException.hasValue() )
+ {
+ // Error during parsing !
+ XML_Error xmlE = XML_GetErrorCode( rEntity.mpParser );
+ OUString sSystemId = mxDocumentLocator->getSystemId();
+ sal_Int32 nLine = mxDocumentLocator->getLineNumber();
+
+ SAXParseException aExcept(
+ lclGetErrorMessage( xmlE, sSystemId, nLine ),
+ Reference< XInterface >(),
+ Any( &rEntity.maSavedException, getCppuType( &rEntity.maSavedException ) ),
+ mxDocumentLocator->getPublicId(),
+ mxDocumentLocator->getSystemId(),
+ mxDocumentLocator->getLineNumber(),
+ mxDocumentLocator->getColumnNumber()
+ );
+
+ // error handler is set, it may throw the exception
+ if( rEntity.mxErrorHandler.is() )
+ rEntity.mxErrorHandler->fatalError( Any( aExcept ) );
+
+ // error handler has not thrown, but parsing cannot go on, the
+ // exception MUST be thrown
+ throw aExcept;
+ }
+ }
+ while( nRead > 0 );
+}
+
+//------------------------------------------
+//
+// The C-Callbacks
+//
+//-----------------------------------------
+
+namespace {
+
+struct AttributeData
+{
+ OString maPrefix;
+ OString maName;
+ OString maValue;
+};
+
+} // namespace
+
+void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char** awAttributes )
+{
+ Reference< XFastContextHandler > xParentContext;
+ Entity& rEntity = getEntity();
+ if( !rEntity.maContextStack.empty() )
+ {
+ xParentContext = rEntity.maContextStack.top()->mxContext;
+ if( !xParentContext.is() )
+ {
+ // we ignore current elements, so no processing needed
+ pushContext();
+ return;
+ }
+ }
+
+ pushContext();
+
+ rEntity.mxAttributes->clear();
+
+ // create attribute map and process namespace instructions
+ int i = 0;
+ sal_Int32 nNameLen, nPrefixLen;
+ const XML_Char *pName;
+ const XML_Char *pPrefix;
+
+ try
+ {
+ /* #158414# Each element may define new namespaces, also for attribues.
+ First, process all namespace attributes and cache other attributes in a
+ vector. Second, process the attributes after namespaces have been
+ initialized. */
+ ::std::vector< AttributeData > aAttribs;
+
+ // #158414# first: get namespaces
+ for( ; awAttributes[i]; i += 2 )
+ {
+ OSL_ASSERT( awAttributes[i+1] );
+
+ splitName( awAttributes[i], pPrefix, nPrefixLen, pName, nNameLen );
+ if( nPrefixLen )
+ {
+ if( (nPrefixLen == 5) && (strncmp( pPrefix, "xmlns", 5 ) == 0) )
+ {
+ DefineNamespace( OString( pName, nNameLen ), awAttributes[i+1] );
+ }
+ else
+ {
+ aAttribs.resize( aAttribs.size() + 1 );
+ aAttribs.back().maPrefix = OString( pPrefix, nPrefixLen );
+ aAttribs.back().maName = OString( pName, nNameLen );
+ aAttribs.back().maValue = OString( awAttributes[i+1] );
+ }
+ }
+ else
+ {
+ if( (nNameLen == 5) && (strcmp( pName, "xmlns" ) == 0) )
+ {
+ // namespace of the element found
+ rEntity.maContextStack.top()->maNamespace = OUString( awAttributes[i+1], strlen( awAttributes[i+1] ), RTL_TEXTENCODING_UTF8 );
+ }
+ else
+ {
+ aAttribs.resize( aAttribs.size() + 1 );
+ aAttribs.back().maName = OString( pName, nNameLen );
+ aAttribs.back().maValue = OString( awAttributes[i+1] );
+ }
+ }
+ }
+
+ // #158414# second: fill attribute list with other attributes
+ for( ::std::vector< AttributeData >::const_iterator aIt = aAttribs.begin(), aEnd = aAttribs.end(); aIt != aEnd; ++aIt )
+ {
+ if( aIt->maPrefix.getLength() > 0 )
+ {
+ sal_Int32 nAttributeToken = GetTokenWithPrefix( aIt->maPrefix, aIt->maName );
+ if( nAttributeToken != FastToken::DONTKNOW )
+ rEntity.mxAttributes->add( nAttributeToken, aIt->maValue );
+ else
+ rEntity.mxAttributes->addUnknown( GetNamespaceURL( aIt->maPrefix ), aIt->maName, aIt->maValue );
+ }
+ else
+ {
+ sal_Int32 nAttributeToken = GetToken( aIt->maName );
+ if( nAttributeToken != FastToken::DONTKNOW )
+ rEntity.mxAttributes->add( nAttributeToken, aIt->maValue );
+ else
+ rEntity.mxAttributes->addUnknown( aIt->maName, aIt->maValue );
+ }
+ }
+
+ sal_Int32 nElementToken;
+ splitName( pwName, pPrefix, nPrefixLen, pName, nNameLen );
+ if( nPrefixLen > 0 )
+ nElementToken = GetTokenWithPrefix( pPrefix, nPrefixLen, pName, nNameLen );
+ else if( rEntity.maContextStack.top()->maNamespace.getLength() > 0 )
+ nElementToken = GetTokenWithNamespaceURL( rEntity.maContextStack.top()->maNamespace, pName, nNameLen );
+ else
+ nElementToken = GetToken( pName );
+ rEntity.maContextStack.top()->mnElementToken = nElementToken;
+
+ Reference< XFastAttributeList > xAttr( rEntity.mxAttributes.get() );
+ Reference< XFastContextHandler > xContext;
+ if( nElementToken == FastToken::DONTKNOW )
+ {
+ if( nPrefixLen > 0 )
+ rEntity.maContextStack.top()->maNamespace = GetNamespaceURL( pPrefix, nPrefixLen );
+
+ const OUString aNamespace( rEntity.maContextStack.top()->maNamespace );
+ const OUString aElementName( pPrefix, nPrefixLen, RTL_TEXTENCODING_UTF8 );
+ rEntity.maContextStack.top()->maElementName = aElementName;
+
+ if( xParentContext.is() )
+ xContext = xParentContext->createUnknownChildContext( aNamespace, aElementName, xAttr );
+ else
+ xContext = rEntity.mxDocumentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
+
+ if( xContext.is() )
+ {
+ rEntity.maContextStack.top()->mxContext = xContext;
+ xContext->startUnknownElement( aNamespace, aElementName, xAttr );
+ }
+ }
+ else
+ {
+ if( xParentContext.is() )
+ xContext = xParentContext->createFastChildContext( nElementToken, xAttr );
+ else
+ xContext = rEntity.mxDocumentHandler->createFastChildContext( nElementToken, xAttr );
+
+
+ if( xContext.is() )
+ {
+ rEntity.maContextStack.top()->mxContext = xContext;
+ xContext->startFastElement( nElementToken, xAttr );
+ }
+ }
+ }
+ catch( Exception& e )
+ {
+ rEntity.maSavedException <<= e;
+ }
+}
+
+void FastSaxParser::callbackEndElement( const XML_Char* )
+{
+ Entity& rEntity = getEntity();
+ OSL_ENSURE( !rEntity.maContextStack.empty(), "FastSaxParser::callbackEndElement - no context" );
+ if( !rEntity.maContextStack.empty() )
+ {
+ SaxContextImplPtr pContext = rEntity.maContextStack.top();
+ const Reference< XFastContextHandler >& xContext( pContext->mxContext );
+ if( xContext.is() ) try
+ {
+ sal_Int32 nElementToken = pContext->mnElementToken;
+ if( nElementToken != FastToken::DONTKNOW )
+ xContext->endFastElement( nElementToken );
+ else
+ xContext->endUnknownElement( pContext->maNamespace, pContext->maElementName );
+ }
+ catch( Exception& e )
+ {
+ rEntity.maSavedException <<= e;
+ }
+
+ popContext();
+ }
+}
+
+
+void FastSaxParser::callbackCharacters( const XML_Char* s, int nLen )
+{
+ Entity& rEntity = getEntity();
+ const Reference< XFastContextHandler >& xContext( rEntity.maContextStack.top()->mxContext );
+ if( xContext.is() ) try
+ {
+ xContext->characters( OUString( s, nLen, RTL_TEXTENCODING_UTF8 ) );
+ }
+ catch( Exception& e )
+ {
+ rEntity.maSavedException <<= e;
+ }
+}
+
+int FastSaxParser::callbackExternalEntityRef( XML_Parser parser,
+ const XML_Char *context, const XML_Char * /*base*/, const XML_Char *systemId, const XML_Char *publicId )
+{
+ bool bOK = true;
+ InputSource source;
+
+ Entity& rCurrEntity = getEntity();
+ Entity aNewEntity( rCurrEntity );
+
+ if( rCurrEntity.mxEntityResolver.is() ) try
+ {
+ aNewEntity.maStructSource = rCurrEntity.mxEntityResolver->resolveEntity(
+ OUString( publicId, strlen( publicId ), RTL_TEXTENCODING_UTF8 ) ,
+ OUString( systemId, strlen( systemId ), RTL_TEXTENCODING_UTF8 ) );
+ }
+ catch( SAXParseException & e )
+ {
+ rCurrEntity.maSavedException <<= e;
+ bOK = false;
+ }
+ catch( SAXException & e )
+ {
+ rCurrEntity.maSavedException <<= SAXParseException(
+ e.Message, e.Context, e.WrappedException,
+ mxDocumentLocator->getPublicId(),
+ mxDocumentLocator->getSystemId(),
+ mxDocumentLocator->getLineNumber(),
+ mxDocumentLocator->getColumnNumber() );
+ bOK = false;
+ }
+
+ if( aNewEntity.maStructSource.aInputStream.is() )
+ {
+ aNewEntity.mpParser = XML_ExternalEntityParserCreate( parser, context, 0 );
+ if( !aNewEntity.mpParser )
+ {
+ return false;
+ }
+
+ aNewEntity.maConverter.setInputStream( aNewEntity.maStructSource.aInputStream );
+ pushEntity( aNewEntity );
+ try
+ {
+ parse();
+ }
+ catch( SAXParseException & e )
+ {
+ rCurrEntity.maSavedException <<= e;
+ bOK = false;
+ }
+ catch( IOException &e )
+ {
+ SAXException aEx;
+ aEx.WrappedException <<= e;
+ rCurrEntity.maSavedException <<= aEx;
+ bOK = false;
+ }
+ catch( RuntimeException &e )
+ {
+ SAXException aEx;
+ aEx.WrappedException <<= e;
+ rCurrEntity.maSavedException <<= aEx;
+ bOK = false;
+ }
+
+ popEntity();
+ XML_ParserFree( aNewEntity.mpParser );
+ }
+
+ return bOK;
+}
+
+} // namespace sax_fastparser
diff --git a/sax/source/fastparser/fastparser.hxx b/sax/source/fastparser/fastparser.hxx
new file mode 100644
index 000000000000..a0331fe4035a
--- /dev/null
+++ b/sax/source/fastparser/fastparser.hxx
@@ -0,0 +1,164 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SAX_FASTPARSER_HXX_
+#define _SAX_FASTPARSER_HXX_
+
+#include <vector>
+#include <stack>
+#include <hash_map>
+#include <boost/shared_ptr.hpp>
+#include <rtl/ref.hxx>
+#include <com/sun/star/xml/sax/XFastParser.hpp>
+#include <com/sun/star/xml/sax/XFastTokenHandler.hpp>
+#include <com/sun/star/xml/sax/XFastDocumentHandler.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/implbase2.hxx>
+
+#include <expat.h>
+#include "xml2utf.hxx"
+
+#include <sax/fastattribs.hxx>
+
+#define PARSER_IMPLEMENTATION_NAME "com.sun.star.comp.extensions.xml.sax.FastParser"
+#define PARSER_SERVICE_NAME "com.sun.star.xml.sax.FastParser"
+
+namespace sax_fastparser {
+
+class FastLocatorImpl;
+struct NamespaceDefine;
+struct SaxContextImpl;
+
+typedef ::boost::shared_ptr< SaxContextImpl > SaxContextImplPtr;
+typedef ::boost::shared_ptr< NamespaceDefine > NamespaceDefineRef;
+
+typedef ::std::hash_map< ::rtl::OUString, sal_Int32,
+ ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > NamespaceMap;
+
+// --------------------------------------------------------------------
+
+struct ParserData
+{
+ ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastDocumentHandler > mxDocumentHandler;
+ ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler > mxTokenHandler;
+ ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XErrorHandler > mxErrorHandler;
+ ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XEntityResolver > mxEntityResolver;
+ ::com::sun::star::lang::Locale maLocale;
+
+ ParserData();
+ ~ParserData();
+};
+
+// --------------------------------------------------------------------
+
+// Entity binds all information needed for a single file
+struct Entity : public ParserData
+{
+ ::com::sun::star::xml::sax::InputSource maStructSource;
+ XML_Parser mpParser;
+ ::sax_expatwrap::XMLFile2UTFConverter maConverter;
+ ::rtl::Reference< FastAttributeList > mxAttributes;
+
+ // Exceptions cannot be thrown through the C-XmlParser (possible resource leaks),
+ // therefore the exception must be saved somewhere.
+ ::com::sun::star::uno::Any maSavedException;
+
+ ::std::stack< SaxContextImplPtr > maContextStack;
+ ::std::vector< NamespaceDefineRef > maNamespaceDefines;
+
+ explicit Entity( const ParserData& rData );
+ ~Entity();
+};
+
+// --------------------------------------------------------------------
+
+// This class implements the external Parser interface
+class FastSaxParser : public ::cppu::WeakImplHelper2< ::com::sun::star::xml::sax::XFastParser, ::com::sun::star::lang::XServiceInfo >
+{
+public:
+ FastSaxParser();
+ virtual ~FastSaxParser();
+
+ // The implementation details
+ static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static(void);
+
+ // XFastParser
+ virtual void SAL_CALL parseStream( const ::com::sun::star::xml::sax::InputSource& aInputSource ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setFastDocumentHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastDocumentHandler >& Handler ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setTokenHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >& Handler ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL registerNamespace( const ::rtl::OUString& NamespaceURL, sal_Int32 NamespaceToken ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setErrorHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XErrorHandler >& Handler ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setEntityResolver( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XEntityResolver >& Resolver ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setLocale( const ::com::sun::star::lang::Locale& rLocale ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // called by the C callbacks of the expat parser
+ void callbackStartElement( const XML_Char* name, const XML_Char** atts );
+ void callbackEndElement( const XML_Char* name );
+ void callbackCharacters( const XML_Char* s, int nLen );
+ int callbackExternalEntityRef( XML_Parser parser, const XML_Char *openEntityNames, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId);
+
+ inline void pushEntity( const Entity& rEntity ) { maEntities.push( rEntity ); }
+ inline void popEntity() { maEntities.pop(); }
+ Entity& getEntity() { return maEntities.top(); }
+
+private:
+ void parse();
+
+ sal_Int32 GetToken( const ::rtl::OString& rToken );
+ sal_Int32 GetToken( const sal_Char* pToken, sal_Int32 nTokenLen = 0 );
+ sal_Int32 GetTokenWithPrefix( const ::rtl::OString& rPrefix, const ::rtl::OString& rName ) throw (::com::sun::star::xml::sax::SAXException);
+ sal_Int32 GetTokenWithPrefix( const sal_Char*pPrefix, int nPrefixLen, const sal_Char* pName, int nNameLen ) throw (::com::sun::star::xml::sax::SAXException);
+ ::rtl::OUString GetNamespaceURL( const ::rtl::OString& rPrefix ) throw (::com::sun::star::xml::sax::SAXException);
+ ::rtl::OUString GetNamespaceURL( const sal_Char*pPrefix, int nPrefixLen ) throw (::com::sun::star::xml::sax::SAXException);
+ sal_Int32 GetNamespaceToken( const ::rtl::OUString& rNamespaceURL );
+ sal_Int32 GetTokenWithNamespaceURL( const ::rtl::OUString& rNamespaceURL, const sal_Char* pName, int nNameLen );
+ void DefineNamespace( const ::rtl::OString& rPrefix, const sal_Char* pNamespaceURL );
+ sal_Int32 CreateCustomToken( const sal_Char* pToken, int len = 0 );
+
+ void pushContext();
+ void popContext();
+
+ void splitName( const XML_Char *pwName, const XML_Char *&rpPrefix, sal_Int32 &rPrefixLen, const XML_Char *&rpName, sal_Int32 &rNameLen );
+
+private:
+ ::osl::Mutex maMutex;
+
+ ::rtl::Reference< FastLocatorImpl > mxDocumentLocator;
+ NamespaceMap maNamespaceMap;
+
+ ParserData maData; /// Cached parser configuration for next call of parseStream().
+ ::std::stack< Entity > maEntities; /// Entity stack for each call of parseStream().
+};
+
+}
+
+#endif // _SAX_FASTPARSER_HXX_
diff --git a/sax/source/fastparser/makefile.mk b/sax/source/fastparser/makefile.mk
new file mode 100644
index 000000000000..7f70b7aee7bf
--- /dev/null
+++ b/sax/source/fastparser/makefile.mk
@@ -0,0 +1,74 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+PRJ=..$/..
+
+PRJNAME=sax
+TARGET=fastsax.uno
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+DLLPRE =
+
+.IF "$(SYSTEM_ZLIB)" == "YES"
+CFLAGS+=-DSYSTEM_ZLIB
+.ENDIF
+
+.IF "$(SYSTEM_EXPAT)" == "YES"
+CFLAGS+=-DSYSTEM_EXPAT
+.ENDIF
+
+#-----------------------------------------------------------
+
+SLOFILES =\
+ $(SLO)$/facreg.obj\
+ $(SLO)$/fastparser.obj\
+ $(SLO)$/xml2utf.obj
+
+SHL1TARGET= $(TARGET)
+SHL1IMPLIB= i$(TARGET)
+
+SHL1STDLIBS= \
+ $(SALLIB) \
+ $(SAXLIB) \
+ $(CPPULIB) \
+ $(CPPUHELPERLIB)\
+ $(EXPATASCII3RDLIB)
+
+SHL1DEPN=
+SHL1VERSIONMAP= $(SOLARENV)$/src$/component.map
+SHL1LIBS= $(SLB)$/$(TARGET).lib
+SHL1DEF= $(MISC)$/$(SHL1TARGET).def
+DEF1NAME= $(SHL1TARGET)
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+
+
diff --git a/sax/source/tools/converter.cxx b/sax/source/tools/converter.cxx
new file mode 100644
index 000000000000..5df3044bd6d3
--- /dev/null
+++ b/sax/source/tools/converter.cxx
@@ -0,0 +1,2098 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#include <com/sun/star/i18n/UnicodeType.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/Duration.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <rtl/ustrbuf.hxx>
+#include <rtl/math.hxx>
+#include "sax/tools/converter.hxx"
+
+using namespace rtl;
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::util;
+//using namespace com::sun::star::text;
+//using namespace com::sun::star::style;
+using namespace ::com::sun::star::i18n;
+
+namespace sax {
+
+static const sal_Char* gpsMM = "mm";
+static const sal_Char* gpsCM = "cm";
+static const sal_Char* gpsPT = "pt";
+static const sal_Char* gpsINCH = "in";
+static const sal_Char* gpsPC = "pc";
+
+const sal_Int8 XML_MAXDIGITSCOUNT_TIME = 11;
+const sal_Int8 XML_MAXDIGITSCOUNT_DATETIME = 6;
+#define XML_NULLDATE "NullDate"
+
+/** convert string to measure using optional min and max values*/
+bool Converter::convertMeasure( sal_Int32& rValue,
+ const OUString& rString,
+ sal_Int16 nTargetUnit /* = MeasureUnit::MM_100TH */,
+ sal_Int32 nMin /* = SAL_MIN_INT32 */,
+ sal_Int32 nMax /* = SAL_MAX_INT32 */ )
+{
+ bool bNeg = false;
+ double nVal = 0;
+
+ sal_Int32 nPos = 0L;
+ sal_Int32 nLen = rString.getLength();
+
+ // skip white space
+ while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) )
+ nPos++;
+
+ if( nPos < nLen && sal_Unicode('-') == rString[nPos] )
+ {
+ bNeg = true;
+ nPos++;
+ }
+
+ // get number
+ while( nPos < nLen &&
+ sal_Unicode('0') <= rString[nPos] &&
+ sal_Unicode('9') >= rString[nPos] )
+ {
+ // TODO: check overflow!
+ nVal *= 10;
+ nVal += (rString[nPos] - sal_Unicode('0'));
+ nPos++;
+ }
+ double nDiv = 1.;
+ if( nPos < nLen && sal_Unicode('.') == rString[nPos] )
+ {
+ nPos++;
+
+ while( nPos < nLen &&
+ sal_Unicode('0') <= rString[nPos] &&
+ sal_Unicode('9') >= rString[nPos] )
+ {
+ // TODO: check overflow!
+ nDiv *= 10;
+ nVal += ( ((double)(rString[nPos] - sal_Unicode('0'))) / nDiv );
+ nPos++;
+ }
+ }
+
+ // skip white space
+ while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) )
+ nPos++;
+
+ if( nPos < nLen )
+ {
+
+ if( MeasureUnit::PERCENT == nTargetUnit )
+ {
+ if( sal_Unicode('%') != rString[nPos] )
+ return false;
+ }
+ else if( MeasureUnit::PIXEL == nTargetUnit )
+ {
+ if( nPos + 1 >= nLen ||
+ (sal_Unicode('p') != rString[nPos] &&
+ sal_Unicode('P') != rString[nPos])||
+ (sal_Unicode('x') != rString[nPos+1] &&
+ sal_Unicode('X') != rString[nPos+1]) )
+ return false;
+ }
+ else
+ {
+ OSL_ENSURE( MeasureUnit::TWIP == nTargetUnit || MeasureUnit::POINT == nTargetUnit ||
+ MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit, "unit is not supported");
+ const sal_Char *aCmpsL[2] = { 0, 0 };
+ const sal_Char *aCmpsU[2] = { 0, 0 };
+ double aScales[2] = { 1., 1. };
+
+ if( MeasureUnit::TWIP == nTargetUnit )
+ {
+ switch( rString[nPos] )
+ {
+ case sal_Unicode('c'):
+ case sal_Unicode('C'):
+ aCmpsL[0] = "cm";
+ aCmpsU[0] = "CM";
+ aScales[0] = (72.*20.)/2.54; // twip
+ break;
+ case sal_Unicode('i'):
+ case sal_Unicode('I'):
+ aCmpsL[0] = "in";
+ aCmpsU[0] = "IN";
+ aScales[0] = 72.*20.; // twip
+ break;
+ case sal_Unicode('m'):
+ case sal_Unicode('M'):
+ aCmpsL[0] = "mm";
+ aCmpsU[0] = "MM";
+ aScales[0] = (72.*20.)/25.4; // twip
+ break;
+ case sal_Unicode('p'):
+ case sal_Unicode('P'):
+ aCmpsL[0] = "pt";
+ aCmpsU[0] = "PT";
+ aScales[0] = 20.; // twip
+
+ aCmpsL[1] = "pc";
+ aCmpsU[1] = "PC";
+ aScales[1] = 12.*20.; // twip
+ break;
+ }
+ }
+ else if( MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit )
+ {
+ double nScaleFactor = (MeasureUnit::MM_100TH == nTargetUnit) ? 100.0 : 10.0;
+ switch( rString[nPos] )
+ {
+ case sal_Unicode('c'):
+ case sal_Unicode('C'):
+ aCmpsL[0] = "cm";
+ aCmpsU[0] = "CM";
+ aScales[0] = 10.0 * nScaleFactor; // mm/100
+ break;
+ case sal_Unicode('i'):
+ case sal_Unicode('I'):
+ aCmpsL[0] = "in";
+ aCmpsU[0] = "IN";
+ aScales[0] = 1000.*2.54; // mm/100
+ break;
+ case sal_Unicode('m'):
+ case sal_Unicode('M'):
+ aCmpsL[0] = "mm";
+ aCmpsU[0] = "MM";
+ aScales[0] = 1.0 * nScaleFactor; // mm/100
+ break;
+ case sal_Unicode('p'):
+ case sal_Unicode('P'):
+ aCmpsL[0] = "pt";
+ aCmpsU[0] = "PT";
+ aScales[0] = (10.0 * nScaleFactor*2.54)/72.; // mm/100
+
+ aCmpsL[1] = "pc";
+ aCmpsU[1] = "PC";
+ aScales[1] = (10.0 * nScaleFactor*2.54)/12.; // mm/100
+ break;
+ }
+ }
+ else if( MeasureUnit::POINT == nTargetUnit )
+ {
+ if( rString[nPos] == 'p' || rString[nPos] == 'P' )
+ {
+ aCmpsL[0] = "pt";
+ aCmpsU[0] = "PT";
+ aScales[0] = 1;
+ }
+ }
+
+ if( aCmpsL[0] == NULL )
+ return false;
+
+ double nScale = 0.;
+ for( sal_uInt16 i= 0; i < 2; i++ )
+ {
+ const sal_Char *pL = aCmpsL[i];
+ if( pL )
+ {
+ const sal_Char *pU = aCmpsU[i];
+ while( nPos < nLen && *pL )
+ {
+ sal_Unicode c = rString[nPos];
+ if( c != *pL && c != *pU )
+ break;
+ pL++;
+ pU++;
+ nPos++;
+ }
+ if( !*pL && (nPos == nLen || ' ' == rString[nPos]) )
+ {
+ nScale = aScales[i];
+ break;
+ }
+ }
+ }
+
+ if( 0. == nScale )
+ return false;
+
+ // TODO: check overflow
+ if( nScale != 1. )
+ nVal *= nScale;
+ }
+ }
+
+ nVal += .5;
+ if( bNeg )
+ nVal = -nVal;
+
+ if( nVal <= (double)nMin )
+ rValue = nMin;
+ else if( nVal >= (double)nMax )
+ rValue = nMax;
+ else
+ rValue = (sal_Int32)nVal;
+
+ return true;
+}
+
+/** convert measure in given unit to string with given unit */
+void Converter::convertMeasure( OUStringBuffer& rBuffer,
+ sal_Int32 nMeasure,
+ sal_Int16 nSourceUnit /* = MeasureUnit::MM_100TH */,
+ sal_Int16 nTargetUnit /* = MeasureUnit::INCH */ )
+{
+ OSL_ENSURE( false, "Converter::convertMeasure - not implemented, tools/BigInt needs replacement" );
+ (void)rBuffer;
+ (void)nMeasure;
+ (void)nSourceUnit;
+ (void)nTargetUnit;
+#if 0
+ if( nSourceUnit == MeasureUnit::PERCENT )
+ {
+ OSL_ENSURE( nTargetUnit == MeasureUnit::PERCENT,
+ "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" );
+
+ rBuffer.append( nMeasure );
+ rBuffer.append( sal_Unicode('%' ) );
+ }
+ else
+ {
+ // the sign is processed seperatly
+ if( nMeasure < 0 )
+ {
+ nMeasure = -nMeasure;
+ rBuffer.append( sal_Unicode('-') );
+ }
+
+ // The new length is (nVal * nMul)/(nDiv*nFac*10)
+ long nMul = 1000;
+ long nDiv = 1;
+ long nFac = 100;
+ const sal_Char* psUnit = 0;
+ switch( nSourceUnit )
+ {
+ case MeasureUnit::TWIP:
+ switch( nTargetUnit )
+ {
+ case MeasureUnit::MM_100TH:
+ case MeasureUnit::MM_10TH:
+ OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,"output unit not supported for twip values" );
+ case MeasureUnit::MM:
+ // 0.01mm = 0.57twip (exactly)
+ nMul = 25400; // 25.4 * 1000
+ nDiv = 1440; // 72 * 20;
+ nFac = 100;
+ psUnit = gpsMM;
+ break;
+
+ case MeasureUnit::CM:
+ // 0.001cm = 0.57twip (exactly)
+ nMul = 25400; // 2.54 * 10000
+ nDiv = 1440; // 72 * 20;
+ nFac = 1000;
+ psUnit = gpsCM;
+ break;
+
+ case MeasureUnit::POINT:
+ // 0.01pt = 0.2twip (exactly)
+ nMul = 1000;
+ nDiv = 20;
+ nFac = 100;
+ psUnit = gpsPT;
+ break;
+
+ case MeasureUnit::INCH:
+ default:
+ OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
+ "output unit not supported for twip values" );
+ // 0.0001in = 0.144twip (exactly)
+ nMul = 100000;
+ nDiv = 1440; // 72 * 20;
+ nFac = 10000;
+ psUnit = gpsINCH;
+ break;
+ }
+ break;
+
+ case MeasureUnit::POINT:
+ // 1pt = 1pt (exactly)
+ OSL_ENSURE( MeasureUnit::POINT == nTargetUnit,
+ "output unit not supported for pt values" );
+ nMul = 10;
+ nDiv = 1;
+ nFac = 1;
+ psUnit = gpsPT;
+ break;
+ case MeasureUnit::MM_10TH:
+ case MeasureUnit::MM_100TH:
+ {
+ long nFac2 = (MeasureUnit::MM_100TH == nSourceUnit) ? 100 : 10;
+ switch( nTargetUnit )
+ {
+ case MeasureUnit::MM_100TH:
+ case MeasureUnit::MM_10TH:
+ OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
+ "output unit not supported for 1/100mm values" );
+ case MeasureUnit::MM:
+ // 0.01mm = 1 mm/100 (exactly)
+ nMul = 10;
+ nDiv = 1;
+ nFac = nFac2;
+ psUnit = gpsMM;
+ break;
+
+ case MeasureUnit::CM:
+ // 0.001mm = 1 mm/100 (exactly)
+ nMul = 10;
+ nDiv = 1; // 72 * 20;
+ nFac = 10*nFac2;
+ psUnit = gpsCM;
+ break;
+
+ case MeasureUnit::POINT:
+ // 0.01pt = 0.35 mm/100 (exactly)
+ nMul = 72000;
+ nDiv = 2540;
+ nFac = nFac2;
+ psUnit = gpsPT;
+ break;
+
+ case MeasureUnit::INCH:
+ default:
+ OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
+ "output unit not supported for 1/100mm values" );
+ // 0.0001in = 0.254 mm/100 (exactly)
+ nMul = 100000;
+ nDiv = 2540;
+ nFac = 100*nFac2;
+ psUnit = gpsINCH;
+ break;
+ }
+ break;
+ }
+ }
+
+ long nLongVal = 0;
+ bool bOutLongVal = true;
+ if( nMeasure > SAL_INT32_MAX / nMul )
+ {
+ // A big int is required for calculation
+ BigInt nBigVal( nMeasure );
+ BigInt nBigFac( nFac );
+ nBigVal *= nMul;
+ nBigVal /= nDiv;
+ nBigVal += 5;
+ nBigVal /= 10;
+
+ if( nBigVal.IsLong() )
+ {
+ // To convert the value into a string a long is sufficient
+ nLongVal = (long)nBigVal;
+ }
+ else
+ {
+ BigInt nBigFac2( nFac );
+ BigInt nBig10( 10 );
+ rBuffer.append( (sal_Int32)(nBigVal / nBigFac2) );
+ if( !(nBigVal % nBigFac2).IsZero() )
+ {
+ rBuffer.append( sal_Unicode('.') );
+ while( nFac > 1 && !(nBigVal % nBigFac2).IsZero() )
+ {
+ nFac /= 10;
+ nBigFac2 = nFac;
+ rBuffer.append( (sal_Int32)((nBigVal / nBigFac2) % nBig10 ) );
+ }
+ }
+ bOutLongVal = false;
+ }
+ }
+ else
+ {
+ nLongVal = nMeasure * nMul;
+ nLongVal /= nDiv;
+ nLongVal += 5;
+ nLongVal /= 10;
+ }
+
+ if( bOutLongVal )
+ {
+ rBuffer.append( (sal_Int32)(nLongVal / nFac) );
+ if( nFac > 1 && (nLongVal % nFac) != 0 )
+ {
+ rBuffer.append( sal_Unicode('.') );
+ while( nFac > 1 && (nLongVal % nFac) != 0 )
+ {
+ nFac /= 10;
+ rBuffer.append( (sal_Int32)((nLongVal / nFac) % 10) );
+ }
+ }
+ }
+
+ if( psUnit )
+ rBuffer.appendAscii( psUnit );
+ }
+#endif
+}
+
+static const OUString& getTrueString()
+{
+ static const OUString sTrue( RTL_CONSTASCII_USTRINGPARAM( "true" ) );
+ return sTrue;
+}
+
+static const OUString& getFalseString()
+{
+ static const OUString sFalse( RTL_CONSTASCII_USTRINGPARAM( "false" ) );
+ return sFalse;
+}
+
+/** convert string to boolean */
+bool Converter::convertBool( bool& rBool, const OUString& rString )
+{
+ rBool = rString == getTrueString();
+
+ return rBool || (rString == getFalseString());
+}
+
+/** convert boolean to string */
+void Converter::convertBool( OUStringBuffer& rBuffer, bool bValue )
+{
+ rBuffer.append( bValue ? getTrueString() : getFalseString() );
+}
+
+/** convert string to percent */
+bool Converter::convertPercent( sal_Int32& rPercent, const OUString& rString )
+{
+ return convertMeasure( rPercent, rString, MeasureUnit::PERCENT );
+}
+
+/** convert percent to string */
+void Converter::convertPercent( OUStringBuffer& rBuffer, sal_Int32 nValue )
+{
+ rBuffer.append( nValue );
+ rBuffer.append( sal_Unicode('%' ) );
+}
+
+/** convert string to pixel measure */
+bool Converter::convertMeasurePx( sal_Int32& rPixel, const OUString& rString )
+{
+ return convertMeasure( rPixel, rString, MeasureUnit::PIXEL );
+}
+
+/** convert pixel measure to string */
+void Converter::convertMeasurePx( OUStringBuffer& rBuffer, sal_Int32 nValue )
+{
+ rBuffer.append( nValue );
+ rBuffer.append( sal_Unicode('p' ) );
+ rBuffer.append( sal_Unicode('x' ) );
+}
+
+int lcl_gethex( int nChar )
+{
+ if( nChar >= '0' && nChar <= '9' )
+ return nChar - '0';
+ else if( nChar >= 'a' && nChar <= 'f' )
+ return nChar - 'a' + 10;
+ else if( nChar >= 'A' && nChar <= 'F' )
+ return nChar - 'A' + 10;
+ else
+ return 0;
+}
+
+/** convert string to color */
+bool Converter::convertColor( sal_Int32& rColor, const OUString& rValue )
+{
+ if( rValue.getLength() != 7 || rValue[0] != '#' )
+ return false;
+
+ rColor = lcl_gethex( rValue[1] ) * 16 + lcl_gethex( rValue[2] );
+ rColor <<= 8;
+
+ rColor |= ( lcl_gethex( rValue[3] ) * 16 + lcl_gethex( rValue[4] ) );
+ rColor <<= 8;
+
+ rColor |= ( lcl_gethex( rValue[5] ) * 16 + lcl_gethex( rValue[6] ) );
+
+ return true;
+}
+
+static sal_Char aHexTab[] = "0123456789abcdef";
+
+/** convert color to string */
+void Converter::convertColor( OUStringBuffer& rBuffer, sal_Int32 nColor )
+{
+ rBuffer.append( sal_Unicode( '#' ) );
+
+ sal_uInt8 nCol = (sal_uInt8)(nColor >> 16);
+ rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
+ rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
+
+ nCol = (sal_uInt8)(nColor >> 8);
+ rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
+ rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
+
+ nCol = (sal_uInt8)nColor;
+ rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
+ rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
+}
+
+/** convert number to string */
+void Converter::convertNumber( OUStringBuffer& rBuffer, sal_Int32 nNumber )
+{
+ rBuffer.append( nNumber );
+}
+
+/** convert string to number with optional min and max values */
+bool Converter::convertNumber( sal_Int32& rValue,
+ const OUString& rString,
+ sal_Int32 nMin, sal_Int32 nMax )
+{
+ bool bNeg = false;
+ rValue = 0;
+
+ sal_Int32 nPos = 0L;
+ sal_Int32 nLen = rString.getLength();
+
+ // skip white space
+ while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) )
+ nPos++;
+
+ if( nPos < nLen && sal_Unicode('-') == rString[nPos] )
+ {
+ bNeg = true;
+ nPos++;
+ }
+
+ // get number
+ while( nPos < nLen &&
+ sal_Unicode('0') <= rString[nPos] &&
+ sal_Unicode('9') >= rString[nPos] )
+ {
+ // TODO: check overflow!
+ rValue *= 10;
+ rValue += (rString[nPos] - sal_Unicode('0'));
+ nPos++;
+ }
+
+ if( bNeg )
+ rValue *= -1;
+
+ if( rValue < nMin )
+ rValue = nMin;
+ else if( rValue > nMax )
+ rValue = nMax;
+
+ return nPos == nLen;
+}
+
+/** convert double number to string (using ::rtl::math) */
+void Converter::convertDouble( OUStringBuffer& rBuffer,
+ double fNumber,
+ bool bWriteUnits,
+ sal_Int16 nSourceUnit,
+ sal_Int16 nTargetUnit)
+{
+ if(MeasureUnit::PERCENT == nSourceUnit)
+ {
+ OSL_ENSURE( nTargetUnit == MeasureUnit::PERCENT, "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" );
+ ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
+ if(bWriteUnits)
+ rBuffer.append(sal_Unicode('%'));
+ }
+ else
+ {
+ OUStringBuffer sUnit;
+ double fFactor = GetConversionFactor(sUnit, nSourceUnit, nTargetUnit);
+ if(fFactor != 1.0)
+ fNumber *= fFactor;
+ ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
+ if(bWriteUnits)
+ rBuffer.append(sUnit);
+ }
+}
+
+/** convert double number to string (using ::rtl::math) */
+void Converter::convertDouble( ::rtl::OUStringBuffer& rBuffer, double fNumber)
+{
+ ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
+}
+
+/** convert string to double number (using ::rtl::math) */
+bool Converter::convertDouble(double& rValue,
+ const ::rtl::OUString& rString, sal_Int16 nTargetUnit)
+{
+ sal_Int16 nSourceUnit = GetUnitFromString(rString, nTargetUnit);
+
+ return convertDouble(rValue, rString, nSourceUnit, nTargetUnit );
+}
+
+/** convert string to double number (using ::rtl::math) */
+bool Converter::convertDouble(double& rValue,
+ const ::rtl::OUString& rString, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
+{
+ rtl_math_ConversionStatus eStatus;
+ rValue = ::rtl::math::stringToDouble( rString, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL );
+
+ if(eStatus == rtl_math_ConversionStatus_Ok)
+ {
+ OUStringBuffer sUnit;
+ double fFactor = GetConversionFactor(sUnit, nSourceUnit, nTargetUnit);
+ if(fFactor != 1.0 && fFactor != 0.0)
+ rValue /= fFactor;
+ }
+
+ return ( eStatus == rtl_math_ConversionStatus_Ok );
+}
+
+/** convert string to double number (using ::rtl::math) */
+bool Converter::convertDouble(double& rValue, const ::rtl::OUString& rString)
+{
+ rtl_math_ConversionStatus eStatus;
+ rValue = ::rtl::math::stringToDouble( rString, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL );
+ return ( eStatus == rtl_math_ConversionStatus_Ok );
+}
+
+/** convert double to ISO "duration" string; negative durations allowed */
+void Converter::convertDuration(::rtl::OUStringBuffer& rBuffer,
+ const double fTime)
+{
+ double fValue = fTime;
+
+ // take care of negative durations as specified in:
+ // XML Schema, W3C Working Draft 07 April 2000, section 3.2.6.1
+ if (fValue < 0.0)
+ {
+ rBuffer.append(sal_Unicode('-'));
+ fValue = - fValue;
+ }
+
+ rBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM( "PT" ));
+ fValue *= 24;
+ double fHoursValue = ::rtl::math::approxFloor (fValue);
+ fValue -= fHoursValue;
+ fValue *= 60;
+ double fMinsValue = ::rtl::math::approxFloor (fValue);
+ fValue -= fMinsValue;
+ fValue *= 60;
+ double fSecsValue = ::rtl::math::approxFloor (fValue);
+ fValue -= fSecsValue;
+ double f100SecsValue;
+ if (fValue > 0.00001)
+ f100SecsValue = ::rtl::math::round( fValue, XML_MAXDIGITSCOUNT_TIME - 5);
+ else
+ f100SecsValue = 0.0;
+
+ if (f100SecsValue == 1.0)
+ {
+ f100SecsValue = 0.0;
+ fSecsValue += 1.0;
+ }
+ if (fSecsValue >= 60.0)
+ {
+ fSecsValue -= 60.0;
+ fMinsValue += 1.0;
+ }
+ if (fMinsValue >= 60.0)
+ {
+ fMinsValue -= 60.0;
+ fHoursValue += 1.0;
+ }
+
+ if (fHoursValue < 10)
+ rBuffer.append( sal_Unicode('0'));
+ rBuffer.append( sal_Int32( fHoursValue));
+ rBuffer.append( sal_Unicode('H'));
+ if (fMinsValue < 10)
+ rBuffer.append( sal_Unicode('0'));
+ rBuffer.append( sal_Int32( fMinsValue));
+ rBuffer.append( sal_Unicode('M'));
+ if (fSecsValue < 10)
+ rBuffer.append( sal_Unicode('0'));
+ rBuffer.append( sal_Int32( fSecsValue));
+ if (f100SecsValue > 0.0)
+ {
+ ::rtl::OUString a100th( ::rtl::math::doubleToUString( fValue,
+ rtl_math_StringFormat_F, XML_MAXDIGITSCOUNT_TIME - 5, '.',
+ true));
+ if ( a100th.getLength() > 2 )
+ {
+ rBuffer.append( sal_Unicode('.'));
+ rBuffer.append( a100th.copy( 2 ) ); // strip 0.
+ }
+ }
+ rBuffer.append( sal_Unicode('S'));
+}
+
+/** convert ISO "duration" string to double; negative durations allowed */
+bool Converter::convertDuration(double& rfTime,
+ const ::rtl::OUString& rString)
+{
+ rtl::OUString aTrimmed = rString.trim().toAsciiUpperCase();
+ const sal_Unicode* pStr = aTrimmed.getStr();
+
+ // negative time duration?
+ bool bIsNegativeDuration = false;
+ if ( sal_Unicode('-') == (*pStr) )
+ {
+ bIsNegativeDuration = true;
+ pStr++;
+ }
+
+ if ( *(pStr++) != sal_Unicode('P') ) // duration must start with "P"
+ return false;
+
+ rtl::OUString sDoubleStr;
+ bool bSuccess = true;
+ bool bDone = false;
+ bool bTimePart = false;
+ bool bIsFraction = false;
+ sal_Int32 nDays = 0;
+ sal_Int32 nHours = 0;
+ sal_Int32 nMins = 0;
+ sal_Int32 nSecs = 0;
+ sal_Int32 nTemp = 0;
+
+ while ( bSuccess && !bDone )
+ {
+ sal_Unicode c = *(pStr++);
+ if ( !c ) // end
+ bDone = true;
+ else if ( sal_Unicode('0') <= c && sal_Unicode('9') >= c )
+ {
+ if ( nTemp >= SAL_MAX_INT32 / 10 )
+ bSuccess = false;
+ else
+ {
+ if ( !bIsFraction )
+ {
+ nTemp *= 10;
+ nTemp += (c - sal_Unicode('0'));
+ }
+ else
+ {
+ sDoubleStr += OUString::valueOf(c);
+ }
+ }
+ }
+ else if ( bTimePart )
+ {
+ if ( c == sal_Unicode('H') )
+ {
+ nHours = nTemp;
+ nTemp = 0;
+ }
+ else if ( c == sal_Unicode('M') )
+ {
+ nMins = nTemp;
+ nTemp = 0;
+ }
+ else if ( (c == sal_Unicode(',')) || (c == sal_Unicode('.')) )
+ {
+ nSecs = nTemp;
+ nTemp = 0;
+ bIsFraction = true;
+ sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0."));
+ }
+ else if ( c == sal_Unicode('S') )
+ {
+ if ( !bIsFraction )
+ {
+ nSecs = nTemp;
+ nTemp = 0;
+ sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.0"));
+ }
+ }
+ else
+ bSuccess = false; // invalid character
+ }
+ else
+ {
+ if ( c == sal_Unicode('T') ) // "T" starts time part
+ bTimePart = true;
+ else if ( c == sal_Unicode('D') )
+ {
+ nDays = nTemp;
+ nTemp = 0;
+ }
+ else if ( c == sal_Unicode('Y') || c == sal_Unicode('M') )
+ {
+ //! how many days is a year or month?
+
+ OSL_ENSURE( false, "years or months in duration: not implemented");
+ bSuccess = false;
+ }
+ else
+ bSuccess = false; // invalid character
+ }
+ }
+
+ if ( bSuccess )
+ {
+ if ( nDays )
+ nHours += nDays * 24; // add the days to the hours part
+ double fTempTime = 0.0;
+ double fHour = nHours;
+ double fMin = nMins;
+ double fSec = nSecs;
+ double fSec100 = 0.0;
+ double fFraction = sDoubleStr.toDouble();
+ fTempTime = fHour / 24;
+ fTempTime += fMin / (24 * 60);
+ fTempTime += fSec / (24 * 60 * 60);
+ fTempTime += fSec100 / (24 * 60 * 60 * 60);
+ fTempTime += fFraction / (24 * 60 * 60);
+
+ // negative duration?
+ if ( bIsNegativeDuration )
+ {
+ fTempTime = -fTempTime;
+ }
+
+ rfTime = fTempTime;
+ }
+ return bSuccess;
+}
+
+/** convert util::Duration to ISO "duration" string */
+void Converter::convertDuration(::rtl::OUStringBuffer& rBuffer,
+ const ::util::Duration& rDuration)
+{
+ if (rDuration.Negative)
+ {
+ rBuffer.append(sal_Unicode('-'));
+ }
+ rBuffer.append(sal_Unicode('P'));
+ const bool bHaveDate(static_cast<sal_Int32>(rDuration.Years)
+ +static_cast<sal_Int32>(rDuration.Months)
+ +static_cast<sal_Int32>(rDuration.Days));
+ if (rDuration.Years)
+ {
+ rBuffer.append(static_cast<sal_Int32>(rDuration.Years));
+ rBuffer.append(sal_Unicode('Y'));
+ }
+ if (rDuration.Months)
+ {
+ rBuffer.append(static_cast<sal_Int32>(rDuration.Months));
+ rBuffer.append(sal_Unicode('M'));
+ }
+ if (rDuration.Days)
+ {
+ rBuffer.append(static_cast<sal_Int32>(rDuration.Days));
+ rBuffer.append(sal_Unicode('D'));
+ }
+ const sal_Int32 nMSecs(static_cast<sal_Int32>(rDuration.Seconds)
+ + static_cast<sal_Int32>(rDuration.MilliSeconds));
+ if (static_cast<sal_Int32>(rDuration.Hours) +
+ static_cast<sal_Int32>(rDuration.Minutes) + nMSecs)
+ {
+ rBuffer.append(sal_Unicode('T')); // time separator
+ if (rDuration.Hours)
+ {
+ rBuffer.append(static_cast<sal_Int32>(rDuration.Hours));
+ rBuffer.append(sal_Unicode('H'));
+ }
+ if (rDuration.Minutes)
+ {
+ rBuffer.append(static_cast<sal_Int32>(rDuration.Minutes));
+ rBuffer.append(sal_Unicode('M'));
+ }
+ if (nMSecs)
+ {
+ // seconds must not be omitted (i.e. ".42S" is not valid)
+ rBuffer.append(static_cast<sal_Int32>(rDuration.Seconds));
+ if (rDuration.MilliSeconds)
+ {
+ rBuffer.append(sal_Unicode('.'));
+ const sal_Int32 nMilliSeconds(rDuration.MilliSeconds % 1000);
+ if (nMilliSeconds < 100)
+ {
+ rBuffer.append(sal_Unicode('0'));
+ }
+ if (nMilliSeconds < 10)
+ {
+ rBuffer.append(sal_Unicode('0'));
+ }
+ if (0 == (nMilliSeconds % 10))
+ {
+ if (0 == (nMilliSeconds % 100))
+ {
+ rBuffer.append(nMilliSeconds / 100);
+ }
+ else
+ {
+ rBuffer.append(nMilliSeconds / 10);
+ }
+ }
+ else
+ {
+ rBuffer.append(nMilliSeconds);
+ }
+ }
+ rBuffer.append(sal_Unicode('S'));
+ }
+ }
+ else if (!bHaveDate)
+ {
+ // zero duration: XMLSchema-2 says there must be at least one component
+ rBuffer.append(sal_Unicode('0'));
+ rBuffer.append(sal_Unicode('D'));
+ }
+}
+
+enum Result { R_NOTHING, R_OVERFLOW, R_SUCCESS };
+
+static Result
+readUnsignedNumber(const ::rtl::OUString & rString,
+ sal_Int32 & io_rnPos, sal_Int32 & o_rNumber)
+{
+ bool bOverflow(false);
+ sal_Int32 nTemp(0);
+ sal_Int32 nPos(io_rnPos);
+
+ while (nPos < rString.getLength())
+ {
+ const sal_Unicode c = rString[nPos];
+ if ((sal_Unicode('0') <= c) && (c <= sal_Unicode('9')))
+ {
+ nTemp *= 10;
+ nTemp += (c - sal_Unicode('0'));
+ if (nTemp >= SAL_MAX_INT16)
+ {
+ bOverflow = true;
+ }
+ }
+ else
+ {
+ break;
+ }
+ ++nPos;
+ }
+
+ if (io_rnPos == nPos) // read something?
+ {
+ o_rNumber = -1;
+ return R_NOTHING;
+ }
+
+ io_rnPos = nPos;
+ o_rNumber = nTemp;
+ return (bOverflow) ? R_OVERFLOW : R_SUCCESS;
+}
+
+static bool
+readDurationT(const ::rtl::OUString & rString, sal_Int32 & io_rnPos)
+{
+ if ((io_rnPos < rString.getLength()) &&
+ (rString[io_rnPos] == sal_Unicode('T')))
+ {
+ ++io_rnPos;
+ return true;
+ }
+ return false;
+}
+
+static bool
+readDurationComponent(const ::rtl::OUString & rString,
+ sal_Int32 & io_rnPos, sal_Int32 & io_rnTemp, bool & io_rbTimePart,
+ sal_Int32 & o_rnTarget, const sal_Unicode c)
+{
+ if ((io_rnPos < rString.getLength()))
+ {
+ if (c == rString[io_rnPos])
+ {
+ ++io_rnPos;
+ if (-1 != io_rnTemp)
+ {
+ o_rnTarget = io_rnTemp;
+ io_rnTemp = -1;
+ if (!io_rbTimePart)
+ {
+ io_rbTimePart = readDurationT(rString, io_rnPos);
+ }
+ return (R_OVERFLOW !=
+ readUnsignedNumber(rString, io_rnPos, io_rnTemp));
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+/** convert ISO "duration" string to util::Duration */
+bool Converter::convertDuration(util::Duration& rDuration,
+ const ::rtl::OUString& rString)
+{
+ const ::rtl::OUString string = rString.trim().toAsciiUpperCase();
+ sal_Int32 nPos(0);
+
+ bool bIsNegativeDuration(false);
+ if (string.getLength() && (sal_Unicode('-') == string[0]))
+ {
+ bIsNegativeDuration = true;
+ ++nPos;
+ }
+
+ if ((nPos < string.getLength())
+ && (string[nPos] != sal_Unicode('P'))) // duration must start with "P"
+ {
+ return false;
+ }
+
+ ++nPos;
+
+ /// last read number; -1 == no valid number! always reset after using!
+ sal_Int32 nTemp(-1);
+ bool bTimePart(false); // have we read 'T'?
+ bool bSuccess(false);
+ sal_Int32 nYears(0);
+ sal_Int32 nMonths(0);
+ sal_Int32 nDays(0);
+ sal_Int32 nHours(0);
+ sal_Int32 nMinutes(0);
+ sal_Int32 nSeconds(0);
+ sal_Int32 nMilliSeconds(0);
+
+ bTimePart = readDurationT(string, nPos);
+ bSuccess = (R_SUCCESS == readUnsignedNumber(string, nPos, nTemp));
+
+ if (!bTimePart && bSuccess)
+ {
+ bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
+ nYears, sal_Unicode('Y'));
+ }
+
+ if (!bTimePart && bSuccess)
+ {
+ bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
+ nMonths, sal_Unicode('M'));
+ }
+
+ if (!bTimePart && bSuccess)
+ {
+ bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
+ nDays, sal_Unicode('D'));
+ }
+
+ if (bTimePart)
+ {
+ if (-1 == nTemp) // a 'T' must be followed by a component
+ {
+ bSuccess = false;
+ }
+
+ if (bSuccess)
+ {
+ bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
+ nHours, sal_Unicode('H'));
+ }
+
+ if (bSuccess)
+ {
+ bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
+ nMinutes, sal_Unicode('M'));
+ }
+
+ // eeek! seconds are icky.
+ if ((nPos < string.getLength()) && bSuccess)
+ {
+ if (sal_Unicode('.') == string[nPos])
+ {
+ ++nPos;
+ if (-1 != nTemp)
+ {
+ nSeconds = nTemp;
+ nTemp = -1;
+ const sal_Int32 nStart(nPos);
+ bSuccess =
+ (R_NOTHING != readUnsignedNumber(string, nPos, nTemp));
+ if ((nPos < string.getLength()) && bSuccess)
+ {
+ if (-1 != nTemp)
+ {
+ nTemp = -1;
+ const sal_Int32 nDigits = nPos - nStart;
+ OSL_ENSURE(nDigits > 0, "bad code monkey");
+ const sal_Unicode cZero('0');
+ nMilliSeconds = 100 * (string[nStart] - cZero);
+ if (nDigits >= 2)
+ {
+ nMilliSeconds += 10 *
+ (string[nStart+1] - cZero);
+ if (nDigits >= 3)
+ {
+ nMilliSeconds += (string[nStart+2] - cZero);
+ }
+ }
+
+ if (sal_Unicode('S') == string[nPos])
+ {
+ ++nPos;
+ }
+ else
+ {
+ bSuccess = false;
+ }
+ }
+ else
+ {
+ bSuccess = false;
+ }
+ }
+ }
+ else
+ {
+ bSuccess = false;
+ }
+ }
+ else if (sal_Unicode('S') == string[nPos])
+ {
+ ++nPos;
+ if (-1 != nTemp)
+ {
+ nSeconds = nTemp;
+ nTemp = -1;
+ }
+ else
+ {
+ bSuccess = false;
+ }
+ }
+ }
+ }
+
+ if (nPos != string.getLength()) // string not processed completely?
+ {
+ bSuccess = false;
+ }
+
+ if (nTemp != -1) // unprocessed number?
+ {
+ bSuccess = false;
+ }
+
+ if (bSuccess)
+ {
+ rDuration.Negative = bIsNegativeDuration;
+ rDuration.Years = static_cast<sal_Int16>(nYears);
+ rDuration.Months = static_cast<sal_Int16>(nMonths);
+ rDuration.Days = static_cast<sal_Int16>(nDays);
+ rDuration.Hours = static_cast<sal_Int16>(nHours);
+ rDuration.Minutes = static_cast<sal_Int16>(nMinutes);
+ rDuration.Seconds = static_cast<sal_Int16>(nSeconds);
+ rDuration.MilliSeconds = static_cast<sal_Int16>(nMilliSeconds);
+ }
+
+ return bSuccess;
+}
+
+
+/** convert util::Date to ISO "date" string */
+void Converter::convertDate(
+ ::rtl::OUStringBuffer& i_rBuffer,
+ const util::Date& i_rDate)
+{
+ const util::DateTime dt(
+ 0, 0, 0, 0, i_rDate.Day, i_rDate.Month, i_rDate.Year);
+ convertDateTime(i_rBuffer, dt, false);
+}
+
+/** convert util::DateTime to ISO "date" or "dateTime" string */
+void Converter::convertDateTime(
+ ::rtl::OUStringBuffer& i_rBuffer,
+ const com::sun::star::util::DateTime& i_rDateTime,
+ bool i_bAddTimeIf0AM )
+{
+ const sal_Unicode dash('-');
+ const sal_Unicode col (':');
+ const sal_Unicode dot ('.');
+ const sal_Unicode zero('0');
+ const sal_Unicode tee ('T');
+
+ if (i_rDateTime.Year < 1000) {
+ i_rBuffer.append(zero);
+ }
+ if (i_rDateTime.Year < 100) {
+ i_rBuffer.append(zero);
+ }
+ if (i_rDateTime.Year < 10) {
+ i_rBuffer.append(zero);
+ }
+ i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Year) ).append(dash);
+ if( i_rDateTime.Month < 10 ) {
+ i_rBuffer.append(zero);
+ }
+ i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Month) ).append(dash);
+ if( i_rDateTime.Day < 10 ) {
+ i_rBuffer.append(zero);
+ }
+ i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Day) );
+
+ if( i_rDateTime.Seconds != 0 ||
+ i_rDateTime.Minutes != 0 ||
+ i_rDateTime.Hours != 0 ||
+ i_bAddTimeIf0AM )
+ {
+ i_rBuffer.append(tee);
+ if( i_rDateTime.Hours < 10 ) {
+ i_rBuffer.append(zero);
+ }
+ i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Hours) )
+ .append(col);
+ if( i_rDateTime.Minutes < 10 ) {
+ i_rBuffer.append(zero);
+ }
+ i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Minutes) )
+ .append(col);
+ if( i_rDateTime.Seconds < 10 ) {
+ i_rBuffer.append(zero);
+ }
+ i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Seconds) );
+ if( i_rDateTime.HundredthSeconds > 0 ) {
+ i_rBuffer.append(dot);
+ if( i_rDateTime.HundredthSeconds < 10 ) {
+ i_rBuffer.append(zero);
+ }
+ i_rBuffer.append(
+ static_cast<sal_Int32>(i_rDateTime.HundredthSeconds) );
+ }
+ }
+}
+
+/** convert ISO "date" or "dateTime" string to util::DateTime */
+bool Converter::convertDateTime( util::DateTime& rDateTime,
+ const ::rtl::OUString& rString )
+{
+ bool isDateTime;
+ util::Date date;
+ if (convertDateOrDateTime(date, rDateTime, isDateTime, rString))
+ {
+ if (!isDateTime)
+ {
+ rDateTime.Year = date.Year;
+ rDateTime.Month = date.Month;
+ rDateTime.Day = date.Day;
+ rDateTime.Hours = 0;
+ rDateTime.Minutes = 0;
+ rDateTime.Seconds = 0;
+ rDateTime.HundredthSeconds = 0;
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+static bool
+readDateTimeComponent(const ::rtl::OUString & rString,
+ sal_Int32 & io_rnPos, sal_Int32 & o_rnTarget,
+ const sal_Int32 nMinLength, const bool bExactLength)
+{
+ const sal_Int32 nOldPos(io_rnPos);
+ sal_Int32 nTemp(0);
+ if (R_SUCCESS != readUnsignedNumber(rString, io_rnPos, nTemp))
+ {
+ return false;
+ }
+ const sal_Int32 nTokenLength(io_rnPos - nOldPos);
+ if ((nTokenLength < nMinLength) ||
+ (bExactLength && (nTokenLength > nMinLength)))
+ {
+ return false; // bad length
+ }
+ o_rnTarget = nTemp;
+ return true;
+}
+
+static bool lcl_isLeapYear(const sal_uInt32 nYear)
+{
+ return ((nYear % 4) == 0)
+ && !(((nYear % 100) == 0) || ((nYear % 400) == 0));
+}
+
+static sal_uInt16
+lcl_MaxDaysPerMonth(const sal_Int32 nMonth, const sal_Int32 nYear)
+{
+ static sal_uInt16 s_MaxDaysPerMonth[12] =
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ OSL_ASSERT(0 < nMonth && nMonth <= 12);
+ if ((2 == nMonth) && lcl_isLeapYear(nYear))
+ {
+ return 29;
+ }
+ return s_MaxDaysPerMonth[nMonth - 1];
+}
+
+/** convert ISO "date" or "dateTime" string to util::DateTime or util::Date */
+bool Converter::convertDateOrDateTime(
+ util::Date & rDate, util::DateTime & rDateTime,
+ bool & rbDateTime, const ::rtl::OUString & rString )
+{
+ bool bSuccess = true;
+
+ const ::rtl::OUString string = rString.trim().toAsciiUpperCase();
+ sal_Int32 nPos(0);
+ bool bNegative(false);
+ if ((string.getLength() > nPos) && (sal_Unicode('-') == string[nPos]))
+ {
+ ++nPos;
+ bNegative = true;
+ }
+
+ sal_Int32 nYear(0);
+ {
+ bSuccess = readDateTimeComponent(string, nPos, nYear, 4, false);
+ bSuccess &= (0 < nYear);
+ bSuccess &= (nPos < string.getLength()); // not last token
+ }
+ if (bSuccess && (sal_Unicode('-') != string[nPos])) // separator
+ {
+ bSuccess = false;
+ }
+ if (bSuccess)
+ {
+ ++nPos;
+ }
+
+ sal_Int32 nMonth(0);
+ if (bSuccess)
+ {
+ bSuccess = readDateTimeComponent(string, nPos, nMonth, 2, true);
+ bSuccess &= (0 < nMonth) && (nMonth <= 12);
+ bSuccess &= (nPos < string.getLength()); // not last token
+ }
+ if (bSuccess && (sal_Unicode('-') != string[nPos])) // separator
+ {
+ bSuccess = false;
+ }
+ if (bSuccess)
+ {
+ ++nPos;
+ }
+
+ sal_Int32 nDay(0);
+ if (bSuccess)
+ {
+ bSuccess = readDateTimeComponent(string, nPos, nDay, 2, true);
+ bSuccess &= (0 < nDay) && (nDay <= lcl_MaxDaysPerMonth(nMonth, nYear));
+ }
+
+ bool bHaveTime(false);
+ if (bSuccess && (nPos < string.getLength()))
+ {
+ if (sal_Unicode('T') == string[nPos]) // time separator
+ {
+ bHaveTime = true;
+ ++nPos;
+ }
+ }
+
+ sal_Int32 nHours(0);
+ sal_Int32 nMinutes(0);
+ sal_Int32 nSeconds(0);
+ sal_Int32 nMilliSeconds(0);
+ if (bSuccess && bHaveTime)
+ {
+ {
+ bSuccess = readDateTimeComponent(string, nPos, nHours, 2, true);
+ bSuccess &= (0 <= nHours) && (nHours <= 24);
+ bSuccess &= (nPos < string.getLength()); // not last token
+ }
+ if (bSuccess && (sal_Unicode(':') != string[nPos])) // separator
+ {
+ bSuccess = false;
+ }
+ if (bSuccess)
+ {
+ ++nPos;
+ }
+
+ if (bSuccess)
+ {
+ bSuccess = readDateTimeComponent(string, nPos, nMinutes, 2, true);
+ bSuccess &= (0 <= nMinutes) && (nMinutes < 60);
+ bSuccess &= (nPos < string.getLength()); // not last token
+ }
+ if (bSuccess && (sal_Unicode(':') != string[nPos])) // separator
+ {
+ bSuccess = false;
+ }
+ if (bSuccess)
+ {
+ ++nPos;
+ }
+
+ if (bSuccess)
+ {
+ bSuccess = readDateTimeComponent(string, nPos, nSeconds, 2, true);
+ bSuccess &= (0 <= nSeconds) && (nSeconds < 60);
+ }
+ if (bSuccess && (nPos < string.getLength()) &&
+ (sal_Unicode('.') == string[nPos])) // fraction separator
+ {
+ ++nPos;
+ const sal_Int32 nStart(nPos);
+ sal_Int32 nTemp(0);
+ if (R_NOTHING == readUnsignedNumber(string, nPos, nTemp))
+ {
+ bSuccess = false;
+ }
+ if (bSuccess)
+ {
+ // cannot use nTemp because of possible leading zeros
+ // and possible overflow => read digits directly
+ const sal_Int32 nDigits(nPos - nStart);
+ OSL_ENSURE(nDigits > 0, "bad code monkey");
+ const sal_Unicode cZero('0');
+ nMilliSeconds = 100 * (string[nStart] - cZero);
+ if (nDigits >= 2)
+ {
+ nMilliSeconds += 10 * (string[nStart+1] - cZero);
+ if (nDigits >= 3)
+ {
+ nMilliSeconds += (string[nStart+2] - cZero);
+ }
+ }
+ }
+ }
+
+ if (bSuccess && (nHours == 24))
+ {
+ if (!((0 == nMinutes) && (0 == nSeconds) && (0 == nMilliSeconds)))
+ {
+ bSuccess = false; // only 24:00:00 is valid
+ }
+#if 0
+ else
+ {
+ nHours = 0; // normalize 24:00:00 to 00:00:00 of next day
+ lcl_addDay(bNegative, nYear, nMonth, nDay, 1);
+ }
+#endif
+ }
+ }
+
+ bool bHaveTimezone(false);
+ bool bHaveTimezonePlus(false);
+ bool bHaveTimezoneMinus(false);
+ if (bSuccess && (nPos < string.getLength()))
+ {
+ const sal_Unicode c(string[nPos]);
+ if (sal_Unicode('+') == c)
+ {
+ bHaveTimezone = true;
+ bHaveTimezonePlus = true;
+ ++nPos;
+ }
+ else if (sal_Unicode('-') == c)
+ {
+ bHaveTimezone = true;
+ bHaveTimezoneMinus = true;
+ ++nPos;
+ }
+ else if (sal_Unicode('Z') == c)
+ {
+ bHaveTimezone = true;
+ ++nPos;
+ }
+ else
+ {
+ bSuccess = false;
+ }
+ }
+ sal_Int32 nTimezoneHours(0);
+ sal_Int32 nTimezoneMinutes(0);
+ if (bSuccess && (bHaveTimezonePlus || bHaveTimezoneMinus))
+ {
+ bSuccess = readDateTimeComponent(
+ string, nPos, nTimezoneHours, 2, true);
+ bSuccess &= (0 <= nTimezoneHours) && (nTimezoneHours <= 14);
+ bSuccess &= (nPos < string.getLength()); // not last token
+ if (bSuccess && (sal_Unicode(':') != string[nPos])) // separator
+ {
+ bSuccess = false;
+ }
+ if (bSuccess)
+ {
+ ++nPos;
+ }
+ if (bSuccess)
+ {
+ bSuccess = readDateTimeComponent(
+ string, nPos, nTimezoneMinutes, 2, true);
+ bSuccess &= (0 <= nTimezoneMinutes) && (nTimezoneMinutes < 60);
+ }
+ if (bSuccess && (nTimezoneHours == 14))
+ {
+ if (0 != nTimezoneMinutes)
+ {
+ bSuccess = false; // only +-14:00 is valid
+ }
+ }
+ }
+
+ bSuccess &= (nPos == string.getLength()); // trailing junk?
+
+ if (bSuccess && bHaveTimezone)
+ {
+ // util::DateTime does not support timezones!
+#if 0
+ // do not add timezone, just strip it (as suggested by er)
+ lcl_addTimezone(bNegative, nYear, nMonth, nDay, nHours, nMinutes,
+ !bHaveTimezoneMinus, nTimezoneHours, nTimezoneMinutes);
+#endif
+ }
+
+ if (bSuccess)
+ {
+ if (bHaveTime) // time is optional
+ {
+ // util::DateTime does not support negative years!
+ rDateTime.Year = static_cast<sal_uInt16>(nYear);
+ rDateTime.Month = static_cast<sal_uInt16>(nMonth);
+ rDateTime.Day = static_cast<sal_uInt16>(nDay);
+ rDateTime.Hours = static_cast<sal_uInt16>(nHours);
+ rDateTime.Minutes = static_cast<sal_uInt16>(nMinutes);
+ rDateTime.Seconds = static_cast<sal_uInt16>(nSeconds);
+ // util::DateTime does not support 3 decimal digits of precision!
+ rDateTime.HundredthSeconds =
+ static_cast<sal_uInt16>(nMilliSeconds / 10);
+ rbDateTime = true;
+ }
+ else
+ {
+ rDate.Year = static_cast<sal_uInt16>(nYear);
+ rDate.Month = static_cast<sal_uInt16>(nMonth);
+ rDate.Day = static_cast<sal_uInt16>(nDay);
+ rbDateTime = false;
+ }
+ }
+ return bSuccess;
+}
+
+
+/** gets the position of the first comma after npos in the string
+ rStr. Commas inside '"' pairs are not matched */
+sal_Int32 Converter::indexOfComma( const OUString& rStr,
+ sal_Int32 nPos )
+{
+ sal_Unicode cQuote = 0;
+ sal_Int32 nLen = rStr.getLength();
+ for( ; nPos < nLen; nPos++ )
+ {
+ sal_Unicode c = rStr[nPos];
+ switch( c )
+ {
+ case sal_Unicode('\''):
+ if( 0 == cQuote )
+ cQuote = c;
+ else if( '\'' == cQuote )
+ cQuote = 0;
+ break;
+
+ case sal_Unicode('"'):
+ if( 0 == cQuote )
+ cQuote = c;
+ else if( '\"' == cQuote )
+ cQuote = 0;
+ break;
+
+ case sal_Unicode(','):
+ if( 0 == cQuote )
+ return nPos;
+ break;
+ }
+ }
+
+ return -1;
+}
+
+const
+ sal_Char aBase64EncodeTable[] =
+ { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
+
+const
+ sal_uInt8 aBase64DecodeTable[] =
+ { 62,255,255,255, 63, // 43-47
+// + /
+
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, // 48-63
+// 0 1 2 3 4 5 6 7 8 9 =
+
+ 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79
+// A B C D E F G H I J K L M N O
+
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, // 80-95
+// P Q R S T U V W X Y Z
+
+ 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111
+// a b c d e f g h i j k l m n o
+
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; // 112-123
+// p q r s t u v w x y z
+
+
+
+void ThreeByteToFourByte (const sal_Int8* pBuffer, const sal_Int32 nStart, const sal_Int32 nFullLen, rtl::OUStringBuffer& sBuffer)
+{
+ sal_Int32 nLen(nFullLen - nStart);
+ if (nLen > 3)
+ nLen = 3;
+ if (nLen == 0)
+ {
+ sBuffer.setLength(0);
+ return;
+ }
+
+ sal_Int32 nBinaer;
+ switch (nLen)
+ {
+ case 1:
+ {
+ nBinaer = ((sal_uInt8)pBuffer[nStart + 0]) << 16;
+ }
+ break;
+ case 2:
+ {
+ nBinaer = (((sal_uInt8)pBuffer[nStart + 0]) << 16) +
+ (((sal_uInt8)pBuffer[nStart + 1]) << 8);
+ }
+ break;
+ default:
+ {
+ nBinaer = (((sal_uInt8)pBuffer[nStart + 0]) << 16) +
+ (((sal_uInt8)pBuffer[nStart + 1]) << 8) +
+ ((sal_uInt8)pBuffer[nStart + 2]);
+ }
+ break;
+ }
+
+ sBuffer.appendAscii("====");
+
+ sal_uInt8 nIndex (static_cast<sal_uInt8>((nBinaer & 0xFC0000) >> 18));
+ sBuffer.setCharAt(0, aBase64EncodeTable [nIndex]);
+
+ nIndex = static_cast<sal_uInt8>((nBinaer & 0x3F000) >> 12);
+ sBuffer.setCharAt(1, aBase64EncodeTable [nIndex]);
+ if (nLen == 1)
+ return;
+
+ nIndex = static_cast<sal_uInt8>((nBinaer & 0xFC0) >> 6);
+ sBuffer.setCharAt(2, aBase64EncodeTable [nIndex]);
+ if (nLen == 2)
+ return;
+
+ nIndex = static_cast<sal_uInt8>((nBinaer & 0x3F));
+ sBuffer.setCharAt(3, aBase64EncodeTable [nIndex]);
+}
+
+void Converter::encodeBase64(rtl::OUStringBuffer& aStrBuffer, const uno::Sequence<sal_Int8>& aPass)
+{
+ sal_Int32 i(0);
+ sal_Int32 nBufferLength(aPass.getLength());
+ const sal_Int8* pBuffer = aPass.getConstArray();
+ while (i < nBufferLength)
+ {
+ rtl::OUStringBuffer sBuffer;
+ ThreeByteToFourByte (pBuffer, i, nBufferLength, sBuffer);
+ aStrBuffer.append(sBuffer);
+ i += 3;
+ }
+}
+
+void Converter::decodeBase64(uno::Sequence<sal_Int8>& aBuffer, const rtl::OUString& sBuffer)
+{
+#if OSL_DEBUG_LEVEL > 0
+ sal_Int32 nCharsDecoded =
+#endif
+ decodeBase64SomeChars( aBuffer, sBuffer );
+ OSL_ENSURE( nCharsDecoded == sBuffer.getLength(), "some bytes left in base64 decoding!" );
+}
+
+sal_Int32 Converter::decodeBase64SomeChars(
+ uno::Sequence<sal_Int8>& rOutBuffer,
+ const rtl::OUString& rInBuffer)
+{
+ sal_Int32 nInBufferLen = rInBuffer.getLength();
+ sal_Int32 nMinOutBufferLen = (nInBufferLen / 4) * 3;
+ if( rOutBuffer.getLength() < nMinOutBufferLen )
+ rOutBuffer.realloc( nMinOutBufferLen );
+
+ const sal_Unicode *pInBuffer = rInBuffer.getStr();
+ sal_Int8 *pOutBuffer = rOutBuffer.getArray();
+ sal_Int8 *pOutBufferStart = pOutBuffer;
+ sal_Int32 nCharsDecoded = 0;
+
+ sal_uInt8 aDecodeBuffer[4];
+ sal_Int32 nBytesToDecode = 0;
+ sal_Int32 nBytesGotFromDecoding = 3;
+ sal_Int32 nInBufferPos= 0;
+ while( nInBufferPos < nInBufferLen )
+ {
+ sal_Unicode cChar = *pInBuffer;
+ if( cChar >= '+' && cChar <= 'z' )
+ {
+ sal_uInt8 nByte = aBase64DecodeTable[cChar-'+'];
+ if( nByte != 255 )
+ {
+ // We have found a valid character!
+ aDecodeBuffer[nBytesToDecode++] = nByte;
+
+ // One '=' character at the end means 2 out bytes
+ // Two '=' characters at the end mean 1 out bytes
+ if( '=' == cChar && nBytesToDecode > 2 )
+ nBytesGotFromDecoding--;
+ if( 4 == nBytesToDecode )
+ {
+ // Four characters found, so we may convert now!
+ sal_uInt32 nOut = (aDecodeBuffer[0] << 18) +
+ (aDecodeBuffer[1] << 12) +
+ (aDecodeBuffer[2] << 6) +
+ aDecodeBuffer[3];
+
+ *pOutBuffer++ = (sal_Int8)((nOut & 0xff0000) >> 16);
+ if( nBytesGotFromDecoding > 1 )
+ *pOutBuffer++ = (sal_Int8)((nOut & 0xff00) >> 8);
+ if( nBytesGotFromDecoding > 2 )
+ *pOutBuffer++ = (sal_Int8)(nOut & 0xff);
+ nCharsDecoded = nInBufferPos + 1;
+ nBytesToDecode = 0;
+ nBytesGotFromDecoding = 3;
+ }
+ }
+ else
+ {
+ nCharsDecoded++;
+ }
+ }
+ else
+ {
+ nCharsDecoded++;
+ }
+
+ nInBufferPos++;
+ pInBuffer++;
+ }
+ if( (pOutBuffer - pOutBufferStart) != rOutBuffer.getLength() )
+ rOutBuffer.realloc( pOutBuffer - pOutBufferStart );
+
+ return nCharsDecoded;
+}
+
+void Converter::clearUndefinedChars(rtl::OUString& rTarget, const rtl::OUString& rSource)
+{
+ sal_uInt32 nLength(rSource.getLength());
+ rtl::OUStringBuffer sBuffer(nLength);
+ for (sal_uInt32 i = 0; i < nLength; i++)
+ {
+ sal_Unicode cChar = rSource[i];
+ if (!(cChar < 0x0020) ||
+ (cChar == 0x0009) || // TAB
+ (cChar == 0x000A) || // LF
+ (cChar == 0x000D)) // legal character
+ sBuffer.append(cChar);
+ }
+ rTarget = sBuffer.makeStringAndClear();
+}
+
+double Converter::GetConversionFactor(::rtl::OUStringBuffer& rUnit, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
+{
+ double fRetval(1.0);
+ rUnit.setLength(0L);
+
+ const sal_Char* psUnit = 0;
+
+ if(nSourceUnit != nTargetUnit)
+ {
+ switch(nSourceUnit)
+ {
+ case MeasureUnit::TWIP:
+ {
+ switch(nTargetUnit)
+ {
+ case MeasureUnit::MM_100TH:
+ case MeasureUnit::MM_10TH:
+ {
+ OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for twip values");
+ }
+ case MeasureUnit::MM:
+ {
+ // 0.01mm = 0.57twip (exactly)
+ fRetval = ((25400.0 / 1440.0) / 1000.0);
+ psUnit = gpsMM;
+ break;
+ }
+ case MeasureUnit::CM:
+ {
+ // 0.001cm = 0.57twip (exactly)
+ fRetval = ((25400.0 / 1440.0) / 10000.0);
+ psUnit = gpsCM;
+ break;
+ }
+ case MeasureUnit::POINT:
+ {
+ // 0.01pt = 0.2twip (exactly)
+ fRetval = ((1000.0 / 20.0) / 1000.0);
+ psUnit = gpsPT;
+ break;
+ }
+ case MeasureUnit::INCH:
+ default:
+ {
+ OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for twip values");
+ // 0.0001in = 0.144twip (exactly)
+ fRetval = ((100000.0 / 1440.0) / 100000.0);
+ psUnit = gpsINCH;
+ break;
+ }
+ }
+ break;
+ }
+ case MeasureUnit::POINT:
+ {
+ switch(nTargetUnit)
+ {
+ case MeasureUnit::MM:
+ // 1mm = 72 / 25.4 pt (exactly)
+ fRetval = ( 25.4 / 72.0 );
+ psUnit = gpsMM;
+ break;
+
+ case MeasureUnit::CM:
+ // 1cm = 72 / 2.54 pt (exactly)
+ fRetval = ( 2.54 / 72.0 );
+ psUnit = gpsCM;
+ break;
+
+ case MeasureUnit::TWIP:
+ // 1twip = 72 / 1440 pt (exactly)
+ fRetval = 20.0; // 1440.0 / 72.0
+ psUnit = gpsPC;
+ break;
+
+ case MeasureUnit::INCH:
+ default:
+ OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for pt values");
+ // 1in = 72 pt (exactly)
+ fRetval = ( 1.0 / 72.0 );
+ psUnit = gpsINCH;
+ break;
+ }
+ break;
+ }
+ case MeasureUnit::MM_10TH:
+ {
+ switch(nTargetUnit)
+ {
+ case MeasureUnit::MM_100TH:
+ case MeasureUnit::MM_10TH:
+ {
+ OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values");
+ }
+ case MeasureUnit::MM:
+ {
+ // 0.01mm = 1 mm/100 (exactly)
+ fRetval = ((10.0 / 1.0) / 100.0);
+ psUnit = gpsMM;
+ break;
+ }
+ case MeasureUnit::CM:
+ {
+ // 0.001mm = 1 mm/100 (exactly)
+ fRetval = ((10.0 / 1.0) / 1000.0);
+ psUnit = gpsCM;
+ break;
+ }
+ case MeasureUnit::POINT:
+ {
+ // 0.01pt = 0.35 mm/100 (exactly)
+ fRetval = ((72000.0 / 2540.0) / 100.0);
+ psUnit = gpsPT;
+ break;
+ }
+ case MeasureUnit::INCH:
+ default:
+ {
+ OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values");
+ // 0.0001in = 0.254 mm/100 (exactly)
+ fRetval = ((100000.0 / 2540.0) / 10000.0);
+ psUnit = gpsINCH;
+ break;
+ }
+ }
+ break;
+ }
+ case MeasureUnit::MM_100TH:
+ {
+ switch(nTargetUnit)
+ {
+ case MeasureUnit::MM_100TH:
+ case MeasureUnit::MM_10TH:
+ {
+ OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values");
+ }
+ case MeasureUnit::MM:
+ {
+ // 0.01mm = 1 mm/100 (exactly)
+ fRetval = ((10.0 / 1.0) / 1000.0);
+ psUnit = gpsMM;
+ break;
+ }
+ case MeasureUnit::CM:
+ {
+ // 0.001mm = 1 mm/100 (exactly)
+ fRetval = ((10.0 / 1.0) / 10000.0);
+ psUnit = gpsCM;
+ break;
+ }
+ case MeasureUnit::POINT:
+ {
+ // 0.01pt = 0.35 mm/100 (exactly)
+ fRetval = ((72000.0 / 2540.0) / 1000.0);
+ psUnit = gpsPT;
+ break;
+ }
+ case MeasureUnit::INCH:
+ default:
+ {
+ OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values");
+ // 0.0001in = 0.254 mm/100 (exactly)
+ fRetval = ((100000.0 / 2540.0) / 100000.0);
+ psUnit = gpsINCH;
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ if( psUnit )
+ rUnit.appendAscii( psUnit );
+ }
+
+ return fRetval;
+}
+
+sal_Int16 Converter::GetUnitFromString(const ::rtl::OUString& rString, sal_Int16 nDefaultUnit)
+{
+ sal_Int32 nPos = 0L;
+ sal_Int32 nLen = rString.getLength();
+ sal_Int16 nRetUnit = nDefaultUnit;
+
+ // skip white space
+ while( nPos < nLen && sal_Unicode(' ') == rString[nPos] )
+ nPos++;
+
+ // skip negative
+ if( nPos < nLen && sal_Unicode('-') == rString[nPos] )
+ nPos++;
+
+ // skip number
+ while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] )
+ nPos++;
+
+ if( nPos < nLen && sal_Unicode('.') == rString[nPos] )
+ {
+ nPos++;
+ while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] )
+ nPos++;
+ }
+
+ // skip white space
+ while( nPos < nLen && sal_Unicode(' ') == rString[nPos] )
+ nPos++;
+
+ if( nPos < nLen )
+ {
+ switch(rString[nPos])
+ {
+ case sal_Unicode('%') :
+ {
+ nRetUnit = MeasureUnit::PERCENT;
+ break;
+ }
+ case sal_Unicode('c'):
+ case sal_Unicode('C'):
+ {
+ if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('m')
+ || rString[nPos+1] == sal_Unicode('M')))
+ nRetUnit = MeasureUnit::CM;
+ break;
+ }
+ case sal_Unicode('e'):
+ case sal_Unicode('E'):
+ {
+ // CSS1_EMS or CSS1_EMX later
+ break;
+ }
+ case sal_Unicode('i'):
+ case sal_Unicode('I'):
+ {
+ if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('n')
+ || rString[nPos+1] == sal_Unicode('n')))
+ nRetUnit = MeasureUnit::INCH;
+ break;
+ }
+ case sal_Unicode('m'):
+ case sal_Unicode('M'):
+ {
+ if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('m')
+ || rString[nPos+1] == sal_Unicode('M')))
+ nRetUnit = MeasureUnit::MM;
+ break;
+ }
+ case sal_Unicode('p'):
+ case sal_Unicode('P'):
+ {
+ if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('t')
+ || rString[nPos+1] == sal_Unicode('T')))
+ nRetUnit = MeasureUnit::POINT;
+ if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('c')
+ || rString[nPos+1] == sal_Unicode('C')))
+ nRetUnit = MeasureUnit::TWIP;
+ break;
+ }
+ }
+ }
+
+ return nRetUnit;
+}
+
+}
diff --git a/sax/source/tools/fastattribs.cxx b/sax/source/tools/fastattribs.cxx
new file mode 100644
index 000000000000..4bf9d55c75b8
--- /dev/null
+++ b/sax/source/tools/fastattribs.cxx
@@ -0,0 +1,168 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <algorithm>
+#include <boost/bind.hpp>
+
+#include <sax/fastattribs.hxx>
+
+using ::rtl::OUString;
+using ::rtl::OString;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::xml;
+using namespace ::com::sun::star::xml::sax;
+namespace sax_fastparser
+{
+
+UnknownAttribute::UnknownAttribute( const OUString& rNamespaceURL, const OString& rName, const OString& rValue )
+ : maNamespaceURL( rNamespaceURL ), maName( rName ), maValue( rValue )
+{
+}
+
+UnknownAttribute::UnknownAttribute( const OString& rName, const OString& rValue )
+ : maName( rName ), maValue( rValue )
+{
+}
+
+void UnknownAttribute::FillAttribute( Attribute* pAttrib ) const
+{
+ if( pAttrib )
+ {
+ pAttrib->Name = OStringToOUString( maName, RTL_TEXTENCODING_UTF8 );
+ pAttrib->NamespaceURL = maNamespaceURL;
+ pAttrib->Value = OStringToOUString( maValue, RTL_TEXTENCODING_UTF8 );
+ }
+}
+
+FastAttributeList::FastAttributeList( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >& xTokenHandler )
+: mxTokenHandler( xTokenHandler )
+{
+ maLastIter = maAttributes.end();
+}
+
+FastAttributeList::~FastAttributeList()
+{
+}
+
+void FastAttributeList::clear()
+{
+ maAttributes.clear();
+ maUnknownAttributes.clear();
+ maLastIter = maAttributes.end();
+}
+
+void FastAttributeList::add( sal_Int32 nToken, const OString& rValue )
+{
+ maAttributes[nToken] = rValue;
+}
+
+void FastAttributeList::addUnknown( const OUString& rNamespaceURL, const OString& rName, const OString& rValue )
+{
+ maUnknownAttributes.push_back( UnknownAttribute( rNamespaceURL, rName, rValue ) );
+}
+
+void FastAttributeList::addUnknown( const OString& rName, const OString& rValue )
+{
+ maUnknownAttributes.push_back( UnknownAttribute( rName, rValue ) );
+}
+
+// XFastAttributeList
+sal_Bool FastAttributeList::hasAttribute( ::sal_Int32 Token ) throw (RuntimeException)
+{
+ maLastIter = maAttributes.find( Token );
+ return ( maLastIter != maAttributes.end() ) ? sal_True : sal_False;
+}
+
+sal_Int32 FastAttributeList::getValueToken( ::sal_Int32 Token ) throw (SAXException, RuntimeException)
+{
+ if( ( maLastIter == maAttributes.end() ) || ( ( *maLastIter ).first != Token ) )
+ maLastIter = maAttributes.find( Token );
+
+ if( maLastIter == maAttributes.end() )
+ throw SAXException();
+
+ Sequence< sal_Int8 > aSeq( (sal_Int8*)(*maLastIter).second.getStr(), (*maLastIter).second.getLength() ) ;
+ return mxTokenHandler->getTokenFromUTF8( aSeq );
+}
+
+sal_Int32 FastAttributeList::getOptionalValueToken( ::sal_Int32 Token, ::sal_Int32 Default ) throw (RuntimeException)
+{
+ if( ( maLastIter == maAttributes.end() ) || ( ( *maLastIter ).first != Token ) )
+ maLastIter = maAttributes.find( Token );
+
+ if( maLastIter == maAttributes.end() )
+ return Default;
+
+ Sequence< sal_Int8 > aSeq( (sal_Int8*)(*maLastIter).second.getStr(), (*maLastIter).second.getLength() ) ;
+ return mxTokenHandler->getTokenFromUTF8( aSeq );
+}
+
+OUString FastAttributeList::getValue( ::sal_Int32 Token ) throw (SAXException, RuntimeException)
+{
+ if( ( maLastIter == maAttributes.end() ) || ( ( *maLastIter ).first != Token ) )
+ maLastIter = maAttributes.find( Token );
+
+ if( maLastIter == maAttributes.end() )
+ throw SAXException();
+
+ return OStringToOUString( (*maLastIter).second, RTL_TEXTENCODING_UTF8 );
+}
+
+OUString FastAttributeList::getOptionalValue( ::sal_Int32 Token ) throw (RuntimeException)
+{
+ if( ( maLastIter == maAttributes.end() ) || ( ( *maLastIter ).first != Token ) )
+ maLastIter = maAttributes.find( Token );
+
+ OUString aRet;
+ if( maLastIter != maAttributes.end() )
+ aRet = OStringToOUString( (*maLastIter).second, RTL_TEXTENCODING_UTF8 );
+
+ return aRet;
+}
+Sequence< Attribute > FastAttributeList::getUnknownAttributes( ) throw (RuntimeException)
+{
+ Sequence< Attribute > aSeq( maUnknownAttributes.size() );
+ Attribute* pAttr = aSeq.getArray();
+ for( UnknownAttributeList::iterator attrIter = maUnknownAttributes.begin(); attrIter != maUnknownAttributes.end(); attrIter++ )
+ (*attrIter).FillAttribute( pAttr++ );
+ return aSeq;
+}
+Sequence< FastAttribute > FastAttributeList::getFastAttributes( ) throw (RuntimeException)
+{
+ Sequence< FastAttribute > aSeq( maAttributes.size() );
+ FastAttribute* pAttr = aSeq.getArray();
+ FastAttributeMap::iterator fastAttrIter = maAttributes.begin();
+ for(; fastAttrIter != maAttributes.end(); fastAttrIter++ )
+ {
+ pAttr->Token = fastAttrIter->first;
+ pAttr->Value = OStringToOUString( fastAttrIter->second, RTL_TEXTENCODING_UTF8 );
+ pAttr++;
+ }
+ return aSeq;
+}
+
+}
diff --git a/sax/source/tools/fastserializer.cxx b/sax/source/tools/fastserializer.cxx
new file mode 100644
index 000000000000..b0318516b72c
--- /dev/null
+++ b/sax/source/tools/fastserializer.cxx
@@ -0,0 +1,401 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#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( "&lt;" ); break;
+ case '>': sBuf.appendAscii( "&gt;" ); break;
+ case '&': sBuf.appendAscii( "&amp;" ); break;
+ case '\'': sBuf.appendAscii( "&apos;" ); break;
+ case '"': sBuf.appendAscii( "&quot;" ); 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( ForMerge() );
+ }
+
+ void FastSaxSerializer::mergeTopMarks( sax_fastparser::MergeMarksEnum eMergeType )
+ {
+ if ( maMarkStack.empty() )
+ return;
+
+ if ( maMarkStack.size() == 1 )
+ {
+ mxOutputStream->writeBytes( maMarkStack.top().getData() );
+ maMarkStack.pop();
+ return;
+ }
+
+ const Int8Sequence aMerge( maMarkStack.top().getData() );
+ maMarkStack.pop();
+
+ switch ( eMergeType )
+ {
+ case MERGE_MARKS_APPEND: maMarkStack.top().append( aMerge ); break;
+ case MERGE_MARKS_PREPEND: maMarkStack.top().prepend( aMerge ); break;
+ case MERGE_MARKS_POSTPONE: maMarkStack.top().postpone( aMerge ); break;
+ }
+ }
+
+ void FastSaxSerializer::writeBytes( const Sequence< ::sal_Int8 >& aData ) throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
+ {
+ if ( maMarkStack.empty() )
+ mxOutputStream->writeBytes( aData );
+ else
+ maMarkStack.top().append( aData );
+ }
+
+ FastSaxSerializer::Int8Sequence& FastSaxSerializer::ForMerge::getData()
+ {
+ merge( maData, maPostponed, true );
+ maPostponed.realloc( 0 );
+
+ return maData;
+ }
+
+ void FastSaxSerializer::ForMerge::prepend( const Int8Sequence &rWhat )
+ {
+ merge( maData, rWhat, false );
+ }
+
+ void FastSaxSerializer::ForMerge::append( const Int8Sequence &rWhat )
+ {
+ merge( maData, rWhat, true );
+ }
+
+ void FastSaxSerializer::ForMerge::postpone( const Int8Sequence &rWhat )
+ {
+ merge( maPostponed, rWhat, true );
+ }
+
+ void FastSaxSerializer::ForMerge::merge( Int8Sequence &rTop, const Int8Sequence &rMerge, bool bAppend )
+ {
+ sal_Int32 nMergeLen = rMerge.getLength();
+ if ( nMergeLen > 0 )
+ {
+ sal_Int32 nTopLen = rTop.getLength();
+
+ rTop.realloc( nTopLen + nMergeLen );
+ if ( bAppend )
+ {
+ // append the rMerge to the rTop
+ memcpy( rTop.getArray() + nTopLen, rMerge.getConstArray(), nMergeLen );
+ }
+ else
+ {
+ // prepend the rMerge to the rTop
+ memmove( rTop.getArray() + nMergeLen, rTop.getConstArray(), nTopLen );
+ memcpy( rTop.getArray(), rMerge.getConstArray(), nMergeLen );
+ }
+ }
+ }
+
+} // namespace sax_fastparser
+
diff --git a/sax/source/tools/fastserializer.hxx b/sax/source/tools/fastserializer.hxx
new file mode 100644
index 000000000000..a98a0ff7a67d
--- /dev/null
+++ b/sax/source/tools/fastserializer.hxx
@@ -0,0 +1,161 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SAX_FASTSERIALIZER_HXX
+#define SAX_FASTSERIALIZER_HXX
+
+#include <com/sun/star/xml/sax/XFastSerializer.hpp>
+#include <com/sun/star/xml/sax/XFastTokenHandler.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <cppuhelper/implbase2.hxx>
+
+#include <stack>
+
+#include "sax/dllapi.h"
+#include "sax/fshelper.hxx"
+
+#define SERIALIZER_IMPLEMENTATION_NAME "com.sun.star.comp.extensions.xml.sax.FastSerializer"
+#define SERIALIZER_SERVICE_NAME "com.sun.star.xml.sax.FastSerializer"
+
+namespace sax_fastparser {
+
+class SAX_DLLPUBLIC FastSaxSerializer : public ::cppu::WeakImplHelper2< ::com::sun::star::xml::sax::XFastSerializer, ::com::sun::star::lang::XServiceInfo >
+{
+public:
+ explicit FastSaxSerializer( );
+ virtual ~FastSaxSerializer();
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > getOutputStream() {return mxOutputStream;}
+
+ // The implementation details
+ static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static(void);
+ static ::rtl::OUString getImplementationName_Static();
+
+ // XFastSerializer
+ virtual void SAL_CALL startDocument( ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL endDocument( ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL startFastElement( ::sal_Int32 Element, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs )
+ throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL startUnknownElement( const ::rtl::OUString& Namespace, const ::rtl::OUString& Name, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs )
+ throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL endFastElement( ::sal_Int32 Element )
+ throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL endUnknownElement( const ::rtl::OUString& Namespace, const ::rtl::OUString& Name )
+ throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL singleFastElement( ::sal_Int32 Element, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs )
+ throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL singleUnknownElement( const ::rtl::OUString& Namespace, const ::rtl::OUString& Name, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs )
+ throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL characters( const ::rtl::OUString& aChars )
+ throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setOutputStream( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >& xOutputStream )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setFastTokenHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >& xFastTokenHandler )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw ( ::com::sun::star::uno::RuntimeException );
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw ( ::com::sun::star::uno::RuntimeException );
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw ( ::com::sun::star::uno::RuntimeException );
+
+ // C++ helpers
+ virtual void SAL_CALL writeId( ::sal_Int32 Element );
+
+ static ::rtl::OUString escapeXml( const ::rtl::OUString& s );
+
+public:
+ /** From now on, don't write directly to the stream, but to top of a stack.
+
+ This is to be able to change the order of the data being written.
+ If you need to write eg.
+ p, r, rPr, [something], /rPr, t, [text], /r, /p,
+ but get it in order
+ p, r, t, [text], /t, rPr, [something], /rPr, /r, /p,
+ simply do
+ p, r, mark(), t, [text], /t, mark(), rPr, [something], /rPr,
+ mergeTopMarks( true ), mergeTopMarks(), /r, /p
+ and you are done.
+ */
+ void mark();
+
+ /** Merge 2 topmost marks.
+
+ There are 3 possibilities - prepend the top before the second top-most
+ mark, append it, or append it later; prepending brings the possibility
+ to switch parts of the output, appending later allows to write some
+ output in advance.
+
+ Writes the result to the output stream if the mark stack becomes empty
+ by the operation.
+
+ When the MERGE_MARKS_POSTPONE is specified, the merge happens just
+ before the next merge.
+
+ @see mark()
+ */
+ void mergeTopMarks( sax_fastparser::MergeMarksEnum eMergeType = sax_fastparser::MERGE_MARKS_APPEND );
+
+private:
+ ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > mxOutputStream;
+ ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler > mxFastTokenHandler;
+
+ typedef ::com::sun::star::uno::Sequence< ::sal_Int8 > Int8Sequence;
+ class ForMerge
+ {
+ Int8Sequence maData;
+ Int8Sequence maPostponed;
+
+ public:
+ ForMerge() : maData(), maPostponed() {}
+
+ Int8Sequence& getData();
+
+ void prepend( const Int8Sequence &rWhat );
+ void append( const Int8Sequence &rWhat );
+ void postpone( const Int8Sequence &rWhat );
+
+ private:
+ static void merge( Int8Sequence &rTop, const Int8Sequence &rMerge, bool bAppend );
+ };
+
+ ::std::stack< ForMerge > maMarkStack;
+
+ void writeFastAttributeList( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs );
+ void write( const ::rtl::OUString& s );
+
+protected:
+ /** Forward the call to the output stream, or write to the stack.
+
+ The latter in the case that we are inside a mark().
+ */
+ void writeBytes( const ::com::sun::star::uno::Sequence< ::sal_Int8 >& aData ) throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+};
+
+} // namespace sax_fastparser
+
+#endif
diff --git a/sax/source/tools/fshelper.cxx b/sax/source/tools/fshelper.cxx
new file mode 100644
index 000000000000..743f499fb4f0
--- /dev/null
+++ b/sax/source/tools/fshelper.cxx
@@ -0,0 +1,201 @@
+#include <sax/fshelper.hxx>
+#include "fastserializer.hxx"
+#include <com/sun/star/xml/sax/XFastTokenHandler.hpp>
+#include <comphelper/processfactory.hxx>
+#include <rtl/ustrbuf.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace sax_fastparser {
+
+FastSerializerHelper::FastSerializerHelper(const Reference< io::XOutputStream >& xOutputStream ) :
+ mpSerializer(new FastSaxSerializer())
+{
+ Reference< lang::XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
+ mxTokenHandler = Reference<xml::sax::XFastTokenHandler> ( xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.sax.FastTokenHandler") ) ), UNO_QUERY_THROW );
+
+ mpSerializer->setFastTokenHandler( mxTokenHandler );
+ mpSerializer->setOutputStream( xOutputStream );
+ mpSerializer->startDocument();
+}
+
+FastSerializerHelper::~FastSerializerHelper()
+{
+ mpSerializer->endDocument();
+
+ if (mpSerializer) {
+ delete mpSerializer;
+ mpSerializer = NULL;
+ }
+}
+
+void FastSerializerHelper::startElement(const char* elementName, ...)
+{
+ FastAttributeList* pAttrList = new FastAttributeList( mxTokenHandler );
+ va_list args;
+ va_start(args, elementName);
+ while (true)
+ {
+ const char* pName = va_arg(args, const char*);
+ if (!pName)
+ break;
+ const char* pValue = va_arg(args, const char*);
+ if (pValue)
+ pAttrList->addUnknown(pName, pValue);
+ }
+ va_end(args);
+ const com::sun::star::uno::Reference<com::sun::star::xml::sax::XFastAttributeList> xAttrList(pAttrList);
+ mpSerializer->startUnknownElement(::rtl::OUString(), ::rtl::OUString::createFromAscii(elementName), xAttrList);
+}
+
+void FastSerializerHelper::singleElement(const char* elementName, ...)
+{
+ FastAttributeList* pAttrList = new FastAttributeList( mxTokenHandler );
+ va_list args;
+ va_start(args, elementName);
+ while (true)
+ {
+ const char* pName = va_arg(args, const char*);
+ if (!pName)
+ break;
+ const char* pValue = va_arg(args, const char*);
+ if (pValue)
+ pAttrList->addUnknown(pName, pValue);
+ }
+ va_end(args);
+ const com::sun::star::uno::Reference<com::sun::star::xml::sax::XFastAttributeList> xAttrList(pAttrList);
+ mpSerializer->singleUnknownElement(::rtl::OUString(), ::rtl::OUString::createFromAscii(elementName), xAttrList);
+}
+
+void FastSerializerHelper::endElement(const char* elementName)
+{
+ mpSerializer->endUnknownElement(::rtl::OUString(), ::rtl::OUString::createFromAscii(elementName));
+}
+
+void FastSerializerHelper::startElementV(sal_Int32 elementTokenId, va_list args)
+{
+ FastAttributeList* pAttrList = new FastAttributeList( mxTokenHandler );
+
+ while (true)
+ {
+ sal_Int32 nName = va_arg(args, sal_Int32);
+ if (nName == FSEND)
+ break;
+ const char* pValue = va_arg(args, const char*);
+ if (pValue)
+ pAttrList->add(nName, pValue);
+ }
+
+ const com::sun::star::uno::Reference<com::sun::star::xml::sax::XFastAttributeList> xAttrList(pAttrList);
+ mpSerializer->startFastElement(elementTokenId, xAttrList);
+}
+
+void FastSerializerHelper::singleElementV(sal_Int32 elementTokenId, va_list args)
+{
+ FastAttributeList* pAttrList = new FastAttributeList( mxTokenHandler );
+
+ while (true)
+ {
+ sal_Int32 nName = va_arg(args, sal_Int32);
+ if (nName == FSEND)
+ break;
+ const char* pValue = va_arg(args, const char*);
+ if (pValue)
+ pAttrList->add(nName, pValue);
+ }
+
+ const com::sun::star::uno::Reference<com::sun::star::xml::sax::XFastAttributeList> xAttrList(pAttrList);
+ mpSerializer->singleFastElement(elementTokenId, xAttrList);
+}
+
+void FastSerializerHelper::endElement(sal_Int32 elementTokenId)
+{
+ mpSerializer->endFastElement(elementTokenId);
+}
+
+void FastSerializerHelper::startElementV(sal_Int32 elementTokenId, XFastAttributeListRef xAttrList)
+{
+ mpSerializer->startFastElement(elementTokenId, xAttrList);
+}
+
+
+void FastSerializerHelper::singleElement(const char* elementName, XFastAttributeListRef xAttrList)
+{
+ mpSerializer->singleUnknownElement(::rtl::OUString(), ::rtl::OUString::createFromAscii(elementName), xAttrList);
+}
+
+void FastSerializerHelper::singleElementV(sal_Int32 elementTokenId, XFastAttributeListRef xAttrList)
+{
+ mpSerializer->singleFastElement(elementTokenId, xAttrList);
+}
+
+FastSerializerHelper* FastSerializerHelper::write(const char* value)
+{
+ return write(rtl::OUString::createFromAscii(value));
+}
+
+FastSerializerHelper* FastSerializerHelper::write(const rtl::OUString& value)
+{
+ mpSerializer->characters(value);
+ return this;
+}
+
+FastSerializerHelper* FastSerializerHelper::write(sal_Int32 value)
+{
+ return write(::rtl::OUString::valueOf(value));
+}
+
+FastSerializerHelper* FastSerializerHelper::write(sal_Int64 value)
+{
+ return write(::rtl::OUString::valueOf(value));
+}
+
+FastSerializerHelper* FastSerializerHelper::write(float value)
+{
+ return write(::rtl::OUString::valueOf(value));
+}
+
+FastSerializerHelper* FastSerializerHelper::write(double value)
+{
+ return write(::rtl::OUString::valueOf(value));
+}
+
+FastSerializerHelper* FastSerializerHelper::writeEscaped(const char* value)
+{
+ return writeEscaped(::rtl::OUString::createFromAscii(value));
+}
+
+FastSerializerHelper* FastSerializerHelper::writeEscaped(const ::rtl::OUString& value)
+{
+ return write(FastSaxSerializer::escapeXml(value));
+}
+
+FastSerializerHelper* FastSerializerHelper::writeId(sal_Int32 tokenId)
+{
+ mpSerializer->writeId(tokenId);
+ return this;
+}
+
+::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > FastSerializerHelper::getOutputStream()
+{
+ return mpSerializer->getOutputStream();
+}
+
+void FastSerializerHelper::mark()
+{
+ mpSerializer->mark();
+}
+
+void FastSerializerHelper::mergeTopMarks( MergeMarksEnum eMergeType )
+{
+ mpSerializer->mergeTopMarks( eMergeType );
+}
+
+FastAttributeList * FastSerializerHelper::createAttrList()
+{
+ return new FastAttributeList( mxTokenHandler );
+}
+
+
+}
diff --git a/sax/source/tools/makefile.mk b/sax/source/tools/makefile.mk
new file mode 100644
index 000000000000..5923fc5a7785
--- /dev/null
+++ b/sax/source/tools/makefile.mk
@@ -0,0 +1,67 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=sax
+TARGET=sax
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES = \
+ $(SLO)$/converter.obj \
+ $(SLO)$/fastattribs.obj \
+ $(SLO)$/fastserializer.obj \
+ $(SLO)$/fshelper.obj
+
+SHL1TARGET= $(TARGET)$(DLLPOSTFIX)
+SHL1IMPLIB= i$(TARGET)
+
+SHL1STDLIBS= \
+ $(CPPULIB) \
+ $(CPPUHELPERLIB)\
+ $(COMPHELPERLIB)\
+ $(RTLLIB) \
+ $(SALLIB) \
+ $(ONELIB)
+
+SHL1DEPN=
+SHL1OBJS= $(SLOFILES)
+SHL1USE_EXPORTS=name
+SHL1DEF= $(MISC)$/$(SHL1TARGET).def
+DEF1NAME= $(SHL1TARGET)
+DEFLIB1NAME= $(TARGET)
+
+# --- Targets -------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/sax/test/makefile.mk b/sax/test/makefile.mk
new file mode 100644
index 000000000000..7fb7837a4ff3
--- /dev/null
+++ b/sax/test/makefile.mk
@@ -0,0 +1,62 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..
+
+PRJNAME=extensions
+TARGET=workben
+LIBTARGET=NO
+
+TARGETTYPE=CUI
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+# --- Files --------------------------------------------------------
+
+
+
+#
+# std testcomponent
+#
+APP1TARGET = testcomponent
+APP2TARGET = saxdemo
+
+APP1OBJS = $(OBJ)$/testcomponent.obj
+APP1STDLIBS = $(SALLIB) \
+ $(CPPULIB)\
+ $(CPPUHELPERLIB)
+
+APP2OBJS = $(OBJ)$/saxdemo.obj
+APP2STDLIBS = $(SALLIB) \
+ $(CPPULIB) \
+ $(CPPUHELPERLIB)
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/sax/test/sax/exports.dxp b/sax/test/sax/exports.dxp
new file mode 100644
index 000000000000..ce95ae0f8deb
--- /dev/null
+++ b/sax/test/sax/exports.dxp
@@ -0,0 +1,3 @@
+component_getImplementationEnvironment
+component_getFactory
+component_writeInfo \ No newline at end of file
diff --git a/sax/test/sax/factory.hxx b/sax/test/sax/factory.hxx
new file mode 100644
index 000000000000..4ab5553a8b78
--- /dev/null
+++ b/sax/test/sax/factory.hxx
@@ -0,0 +1,89 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include <rtl/strbuf.hxx>
+
+namespace sax_test {
+Reference< XInterface > SAL_CALL OSaxWriterTest_CreateInstance(
+ const Reference< XMultiServiceFactory > & rSMgr ) throw ( Exception );
+OUString OSaxWriterTest_getServiceName( ) throw();
+OUString OSaxWriterTest_getImplementationName( ) throw();
+Sequence<OUString> OSaxWriterTest_getSupportedServiceNames( ) throw();
+}
+#define BUILD_ERROR(expr, Message)\
+ {\
+ m_seqErrors.realloc( m_seqErrors.getLength() + 1 ); \
+ m_seqExceptions.realloc( m_seqExceptions.getLength() + 1 ); \
+ OStringBuffer str(128); \
+ str.append( __FILE__ );\
+ str.append( " " ); \
+ str.append( "(" ); \
+ str.append( OString::valueOf( (sal_Int32)__LINE__) );\
+ str.append(")\n" );\
+ str.append( "[ " ); \
+ str.append( #expr ); \
+ str.append( " ] : " ); \
+ str.append( Message ); \
+ m_seqErrors.getArray()[ m_seqErrors.getLength()-1] =\
+ OStringToOUString( str.makeStringAndClear() , RTL_TEXTENCODING_ASCII_US ); \
+ }\
+ ((void)0)
+
+
+#define WARNING_ASSERT(expr, Message) \
+ if( ! (expr) ) { \
+ m_seqWarnings.realloc( m_seqErrors.getLength() +1 ); \
+ OStringBuffer str(128);\
+ str.append( __FILE__);\
+ str.append( " "); \
+ str.append( "(" ); \
+ str.append(OString::valueOf( (sal_Int32)__LINE__)) ;\
+ str.append( ")\n");\
+ str.append( "[ " ); \
+ str.append( #expr ); \
+ str.append( " ] : ") ; \
+ str.append( Message); \
+ m_seqWarnings.getArray()[ m_seqWarnings.getLength()-1] =\
+ OStringToOUString( str.makeStringAndClear() , RTL_TEXTENCODING_ASCII_US ); \
+ return; \
+ }\
+ ((void)0)
+
+#define ERROR_ASSERT(expr, Message) \
+ if( ! (expr) ) { \
+ BUILD_ERROR(expr, Message );\
+ return; \
+ }\
+ ((void)0)
+
+#define ERROR_EXCEPTION_ASSERT(expr, Message, Exception) \
+ if( !(expr)) { \
+ BUILD_ERROR(expr,Message);\
+ m_seqExceptions.getArray()[ m_seqExceptions.getLength()-1] = Any( Exception );\
+ return; \
+ } \
+ ((void)0)
+
diff --git a/sax/test/sax/makefile.mk b/sax/test/sax/makefile.mk
new file mode 100644
index 000000000000..b283366ff8a3
--- /dev/null
+++ b/sax/test/sax/makefile.mk
@@ -0,0 +1,61 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+PRJ=..$/..
+
+PRJNAME=extensions
+TARGET=testsax
+USE_DEFFILE=TRUE
+ENABLE_EXCEPTIONS=TRUE
+# --- Settings -----------------------------------------------------
+.INCLUDE : settings.mk
+
+# --- Files --------------------------------------------------------
+
+
+SLOFILES = $(SLO)$/testsax.obj \
+ $(SLO)$/testwriter.obj
+
+SHL1TARGET= $(TARGET)
+SHL1IMPLIB= i$(TARGET)
+
+SHL1STDLIBS= \
+ $(SALLIB) \
+ $(CPPULIB) \
+ $(CPPUHELPERLIB)
+
+
+SHL1LIBS= $(SLB)$/$(TARGET).lib
+SHL1DEPN= makefile.mk $(SHL1LIBS)
+SHL1DEF= $(MISC)$/$(SHL1TARGET).def
+
+DEF1NAME= $(SHL1TARGET)
+DEF1EXPORTFILE= exports.dxp
+
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/sax/test/sax/testsax.cxx b/sax/test/sax/testsax.cxx
new file mode 100644
index 000000000000..b51f4cb59181
--- /dev/null
+++ b/sax/test/sax/testsax.cxx
@@ -0,0 +1,870 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include <osl/time.h>
+#include <osl/diagnose.h>
+
+
+#include <com/sun/star/test/XSimpleTest.hpp>
+
+#include <com/sun/star/io/XOutputStream.hpp>
+
+#include <com/sun/star/xml/sax/SAXParseException.hpp>
+#include <com/sun/star/xml/sax/XParser.hpp>
+#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
+
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <cppuhelper/implbase3.hxx>
+
+using namespace ::rtl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::test;
+using namespace ::com::sun::star::registry;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::xml::sax;
+
+#include "factory.hxx"
+
+/****
+* test szenarios :
+*
+*
+*
+****/
+
+namespace sax_test {
+
+class OSaxParserTest : public WeakImplHelper1< XSimpleTest >
+{
+public:
+ OSaxParserTest( const Reference < XMultiServiceFactory > & rFactory ) : m_rFactory( rFactory )
+ {
+ }
+public:
+ virtual void SAL_CALL testInvariant(
+ const OUString& TestName,
+ const Reference < XInterface >& TestObject)
+ throw ( IllegalArgumentException, RuntimeException);
+
+ virtual sal_Int32 SAL_CALL test(
+ const OUString& TestName,
+ const Reference < XInterface >& TestObject,
+ sal_Int32 hTestHandle)
+ throw ( IllegalArgumentException,RuntimeException);
+
+ virtual sal_Bool SAL_CALL testPassed(void) throw ( RuntimeException);
+ virtual Sequence< OUString > SAL_CALL getErrors(void) throw (RuntimeException);
+ virtual Sequence< Any > SAL_CALL getErrorExceptions(void) throw (RuntimeException);
+ virtual Sequence< OUString > SAL_CALL getWarnings(void) throw (RuntimeException);
+
+private:
+ void testSimple( const Reference < XParser > &r );
+ void testNamespaces( const Reference < XParser > &r );
+ void testFile( const Reference < XParser > &r );
+ void testEncoding( const Reference < XParser > &rParser );
+ void testPerformance( const Reference < XParser > &rParser );
+
+private:
+ Sequence<Any> m_seqExceptions;
+ Sequence<OUString> m_seqErrors;
+ Sequence<OUString> m_seqWarnings;
+ Reference < XMultiServiceFactory > m_rFactory;
+};
+
+
+
+/**
+* for external binding
+*
+*
+**/
+Reference < XInterface > SAL_CALL OSaxParserTest_CreateInstance( const Reference < XMultiServiceFactory > & rSMgr ) throw(Exception)
+{
+ OSaxParserTest *p = new OSaxParserTest( rSMgr );
+ return Reference < XInterface > ( SAL_STATIC_CAST( OWeakObject * , p ) );
+}
+
+
+OUString OSaxParserTest_getServiceName( ) throw ()
+{
+ return OUString( RTL_CONSTASCII_USTRINGPARAM("test.com.sun.star.xml.sax.Parser" ));
+}
+
+OUString OSaxParserTest_getImplementationName( ) throw ()
+{
+ return OUString( RTL_CONSTASCII_USTRINGPARAM("test.extensions.xml.sax.Parser"));
+}
+
+Sequence<OUString> OSaxParserTest_getSupportedServiceNames( ) throw ()
+{
+ Sequence<OUString> aRet(1);
+
+ aRet.getArray()[0] = OSaxParserTest_getImplementationName( );
+
+ return aRet;
+}
+
+
+
+
+void OSaxParserTest::testInvariant(
+ const OUString& TestName,
+ const Reference < XInterface >& TestObject )
+ throw ( IllegalArgumentException, RuntimeException)
+{
+ if( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Parser")) == TestName ) {
+ Reference < XParser > parser( TestObject , UNO_QUERY );
+
+ ERROR_ASSERT( parser.is() , "XDataInputStream cannot be queried" );
+ }
+}
+
+
+sal_Int32 OSaxParserTest::test(
+ const OUString& TestName,
+ const Reference < XInterface >& TestObject,
+ sal_Int32 hTestHandle)
+ throw ( IllegalArgumentException, RuntimeException)
+{
+ if( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Parser")) == TestName ) {
+ try
+ {
+ if( 0 == hTestHandle ) {
+ testInvariant( TestName , TestObject );
+ }
+ else {
+
+ Reference < XParser > parser( TestObject , UNO_QUERY );
+
+ if( 1 == hTestHandle ) {
+ testSimple( parser );
+ }
+ else if( 2 == hTestHandle ) {
+ testNamespaces( parser );
+ }
+ else if( 3 == hTestHandle ) {
+ testEncoding( parser );
+ }
+ else if( 4 == hTestHandle ) {
+ testFile( parser );
+ }
+ else if( 5 == hTestHandle ) {
+ testPerformance( parser );
+ }
+ }
+ }
+ catch( Exception & e )
+ {
+ OString o = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US);
+ BUILD_ERROR( 0 , o.getStr() );
+ }
+ catch( ... )
+ {
+ BUILD_ERROR( 0 , "unknown exception (Exception is not base class)" );
+ }
+
+ hTestHandle ++;
+
+ if( hTestHandle >= 6) {
+ // all tests finished.
+ hTestHandle = -1;
+ }
+ }
+ else {
+ BUILD_ERROR( 0 , "service not supported by test." );
+ }
+ return hTestHandle;
+}
+
+
+
+sal_Bool OSaxParserTest::testPassed(void) throw (RuntimeException)
+{
+ return m_seqErrors.getLength() == 0;
+}
+
+
+Sequence< OUString > OSaxParserTest::getErrors(void) throw (RuntimeException)
+{
+ return m_seqErrors;
+}
+
+
+Sequence< Any > OSaxParserTest::getErrorExceptions(void) throw (RuntimeException)
+{
+ return m_seqExceptions;
+}
+
+
+Sequence< OUString > OSaxParserTest::getWarnings(void) throw (RuntimeException)
+{
+ return m_seqWarnings;
+}
+
+Reference < XInputStream > createStreamFromSequence(
+ const Sequence<sal_Int8> seqBytes ,
+ const Reference < XMultiServiceFactory > &xSMgr )
+{
+ Reference < XInterface > xOutStreamService =
+ xSMgr->createInstance( OUString::createFromAscii("com.sun.star.io.Pipe") );
+ OSL_ASSERT( xOutStreamService.is() );
+ Reference< XOutputStream > rOutStream( xOutStreamService , UNO_QUERY );
+ OSL_ASSERT( rOutStream.is() );
+
+ Reference< XInputStream > rInStream( xOutStreamService , UNO_QUERY );
+ OSL_ASSERT( rInStream.is() );
+
+ rOutStream->writeBytes( seqBytes );
+ rOutStream->flush();
+ rOutStream->closeOutput();
+
+ return rInStream;
+}
+
+Reference< XInputStream > createStreamFromFile(
+ const char *pcFile ,
+ const Reference < XMultiServiceFactory > &xSMgr )
+{
+ FILE *f = fopen( pcFile , "rb" );
+ Reference< XInputStream > r;
+
+ if( f ) {
+ fseek( f , 0 , SEEK_END );
+ int nLength = ftell( f );
+ fseek( f , 0 , SEEK_SET );
+
+ Sequence<sal_Int8> seqIn(nLength);
+ fread( seqIn.getArray() , nLength , 1 , f );
+
+ r = createStreamFromSequence( seqIn , xSMgr );
+ fclose( f );
+ }
+ return r;
+}
+
+
+
+
+
+
+
+
+
+// #define PCHAR_TO_OUSTRING(x) OStringToOUString(x,CHARSET_PC_1252)
+// #define USTRING_TO_PCHAR(x) UStringToString(x,CHARSET_PC_437).GetStr()
+
+
+
+class TestDocumentHandler :
+ public WeakImplHelper3< XExtendedDocumentHandler , XEntityResolver , XErrorHandler >
+{
+public:
+ TestDocumentHandler( const Reference < XMultiServiceFactory > &r , sal_Bool bPrint )
+ {
+ m_xSMgr = r;
+ m_bPrint = bPrint;
+ }
+
+public: // Error handler
+ virtual void SAL_CALL error(const Any& aSAXParseException) throw (SAXException, RuntimeException)
+ {
+ printf( "Error !\n" );
+ throw SAXException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM("error from error handler")) ,
+ Reference < XInterface >() ,
+ aSAXParseException );
+ }
+ virtual void SAL_CALL fatalError(const Any& aSAXParseException) throw (SAXException, RuntimeException)
+ {
+ printf( "Fatal Error !\n" );
+ }
+ virtual void SAL_CALL warning(const Any& aSAXParseException) throw (SAXException, RuntimeException)
+ {
+ printf( "Warning !\n" );
+ }
+
+
+public: // ExtendedDocumentHandler
+
+ virtual void SAL_CALL startDocument(void) throw (SAXException, RuntimeException)
+ {
+ m_iLevel = 0;
+ m_iElementCount = 0;
+ m_iAttributeCount = 0;
+ m_iWhitespaceCount =0;
+ m_iCharCount=0;
+ if( m_bPrint ) {
+ printf( "document started\n" );
+ }
+ }
+ virtual void SAL_CALL endDocument(void) throw (SAXException, RuntimeException)
+ {
+ if( m_bPrint ) {
+ printf( "document finished\n" );
+ printf( "(ElementCount %d),(AttributeCount %d),(WhitespaceCount %d),(CharCount %d)\n",
+ m_iElementCount, m_iAttributeCount, m_iWhitespaceCount , m_iCharCount );
+ }
+ }
+ virtual void SAL_CALL startElement(const OUString& aName,
+ const Reference< XAttributeList > & xAttribs)
+ throw (SAXException,RuntimeException)
+ {
+
+ if( m_rLocator.is() ) {
+ if( m_bPrint )
+ {
+ OString o = OUStringToOString( m_rLocator->getSystemId() , RTL_TEXTENCODING_UTF8 );
+ printf( "%s(%d):" , o.getStr() , m_rLocator->getLineNumber() );
+ }
+ }
+ if( m_bPrint ) {
+ int i;
+ for( i = 0; i < m_iLevel ; i ++ ) {
+ printf( " " );
+ }
+ OString o = OUStringToOString(aName , RTL_TEXTENCODING_UTF8 );
+ printf( "<%s> " , aName.getStr() );
+
+ for( i = 0 ; i < xAttribs->getLength() ; i ++ )
+ {
+ OString o1 = OUStringToOString(xAttribs->getNameByIndex( i ), RTL_TEXTENCODING_UTF8 );
+ OString o2 = OUStringToOString(xAttribs->getTypeByIndex( i ), RTL_TEXTENCODING_UTF8 );
+ OString o3 = OUStringToOString(xAttribs->getValueByIndex( i ) , RTL_TEXTENCODING_UTF8 );
+ printf( "(%s,%s,'%s')" , o1.getStr(), o2.getStr(), o3.getStr() );
+ }
+ printf( "\n" );
+ }
+ m_iLevel ++;
+ m_iElementCount ++;
+ m_iAttributeCount += xAttribs->getLength();
+ }
+
+ virtual void SAL_CALL endElement(const OUString& aName) throw (SAXException,RuntimeException)
+ {
+ OSL_ASSERT( m_iLevel );
+ m_iLevel --;
+ if( m_bPrint ) {
+ int i;
+ for( i = 0; i < m_iLevel ; i ++ ) {
+ printf( " " );
+ }
+ OString o = OUStringToOString(aName , RTL_TEXTENCODING_UTF8 );
+ printf( "</%s>\n" , o.getStr() );
+ }
+ }
+
+ virtual void SAL_CALL characters(const OUString& aChars) throw (SAXException,RuntimeException)
+ {
+ if( m_bPrint ) {
+ int i;
+ for( i = 0; i < m_iLevel ; i ++ ) {
+ printf( " " );
+ }
+ OString o = OUStringToOString(aChars , RTL_TEXTENCODING_UTF8 );
+ printf( "%s\n" , o.getStr() );
+ }
+ m_iCharCount += aChars.getLength();
+ }
+ virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces) throw (SAXException,RuntimeException)
+ {
+ m_iWhitespaceCount += aWhitespaces.getLength();
+ }
+
+ virtual void SAL_CALL processingInstruction(const OUString& aTarget, const OUString& aData) throw (SAXException,RuntimeException)
+ {
+ if( m_bPrint )
+ {
+ OString o1 = OUStringToOString(aTarget, RTL_TEXTENCODING_UTF8 );
+ OString o2 = OUStringToOString(aData, RTL_TEXTENCODING_UTF8 );
+ printf( "PI : %s,%s\n" , o1.getStr() , o2.getStr() );
+ }
+ }
+
+ virtual void SAL_CALL setDocumentLocator(const Reference< XLocator> & xLocator)
+ throw (SAXException,RuntimeException)
+ {
+ m_rLocator = xLocator;
+ }
+
+ virtual InputSource SAL_CALL resolveEntity(
+ const OUString& sPublicId,
+ const OUString& sSystemId)
+ throw (SAXException,RuntimeException)
+ {
+ InputSource source;
+ source.sSystemId = sSystemId;
+ source.sPublicId = sPublicId;
+
+ source.aInputStream = createStreamFromFile(
+ OUStringToOString( sSystemId , RTL_TEXTENCODING_ASCII_US) , m_xSMgr );
+
+ return source;
+ }
+
+ virtual void SAL_CALL startCDATA(void) throw (SAXException,RuntimeException)
+ {
+ if( m_bPrint ) {
+ printf( "CDataStart :\n" );
+ }
+ }
+ virtual void SAL_CALL endCDATA(void) throw (SAXException,RuntimeException)
+ {
+ if( m_bPrint ) {
+ printf( "CEndStart :\n" );
+ }
+ }
+ virtual void SAL_CALL comment(const OUString& sComment) throw (SAXException,RuntimeException)
+ {
+ if( m_bPrint ) {
+ OString o1 = OUStringToOString(sComment, RTL_TEXTENCODING_UTF8 );
+ printf( "<!--%s-->\n" , o1.getStr() );
+ }
+ }
+ virtual void SAL_CALL unknown(const OUString& sString) throw (SAXException,RuntimeException)
+ {
+ if( m_bPrint )
+ {
+ OString o1 = OUStringToOString(sString, RTL_TEXTENCODING_UTF8 );
+ printf( "UNKNOWN : {%s}\n" , o1.getStr() );
+ }
+ }
+
+ virtual void SAL_CALL allowLineBreak( void) throw (SAXException, RuntimeException )
+ {
+
+ }
+
+
+public:
+ int m_iLevel;
+ int m_iElementCount;
+ int m_iAttributeCount;
+ int m_iWhitespaceCount;
+ int m_iCharCount;
+ sal_Bool m_bPrint;
+
+ Reference < XMultiServiceFactory > m_xSMgr;
+ Reference < XLocator > m_rLocator;
+};
+
+
+void OSaxParserTest::testSimple( const Reference < XParser > &rParser )
+{
+
+ char TestString[] = "<!DOCTYPE personnel [\n"
+ "<!ENTITY testInternal \"internal Test!\">\n"
+ "<!ENTITY test SYSTEM \"external_entity.xml\">\n"
+ "]>\n"
+ "<personnel>\n"
+ "<person> fjklsfdklsdfkl\n"
+ "fjklsfdklsdfkl\n"
+ "<?testpi pidata?>\n"
+ "&testInternal;\n"
+ "<HUHU x='5' y='kjfd'> blahuhu\n"
+ "<HI> blahi\n"
+ " <![CDATA[<greeting>Hello, '+1+12world!</greeting>]]>\n"
+ " <!-- huhu <jdk> -->\n"
+ "<?testpi pidata?>\n"
+ "</HI>\n"
+ "aus XMLTest\n"
+ "</HUHU>\n"
+ "</person>\n"
+ "</personnel>\n\n\n";
+
+ Sequence< sal_Int8> seqBytes( strlen( TestString ) );
+ memcpy( seqBytes.getArray() , TestString , strlen( TestString ) );
+
+
+ Reference< XInputStream > rInStream;
+ OUString sInput;
+ rInStream = createStreamFromSequence( seqBytes , m_rFactory );
+ sInput = OUString( OUString( RTL_CONSTASCII_USTRINGPARAM("internal")) );
+
+ if( rParser.is() ) {
+ InputSource source;
+
+ source.aInputStream = rInStream;
+ source.sSystemId = sInput;
+
+ TestDocumentHandler *pDocHandler = new TestDocumentHandler( m_rFactory , sal_False );
+ Reference < XDocumentHandler > rDocHandler( (XDocumentHandler *) pDocHandler , UNO_QUERY );
+ Reference< XEntityResolver >
+ rEntityResolver( (XEntityResolver *) pDocHandler , UNO_QUERY );
+
+ rParser->setDocumentHandler( rDocHandler );
+ rParser->setEntityResolver( rEntityResolver );
+
+ try
+ {
+ rParser->parseStream( source );
+ ERROR_ASSERT( pDocHandler->m_iElementCount == 4 , "wrong element count" );
+ ERROR_ASSERT( pDocHandler->m_iAttributeCount == 2 , "wrong attribut count" );
+ ERROR_ASSERT( pDocHandler->m_iCharCount == 130 , "wrong char count" );
+ ERROR_ASSERT( pDocHandler->m_iWhitespaceCount == 0, "wrong whitespace count" );
+ }
+ catch( SAXParseException & e )
+ {
+ OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 );
+ BUILD_ERROR( 1 , o1.getStr() );
+ }
+ catch( SAXException & e )
+ {
+ OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 );
+ BUILD_ERROR( 1 , o1.getStr() );
+ }
+ catch( Exception & e )
+ {
+ OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 );
+ BUILD_ERROR( 1 , o1.getStr() );
+ }
+ catch( ... )
+ {
+ BUILD_ERROR( 1 , "unknown exception" );
+ }
+ }
+}
+
+void OSaxParserTest::testNamespaces( const Reference < XParser > &rParser )
+{
+
+ char TestString[] =
+ "<?xml version='1.0'?>\n"
+ "<!-- all elements here are explicitly in the HTML namespace -->\n"
+ "<html:html xmlns:html='http://www.w3.org/TR/REC-html40'>\n"
+ "<html:head><html:title>Frobnostication</html:title></html:head>\n"
+ "<html:body><html:p>Moved to \n"
+ "<html:a href='http://frob.com'>here.</html:a></html:p></html:body>\n"
+ "</html:html>\n";
+
+ Sequence<sal_Int8> seqBytes( strlen( TestString ) );
+ memcpy( seqBytes.getArray() , TestString , strlen( TestString ) );
+
+
+ Reference< XInputStream > rInStream;
+ OUString sInput;
+
+ rInStream = createStreamFromSequence( seqBytes , m_rFactory );
+ sInput = OUString( RTL_CONSTASCII_USTRINGPARAM( "internal" ));
+
+ if( rParser.is() ) {
+ InputSource source;
+
+ source.aInputStream = rInStream;
+ source.sSystemId = sInput;
+
+ TestDocumentHandler *pDocHandler = new TestDocumentHandler( m_rFactory , sal_False );
+ Reference < XDocumentHandler > rDocHandler( (XDocumentHandler *) pDocHandler , UNO_QUERY );
+ Reference< XEntityResolver > rEntityResolver(
+ (XEntityResolver *) pDocHandler , UNO_QUERY );
+
+ rParser->setDocumentHandler( rDocHandler );
+ rParser->setEntityResolver( rEntityResolver );
+
+ try
+ {
+ rParser->parseStream( source );
+ ERROR_ASSERT( pDocHandler->m_iElementCount == 6 , "wrong element count" );
+ ERROR_ASSERT( pDocHandler->m_iAttributeCount == 2 , "wrong attribut count" );
+ ERROR_ASSERT( pDocHandler->m_iCharCount == 33, "wrong char count" );
+ ERROR_ASSERT( pDocHandler->m_iWhitespaceCount == 0 , "wrong whitespace count" );
+ }
+ catch( Exception & e ) {
+ OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 );
+ BUILD_ERROR( 1 , o1.getStr() );
+ }
+ catch( ... )
+ {
+ BUILD_ERROR( 1 , "unknown exception" );
+ }
+ }
+}
+
+void OSaxParserTest::testEncoding( const Reference < XParser > &rParser )
+{
+ char TestString[] =
+ "<?xml version='1.0' encoding=\"iso-8859-1\"?>\n"
+ "<!-- all elements here are explicitly in the HTML namespace -->\n"
+ "<html:html xmlns:html='http://www.w3.org/TR/REC-html40'>\n"
+ "<html:head><html:title>Frobnostication</html:title></html:head>\n"
+ "<html:body><html:p>Moved to ß\n"
+ "<html:a href='http://frob.com'>here.</html:a></html:p></html:body>\n"
+ "</html:html>\n";
+
+ Sequence<sal_Int8> seqBytes( strlen( TestString ) );
+ memcpy( seqBytes.getArray() , TestString , strlen( TestString ) );
+
+
+ Reference< XInputStream > rInStream;
+ OUString sInput;
+
+ rInStream = createStreamFromSequence( seqBytes , m_rFactory );
+ sInput = OUString( RTL_CONSTASCII_USTRINGPARAM("internal") );
+
+ if( rParser.is() ) {
+ InputSource source;
+
+ source.aInputStream = rInStream;
+ source.sSystemId = sInput;
+
+ TestDocumentHandler *pDocHandler = new TestDocumentHandler( m_rFactory , sal_False );
+ Reference < XDocumentHandler > rDocHandler( (XDocumentHandler *) pDocHandler , UNO_QUERY );
+ Reference< XEntityResolver > rEntityResolver( (XEntityResolver *) pDocHandler , UNO_QUERY );
+
+ rParser->setDocumentHandler( rDocHandler );
+ rParser->setEntityResolver( rEntityResolver );
+ try
+ {
+ rParser->parseStream( source );
+ }
+ catch( Exception & e )
+ {
+ OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 );
+ BUILD_ERROR( 1 , o1.getStr() );
+ }
+ catch ( ... )
+ {
+ BUILD_ERROR( 1 , "unknown exception" );
+ }
+ }
+}
+
+void OSaxParserTest::testFile( const Reference < XParser > & rParser )
+{
+
+ Reference< XInputStream > rInStream = createStreamFromFile( "testsax.xml" , m_rFactory );
+ OUString sInput = OUString( RTL_CONSTASCII_USTRINGPARAM( "testsax.xml" ) );
+
+
+ if( rParser.is() && rInStream.is() ) {
+ InputSource source;
+
+ source.aInputStream = rInStream;
+ source.sSystemId = sInput;
+
+ TestDocumentHandler *pDocHandler = new TestDocumentHandler( m_rFactory , sal_True );
+ Reference < XDocumentHandler > rDocHandler( (XDocumentHandler *) pDocHandler , UNO_QUERY );
+ Reference < XEntityResolver > rEntityResolver( (XEntityResolver *) pDocHandler , UNO_QUERY );
+ Reference < XErrorHandler > rErrorHandler( ( XErrorHandler * )pDocHandler , UNO_QUERY );
+
+ rParser->setDocumentHandler( rDocHandler );
+ rParser->setEntityResolver( rEntityResolver );
+ rParser->setErrorHandler( rErrorHandler );
+
+ try
+ {
+ rParser->parseStream( source );
+ }
+ catch( SAXParseException & e ) {
+ Any any;
+ any <<= e;
+
+ while(sal_True) {
+ SAXParseException *pEx;
+ if( any.getValueType() == getCppuType( &e ) ) {
+ pEx = ( SAXParseException * ) any.getValue();
+ OString o1 = OUStringToOString(pEx->Message, RTL_TEXTENCODING_UTF8 );
+ printf( "%s\n" , o1.getStr() );
+ any = pEx->WrappedException;
+ }
+ else {
+ break;
+ }
+ }
+ }
+ catch( SAXException & e )
+ {
+ OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 );
+ BUILD_ERROR( 1 , o1.getStr() );
+
+ }
+ catch( Exception & e ) {
+ printf( "normal exception ! %s\n", e.Message );
+ }
+ catch ( ... )
+ {
+ printf( "any exception !!!!\n" );
+ }
+ }
+}
+
+void OSaxParserTest::testPerformance( const Reference < XParser > & rParser )
+{
+
+ Reference < XInputStream > rInStream =
+ createStreamFromFile( "testPerformance.xml" , m_rFactory );
+ OUString sInput = OUString( RTL_CONSTASCII_USTRINGPARAM( "testperformance.xml") );
+
+ if( rParser.is() && rInStream.is() ) {
+ InputSource source;
+
+ source.aInputStream = rInStream;
+ source.sSystemId = sInput;
+
+ TestDocumentHandler *pDocHandler = new TestDocumentHandler( m_rFactory , sal_False );
+ Reference < XDocumentHandler > rDocHandler( (XDocumentHandler *) pDocHandler , UNO_QUERY );
+ Reference < XEntityResolver > rEntityResolver( (XEntityResolver *) pDocHandler , UNO_QUERY );
+ Reference < XErrorHandler > rErrorHandler( ( XErrorHandler * )pDocHandler , UNO_QUERY );
+
+ rParser->setDocumentHandler( rDocHandler );
+ rParser->setEntityResolver( rEntityResolver );
+ rParser->setErrorHandler( rErrorHandler );
+
+ try
+ {
+ TimeValue aStartTime, aEndTime;
+ osl_getSystemTime( &aStartTime );
+ rParser->parseStream( source );
+ osl_getSystemTime( &aEndTime );
+
+ double fStart = (double)aStartTime.Seconds + ((double)aStartTime.Nanosec / 1000000000.0);
+ double fEnd = (double)aEndTime.Seconds + ((double)aEndTime.Nanosec / 1000000000.0);
+
+ printf( "Performance reading : %g s\n" , fEnd - fStart );
+
+ }
+ catch( SAXParseException &e ) {
+ Any any;
+ any <<= e;
+ while(sal_True) {
+ if( any.getValueType() == getCppuType( &e ) ) {
+ SAXParseException ex;
+ any >>= ex;
+ OString o = OUStringToOString( ex.Message , RTL_TEXTENCODING_ASCII_US );
+ printf( "%s\n" , o.getStr() );
+ any <<= ex.WrappedException;
+ }
+ else {
+ break;
+ }
+ }
+ }
+ catch( SAXException &e ) {
+ OString o = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US );
+ printf( "%s\n" , o.getStr() );
+
+ }
+ catch( ... )
+ {
+ printf( "any exception !!!!\n" );
+ }
+ }
+}
+}
+using namespace sax_test;
+
+extern "C"
+{
+
+
+void SAL_CALL component_getImplementationEnvironment(
+ const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv )
+{
+ *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
+}
+
+
+sal_Bool SAL_CALL component_writeInfo(
+ void * pServiceManager, void * pRegistryKey )
+{
+ if (pRegistryKey)
+ {
+ try
+ {
+ Reference< XRegistryKey > xKey(
+ reinterpret_cast< XRegistryKey * >( pRegistryKey ) );
+
+ OUString str =
+ OUString( RTL_CONSTASCII_USTRINGPARAM("/") ) +
+ OSaxParserTest_getImplementationName() +
+ OUString( RTL_CONSTASCII_USTRINGPARAM("/UNO/SERVICES") );
+ Reference< XRegistryKey > xNewKey = xKey->createKey( str );
+ xNewKey->createKey( OSaxParserTest_getServiceName() );
+
+ str =
+ OUString( RTL_CONSTASCII_USTRINGPARAM("/") ) +
+ OSaxWriterTest_getImplementationName() +
+ OUString( RTL_CONSTASCII_USTRINGPARAM("/UNO/SERVICES") );
+
+ xNewKey = xKey->createKey( str );
+ xNewKey->createKey( OSaxWriterTest_getServiceName() );
+
+ return sal_True;
+ }
+ catch (InvalidRegistryException &)
+ {
+ OSL_ENSURE( sal_False, "### InvalidRegistryException!" );
+ }
+ }
+
+ return sal_False;
+}
+
+void * SAL_CALL component_getFactory(
+ const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
+{
+ void * pRet = 0;
+
+ if (pServiceManager )
+ {
+ Reference< XSingleServiceFactory > xRet;
+ Reference< XMultiServiceFactory > xSMgr =
+ reinterpret_cast< XMultiServiceFactory * > ( pServiceManager );
+
+ OUString aImplementationName = OUString::createFromAscii( pImplName );
+
+
+ if (aImplementationName == OSaxWriterTest_getImplementationName() )
+ {
+ xRet = createSingleFactory( xSMgr, aImplementationName,
+ OSaxWriterTest_CreateInstance,
+ OSaxWriterTest_getSupportedServiceNames() );
+ }
+ else if (aImplementationName == OSaxParserTest_getImplementationName() )
+ {
+ xRet = createSingleFactory( xSMgr, aImplementationName,
+ OSaxParserTest_CreateInstance,
+ OSaxParserTest_getSupportedServiceNames() );
+ }
+ if (xRet.is())
+ {
+ xRet->acquire();
+ pRet = xRet.get();
+ }
+ }
+
+ return pRet;
+}
+
+}
+
+
diff --git a/sax/test/sax/testwriter.cxx b/sax/test/sax/testwriter.cxx
new file mode 100644
index 000000000000..27c8559d51d4
--- /dev/null
+++ b/sax/test/sax/testwriter.cxx
@@ -0,0 +1,698 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include <vector>
+#include <stdio.h>
+
+#include <com/sun/star/test/XSimpleTest.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp> // for the multiservice-factories
+
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/xml/sax/SAXParseException.hpp>
+#include <com/sun/star/xml/sax/XParser.hpp>
+#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
+
+#include <osl/time.h>
+
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <cppuhelper/implbase3.hxx>
+
+
+using namespace ::std;
+using namespace ::rtl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::test;
+using namespace ::com::sun::star::registry;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::xml::sax;
+
+#include "factory.hxx"
+
+namespace sax_test {
+
+class OFileWriter :
+ public WeakImplHelper1< XOutputStream >
+{
+public:
+ OFileWriter( char *pcFile ) { strncpy( m_pcFile, pcFile, 256 - 1 ); m_f = 0; }
+
+
+public:
+ virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData)
+ throw (NotConnectedException, BufferSizeExceededException, RuntimeException);
+ virtual void SAL_CALL flush(void)
+ throw (NotConnectedException, BufferSizeExceededException, RuntimeException);
+ virtual void SAL_CALL closeOutput(void)
+ throw (NotConnectedException, BufferSizeExceededException, RuntimeException);
+private:
+ char m_pcFile[256];
+ FILE *m_f;
+};
+
+
+void OFileWriter::writeBytes(const Sequence< sal_Int8 >& aData)
+ throw (NotConnectedException, BufferSizeExceededException, RuntimeException)
+{
+ if( ! m_f ) {
+ m_f = fopen( m_pcFile , "w" );
+ }
+
+ fwrite( aData.getConstArray() , 1 , aData.getLength() , m_f );
+}
+
+
+void OFileWriter::flush(void)
+ throw (NotConnectedException, BufferSizeExceededException, RuntimeException)
+{
+ fflush( m_f );
+}
+
+void OFileWriter::closeOutput(void)
+ throw (NotConnectedException, BufferSizeExceededException, RuntimeException)
+{
+ fclose( m_f );
+ m_f = 0;
+}
+
+
+class OSaxWriterTest :
+ public WeakImplHelper1< XSimpleTest >
+{
+public:
+ OSaxWriterTest( const Reference < XMultiServiceFactory > & rFactory ) : m_rFactory( rFactory )
+ {
+
+ }
+ ~OSaxWriterTest() {}
+
+
+public:
+ virtual void SAL_CALL testInvariant(
+ const OUString& TestName,
+ const Reference < XInterface >& TestObject)
+ throw ( IllegalArgumentException,
+ RuntimeException);
+
+ virtual sal_Int32 SAL_CALL test(
+ const OUString& TestName,
+ const Reference < XInterface >& TestObject,
+ sal_Int32 hTestHandle)
+ throw ( IllegalArgumentException,RuntimeException);
+
+ virtual sal_Bool SAL_CALL testPassed(void)
+ throw ( RuntimeException);
+ virtual Sequence< OUString > SAL_CALL getErrors(void) throw (RuntimeException);
+ virtual Sequence< Any > SAL_CALL getErrorExceptions(void) throw (RuntimeException);
+ virtual Sequence< OUString > SAL_CALL getWarnings(void) throw (RuntimeException);
+
+private:
+ void testSimple( const Reference< XExtendedDocumentHandler > &r );
+ void testExceptions( const Reference< XExtendedDocumentHandler > &r );
+ void testDTD( const Reference< XExtendedDocumentHandler > &r );
+ void testPerformance( const Reference< XExtendedDocumentHandler > &r );
+ void writeParagraph( const Reference< XExtendedDocumentHandler > &r , const OUString & s);
+
+private:
+ Sequence<Any> m_seqExceptions;
+ Sequence<OUString> m_seqErrors;
+ Sequence<OUString> m_seqWarnings;
+ Reference < XMultiServiceFactory > m_rFactory;
+
+};
+
+
+
+/*----------------------------------------
+*
+* Attributlist implementation
+*
+*----------------------------------------*/
+struct AttributeListImpl_impl;
+class AttributeListImpl : public WeakImplHelper1< XAttributeList >
+{
+public:
+ AttributeListImpl();
+ AttributeListImpl( const AttributeListImpl & );
+ ~AttributeListImpl();
+
+public:
+ virtual sal_Int16 SAL_CALL getLength(void) throw (RuntimeException);
+ virtual OUString SAL_CALL getNameByIndex(sal_Int16 i) throw (RuntimeException);
+ virtual OUString SAL_CALL getTypeByIndex(sal_Int16 i) throw (RuntimeException);
+ virtual OUString SAL_CALL getTypeByName(const OUString& aName) throw (RuntimeException);
+ virtual OUString SAL_CALL getValueByIndex(sal_Int16 i) throw (RuntimeException);
+ virtual OUString SAL_CALL getValueByName(const OUString& aName) throw (RuntimeException);
+
+public:
+ void addAttribute( const OUString &sName ,
+ const OUString &sType ,
+ const OUString &sValue );
+ void clear();
+
+private:
+ struct AttributeListImpl_impl *m_pImpl;
+};
+
+
+struct TagAttribute
+{
+ TagAttribute(){}
+ TagAttribute( const OUString &sName,
+ const OUString &sType ,
+ const OUString &sValue )
+ {
+ this->sName = sName;
+ this->sType = sType;
+ this->sValue = sValue;
+ }
+
+ OUString sName;
+ OUString sType;
+ OUString sValue;
+};
+
+struct AttributeListImpl_impl
+{
+ AttributeListImpl_impl()
+ {
+ // performance improvement during adding
+ vecAttribute.reserve(20);
+ }
+ vector<struct TagAttribute> vecAttribute;
+};
+
+
+
+sal_Int16 AttributeListImpl::getLength(void) throw (RuntimeException)
+{
+ return m_pImpl->vecAttribute.size();
+}
+
+
+AttributeListImpl::AttributeListImpl( const AttributeListImpl &r )
+{
+ m_pImpl = new AttributeListImpl_impl;
+ *m_pImpl = *(r.m_pImpl);
+}
+
+OUString AttributeListImpl::getNameByIndex(sal_Int16 i) throw (RuntimeException)
+{
+ if( i < m_pImpl->vecAttribute.size() ) {
+ return m_pImpl->vecAttribute[i].sName;
+ }
+ return OUString();
+}
+
+
+OUString AttributeListImpl::getTypeByIndex(sal_Int16 i) throw (RuntimeException)
+{
+ if( i < m_pImpl->vecAttribute.size() ) {
+ return m_pImpl->vecAttribute[i].sType;
+ }
+ return OUString();
+}
+
+OUString AttributeListImpl::getValueByIndex(sal_Int16 i) throw (RuntimeException)
+{
+ if( i < m_pImpl->vecAttribute.size() ) {
+ return m_pImpl->vecAttribute[i].sValue;
+ }
+ return OUString();
+
+}
+
+OUString AttributeListImpl::getTypeByName( const OUString& sName ) throw (RuntimeException)
+{
+ vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin();
+
+ for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
+ if( (*ii).sName == sName ) {
+ return (*ii).sType;
+ }
+ }
+ return OUString();
+}
+
+OUString AttributeListImpl::getValueByName(const OUString& sName) throw (RuntimeException)
+{
+ vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin();
+
+ for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
+ if( (*ii).sName == sName ) {
+ return (*ii).sValue;
+ }
+ }
+ return OUString();
+}
+
+
+
+AttributeListImpl::AttributeListImpl()
+{
+ m_pImpl = new AttributeListImpl_impl;
+}
+
+
+
+AttributeListImpl::~AttributeListImpl()
+{
+ delete m_pImpl;
+}
+
+
+void AttributeListImpl::addAttribute( const OUString &sName ,
+ const OUString &sType ,
+ const OUString &sValue )
+{
+ m_pImpl->vecAttribute.push_back( TagAttribute( sName , sType , sValue ) );
+}
+
+void AttributeListImpl::clear()
+{
+ m_pImpl->vecAttribute.clear();
+
+}
+
+
+
+
+
+
+
+
+
+
+
+/**
+* for external binding
+*
+*
+**/
+Reference < XInterface > SAL_CALL OSaxWriterTest_CreateInstance( const Reference < XMultiServiceFactory > & rSMgr ) throw (Exception)
+{
+ OSaxWriterTest *p = new OSaxWriterTest( rSMgr );
+ Reference < XInterface > xService = *p;
+ return xService;
+}
+
+OUString OSaxWriterTest_getServiceName( ) throw ()
+{
+ return OUString( RTL_CONSTASCII_USTRINGPARAM("test.com.sun.star.xml.sax.Writer"));
+}
+
+OUString OSaxWriterTest_getImplementationName( ) throw ()
+{
+ return OUString( RTL_CONSTASCII_USTRINGPARAM("test.extensions.xml.sax.Writer"));
+}
+
+Sequence<OUString> OSaxWriterTest_getSupportedServiceNames( ) throw ()
+{
+ Sequence<OUString> aRet(1);
+
+ aRet.getArray()[0] = OSaxWriterTest_getImplementationName( );
+
+ return aRet;
+}
+
+
+
+void OSaxWriterTest::testInvariant( const OUString& TestName,
+ const Reference < XInterface >& TestObject )
+ throw ( IllegalArgumentException, RuntimeException)
+{
+ if( OUString::createFromAscii("com.sun.star.xml.sax.Writer") == TestName ) {
+ Reference< XDocumentHandler > doc( TestObject , UNO_QUERY );
+ Reference< XExtendedDocumentHandler > ext( TestObject , UNO_QUERY );
+ Reference< XActiveDataSource > source( TestObject , UNO_QUERY );
+
+ ERROR_ASSERT( doc.is() , "XDocumentHandler cannot be queried" );
+ ERROR_ASSERT( ext.is() , "XExtendedDocumentHandler cannot be queried" );
+ ERROR_ASSERT( source.is() , "XActiveDataSource cannot be queried" );
+ }
+ else {
+ BUILD_ERROR( 0 , "wrong test" );
+ }
+}
+
+
+sal_Int32 OSaxWriterTest::test(
+ const OUString& TestName,
+ const Reference < XInterface >& TestObject,
+ sal_Int32 hTestHandle)
+ throw ( IllegalArgumentException,RuntimeException)
+{
+ if( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Writer")) == TestName )
+ {
+ try
+ {
+ if( 0 == hTestHandle )
+ {
+ testInvariant( TestName , TestObject );
+ }
+ else
+ {
+ Reference< XExtendedDocumentHandler > writer( TestObject , UNO_QUERY );
+
+ if( 1 == hTestHandle ) {
+ testSimple( writer );
+ }
+ else if( 2 == hTestHandle ) {
+ testExceptions( writer );
+ }
+ else if( 3 == hTestHandle ) {
+ testDTD( writer );
+ }
+ else if( 4 == hTestHandle ) {
+ testPerformance( writer );
+ }
+ }
+ }
+ catch( Exception & e ) {
+ OString o = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US );
+ BUILD_ERROR( 0 , o.getStr() );
+ }
+ catch( ... )
+ {
+ BUILD_ERROR( 0 , "unknown exception (Exception is not base class)" );
+ }
+
+ hTestHandle ++;
+
+ if( hTestHandle >= 5) {
+ // all tests finished.
+ hTestHandle = -1;
+ }
+ }
+ else {
+ BUILD_ERROR( 0 , "service not supported by test." );
+ }
+ return hTestHandle;
+}
+
+
+
+sal_Bool OSaxWriterTest::testPassed(void) throw (RuntimeException)
+{
+ return m_seqErrors.getLength() == 0;
+}
+
+
+Sequence< OUString > OSaxWriterTest::getErrors(void) throw (RuntimeException)
+{
+ return m_seqErrors;
+}
+
+
+Sequence< Any > OSaxWriterTest::getErrorExceptions(void) throw (RuntimeException)
+{
+ return m_seqExceptions;
+}
+
+
+Sequence< OUString > OSaxWriterTest::getWarnings(void) throw (RuntimeException)
+{
+ return m_seqWarnings;
+}
+
+void OSaxWriterTest::writeParagraph(
+ const Reference< XExtendedDocumentHandler > &r ,
+ const OUString & s)
+{
+ int nMax = s.getLength();
+ int nStart = 0;
+
+ Sequence<sal_uInt16> seq( s.getLength() );
+ memcpy( seq.getArray() , s.getStr() , s.getLength() * sizeof( sal_uInt16 ) );
+
+ for( int n = 1 ; n < nMax ; n++ ){
+ if( 32 == seq.getArray()[n] ) {
+ r->allowLineBreak();
+ r->characters( s.copy( nStart , n - nStart ) );
+ nStart = n;
+ }
+ }
+ r->allowLineBreak();
+ r->characters( s.copy( nStart , n - nStart ) );
+}
+
+
+
+void OSaxWriterTest::testSimple( const Reference< XExtendedDocumentHandler > &r )
+{
+ OUString testParagraph = OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Dies ist ein bloeder Test um zu uberpruefen, ob der SAXWriter "
+ "wohl Zeilenumbrueche halbwegs richtig macht oder ob er die Zeile "
+ "bis zum bitteren Ende schreibt." ));
+
+ OFileWriter *pw = new OFileWriter("output.xml");
+ AttributeListImpl *pList = new AttributeListImpl;
+
+ Reference< XAttributeList > rList( (XAttributeList *) pList , UNO_QUERY );
+ Reference< XOutputStream > ref( ( XOutputStream * ) pw , UNO_QUERY );
+
+ Reference< XActiveDataSource > source( r , UNO_QUERY );
+
+ ERROR_ASSERT( ref.is() , "no output stream" );
+ ERROR_ASSERT( source.is() , "no active data source" );
+
+ source->setOutputStream( ref );
+
+ r->startDocument();
+
+ pList->addAttribute( OUString( RTL_CONSTASCII_USTRINGPARAM("Arg1" )),
+ OUString( RTL_CONSTASCII_USTRINGPARAM("CDATA")) ,
+ OUString( RTL_CONSTASCII_USTRINGPARAM("bla\n u")) );
+ pList->addAttribute( OUString( RTL_CONSTASCII_USTRINGPARAM("Arg2")) ,
+ OUString( RTL_CONSTASCII_USTRINGPARAM("CDATA")) ,
+ OUString( RTL_CONSTASCII_USTRINGPARAM("blub")) );
+
+ r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("tag1")) , rList );
+ r->ignorableWhitespace( OUString() );
+
+ r->characters( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) );
+ r->ignorableWhitespace( OUString() );
+
+ r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("hi")) , rList );
+ r->ignorableWhitespace( OUString() );
+
+ // the enpassant must be converted & -> &amp;
+ r->characters( OUString( RTL_CONSTASCII_USTRINGPARAM("&#252;")) );
+
+ // Test added for mib. Tests if errors during conversions occurs
+ r->ignorableWhitespace( OUString() );
+ sal_Char array[256];
+ for( sal_Int32 n = 32 ; n < 254 ; n ++ ) {
+ array[n-32] = n;
+ }
+ array[254-32] = 0;
+ r->characters(
+ OStringToOUString( array , RTL_TEXTENCODING_SYMBOL )
+ );
+ r->ignorableWhitespace( OUString() );
+
+ // '>' must not be converted
+ r->startCDATA();
+ r->characters( OUString( RTL_CONSTASCII_USTRINGPARAM(">fsfsdf<")) );
+ r->endCDATA();
+ r->ignorableWhitespace( OUString() );
+
+ writeParagraph( r , testParagraph );
+
+
+ r->ignorableWhitespace( OUString() );
+ r->comment( OUString( RTL_CONSTASCII_USTRINGPARAM("Dies ist ein Kommentar !")) );
+ r->ignorableWhitespace( OUString() );
+
+ r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("emptytagtest")) , rList );
+ r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("emptytagtest")) );
+
+ r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("hi")) );
+ r->ignorableWhitespace( OUString() );
+
+ r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("tag1")) );
+ r->endDocument();
+
+}
+
+void OSaxWriterTest::testExceptions( const Reference< XExtendedDocumentHandler > & r )
+{
+
+ OFileWriter *pw = new OFileWriter("output2.xml");
+ AttributeListImpl *pList = new AttributeListImpl;
+
+ Reference< XAttributeList > rList( (XAttributeList *) pList , UNO_QUERY );
+ Reference< XOutputStream > ref( ( XOutputStream * ) pw , UNO_QUERY );
+
+ Reference< XActiveDataSource > source( r , UNO_QUERY );
+
+ ERROR_ASSERT( ref.is() , "no output stream" );
+ ERROR_ASSERT( source.is() , "no active data source" );
+
+ source->setOutputStream( ref );
+
+ { // startDocument must be called before start element
+ sal_Bool bException = sal_True;
+ try
+ {
+ r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) , rList );
+ bException = sal_False;
+ }
+ catch( SAXException &e )
+ {
+
+ }
+ ERROR_ASSERT( bException , "expected exception not thrown !" );
+ }
+
+ r->startDocument();
+
+ r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) , rList );
+ r->startCDATA();
+
+ {
+ sal_Bool bException = sal_True;
+ try{
+ r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) , rList );
+ bException = sal_False;
+ }
+ catch( SAXException &e ) {
+
+ }
+ ERROR_ASSERT( bException , "expected exception not thrown !" );
+ }
+
+ r->endCDATA();
+
+ {
+ sal_Unicode array[] = { 'a' , 'b' , 4 , 9 , 10 };
+ OUString o( array , 5 );
+ try
+ {
+ r->characters( o );
+ ERROR_ASSERT( 0 , "Writer allowed to write forbidden characters" );
+ }
+ catch( SAXException & e )
+ {
+
+ }
+ }
+ r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) );
+
+ r->endDocument();
+}
+
+
+void OSaxWriterTest::testDTD(const Reference< XExtendedDocumentHandler > &r )
+{
+ OFileWriter *pw = new OFileWriter("outputDTD.xml");
+ AttributeListImpl *pList = new AttributeListImpl;
+
+ Reference< XAttributeList > rList( (XAttributeList *) pList , UNO_QUERY );
+ Reference< XOutputStream > ref( ( XOutputStream * ) pw , UNO_QUERY );
+
+ Reference< XActiveDataSource > source( r , UNO_QUERY );
+
+ ERROR_ASSERT( ref.is() , "no output stream" );
+ ERROR_ASSERT( source.is() , "no active data source" );
+
+ source->setOutputStream( ref );
+
+
+ r->startDocument();
+ r->unknown( OUString( RTL_CONSTASCII_USTRINGPARAM("<!DOCTYPE iCalendar >\n")) );
+ r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) , rList );
+
+ r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) );
+ r->endDocument();
+}
+
+void OSaxWriterTest::testPerformance(const Reference< XExtendedDocumentHandler > &r )
+{
+ OFileWriter *pw = new OFileWriter("testPerformance.xml");
+ AttributeListImpl *pList = new AttributeListImpl;
+
+ OUString testParagraph =
+ OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Dies ist ein bloeder Test um zu uberpruefen, ob der SAXWriter "
+ "wohl Zeilenumbrueche halbwegs richtig macht oder ob er die Zeile "
+ "bis zum bitteren Ende schreibt." ));
+
+
+ Reference< XAttributeList > rList( (XAttributeList *) pList , UNO_QUERY );
+ Reference< XOutputStream > ref( ( XOutputStream * ) pw , UNO_QUERY );
+
+ Reference< XActiveDataSource > source( r , UNO_QUERY );
+
+ ERROR_ASSERT( ref.is() , "no output stream" );
+ ERROR_ASSERT( source.is() , "no active data source" );
+
+ source->setOutputStream( ref );
+
+ TimeValue aStartTime, aEndTime;
+ osl_getSystemTime( &aStartTime );
+
+
+ r->startDocument();
+ // just write a bunch of xml tags !
+ // for performance testing
+ sal_Int32 i2;
+ OUString huhu( RTL_CONSTASCII_USTRINGPARAM("huhu") );
+ OUString emptyString;
+ const int ITERATIONS = 125;
+ for( i2 = 0 ; i2 < ITERATIONS ; i2 ++ )
+ {
+ r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("tag") ) +
+ OUString::valueOf( i2 ), rList );
+ for( sal_Int32 i = 0 ; i < 450 ; i ++ )
+ {
+ r->ignorableWhitespace( emptyString );
+ r->startElement( huhu , rList );
+ r->characters( testParagraph );
+
+ r->ignorableWhitespace( emptyString );
+ r->endElement( huhu );
+ }
+ }
+ for( i2 = ITERATIONS-1 ; i2 >= 0 ; i2-- )
+ {
+ r->ignorableWhitespace( emptyString );
+ r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("tag") ) + OUString::valueOf( i2 ) );
+ }
+
+ r->endDocument();
+
+ osl_getSystemTime( &aEndTime );
+
+ double fStart = (double)aStartTime.Seconds + ((double)aStartTime.Nanosec / 1000000000.0);
+ double fEnd = (double)aEndTime.Seconds + ((double)aEndTime.Nanosec / 1000000000.0);
+
+ printf( "Performance writing : %g s\n" , fEnd - fStart );
+}
+}
diff --git a/sax/test/saxdemo.cxx b/sax/test/saxdemo.cxx
new file mode 100644
index 000000000000..6023f09ac948
--- /dev/null
+++ b/sax/test/saxdemo.cxx
@@ -0,0 +1,651 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+//------------------------------------------------------
+// testcomponent - Loads a service and its testcomponent from dlls performs a test.
+// Expands the dll-names depending on the actual environment.
+// Example : testcomponent stardiv.uno.io.Pipe stm
+//
+// Therefor the testcode must exist in teststm and the testservice must be named test.stardiv.uno.io.Pipe
+//
+
+#include <stdio.h>
+#include <vector>
+
+#include <com/sun/star/registry/XImplementationRegistration.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+
+#include <com/sun/star/xml/sax/SAXParseException.hpp>
+#include <com/sun/star/xml/sax/XParser.hpp>
+#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
+
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XActiveDataSource.hpp>
+
+#include <cppuhelper/servicefactory.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <cppuhelper/implbase3.hxx>
+
+#include <vos/dynload.hxx>
+#include <vos/diagnose.hxx>
+
+using namespace ::rtl;
+using namespace ::std;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::registry;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::com::sun::star::io;
+
+
+/************
+ * Sequence of bytes -> InputStream
+ ************/
+class OInputStream : public WeakImplHelper1 < XInputStream >
+{
+public:
+ OInputStream( const Sequence< sal_Int8 >&seq ) :
+ m_seq( seq ),
+ nPos( 0 )
+ {}
+
+public:
+ virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
+ throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+ {
+ nBytesToRead = (nBytesToRead > m_seq.getLength() - nPos ) ?
+ m_seq.getLength() - nPos :
+ nBytesToRead;
+ aData = Sequence< sal_Int8 > ( &(m_seq.getConstArray()[nPos]) , nBytesToRead );
+ nPos += nBytesToRead;
+ return nBytesToRead;
+ }
+ virtual sal_Int32 SAL_CALL readSomeBytes(
+ ::com::sun::star::uno::Sequence< sal_Int8 >& aData,
+ sal_Int32 nMaxBytesToRead )
+ throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+ {
+ return readBytes( aData, nMaxBytesToRead );
+ }
+ virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
+ throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+ {
+ // not implemented
+ }
+ virtual sal_Int32 SAL_CALL available( )
+ throw(NotConnectedException, IOException, RuntimeException)
+ {
+ return m_seq.getLength() - nPos;
+ }
+ virtual void SAL_CALL closeInput( )
+ throw(NotConnectedException, IOException, RuntimeException)
+ {
+ // not needed
+ }
+ sal_Int32 nPos;
+ Sequence< sal_Int8> m_seq;
+};
+
+//-------------------------------
+// Helper : create an input stream from a file
+//------------------------------
+Reference< XInputStream > createStreamFromFile(
+ const char *pcFile )
+{
+ FILE *f = fopen( pcFile , "rb" );
+ Reference< XInputStream > r;
+
+ if( f ) {
+ fseek( f , 0 , SEEK_END );
+ int nLength = ftell( f );
+ fseek( f , 0 , SEEK_SET );
+
+ Sequence<sal_Int8> seqIn(nLength);
+ fread( seqIn.getArray() , nLength , 1 , f );
+
+ r = Reference< XInputStream > ( new OInputStream( seqIn ) );
+ fclose( f );
+ }
+ return r;
+}
+
+//-----------------------------------------
+// The document handler, which is needed for the saxparser
+// The Documenthandler for reading sax
+//-----------------------------------------
+class TestDocumentHandler :
+ public WeakImplHelper3< XExtendedDocumentHandler , XEntityResolver , XErrorHandler >
+{
+public:
+ TestDocumentHandler( )
+ {
+ }
+
+public: // Error handler
+ virtual void SAL_CALL error(const Any& aSAXParseException) throw (SAXException, RuntimeException)
+ {
+ printf( "Error !\n" );
+ throw SAXException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM("error from error handler")) ,
+ Reference < XInterface >() ,
+ aSAXParseException );
+ }
+ virtual void SAL_CALL fatalError(const Any& aSAXParseException) throw (SAXException, RuntimeException)
+ {
+ printf( "Fatal Error !\n" );
+ }
+ virtual void SAL_CALL warning(const Any& aSAXParseException) throw (SAXException, RuntimeException)
+ {
+ printf( "Warning !\n" );
+ }
+
+
+public: // ExtendedDocumentHandler
+
+ virtual void SAL_CALL startDocument(void) throw (SAXException, RuntimeException)
+ {
+ m_iElementCount = 0;
+ m_iAttributeCount = 0;
+ m_iWhitespaceCount =0;
+ m_iCharCount=0;
+ printf( "document started\n" );
+ }
+ virtual void SAL_CALL endDocument(void) throw (SAXException, RuntimeException)
+ {
+ printf( "document finished\n" );
+ printf( "(ElementCount %d),(AttributeCount %d),(WhitespaceCount %d),(CharCount %d)\n",
+ m_iElementCount, m_iAttributeCount, m_iWhitespaceCount , m_iCharCount );
+
+ }
+ virtual void SAL_CALL startElement(const OUString& aName,
+ const Reference< XAttributeList > & xAttribs)
+ throw (SAXException,RuntimeException)
+ {
+ m_iElementCount ++;
+ m_iAttributeCount += xAttribs->getLength();
+ }
+
+ virtual void SAL_CALL endElement(const OUString& aName) throw (SAXException,RuntimeException)
+ {
+ // ignored
+ }
+
+ virtual void SAL_CALL characters(const OUString& aChars) throw (SAXException,RuntimeException)
+ {
+ m_iCharCount += aChars.getLength();
+ }
+ virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces) throw (SAXException,RuntimeException)
+ {
+ m_iWhitespaceCount += aWhitespaces.getLength();
+ }
+
+ virtual void SAL_CALL processingInstruction(const OUString& aTarget, const OUString& aData) throw (SAXException,RuntimeException)
+ {
+ // ignored
+ }
+
+ virtual void SAL_CALL setDocumentLocator(const Reference< XLocator> & xLocator)
+ throw (SAXException,RuntimeException)
+ {
+ // ignored
+ }
+
+ virtual InputSource SAL_CALL resolveEntity(
+ const OUString& sPublicId,
+ const OUString& sSystemId)
+ throw (SAXException,RuntimeException)
+ {
+ InputSource source;
+ source.sSystemId = sSystemId;
+ source.sPublicId = sPublicId;
+
+ source.aInputStream = createStreamFromFile(
+ OUStringToOString( sSystemId , RTL_TEXTENCODING_ASCII_US) );
+
+ return source;
+ }
+
+ virtual void SAL_CALL startCDATA(void) throw (SAXException,RuntimeException)
+ {
+ }
+ virtual void SAL_CALL endCDATA(void) throw (SAXException,RuntimeException)
+ {
+ }
+ virtual void SAL_CALL comment(const OUString& sComment) throw (SAXException,RuntimeException)
+ {
+ }
+ virtual void SAL_CALL unknown(const OUString& sString) throw (SAXException,RuntimeException)
+ {
+ }
+
+ virtual void SAL_CALL allowLineBreak( void) throw (SAXException, RuntimeException )
+ {
+
+ }
+
+public:
+ int m_iElementCount;
+ int m_iAttributeCount;
+ int m_iWhitespaceCount;
+ int m_iCharCount;
+};
+
+//--------------------------------------
+// helper implementation for writing
+// implements an XAttributeList
+//-------------------------------------
+struct AttributeListImpl_impl;
+class AttributeListImpl : public WeakImplHelper1< XAttributeList >
+{
+public:
+ AttributeListImpl();
+ AttributeListImpl( const AttributeListImpl & );
+ ~AttributeListImpl();
+
+public:
+ virtual sal_Int16 SAL_CALL getLength(void) throw (RuntimeException);
+ virtual OUString SAL_CALL getNameByIndex(sal_Int16 i) throw (RuntimeException);
+ virtual OUString SAL_CALL getTypeByIndex(sal_Int16 i) throw (RuntimeException);
+ virtual OUString SAL_CALL getTypeByName(const OUString& aName) throw (RuntimeException);
+ virtual OUString SAL_CALL getValueByIndex(sal_Int16 i) throw (RuntimeException);
+ virtual OUString SAL_CALL getValueByName(const OUString& aName) throw (RuntimeException);
+
+public:
+ void addAttribute( const OUString &sName ,
+ const OUString &sType ,
+ const OUString &sValue );
+ void clear();
+
+private:
+ struct AttributeListImpl_impl *m_pImpl;
+};
+
+
+struct TagAttribute
+{
+ TagAttribute(){}
+ TagAttribute( const OUString &sName,
+ const OUString &sType ,
+ const OUString &sValue )
+ {
+ this->sName = sName;
+ this->sType = sType;
+ this->sValue = sValue;
+ }
+
+ OUString sName;
+ OUString sType;
+ OUString sValue;
+};
+
+struct AttributeListImpl_impl
+{
+ AttributeListImpl_impl()
+ {
+ // performance improvement during adding
+ vecAttribute.reserve(20);
+ }
+ vector<struct TagAttribute> vecAttribute;
+};
+
+
+
+sal_Int16 AttributeListImpl::getLength(void) throw (RuntimeException)
+{
+ return m_pImpl->vecAttribute.size();
+}
+
+
+AttributeListImpl::AttributeListImpl( const AttributeListImpl &r )
+{
+ m_pImpl = new AttributeListImpl_impl;
+ *m_pImpl = *(r.m_pImpl);
+}
+
+OUString AttributeListImpl::getNameByIndex(sal_Int16 i) throw (RuntimeException)
+{
+ if( i < m_pImpl->vecAttribute.size() ) {
+ return m_pImpl->vecAttribute[i].sName;
+ }
+ return OUString();
+}
+
+
+OUString AttributeListImpl::getTypeByIndex(sal_Int16 i) throw (RuntimeException)
+{
+ if( i < m_pImpl->vecAttribute.size() ) {
+ return m_pImpl->vecAttribute[i].sType;
+ }
+ return OUString();
+}
+
+OUString AttributeListImpl::getValueByIndex(sal_Int16 i) throw (RuntimeException)
+{
+ if( i < m_pImpl->vecAttribute.size() ) {
+ return m_pImpl->vecAttribute[i].sValue;
+ }
+ return OUString();
+
+}
+
+OUString AttributeListImpl::getTypeByName( const OUString& sName ) throw (RuntimeException)
+{
+ vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin();
+
+ for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
+ if( (*ii).sName == sName ) {
+ return (*ii).sType;
+ }
+ }
+ return OUString();
+}
+
+OUString AttributeListImpl::getValueByName(const OUString& sName) throw (RuntimeException)
+{
+ vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin();
+
+ for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
+ if( (*ii).sName == sName ) {
+ return (*ii).sValue;
+ }
+ }
+ return OUString();
+}
+
+
+
+AttributeListImpl::AttributeListImpl()
+{
+ m_pImpl = new AttributeListImpl_impl;
+}
+
+
+
+AttributeListImpl::~AttributeListImpl()
+{
+ delete m_pImpl;
+}
+
+
+void AttributeListImpl::addAttribute( const OUString &sName ,
+ const OUString &sType ,
+ const OUString &sValue )
+{
+ m_pImpl->vecAttribute.push_back( TagAttribute( sName , sType , sValue ) );
+}
+
+void AttributeListImpl::clear()
+{
+ m_pImpl->vecAttribute.clear();
+}
+
+
+//--------------------------------------
+// helper function for writing
+// ensures that linebreaks are inserted
+// when writing a long text.
+// Note: this implementation may be a bit slow,
+// but it shows, how the SAX-Writer handles the allowLineBreak calls.
+//--------------------------------------
+void writeParagraphHelper(
+ const Reference< XExtendedDocumentHandler > &r ,
+ const OUString & s)
+{
+ int nMax = s.getLength();
+ int nStart = 0;
+
+ Sequence<sal_uInt16> seq( s.getLength() );
+ memcpy( seq.getArray() , s.getStr() , s.getLength() * sizeof( sal_uInt16 ) );
+
+ for( int n = 1 ; n < nMax ; n++ ){
+ if( 32 == seq.getArray()[n] ) {
+ r->allowLineBreak();
+ r->characters( s.copy( nStart , n - nStart ) );
+ nStart = n;
+ }
+ }
+ r->allowLineBreak();
+ r->characters( s.copy( nStart , n - nStart ) );
+}
+
+
+//---------------------------------
+// helper implementation for SAX-Writer
+// writes data to a file
+//--------------------------------
+class OFileWriter :
+ public WeakImplHelper1< XOutputStream >
+{
+public:
+ OFileWriter( char *pcFile ) { strncpy( m_pcFile , pcFile, 256 - 1 ); m_f = 0; }
+
+
+public:
+ virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData)
+ throw (NotConnectedException, BufferSizeExceededException, RuntimeException);
+ virtual void SAL_CALL flush(void)
+ throw (NotConnectedException, BufferSizeExceededException, RuntimeException);
+ virtual void SAL_CALL closeOutput(void)
+ throw (NotConnectedException, BufferSizeExceededException, RuntimeException);
+private:
+ char m_pcFile[256];
+ FILE *m_f;
+};
+
+
+void OFileWriter::writeBytes(const Sequence< sal_Int8 >& aData)
+ throw (NotConnectedException, BufferSizeExceededException, RuntimeException)
+{
+ if( ! m_f ) {
+ m_f = fopen( m_pcFile , "w" );
+ }
+
+ fwrite( aData.getConstArray() , 1 , aData.getLength() , m_f );
+}
+
+
+void OFileWriter::flush(void)
+ throw (NotConnectedException, BufferSizeExceededException, RuntimeException)
+{
+ fflush( m_f );
+}
+
+void OFileWriter::closeOutput(void)
+ throw (NotConnectedException, BufferSizeExceededException, RuntimeException)
+{
+ fclose( m_f );
+ m_f = 0;
+}
+
+
+
+// Needed to switch on solaris threads
+#ifdef SOLARIS
+extern "C" void ChangeGlobalInit();
+#endif
+int main (int argc, char **argv)
+{
+
+ if( argc < 3) {
+ printf( "usage : saxdemo inputfile outputfile\n" );
+ exit( 0 );
+ }
+#ifdef SOLARIS
+ // switch on threads in solaris
+ ChangeGlobalInit();
+#endif
+
+ // create service manager
+ Reference< XMultiServiceFactory > xSMgr = createRegistryServiceFactory(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "applicat.rdb" )) );
+
+ Reference < XImplementationRegistration > xReg;
+ try
+ {
+ // Create registration service
+ Reference < XInterface > x = xSMgr->createInstance(
+ OUString::createFromAscii( "com.sun.star.registry.ImplementationRegistration" ) );
+ xReg = Reference< XImplementationRegistration > ( x , UNO_QUERY );
+ }
+ catch( Exception & ) {
+ printf( "Couldn't create ImplementationRegistration service\n" );
+ exit(1);
+ }
+
+ OString sTestName;
+ try
+ {
+ // Load dll for the tested component
+ OUString aDllName =
+ OUString::createFromAscii( "sax.uno" SAL_DLLEXTENSION );
+ xReg->registerImplementation(
+ OUString::createFromAscii( "com.sun.star.loader.SharedLibrary" ),
+ aDllName,
+ Reference< XSimpleRegistry > () );
+ }
+ catch( Exception &e ) {
+ printf( "Couldn't reach sax dll\n" );
+ printf( "%s\n" , OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ).getStr() );
+
+ exit(1);
+ }
+
+
+ //--------------------------------
+ // parser demo
+ // read xml from a file and count elements
+ //--------------------------------
+ Reference< XInterface > x = xSMgr->createInstance(
+ OUString::createFromAscii( "com.sun.star.xml.sax.Parser" ) );
+ if( x.is() )
+ {
+ Reference< XParser > rParser( x , UNO_QUERY );
+
+ // create and connect the document handler to the parser
+ TestDocumentHandler *pDocHandler = new TestDocumentHandler( );
+
+ Reference < XDocumentHandler > rDocHandler( (XDocumentHandler *) pDocHandler );
+ Reference< XEntityResolver > rEntityResolver( (XEntityResolver *) pDocHandler );
+
+ rParser->setDocumentHandler( rDocHandler );
+ rParser->setEntityResolver( rEntityResolver );
+
+ // create the input stream
+ InputSource source;
+ source.aInputStream = createStreamFromFile( argv[1] );
+ source.sSystemId = OUString::createFromAscii( argv[1] );
+
+ try
+ {
+ // start parsing
+ rParser->parseStream( source );
+ }
+
+ catch( Exception & e )
+ {
+ OString o1 = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8 );
+ printf( "Exception during parsing : %s\n" , o1.getStr() );
+ }
+ }
+ else
+ {
+ printf( "couln't create sax-parser component\n" );
+ }
+
+
+ //----------------------
+ // The SAX-Writer demo
+ //----------------------
+ x= xSMgr->createInstance( OUString::createFromAscii( "com.sun.star.xml.sax.Writer" ) );
+ if( x.is() )
+ {
+ printf( "start writing to %s\n" , argv[2] );
+
+ OFileWriter *pw = new OFileWriter( argv[2] );
+ Reference< XActiveDataSource > source( x , UNO_QUERY );
+ source->setOutputStream( Reference< XOutputStream> ( (XOutputStream*) pw ) );
+
+ AttributeListImpl *pList = new AttributeListImpl;
+ Reference< XAttributeList > rList( (XAttributeList *) pList );
+
+ Reference< XExtendedDocumentHandler > r( x , UNO_QUERY );
+ r->startDocument();
+
+ pList->addAttribute( OUString( RTL_CONSTASCII_USTRINGPARAM("Arg1" )),
+ OUString( RTL_CONSTASCII_USTRINGPARAM("CDATA")) ,
+ OUString( RTL_CONSTASCII_USTRINGPARAM("foo\n u")) );
+ pList->addAttribute( OUString( RTL_CONSTASCII_USTRINGPARAM("Arg2")) ,
+ OUString( RTL_CONSTASCII_USTRINGPARAM("CDATA")) ,
+ OUString( RTL_CONSTASCII_USTRINGPARAM("foo2")) );
+
+ r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("tag1")) , rList );
+ // tells the writer to insert a linefeed
+ r->ignorableWhitespace( OUString() );
+
+ r->characters( OUString( RTL_CONSTASCII_USTRINGPARAM("huhu")) );
+ r->ignorableWhitespace( OUString() );
+
+ r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("hi")) , rList );
+ r->ignorableWhitespace( OUString() );
+
+ // the enpassant must be converted & -> &amp;
+ r->characters( OUString( RTL_CONSTASCII_USTRINGPARAM("&#252;")) );
+ r->ignorableWhitespace( OUString() );
+
+ // '>' must not be converted
+ r->startCDATA();
+ r->characters( OUString( RTL_CONSTASCII_USTRINGPARAM(" > foo < ")) );
+ r->endCDATA();
+ r->ignorableWhitespace( OUString() );
+
+ OUString testParagraph = OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "This is only a test to check, if the writer inserts line feeds "
+ "if needed or if the writer puts the whole text into one line." ));
+ writeParagraphHelper( r , testParagraph );
+
+ r->ignorableWhitespace( OUString() );
+ r->comment( OUString( RTL_CONSTASCII_USTRINGPARAM("This is a comment !")) );
+ r->ignorableWhitespace( OUString() );
+
+ r->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM("emptytagtest")) , rList );
+ r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("emptytagtest")) );
+ r->ignorableWhitespace( OUString() );
+
+ r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("hi")) );
+ r->ignorableWhitespace( OUString() );
+
+ r->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM("tag1")) );
+ r->endDocument();
+
+ printf( "finished writing\n" );
+ }
+ else
+ {
+ printf( "couln't create sax-writer component\n" );
+ }
+}
diff --git a/sax/test/testcomponent.cxx b/sax/test/testcomponent.cxx
new file mode 100644
index 000000000000..f22366092b67
--- /dev/null
+++ b/sax/test/testcomponent.cxx
@@ -0,0 +1,230 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+//------------------------------------------------------
+// testcomponent - Loads a service and its testcomponent from dlls performs a test.
+// Expands the dll-names depending on the actual environment.
+// Example : testcomponent stardiv.uno.io.Pipe stm
+//
+// Therefor the testcode must exist in teststm and the testservice must be named test.stardiv.uno.io.Pipe
+//
+
+#include <stdio.h>
+#include <com/sun/star/registry/XImplementationRegistration.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+
+#include <com/sun/star/test/XSimpleTest.hpp>
+
+#include <cppuhelper/servicefactory.hxx>
+
+#include <vos/dynload.hxx>
+#include <vos/diagnose.hxx>
+
+using namespace ::rtl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::test;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::registry;
+
+// Needed to switch on solaris threads
+#ifdef SOLARIS
+extern "C" void ChangeGlobalInit();
+#endif
+
+int main (int argc, char **argv)
+{
+
+ if( argc < 3) {
+ printf( "usage : testcomponent service dll [additional dlls]\n" );
+ exit( 0 );
+ }
+#ifdef SOLARIS
+ // switch on threads in solaris
+ ChangeGlobalInit();
+#endif
+
+ // create service manager
+ Reference< XMultiServiceFactory > xSMgr =
+ createRegistryServiceFactory( OUString( RTL_CONSTASCII_USTRINGPARAM("applicat.rdb")) );
+
+ Reference < XImplementationRegistration > xReg;
+ Reference < XSimpleRegistry > xSimpleReg;
+
+ try
+ {
+ // Create registration service
+ Reference < XInterface > x = xSMgr->createInstance(
+ OUString::createFromAscii( "com.sun.star.registry.ImplementationRegistration" ) );
+ xReg = Reference< XImplementationRegistration > ( x , UNO_QUERY );
+ }
+ catch( Exception & ) {
+ printf( "Couldn't create ImplementationRegistration service\n" );
+ exit(1);
+ }
+
+ sal_Char szBuf[1024];
+ OString sTestName;
+
+ try
+ {
+ // Load dll for the tested component
+ for( int n = 2 ; n <argc ; n ++ ) {
+#ifdef SAL_W32
+ OUString aDllName = OStringToOUString( argv[n] , RTL_TEXTENCODING_ASCII_US );
+#else
+ OUString aDllName = OUString( RTL_CONSTASCII_USTRINGPARAM("lib"));
+ aDllName += OStringToOUString( argv[n] , RTL_TEXTENCODING_ASCII_US );
+ aDllName += OUString( RTL_CONSTASCII_USTRINGPARAM(".so"));
+#endif
+ xReg->registerImplementation(
+ OUString::createFromAscii( "com.sun.star.loader.SharedLibrary" ),
+ aDllName,
+ xSimpleReg );
+ }
+ }
+ catch( Exception &e ) {
+ printf( "Couldn't reach dll %s\n" , szBuf );
+ printf( "%s\n" , OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ).getStr() );
+
+ exit(1);
+ }
+
+
+ try
+ {
+ // Load dll for the test component
+ sTestName = "test";
+ sTestName += argv[2];
+
+#ifdef SAL_W32
+ OUString aDllName = OStringToOUString( sTestName , RTL_TEXTENCODING_ASCII_US );
+#else
+ OUString aDllName = OUString( RTL_CONSTASCII_USTRINGPARAM("lib"));
+ aDllName += OStringToOUString( sTestName , RTL_TEXTENCODING_ASCII_US );
+ aDllName += OUString( RTL_CONSTASCII_USTRINGPARAM(".so"));
+#endif
+
+ xReg->registerImplementation(
+ OUString::createFromAscii( "com.sun.star.loader.SharedLibrary" ) ,
+ aDllName,
+ xSimpleReg );
+ }
+ catch( Exception & e )
+ {
+ printf( "Couldn't reach dll %s\n" , szBuf );
+ exit(1);
+ }
+
+
+ // Instantiate test service
+ sTestName = "test.";
+ sTestName += argv[1];
+
+ Reference < XInterface > xIntTest =
+ xSMgr->createInstance( OStringToOUString( sTestName , RTL_TEXTENCODING_ASCII_US ) );
+ Reference< XSimpleTest > xTest( xIntTest , UNO_QUERY );
+
+ if( ! xTest.is() ) {
+ printf( "Couldn't instantiate test service \n" );
+ exit( 1 );
+ }
+
+
+ sal_Int32 nHandle = 0;
+ sal_Int32 nNewHandle;
+ sal_Int32 nErrorCount = 0;
+ sal_Int32 nWarningCount = 0;
+
+ // loop until all test are performed
+ while( nHandle != -1 )
+ {
+ // Instantiate serivce
+ Reference< XInterface > x =
+ xSMgr->createInstance( OStringToOUString( argv[1] , RTL_TEXTENCODING_ASCII_US ) );
+ if( ! x.is() )
+ {
+ printf( "Couldn't instantiate service !\n" );
+ exit( 1 );
+ }
+
+ // do the test
+ try
+ {
+ nNewHandle = xTest->test(
+ OStringToOUString( argv[1] , RTL_TEXTENCODING_ASCII_US ) , x , nHandle );
+ }
+ catch( Exception & e ) {
+ OString o = OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US );
+ printf( "testcomponent : uncaught exception %s\n" , o.getStr() );
+ exit(1);
+ }
+ catch( ... )
+ {
+ printf( "testcomponent : uncaught unknown exception\n" );
+ exit(1);
+ }
+
+
+ // print errors and warning
+ Sequence<OUString> seqErrors = xTest->getErrors();
+ Sequence<OUString> seqWarnings = xTest->getWarnings();
+ if( seqWarnings.getLength() > nWarningCount )
+ {
+ printf( "Warnings during test %d!\n" , nHandle );
+ for( ; nWarningCount < seqWarnings.getLength() ; nWarningCount ++ )
+ {
+ OString o = OUStringToOString(
+ seqWarnings.getArray()[nWarningCount], RTL_TEXTENCODING_ASCII_US );
+ printf( "Warning\n%s\n---------\n" , o.getStr() );
+ }
+ }
+
+
+ if( seqErrors.getLength() > nErrorCount ) {
+ printf( "Errors during test %d!\n" , nHandle );
+ for( ; nErrorCount < seqErrors.getLength() ; nErrorCount ++ ) {
+ OString o = OUStringToOString(
+ seqErrors.getArray()[nErrorCount], RTL_TEXTENCODING_ASCII_US );
+ printf( "%s\n" , o.getStr() );
+ }
+ }
+
+ nHandle = nNewHandle;
+ }
+
+ if( xTest->testPassed() ) {
+ printf( "Test passed !\n" );
+ }
+ else {
+ printf( "Test failed !\n" );
+ }
+
+ Reference <XComponent > rComp( xSMgr , UNO_QUERY );
+ rComp->dispose();
+ return 0;
+}
diff --git a/sax/util/makefile.mk b/sax/util/makefile.mk
new file mode 100644
index 000000000000..5e2f378603e9
--- /dev/null
+++ b/sax/util/makefile.mk
@@ -0,0 +1,68 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..
+
+PRJNAME=sax
+TARGET=sax
+
+USE_DEFFILE=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# ------------------------------------------------------------------
+
+LIB1TARGET= $(SLB)$/$(TARGET).lib
+LIB1FILES=\
+ $(SLB)$/saxtools.lib
+
+# sax
+
+SHL1TARGET= $(TARGET)$(DLLPOSTFIX)
+SHL1IMPLIB= i$(TARGET)
+SHL1USE_EXPORTS=name
+
+SHL1LIBS= $(LIB1TARGET)
+SHL1STDLIBS= \
+ $(VOSLIB) \
+ $(CPPULIB) \
+ $(CPPUHELPERLIB)\
+ $(COMPHELPERLIB)\
+ $(RTLLIB) \
+ $(SALLIB) \
+ $(ONELIB) \
+ $(SALHELPERLIB)
+
+SHL1DEF= $(MISC)$/$(SHL1TARGET).def
+DEF1NAME= $(SHL1TARGET)
+DEFLIB1NAME=$(TARGET)
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/sax/util/makefile.pmk b/sax/util/makefile.pmk
new file mode 100644
index 000000000000..1c044bb10ff0
--- /dev/null
+++ b/sax/util/makefile.pmk
@@ -0,0 +1,30 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+# Reduction of exported symbols:
+CDEFS += -DSAX_DLLIMPLEMENTATION
+VISIBILITY_HIDDEN=TRUE