Files
epics-base/modules/libcom/src/osi/os/default/osdWireFormat.h
T
Andrew Johnson 3c99391d93 Added SPDX License ID to all EPICS-original source files
In some cases the license-identification header was missing,
so I added that as well. Replaced the remaining headers that
specifically identified "Versions 3.13.7 and higher".

Makefiles and the build system were deliberately excluded.
2020-08-03 11:53:01 -05:00

242 lines
7.0 KiB
C++

/*************************************************************************\
* Copyright (c) 2007 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author Jeffrey O. Hill
* johill@lanl.gov
*/
#ifndef osdWireFormat
#define osdWireFormat
#ifdef __SUNPRO_CC
# include <string.h>
#else
# include <cstring>
#endif
#include "epicsEndian.h"
//
// The default assumption is that the local floating point format is
// IEEE and that these routines only need to perform byte swapping
// as a side effect of copying an aligned operand into an unaligned
// network byte stream. OS specific code can provide a alternative
// for this file if that assumption is wrong.
//
//
// EPICS_CONVERSION_REQUIRED is set if either the byte order
// or the floating point word order are not exactly big endian.
// This can be set by hand above for a specific architecture
// should there be an architecture that is a weird middle endian
// ieee floating point format that is also big endian integer.
//
#if EPICS_BYTE_ORDER != EPICS_ENDIAN_BIG || EPICS_FLOAT_WORD_ORDER != EPICS_BYTE_ORDER
# if ! defined ( EPICS_CONVERSION_REQUIRED )
# define EPICS_CONVERSION_REQUIRED
# endif
#endif
//
// We still use a big endian wire format for CA consistent with the internet,
// but inconsistent with the vast majority of CPUs
//
template <>
inline void WireGet < epicsFloat64 > (
const epicsUInt8 * pWireSrc, epicsFloat64 & dst )
{
// copy through union here
// a) prevents over-aggressive optimization under strict aliasing rules
// b) doesnt preclude extra copy operation being optimized away
union {
epicsFloat64 _f;
epicsUInt32 _u[2];
} tmp;
# if EPICS_FLOAT_WORD_ORDER == EPICS_ENDIAN_LITTLE
WireGet ( pWireSrc, tmp._u[1] );
WireGet ( pWireSrc + 4, tmp._u[0] );
# elif EPICS_FLOAT_WORD_ORDER == EPICS_ENDIAN_BIG
WireGet ( pWireSrc, tmp._u[0] );
WireGet ( pWireSrc + 4, tmp._u[1] );
# else
# error unsupported floating point word order
# endif
dst = tmp._f;
}
#if defined ( __GNUC__ ) && ( __GNUC__ == 4 && __GNUC_MINOR__ <= 0 )
template <>
inline void WireGet < epicsOldString > (
const epicsUInt8 * pWireSrc, epicsOldString & dst )
{
memcpy ( dst, pWireSrc, sizeof ( dst ) );
}
#else
inline void WireGet (
const epicsUInt8 * pWireSrc, epicsOldString & dst )
{
memcpy ( dst, pWireSrc, sizeof ( dst ) );
}
#endif
template <>
inline void WireSet < epicsFloat64 > (
const epicsFloat64 & src, epicsUInt8 * pWireDst )
{
// copy through union here
// a) prevents over-aggressive optimization under strict aliasing rules
// b) doesnt preclude extra copy operation being optimized away
union {
epicsFloat64 _f;
epicsUInt32 _u[2];
} tmp;
tmp._f = src;
# if EPICS_FLOAT_WORD_ORDER == EPICS_ENDIAN_LITTLE
WireSet ( tmp._u[1], pWireDst );
WireSet ( tmp._u[0], pWireDst + 4 );
# elif EPICS_FLOAT_WORD_ORDER == EPICS_ENDIAN_BIG
WireSet ( tmp._u[0], pWireDst );
WireSet ( tmp._u[1], pWireDst + 4 );
# else
# error unsupported floating point word order
# endif
}
#if defined ( __GNUC__ ) && ( __GNUC__ == 4 && __GNUC_MINOR__ <= 0 )
template <>
inline void WireSet < epicsOldString > (
const epicsOldString & src, epicsUInt8 * pWireDst )
{
memcpy ( pWireDst, src, sizeof ( src ) );
}
#else
inline void WireSet (
const epicsOldString & src, epicsUInt8 * pWireDst )
{
memcpy ( pWireDst, src, sizeof ( src ) );
}
#endif
template <>
inline void AlignedWireGet < epicsUInt16 > (
const epicsUInt16 & src, epicsUInt16 & dst )
{
# if EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE
dst = byteSwap ( src );
# elif EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG
dst = src;
# else
# error unsupported endian type
# endif
}
template <>
inline void AlignedWireGet < epicsUInt32 > (
const epicsUInt32 & src, epicsUInt32 & dst )
{
# if EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE
dst = byteSwap ( src );
# elif EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG
dst = src;
# else
# error unsupported endian type
# endif
}
template <>
inline void AlignedWireGet < epicsFloat64 > (
const epicsFloat64 & src, epicsFloat64 & dst )
{
// copy through union here
// a) prevents over-aggressive optimization under strict aliasing rules
// b) doesnt preclude extra copy operation being optimized away
union Swapper {
epicsUInt32 _u[2];
epicsFloat64 _f;
};
# if EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG && EPICS_FLOAT_WORD_ORDER == EPICS_BYTE_ORDER
dst = src;
# elif EPICS_FLOAT_WORD_ORDER == EPICS_ENDIAN_BIG
Swapper tmp;
tmp._f = src;
AlignedWireGet ( tmp._u[0], tmp._u[0] );
AlignedWireGet ( tmp._u[1], tmp._u[1] );
dst = tmp._f;
# elif EPICS_FLOAT_WORD_ORDER == EPICS_ENDIAN_LITTLE
Swapper srcu, dstu;
srcu._f = src;
AlignedWireGet ( srcu._u[1], dstu._u[0] );
AlignedWireGet ( srcu._u[0], dstu._u[1] );
dst = dstu._f;
# else
# error unsupported floating point word order
# endif
}
template <>
inline void AlignedWireSet < epicsUInt16 >
( const epicsUInt16 & src, epicsUInt16 & dst )
{
# if EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE
dst = byteSwap ( src );
# elif EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG
dst = src;
# else
# error undefined endian type
# endif
}
template <>
inline void AlignedWireSet < epicsUInt32 > (
const epicsUInt32 & src, epicsUInt32 & dst )
{
# if EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE
dst = byteSwap ( src );
# elif EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG
dst = src;
# else
# error undefined endian type
# endif
}
template <>
inline void AlignedWireSet < epicsFloat64 > (
const epicsFloat64 & src, epicsFloat64 & dst )
{
// copy through union here
// a) prevents over-aggressive optimization under strict aliasing rules
// b) doesnt preclude extra copy operation being optimized away
union Swapper {
epicsUInt32 _u[2];
epicsFloat64 _f;
};
# if EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG && EPICS_FLOAT_WORD_ORDER == EPICS_BYTE_ORDER
dst = src;
# elif EPICS_FLOAT_WORD_ORDER == EPICS_ENDIAN_BIG
Swapper tmp;
tmp._f = src;
AlignedWireSet ( tmp._u[0], tmp._u[0] );
AlignedWireSet ( tmp._u[1], tmp._u[1] );
dst = tmp._f;
# elif EPICS_FLOAT_WORD_ORDER == EPICS_ENDIAN_LITTLE
Swapper srcu, dstu;
srcu._f = src;
AlignedWireSet ( srcu._u[1], dstu._u[0] );
AlignedWireSet ( srcu._u[0], dstu._u[1] );
dst = dstu._f;
# else
# error unsupported floating point word order
# endif
}
#endif // osdWireFormat