archive_endian.h revision 302001
1/*-
2 * Copyright (c) 2002 Thomas Moestl <tmm@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: stable/10/contrib/libarchive/libarchive/archive_endian.h 302001 2016-06-17 22:40:10Z mm $
27 *
28 * Borrowed from FreeBSD's <sys/endian.h>
29 */
30
31#ifndef __LIBARCHIVE_BUILD
32#error This header is only to be used internally to libarchive.
33#endif
34
35/* Note:  This is a purely internal header! */
36/* Do not use this outside of libarchive internal code! */
37
38#ifndef ARCHIVE_ENDIAN_H_INCLUDED
39#define ARCHIVE_ENDIAN_H_INCLUDED
40
41
42/*
43 * Disabling inline keyword for compilers known to choke on it:
44 * - Watcom C++ in C code.  (For any version?)
45 * - SGI MIPSpro
46 * - Microsoft Visual C++ 6.0 (supposedly newer versions too)
47 * - IBM VisualAge 6 (XL v6)
48 * - Sun WorkShop C (SunPro) before 5.9
49 */
50#if defined(__WATCOMC__) || defined(__sgi) || defined(__hpux) || defined(__BORLANDC__)
51#define	inline
52#elif defined(__IBMC__) && __IBMC__ < 700
53#define	inline
54#elif defined(__SUNPRO_C) && __SUNPRO_C < 0x590
55#define inline
56#elif defined(_MSC_VER) || defined(__osf__)
57#define inline __inline
58#endif
59
60/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */
61
62static inline uint16_t
63archive_be16dec(const void *pp)
64{
65	unsigned char const *p = (unsigned char const *)pp;
66
67	/* Store into unsigned temporaries before left shifting, to avoid
68	promotion to signed int and then left shifting into the sign bit,
69	which is undefined behaviour. */
70	unsigned int p1 = p[1];
71	unsigned int p0 = p[0];
72
73	return ((p0 << 8) | p1);
74}
75
76static inline uint32_t
77archive_be32dec(const void *pp)
78{
79	unsigned char const *p = (unsigned char const *)pp;
80
81	/* Store into unsigned temporaries before left shifting, to avoid
82	promotion to signed int and then left shifting into the sign bit,
83	which is undefined behaviour. */
84	unsigned int p3 = p[3];
85	unsigned int p2 = p[2];
86	unsigned int p1 = p[1];
87	unsigned int p0 = p[0];
88
89	return ((p0 << 24) | (p1 << 16) | (p2 << 8) | p3);
90}
91
92static inline uint64_t
93archive_be64dec(const void *pp)
94{
95	unsigned char const *p = (unsigned char const *)pp;
96
97	return (((uint64_t)archive_be32dec(p) << 32) | archive_be32dec(p + 4));
98}
99
100static inline uint16_t
101archive_le16dec(const void *pp)
102{
103	unsigned char const *p = (unsigned char const *)pp;
104
105	/* Store into unsigned temporaries before left shifting, to avoid
106	promotion to signed int and then left shifting into the sign bit,
107	which is undefined behaviour. */
108	unsigned int p1 = p[1];
109	unsigned int p0 = p[0];
110
111	return ((p1 << 8) | p0);
112}
113
114static inline uint32_t
115archive_le32dec(const void *pp)
116{
117	unsigned char const *p = (unsigned char const *)pp;
118
119	/* Store into unsigned temporaries before left shifting, to avoid
120	promotion to signed int and then left shifting into the sign bit,
121	which is undefined behaviour. */
122	unsigned int p3 = p[3];
123	unsigned int p2 = p[2];
124	unsigned int p1 = p[1];
125	unsigned int p0 = p[0];
126
127	return ((p3 << 24) | (p2 << 16) | (p1 << 8) | p0);
128}
129
130static inline uint64_t
131archive_le64dec(const void *pp)
132{
133	unsigned char const *p = (unsigned char const *)pp;
134
135	return (((uint64_t)archive_le32dec(p + 4) << 32) | archive_le32dec(p));
136}
137
138static inline void
139archive_be16enc(void *pp, uint16_t u)
140{
141	unsigned char *p = (unsigned char *)pp;
142
143	p[0] = (u >> 8) & 0xff;
144	p[1] = u & 0xff;
145}
146
147static inline void
148archive_be32enc(void *pp, uint32_t u)
149{
150	unsigned char *p = (unsigned char *)pp;
151
152	p[0] = (u >> 24) & 0xff;
153	p[1] = (u >> 16) & 0xff;
154	p[2] = (u >> 8) & 0xff;
155	p[3] = u & 0xff;
156}
157
158static inline void
159archive_be64enc(void *pp, uint64_t u)
160{
161	unsigned char *p = (unsigned char *)pp;
162
163	archive_be32enc(p, (uint32_t)(u >> 32));
164	archive_be32enc(p + 4, (uint32_t)(u & 0xffffffff));
165}
166
167static inline void
168archive_le16enc(void *pp, uint16_t u)
169{
170	unsigned char *p = (unsigned char *)pp;
171
172	p[0] = u & 0xff;
173	p[1] = (u >> 8) & 0xff;
174}
175
176static inline void
177archive_le32enc(void *pp, uint32_t u)
178{
179	unsigned char *p = (unsigned char *)pp;
180
181	p[0] = u & 0xff;
182	p[1] = (u >> 8) & 0xff;
183	p[2] = (u >> 16) & 0xff;
184	p[3] = (u >> 24) & 0xff;
185}
186
187static inline void
188archive_le64enc(void *pp, uint64_t u)
189{
190	unsigned char *p = (unsigned char *)pp;
191
192	archive_le32enc(p, (uint32_t)(u & 0xffffffff));
193	archive_le32enc(p + 4, (uint32_t)(u >> 32));
194}
195
196#endif
197