• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2  ** Copyright (C) 1999-2018 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  #include <stdint.h>
25  #include <inttypes.h>
26  
27  #if HAVE_BYTESWAP_H			/* Linux, any CPU */
28  #include <byteswap.h>
29  
30  #define	ENDSWAP_16(x)		(bswap_16 (x))
31  #define	ENDSWAP_32(x)		(bswap_32 (x))
32  #define	ENDSWAP_64(x)		(bswap_64 (x))
33  
34  #elif defined __has_builtin
35  
36  #if __has_builtin (__builtin_bswap16)
37  #define ENDSWAP_16(x) ((int16_t) __builtin_bswap16 ((uint16_t) x))
38  #endif
39  
40  #if __has_builtin (__builtin_bswap32)
41  #define ENDSWAP_32(x) ((int32_t) __builtin_bswap32 ((uint32_t) x))
42  #endif
43  
44  #if __has_builtin (__builtin_bswap64)
45  #define ENDSWAP_64(x) ((int64_t) __builtin_bswap64 ((uint64_t) x))
46  #endif
47  
48  #elif COMPILER_IS_GCC
49  
50  #if CPU_IS_X86
51  
52  static inline int16_t
ENDSWAP_16X(int16_t x)53  ENDSWAP_16X (int16_t x)
54  {	int16_t y ;
55  	__asm__ ("rorw $8, %w0" : "=r" (y) : "0" (x) : "cc") ;
56  	return y ;
57  } /* ENDSWAP_16 */
58  
59  static inline int32_t
ENDSWAP_32X(int32_t x)60  ENDSWAP_32X (int32_t x)
61  {	int32_t y ;
62  	__asm__ ("bswap %0" : "=r" (y) : "0" (x)) ;
63  	return y ;
64  } /* ENDSWAP_32 */
65  
66  #define ENDSWAP_16 ENDSWAP_16X
67  #define ENDSWAP_32 ENDSWAP_32X
68  
69  #endif
70  
71  #if CPU_IS_X86_64
72  
73  static inline int64_t
ENDSWAP_64X(int64_t x)74  ENDSWAP_64X (int64_t x)
75  {	int64_t y ;
76  	__asm__ ("bswap %q0" : "=r" (y) : "0" (x)) ;
77  	return y ;
78  } /* ENDSWAP_64X */
79  
80  #define ENDSWAP_64 ENDSWAP_64X
81  
82  #endif
83  
84  #elif defined _MSC_VER
85  #include <stdlib.h>
86  
87  #define	ENDSWAP_16(x)		(_byteswap_ushort (x))
88  #define	ENDSWAP_32(x)		(_byteswap_ulong (x))
89  #define	ENDSWAP_64(x)		(_byteswap_uint64 (x))
90  
91  #endif
92  
93  #ifndef ENDSWAP_16
94  #define	ENDSWAP_16(x)		((((x) >> 8) & 0xFF) + (((x) & 0xFF) << 8))
95  #endif
96  
97  #ifndef ENDSWAP_32
98  #define	ENDSWAP_32(x)		((((x) >> 24) & 0xFF) + (((x) >> 8) & 0xFF00) + (((x) & 0xFF00) << 8) + (((x) & 0xFF) << 24))
99  #endif
100  
101  #ifndef ENDSWAP_64
102  static inline uint64_t
ENDSWAP_64(uint64_t x)103  ENDSWAP_64 (uint64_t x)
104  {	union
105  	{	uint32_t parts [2] ;
106  		uint64_t whole ;
107  	} u ;
108  	uint32_t temp ;
109  
110  	u.whole = x ;
111  	temp = u.parts [0] ;
112  	u.parts [0] = ENDSWAP_32 (u.parts [1]) ;
113  	u.parts [1] = ENDSWAP_32 (temp) ;
114  	return u.whole ;
115  }
116  #endif
117  
118  /*
119  ** Many file types (ie WAV, AIFF) use sets of four consecutive bytes as a
120  ** marker indicating different sections of the file.
121  ** The following MAKE_MARKER macro allows th creation of integer constants
122  ** for these markers.
123  */
124  
125  #if (CPU_IS_LITTLE_ENDIAN == 1)
126  	#define	MAKE_MARKER(a, b, c, d)		((uint32_t) ((a) | ((b) << 8) | ((c) << 16) | (((uint32_t) (d)) << 24)))
127  #elif (CPU_IS_BIG_ENDIAN == 1)
128  	#define	MAKE_MARKER(a, b, c, d)		((uint32_t) ((((uint32_t) (a)) << 24) | ((b) << 16) | ((c) << 8) | (d)))
129  #else
130  	#error "Target CPU endian-ness unknown. May need to hand edit src/sfconfig.h"
131  #endif
132  
133  /*
134  ** Macros to handle reading of data of a specific endian-ness into host endian
135  ** shorts and ints. The single input is an unsigned char* pointer to the start
136  ** of the object. There are two versions of each macro as we need to deal with
137  ** both big and little endian CPUs.
138  */
139  
140  #if (CPU_IS_LITTLE_ENDIAN == 1)
141  	#define LE2H_16(x)			(x)
142  	#define LE2H_32(x)			(x)
143  
144  	#define BE2H_16(x)			ENDSWAP_16 (x)
145  	#define BE2H_32(x)			ENDSWAP_32 (x)
146  	#define BE2H_64(x)			ENDSWAP_64 (x)
147  
148  	#define H2BE_16(x)			ENDSWAP_16 (x)
149  	#define H2BE_32(x)			ENDSWAP_32 (x)
150  
151  	#define H2LE_16(x)			(x)
152  	#define H2LE_32(x)			(x)
153  
154  #elif (CPU_IS_BIG_ENDIAN == 1)
155  	#define LE2H_16(x)			ENDSWAP_16 (x)
156  	#define LE2H_32(x)			ENDSWAP_32 (x)
157  
158  	#define BE2H_16(x)			(x)
159  	#define BE2H_32(x)			(x)
160  	#define	BE2H_64(x)			(x)
161  
162  	#define H2BE_16(x)			(x)
163  	#define H2BE_32(x)			(x)
164  
165  	#define H2LE_16(x)			ENDSWAP_16 (x)
166  	#define H2LE_32(x)			ENDSWAP_32 (x)
167  
168  #else
169  	#error "Target CPU endian-ness unknown. May need to hand edit src/sfconfig.h"
170  #endif
171  
172  #define LE2H_32_PTR(x)			(((x) [0]) + ((x) [1] << 8) + ((x) [2] << 16) + ((x) [3] << 24))
173  
174  #define LET2H_16_PTR(x)			((x) [1] + ((x) [2] << 8))
175  #define LET2H_32_PTR(x)			(((x) [0] << 8) + ((x) [1] << 16) + ((x) [2] << 24))
176  
177  #define BET2H_16_PTR(x)			(((x) [0] << 8) + (x) [1])
178  #define BET2H_32_PTR(x)			(((x) [0] << 24) + ((x) [1] << 16) + ((x) [2] << 8))
179  
180  static inline void
psf_put_be64(uint8_t * ptr,int offset,int64_t value)181  psf_put_be64 (uint8_t *ptr, int offset, int64_t value)
182  {
183  	ptr [offset] = (uint8_t) (value >> 56) ;
184  	ptr [offset + 1] = (uint8_t) (value >> 48) ;
185  	ptr [offset + 2] = (uint8_t) (value >> 40) ;
186  	ptr [offset + 3] = (uint8_t) (value >> 32) ;
187  	ptr [offset + 4] = (uint8_t) (value >> 24) ;
188  	ptr [offset + 5] = (uint8_t) (value >> 16) ;
189  	ptr [offset + 6] = (uint8_t) (value >> 8) ;
190  	ptr [offset + 7] = (uint8_t) value ;
191  } /* psf_put_be64 */
192  
193  static inline void
psf_put_be32(uint8_t * ptr,int offset,int32_t value)194  psf_put_be32 (uint8_t *ptr, int offset, int32_t value)
195  {
196  	ptr [offset] = (uint8_t) (value >> 24) ;
197  	ptr [offset + 1] = (uint8_t) (value >> 16) ;
198  	ptr [offset + 2] = (uint8_t) (value >> 8) ;
199  	ptr [offset + 3] = (uint8_t) value ;
200  } /* psf_put_be32 */
201  
202  static inline void
psf_put_be16(uint8_t * ptr,int offset,int16_t value)203  psf_put_be16 (uint8_t *ptr, int offset, int16_t value)
204  {
205  	ptr [offset] = (uint8_t) (value >> 8) ;
206  	ptr [offset + 1] = (uint8_t) value ;
207  } /* psf_put_be16 */
208  
209  static inline int64_t
psf_get_be64(const uint8_t * ptr,int offset)210  psf_get_be64 (const uint8_t *ptr, int offset)
211  {	int64_t value ;
212  
213  	value = ((uint32_t) ptr [offset]) << 24 ;
214  	value += ptr [offset + 1] << 16 ;
215  	value += ptr [offset + 2] << 8 ;
216  	value += ptr [offset + 3] ;
217  
218  	value = (int64_t) (((uint64_t) value) << 32) ;
219  
220  	value += ((uint32_t) ptr [offset + 4]) << 24 ;
221  	value += ptr [offset + 5] << 16 ;
222  	value += ptr [offset + 6] << 8 ;
223  	value += ptr [offset + 7] ;
224  	return value ;
225  } /* psf_get_be64 */
226  
227  static inline int64_t
psf_get_le64(const uint8_t * ptr,int offset)228  psf_get_le64 (const uint8_t *ptr, int offset)
229  {	int64_t value ;
230  
231  	value = ((uint32_t) ptr [offset + 7]) << 24 ;
232  	value += ptr [offset + 6] << 16 ;
233  	value += ptr [offset + 5] << 8 ;
234  	value += ptr [offset + 4] ;
235  
236  	value = (int64_t) (((uint64_t) value) << 32) ;
237  
238  	value += ((uint32_t) ptr [offset + 3]) << 24 ;
239  	value += ptr [offset + 2] << 16 ;
240  	value += ptr [offset + 1] << 8 ;
241  	value += ptr [offset] ;
242  	return value ;
243  } /* psf_get_le64 */
244  
245  static inline int32_t
psf_get_be32(const uint8_t * ptr,int offset)246  psf_get_be32 (const uint8_t *ptr, int offset)
247  {	int32_t value ;
248  
249  	value = ((uint32_t) ptr [offset]) << 24 ;
250  	value += ptr [offset + 1] << 16 ;
251  	value += ptr [offset + 2] << 8 ;
252  	value += ptr [offset + 3] ;
253  	return value ;
254  } /* psf_get_be32 */
255  
256  static inline int32_t
psf_get_le32(const uint8_t * ptr,int offset)257  psf_get_le32 (const uint8_t *ptr, int offset)
258  {	int32_t value ;
259  
260  	value = ((uint32_t) ptr [offset + 3]) << 24 ;
261  	value += ptr [offset + 2] << 16 ;
262  	value += ptr [offset + 1] << 8 ;
263  	value += ptr [offset] ;
264  	return value ;
265  } /* psf_get_le32 */
266  
267  static inline int32_t
psf_get_be24(const uint8_t * ptr,int offset)268  psf_get_be24 (const uint8_t *ptr, int offset)
269  {	int32_t value ;
270  
271  	value = ((uint32_t) ptr [offset]) << 24 ;
272  	value += ptr [offset + 1] << 16 ;
273  	value += ptr [offset + 2] << 8 ;
274  	return value ;
275  } /* psf_get_be24 */
276  
277  static inline int32_t
psf_get_le24(const uint8_t * ptr,int offset)278  psf_get_le24 (const uint8_t *ptr, int offset)
279  {	int32_t value ;
280  
281  	value = ((uint32_t) ptr [offset + 2]) << 24 ;
282  	value += ptr [offset + 1] << 16 ;
283  	value += ptr [offset] << 8 ;
284  	return value ;
285  } /* psf_get_le24 */
286  
287  static inline int16_t
psf_get_be16(const uint8_t * ptr,int offset)288  psf_get_be16 (const uint8_t *ptr, int offset)
289  {	return (int16_t) (ptr [offset] << 8) + ptr [offset + 1] ;
290  } /* psf_get_be16 */
291  
292  /*-----------------------------------------------------------------------------------------------
293  ** Generic functions for performing endian swapping on integer arrays.
294  */
295  
296  static inline void
endswap_short_array(short * ptr,int len)297  endswap_short_array (short *ptr, int len)
298  {	short	temp ;
299  
300  	while (--len >= 0)
301  	{	temp = ptr [len] ;
302  		ptr [len] = ENDSWAP_16 (temp) ;
303  		} ;
304  } /* endswap_short_array */
305  
306  static inline void
endswap_short_copy(short * dest,const short * src,int len)307  endswap_short_copy (short *dest, const short *src, int len)
308  {
309  	while (--len >= 0)
310  	{	dest [len] = ENDSWAP_16 (src [len]) ;
311  		} ;
312  } /* endswap_short_copy */
313  
314  static inline void
endswap_int_array(int * ptr,int len)315  endswap_int_array (int *ptr, int len)
316  {	int temp ;
317  
318  	while (--len >= 0)
319  	{	temp = ptr [len] ;
320  		ptr [len] = ENDSWAP_32 (temp) ;
321  		} ;
322  } /* endswap_int_array */
323  
324  static inline void
endswap_int_copy(int * dest,const int * src,int len)325  endswap_int_copy (int *dest, const int *src, int len)
326  {
327  	while (--len >= 0)
328  	{	dest [len] = ENDSWAP_32 (src [len]) ;
329  		} ;
330  } /* endswap_int_copy */
331  
332  /*========================================================================================
333  */
334  
335  static inline void
endswap_int64_t_array(int64_t * ptr,int len)336  endswap_int64_t_array (int64_t *ptr, int len)
337  {	int64_t value ;
338  
339  	while (--len >= 0)
340  	{	value = ptr [len] ;
341  		ptr [len] = ENDSWAP_64 (value) ;
342  		} ;
343  } /* endswap_int64_t_array */
344  
345  static inline void
endswap_int64_t_copy(int64_t * dest,const int64_t * src,int len)346  endswap_int64_t_copy (int64_t *dest, const int64_t *src, int len)
347  {	int64_t value ;
348  
349  	while (--len >= 0)
350  	{	value = src [len] ;
351  		dest [len] = ENDSWAP_64 (value) ;
352  		} ;
353  } /* endswap_int64_t_copy */
354  
355  /* A couple of wrapper functions. */
356  
357  static inline void
endswap_float_array(float * ptr,int len)358  endswap_float_array (float *ptr, int len)
359  {	endswap_int_array ((int *) ptr, len) ;
360  } /* endswap_float_array */
361  
362  static inline void
endswap_double_array(double * ptr,int len)363  endswap_double_array (double *ptr, int len)
364  {	endswap_int64_t_array ((int64_t *) ptr, len) ;
365  } /* endswap_double_array */
366  
367  static inline void
endswap_float_copy(float * dest,const float * src,int len)368  endswap_float_copy (float *dest, const float *src, int len)
369  {	endswap_int_copy ((int *) dest, (const int *) src, len) ;
370  } /* endswap_float_copy */
371  
372  static inline void
endswap_double_copy(double * dest,const double * src,int len)373  endswap_double_copy (double *dest, const double *src, int len)
374  {	endswap_int64_t_copy ((int64_t *) dest, (const int64_t *) src, len) ;
375  } /* endswap_double_copy */
376  
377  #endif /* SFENDIAN_INCLUDED */
378  
379