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

Reply via email to