endian.hpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. // Boost endian.hpp header file -------------------------------------------------------//
  2. // (C) Copyright Darin Adler 2000
  3. // (C) Copyright Beman Dawes 2006, 2009
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // See http://www.boost.org/LICENSE_1_0.txt
  6. // See library home page at http://www.boost.org/libs/endian
  7. //--------------------------------------------------------------------------------------//
  8. // Original design developed by Darin Adler based on classes developed by Mark
  9. // Borgerding. Four original class templates were combined into a single endian
  10. // class template by Beman Dawes, who also added the unrolled_byte_loops sign
  11. // partial specialization to correctly extend the sign when cover integer size
  12. // differs from endian representation size.
  13. // TODO: When a compiler supporting constexpr becomes available, try possible uses.
  14. #ifndef BOOST_SPIRIT_ENDIAN_HPP
  15. #define BOOST_SPIRIT_ENDIAN_HPP
  16. #if defined(_MSC_VER)
  17. #pragma once
  18. #endif
  19. #ifdef BOOST_ENDIAN_LOG
  20. # include <iostream>
  21. #endif
  22. #if defined(__BORLANDC__) || defined( __CODEGEARC__)
  23. # pragma pack(push, 1)
  24. #endif
  25. #include <boost/config.hpp>
  26. #include <boost/predef/other/endian.h>
  27. #ifndef BOOST_MINIMAL_INTEGER_COVER_OPERATORS
  28. #define BOOST_MINIMAL_INTEGER_COVER_OPERATORS
  29. #endif
  30. #ifndef BOOST_NO_IO_COVER_OPERATORS
  31. #define BOOST_NO_IO_COVER_OPERATORS
  32. #endif
  33. #include <boost/spirit/home/support/detail/endian/cover_operators.hpp>
  34. #undef BOOST_NO_IO_COVER_OPERATORS
  35. #undef BOOST_MINIMAL_INTEGER_COVER_OPERATORS
  36. #include <boost/type_traits/is_signed.hpp>
  37. #include <boost/type_traits/make_unsigned.hpp>
  38. #include <boost/cstdint.hpp>
  39. #include <boost/static_assert.hpp>
  40. #include <boost/spirit/home/support/detail/scoped_enum_emulation.hpp>
  41. #include <iosfwd>
  42. #include <climits>
  43. # if CHAR_BIT != 8
  44. # error Platforms with CHAR_BIT != 8 are not supported
  45. # endif
  46. # define BOOST_SPIRIT_ENDIAN_DEFAULT_CONSTRUCT {} // C++03
  47. # if defined(BOOST_ENDIAN_NO_CTORS) || defined(BOOST_ENDIAN_FORCE_PODNESS)
  48. # define BOOST_SPIRIT_ENDIAN_NO_CTORS
  49. # endif
  50. namespace boost { namespace spirit
  51. {
  52. namespace detail
  53. {
  54. // Unrolled loops for loading and storing streams of bytes.
  55. template <typename T, std::size_t n_bytes,
  56. bool sign=boost::is_signed<T>::value >
  57. struct unrolled_byte_loops
  58. {
  59. typedef unrolled_byte_loops<T, n_bytes - 1, sign> next;
  60. static typename boost::make_unsigned<T>::type load_big(const unsigned char* bytes)
  61. { return *(bytes - 1) | (next::load_big(bytes - 1) << 8); }
  62. static typename boost::make_unsigned<T>::type load_little(const unsigned char* bytes)
  63. { return *bytes | (next::load_little(bytes + 1) << 8); }
  64. static void store_big(char* bytes, T value)
  65. {
  66. *(bytes - 1) = static_cast<char>(value);
  67. next::store_big(bytes - 1, value >> 8);
  68. }
  69. static void store_little(char* bytes, T value)
  70. {
  71. *bytes = static_cast<char>(value);
  72. next::store_little(bytes + 1, value >> 8);
  73. }
  74. };
  75. template <typename T>
  76. struct unrolled_byte_loops<T, 1, false>
  77. {
  78. static T load_big(const unsigned char* bytes)
  79. { return *(bytes - 1); }
  80. static T load_little(const unsigned char* bytes)
  81. { return *bytes; }
  82. static void store_big(char* bytes, T value)
  83. { *(bytes - 1) = static_cast<char>(value); }
  84. static void store_little(char* bytes, T value)
  85. { *bytes = static_cast<char>(value); }
  86. };
  87. template <typename T>
  88. struct unrolled_byte_loops<T, 1, true>
  89. {
  90. static typename boost::make_unsigned<T>::type load_big(const unsigned char* bytes)
  91. { return *(bytes - 1); }
  92. static typename boost::make_unsigned<T>::type load_little(const unsigned char* bytes)
  93. { return *bytes; }
  94. static void store_big(char* bytes, T value)
  95. { *(bytes - 1) = static_cast<char>(value); }
  96. static void store_little(char* bytes, T value)
  97. { *bytes = static_cast<char>(value); }
  98. };
  99. template <typename T, std::size_t n_bytes>
  100. inline
  101. T load_big_endian(const void* bytes)
  102. {
  103. return static_cast<T>(unrolled_byte_loops<T, n_bytes>::load_big
  104. (static_cast<const unsigned char*>(bytes) + n_bytes));
  105. }
  106. template <>
  107. inline
  108. float load_big_endian<float, 4>(const void* bytes)
  109. {
  110. const unsigned char *b = reinterpret_cast<const unsigned char *>(
  111. bytes);
  112. b += 3;
  113. float value;
  114. unsigned char *v = reinterpret_cast<unsigned char *>(&value);
  115. for(std::size_t i = 0; i < 4; ++i)
  116. {
  117. *v++ = *b--;
  118. }
  119. return value;
  120. }
  121. template <>
  122. inline
  123. double load_big_endian<double, 8>(const void* bytes)
  124. {
  125. const unsigned char *b = reinterpret_cast<const unsigned char *>(
  126. bytes);
  127. b += 7;
  128. double value;
  129. unsigned char *v = reinterpret_cast<unsigned char *>(&value);
  130. for(std::size_t i = 0; i < 8; ++i)
  131. {
  132. *v++ = *b--;
  133. }
  134. return value;
  135. }
  136. template <typename T, std::size_t n_bytes>
  137. inline
  138. T load_little_endian(const void* bytes)
  139. {
  140. return static_cast<T>(unrolled_byte_loops<T, n_bytes>::load_little
  141. (static_cast<const unsigned char*>(bytes)));
  142. }
  143. template <>
  144. inline
  145. float load_little_endian<float, 4>(const void* bytes)
  146. {
  147. const unsigned char *b = reinterpret_cast<const unsigned char *>(
  148. bytes);
  149. float value;
  150. unsigned char *v = reinterpret_cast<unsigned char *>(&value);
  151. for(std::size_t i = 0; i < 4; ++i)
  152. {
  153. *v++ = *b++;
  154. }
  155. return value;
  156. }
  157. template <>
  158. inline
  159. double load_little_endian<double, 8>(const void* bytes)
  160. {
  161. const unsigned char *b = reinterpret_cast<const unsigned char *>(
  162. bytes);
  163. double value;
  164. unsigned char *v = reinterpret_cast<unsigned char *>(&value);
  165. for(std::size_t i = 0; i < 8; ++i)
  166. {
  167. *v++ = *b++;
  168. }
  169. return value;
  170. }
  171. template <typename T, std::size_t n_bytes>
  172. inline
  173. void store_big_endian(void* bytes, T value)
  174. {
  175. unrolled_byte_loops<T, n_bytes>::store_big
  176. (static_cast<char*>(bytes) + n_bytes, value);
  177. }
  178. template <>
  179. inline
  180. void store_big_endian<float, 4>(void* bytes, float value)
  181. {
  182. unsigned char *b = reinterpret_cast<unsigned char *>(bytes);
  183. b += 3;
  184. const unsigned char *v = reinterpret_cast<const unsigned char *>(
  185. &value);
  186. for(std::size_t i = 0; i < 4; ++i)
  187. {
  188. *b-- = *v++;
  189. }
  190. }
  191. template <>
  192. inline
  193. void store_big_endian<double, 8>(void* bytes, double value)
  194. {
  195. unsigned char *b = reinterpret_cast<unsigned char *>(bytes);
  196. b += 7;
  197. const unsigned char *v = reinterpret_cast<const unsigned char *>(
  198. &value);
  199. for(std::size_t i = 0; i < 8; ++i)
  200. {
  201. *b-- = *v++;
  202. }
  203. }
  204. template <typename T, std::size_t n_bytes>
  205. inline
  206. void store_little_endian(void* bytes, T value)
  207. {
  208. unrolled_byte_loops<T, n_bytes>::store_little
  209. (static_cast<char*>(bytes), value);
  210. }
  211. template <>
  212. inline
  213. void store_little_endian<float, 4>(void* bytes, float value)
  214. {
  215. unsigned char *b = reinterpret_cast<unsigned char *>(bytes);
  216. const unsigned char *v = reinterpret_cast<const unsigned char *>(
  217. &value);
  218. for(std::size_t i = 0; i < 4; ++i)
  219. {
  220. *b++ = *v++;
  221. }
  222. }
  223. template <>
  224. inline
  225. void store_little_endian<double, 8>(void* bytes, double value)
  226. {
  227. unsigned char *b = reinterpret_cast<unsigned char *>(bytes);
  228. const unsigned char *v = reinterpret_cast<const unsigned char *>(
  229. &value);
  230. for(std::size_t i = 0; i < 8; ++i)
  231. {
  232. *b++ = *v++;
  233. }
  234. }
  235. } // namespace detail
  236. namespace endian
  237. {
  238. # ifdef BOOST_ENDIAN_LOG
  239. bool endian_log(true);
  240. # endif
  241. // endian class template and specializations ---------------------------------------//
  242. BOOST_SCOPED_ENUM_START(endianness) { big, little, native }; BOOST_SCOPED_ENUM_END
  243. BOOST_SCOPED_ENUM_START(alignment) { unaligned, aligned }; BOOST_SCOPED_ENUM_END
  244. template <BOOST_SCOPED_ENUM(endianness) E, typename T, std::size_t n_bits,
  245. BOOST_SCOPED_ENUM(alignment) A = alignment::unaligned>
  246. class endian;
  247. // Specializations that represent unaligned bytes.
  248. // Taking an integer type as a parameter provides a nice way to pass both
  249. // the size and signedness of the desired integer and get the appropriate
  250. // corresponding integer type for the interface.
  251. // unaligned big endian specialization
  252. template <typename T, std::size_t n_bits>
  253. class endian< endianness::big, T, n_bits, alignment::unaligned >
  254. : cover_operators< endian< endianness::big, T, n_bits >, T >
  255. {
  256. BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
  257. public:
  258. typedef T value_type;
  259. # ifndef BOOST_SPIRIT_ENDIAN_NO_CTORS
  260. endian() BOOST_SPIRIT_ENDIAN_DEFAULT_CONSTRUCT
  261. explicit endian(T val)
  262. {
  263. # ifdef BOOST_ENDIAN_LOG
  264. if ( endian_log )
  265. std::clog << "big, unaligned, " << n_bits << "-bits, construct(" << val << ")\n";
  266. # endif
  267. detail::store_big_endian<T, n_bits/8>(m_value, val);
  268. }
  269. # endif
  270. endian & operator=(T val) { detail::store_big_endian<T, n_bits/8>(m_value, val); return *this; }
  271. operator T() const
  272. {
  273. # ifdef BOOST_ENDIAN_LOG
  274. if ( endian_log )
  275. std::clog << "big, unaligned, " << n_bits << "-bits, convert(" << detail::load_big_endian<T, n_bits/8>(m_value) << ")\n";
  276. # endif
  277. return detail::load_big_endian<T, n_bits/8>(m_value);
  278. }
  279. private:
  280. char m_value[n_bits/8];
  281. };
  282. // unaligned little endian specialization
  283. template <typename T, std::size_t n_bits>
  284. class endian< endianness::little, T, n_bits, alignment::unaligned >
  285. : cover_operators< endian< endianness::little, T, n_bits >, T >
  286. {
  287. BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
  288. public:
  289. typedef T value_type;
  290. # ifndef BOOST_SPIRIT_ENDIAN_NO_CTORS
  291. endian() BOOST_SPIRIT_ENDIAN_DEFAULT_CONSTRUCT
  292. explicit endian(T val)
  293. {
  294. # ifdef BOOST_ENDIAN_LOG
  295. if ( endian_log )
  296. std::clog << "little, unaligned, " << n_bits << "-bits, construct(" << val << ")\n";
  297. # endif
  298. detail::store_little_endian<T, n_bits/8>(m_value, val);
  299. }
  300. # endif
  301. endian & operator=(T val) { detail::store_little_endian<T, n_bits/8>(m_value, val); return *this; }
  302. operator T() const
  303. {
  304. # ifdef BOOST_ENDIAN_LOG
  305. if ( endian_log )
  306. std::clog << "little, unaligned, " << n_bits << "-bits, convert(" << detail::load_little_endian<T, n_bits/8>(m_value) << ")\n";
  307. # endif
  308. return detail::load_little_endian<T, n_bits/8>(m_value);
  309. }
  310. private:
  311. char m_value[n_bits/8];
  312. };
  313. // unaligned native endian specialization
  314. template <typename T, std::size_t n_bits>
  315. class endian< endianness::native, T, n_bits, alignment::unaligned >
  316. : cover_operators< endian< endianness::native, T, n_bits >, T >
  317. {
  318. BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
  319. public:
  320. typedef T value_type;
  321. # ifndef BOOST_SPIRIT_ENDIAN_NO_CTORS
  322. endian() BOOST_SPIRIT_ENDIAN_DEFAULT_CONSTRUCT
  323. # if BOOST_ENDIAN_BIG_BYTE
  324. explicit endian(T val) { detail::store_big_endian<T, n_bits/8>(m_value, val); }
  325. # else
  326. explicit endian(T val) { detail::store_little_endian<T, n_bits/8>(m_value, val); }
  327. # endif
  328. # endif
  329. # if BOOST_ENDIAN_BIG_BYTE
  330. endian & operator=(T val) { detail::store_big_endian<T, n_bits/8>(m_value, val); return *this; }
  331. operator T() const { return detail::load_big_endian<T, n_bits/8>(m_value); }
  332. # else
  333. endian & operator=(T val) { detail::store_little_endian<T, n_bits/8>(m_value, val); return *this; }
  334. operator T() const { return detail::load_little_endian<T, n_bits/8>(m_value); }
  335. # endif
  336. private:
  337. char m_value[n_bits/8];
  338. };
  339. // Specializations that mimic built-in integer types.
  340. // These typically have the same alignment as the underlying types.
  341. // aligned big endian specialization
  342. template <typename T, std::size_t n_bits>
  343. class endian< endianness::big, T, n_bits, alignment::aligned >
  344. : cover_operators< endian< endianness::big, T, n_bits, alignment::aligned >, T >
  345. {
  346. BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
  347. BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
  348. public:
  349. typedef T value_type;
  350. # ifndef BOOST_SPIRIT_ENDIAN_NO_CTORS
  351. endian() BOOST_SPIRIT_ENDIAN_DEFAULT_CONSTRUCT
  352. # if BOOST_ENDIAN_BIG_BYTE
  353. endian(T val) : m_value(val) { }
  354. # else
  355. explicit endian(T val) { detail::store_big_endian<T, sizeof(T)>(&m_value, val); }
  356. # endif
  357. # endif
  358. # if BOOST_ENDIAN_BIG_BYTE
  359. endian & operator=(T val) { m_value = val; return *this; }
  360. operator T() const { return m_value; }
  361. # else
  362. endian & operator=(T val) { detail::store_big_endian<T, sizeof(T)>(&m_value, val); return *this; }
  363. operator T() const { return detail::load_big_endian<T, sizeof(T)>(&m_value); }
  364. # endif
  365. private:
  366. T m_value;
  367. };
  368. // aligned little endian specialization
  369. template <typename T, std::size_t n_bits>
  370. class endian< endianness::little, T, n_bits, alignment::aligned >
  371. : cover_operators< endian< endianness::little, T, n_bits, alignment::aligned >, T >
  372. {
  373. BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
  374. BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
  375. public:
  376. typedef T value_type;
  377. # ifndef BOOST_SPIRIT_ENDIAN_NO_CTORS
  378. endian() BOOST_SPIRIT_ENDIAN_DEFAULT_CONSTRUCT
  379. # if BOOST_ENDIAN_LITTLE_BYTE
  380. endian(T val) : m_value(val) { }
  381. # else
  382. explicit endian(T val) { detail::store_little_endian<T, sizeof(T)>(&m_value, val); }
  383. # endif
  384. # endif
  385. # if BOOST_ENDIAN_LITTLE_BYTE
  386. endian & operator=(T val) { m_value = val; return *this; }
  387. operator T() const { return m_value; }
  388. #else
  389. endian & operator=(T val) { detail::store_little_endian<T, sizeof(T)>(&m_value, val); return *this; }
  390. operator T() const { return detail::load_little_endian<T, sizeof(T)>(&m_value); }
  391. #endif
  392. private:
  393. T m_value;
  394. };
  395. // naming convention typedefs ------------------------------------------------------//
  396. // unaligned big endian signed integer types
  397. typedef endian< endianness::big, int_least8_t, 8 > big8_t;
  398. typedef endian< endianness::big, int_least16_t, 16 > big16_t;
  399. typedef endian< endianness::big, int_least32_t, 24 > big24_t;
  400. typedef endian< endianness::big, int_least32_t, 32 > big32_t;
  401. typedef endian< endianness::big, int_least64_t, 40 > big40_t;
  402. typedef endian< endianness::big, int_least64_t, 48 > big48_t;
  403. typedef endian< endianness::big, int_least64_t, 56 > big56_t;
  404. typedef endian< endianness::big, int_least64_t, 64 > big64_t;
  405. // unaligned big endian unsigned integer types
  406. typedef endian< endianness::big, uint_least8_t, 8 > ubig8_t;
  407. typedef endian< endianness::big, uint_least16_t, 16 > ubig16_t;
  408. typedef endian< endianness::big, uint_least32_t, 24 > ubig24_t;
  409. typedef endian< endianness::big, uint_least32_t, 32 > ubig32_t;
  410. typedef endian< endianness::big, uint_least64_t, 40 > ubig40_t;
  411. typedef endian< endianness::big, uint_least64_t, 48 > ubig48_t;
  412. typedef endian< endianness::big, uint_least64_t, 56 > ubig56_t;
  413. typedef endian< endianness::big, uint_least64_t, 64 > ubig64_t;
  414. // unaligned little endian signed integer types
  415. typedef endian< endianness::little, int_least8_t, 8 > little8_t;
  416. typedef endian< endianness::little, int_least16_t, 16 > little16_t;
  417. typedef endian< endianness::little, int_least32_t, 24 > little24_t;
  418. typedef endian< endianness::little, int_least32_t, 32 > little32_t;
  419. typedef endian< endianness::little, int_least64_t, 40 > little40_t;
  420. typedef endian< endianness::little, int_least64_t, 48 > little48_t;
  421. typedef endian< endianness::little, int_least64_t, 56 > little56_t;
  422. typedef endian< endianness::little, int_least64_t, 64 > little64_t;
  423. // unaligned little endian unsigned integer types
  424. typedef endian< endianness::little, uint_least8_t, 8 > ulittle8_t;
  425. typedef endian< endianness::little, uint_least16_t, 16 > ulittle16_t;
  426. typedef endian< endianness::little, uint_least32_t, 24 > ulittle24_t;
  427. typedef endian< endianness::little, uint_least32_t, 32 > ulittle32_t;
  428. typedef endian< endianness::little, uint_least64_t, 40 > ulittle40_t;
  429. typedef endian< endianness::little, uint_least64_t, 48 > ulittle48_t;
  430. typedef endian< endianness::little, uint_least64_t, 56 > ulittle56_t;
  431. typedef endian< endianness::little, uint_least64_t, 64 > ulittle64_t;
  432. // unaligned native endian signed integer types
  433. typedef endian< endianness::native, int_least8_t, 8 > native8_t;
  434. typedef endian< endianness::native, int_least16_t, 16 > native16_t;
  435. typedef endian< endianness::native, int_least32_t, 24 > native24_t;
  436. typedef endian< endianness::native, int_least32_t, 32 > native32_t;
  437. typedef endian< endianness::native, int_least64_t, 40 > native40_t;
  438. typedef endian< endianness::native, int_least64_t, 48 > native48_t;
  439. typedef endian< endianness::native, int_least64_t, 56 > native56_t;
  440. typedef endian< endianness::native, int_least64_t, 64 > native64_t;
  441. // unaligned native endian unsigned integer types
  442. typedef endian< endianness::native, uint_least8_t, 8 > unative8_t;
  443. typedef endian< endianness::native, uint_least16_t, 16 > unative16_t;
  444. typedef endian< endianness::native, uint_least32_t, 24 > unative24_t;
  445. typedef endian< endianness::native, uint_least32_t, 32 > unative32_t;
  446. typedef endian< endianness::native, uint_least64_t, 40 > unative40_t;
  447. typedef endian< endianness::native, uint_least64_t, 48 > unative48_t;
  448. typedef endian< endianness::native, uint_least64_t, 56 > unative56_t;
  449. typedef endian< endianness::native, uint_least64_t, 64 > unative64_t;
  450. // These types only present if platform has exact size integers:
  451. // aligned big endian signed integer types
  452. // aligned big endian unsigned integer types
  453. // aligned little endian signed integer types
  454. // aligned little endian unsigned integer types
  455. // aligned native endian typedefs are not provided because
  456. // <cstdint> types are superior for this use case
  457. #ifdef INT16_MAX
  458. typedef endian< endianness::big, int16_t, 16, alignment::aligned > aligned_big16_t;
  459. typedef endian< endianness::big, uint16_t, 16, alignment::aligned > aligned_ubig16_t;
  460. typedef endian< endianness::little, int16_t, 16, alignment::aligned > aligned_little16_t;
  461. typedef endian< endianness::little, uint16_t, 16, alignment::aligned > aligned_ulittle16_t;
  462. #endif
  463. #ifdef INT32_MAX
  464. typedef endian< endianness::big, int32_t, 32, alignment::aligned > aligned_big32_t;
  465. typedef endian< endianness::big, uint32_t, 32, alignment::aligned > aligned_ubig32_t;
  466. typedef endian< endianness::little, int32_t, 32, alignment::aligned > aligned_little32_t;
  467. typedef endian< endianness::little, uint32_t, 32, alignment::aligned > aligned_ulittle32_t;
  468. #endif
  469. #ifdef INT64_MAX
  470. typedef endian< endianness::big, int64_t, 64, alignment::aligned > aligned_big64_t;
  471. typedef endian< endianness::big, uint64_t, 64, alignment::aligned > aligned_ubig64_t;
  472. typedef endian< endianness::little, int64_t, 64, alignment::aligned > aligned_little64_t;
  473. typedef endian< endianness::little, uint64_t, 64, alignment::aligned > aligned_ulittle64_t;
  474. #endif
  475. } // namespace endian
  476. }} // namespace boost::spirit
  477. #undef BOOST_SPIRIT_ENDIAN_DEFAULT_CONSTRUCT
  478. #undef BOOST_SPIRIT_ENDIAN_NO_CTORS
  479. #if defined(__BORLANDC__) || defined( __CODEGEARC__)
  480. # pragma pack(pop)
  481. #endif
  482. #endif // BOOST_SPIRIT_ENDIAN_HPP