Advertisement
fastman92

Endianness

Feb 6th, 2016
167
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.97 KB | None | 0 0
  1. /*
  2. * Copyright (C) 2016  fastman92 <fastman92@gmail.com>, website: http://fastman92.ml
  3. * Licensed under the MIT License, see LICENSE at top level directory.
  4. *
  5. */
  6.  
  7. #pragma once
  8.  
  9. template <typename T>
  10. using NoWrapper = T;
  11.  
  12. // Checks if currently running machine is little endian
  13. inline bool IsCurrentMachineLittleEndian()
  14. {
  15.     unsigned __int16 value = 0x0201;
  16.  
  17.     return *(unsigned __int8*)&value == 0x01;
  18. }
  19.  
  20. // Checks if currently running machine is little endian
  21. inline bool IsCurrentMachineBigEndian()
  22. {
  23.     unsigned __int16 value = 0x0201;
  24.  
  25.     return *(unsigned __int8*)&value == 0x02;
  26. }
  27.  
  28. // Endian base
  29. template<typename T, bool(*func)()> struct tEndianBase
  30. {
  31. private:
  32.     T value;
  33.  
  34. public:
  35.     // Default constructor
  36.     tEndianBase() {}
  37.  
  38.     // Copy constructor
  39.     tEndianBase(const tEndianBase& other)
  40.     {
  41.         *this = other;
  42.     }
  43.  
  44.     // Copy constructor
  45.     tEndianBase(const T& other)
  46.     {
  47.         *this = other;
  48.     }
  49.  
  50.     // Assignment
  51.     tEndianBase operator=(const tEndianBase other)
  52.     {
  53.         this->value = other.value;
  54.         return *this;
  55.     }
  56.  
  57.     // Assignment
  58.     tEndianBase operator=(const T other)
  59.     {
  60.         if (func())
  61.             this->value = other;
  62.         else
  63.             for (int i = 0; i < sizeof(T); i++)
  64.                 *((char*)&this->value + i) = *((char*)&other + sizeof(T) - i - 1);
  65.  
  66.         return *this;
  67.     }
  68.  
  69.     // Convert to base type
  70.     operator T()
  71.     {
  72.         T result;
  73.  
  74.         for (int i = 0; i < sizeof(T); i++)
  75.             *((char*)&result + i) = *((char*)&this->value + sizeof(T) - i - 1);
  76.  
  77.         return result;
  78.     }
  79. };
  80.  
  81. // Little endian
  82. template <class T>
  83. using tLittleEndian = tEndianBase<T, IsCurrentMachineBigEndian>;
  84.  
  85. // Big endian
  86. template <typename T>
  87. using tBigEndian = tEndianBase<T, IsCurrentMachineBigEndian>;
  88.  
  89. // Endian
  90. template <typename T> struct tVariedEndian
  91. {
  92.     T value;
  93.  
  94. public:
  95.    
  96.     // Sets value
  97.     void SetValue(const T value, bool bIsBigEndian)
  98.     {
  99.         if (bIsBigEndian != IsCurrentMachineBigEndianEndian())
  100.         {
  101.             for (int i = 0; i < sizeof(T); i++)
  102.                 *((char*)&this->value + i) = *((char*)&value + sizeof(T) - i - 1);
  103.         }
  104.         else
  105.             this->value = value;
  106.     }
  107.  
  108.     // Returns a value
  109.     const T GetValue(bool bIsBigEndian) const
  110.     {
  111.         if (bIsBigEndian != IsCurrentMachineBigEndianEndian())
  112.         {
  113.             T result;
  114.  
  115.             for (int i = 0; i < sizeof(T); i++)
  116.                 *((char*)&result + i) = *((char*)&this->value + sizeof(T) - i - 1);
  117.  
  118.             return result;
  119.         }
  120.         else
  121.             return this->value;
  122.     }
  123.  
  124.     // Returns value as little endian
  125.     const T GetValueAsLittleEndian() const
  126.     {
  127.         return GetValue(false);
  128.     }
  129.  
  130.     // Returns value as big endian
  131.     const T GetValueAsBigEndian() const
  132.     {
  133.         return GetValue(true);
  134.     }
  135. };
  136.  
  137. #define DEFINE_ENDIAN_STRUCTURE(normal_name, fields_name) \
  138. typedef fields_name<NoWrapper> CVector; \
  139. template<> class tVariedEndian<normal_name> : public fields_name<tVariedEndian>{}; \
  140. template<> class tEndianBase<normal_name, IsCurrentMachineLittleEndian> : public fields_name<tLittleEndian> {}; \
  141. template<> class tEndianBase<normal_name, IsCurrentMachineBigEndian> : public fields_name<tLittleEndian> {};
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement