summaryrefslogtreecommitdiffstats
path: root/src/uscxml/Convenience.h
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-11-16 00:10:01 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-11-16 00:10:01 (GMT)
commitc60cc4c17191bc432e89af914dde700724633b38 (patch)
treee9a0f6046d5baea970328d49d9d085149394ff76 /src/uscxml/Convenience.h
parent938befbf5dc08cc658d058cd2581314269bf4a27 (diff)
downloaduscxml-c60cc4c17191bc432e89af914dde700724633b38.zip
uscxml-c60cc4c17191bc432e89af914dde700724633b38.tar.gz
uscxml-c60cc4c17191bc432e89af914dde700724633b38.tar.bz2
Moved endian functions into convenience header
Diffstat (limited to 'src/uscxml/Convenience.h')
-rw-r--r--src/uscxml/Convenience.h146
1 files changed, 146 insertions, 0 deletions
diff --git a/src/uscxml/Convenience.h b/src/uscxml/Convenience.h
index 64abbda..f764d06 100644
--- a/src/uscxml/Convenience.h
+++ b/src/uscxml/Convenience.h
@@ -20,6 +20,8 @@
#ifndef CONVENIENCE_H_LU7GZ6CB
#define CONVENIENCE_H_LU7GZ6CB
+#include <boost/detail/endian.hpp>
+
namespace uscxml {
inline bool isnan(double x) {
return x != x;
@@ -57,6 +59,150 @@ inline bool iequals(const std::string& a, const std::string& b) {
return true;
}
+// see http://www.cplusplus.com/forum/general/27544/
+
+// Little-endian operating systems:
+//---------------------------------
+// Linux on x86, x64, Alpha and Itanium
+// Mac OS on x86, x64
+// Solaris on x86, x64, PowerPC
+// Tru64 on Alpha
+// Windows on x86, x64 and Itanium
+
+// Big-endian operating systems:
+//------------------------------
+// AIX on POWER
+// AmigaOS on PowerPC and 680x0
+// HP-UX on Itanium and PA-RISC
+// Linux on MIPS, SPARC, PA-RISC, POWER, PowerPC, and 680x0
+// Mac OS on PowerPC and 680x0
+// Solaris on SPARC
+
+/**
+Detect endianness, see http://stackoverflow.com/questions/809902/64-bit-ntohl-in-c
+union {
+ unsigned long long ull;
+ char c[8];
+} x;
+x.ull = 0x0123456789abcdef; // may need special suffix for ULL.
+*/
+
+enum endianness {
+ little_endian,
+ big_endian,
+ network_endian = big_endian,
+
+#if defined(BOOST_LITTLE_ENDIAN)
+ host_endian = little_endian
+#elif defined(BOOST_BIG_ENDIAN)
+ host_endian = big_endian
+#else
+#error "unable to determine system endianness"
+#endif
+};
+
+namespace detail {
+
+ template<typename T, size_t sz>
+ struct swap_bytes {
+ inline T operator()(T val) {
+ throw std::out_of_range("data size");
+ }
+ };
+
+ template<typename T>
+ struct swap_bytes<T, 1> {
+ inline T operator()(T val) {
+ return val;
+ }
+ };
+
+ template<typename T>
+ struct swap_bytes<T, 2> { // for 16 bit
+ inline T operator()(T val) {
+ return ((((val) >> 8) & 0xff) | (((val) & 0xff) << 8));
+ }
+ };
+
+ template<typename T>
+ struct swap_bytes<T, 4> { // for 32 bit
+ inline T operator()(T val) {
+#if defined(_USE_BUILTIN_BSWAPS) && defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4)
+ return __builtin_bswap32(val);
+#else
+ return ((((val) & 0xff000000) >> 24) |
+ (((val) & 0x00ff0000) >> 8) |
+ (((val) & 0x0000ff00) << 8) |
+ (((val) & 0x000000ff) << 24));
+#endif
+ }
+ };
+
+ template<>
+ struct swap_bytes<float, 4> {
+ inline float operator()(float val) {
+ uint32_t mem = swap_bytes<uint32_t, sizeof(uint32_t)>()(*(uint32_t*)&val);
+ return *(float*)&mem;
+ }
+ };
+
+ template<typename T>
+ struct swap_bytes<T, 8> { // for 64 bit
+ inline T operator()(T val) {
+#if defined(_USE_BUILTIN_BSWAPS) && defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4)
+ return __builtin_bswap64(val);
+#else
+ return ((((val) & 0xff00000000000000ull) >> 56) |
+ (((val) & 0x00ff000000000000ull) >> 40) |
+ (((val) & 0x0000ff0000000000ull) >> 24) |
+ (((val) & 0x000000ff00000000ull) >> 8 ) |
+ (((val) & 0x00000000ff000000ull) << 8 ) |
+ (((val) & 0x0000000000ff0000ull) << 24) |
+ (((val) & 0x000000000000ff00ull) << 40) |
+ (((val) & 0x00000000000000ffull) << 56));
+#endif
+ }
+ };
+
+ template<>
+ struct swap_bytes<double, 8> {
+ inline double operator()(double val) {
+ uint64_t mem = swap_bytes<uint64_t, sizeof(uint64_t)>()(*(uint64_t*)&val);
+ return *(double*)&mem;
+ }
+ };
+
+ template<endianness from, endianness to, class T>
+ struct do_byte_swap {
+ inline T operator()(T value) {
+ return swap_bytes<T, sizeof(T)>()(value);
+ }
+ };
+ // specialisations when attempting to swap to the same endianess
+ template<class T> struct do_byte_swap<little_endian, little_endian, T> {
+ inline T operator()(T value) {
+ return value;
+ }
+ };
+ template<class T> struct do_byte_swap<big_endian, big_endian, T> {
+ inline T operator()(T value) {
+ return value;
+ }
+ };
+
+} // namespace detail
+
+template<endianness from, endianness to, class T>
+inline T byte_swap(T value) {
+ // ensure the data is only 1, 2, 4 or 8 bytes
+ BOOST_STATIC_ASSERT(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8);
+ // ensure we're only swapping arithmetic types
+ BOOST_STATIC_ASSERT(boost::is_arithmetic<T>::value);
+
+ return detail::do_byte_swap<from, to, T>()(value);
+}
+
+
}