diff --git a/sax/inc/sax/fshelper.hxx b/sax/inc/sax/fshelper.hxx index c416c2a2d79b..b0b8b0970465 100644 --- a/sax/inc/sax/fshelper.hxx +++ b/sax/inc/sax/fshelper.hxx @@ -28,7 +28,37 @@ #include #define FSNS(namespc, element) ((namespc << 16) | element) -const sal_Int32 FSEND = -1; // same as XML_TOKEN_INVALID +// Backwards compatibility for code that used FSEND to terminate the vararg. +// As soon as no supported LO version has the varargs code, this can be removed entirely +// (otherwise backports might break silently if people didn't add FSEND). +// Ctor is there to get an error when trying to pass it to a vararg by accident. +struct FSEND_t { FSEND_t() {}; }; +static const FSEND_t FSEND = FSEND_t(); +const sal_Int32 FSEND_internal = -1; // same as XML_TOKEN_INVALID + +#define SAX_ARGS_ARG( arg1, arg2, convert, num ) arg1##num, arg2##num convert +#define SAX_ARGS_ARG1( arg1, arg2, convert ) SAX_ARGS_ARG( arg1, arg2, convert, 1 ) +#define SAX_ARGS_ARG2( arg1, arg2, convert ) SAX_ARGS_ARG1( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 2 ) +#define SAX_ARGS_ARG3( arg1, arg2, convert ) SAX_ARGS_ARG2( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 3 ) +#define SAX_ARGS_ARG4( arg1, arg2, convert ) SAX_ARGS_ARG3( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 4 ) +#define SAX_ARGS_ARG5( arg1, arg2, convert ) SAX_ARGS_ARG4( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 5 ) +#define SAX_ARGS_ARG6( arg1, arg2, convert ) SAX_ARGS_ARG5( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 6 ) +#define SAX_ARGS_ARG7( arg1, arg2, convert ) SAX_ARGS_ARG6( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 7 ) +#define SAX_ARGS_ARG8( arg1, arg2, convert ) SAX_ARGS_ARG7( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 8 ) +#define SAX_ARGS_ARG9( arg1, arg2, convert ) SAX_ARGS_ARG8( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 9 ) +#define SAX_ARGS_ARG10( arg1, arg2, convert ) SAX_ARGS_ARG9( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 10 ) +#define SAX_ARGS_ARG11( arg1, arg2, convert ) SAX_ARGS_ARG10( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 11 ) +#define SAX_ARGS_ARG12( arg1, arg2, convert ) SAX_ARGS_ARG11( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 12 ) +#define SAX_ARGS_ARG13( arg1, arg2, convert ) SAX_ARGS_ARG12( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 13 ) +#define SAX_ARGS_ARG14( arg1, arg2, convert ) SAX_ARGS_ARG13( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 14 ) +#define SAX_ARGS_ARG15( arg1, arg2, convert ) SAX_ARGS_ARG14( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 15 ) +#define SAX_ARGS_ARG16( arg1, arg2, convert ) SAX_ARGS_ARG15( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 16 ) +#define SAX_ARGS_ARG17( arg1, arg2, convert ) SAX_ARGS_ARG16( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 17 ) +#define SAX_ARGS_ARG18( arg1, arg2, convert ) SAX_ARGS_ARG17( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 18 ) +#define SAX_ARGS_ARG19( arg1, arg2, convert ) SAX_ARGS_ARG18( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 19 ) +#define SAX_ARGS_ARG20( arg1, arg2, convert ) SAX_ARGS_ARG19( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 20 ) +#define SAX_ARGS_ARG21( arg1, arg2, convert ) SAX_ARGS_ARG20( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 21 ) +#define SAX_ARGS_ARG22( arg1, arg2, convert ) SAX_ARGS_ARG21( arg1, arg2, convert ), SAX_ARGS_ARG( arg1, arg2, convert, 22 ) namespace sax_fastparser { @@ -46,30 +76,53 @@ public: ~FastSerializerHelper(); - 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 ); } + /// Start an element. After the first argument there can be a number of (attribute, value) pairs. + void startElement(sal_Int32 elementTokenId, FSEND_t) + { startElementInternal( elementTokenId, FSEND_internal ); } + /// overload + void startElement(sal_Int32 elementTokenId, sal_Int32 attribute, const char* value, FSEND_t) + { startElementInternal( elementTokenId, attribute, value, FSEND_internal ); } + /// overload + void startElement(sal_Int32 elementTokenId, sal_Int32 attribute, const OString& value, FSEND_t) + { startElementInternal( elementTokenId, attribute, value.getStr(), FSEND_internal ); } + /// Create a single element. After the first argument there can be a number of (attribute, value) pairs. + void singleElement(sal_Int32 elementTokenId, FSEND_t) + { singleElementInternal( elementTokenId, FSEND_internal ); } + /// overload + void singleElement(sal_Int32 elementTokenId, sal_Int32 attribute, const char* value, FSEND_t) + { singleElementInternal( elementTokenId, attribute, value, FSEND_internal ); } + /// overload + void singleElement(sal_Int32 elementTokenId, sal_Int32 attribute, const OString& value, FSEND_t) + { singleElementInternal( elementTokenId, attribute, value.getStr(), FSEND_internal ); } + /// Start an element. After the first two arguments there can be a number of (attribute, value) pairs. + void startElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, FSEND_t) + { startElementInternal( FSNS( namespaceTokenId, elementTokenId), FSEND_internal ); } + /// overload + void startElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, sal_Int32 attribute, const char* value, FSEND_t) + { startElementInternal( FSNS( namespaceTokenId, elementTokenId), attribute, value, FSEND_internal ); } + /// overload + void startElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, sal_Int32 attribute, const OString& value, FSEND_t) + { startElementInternal( FSNS( namespaceTokenId, elementTokenId), attribute, value.getStr(), FSEND_internal ); } + /// Create a single element. After the first two arguments there can be a number of (attribute, value) pairs. + void singleElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, FSEND_t) + { singleElementInternal( FSNS( namespaceTokenId, elementTokenId), FSEND_internal ); } + /// overload + void singleElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, sal_Int32 attribute, const char* value, FSEND_t) + { singleElementInternal( FSNS( namespaceTokenId, elementTokenId), attribute, value, FSEND_internal ); } + /// overload + void singleElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, sal_Int32 attribute, const OString& value, FSEND_t) + { singleElementInternal( FSNS( namespaceTokenId, elementTokenId), attribute, value.getStr(), FSEND_internal ); } void endElement(sal_Int32 elementTokenId); inline void endElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId) { endElement( FSNS( namespaceTokenId, elementTokenId ) ); } - inline void singleElement(sal_Int32 elementTokenId, XFastAttributeListRef xAttrList) - { singleElementV(elementTokenId, xAttrList); } - void singleElementV(sal_Int32 elementTokenId, XFastAttributeListRef xAttrList); + void singleElement(sal_Int32 elementTokenId, XFastAttributeListRef xAttrList); inline void singleElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, XFastAttributeListRef xAttrList) - { singleElementV(FSNS( namespaceTokenId, elementTokenId), xAttrList); } + { singleElement(FSNS( namespaceTokenId, elementTokenId), xAttrList); } - void startElementV(sal_Int32 elementTokenId, XFastAttributeListRef xAttrList); + void startElement(sal_Int32 elementTokenId, XFastAttributeListRef xAttrList); inline void startElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, XFastAttributeListRef xAttrList) - { startElementV( FSNS( namespaceTokenId, elementTokenId ), xAttrList ); } + { startElement( FSNS( namespaceTokenId, elementTokenId ), xAttrList ); } FastSerializerHelper* write(const char* value); FastSerializerHelper* write(const rtl::OUString& value); @@ -90,7 +143,45 @@ public: ::com::sun::star::uno::Sequence< sal_Int32 >() ); void mergeTopMarks( MergeMarksEnum eMergeType = MERGE_MARKS_APPEND ); + /* + Now create all the overloads in a typesafe way (i.e. without varargs) by creating a number of overloads + up to a certain reasonable limit (feel free to raise it). This would be a lot easier with C++11 vararg templates. + */ + // now overloads for 2 and more pairs + #define SAX_ARGS_FUNC_DECL( argsdecl, argsuse ) \ + void startElement(sal_Int32 elementTokenId, argsdecl, FSEND_t) \ + { startElementInternal( elementTokenId, argsuse, FSEND_internal ); } \ + void singleElement(sal_Int32 elementTokenId, argsdecl, FSEND_t) \ + { singleElementInternal( elementTokenId, argsuse, FSEND_internal ); } \ + void startElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, argsdecl, FSEND_t) \ + { startElementInternal( FSNS( namespaceTokenId, elementTokenId), argsuse, FSEND_internal ); } \ + void singleElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, argsdecl, FSEND_t) \ + { singleElementInternal( FSNS( namespaceTokenId, elementTokenId), argsuse, FSEND_internal ); } + #define SAX_ARGS_FUNC_NUM( decl1, decl2, use1, use2, convert, num ) \ + SAX_ARGS_FUNC_DECL( SAX_ARGS_ARG##num( decl1, decl2, ), SAX_ARGS_ARG##num( use1, use2, convert )) + #define SAX_ARGS_FUNC_SUBST( type, convert, num ) \ + SAX_ARGS_FUNC_NUM( sal_Int32 attribute, type value, attribute, value, convert, num ) + #define SAX_ARGS_FUNC( arg, convert ) SAX_ARGS_FUNC_SUBST( arg, convert, 2 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 3 ) SAX_ARGS_FUNC_SUBST( arg, convert, 4 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 5 ) SAX_ARGS_FUNC_SUBST( arg, convert, 6 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 7 ) SAX_ARGS_FUNC_SUBST( arg, convert, 8 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 9 ) SAX_ARGS_FUNC_SUBST( arg, convert, 10 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 11 ) SAX_ARGS_FUNC_SUBST( arg, convert, 12 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 13 ) SAX_ARGS_FUNC_SUBST( arg, convert, 14 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 15 ) SAX_ARGS_FUNC_SUBST( arg, convert, 16 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 17 ) SAX_ARGS_FUNC_SUBST( arg, convert, 18 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 19 ) SAX_ARGS_FUNC_SUBST( arg, convert, 20 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 21 ) SAX_ARGS_FUNC_SUBST( arg, convert, 22 ) + SAX_ARGS_FUNC( const char*, ) + SAX_ARGS_FUNC( const OString&, .getStr() ) + #undef SAX_ARGS_FUNC_DECL + #undef SAX_ARGS_FUNC_NUM + #undef SAX_ARGS_FUNC_SUBST + #undef SAX_ARGS_FUNC + private: + void startElementInternal(sal_Int32 elementTokenId, ...); + void singleElementInternal(sal_Int32 elementTokenId, ...); FastSaxSerializer* mpSerializer; com::sun::star::uno::Reference mxTokenHandler; diff --git a/sax/source/tools/fshelper.cxx b/sax/source/tools/fshelper.cxx index ffb3506c175d..2f3f7bfc5292 100644 --- a/sax/source/tools/fshelper.cxx +++ b/sax/source/tools/fshelper.cxx @@ -47,14 +47,16 @@ FastSerializerHelper::~FastSerializerHelper() delete mpSerializer; } -void FastSerializerHelper::startElementV(sal_Int32 elementTokenId, va_list args) +void FastSerializerHelper::startElementInternal(sal_Int32 elementTokenId, ...) { + va_list args; + va_start( args, elementTokenId ); FastAttributeList* pAttrList = new FastAttributeList( mxTokenHandler ); while (true) { sal_Int32 nName = va_arg(args, sal_Int32); - if (nName == FSEND) + if (nName == FSEND_internal) break; const char* pValue = va_arg(args, const char*); if (pValue) @@ -63,16 +65,19 @@ void FastSerializerHelper::startElementV(sal_Int32 elementTokenId, va_list args) const com::sun::star::uno::Reference xAttrList(pAttrList); mpSerializer->startFastElement(elementTokenId, xAttrList); + va_end( args ); } -void FastSerializerHelper::singleElementV(sal_Int32 elementTokenId, va_list args) +void FastSerializerHelper::singleElementInternal(sal_Int32 elementTokenId, ...) { + va_list args; + va_start( args, elementTokenId ); FastAttributeList* pAttrList = new FastAttributeList( mxTokenHandler ); while (true) { sal_Int32 nName = va_arg(args, sal_Int32); - if (nName == FSEND) + if (nName == FSEND_internal) break; const char* pValue = va_arg(args, const char*); if (pValue) @@ -81,6 +86,7 @@ void FastSerializerHelper::singleElementV(sal_Int32 elementTokenId, va_list args const com::sun::star::uno::Reference xAttrList(pAttrList); mpSerializer->singleFastElement(elementTokenId, xAttrList); + va_end( args ); } void FastSerializerHelper::endElement(sal_Int32 elementTokenId) @@ -88,13 +94,13 @@ void FastSerializerHelper::endElement(sal_Int32 elementTokenId) mpSerializer->endFastElement(elementTokenId); } -void FastSerializerHelper::startElementV(sal_Int32 elementTokenId, XFastAttributeListRef xAttrList) +void FastSerializerHelper::startElement(sal_Int32 elementTokenId, XFastAttributeListRef xAttrList) { mpSerializer->startFastElement(elementTokenId, xAttrList); } -void FastSerializerHelper::singleElementV(sal_Int32 elementTokenId, XFastAttributeListRef xAttrList) +void FastSerializerHelper::singleElement(sal_Int32 elementTokenId, XFastAttributeListRef xAttrList) { mpSerializer->singleFastElement(elementTokenId, xAttrList); } diff --git a/sc/source/filter/excel/xestream.cxx b/sc/source/filter/excel/xestream.cxx index 9df58112cf23..a22496c2b52d 100644 --- a/sc/source/filter/excel/xestream.cxx +++ b/sc/source/filter/excel/xestream.cxx @@ -999,7 +999,7 @@ sax_fastparser::FSHelperPtr XclExpXmlStream::GetStreamForPath( const OUString& s return maOpenedStreamMap[ sPath ].second; } -sax_fastparser::FSHelperPtr& XclExpXmlStream::WriteAttributes( sal_Int32 nAttribute, ... ) +sax_fastparser::FSHelperPtr& XclExpXmlStream::WriteAttributesInternal( sal_Int32 nAttribute, ... ) { sax_fastparser::FSHelperPtr& rStream = GetCurrentStream(); @@ -1017,7 +1017,7 @@ sax_fastparser::FSHelperPtr& XclExpXmlStream::WriteAttributes( sal_Int32 nAttrib } nAttribute = va_arg( args, sal_Int32 ); - if( nAttribute == FSEND ) + if( nAttribute == FSEND_internal ) break; } while( true ); va_end( args ); diff --git a/sc/source/filter/inc/xestream.hxx b/sc/source/filter/inc/xestream.hxx index 3c22bda1c096..571809c29276 100644 --- a/sc/source/filter/inc/xestream.hxx +++ b/sc/source/filter/inc/xestream.hxx @@ -311,7 +311,10 @@ public: sax_fastparser::FSHelperPtr GetStreamForPath( const ::rtl::OUString& rPath ); - sax_fastparser::FSHelperPtr& WriteAttributes( sal_Int32 nAttribute, ... ); + sax_fastparser::FSHelperPtr& WriteAttributes( sal_Int32 nAttribute, const char* value, FSEND_t ) + { return WriteAttributesInternal( nAttribute, value, FSEND_internal ); } + sax_fastparser::FSHelperPtr& WriteAttributes( sal_Int32 nAttribute, const OString& value, FSEND_t ) + { return WriteAttributesInternal( nAttribute, value.getStr(), FSEND_internal ); } sax_fastparser::FSHelperPtr CreateOutputStream ( const ::rtl::OUString& sFullStream, @@ -331,10 +334,41 @@ public: virtual const oox::drawingml::table::TableStyleListPtr getTableStyles(); virtual oox::drawingml::chart::ChartConverter* getChartConverter(); + /* + Now create all the overloads in a typesafe way (i.e. without varargs) by creating a number of overloads + up to a certain reasonable limit (feel free to raise it). This would be a lot easier with C++11 vararg templates. + */ + // now overloads for 2 and more pairs + #define SAX_ARGS_FUNC_DECL( argsdecl, argsuse ) \ + sax_fastparser::FSHelperPtr& WriteAttributes( argsdecl, FSEND_t ) \ + { return WriteAttributesInternal( argsuse, FSEND_internal ); } + #define SAX_ARGS_FUNC_NUM( decl1, decl2, use1, use2, convert, num ) \ + SAX_ARGS_FUNC_DECL( SAX_ARGS_ARG##num( decl1, decl2, ), SAX_ARGS_ARG##num( use1, use2, convert )) + #define SAX_ARGS_FUNC_SUBST( type, convert, num ) \ + SAX_ARGS_FUNC_NUM( sal_Int32 attribute, type value, attribute, value, convert, num ) + #define SAX_ARGS_FUNC( arg, convert ) SAX_ARGS_FUNC_SUBST( arg, convert, 2 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 3 ) SAX_ARGS_FUNC_SUBST( arg, convert, 4 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 5 ) SAX_ARGS_FUNC_SUBST( arg, convert, 6 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 7 ) SAX_ARGS_FUNC_SUBST( arg, convert, 8 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 9 ) SAX_ARGS_FUNC_SUBST( arg, convert, 10 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 11 ) SAX_ARGS_FUNC_SUBST( arg, convert, 12 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 13 ) SAX_ARGS_FUNC_SUBST( arg, convert, 14 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 15 ) SAX_ARGS_FUNC_SUBST( arg, convert, 16 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 17 ) SAX_ARGS_FUNC_SUBST( arg, convert, 18 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 19 ) SAX_ARGS_FUNC_SUBST( arg, convert, 20 ) \ + SAX_ARGS_FUNC_SUBST( arg, convert, 21 ) SAX_ARGS_FUNC_SUBST( arg, convert, 22 ) + SAX_ARGS_FUNC( const char*, ) + SAX_ARGS_FUNC( const OString&, .getStr() ) + #undef SAX_ARGS_FUNC_DECL + #undef SAX_ARGS_FUNC_NUM + #undef SAX_ARGS_FUNC_SUBST + #undef SAX_ARGS_FUNC + private: virtual ::oox::ole::VbaProject* implCreateVbaProject() const; virtual ::rtl::OUString implGetImplementationName() const; ScDocShell *getDocShell(); + sax_fastparser::FSHelperPtr& WriteAttributesInternal( sal_Int32 nAttribute, ... ); typedef std::map< ::rtl::OUString, std::pair< ::rtl::OUString,