qendian.h
上传用户:detong
上传日期:2022-06-22
资源大小:20675k
文件大小:11k
源码类别:

系统编程

开发平台:

Unix_Linux

  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
  4. ** Contact: Qt Software Information (qt-info@nokia.com)
  5. **
  6. ** This file is part of the QtCore module of the Qt Toolkit.
  7. **
  8. ** Commercial Usage
  9. ** Licensees holding valid Qt Commercial licenses may use this file in
  10. ** accordance with the Qt Commercial License Agreement provided with the
  11. ** Software or, alternatively, in accordance with the terms contained in
  12. ** a written agreement between you and Nokia.
  13. **
  14. **
  15. ** GNU General Public License Usage
  16. ** Alternatively, this file may be used under the terms of the GNU
  17. ** General Public License versions 2.0 or 3.0 as published by the Free
  18. ** Software Foundation and appearing in the file LICENSE.GPL included in
  19. ** the packaging of this file.  Please review the following information
  20. ** to ensure GNU General Public Licensing requirements will be met:
  21. ** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
  22. ** http://www.gnu.org/copyleft/gpl.html.  In addition, as a special
  23. ** exception, Nokia gives you certain additional rights. These rights
  24. ** are described in the Nokia Qt GPL Exception version 1.3, included in
  25. ** the file GPL_EXCEPTION.txt in this package.
  26. **
  27. ** Qt for Windows(R) Licensees
  28. ** As a special exception, Nokia, as the sole copyright holder for Qt
  29. ** Designer, grants users of the Qt/Eclipse Integration plug-in the
  30. ** right for the Qt/Eclipse Integration to link to functionality
  31. ** provided by Qt Designer and its related libraries.
  32. **
  33. ** If you are unsure which license is appropriate for your use, please
  34. ** contact the sales department at qt-sales@nokia.com.
  35. **
  36. ****************************************************************************/
  37. #ifndef QENDIAN_H
  38. #define QENDIAN_H
  39. #include <QtCore/qglobal.h>
  40. QT_BEGIN_HEADER
  41. QT_BEGIN_NAMESPACE
  42. QT_MODULE(Core)
  43. /*
  44.  * ENDIAN FUNCTIONS
  45. */
  46. inline void qbswap_helper(const uchar *src, uchar *dest, int size)
  47. {
  48.     for (int i = 0; i < size ; ++i) dest[i] = src[size - 1 - i];
  49. }
  50. /*
  51.  * qbswap(const T src, const uchar *dest);
  52.  * Changes the byte order of a src from big endian to little endian or vice versa
  53.  * and stores the result in a dest.
  54.  * There is no alignment requirements for a dest.
  55. */
  56. template <typename T> inline void qbswap(const T src, uchar *dest)
  57. {
  58.     qbswap_helper(reinterpret_cast<const uchar *>(&src), dest, sizeof(T));
  59. }
  60. // Used to implement a type-safe and alignment-safe copy operation
  61. // If you want to avoid the memcopy, you must write specializations for this function
  62. template <typename T> inline void qToUnaligned(const T src, uchar *dest)
  63. {
  64.     qMemCopy(dest, &src, sizeof(T));
  65. }
  66. /* T qFromLittleEndian(const uchar *src)
  67.  * This function will read a little-endian encoded value from a src
  68.  * and return the value in host-endian encoding.
  69.  * There is no requirement that a src must be aligned.
  70. */
  71. #if defined Q_CC_MSVC && _MSC_VER < 1300 || defined Q_CC_SUN
  72. inline quint64 qFromLittleEndian_helper(const uchar *src, quint64 *dest)
  73. {
  74.     return 0
  75.         | src[0]
  76.         | src[1] * Q_UINT64_C(0x0000000000000100)
  77.         | src[2] * Q_UINT64_C(0x0000000000010000)
  78.         | src[3] * Q_UINT64_C(0x0000000001000000)
  79.         | src[4] * Q_UINT64_C(0x0000000100000000)
  80.         | src[5] * Q_UINT64_C(0x0000010000000000)
  81.         | src[6] * Q_UINT64_C(0x0001000000000000)
  82.         | src[7] * Q_UINT64_C(0x0100000000000000);
  83. }
  84. inline quint32 qFromLittleEndian_helper(const uchar *src, quint32 *dest)
  85. {
  86.     return 0
  87.         | src[0]
  88.         | src[1] * quint32(0x00000100)
  89.         | src[2] * quint32(0x00010000)
  90.         | src[3] * quint32(0x01000000);
  91. }
  92. inline quint16 qFromLittleEndian_helper(const uchar *src, quint16 *dest)
  93. {
  94.     return 0
  95.         | src[0]
  96.         | src[1] * 0x0100;
  97. }
  98. inline qint64 qFromLittleEndian_helper(const uchar *src, qint64 * dest)
  99. { return static_cast<qint64>(qFromLittleEndian_helper(src, reinterpret_cast<quint64*>(0))); }
  100. inline qint32 qFromLittleEndian_helper(const uchar *src, qint32 * dest)
  101. { return static_cast<qint32>(qFromLittleEndian_helper(src, reinterpret_cast<quint32*>(0))); }
  102. inline qint16 qFromLittleEndian_helper(const uchar *src, qint16 * dest)
  103. { return static_cast<qint16>(qFromLittleEndian_helper(src, reinterpret_cast<quint16*>(0))); }
  104. template <class T> inline T qFromLittleEndian(const uchar *src)
  105. {
  106.     return qFromLittleEndian_helper(src, reinterpret_cast<T*>(0));
  107. }
  108. #else
  109. template <typename T> inline T qFromLittleEndian(const uchar *src);
  110. template <> inline quint64 qFromLittleEndian<quint64>(const uchar *src)
  111. {
  112.     return 0
  113.         | src[0]
  114.         | src[1] * Q_UINT64_C(0x0000000000000100)
  115.         | src[2] * Q_UINT64_C(0x0000000000010000)
  116.         | src[3] * Q_UINT64_C(0x0000000001000000)
  117.         | src[4] * Q_UINT64_C(0x0000000100000000)
  118.         | src[5] * Q_UINT64_C(0x0000010000000000)
  119.         | src[6] * Q_UINT64_C(0x0001000000000000)
  120.         | src[7] * Q_UINT64_C(0x0100000000000000);
  121. }
  122. template <> inline quint32 qFromLittleEndian<quint32>(const uchar *src)
  123. {
  124.     return 0
  125.         | src[0]
  126.         | src[1] * quint32(0x00000100)
  127.         | src[2] * quint32(0x00010000)
  128.         | src[3] * quint32(0x01000000);
  129. }
  130. template <> inline quint16 qFromLittleEndian<quint16>(const uchar *src)
  131. {
  132.     return 0
  133.         | src[0]
  134.         | src[1] * 0x0100;
  135. }
  136. // signed specializations
  137. template <> inline qint64 qFromLittleEndian<qint64>(const uchar *src)
  138. { return static_cast<qint64>(qFromLittleEndian<quint64>(src)); }
  139. template <> inline qint32 qFromLittleEndian<qint32>(const uchar *src)
  140. { return static_cast<qint32>(qFromLittleEndian<quint32>(src)); }
  141. template <> inline qint16 qFromLittleEndian<qint16>(const uchar *src)
  142. { return static_cast<qint16>(qFromLittleEndian<quint16>(src)); }
  143. #endif
  144. /* This function will read a big-endian (also known as network order) encoded value from a src
  145.  * and return the value in host-endian encoding.
  146.  * There is no requirement that a src must be aligned.
  147. */
  148. #if defined Q_CC_MSVC && _MSC_VER < 1300 || defined Q_CC_SUN
  149. inline quint64 qFromBigEndian_helper(const uchar *src, quint64 *dest)
  150. {
  151.     return 0
  152.         | src[7]
  153.         | src[6] * Q_UINT64_C(0x0000000000000100)
  154.         | src[5] * Q_UINT64_C(0x0000000000010000)
  155.         | src[4] * Q_UINT64_C(0x0000000001000000)
  156.         | src[3] * Q_UINT64_C(0x0000000100000000)
  157.         | src[2] * Q_UINT64_C(0x0000010000000000)
  158.         | src[1] * Q_UINT64_C(0x0001000000000000)
  159.         | src[0] * Q_UINT64_C(0x0100000000000000);
  160. }
  161. inline quint32 qFromBigEndian_helper(const uchar *src, quint32 * dest)
  162. {
  163.     return 0
  164.         | src[3]
  165.         | src[2] * quint32(0x00000100)
  166.         | src[1] * quint32(0x00010000)
  167.         | src[0] * quint32(0x01000000);
  168. }
  169. inline quint16 qFromBigEndian_helper(const uchar *src, quint16 * des)
  170. {
  171.     return 0
  172.         | src[1]
  173.         | src[0] * 0x0100;
  174. }
  175. inline qint64 qFromBigEndian_helper(const uchar *src, qint64 * dest)
  176. { return static_cast<qint64>(qFromBigEndian_helper(src, reinterpret_cast<quint64*>(0))); }
  177. inline qint32 qFromBigEndian_helper(const uchar *src, qint32 * dest)
  178. { return static_cast<qint32>(qFromBigEndian_helper(src, reinterpret_cast<quint32*>(0))); }
  179. inline qint16 qFromBigEndian_helper(const uchar *src, qint16 * dest)
  180. { return static_cast<qint16>(qFromBigEndian_helper(src, reinterpret_cast<quint16*>(0))); }
  181. template <class T> inline T qFromBigEndian(const uchar *src)
  182. {
  183.     return qFromBigEndian_helper(src, reinterpret_cast<T*>(0));
  184. }
  185. #else
  186. template <class T> inline T qFromBigEndian(const uchar *src);
  187. template<>
  188. inline quint64 qFromBigEndian<quint64>(const uchar *src)
  189. {
  190.     return 0
  191.         | src[7]
  192.         | src[6] * Q_UINT64_C(0x0000000000000100)
  193.         | src[5] * Q_UINT64_C(0x0000000000010000)
  194.         | src[4] * Q_UINT64_C(0x0000000001000000)
  195.         | src[3] * Q_UINT64_C(0x0000000100000000)
  196.         | src[2] * Q_UINT64_C(0x0000010000000000)
  197.         | src[1] * Q_UINT64_C(0x0001000000000000)
  198.         | src[0] * Q_UINT64_C(0x0100000000000000);
  199. }
  200. template<>
  201. inline quint32 qFromBigEndian<quint32>(const uchar *src)
  202. {
  203.     return 0
  204.         | src[3]
  205.         | src[2] * quint32(0x00000100)
  206.         | src[1] * quint32(0x00010000)
  207.         | src[0] * quint32(0x01000000);
  208. }
  209. template<>
  210. inline quint16 qFromBigEndian<quint16>(const uchar *src)
  211. {
  212.     return 0
  213.         | src[1]
  214.         | src[0] * quint16(0x0100);
  215. }
  216. // signed specializations
  217. template <> inline qint64 qFromBigEndian<qint64>(const uchar *src)
  218. { return static_cast<qint64>(qFromBigEndian<quint64>(src)); }
  219. template <> inline qint32 qFromBigEndian<qint32>(const uchar *src)
  220. { return static_cast<qint32>(qFromBigEndian<quint32>(src)); }
  221. template <> inline qint16 qFromBigEndian<qint16>(const uchar *src)
  222. { return static_cast<qint16>(qFromBigEndian<quint16>(src)); }
  223. #endif
  224. /*
  225.  * T qbswap(T source).
  226.  * Changes the byte order of a value from big endian to little endian or vice versa.
  227.  * This function can be used if you are not concerned about alignment issues,
  228.  * and it is therefore a bit more convenient and in most cases more efficient.
  229. */
  230. template <typename T> T qbswap(T source);
  231. template <> inline quint64 qbswap<quint64>(quint64 source)
  232. {
  233.     return 0
  234.         | ((source & Q_UINT64_C(0x00000000000000ff)) << 56)
  235.         | ((source & Q_UINT64_C(0x000000000000ff00)) << 40)
  236.         | ((source & Q_UINT64_C(0x0000000000ff0000)) << 24)
  237.         | ((source & Q_UINT64_C(0x00000000ff000000)) << 8)
  238.         | ((source & Q_UINT64_C(0x000000ff00000000)) >> 8)
  239.         | ((source & Q_UINT64_C(0x0000ff0000000000)) >> 24)
  240.         | ((source & Q_UINT64_C(0x00ff000000000000)) >> 40)
  241.         | ((source & Q_UINT64_C(0xff00000000000000)) >> 56);
  242. }
  243. template <> inline quint32 qbswap<quint32>(quint32 source)
  244. {
  245.     return 0
  246.         | ((source & 0x000000ff) << 24)
  247.         | ((source & 0x0000ff00) << 8)
  248.         | ((source & 0x00ff0000) >> 8)
  249.         | ((source & 0xff000000) >> 24);
  250. }
  251. template <> inline quint16 qbswap<quint16>(quint16 source)
  252. {
  253.     return 0
  254.         | ((source & 0x00ff) << 8)
  255.         | ((source & 0xff00) >> 8);
  256. }
  257. // signed specializations
  258. template <> inline qint64 qbswap<qint64>(qint64 source)
  259. {
  260.     return qbswap<quint64>(quint64(source));
  261. }
  262. template <> inline qint32 qbswap<qint32>(qint32 source)
  263. {
  264.     return qbswap<quint32>(quint32(source));
  265. }
  266. template <> inline qint16 qbswap<qint16>(qint16 source)
  267. {
  268.     return qbswap<quint16>(quint16(source));
  269. }
  270. #if Q_BYTE_ORDER == Q_BIG_ENDIAN
  271. template <typename T> inline T qToBigEndian(T source)
  272. { return source; }
  273. template <typename T> inline T qFromBigEndian(T source)
  274. { return source; }
  275. template <typename T> inline T qToLittleEndian(T source)
  276. { return qbswap<T>(source); }
  277. template <typename T> inline T qFromLittleEndian(T source)
  278. { return qbswap<T>(source); }
  279. template <typename T> inline void qToBigEndian(T src, uchar *dest)
  280. { qToUnaligned<T>(src, dest); }
  281. template <typename T> inline void qToLittleEndian(T src, uchar *dest)
  282. { qbswap<T>(src, dest); }
  283. #else // Q_LITTLE_ENDIAN
  284. template <typename T> inline T qToBigEndian(T source)
  285. { return qbswap<T>(source); }
  286. template <typename T> inline T qFromBigEndian(T source)
  287. { return qbswap<T>(source); }
  288. template <typename T> inline T qToLittleEndian(T source)
  289. { return source; }
  290. template <typename T> inline T qFromLittleEndian(T source)
  291. { return source; }
  292. template <typename T> inline void qToBigEndian(T src, uchar *dest)
  293. { qbswap<T>(src, dest); }
  294. template <typename T> inline void qToLittleEndian(T src, uchar *dest)
  295. { qToUnaligned<T>(src, dest); }
  296. #endif // Q_BYTE_ORDER == Q_BIG_ENDIAN
  297. QT_END_NAMESPACE
  298. QT_END_HEADER
  299. #endif // QENDIAN_H