1 /*
2     Copyright (C) 2000, 2004 Herbert Valerio Riedel <hvr@gnu.org>
3     Copyright (C) 2005, 2008, 2012, 2015 Rocky Bernstein <rocky@gnu.org>
4 
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 /** \file bytesex.h
20  *  \brief  Generic Byte-swapping routines.
21  *
22  *   Note: this header will is slated to get removed and libcdio will
23  *   use glib.h routines instead.
24 */
25 
26 #ifndef CDIO_BYTESEX_H_
27 #define CDIO_BYTESEX_H_
28 
29 #include <cdio/types.h>
30 #include <cdio/bytesex_asm.h> /* also defines CDIO_INLINE */
31 #include <cdio/logging.h>
32 
33 /** 16-bit big-endian to little-endian */
34 #define UINT16_SWAP_LE_BE_C(val) ((uint16_t) ( \
35     (((uint16_t) (val) & (uint16_t) 0x00ffU) << 8) | \
36     (((uint16_t) (val) & (uint16_t) 0xff00U) >> 8)))
37 
38 /** 32-bit big-endian to little-endian */
39 #define UINT32_SWAP_LE_BE_C(val) ((uint32_t) ( \
40     (((uint32_t) (val) & (uint32_t) 0x000000ffU) << 24) | \
41     (((uint32_t) (val) & (uint32_t) 0x0000ff00U) <<  8) | \
42     (((uint32_t) (val) & (uint32_t) 0x00ff0000U) >>  8) | \
43     (((uint32_t) (val) & (uint32_t) 0xff000000U) >> 24)))
44 
45 /** 64-bit big-endian to little-endian */
46 #define UINT64_SWAP_LE_BE_C(val) ((uint64_t) ( \
47     (((uint64_t) (val) & (uint64_t) UINT64_C(0x00000000000000ff)) << 56) | \
48     (((uint64_t) (val) & (uint64_t) UINT64_C(0x000000000000ff00)) << 40) | \
49     (((uint64_t) (val) & (uint64_t) UINT64_C(0x0000000000ff0000)) << 24) | \
50     (((uint64_t) (val) & (uint64_t) UINT64_C(0x00000000ff000000)) <<  8) | \
51     (((uint64_t) (val) & (uint64_t) UINT64_C(0x000000ff00000000)) >>  8) | \
52     (((uint64_t) (val) & (uint64_t) UINT64_C(0x0000ff0000000000)) >> 24) | \
53     (((uint64_t) (val) & (uint64_t) UINT64_C(0x00ff000000000000)) >> 40) | \
54     (((uint64_t) (val) & (uint64_t) UINT64_C(0xff00000000000000)) >> 56)))
55 
56 #ifndef UINT16_SWAP_LE_BE
57 # define UINT16_SWAP_LE_BE UINT16_SWAP_LE_BE_C
58 #endif
59 
60 #ifndef UINT32_SWAP_LE_BE
61 # define UINT32_SWAP_LE_BE UINT32_SWAP_LE_BE_C
62 #endif
63 
64 #ifndef UINT64_SWAP_LE_BE
65 # define UINT64_SWAP_LE_BE UINT64_SWAP_LE_BE_C
66 #endif
67 
68 static CDIO_INLINE
uint16_swap_le_be(const uint16_t val)69 uint16_t uint16_swap_le_be (const uint16_t val)
70 {
71   return UINT16_SWAP_LE_BE (val);
72 }
73 
74 static CDIO_INLINE
uint32_swap_le_be(const uint32_t val)75 uint32_t uint32_swap_le_be (const uint32_t val)
76 {
77   return UINT32_SWAP_LE_BE (val);
78 }
79 
80 static CDIO_INLINE
uint64_swap_le_be(const uint64_t val)81 uint64_t uint64_swap_le_be (const uint64_t val)
82 {
83   return UINT64_SWAP_LE_BE (val);
84 }
85 
86 # define UINT8_TO_BE(val)      ((uint8_t) (val))
87 # define UINT8_TO_LE(val)      ((uint8_t) (val))
88 #ifdef WORDS_BIGENDIAN
89 # define UINT16_TO_BE(val)     ((uint16_t) (val))
90 # define UINT16_TO_LE(val)     ((uint16_t) UINT16_SWAP_LE_BE(val))
91 
92 # define UINT32_TO_BE(val)     ((uint32_t) (val))
93 # define UINT32_TO_LE(val)     ((uint32_t) UINT32_SWAP_LE_BE(val))
94 
95 # define UINT64_TO_BE(val)     ((uint64_t) (val))
96 # define UINT64_TO_LE(val)     ((uint64_t) UINT64_SWAP_LE_BE(val))
97 #else
98 # define UINT16_TO_BE(val)     ((uint16_t) UINT16_SWAP_LE_BE(val))
99 # define UINT16_TO_LE(val)     ((uint16_t) (val))
100 
101 # define UINT32_TO_BE(val)     ((uint32_t) UINT32_SWAP_LE_BE(val))
102 # define UINT32_TO_LE(val)     ((uint32_t) (val))
103 
104 # define UINT64_TO_BE(val)     ((uint64_t) UINT64_SWAP_LE_BE(val))
105 # define UINT64_TO_LE(val)     ((uint64_t) (val))
106 #endif
107 
108 /** symmetric conversions */
109 #define UINT8_FROM_BE(val)     (UINT8_TO_BE (val))
110 #define UINT8_FROM_LE(val)     (UINT8_TO_LE (val))
111 #define UINT16_FROM_BE(val)    (UINT16_TO_BE (val))
112 #define UINT16_FROM_LE(val)    (UINT16_TO_LE (val))
113 #define UINT32_FROM_BE(val)    (UINT32_TO_BE (val))
114 #define UINT32_FROM_LE(val)    (UINT32_TO_LE (val))
115 #define UINT64_FROM_BE(val)    (UINT64_TO_BE (val))
116 #define UINT64_FROM_LE(val)    (UINT64_TO_LE (val))
117 
118 /** converter function template */
119 #define CVT_TO_FUNC(bits) \
120  static CDIO_INLINE uint ## bits ## _t \
121  uint ## bits ## _to_be (uint ## bits ## _t val) \
122  { return UINT ## bits ## _TO_BE (val); } \
123  static CDIO_INLINE uint ## bits ## _t \
124  uint ## bits ## _to_le (uint ## bits ## _t val) \
125  { return UINT ## bits ## _TO_LE (val); } \
126 
127 CVT_TO_FUNC(8)
128 CVT_TO_FUNC(16)
129 CVT_TO_FUNC(32)
130 CVT_TO_FUNC(64)
131 
132 #undef CVT_TO_FUNC
133 
134 #define uint8_from_be(val)     (uint8_to_be (val))
135 #define uint8_from_le(val)     (uint8_to_le (val))
136 #define uint16_from_be(val)    (uint16_to_be (val))
137 #define uint16_from_le(val)    (uint16_to_le (val))
138 #define uint32_from_be(val)    (uint32_to_be (val))
139 #define uint32_from_le(val)    (uint32_to_le (val))
140 #define uint64_from_be(val)    (uint64_to_be (val))
141 #define uint64_from_le(val)    (uint64_to_le (val))
142 
143 /** ISO9660-related field conversion routines */
144 
145 /** Convert from uint8_t to ISO 9660 7.1.1 format */
146 #define to_711(i)   uint8_to_le(i)
147 
148 /** Convert from ISO 9660 7.1.1 format to uint8_t */
149 #define from_711(i) uint8_from_le(i)
150 
151 /** Convert from uint16_t to ISO 9669 7.2.1 format */
152 #define to_721(i)   uint16_to_le(i)
153 
154 /** Convert from ISO 9660 7.2.1 format to uint16_t */
155 #define from_721(i) uint16_from_le(i)
156 
157 /** Convert from uint16_t to ISO 9669 7.2.2 format */
158 #define to_722(i)   uint16_to_be(i)
159 
160 /** Convert from ISO 9660 7.2.2 format to uint16_t */
161 #define from_722(i) uint16_from_be(i)
162 
163 /** Convert from uint16_t to ISO 9669 7.2.3 format */
164 static CDIO_INLINE uint32_t
to_723(uint16_t i)165 to_723(uint16_t i)
166 {
167   return uint32_swap_le_be(i) | i;
168 }
169 
170 /** Convert from ISO 9660 7.2.3 format to uint16_t */
171 static CDIO_INLINE uint16_t
from_723(uint32_t p)172 from_723 (uint32_t p)
173 {
174   uint8_t *u = (uint8_t *) &p;
175   /* Return the little-endian part always, to handle non-specs-compliant images */
176   return (u[0] | (u[1] << 8));
177 }
178 
179 static CDIO_INLINE uint16_t
from_723_with_err(uint32_t p,bool * err)180 from_723_with_err (uint32_t p, bool *err)
181 {
182   if (uint32_swap_le_be (p) != p) {
183     cdio_warn ("from_723: broken byte order");
184     *err = true;
185   } else {
186     *err = false;
187   }
188   return (0xFFFF & p);
189 }
190 
191 /** Convert from uint16_t to ISO 9669 7.3.1 format */
192 #define to_731(i)   uint32_to_le(i)
193 
194 /** Convert from ISO 9660 7.3.1 format to uint32_t */
195 #define from_731(i) uint32_from_le(i)
196 
197 /** Convert from uint32_t to ISO 9669 7.3.2 format */
198 #define to_732(i)   uint32_to_be(i)
199 
200 /** Convert from ISO 9660 7.3.2 format to uint32_t */
201 #define from_732(i) uint32_from_be(i)
202 
203 /** Convert from uint16_t to ISO 9669 7.3.3 format */
204 static CDIO_INLINE uint64_t
to_733(uint32_t i)205 to_733(uint32_t i)
206 {
207   return uint64_swap_le_be(i) | i;
208 }
209 
210 /** Convert from ISO 9660 7.3.3 format to uint32_t */
211 static CDIO_INLINE uint32_t
from_733(uint64_t p)212 from_733 (uint64_t p)
213 {
214   uint8_t *u = (uint8_t *) &p;
215   /* Return the little-endian part always, to handle non-specs-compliant images */
216   return (u[0] | (u[1] << 8) | (u[2] << 16) | (u[3] << 24));
217 }
218 
219 static CDIO_INLINE uint32_t
from_733_with_err(uint64_t p,bool * err)220 from_733_with_err (uint64_t p, bool *err)
221 {
222   if (uint64_swap_le_be (p) != p) {
223     cdio_warn ("from_733: broken byte order");
224     *err = true;
225   } else {
226     *err = false;
227   }
228   return (UINT32_C(0xFFFFFFFF) & p);
229 }
230 
231 #endif /* CDIO_BYTESEX_H_ */
232 
233 
234 /*
235  * Local variables:
236  *  c-file-style: "gnu"
237  *  tab-width: 8
238  *  indent-tabs-mode: nil
239  * End:
240  */
241