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.

239 lines
9.7 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Copyright (C) Microsoft Corporation, 1997-1998.
  4. //
  5. // File: unaligned.hpp
  6. //
  7. // Contents: Templatized data types for access to unaligned scalar values.
  8. //
  9. //----------------------------------------------------------------------------
  10. // Implementation of UNALIGNED 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 UNALIGNED type, use the MAKE_UNALIGNED_TYPE macro. For example, if
  15. // you need an int_UNALIGNED, say
  16. //
  17. // MAKE_UNALIGNED_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 UNALIGNED" in your code
  23. // with "type_UNALIGNED". 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. // UNALIGNED64: 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 __unaligned_h__
  32. #define __unaligned_h__
  33. #if defined (_MSC_VER) || defined(__APOGEE__)
  34. #define MAKE_UNALIGNED_TYPE(base,size) typedef base UNALIGNED base##_UNALIGNED
  35. //
  36. // Use MAKE_UNALIGNED64_TYPE for QWORD data that may only be DWORD aligned on 64-bit
  37. // machines. Only 64-bit architectures pay the penalty for accessing such data.
  38. //
  39. #ifdef SPARC
  40. #define MAKE_UNALIGNED64_TYPE(base,size) typedef base base##_UNALIGNED64
  41. #else
  42. #define MAKE_UNALIGNED64_TYPE(base,size) typedef base UNALIGNED base##_UNALIGNED64
  43. #endif // SPARC
  44. #define MAKE_UNALIGNEDPTR_TYPE(base) typedef base UNALIGNED *base##_UNALIGNEDPTR
  45. #else // defined (_MSC_VER) || defined(__APOGEE__)
  46. #ifdef BIG_ENDIAN
  47. #define SET2(val,data) \
  48. data[0] = (val) >> 8, \
  49. data[1] = (val)
  50. #define GET2(data) \
  51. ( ( data[0] << 8 ) | \
  52. ( data[1] ) )
  53. #define SET4(val,data) \
  54. data[0] = (val) >> 24, \
  55. data[1] = (val) >> 16, \
  56. data[2] = (val) >> 8, \
  57. data[3] = (val)
  58. #define GET4(data) \
  59. ( ( data[0] << 24 ) | \
  60. ( data[1] << 16 ) | \
  61. ( data[2] << 8 ) | \
  62. ( data[3] ) )
  63. #define SET8(val,data) \
  64. data[0] = (val) >> 56, \
  65. data[1] = (val) >> 48, \
  66. data[2] = (val) >> 40, \
  67. data[3] = (val) >> 32 \
  68. data[4] = (val) >> 24, \
  69. data[5] = (val) >> 16, \
  70. data[6] = (val) >> 8, \
  71. data[7] = (val)
  72. #define GET8(data) \
  73. ( ( data[0] << 56 ) | \
  74. ( data[1] << 48 ) | \
  75. ( data[2] << 40 ) | \
  76. ( data[3] << 32 ) | \
  77. ( data[4] << 24 ) | \
  78. ( data[5] << 16 ) | \
  79. ( data[6] << 8 ) | \
  80. ( data[7] ) )
  81. #define SET648(val,data) \
  82. data[0] = (val) >> 32, \
  83. data[1] = (val)
  84. #define GET648(data) \
  85. ( ( data[0] << 32 ) | \
  86. ( data[1] ) )
  87. #else
  88. #define SET2(val,data) \
  89. data[1] = (val) >> 8, \
  90. data[0] = (val)
  91. #define GET2(data) \
  92. ( ( data[1] << 8 ) | \
  93. ( data[0] ) )
  94. #define SET4(val,data) \
  95. data[3] = (val) >> 24, \
  96. data[2] = (val) >> 16, \
  97. data[1] = (val) >> 8, \
  98. data[0] = (val)
  99. #define GET4(data) \
  100. ( ( data[3] << 24 ) | \
  101. ( data[2] << 16 ) | \
  102. ( data[1] << 8 ) | \
  103. ( data[0] ) )
  104. #define SET8(val,data) \
  105. data[7] = (val) >> 56, \
  106. data[6] = (val) >> 48, \
  107. data[5] = (val) >> 40, \
  108. data[4] = (val) >> 32, \
  109. data[3] = (val) >> 24, \
  110. data[2] = (val) >> 16, \
  111. data[1] = (val) >> 8, \
  112. data[0] = (val)
  113. #define GET8(data) \
  114. ( ( data[7] << 56 ) | \
  115. ( data[6] << 48 ) | \
  116. ( data[5] << 40 ) | \
  117. ( data[4] << 32 ) | \
  118. ( data[3] << 24 ) | \
  119. ( data[2] << 16 ) | \
  120. ( data[1] << 8 ) | \
  121. ( data[0] ) )
  122. #define SET648(val,data) \
  123. data[1] = (val) >> 32, \
  124. data[0] = (val)
  125. #define GET648(data) \
  126. ( ( data[1] << 32 ) | \
  127. ( data[0] ) )
  128. #endif
  129. #define GROUP(type,size,get,set,sfx) \
  130. Unaligned##sfx##size( type v ) { set##size( v, data ); } \
  131. type operator = ( type v ) { set##size( v, data ); return v; } \
  132. operator type() { return get##size( data ); } \
  133. type operator += (const type v) { set##size( get##size(data) + v, data); return *this; } \
  134. type operator -= (const type v) { set##size( get##size(data) - v, data); return *this; } \
  135. type operator <<= (const type v) { set##size( get##size(data) << v, data); return *this; } \
  136. type operator *= (const type v) { set##size( get##size(data) * v, data); return *this; } \
  137. type operator /= (const type v) { set##size( get##size(data) / v, data); return *this; } \
  138. type operator %= (const type v) { set##size( get##size(data) % v, data); return *this; } \
  139. type operator >>= (const type v) { set##size( get##size(data) >> v, data); return *this; } \
  140. type operator ^= (const type v) { set##size( get##size(data) ^ v, data); return *this; } \
  141. type operator &= (const type v) { set##size( get##size(data) & v, data); return *this; } \
  142. type operator |= (const type v) { set##size( get##size(data) | v, data); return *this; } \
  143. #define MAKE_TEMPLATE(size,type,sfx) \
  144. template<class BASE> \
  145. class Unaligned##sfx##size<BASE> \
  146. { \
  147. protected: \
  148. type data[ size / sizeof(type) ]; \
  149. \
  150. public: \
  151. \
  152. GROUP( signed char, size, GET##sfx, SET##sfx, sfx ) \
  153. GROUP( short, size, GET##sfx, SET##sfx, sfx ) \
  154. GROUP( int, size, GET##sfx, SET##sfx, sfx ) \
  155. GROUP( wchar_t, size, GET##sfx, SET##sfx, sfx ) \
  156. GROUP( long, size, GET##sfx, SET##sfx, sfx ) \
  157. GROUP( __int64, size, GET##sfx, SET##sfx, sfx ) \
  158. GROUP( unsigned char, size, GET##sfx, SET##sfx, sfx ) \
  159. GROUP( unsigned short, size, GET##sfx, SET##sfx, sfx ) \
  160. GROUP( unsigned int, size, GET##sfx, SET##sfx, sfx ) \
  161. GROUP( unsigned long, size, GET##sfx, SET##sfx, sfx ) \
  162. GROUP( unsigned __int64, size, GET##sfx, SET##sfx, sfx ) \
  163. }
  164. MAKE_TEMPLATE( 2, unsigned char, );
  165. MAKE_TEMPLATE( 4, unsigned char, );
  166. MAKE_TEMPLATE( 8, unsigned char, );
  167. MAKE_TEMPLATE( 8, unsigned int, 64 );
  168. template<class BASE>
  169. class UnalignedPtr<BASE> : Unaligned4<BASE> {
  170. public:
  171. UnalignedPtr<BASE>(const void * v) : Unaligned4<BASE>((int)v) { }
  172. void *operator = (void * v) { SET4((int)v,data); return v; }
  173. const void *operator = (const void * v) { SET4((int)v,data); return v; }
  174. operator BASE() { return (BASE)GET4(data); }
  175. };
  176. #undef SET2
  177. #undef SET4
  178. #undef SET8
  179. #undef SET648
  180. #undef GROUP
  181. #undef MAKE_TEMPLATE
  182. #define MAKE_UNALIGNED_TYPE(base,size) typedef Unaligned##size<base> base##_UNALIGNED
  183. #define MAKE_UNALIGNED64_TYPE(base,size) typedef Unaligned64##size<base> base##_UNALIGNED64
  184. #define MAKE_UNALIGNEDPTR_TYPE(base) typedef UnalignedPtr<base> * base##_UNALIGNEDPTR
  185. #endif // _MSC_VER
  186. // Predefine some of the basic types.
  187. MAKE_UNALIGNED_TYPE( short, 2 );
  188. MAKE_UNALIGNED_TYPE( int, 4 );
  189. MAKE_UNALIGNED_TYPE( long, 4 );
  190. MAKE_UNALIGNED_TYPE( WORD, 2 );
  191. MAKE_UNALIGNED_TYPE( DWORD, 4 );
  192. MAKE_UNALIGNED_TYPE( USHORT, 4 );
  193. MAKE_UNALIGNED_TYPE( SHORT, 4 );
  194. MAKE_UNALIGNED_TYPE( __int64, 8 );
  195. MAKE_UNALIGNED64_TYPE( __int64, 8 );
  196. #endif __unaligned_h__