blob: 386361c64ccd1b26ca5b8e8eb5f5010c1f5661bc [file] [log] [blame]
Alexandre Lision7c6f4a62013-09-05 13:27:01 -04001/*
2** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
3**
4** This program is free software; you can redistribute it and/or modify
5** it under the terms of the GNU Lesser General Public License as published by
6** the Free Software Foundation; either version 2.1 of the License, or
7** (at your option) any later version.
8**
9** This program is distributed in the hope that it will be useful,
10** but WITHOUT ANY WARRANTY; without even the implied warranty of
11** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12** GNU Lesser General Public License for more details.
13**
14** You should have received a copy of the GNU Lesser General Public License
15** along with this program; if not, write to the Free Software
16** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17*/
18
19#ifndef SFENDIAN_INCLUDED
20#define SFENDIAN_INCLUDED
21
22#include "sfconfig.h"
23
24#if HAVE_STDINT_H
25#include <stdint.h>
26#elif HAVE_INTTYPES_H
27#include <inttypes.h>
28#endif
29
30#if (defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8))
31/* Good, we have int64_t. */
32#elif (defined (SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8))
33typedef long long int64_t ;
34#elif (defined (SIZEOF_LONG) && (SIZEOF_LONG == 8))
35typedef long int64_t ;
36#elif (defined (WIN32) || defined (_WIN32))
37typedef __int64 int64_t ;
38#else
39#error "No 64 bit integer type."
40#endif
41
42#if HAVE_BYTESWAP_H
43
44#include <byteswap.h>
45
46#define ENDSWAP_SHORT(x) ((short) bswap_16 (x))
47#define ENDSWAP_INT(x) ((int) bswap_32 (x))
48
49#else
50
51#define ENDSWAP_SHORT(x) ((((x) >> 8) & 0xFF) + (((x) & 0xFF) << 8))
52#define ENDSWAP_INT(x) ((((x) >> 24) & 0xFF) + (((x) >> 8) & 0xFF00) + (((x) & 0xFF00) << 8) + (((x) & 0xFF) << 24))
53
54#endif
55
56/*
57** Many file types (ie WAV, AIFF) use sets of four consecutive bytes as a
58** marker indicating different sections of the file.
59** The following MAKE_MARKER macro allows th creation of integer constants
60** for these markers.
61*/
62
63#if (CPU_IS_LITTLE_ENDIAN == 1)
64 #define MAKE_MARKER(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
65#elif (CPU_IS_BIG_ENDIAN == 1)
66 #define MAKE_MARKER(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
67#else
68 #error "Target CPU endian-ness unknown. May need to hand edit src/sfconfig.h"
69#endif
70
71/*
72** Macros to handle reading of data of a specific endian-ness into host endian
73** shorts and ints. The single input is an unsigned char* pointer to the start
74** of the object. There are two versions of each macro as we need to deal with
75** both big and little endian CPUs.
76*/
77
78#if (CPU_IS_LITTLE_ENDIAN == 1)
79 #define LES2H_SHORT(x) (x)
80 #define LEI2H_INT(x) (x)
81
82 #define BES2H_SHORT(x) ENDSWAP_SHORT (x)
83 #define BEI2H_INT(x) ENDSWAP_INT (x)
84
85 #define H2BE_SHORT(x) ENDSWAP_SHORT (x)
86 #define H2BE_INT(x) ENDSWAP_INT (x)
87
88#elif (CPU_IS_BIG_ENDIAN == 1)
89 #define LES2H_SHORT(x) ENDSWAP_SHORT (x)
90 #define LEI2H_INT(x) ENDSWAP_INT (x)
91
92 #define BES2H_SHORT(x) (x)
93 #define BEI2H_INT(x) (x)
94
95 #define H2LE_SHORT(x) ENDSWAP_SHORT (x)
96 #define H2LE_INT(x) ENDSWAP_INT (x)
97
98#else
99 #error "Target CPU endian-ness unknown. May need to hand edit src/sfconfig.h"
100#endif
101
102#define LET2H_SHORT_PTR(x) ((x) [1] + ((x) [2] << 8))
103#define LET2H_INT_PTR(x) (((x) [0] << 8) + ((x) [1] << 16) + ((x) [2] << 24))
104
105#define BET2H_SHORT_PTR(x) (((x) [0] << 8) + (x) [1])
106#define BET2H_INT_PTR(x) (((x) [0] << 24) + ((x) [1] << 16) + ((x) [2] << 8))
107
108/*-----------------------------------------------------------------------------------------------
109** Generic functions for performing endian swapping on integer arrays.
110*/
111
112static inline void
113endswap_short_array (short *ptr, int len)
114{ short temp ;
115
116 while (--len >= 0)
117 { temp = ptr [len] ;
118 ptr [len] = ENDSWAP_SHORT (temp) ;
119 } ;
120} /* endswap_short_array */
121
122static inline void
123endswap_short_copy (short *dest, const short *src, int len)
124{
125 while (--len >= 0)
126 { dest [len] = ENDSWAP_SHORT (src [len]) ;
127 } ;
128} /* endswap_short_copy */
129
130static inline void
131endswap_int_array (int *ptr, int len)
132{ int temp ;
133
134 while (--len >= 0)
135 { temp = ptr [len] ;
136 ptr [len] = ENDSWAP_INT (temp) ;
137 } ;
138} /* endswap_int_array */
139
140static inline void
141endswap_int_copy (int *dest, const int *src, int len)
142{
143 while (--len >= 0)
144 { dest [len] = ENDSWAP_INT (src [len]) ;
145 } ;
146} /* endswap_int_copy */
147
148/*========================================================================================
149*/
150
151#if (HAVE_BYTESWAP_H && defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8))
152
153static inline void
154endswap_int64_t_array (int64_t *ptr, int len)
155{ int64_t value ;
156
157 while (--len >= 0)
158 { value = ptr [len] ;
159 ptr [len] = bswap_64 (value) ;
160 } ;
161} /* endswap_int64_t_array */
162
163static inline void
164endswap_int64_t_copy (int64_t *dest, const int64_t *src, int len)
165{ int64_t value ;
166
167 while (--len >= 0)
168 { value = src [len] ;
169 dest [len] = bswap_64 (value) ;
170 } ;
171} /* endswap_int64_t_copy */
172
173#else
174
175static inline void
176endswap_int64_t_array (int64_t *ptr, int len)
177{ unsigned char *ucptr, temp ;
178
179 ucptr = (unsigned char *) ptr ;
180 ucptr += 8 * len ;
181 while (--len >= 0)
182 { ucptr -= 8 ;
183
184 temp = ucptr [0] ;
185 ucptr [0] = ucptr [7] ;
186 ucptr [7] = temp ;
187
188 temp = ucptr [1] ;
189 ucptr [1] = ucptr [6] ;
190 ucptr [6] = temp ;
191
192 temp = ucptr [2] ;
193 ucptr [2] = ucptr [5] ;
194 ucptr [5] = temp ;
195
196 temp = ucptr [3] ;
197 ucptr [3] = ucptr [4] ;
198 ucptr [4] = temp ;
199 } ;
200} /* endswap_int64_t_array */
201
202static inline void
203endswap_int64_t_copy (int64_t *dest, const int64_t *src, int len)
204{ const unsigned char *psrc ;
205 unsigned char *pdest ;
206
207 if (dest == src)
208 { endswap_int64_t_array (dest, len) ;
209 return ;
210 } ;
211
212 psrc = ((const unsigned char *) src) + 8 * len ;
213 pdest = ((unsigned char *) dest) + 8 * len ;
214 while (--len >= 0)
215 { psrc -= 8 ;
216 pdest -= 8 ;
217
218 pdest [0] = psrc [7] ;
219 pdest [2] = psrc [5] ;
220 pdest [4] = psrc [3] ;
221 pdest [6] = psrc [1] ;
222 pdest [7] = psrc [0] ;
223 pdest [1] = psrc [6] ;
224 pdest [3] = psrc [4] ;
225 pdest [5] = psrc [2] ;
226 } ;
227} /* endswap_int64_t_copy */
228
229#endif
230
231/* A couple of wrapper functions. */
232
233static inline void
234endswap_float_array (float *ptr, int len)
235{ endswap_int_array ((void *) ptr, len) ;
236} /* endswap_float_array */
237
238static inline void
239endswap_double_array (double *ptr, int len)
240{ endswap_int64_t_array ((void *) ptr, len) ;
241} /* endswap_double_array */
242
243static inline void
244endswap_float_copy (float *dest, const float *src, int len)
245{ endswap_int_copy ((int *) dest, (const int *) src, len) ;
246} /* endswap_float_copy */
247
248static inline void
249endswap_double_copy (double *dest, const double *src, int len)
250{ endswap_int64_t_copy ((int64_t *) dest, (const int64_t *) src, len) ;
251} /* endswap_double_copy */
252
253#endif /* SFENDIAN_INCLUDED */
254