GCS  0.2.3
gu_byteswap.h
1 // Copyright (C) 2012 Codership Oy <info@codership.com>
2 
9 #ifndef _gu_byteswap_h_
10 #define _gu_byteswap_h_
11 
12 #include "gu_arch.h"
13 #include "gu_types.h"
14 #include "gu_macros.h"
15 
16 /*
17  * Platform-dependent macros
18  */
19 
20 #if defined(_MSC_VER)
21 
22 #include <stdlib.h>
23 
24 #define GU_ROTL32(x,y) _rotl(x,y)
25 #define GU_ROTL64(x,y) _rotl64(x,y)
26 
27 #else /* !defined(_MSC_VER) */
28 
29 static GU_FORCE_INLINE uint32_t GU_ROTL32 (uint32_t x, int8_t r)
30 {
31  return (x << r) | (x >> (32 - r));
32 }
33 
34 static GU_FORCE_INLINE uint64_t GU_ROTL64 (uint64_t x, int8_t r)
35 {
36  return (x << r) | (x >> (64 - r));
37 }
38 
39 #endif /* !defined(_MSC_VER) */
40 
41 /*
42  * End of paltform-dependent macros
43  */
44 
45 #if defined(HAVE_BYTESWAP_H)
46 # include <byteswap.h> // for bswap_16(x), bswap_32(x), bswap_64(x)
47 #elif defined(__APPLE__)
48 # include <libkern/OSByteOrder.h> // for OSSwapInt16(x), etc.
49 #endif /* HAVE_BYTESWAP_H */
50 
51 #if defined(__APPLE__)
52 /* do not use OSSwapIntXX, because gcc44 gives old-style cast warnings */
53 # define gu_bswap16 _OSSwapInt16
54 # define gu_bswap32 _OSSwapInt32
55 # define gu_bswap64 _OSSwapInt64
56 #elif defined(__FreeBSD__)
57 /* do not use bswapXX, because gcc44 gives old-style cast warnings */
58 # define gu_bswap16 __bswap16_var
59 # define gu_bswap32 __bswap32_var
60 # define gu_bswap64 __bswap64_var
61 #elif defined(__sun__) /* BSWAP macros inherited from gu_arch.h */
62 # define gu_bswap16 BSWAP_16
63 # define gu_bswap32 BSWAP_32
64 # define gu_bswap64 BSWAP_64
65 #elif defined(bswap16)
66 # define gu_bswap16 bswap16
67 # define gu_bswap32 bswap32
68 # define gu_bswap64 bswap64
69 #elif defined(bswap_16)
70 # define gu_bswap16 bswap_16
71 # define gu_bswap32 bswap_32
72 # define gu_bswap64 bswap_64
73 #else
74 # error "No byteswap macros are defined"
75 #endif
76 
77 /* @note: there are inline functions behind these macros below,
78  * so typesafety is taken care of... However C++ still has issues: */
79 #ifdef __cplusplus
80 // To pacify C++. Not loosing much optimization on 2 bytes anyways.
81 #include <stdint.h>
82 #undef gu_bswap16
83 static GU_FORCE_INLINE uint16_t gu_bswap16(uint16_t const x)
84 // Even though x is declared as 'uint16_t', g++-4.4.1 still treats results
85 // of operations with it as 'int' and freaks out on return with -Wconversion.
86 { return static_cast<uint16_t>((x >> 8) | (x << 8)); }
87 #endif // __cplusplus
88 
89 #if defined(GU_LITTLE_ENDIAN)
90 /* convert to/from Little Endian representation */
91 #define gu_le16(x) (x)
92 #define gu_le32(x) (x)
93 #define gu_le64(x) (x)
94 
95 /* convert to/from Big Endian representation */
96 #define gu_be16(x) gu_bswap16(x)
97 #define gu_be32(x) gu_bswap32(x)
98 #define gu_be64(x) gu_bswap64(x)
99 
100 #else /* Big-Endian */
101 
102 /* convert to/from Little Endian representation */
103 #define gu_le16(x) gu_bswap16(x)
104 #define gu_le32(x) gu_bswap32(x)
105 #define gu_le64(x) gu_bswap64(x)
106 
107 /* convert to/from Big Endian representation */
108 #define gu_be16(x) (x)
109 #define gu_be32(x) (x)
110 #define gu_be64(x) (x)
111 
112 #endif /* Big-Endian */
113 
114 /* Analogues to htonl and friends. Since we'll be dealing mostly with
115  * little-endian architectures, there is more sense to use little-endian
116  * as default */
117 #define htogs(x) gu_le16(x)
118 #define gtohs(x) htogs(x)
119 #define htogl(x) gu_le32(x)
120 #define gtohl(x) htogl(x)
121 
122 /* Analogues to htogs() and friends, suffixed with type width */
123 #define htog16(x) gu_le16(x)
124 #define gtoh16(x) htog16(x)
125 #define htog32(x) gu_le32(x)
126 #define gtoh32(x) htog32(x)
127 #define htog64(x) gu_le64(x)
128 #define gtoh64(x) htog64(x)
129 
130 #endif /* _gu_byteswap_h_ */