1 /*
2  *  $Id$
3  *
4  *  Reverse bytes in 2, 4 and 8 byte objects
5  *
6  *  Copyright 2000-2000 Saikat DebRoy <saikat@stat.wisc.edu>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be
14  *  useful, but WITHOUT ANY WARRANTY; without even the implied
15  *  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16  *  PURPOSE.  See the GNU General Public License for more
17  *  details.
18  *
19  *  You should have received a copy of the GNU General Public
20  *  License along with this program; if not, write to the Free
21  *  Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22  *  MA 02111-1307, USA
23  *
24  */
25 
26 #ifndef SWAP_BYTES_H
27 #define SWAP_BYTES_H
28 
29 #ifdef HAVE_BYTESWAP_H  /* use GNU bswap macros */
30 
31 #include <byteswap.h>
32 
33 #define swap_bytes_16(from, to) do { (to) = bswap_16(from); } while (0)
34 
35 #define swap_bytes_32(from, to) do { (to) = bswap_32(from); } while (0)
36 
37 #if defined __GNUC__ && __GNUC__ >= 2
38 
39 #define swap_bytes_double(from, to)		\
40 do {						\
41     union {					\
42 	unsigned long long int u64;		\
43 	double d;				\
44     } from__, to__;				\
45     from__.d = (from);				\
46     to__.u64 = bswap_64(from__.u64);		\
47     (to) = to__.d;				\
48 } while (0)
49 
50 #else
51 
52 #define swap_bytes_double(from, to)		\
53 do {						\
54     union {					\
55 	unsigned int u32[2];			\
56 	double d;				\
57     } from__, to__;				\
58     from__.d = (from);  			\
59     swap_bytes_32(from__.u32[1], to__.u32[0]);	\
60     swap_bytes_32(from__.u32[0], to__.u32[1]);	\
61     (to) = to__.d;				\
62 } while (0)
63 
64 #endif
65 
66 #else /* use reasonably portable definitions */
67 
68 #define swap_bytes_16(from, to)						\
69 do {									\
70     unsigned short from__16 = (from);					\
71     (to) = ((((from__16) >> 8) & 0xff) | (((from__16) & 0xff) << 8));	\
72 } while (0)
73 
74 #define swap_bytes_32(from, to)			\
75 do {						\
76     unsigned int from__32 = (from);		\
77     (to) = (((from__32 & 0xff000000) >> 24) |	\
78 	    ((from__32 & 0x00ff0000) >>  8) |	\
79 	    ((from__32 & 0x0000ff00) <<  8) |	\
80 	    ((from__32 & 0x000000ff) << 24));	\
81 } while (0)
82 
83 #define swap_bytes_double(from, to)		\
84 do {						\
85     union {					\
86 	unsigned int u32[2];			\
87 	double d;				\
88     } from__, to__;				\
89     from__.d = (from);  			\
90     swap_bytes_32(from__.u32[1], to__.u32[0]);	\
91     swap_bytes_32(from__.u32[0], to__.u32[1]);	\
92     (to) = to__.d;				\
93 } while (0)
94 
95 #endif  /* HAVE_BYTESWAP_H or not */
96 
97 #define swap_bytes_ushort(from, to) swap_bytes_16(from, to)
98 
99 #define reverse_ushort(x) swap_bytes_16(x, x)
100 
101 #define swap_bytes_short(from, to)              \
102 do {						\
103     union {					\
104 	unsigned short u16;			\
105 	short          s16;			\
106     } from__, to__;				\
107     from__.s16 = (from);			\
108     swap_bytes_16(from__.u16, to__.u16);	\
109     (to) = to__.s16;				\
110 } while (0)
111 
112 #define reverse_short(x)                        \
113 do {						\
114     union {					\
115 	unsigned short u16;			\
116 	short          s16;			\
117     } from__, to__;				\
118     from__.s16 = (x);    			\
119     swap_bytes_16(from__.u16, to__.u16);	\
120     (x) = to__.s16;				\
121 } while (0)
122 
123 #define swap_bytes_uint(from, to) swap_bytes_32(from, to)
124 
125 #define reverse_uint(x) swap_bytes_32(x, x)
126 
127 #define swap_bytes_int(from, to)                \
128 do {						\
129     union {					\
130 	unsigned int u32;			\
131 	int          s32;			\
132     } from__, to__;				\
133     from__.s32 = (from);			\
134     swap_bytes_32(from__.u32, to__.u32);	\
135     (to) = to__.s32;				\
136 } while (0)
137 
138 #define reverse_int(x)                          \
139 do {						\
140     union {					\
141 	unsigned int u32;			\
142 	int          s32;			\
143     } from__, to__;				\
144     from__.s32 = (x);    			\
145     swap_bytes_32(from__.u32, to__.u32);	\
146     (x) = to__.s32;				\
147 } while (0)
148 
149 #define swap_bytes_float(from, to)		\
150 do {						\
151     union {					\
152 	unsigned int u32;			\
153 	float f;				\
154     } from__, to__;				\
155     from__.f = (from);				\
156     swap_bytes_32(from__.u32, to__.u32);	\
157     (to) = to__.f;				\
158 } while (0)
159 
160 #define reverse_float(x)        		\
161 do {						\
162     union {					\
163 	unsigned int u32;			\
164 	float f;				\
165     } from__, to__;				\
166     from__.f = (x);				\
167     swap_bytes_32(from__.u32, to__.u32);	\
168     (x) = to__.f;				\
169 } while (0)
170 
171 #define reverse_double(x) swap_bytes_double(x, x)
172 
173 #endif /* SWAP_BYTES_H */
174