1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 1996,2008 Oracle.  All rights reserved.
5 */
6/*
7 * Copyright (c) 1990, 1993, 1994
8 *	The Regents of the University of California.  All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * $Id: db_swap.h,v 12.13 2008/05/05 20:26:04 mbrey Exp $
35 */
36
37#ifndef _DB_SWAP_H_
38#define	_DB_SWAP_H_
39
40#if defined(__cplusplus)
41extern "C" {
42#endif
43
44/*
45 * Little endian <==> big endian 64-bit swap macros.
46 *	M_64_SWAP	swap a memory location
47 *	P_64_COPY	copy potentially unaligned 4 byte quantities
48 *	P_64_SWAP	swap a referenced memory location
49 */
50#undef	M_64_SWAP
51#define	M_64_SWAP(a) {							\
52	u_int64_t _tmp;							\
53	_tmp = (u_int64_t)a;						\
54	((u_int8_t *)&a)[0] = ((u_int8_t *)&_tmp)[7];			\
55	((u_int8_t *)&a)[1] = ((u_int8_t *)&_tmp)[6];			\
56	((u_int8_t *)&a)[2] = ((u_int8_t *)&_tmp)[5];			\
57	((u_int8_t *)&a)[3] = ((u_int8_t *)&_tmp)[4];			\
58	((u_int8_t *)&a)[4] = ((u_int8_t *)&_tmp)[3];			\
59	((u_int8_t *)&a)[5] = ((u_int8_t *)&_tmp)[2];			\
60	((u_int8_t *)&a)[6] = ((u_int8_t *)&_tmp)[1];			\
61	((u_int8_t *)&a)[7] = ((u_int8_t *)&_tmp)[0];			\
62}
63#undef	P_64_COPY
64#define	P_64_COPY(a, b) {						\
65	((u_int8_t *)b)[0] = ((u_int8_t *)a)[0];			\
66	((u_int8_t *)b)[1] = ((u_int8_t *)a)[1];			\
67	((u_int8_t *)b)[2] = ((u_int8_t *)a)[2];			\
68	((u_int8_t *)b)[3] = ((u_int8_t *)a)[3];			\
69	((u_int8_t *)b)[4] = ((u_int8_t *)a)[4];			\
70	((u_int8_t *)b)[5] = ((u_int8_t *)a)[5];			\
71	((u_int8_t *)b)[6] = ((u_int8_t *)a)[6];			\
72	((u_int8_t *)b)[7] = ((u_int8_t *)a)[7];			\
73}
74#undef	P_64_SWAP
75#define	P_64_SWAP(a) {							\
76	u_int64_t _tmp;							\
77	P_64_COPY(a, &_tmp);						\
78	((u_int8_t *)a)[0] = ((u_int8_t *)&_tmp)[7];			\
79	((u_int8_t *)a)[1] = ((u_int8_t *)&_tmp)[6];			\
80	((u_int8_t *)a)[2] = ((u_int8_t *)&_tmp)[5];			\
81	((u_int8_t *)a)[3] = ((u_int8_t *)&_tmp)[4];			\
82	((u_int8_t *)a)[4] = ((u_int8_t *)&_tmp)[3];			\
83	((u_int8_t *)a)[5] = ((u_int8_t *)&_tmp)[2];			\
84	((u_int8_t *)a)[6] = ((u_int8_t *)&_tmp)[1];			\
85	((u_int8_t *)a)[7] = ((u_int8_t *)&_tmp)[0];			\
86}
87
88/*
89 * Little endian <==> big endian 32-bit swap macros.
90 *	P_32_COPY	copy potentially unaligned 4 byte quantities
91 *	P_32_COPYSWAP	copy and swap potentially unaligned 4 byte quantities
92 *	P_32_SWAP	swap a referenced memory location
93 *	M_32_SWAP	swap a memory location
94 */
95#undef	P_32_COPY
96#define	P_32_COPY(a, b) do {						\
97	((u_int8_t *)b)[0] = ((u_int8_t *)a)[0];			\
98	((u_int8_t *)b)[1] = ((u_int8_t *)a)[1];			\
99	((u_int8_t *)b)[2] = ((u_int8_t *)a)[2];			\
100	((u_int8_t *)b)[3] = ((u_int8_t *)a)[3];			\
101} while (0)
102#undef	P_32_COPYSWAP
103#define	P_32_COPYSWAP(a, b) do {					\
104	((u_int8_t *)b)[0] = ((u_int8_t *)a)[3];			\
105	((u_int8_t *)b)[1] = ((u_int8_t *)a)[2];			\
106	((u_int8_t *)b)[2] = ((u_int8_t *)a)[1];			\
107	((u_int8_t *)b)[3] = ((u_int8_t *)a)[0];			\
108} while (0)
109#undef	P_32_SWAP
110#define	P_32_SWAP(a) do {						\
111	u_int32_t _tmp;							\
112	P_32_COPY(a, &_tmp);						\
113	P_32_COPYSWAP(&_tmp, a);					\
114} while (0)
115#undef	M_32_SWAP
116#define	M_32_SWAP(a) P_32_SWAP(&a)
117
118/*
119 * Little endian <==> big endian 16-bit swap macros.
120 *	P_16_COPY	copy potentially unaligned 2 byte quantities
121 *	P_16_COPYSWAP	copy and swap potentially unaligned 2 byte quantities
122 *	P_16_SWAP	swap a referenced memory location
123 *	M_16_SWAP	swap a memory location
124 */
125#undef	P_16_COPY
126#define	P_16_COPY(a, b) do {						\
127	((u_int8_t *)b)[0] = ((u_int8_t *)a)[0];			\
128	((u_int8_t *)b)[1] = ((u_int8_t *)a)[1];			\
129} while (0)
130#undef	P_16_COPYSWAP
131#define	P_16_COPYSWAP(a, b) do {					\
132	((u_int8_t *)b)[0] = ((u_int8_t *)a)[1];			\
133	((u_int8_t *)b)[1] = ((u_int8_t *)a)[0];			\
134} while (0)
135#undef	P_16_SWAP
136#define	P_16_SWAP(a) do {						\
137	u_int16_t _tmp;							\
138	P_16_COPY(a, &_tmp);						\
139	P_16_COPYSWAP(&_tmp, a);					\
140} while (0)
141#undef	M_16_SWAP
142#define	M_16_SWAP(a) P_16_SWAP(&a)
143
144#undef	SWAP32
145#define	SWAP32(p) {							\
146	P_32_SWAP(p);							\
147	(p) += sizeof(u_int32_t);					\
148}
149#undef	SWAP16
150#define	SWAP16(p) {							\
151	P_16_SWAP(p);							\
152	(p) += sizeof(u_int16_t);					\
153}
154
155/*
156 * Berkeley DB has local versions of htonl() and ntohl() that operate on
157 * pointers to the right size memory locations; the portability magic for
158 * finding the real system functions isn't worth the effort.
159 */
160#undef	DB_HTONL_SWAP
161#define	DB_HTONL_SWAP(env, p) do {					\
162	if (F_ISSET((env), ENV_LITTLEENDIAN))				\
163		P_32_SWAP(p);						\
164} while (0)
165#undef	DB_NTOHL_SWAP
166#define	DB_NTOHL_SWAP(env, p) do {					\
167	if (F_ISSET((env), ENV_LITTLEENDIAN))				\
168		P_32_SWAP(p);						\
169} while (0)
170
171#undef	DB_NTOHL_COPYIN
172#define	DB_NTOHL_COPYIN(env, i, p) do {					\
173	u_int8_t *tmp;							\
174	tmp = (u_int8_t *)&(i);						\
175	if (F_ISSET(env, ENV_LITTLEENDIAN)) {				\
176		tmp[3] = *p++;						\
177		tmp[2] = *p++;						\
178		tmp[1] = *p++;						\
179		tmp[0] = *p++;						\
180	} else {							\
181		memcpy(&i, p, sizeof(u_int32_t));			\
182		p = (u_int8_t *)p + sizeof(u_int32_t);			\
183	}								\
184} while (0)
185
186#undef	DB_NTOHS_COPYIN
187#define	DB_NTOHS_COPYIN(env, i, p) do {					\
188	u_int8_t *tmp;							\
189	tmp = (u_int8_t *)&(i);						\
190	if (F_ISSET(env, ENV_LITTLEENDIAN)) {				\
191		tmp[1] = *p++;						\
192		tmp[0] = *p++;						\
193	} else {							\
194		memcpy(&i, p, sizeof(u_int16_t));			\
195		p = (u_int8_t *)p + sizeof(u_int16_t);			\
196	}								\
197} while (0)
198
199#undef	DB_HTONL_COPYOUT
200#define	DB_HTONL_COPYOUT(env, p, i) do {				\
201	u_int8_t *tmp;							\
202	tmp = (u_int8_t *)p;						\
203	if (F_ISSET(env, ENV_LITTLEENDIAN)) {				\
204		*tmp++ = ((u_int8_t *)&(i))[3];				\
205		*tmp++ = ((u_int8_t *)&(i))[2];				\
206		*tmp++ = ((u_int8_t *)&(i))[1];				\
207		*tmp++ = ((u_int8_t *)&(i))[0];				\
208	} else								\
209		memcpy(p, &i, sizeof(u_int32_t));			\
210	p = (u_int8_t *)p + sizeof(u_int32_t);				\
211} while (0)
212
213#undef	DB_HTONS_COPYOUT
214#define	DB_HTONS_COPYOUT(env, p, i) do {				\
215	u_int8_t *tmp;							\
216	tmp = (u_int8_t *)p;						\
217	if (F_ISSET(env, ENV_LITTLEENDIAN)) {				\
218		*tmp++ = ((u_int8_t *)&(i))[1];				\
219		*tmp++ = ((u_int8_t *)&(i))[0];				\
220	} else								\
221		memcpy(p, &i, sizeof(u_int16_t));			\
222	p = (u_int8_t *)p + sizeof(u_int16_t);				\
223} while (0)
224
225/*
226 * Helper macros for swapped logs.  We write logs in little endian format to
227 * minimize disruption on x86 when upgrading from native byte order to
228 * platform-independent logs.
229 */
230#define	LOG_SWAPPED(env) !F_ISSET(env, ENV_LITTLEENDIAN)
231
232#define	LOGCOPY_32(env, x, p) do {					\
233	if (LOG_SWAPPED(env))						\
234		P_32_COPYSWAP((p), (x));				\
235	else								\
236		memcpy((x), (p), sizeof (u_int32_t));			\
237} while (0)
238
239#define	LOGCOPY_16(env, x, p) do {					\
240	if (LOG_SWAPPED(env))						\
241		P_16_COPYSWAP((p), (x));				\
242	else								\
243		memcpy((x), (p), sizeof (u_int16_t));			\
244} while (0)
245
246#define	LOGCOPY_TOLSN(env, lsnp, p) do {				\
247	LOGCOPY_32((env), &(lsnp)->file, (p));				\
248	LOGCOPY_32((env), &(lsnp)->offset, 				\
249	    (u_int8_t *)(p) + sizeof (u_int32_t));			\
250} while (0)
251
252#define	LOGCOPY_FROMLSN(env, p, lsnp) do {				\
253	LOGCOPY_32((env), (p), &(lsnp)->file);				\
254	LOGCOPY_32((env),						\
255	    (u_int8_t *)(p) + sizeof (u_int32_t), &(lsnp)->offset);	\
256} while (0)
257
258#if defined(__cplusplus)
259}
260#endif
261
262#endif /* !_DB_SWAP_H_ */
263