Hello Johannes,
Johannes Brunen wrote:
"Carsten Neumann" <carsten_neum...@gmx.net> schrieb im
Newsbeitrag news:4c50ca12.6080...@gmx.net...
Anyway, out of curiosity, do you use different compiler switches from
OpenSG's defaults?
I use default settings with the exception of
OSG_ENABLE_SSE2:BOOL=OFF
ok. It seems the default VC++ setting of /fp:precise makes the compiler
pass floats through FPU (387) registers.
I get the same problem on linux when passing -fpmath=387 to gcc.
I have not set additional compiler flags. The only other difference is that
I use a special memory manager, which is not the cause of the problem.
yes, the problem is that values get passed through FPU registers and the
excess precision of the 387 modifies the value :(
I have one other idea how to work around this [1], but have to admit
that I'm at the point where I don't really understand these things well
enough to have much confidence even if the proposed patch should happen
to work.
I think that this is the right direction to go. Changing the bit order,
basically means changing the type representation. After swapping only
UInt32/64 should be carried around. IMO this is a save way to go.
yeah, this is pretty much what I ended up doing, after trying a large
number of approaches and looking at the generated assembler on both win
and linux that seemed the only way to keep the FPU out of the picture.
Alternatively, for the short term my initial solution might be applicable.
It is not elegant but also avoids the copying and assignment of swaped
reals. I did, however, not check for other use cases of the
osgSwapBytes(RealXX) functions.
Unfortunately this
requires a bunch of changes throughout OpenSG and I have not finished
the patch yet.
Sorry, but it is crucial that the core is running stable and predictable.
?
Attached is a patch that modifies the endian conversion functions in
OpenSG and adjust uses in the system. I've also attached my test program
in case anyone feels like playing with this.
This breaks the interfaces for endian conversion in OpenSG, but I see no
way to make the existing ones work reliably and hopefully this does not
break too many applications or only in a few places.
Thanks for your patience and assistance in discovering this (apparently)
long standing problem [1].
Cheers,
Carsten
[1] One thing I still don't quite understand is why nobody else is
seeing this; this bug has been present in OpenSG as far as I can
remember and all examples of htonf functions I could find on the net
have the signature float htonf(float value), so AFAICS they suffer from
the exact same problem...
diff --git a/Source/Base/Base/OSGBaseFunctions.h b/Source/Base/Base/OSGBaseFunctions.h
index f0acc0a..1b6ca72 100644
--- a/Source/Base/Base/OSGBaseFunctions.h
+++ b/Source/Base/Base/OSGBaseFunctions.h
@@ -410,26 +410,41 @@ std::string getCallStack();
inline
bool osgIsBigEndian(void);
-template <class ValueTypeT> inline
+template <class ValueTypeT> inline
ValueTypeT osgSwapBytes(ValueTypeT src);
-template <class TypeT> inline
-TypeT osgHostToBigEndian(TypeT src);
+inline
+OSG::UInt32 osgSwapBytesFP(OSG::Real32 src);
+
+inline
+OSG::Real32 osgSwapBytesFP(OSG::UInt32 src);
+
+inline
+OSG::UInt64 osgSwapBytesFP(OSG::Real64 src);
-template <class TypeT> inline
-TypeT osgHostToLittleEndian(TypeT src);
+inline
+OSG::Real64 osgSwapBytesFP(OSG::UInt64 src);
-template <class TypeT> inline
-TypeT osgBigEndianToHost(TypeT src);
+template <OSG::UInt8 ElemSize> inline
+void osgSwapMem(void *mem, OSG::UInt32 count);
-template <class TypeT> inline
-TypeT osgLittleEndianToHost(TypeT src);
+template <class TypeT> inline
+TypeT osgHostToNet (const TypeT src);
-template <class TypeT> inline
-TypeT osgHostToNet(const TypeT src);
+inline
+OSG::UInt32 osgHostToNetFP(const OSG::Real32 src);
-template <class TypeT> inline
-TypeT osgNetToHost(const TypeT src);
+inline
+OSG::UInt64 osgHostToNetFP(const OSG::Real64 src);
+
+template <class TypeT> inline
+TypeT osgNetToHost (const TypeT src);
+
+inline
+OSG::Real32 osgNetToHostFP(const OSG::UInt32 src);
+
+inline
+OSG::Real64 osgNetToHostFP(const OSG::UInt64 src);
// host to network
diff --git a/Source/Base/Base/OSGBaseFunctions.inl b/Source/Base/Base/OSGBaseFunctions.inl
index c73f8ec..c9cc970 100644
--- a/Source/Base/Base/OSGBaseFunctions.inl
+++ b/Source/Base/Base/OSGBaseFunctions.inl
@@ -2848,13 +2848,11 @@ bool osgIsBigEndian(void)
#ifdef OSG_LONGLONG_HAS_LL
#define OSG_UINT64_LITERAL(value) value##ULL
-
#define OSG_INT64_LITERAL(value) value##LL
#else
#define OSG_UINT64_LITERAL(value) value##U
-
#define OSG_INT64_LITERAL(value) value
#endif
@@ -2934,130 +2932,139 @@ OSG::Int64 osgSwapBytes<Int64>(OSG::Int64 src)
return static_cast<Int64>(osgSwapBytes<UInt64>(static_cast<UInt64>(src)));
}
-/*! \ingroup GrpBaseBaseMiscFn
+/*! Reverse the bytes of the floating point value \a src.
+
+ \note It does not return a floating point value, to avoid the value being
+ passed through a 387 FPU register - the excess precision of the 387
+ causes certain values (NaN) to be garbled and after the reversal
+ the bit pattern of a regular value might be the same as a NaN.
+
+ \ingroup GrpBaseBaseMiscFn
*/
-template <> inline
-OSG::Real32 osgSwapBytes<Real32>(OSG::Real32 src)
+inline
+OSG::UInt32 osgSwapBytesFP(OSG::Real32 src)
{
- UInt8* pStart = reinterpret_cast<UInt8*>(&src);
- UInt8* pEnd = reinterpret_cast<UInt8*>(&src) + sizeof(Real32);
+ union
+ {
+ OSG::Real32 floatVal;
+ OSG::UInt32 intVal;
+ } unionVal;
- std::reverse(pStart, pEnd);
+ unionVal.floatVal = src;
+ unionVal.intVal = osgSwapBytes(unionVal.intVal);
- return src;
+ return unionVal.intVal;
}
/*! \ingroup GrpBaseBaseMiscFn
*/
-template <> inline
-OSG::Real64 osgSwapBytes<Real64>(OSG::Real64 src)
+inline
+OSG::Real32 osgSwapBytesFP(OSG::UInt32 src)
{
- UInt8* pStart = reinterpret_cast<UInt8*>(&src);
- UInt8* pEnd = reinterpret_cast<UInt8*>(&src) + sizeof(Real64);
+ union
+ {
+ OSG::Real32 floatVal;
+ OSG::UInt32 intVal;
+ } unionVal;
- std::reverse(pStart, pEnd);
+ unionVal.intVal = osgSwapBytes(src);
- return src;
+ return unionVal.floatVal;
}
-/*! Convert a value from host byte order to big endian byte order.
-
- \param[in] src Input value in host byte order.
- \return The input converted to big endian byte order.
-
- \note An actual conversion only happens on little endian architectures.
-
- \ingroup GrpBaseBaseMiscFn
+/*! \ingroup GrpBaseBaseMiscFn
*/
-template <class TypeT> inline
-TypeT osgHostToBigEndian(TypeT src)
+inline
+OSG::UInt64 osgSwapBytesFP(OSG::Real64 src)
{
-#if BYTE_ORDER == LITTLE_ENDIAN
- return osgSwapBytes(src);
-#else
- return src;
-#endif
+ union
+ {
+ OSG::Real64 floatVal;
+ OSG::UInt64 intVal;
+ } unionVal;
+
+ unionVal.floatVal = src;
+ unionVal.intVal = osgSwapBytes(unionVal.intVal);
+
+ return unionVal.intVal;
}
/*! \ingroup GrpBaseBaseMiscFn
*/
-template <> inline
-OSG::Real128 osgHostToBigEndian<Real128>(OSG::Real128 src)
+inline
+OSG::Real64 osgSwapBytesFP(OSG::UInt64 src)
{
-#if BYTE_ORDER == LITTLE_ENDIAN
- char *p = reinterpret_cast<char*>(&src);
+ union
+ {
+ OSG::Real64 floatVal;
+ OSG::UInt64 intVal;
+ } unionVal;
- std::swap(p[0], p[15]);
- std::swap(p[1], p[14]);
- std::swap(p[2], p[13]);
- std::swap(p[3], p[12]);
- std::swap(p[4], p[11]);
- std::swap(p[5], p[10]);
- std::swap(p[6], p[9]);
- std::swap(p[7], p[8]);
+ unionVal.intVal = osgSwapBytes(src);
- return src;
-#else
- return src;
-#endif
+ return unionVal.floatVal;
}
-/*! Convert a value from host byte order to little endian byte order.
-
- \param[in] src Input value in host byte order.
- \return The input converted to little endian byte order.
+/*! Reverses bytes of the \a count values of size \a ElemSize pointed to by
+ \a mem.
- \note An actual conversion only happens on big endian architectures.
+ \warning Be sure you know what you are doing when using these functions,
+ as they make aliasing rule violiations very easy/likely.
\ingroup GrpBaseBaseMiscFn
*/
-template <class TypeT> inline
-TypeT osgHostToLittleEndian(TypeT src)
+template <> inline
+void osgSwapMem<2>(void *mem, OSG::UInt32 count)
{
-#if BYTE_ORDER == LITTLE_ENDIAN
- return src;
-#else
- return osgSwapBytes(src);
-#endif
+ OSG::UInt16 *p = static_cast<OSG::UInt16 *>(mem);
+
+ for(OSG::UInt32 i = 0; i < count; ++i)
+ {
+ p[i] = osgSwapBytes(p[i]);
+ }
}
/*! \ingroup GrpBaseBaseMiscFn
*/
-template <> inline
-OSG::Real128 osgHostToLittleEndian<Real128>(OSG::Real128 src)
+template <> inline
+void osgSwapMem<4>(void *mem, OSG::UInt32 count)
{
-#if BYTE_ORDER == LITTLE_ENDIAN
- return src;
-#else
- char *p = reinterpret_cast<char*>(&src);
+ OSG::UInt32 *p = static_cast<OSG::UInt32 *>(mem);
- std::swap(p[0], p[15]);
- std::swap(p[1], p[14]);
- std::swap(p[2], p[13]);
- std::swap(p[3], p[12]);
- std::swap(p[4], p[11]);
- std::swap(p[5], p[10]);
- std::swap(p[6], p[9]);
- std::swap(p[7], p[8]);
+ for(OSG::UInt32 i = 0; i < count; ++i)
+ {
+ p[i] = osgSwapBytes(p[i]);
+ }
+}
- return src;
-#endif
+/*! \ingroup GrpBaseBaseMiscFn
+ */
+template <> inline
+void osgSwapMem<8>(void *mem, OSG::UInt32 count)
+{
+ OSG::UInt64 *p = static_cast<OSG::UInt64 *>(mem);
+
+ for(OSG::UInt64 i = 0; i < count; ++i)
+ {
+ p[i] = osgSwapBytes(p[i]);
+ }
}
-/*! Convert a value from big endian byte order to host byte order.
+/*! Convert a value from host byte order to network byte order.
- \param[in] src Input value in big endian byte order.
- \return The input converted to host byte order.
+ \param[in] src Input value in host byte order.
+ \return The input converted to network byte order.
- \note An actual conversion only happens on little endian architectures.
+ \note Network byte order is big endian, so an actual conversion only
+ happens on little endian architectures.
\ingroup GrpBaseBaseMiscFn
*/
template <class TypeT> inline
-TypeT osgBigEndianToHost(TypeT src)
+TypeT osgHostToNet(const TypeT src)
{
#if BYTE_ORDER == LITTLE_ENDIAN
- return osgSwapBytes(src);
+ return OSG::osgSwapBytes(src);
#else
return src;
#endif
@@ -3065,99 +3072,102 @@ TypeT osgBigEndianToHost(TypeT src)
/*! \ingroup GrpBaseBaseMiscFn
*/
-template <> inline
-OSG::Real128 osgBigEndianToHost<Real128>(OSG::Real128 src)
+inline
+OSG::UInt32 osgHostToNetFP(const OSG::Real32 src)
{
#if BYTE_ORDER == LITTLE_ENDIAN
- char *p = reinterpret_cast<char*>(&src);
+ return OSG::osgSwapBytesFP(src);
+#else
+ union
+ {
+ OSG::Real32 floatVal;
+ OSG::UInt32 intVal;
+ } unionVal;
- std::swap(p[0], p[15]);
- std::swap(p[1], p[14]);
- std::swap(p[2], p[13]);
- std::swap(p[3], p[12]);
- std::swap(p[4], p[11]);
- std::swap(p[5], p[10]);
- std::swap(p[6], p[9]);
- std::swap(p[7], p[8]);
+ unionVal.floatVal = src;
- return src;
+ return unionVal.intVal;
+#endif
+}
+
+/*! \ingroup GrpBaseBaseMiscFn
+ */
+inline
+OSG::UInt64 osgHostToNetFP(const OSG::Real64 src)
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+ return OSG::osgSwapBytesFP(src);
#else
- return src;
+ union
+ {
+ OSG::Real64 floatVal;
+ OSG::UInt64 intVal;
+ } unionVal;
+
+ unionVal.floatVal = src;
+
+ return unionVal.intVal;
#endif
}
-/*! Convert a value from little endian byte order to host byte order.
+/*! Convert a value from network byte order to host byte order.
- \param[in] src Input value in little endian byte order.
+ \param[in] src Input value in network byte order.
\return The input converted to host byte order.
- \note An actual conversion only happens on big endian architectures.
+ \note Network byte order is big endian, so an actual conversion only
+ happens on little endian architectures.
\ingroup GrpBaseBaseMiscFn
*/
template <class TypeT> inline
-TypeT osgLittleEndianToHost(TypeT src)
+TypeT osgNetToHost(const TypeT src)
{
#if BYTE_ORDER == LITTLE_ENDIAN
- return src;
+ return OSG::osgSwapBytes(src);
#else
- return osgSwapBytes(src);
+ return src;
#endif
}
/*! \ingroup GrpBaseBaseMiscFn
*/
-template <> inline
-OSG::Real128 osgLittleEndianToHost<Real128>(OSG::Real128 src)
+inline
+OSG::Real32 osgNetToHostFP(const OSG::UInt32 src)
{
#if BYTE_ORDER == LITTLE_ENDIAN
- return src;
+ return OSG::osgSwapBytesFP(src);
#else
- char *p = reinterpret_cast<char*>(&src);
+ union
+ {
+ OSG::Real32 floatVal;
+ OSG::UInt32 intVal;
+ } unionVal;
- std::swap(p[0], p[15]);
- std::swap(p[1], p[14]);
- std::swap(p[2], p[13]);
- std::swap(p[3], p[12]);
- std::swap(p[4], p[11]);
- std::swap(p[5], p[10]);
- std::swap(p[6], p[9]);
- std::swap(p[7], p[8]);
+ unionVal.intVal = src;
- return src;
+ return unionVal.floatVal;
#endif
}
-/*! Convert a value from host byte order to network byte order.
-
- \param[in] src Input value in host byte order.
- \return The input converted to network byte order.
-
- \note Network byte order is big endian, so an actual conversion only
- happens on little endian architectures.
-
- \ingroup GrpBaseBaseMiscFn
+/*! \ingroup GrpBaseBaseMiscFn
*/
-template <class TypeT> inline
-TypeT osgHostToNet(const TypeT src)
+inline
+OSG::Real64 osgNetToHostFP(const OSG::UInt64 src)
{
- return OSG::osgHostToBigEndian(src);
-}
-
-/*! Convert a value from network byte order to host byte order.
-
- \param[in] src Input value in network byte order.
- \return The input converted to host byte order.
+#if BYTE_ORDER == LITTLE_ENDIAN
+ return OSG::osgSwapBytesFP(src);
+#else
+ union
+ {
+ OSG::Real64 floatVal;
+ OSG::UInt64 intVal;
+ } unionVal;
- \note Network byte order is big endian, so an actual conversion only
- happens on little endian architectures.
+ unionVal.intVal = src;
- \ingroup GrpBaseBaseMiscFn
- */
-template <class TypeT> inline
-TypeT osgNetToHost(const TypeT src)
-{
- return OSG::osgBigEndianToHost(src);
+ return unionVal.floatVal;
+#endif
}
// host to network
@@ -3231,7 +3241,13 @@ OSG::UInt64 osghtonll(OSG::UInt64 src)
inline
OSG::Real32 osghtonf(OSG::Real32 src)
{
- return OSG::osgHostToNet<Real32>(src);
+#if BYTE_ORDER == LITTLE_ENDIAN
+ UInt8 *p = reinterpret_cast<UInt8 *>(&src);
+ std::swap(p[0], p[3]);
+ std::swap(p[1], p[2]);
+#endif
+
+ return src;
}
/*! Convert a Real64 from host byte order to network byte order.
@@ -3249,7 +3265,15 @@ OSG::Real32 osghtonf(OSG::Real32 src)
inline
OSG::Real64 osghtond(OSG::Real64 src)
{
- return OSG::osgHostToNet<Real64>(src);
+#if BYTE_ORDER == LITTLE_ENDIAN
+ UInt8 *p = reinterpret_cast<UInt8 *>(&src);
+ std::swap(p[0], p[7]);
+ std::swap(p[1], p[6]);
+ std::swap(p[2], p[5]);
+ std::swap(p[3], p[4]);
+#endif
+
+ return src;
}
/*! Convert a Real128 from host byte order to network byte order.
@@ -3267,7 +3291,19 @@ OSG::Real64 osghtond(OSG::Real64 src)
inline
OSG::Real128 osghtondd(OSG::Real128 src)
{
- return OSG::osgHostToNet<Real128>(src);
+#if BYTE_ORDER == LITTLE_ENDIAN
+ UInt8 *p = reinterpret_cast<UInt8 *>(&src);
+ std::swap(p[0], p[15]);
+ std::swap(p[1], p[14]);
+ std::swap(p[2], p[13]);
+ std::swap(p[3], p[12]);
+ std::swap(p[4], p[11]);
+ std::swap(p[5], p[10]);
+ std::swap(p[6], p[9]);
+ std::swap(p[7], p[8]);
+#endif
+
+ return src;
}
// network to host
@@ -3287,7 +3323,7 @@ OSG::Real128 osghtondd(OSG::Real128 src)
inline
UInt16 osgntohs(UInt16 src)
{
- return OSG::osgNetToHost<UInt16>(src);
+ return osghtons(src);
}
/*! Convert a UInt32 from network byte order to host byte order.
@@ -3305,7 +3341,7 @@ UInt16 osgntohs(UInt16 src)
inline
OSG::UInt32 osgntohl(OSG::UInt32 src)
{
- return OSG::osgNetToHost<UInt32>(src);
+ return osgntohl(src);
}
/*! Convert a UInt64 from network byte order to host byte order.
@@ -3323,7 +3359,7 @@ OSG::UInt32 osgntohl(OSG::UInt32 src)
inline
OSG::UInt64 osgntohll(OSG::UInt64 src)
{
- return OSG::osgNetToHost<UInt64>(src);
+ return osghtonll(src);
}
/*! Convert a Real32 from network byte order to host byte order.
@@ -3341,7 +3377,7 @@ OSG::UInt64 osgntohll(OSG::UInt64 src)
inline
OSG::Real32 osgntohf(OSG::Real32 src)
{
- return OSG::osgNetToHost<Real32>(src);
+ return osghtonf(src);
}
/*! Convert a OSG::Real64 from network byte order to host byte order.
@@ -3359,7 +3395,7 @@ OSG::Real32 osgntohf(OSG::Real32 src)
inline
OSG::Real64 osgntohd(OSG::Real64 src)
{
- return OSG::osgNetToHost<Real64>(src);
+ return osghtond(src);
}
/*! Convert a Real128 from network byte order to host byte order.
@@ -3377,10 +3413,9 @@ OSG::Real64 osgntohd(OSG::Real64 src)
inline
OSG::Real128 osgntohdd(OSG::Real128 src)
{
- return OSG::osgNetToHost<Real128>(src);
+ return osghtondd(src);
}
-
/*! \} */
/*---------------------------------------------------------------------*/
/*! \name C strings */
diff --git a/Source/Base/Base/OSGExceptionBinaryDataHandler.h b/Source/Base/Base/OSGExceptionBinaryDataHandler.h
index 6a34cce..791b6a9 100644
--- a/Source/Base/Base/OSGExceptionBinaryDataHandler.h
+++ b/Source/Base/Base/OSGExceptionBinaryDataHandler.h
@@ -116,7 +116,6 @@ class OSG_BASE_DLLMAPPING ExceptionBinaryDataHandler
void putValue (const Fixed32 &value );
void putValue (const Real32 &value );
void putValue (const Real64 &value );
- void putValue (const Real128 &value );
void putValue (const std::string &value );
#ifdef OSG_GLENUM_NEQ_UINT32
void putValue (const GLenum &value );
@@ -135,7 +134,6 @@ class OSG_BASE_DLLMAPPING ExceptionBinaryDataHandler
void putValues (const Fixed32 *value, UInt32 size);
void putValues (const Real32 *value, UInt32 size);
void putValues (const Real64 *value, UInt32 size);
- void putValues (const Real128 *value, UInt32 size);
void putValues (const std::string *value, UInt32 size);
#ifdef OSG_GLENUM_NEQ_UINT32
void putValues (const GLenum *value, UInt32 size);
@@ -162,7 +160,6 @@ class OSG_BASE_DLLMAPPING ExceptionBinaryDataHandler
void getValue (Fixed32 &value ) throw (ReadError);
void getValue (Real32 &value ) throw (ReadError);
void getValue (Real64 &value ) throw (ReadError);
- void getValue (Real128 &value ) throw (ReadError);
void getValue (std::string &value ) throw (ReadError);
#ifdef OSG_GLENUM_NEQ_UINT32
void getValue (GLenum &value ) throw (ReadError);
@@ -181,7 +178,6 @@ class OSG_BASE_DLLMAPPING ExceptionBinaryDataHandler
void getValues (Fixed32 *value, UInt32 size) throw (ReadError);
void getValues (Real32 *value, UInt32 size) throw (ReadError);
void getValues (Real64 *value, UInt32 size) throw (ReadError);
- void getValues (Real128 *value, UInt32 size) throw (ReadError);
void getValues (std::string *value, UInt32 size) throw (ReadError);
#ifdef OSG_GLENUM_NEQ_UINT32
void getValues (GLenum *value, UInt32 size) throw (ReadError);
diff --git a/Source/Base/Base/OSGExceptionBinaryDataHandler.inl b/Source/Base/Base/OSGExceptionBinaryDataHandler.inl
index fc27a19..ac42b3a 100644
--- a/Source/Base/Base/OSGExceptionBinaryDataHandler.inl
+++ b/Source/Base/Base/OSGExceptionBinaryDataHandler.inl
@@ -143,28 +143,19 @@ void ExceptionBinaryDataHandler::putValue(const Fixed32 &value)
inline
void ExceptionBinaryDataHandler::putValue(const Real32 &value)
{
- Real32 v = osgHostToNet<Real32>(value);
+ UInt32 v = osgHostToNetFP(value);
- put(&v, sizeof(Real32));
+ put(&v, sizeof(UInt32));
}
inline
void ExceptionBinaryDataHandler::putValue(const Real64 &value)
{
- Real64 v = osgHostToNet<Real64>(value);
+ UInt64 v = osgHostToNetFP(value);
- put(&v, sizeof(Real64));
+ put(&v, sizeof(UInt64));
}
-inline
-void ExceptionBinaryDataHandler::putValue(const Real128 &value)
-{
- Real128 v = osgHostToNet<Real128>(value);
-
- // sizeof(Real128) != 16 on most arch - force it.
- put(&v, 16);
-}
-
inline
void ExceptionBinaryDataHandler::putValue(const std::string &value)
{
@@ -400,25 +391,6 @@ void ExceptionBinaryDataHandler::putValues(const Real64 *value, UInt32 size)
}
}
-inline
-void ExceptionBinaryDataHandler::putValues(const Real128 *value, UInt32 size)
-{
-#if BYTE_ORDER == LITTLE_ENDIAN
- if(_networkOrder == true)
- {
- for(UInt32 i = 0; i < size; ++i)
- {
- putValue(value[i]);
- }
- }
- else
-#endif
- {
- // sizeof(Real128) != 16 on most arch - force it.
- put(value, size * 16);
- }
-}
-
inline
void ExceptionBinaryDataHandler::putValues(const std::string *value,
UInt32 size )
@@ -544,26 +516,19 @@ void ExceptionBinaryDataHandler::getValue(Fixed32 &value) throw (ReadError)
inline
void ExceptionBinaryDataHandler::getValue(Real32 &value) throw (ReadError)
{
- get(&value, sizeof(Real32));
+ UInt32 v;
+ get(&v, sizeof(UInt32));
- value = osgNetToHost<Real32>(value);
+ value = osgNetToHostFP(v);
}
inline
void ExceptionBinaryDataHandler::getValue(Real64 &value) throw (ReadError)
{
- get(&value, sizeof(Real64));
+ UInt64 v;
+ get(&v, sizeof(UInt64));
- value = osgNetToHost<Real64>(value);
-}
-
-inline
-void ExceptionBinaryDataHandler::getValue(Real128 &value) throw (ReadError)
-{
- // sizeof(Real128) != 16 on most arch - force it.
- get(&value, 16);
-
- value = osgNetToHost<Real128>(value);
+ value = osgNetToHostFP(v);
}
inline
@@ -773,10 +738,7 @@ void ExceptionBinaryDataHandler::getValues(Real32 *value,
#if BYTE_ORDER == LITTLE_ENDIAN
if(_networkOrder == true)
{
- for(UInt32 i = 0; i < size; ++i)
- {
- value[i] = osgNetToHost<Real32>(value[i]);
- }
+ osgSwapMem<sizeof(Real32)>(value, size);
}
#endif
}
@@ -790,27 +752,7 @@ void ExceptionBinaryDataHandler::getValues(Real64 *value,
#if BYTE_ORDER == LITTLE_ENDIAN
if(_networkOrder == true)
{
- for(UInt32 i = 0; i < size; ++i)
- {
- value[i] = osgNetToHost<Real64>(value[i]);
- }
- }
-#endif
-}
-
-inline
-void ExceptionBinaryDataHandler::getValues(Real128 *value,
- UInt32 size) throw (ReadError)
-{
- get(value, size * sizeof(UInt64) * 2);
-
-#if BYTE_ORDER == LITTLE_ENDIAN
- if(_networkOrder == true)
- {
- for(UInt32 i = 0; i < size; ++i)
- {
- value[i] = osgNetToHost<Real128>(value[i]);
- }
+ osgSwapMem<sizeof(Real64)>(value, size);
}
#endif
}
diff --git a/Source/Base/Network/Base/OSGBinaryMessage.inl b/Source/Base/Network/Base/OSGBinaryMessage.inl
index 1b6b51a..77081c4 100644
--- a/Source/Base/Network/Base/OSGBinaryMessage.inl
+++ b/Source/Base/Network/Base/OSGBinaryMessage.inl
@@ -100,7 +100,8 @@ inline void BinaryMessage::putString(const std::string &value)
inline void BinaryMessage::putReal32(const Real32 value)
{
- Real32 net = osgHostToNet<Real32>(value);
+ UInt32 net = osgHostToNetFP(value);
+
_buffer.insert(_buffer.end(),
reinterpret_cast<UInt8*>(&net),
reinterpret_cast<UInt8*>(&net) + sizeof(net));
@@ -170,9 +171,9 @@ inline void BinaryMessage::getString(std::string &value)
inline void BinaryMessage::getReal32(Real32 &value)
{
- Real32 net = *reinterpret_cast<Real32*>(&_buffer[_pos]);
- value = osgNetToHost<Real32>(net);
- _pos += sizeof(net);
+ UInt32 net = getUInt32();
+
+ value = osgNetToHostFP(net);
}
inline UInt32 BinaryMessage::getUInt32(void)
diff --git a/Source/System/FileIO/OpenFlight/OSGOFRecords.cpp b/Source/System/FileIO/OpenFlight/OSGOFRecords.cpp
index c4ed066..8930aa1 100644
--- a/Source/System/FileIO/OpenFlight/OSGOFRecords.cpp
+++ b/Source/System/FileIO/OpenFlight/OSGOFRecords.cpp
@@ -324,7 +324,7 @@ UInt32 OFRecord::readVal(std::istream &is, ValueT &val)
{
is.read(reinterpret_cast<char *>(&val), sizeof(ValueT));
- val = osgBigEndianToHost(val);
+ val = osgNetToHost<ValueT>(val);
return sizeof(ValueT);
}
@@ -345,6 +345,28 @@ UInt32 OFRecord::readVal<UInt8>(std::istream &is, UInt8 &val)
return sizeof(UInt8);
}
+template <>
+UInt32 OFRecord::readVal<Real32>(std::istream &is, Real32 &val)
+{
+ UInt32 v;
+ is.read(reinterpret_cast<char *>(&v), sizeof(UInt32));
+
+ val = osgNetToHostFP(v);
+
+ return sizeof(Real32);
+}
+
+template <>
+UInt32 OFRecord::readVal<Real64>(std::istream &is, Real64 &val)
+{
+ UInt64 v;
+ is.read(reinterpret_cast<char *>(&v), sizeof(UInt64));
+
+ val = osgNetToHostFP(v);
+
+ return sizeof(Real64);
+}
+
OFRecord::OFRecord(const OFRecordHeader &oHeader) :
Inherited( ),
_sLength (oHeader.sLength)
@@ -986,10 +1008,7 @@ bool OFVertexPaletteRecord::read(std::istream &is, OFDatabase &oDB)
static std::vector<char> tmpBuf;
Int32 iFullLength;
-
- is.read(reinterpret_cast<char *>(&iFullLength), 4);
-
- iFullLength = osgBigEndianToHost(iFullLength);
+ Inherited::readVal(is, iFullLength);
Int32 iRead = 0;
diff --git a/Source/System/FileIO/OpenFlight/OSGOFRecords.h b/Source/System/FileIO/OpenFlight/OSGOFRecords.h
index a838fa9..d834fa3 100644
--- a/Source/System/FileIO/OpenFlight/OSGOFRecords.h
+++ b/Source/System/FileIO/OpenFlight/OSGOFRecords.h
@@ -79,8 +79,8 @@ struct OFRecordHeader
is.read(reinterpret_cast<char *>(&sOpCode), 2);
is.read(reinterpret_cast<char *>(&sLength), 2);
- sOpCode = osgBigEndianToHost(sOpCode);
- sLength = osgBigEndianToHost(sLength);
+ sOpCode = osgNetToHost(sOpCode);
+ sLength = osgNetToHost(sLength);
// fprintf(stderr, "opcode %hu, length %hu\n", sOpCode, sLength);
diff --git a/Source/System/FileIO/STL/OSGSTLSceneFileType.cpp b/Source/System/FileIO/STL/OSGSTLSceneFileType.cpp
index 709793f..7305990 100644
--- a/Source/System/FileIO/STL/OSGSTLSceneFileType.cpp
+++ b/Source/System/FileIO/STL/OSGSTLSceneFileType.cpp
@@ -334,14 +334,19 @@ bool STLSceneFileType::readBinary(std::istream &is, STLFaceList& theFaces, std::
Real32 STLSceneFileType::readFloat(std::istream& is, bool bigEndian) const
{
- Real32 result = 0.f;
- char buffer[4];
-
- is.read(&buffer[0], 4);
- std::memcpy(reinterpret_cast<char *>(&result), buffer, 4);
+ Real32 result = 0.f;
if(bigEndian)
- result = osgNetToHost(result);
+ {
+ UInt32 buffer;
+
+ is.read(reinterpret_cast<char *>(&buffer), sizeof(Real32));
+ result = osgNetToHostFP(buffer);
+ }
+ else
+ {
+ is.read(reinterpret_cast<char *>(&result), sizeof(Real32));
+ }
return result;
}
diff --git a/Source/System/Image/FileIO/OSGDBImageFileType.cpp b/Source/System/Image/FileIO/OSGDBImageFileType.cpp
index b502e91..4897940 100644
--- a/Source/System/Image/FileIO/OSGDBImageFileType.cpp
+++ b/Source/System/Image/FileIO/OSGDBImageFileType.cpp
@@ -801,9 +801,7 @@ bool DBImageFileType::read( Image *pImage,
&clampMin<Int16, -100, 0> >(pImage);
break;
case 2:
- swapAndConvertImageByteOrder<
- Real32,
- &doNothing<Real32> >(pImage);
+ swapImageByteOrder<Real32>(pImage);
break;
default:
break;
diff --git a/Source/System/Image/OSGImageFunctions.inl b/Source/System/Image/OSGImageFunctions.inl
index ebdb1bc..064c200 100644
--- a/Source/System/Image/OSGImageFunctions.inl
+++ b/Source/System/Image/OSGImageFunctions.inl
@@ -195,14 +195,10 @@ void swapImageByteOrder(Image * const pImage)
if(pImage == NULL)
return;
- ValueT *pData = reinterpret_cast<ValueT *>(pImage->editData());
+ void *pData = static_cast<void *>(pImage->editData());
+ UInt32 uiSize = pImage->getSize() / sizeof(ValueT);
- UInt32 uiSize = pImage->getSize() / sizeof(ValueT);
-
- for(UInt32 i = 0; i < uiSize; ++i)
- {
- pData[i] = osgSwapBytes<ValueT>(pData[i]);
- }
+ osgSwapMem<sizeof(ValueT)>(pData, uiSize);
}
template<class ValueT, ValueT (*ConvF)(ValueT)> inline
@@ -211,13 +207,13 @@ void swapAndConvertImageByteOrder(Image * const pImage)
if(pImage == NULL)
return;
- ValueT *pData = reinterpret_cast<ValueT *>(pImage->editData());
-
- UInt32 uiSize = pImage->getSize() / sizeof(ValueT);
+ ValueT *pData = reinterpret_cast<ValueT *>(pImage->editData());
+ UInt32 uiSize = pImage->getSize() / sizeof(ValueT);
for(UInt32 i = 0; i < uiSize; ++i)
{
- pData[i] = ConvF(osgSwapBytes<ValueT>(pData[i]));
+ osgSwapMem<sizeof(ValueT)>(&pData[i], 1);
+ pData[i] = ConvF(pData[i]);
}
}
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#if 1
#define OSG_UINT64_LITERAL(value) value##ULL
#else
#define OSG_UINT64_LITERAL(value) value##U
#endif
typedef char Int8;
typedef int Int32;
typedef long int Int64;
typedef unsigned char UInt8;
typedef unsigned int UInt32;
typedef unsigned long int UInt64;
typedef float Real32;
typedef double Real64;
template <class TypeT> inline
TypeT swapBytes(TypeT src);
template <> inline
UInt32 swapBytes(UInt32 src);
inline UInt32 swapBytesFP(Real32 src);
inline Real32 swapBytesFP(UInt32 src);
template <UInt8 ElemSize> inline
void swapMem(void *mem, UInt32 count);
template <> inline
void swapMem<4>(void *mem, UInt32 count);
void doput(const void *mem, std::size_t size);
Real32 makeR32(void);
int main(int, char *[])
{
std::cout << "sizeof(UInt32) = " << sizeof(UInt32)
<< "\nsizeof(Int32) = " << sizeof(Int32)
<< "\nsizeof(UInt64) = " << sizeof(UInt64)
<< "\nsizeof(Int64) = " << sizeof(Int64)
<< "\nsizeof(Real32) = " << sizeof(Real32)
<< "\nsizeof(Real64) = " << sizeof(Real64) << std::endl;
UInt32 ui32 = 0;
Real32 r32 = makeR32();
std::cout << std::hex
<< "ui32 = " << ui32
<< "\nr32 = " << r32
<< std::endl;
doput(&ui32, sizeof(UInt32));
doput(&r32, sizeof(Real32));
std::cout << " === SWAP ===\n";
//r32 = swapBytes (r32); // compile/link error - expected!
ui32 = swapBytesFP(r32);
//swapMem<sizeof(Real32)>(&r32, 1); // violates aliasing rules (access to Real32 through UInt32)
// and the compiler is allowed to keep r32 in a register
// across the call
std::cout << std::hex
<< "ui32 = " << ui32
<< "\nr32 = " << r32
<< std::endl;
doput(&ui32, sizeof(UInt32));
doput(&r32, sizeof(Real32));
std::cout << " === SWAP ===\n";
//r32 = swapBytes (r32); // compile/link error - expected!
r32 = swapBytesFP(ui32);
//swapMem<sizeof(Real32)>(&r32, 1); // violates aliasing rules (access to Real32 through UInt32)
// and the compiler is allowed to keep r32 in a register
// across the call
std::cout << std::hex
<< "ui32 = " << ui32
<< "\nr32 = " << r32
<< std::endl;
doput(&ui32, sizeof(UInt32));
doput(&r32, sizeof(Real32));
return 0;
}
// =========================================================
template <>
UInt32 swapBytes(UInt32 src)
{
return (((src & 0x000000ff) << 24) |
((src & 0x0000ff00) << 8) |
((src & 0x00ff0000) >> 8) |
((src & 0xff000000) >> 24) );
}
UInt32 swapBytesFP(Real32 src)
{
union
{
UInt32 intVal;
Real32 floatVal;
} unionVal;
unionVal.floatVal = src;
return swapBytes(unionVal.intVal);
}
Real32 swapBytesFP(UInt32 src)
{
union
{
UInt32 intVal;
Real32 floatVal;
} unionVal;
unionVal.intVal = swapBytes(src);
return unionVal.floatVal;
}
template <>
void swapMem<4>(void *mem, UInt32 count)
{
UInt32 *p = static_cast<UInt32 *>(mem);
for(UInt32 i = 0; i < count; ++i)
{
p[i] = swapBytes(p[i]);
}
}
void doput(const void *mem, std::size_t size)
{
char *buffer = new char[size];
std::memcpy(buffer, mem, size);
for(std::size_t i = 0; i < size; ++i)
{
std::cout << std::hex << std::setw(2) << static_cast<unsigned short>(static_cast<unsigned char>(buffer[i])) << " ";
}
std::cout << std::endl;
delete [] buffer;
}
Real32 makeR32(void)
{
union
{
unsigned char charVal[4];
UInt32 intVal;
} u1;
u1.charVal[0] = 0xff;
u1.charVal[1] = 0x91;
u1.charVal[2] = 0xea;
u1.charVal[3] = 0x43;
union
{
UInt32 intVal;
Real32 floatVal;
} u2;
u2.intVal = u1.intVal;
return u2.floatVal;
}
------------------------------------------------------------------------------
The Palm PDK Hot Apps Program offers developers who use the
Plug-In Development Kit to bring their C/C++ apps to Palm for a share
of $1 Million in cash or HP Products. Visit us here for more details:
http://p.sf.net/sfu/dev2dev-palm
_______________________________________________
Opensg-users mailing list
Opensg-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensg-users