Seaside/SpyCustom/byteswap.h
2021-06-16 16:08:23 +03:00

170 lines
3.6 KiB
C++

#ifndef BYTESWAP_H
#define BYTESWAP_H
#if defined(_WIN32)
#pragma once
#endif
#include "datamap.h"
class CByteswap
{
public:
CByteswap()
{
SetTargetBigEndian(IsMachineBigEndian());
}
void SwapFieldToTargetEndian(void* pOutputBuffer, void* pData, typedescription_t* pField);
void SwapFieldsToTargetEndian(void* pOutputBuffer, void* pBaseData, datamap_t* pDataMap);
template<typename T> inline void SwapFieldsToTargetEndian(T* pOutputBuffer, void* pBaseData, unsigned int objectCount = 1)
{
for (unsigned int i = 0; i < objectCount; ++i, ++pOutputBuffer)
{
SwapFieldsToTargetEndian((void*)pOutputBuffer, pBaseData, &T::m_DataMap);
pBaseData = (byte*)pBaseData + sizeof(T);
}
}
template<typename T> inline void SwapFieldsToTargetEndian(T* pOutputBuffer, unsigned int objectCount = 1)
{
SwapFieldsToTargetEndian<T>(pOutputBuffer, (void*)pOutputBuffer, objectCount);
}
static bool IsMachineBigEndian()
{
short nIsBigEndian = 1;
return (bool)(0 == *(char*)&nIsBigEndian);
}
inline void SetTargetBigEndian(bool bigEndian)
{
m_bBigEndian = bigEndian;
m_bSwapBytes = IsMachineBigEndian() != bigEndian;
}
inline void FlipTargetEndian(void)
{
m_bSwapBytes = !m_bSwapBytes;
m_bBigEndian = !m_bBigEndian;
}
inline void ActivateByteSwapping(bool bActivate)
{
SetTargetBigEndian(IsMachineBigEndian() != bActivate);
}
inline bool IsSwappingBytes(void)
{
return m_bSwapBytes;
}
inline bool IsTargetBigEndian(void)
{
return m_bBigEndian;
}
template<typename T> inline int SourceIsNativeEndian(T input, T nativeConstant)
{
if (input == nativeConstant)
return 1;
int output;
LowLevelByteSwap<T>(&output, &input);
if (output == nativeConstant)
return 0;
assert(0);
return -1;
}
template<typename T> inline void SwapBuffer(T* outputBuffer, T* inputBuffer = NULL, int count = 1)
{
assert(count >= 0);
assert(outputBuffer);
if (count <= 0 || !outputBuffer)
return;
if (inputBuffer == NULL)
{
inputBuffer = outputBuffer;
}
for (int i = 0; i < count; i++)
{
LowLevelByteSwap<T>(&outputBuffer[i], &inputBuffer[i]);
}
}
template<typename T> inline void SwapBufferToTargetEndian(T* outputBuffer, T* inputBuffer = NULL, int count = 1)
{
assert(count >= 0);
assert(outputBuffer);
if (count <= 0 || !outputBuffer)
return;
if (inputBuffer == NULL)
{
inputBuffer = outputBuffer;
}
if (!m_bSwapBytes || (sizeof(T) == 1))
{
if (!inputBuffer)
return;
memcpy(outputBuffer, inputBuffer, count * sizeof(T));
return;
}
for (int i = 0; i < count; i++)
{
LowLevelByteSwap<T>(&outputBuffer[i], &inputBuffer[i]);
}
}
private:
template<typename T> static void LowLevelByteSwap(T* output, T* input)
{
T temp = *output;
#if defined( _X360 )
DWORD* word = (DWORD*)input;
switch (sizeof(T))
{
case 8:
{
__storewordbytereverse(*word, 0, &temp);
__storewordbytereverse(*(word + 1), 4, &temp);
}
break;
case 4:
__storewordbytereverse(*word, 0, &temp);
break;
case 2:
__storeshortbytereverse(*input, 0, &temp);
break;
default:
Assert("Invalid size in CByteswap::LowLevelByteSwap" && 0);
}
#else
for (int i = 0; i < sizeof(T); i++)
{
((unsigned char*)&temp)[i] = ((unsigned char*)input)[sizeof(T) - (i + 1)];
}
#endif
Q_memcpy(output, &temp, sizeof(T));
}
unsigned int m_bSwapBytes : 1;
unsigned int m_bBigEndian : 1;
};
#endif