Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

234 lines
9.7 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Copyright (C) Microsoft Corporation, 1997.
  4. //
  5. // File: lendian.hpp
  6. //
  7. // Contents: Templatized data types for access to unaligned scalar values.
  8. //
  9. //----------------------------------------------------------------------------
  10. // Implementation of LENDIAN data values. This works for simple scalar values.
  11. // This file is heavily macro-based. The intent is to do this work with arithmetic.
  12. // The functionality may be expressed much more consisely with memcpy, but I need an
  13. // implementation faster than that.
  14. // To create an LENDIAN type, use the MAKE_LENDIAN_TYPE macro. For example, if
  15. // you need an int_LENDIAN, say
  16. //
  17. // MAKE_LENDIAN_TYPE( int, 4 );
  18. //
  19. // Note that you need to specifiy the size of the base type. This is because the
  20. // amount of work to be done needs to be known by the preprocessor, where sizeof()
  21. // doesn't work.
  22. // To use: The intent is that replace occurances of "type LENDIAN" in your code
  23. // with "type_LENDIAN". It's simply a lexical change. You could automate this
  24. // change in order to easily convert code. More importantly, the reverse
  25. // transformation may also be easily automated, making it easier to merge with code
  26. // that doesn't use these types.
  27. // LENDIAN64: The unaligned 64 types are an optimization. They should only be used
  28. // for values over four bytes in size (e.g. __int64, double). They assume that the
  29. // pointers are aligned to 4-bytes, so that access may be done with two 32-bit
  30. // references, instead of 8 8-bit references.
  31. #ifndef __lendian_h__
  32. #define __lendian_h__
  33. #if defined(_MSC_VER) && !defined(BIG_ENDIAN)
  34. #define MAKE_LENDIAN_UNALIGNED_TYPE(base,size) typedef base UNALIGNED base##_LENDIAN_UNALIGNED
  35. #define MAKE_LENDIAN_TYPE(base,size) typedef base base##_LENDIAN_UNALIGNED; \
  36. typedef base base##_LENDIAN \
  37. //
  38. // Use MAKE_UNALIGNED64_TYPE for QWORD data that may only be DWORD aligned on 64-bit
  39. // machines. Only 64-bit architectures pay the penalty for accessing such data.
  40. //
  41. #if defined(ALPHA)
  42. # define MAKE_LENDIAN64_UNALIGNED_TYPE(base,size) typedef base UNALIGNED base##_LENDIAN64_UNALIGNED
  43. #else
  44. # define MAKE_LENDIAN64_UNALIGNED_TYPE(base,size) typedef base base##_LENDIAN64_UNALIGNED
  45. #endif
  46. #define MAKE_LENDIAN64_TYPE(base,size) typedef base base##_LENDIAN64
  47. #define MAKE_LENDIANPTR_UNALIGNED_TYPE(base) typedef base UNALIGNED *base##_LENDIANPTR_UNALIGNED
  48. #define MAKE_LENDIANPTR_TYPE(base) typedef base *base##_LENDIANPTR
  49. #else // _MSC_VER
  50. #define SET2(val,data) \
  51. data[1] = (val) >> 8, \
  52. data[0] = (val)
  53. #define GET2(data) \
  54. ( ( data[1] << 8 ) | \
  55. ( data[0] ) )
  56. #define SET4(val,data) \
  57. data[3] = (val) >> 24, \
  58. data[2] = (val) >> 16, \
  59. data[1] = (val) >> 8, \
  60. data[0] = (val)
  61. #define GET4(data) \
  62. ( ( data[3] << 24 ) | \
  63. ( data[2] << 16 ) | \
  64. ( data[1] << 8 ) | \
  65. ( data[0] ) )
  66. #define SET8(val,data) \
  67. data[7] = (val) >> 56, \
  68. data[6] = (val) >> 48, \
  69. data[5] = (val) >> 40, \
  70. data[4] = (val) >> 32, \
  71. data[3] = (val) >> 24, \
  72. data[2] = (val) >> 16, \
  73. data[1] = (val) >> 8, \
  74. data[0] = (val)
  75. #define GET8(data) \
  76. ( ( data[7] << 56 ) | \
  77. ( data[6] << 48 ) | \
  78. ( data[5] << 40 ) | \
  79. ( data[4] << 32 ) | \
  80. ( data[3] << 24 ) | \
  81. ( data[2] << 16 ) | \
  82. ( data[1] << 8 ) | \
  83. ( data[0] ) )
  84. #if defined( ux10 )
  85. #define SET02(x,y) SET2(x,y)
  86. #define GET02(x) GET2(x)
  87. #define SET04(x,y) SET4(x,y)
  88. #define GET04(x) GET4(x)
  89. #define SET08(x,y) SET8(x,y)
  90. #define GET08(x) GET8(x)
  91. #endif
  92. #define SET648(val,data) \
  93. data[1] = (val) >> 32, \
  94. data[0] = (val)
  95. #define GET648(data) \
  96. ( ( data[1] << 32 ) | \
  97. ( data[0] ) )
  98. #define GROUP(type,size,get,set,sfx) \
  99. LEndian##sfx##size( type v ) { set##size( v, data ); } \
  100. type operator = ( type v ) { set##size( v, data ); return v; } \
  101. operator type() { return get##size( data ); } \
  102. type operator += (const type v) { set##size( get##size(data) + v, data); return *this; } \
  103. type operator -= (const type v) { set##size( get##size(data) - v, data); return *this; } \
  104. type operator <<= (const type v) { set##size( get##size(data) << v, data); return *this; } \
  105. type operator <= (const type v) { set##size( get##size(data) < v, data); return *this; } \
  106. type operator >= (const type v) { set##size( get##size(data) > v, data); return *this; } \
  107. type operator *= (const type v) { set##size( get##size(data) * v, data); return *this; } \
  108. type operator /= (const type v) { set##size( get##size(data) / v, data); return *this; } \
  109. type operator %= (const type v) { set##size( get##size(data) % v, data); return *this; } \
  110. type operator >>= (const type v) { set##size( get##size(data) >> v, data); return *this; } \
  111. type operator ^= (const type v) { set##size( get##size(data) ^ v, data); return *this; } \
  112. type operator &= (const type v) { set##size( get##size(data) & v, data); return *this; } \
  113. type operator |= (const type v) { set##size( get##size(data) | v, data); return *this; }
  114. #define MAKE_TEMPLATE(size,type,sfx) \
  115. template<class BASE> \
  116. class LEndian##sfx##size \
  117. { \
  118. protected: \
  119. type data[ size / sizeof(type) ]; \
  120. \
  121. public: \
  122. \
  123. GROUP( signed char, size, GET##sfx, SET##sfx, sfx ) \
  124. GROUP( short, size, GET##sfx, SET##sfx, sfx ) \
  125. GROUP( int, size, GET##sfx, SET##sfx, sfx ) \
  126. GROUP( wchar_t, size, GET##sfx, SET##sfx, sfx ) \
  127. GROUP( long, size, GET##sfx, SET##sfx, sfx ) \
  128. GROUP( __int64, size, GET##sfx, SET##sfx, sfx ) \
  129. GROUP( unsigned char, size, GET##sfx, SET##sfx, sfx ) \
  130. GROUP( unsigned short, size, GET##sfx, SET##sfx, sfx ) \
  131. GROUP( unsigned int, size, GET##sfx, SET##sfx, sfx ) \
  132. GROUP( unsigned long, size, GET##sfx, SET##sfx, sfx ) \
  133. GROUP( unsigned __int64, size, GET##sfx, SET##sfx, sfx ) \
  134. }
  135. #if defined( ux10 )
  136. MAKE_TEMPLATE( 2, unsigned char, 0);
  137. MAKE_TEMPLATE( 4, unsigned char, 0);
  138. MAKE_TEMPLATE( 8, unsigned char, 0);
  139. #else
  140. MAKE_TEMPLATE( 2, unsigned char, );
  141. MAKE_TEMPLATE( 4, unsigned char, );
  142. MAKE_TEMPLATE( 8, unsigned char, );
  143. #endif
  144. MAKE_TEMPLATE( 8, unsigned int, 64 );
  145. #if defined( ux10 )
  146. template<class BASE>
  147. class LEndianPtr : LEndian04<BASE> {
  148. public:
  149. LEndianPtr(const void * v) : LEndian04<BASE>((int)v) { }
  150. void *operator = (void * v) { SET4((int)v,data); return v; }
  151. const void *operator = (const void * v) { SET4((int)v,data); return v; }
  152. operator BASE() { return (BASE)GET4(data); }
  153. };
  154. #else
  155. template<class BASE>
  156. class LEndianPtr : LEndian4<BASE> {
  157. public:
  158. LEndianPtr(const void * v) : LEndian4<BASE>((int)v) { }
  159. void *operator = (void * v) { SET4((int)v,data); return v; }
  160. const void *operator = (const void * v) { SET4((int)v,data); return v; }
  161. operator BASE() { return (BASE)GET4(data); }
  162. };
  163. #endif
  164. #undef SET2
  165. #undef SET4
  166. #undef SET8
  167. #undef SET648
  168. #undef GROUP
  169. #undef MAKE_TEMPLATE
  170. #if defined( ux10 )
  171. #define MAKE_LENDIAN_TYPE(base,size) \
  172. typedef LEndian0##size<base> base##_LENDIAN; \
  173. typedef LEndian0##size<base> base##_LENDIAN_UNALIGNED
  174. #else
  175. #define MAKE_LENDIAN_TYPE(base,size) \
  176. typedef LEndian##size<base> base##_LENDIAN; \
  177. typedef LEndian##size<base> base##_LENDIAN_UNALIGNED
  178. #endif
  179. #define MAKE_LENDIAN64_TYPE(base,size) \
  180. typedef LEndian64##size<base> base##_LENDIAN64; \
  181. typedef LEndian64##size<base> base##_LENDIAN64_UNALIGNED
  182. #define MAKE_LENDIANPTR_TYPE(base) \
  183. typedef LEndianPtr<base> base##_LENDIANPTR; \
  184. typedef LEndianPtr<base> base##_LENDIANPTR_UNALIGNED
  185. #endif // _MSC_VER
  186. // Predefine some of the basic types.
  187. MAKE_LENDIAN_TYPE( short, 2 );
  188. MAKE_LENDIAN_TYPE( int, 4 );
  189. MAKE_LENDIAN_TYPE( long, 4 );
  190. MAKE_LENDIAN_TYPE( WORD, 2 );
  191. MAKE_LENDIAN_TYPE( DWORD, 4 );
  192. MAKE_LENDIAN_TYPE( USHORT, 4 );
  193. MAKE_LENDIAN_TYPE( SHORT, 4 );
  194. MAKE_LENDIAN_TYPE( __int64, 8 );
  195. MAKE_LENDIAN64_TYPE( __int64, 8 );
  196. #endif // __lendian_h__