2.12.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Commit 506cba1c authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

rewrote EndianHelper to comply with gcc strict aliasing

parent ea21c6cd
......@@ -151,32 +151,23 @@ namespace campvis {
if (_endianess != localEndianess) {
// This is not the most beautiful design, but unfortunately swapEndian needs to know the number of bytes at compiletime...
switch (_type) {
case WeaklyTypedPointer::UINT8:
case WeaklyTypedPointer::UINT8: // fallthrough
case WeaklyTypedPointer::INT8:
for (size_t i = 0; i < numElements; ++i)
data[i] = EndianHelper::swapEndian(data[i]);
// nothing to do here.
break;
case WeaklyTypedPointer::UINT16:
case WeaklyTypedPointer::UINT16: // fallthrough
case WeaklyTypedPointer::INT16: {
int16_t* tmp = reinterpret_cast<int16_t*>(data);
for (size_t i = 0; i < numElements; ++i)
tmp[i] = EndianHelper::swapEndian(tmp[i]);
break;
}
case WeaklyTypedPointer::UINT32:
case WeaklyTypedPointer::INT32: {
int32_t* tmp = reinterpret_cast<int32_t*>(data);
for (size_t i = 0; i < numElements; ++i)
tmp[i] = EndianHelper::swapEndian(tmp[i]);
EndianHelper::swapEndian<2>(data + (2*i));
break;
}
case WeaklyTypedPointer::UINT32: // fallthrough
case WeaklyTypedPointer::INT32: // fallthrough
case WeaklyTypedPointer::FLOAT: {
float* tmp = reinterpret_cast<float*>(data);
for (size_t i = 0; i < numElements; ++i)
tmp[i] = EndianHelper::swapEndian(tmp[i]);
EndianHelper::swapEndian<4>(data + (4*i));
break;
}
......
......@@ -33,64 +33,7 @@
#include "tgt/logmanager.h"
#include "tgt/types.h"
/// Anonymous namespace for templated endian swapping helper methods
namespace {
// template
template<typename T, size_t N>
struct SwapHelper {
static inline T swap(T value) {
LERRORC("CAMPVis.Tools.EndianHelper", "Tried to call SwapHelper<T,N>::swap() with unsupported template arguments.");
return value;
}
};
template<typename T>
struct SwapHelper<T, 2> {
static inline T swap(T value) {
return (value>>8) | (value<<8);
}
};
template<typename T>
struct SwapHelper<T, 4> {
static inline T swap(T value) {
return (value>>24) |
((value<<8) & 0x00FF0000) |
((value>>8) & 0x0000FF00) |
(value<<24);
}
};
template<>
struct SwapHelper<float, 4> {
static inline float swap(float value) {
uint32_t tmp = SwapHelper<uint32_t, 4>::swap(*reinterpret_cast<uint32_t*>(&value));
return (*reinterpret_cast<float*>(&tmp));
}
};
template<typename T>
struct SwapHelper<T, 8> {
static inline T swap(T value) {
return (value>>56) |
((value<<40) & 0x00FF000000000000) |
((value<<24) & 0x0000FF0000000000) |
((value<<8) & 0x000000FF00000000) |
((value>>8) & 0x00000000FF000000) |
((value>>24) & 0x0000000000FF0000) |
((value>>40) & 0x000000000000FF00) |
(value<<56);
}
};
template<>
struct SwapHelper<double, 8> {
static inline double swap(double value) {
uint64_t tmp = SwapHelper<uint64_t, 4>::swap(*reinterpret_cast<uint64_t*>(&value));
return (*reinterpret_cast<double*>(&tmp));
}
};
}
#include <utility>
namespace campvis {
......@@ -117,13 +60,15 @@ namespace campvis {
}
/**
* Performs endian-swapping of \a value in respect of its size.
* \param value Value to perform endian-swapping on.
* \return Endian-swapped version of \a value.
* Performs in-place endian-swapping of value pointed to by \a value, supposing its size to be \a N bytes.
* \param value Pointer to the value to be endian-swapped.
* \tparam N Number of bytes of the value to be swapped.
*/
template<typename T>
static inline T swapEndian(T value) {
return SwapHelper<T, sizeof(T)>::swap(value);
template<size_t N>
static inline void swapEndian(char* value) {
for (size_t i = 0; i < N/2; ++i) {
std::swap(value[i], value[N-i-1]);
}
}
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment