No UNSIGNED_BYTE in Any
Lionel Elie Mamane
lionel at mamane.lu
Thu Dec 27 06:14:11 PST 2012
Hi,
The following code does not do what one would think:
sal_uInt8 nValue = 255;
Any aValue;
aValue <<= nValue;
aValue now contains a *BOOLEAN*. That's rather... surprising, and
could bite any of us one day. In particular:
sal_uInt8 naValue;
aValue >>= naValue;
now naValue contains 1. Not 255..
Ideally, I'd like that we fix this in LibreOffice 4.1.
The cleanest would be to add support for unsigned 8 bit integer in
Any, which as far as I understand would entail:
- adding typelib_TypeClass_UNSIGNED_BYTE to cppu/inc/typelib/typeclass.h
- adding "UNSIGNED_BYTE" to udkapi/com/sun/star/uno/TypeClass.idl (published!)
I'm not sure what the consequences of the latter are. E.g. do all Uno
bindings/bridges/... (Java, StarBasic, Python, ...) have to be updated
one by one?
Also, it seems the basic mechanism of dispatch with Any is C++
overloads; in particular, this is what happens in:
aValue <<= nValue
But sal_uInt8 and sal_Bool are typedefs of the same type, namely
"unsigned char", so I don't know how to make the distinction between
sal_Bool and sal_uInt8 in there.
So frankly, I'm not sure what to do... If we were a
pure C++ program, I'd change:
typedef unsigned char sal_Bool;
into
typedef bool sal_Bool;
or maybe
class sal_Bool
{
unsigned char m_bValue;
// constructors, member functions, operators, etc so that
// everything works right
}
But we have a "pure C" layer, so no can no do. In my understanding,
even C99's _Bool type won't save us, for several reasons:
1) I'm not sure it is really a "different type" than the other integer
types
2) It is not available in C++, so we can't have it in C++ code?
3) MSVC doesn't have C99 anyway
Hmm... Could we do something like:
typedef struct _sal_Bool
{
unsigned char bValue;
#ifdef __cplusplus
inline operator bool() const
{
return bValue;
}
inline _sal_Bool(bool b)
: bValue(b)
{ }
inline void operator=(bool b)
{
bValue=b;
}
#endif
} sal_Bool;
# define sal_False ((sal_Bool){0})
# define sal_True ((sal_Bool){1})
#ifdef __cplusplus
bool operator==(sal_Bool b0, sal_Bool b1)
{
return b0.bValue == b1.bValue;
}
#endif
??
So, in pure C code, we can still write:
sal_Bool b0 = sal_False;
sal_Bool b1 = sal_True;
b0 = b1;
but we'd have to write:
if (b0.bValue) {}
if (b0.bValue == b1.bValue) {}
b0.bValue = A || B && C
On the other hand, in C++ code, we could write:
if (b0 == sal_False) {}
if (b0 == b1) {}
if (b0) {}
b0 = A || B && C
The other solution would be an enum? Makes things a bit easier in C,
but less in C++. All these would work in C:
if (b0 == sal_False) {}
if (b0 == b1) {}
if (b0) {}
but not
b0 = A || B && C
and I don't think we can get it to work in C++, either.
So I'd rather make things maximally easy in C++, which is our main
language :)
Since we are in our "unstable API/ABI" period, *if* we can have a
clean solution, let's have it for LibreOffice 4.1. Since the in-memory
layout of sal_Bool does not change (right?), this might even be fully
ABI-compatible? (but not API-compatible for C, but API-compatible for
C++)
In terms of more hackish solutions, I have thought of not normalising
sal_Bool in Any (to make them "true" synonyms of sal_uInt8), *but*
this would break any code of the form:
if (b0 == sal_True) {}
switch (b0)
{
case sal_False:
case sal_True:
}
so, bleh, not looking forward to it. It would be something like:
diff --git a/cppu/inc/com/sun/star/uno/Any.hxx
b/cppu/inc/com/sun/star/uno/Any.hxx
index 6f3bda9..62ca967 100644
--- a/cppu/inc/com/sun/star/uno/Any.hxx
+++ b/cppu/inc/com/sun/star/uno/Any.hxx
@@ -248,7 +248,7 @@ inline sal_Bool SAL_CALL operator >>= ( const ::com::sun::star::uno::Any & rAny,
{
if (typelib_TypeClass_BOOLEAN == rAny.pType->eTypeClass)
{
- value = (* reinterpret_cast< const sal_Bool * >( rAny.pData ) != sal_False);
+ value = * reinterpret_cast< const sal_Bool * >( rAny.pData );
return sal_True;
}
return sal_False;
diff --git a/cppu/source/uno/copy.hxx b/cppu/source/uno/copy.hxx
index ce46492..d532d21 100644
--- a/cppu/source/uno/copy.hxx
+++ b/cppu/source/uno/copy.hxx
@@ -179,7 +179,7 @@ inline void _copyConstructAnyFromData(
break;
case typelib_TypeClass_BOOLEAN:
pDestAny->pData = &pDestAny->pReserved;
- *(sal_Bool *)pDestAny->pData = (*(sal_Bool *)pSource != sal_False);
+ *(sal_Bool *)pDestAny->pData = *(sal_Bool *)pSource;
break;
case typelib_TypeClass_BYTE:
pDestAny->pData = &pDestAny->pReserved;
Why did I get into this? Well, see https://gerrit.libreoffice.org/#/c/1164/
--
Lionel
More information about the LibreOffice
mailing list