Adapt structpack to big-endian targets

This commit is contained in:
Iliyas Jorio 2022-09-02 20:50:49 +02:00
parent 98142aa132
commit 191500dec1
2 changed files with 145 additions and 22 deletions

View File

@ -111,7 +111,7 @@ static int Unpack(const char* format, char* buffer)
return totalBytes;
}
int ByteswapStructs(const char* format, int structSize, int structCount, void* buffer)
int UnpackStructs(const char* format, int structSize, int structCount, void* buffer)
{
char* byteBuffer = (char*) buffer;
int totalBytes = 0;

View File

@ -2,11 +2,17 @@
#include <stdint.h>
#if __BIG_ENDIAN__
#define kIsBigEndianNative 1
#else
#define kIsBigEndianNative 0
#endif
#ifdef __cplusplus
#include <algorithm>
template<typename T> T ByteswapScalar(T x)
template<typename T> T UnpackBEScalar(T x)
{
#if __BIG_ENDIAN__
return x;
@ -17,57 +23,174 @@ template<typename T> T ByteswapScalar(T x)
#endif
}
template<typename T> T UnpackLEScalar(T x)
{
#if !(__BIG_ENDIAN__)
return x;
#else
char* b = (char*)&x;
std::reverse(b, b + sizeof(T));
return x;
#endif
}
#ifdef __cplusplus
extern "C" {
#endif
int ByteswapStructs(const char* format, int structSize, int structCount, void* buffer);
#endif // __cplusplus
//-----------------------------------------------------------------------------
// Byteswap an array of scalars
int ByteswapInts(int intSize, int intCount, void* buffer);
static inline uint16_t Byteswap16(const void* data)
static inline int UnpackIntsBE(int intSize, int intCount, void* buffer)
{
#if __BIG_ENDIAN__
// no-op on big-endian systems
(void) buffer;
return intCount * intSize;
#else
return ByteswapInts(intSize, intCount, buffer);
#endif
}
static inline int UnpackIntsLE(int intSize, int intCount, void* buffer)
{
#if __BIG_ENDIAN__
return ByteswapInts(intSize, intCount, buffer);
#else
// no-op on little-endian systems
(void) buffer;
return intCount * intSize;
#endif
}
//-----------------------------------------------------------------------------
// Unpack an array of structures
int UnpackStructs(const char* format, int structSize, int structCount, void* buffer);
//-----------------------------------------------------------------------------
// Unpack basic unsigned scalars
static inline uint16_t UnpackU16BE(const void* data)
{
#if __BIG_ENDIAN__
// no-op on big-endian systems
return *(const uint16_t*) data;
#else
const uint8_t* p = (uint8_t*) data;
return ( p[0] << 8 )
| ( p[1] );
#endif
}
static inline int16_t Byteswap16Signed(const void* data)
static inline uint16_t UnpackU16LE(const void* data)
{
return (int16_t) Byteswap16(data);
#if __BIG_ENDIAN__
const uint8_t* p = (uint8_t*) data;
return ( p[0] )
| ( p[1] << 8 );
#else
// no-op on little-endian systems
return *(const uint16_t*) data;
#endif
}
static inline int32_t Byteswap16SignedRW(void* data)
{
int16_t result = Byteswap16Signed(data);
*(int16_t*) data = result;
return result;
}
static inline uint32_t Byteswap32(const void* data)
static inline uint32_t UnpackU32BE(const void* data)
{
#if __BIG_ENDIAN_
// no-op on big-endian systems
return *(const uint32_t*) data;
#else
const uint8_t* p = (uint8_t*) data;
return ( p[0] << 24 )
| ( p[1] << 16 )
| ( p[2] << 8 )
| ( p[3] );
#endif
}
static inline int32_t Byteswap32Signed(const void* data)
static inline uint32_t UnpackU32LE(const void* data)
{
return (int32_t) Byteswap32(data);
#if __BIG_ENDIAN__
const uint8_t* p = (uint8_t*) data;
return ( p[0] )
| ( p[1] << 8 )
| ( p[2] << 16 )
| ( p[3] << 24 );
#else
// no-op on little-endian systems
return *(const uint32_t*) data;
#endif
}
static inline int32_t Byteswap32SignedRW(void* data)
//-----------------------------------------------------------------------------
// Swap in place
static inline uint16_t UnpackU16BEInPlace(void* data)
{
int32_t result = Byteswap32Signed(data);
*(int32_t*) data = result;
#if __BIG_ENDIAN__
// no-op on big-endian systems
return *(uint16_t*) data;
#else
uint16_t result = UnpackU16BE(data);
*(uint16_t*) data = result;
return result;
#endif
}
static inline uint16_t UnpackU16LEInPlace(void* data)
{
#if __BIG_ENDIAN__
uint16_t result = UnpackU16LE(data);
*(uint16_t*) data = result;
return result;
#else
// no-op on little-endian systems
return *(uint16_t*) data;
#endif
}
static inline uint32_t UnpackU32BEInPlace(void* data)
{
#if __BIG_ENDIAN__
// no-op on big-endian systems
return *(uint32_t*) data;
#else
uint32_t result = UnpackU32BE(data);
*(uint32_t*) data = result;
return result;
#endif
}
static inline uint32_t UnpackU32LEInPlace(void* data)
{
#if __BIG_ENDIAN__
uint32_t result = UnpackU32LE(data);
*(uint32_t*) data = result;
return result;
#else
// no-op on little-endian systems
return *(uint32_t*) data;
#endif
}
//-----------------------------------------------------------------------------
// Signed variants
static inline int16_t UnpackI16BE(const void* data) { return (int16_t) UnpackU16BE(data); }
static inline int32_t UnpackI32BE(const void* data) { return (int32_t) UnpackU32BE(data); }
static inline int16_t UnpackI16LE(const void* data) { return (int16_t) UnpackU16LE(data); }
static inline int32_t UnpackI32LE(const void* data) { return (int32_t) UnpackU32LE(data); }
static inline int16_t UnpackI16BEInPlace(void* data) { return (int16_t) UnpackU16BEInPlace(data); }
static inline int32_t UnpackI32BEInPlace(void* data) { return (int32_t) UnpackU32BEInPlace(data); }
static inline int16_t UnpackI16LEInPlace(void* data) { return (int16_t) UnpackU16LEInPlace(data); }
static inline int32_t UnpackI32LEInPlace(void* data) { return (int32_t) UnpackU32LEInPlace(data); }
#ifdef __cplusplus
}
#endif