summaryrefslogtreecommitdiff
path: root/sax
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@suse.cz>2012-12-19 12:13:13 +0100
committerLuboš Luňák <l.lunak@suse.cz>2012-12-19 12:20:00 +0100
commit9c17f2b24bc97b46640b1728fb04d65b88c09f75 (patch)
tree793a1818707d40e3a05258fee96627bd25e84869 /sax
parenta6d5ed529a373863eb670cc75bd797057a339745 (diff)
wrap vararg sax functions in typesafe overloads
Now automatic conversions can take place (no getStr() needed), and there are compile errors when used improperly. The FSEND terminator is also no longer needed, but it's better to dump it only after forgetting it no longer silently breaks backports. Change-Id: Ib47e6eda2d5e12ce889b69bf2affbda3679c2d3f
Diffstat (limited to 'sax')
-rw-r--r--sax/inc/sax/fshelper.hxx127
-rw-r--r--sax/source/tools/fshelper.cxx18
2 files changed, 121 insertions, 24 deletions
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 <sax/fastattribs.hxx>
#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<com::sun::star::xml::sax::XFastTokenHandler> 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<com::sun::star::xml::sax::XFastAttributeList> 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<com::sun::star::xml::sax::XFastAttributeList> 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);
}