📄 common.c
字号:
/*** Copyright (C) 1999-2001 Erik de Castro Lopo <erikd@zip.com.au>** ** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU Lesser General Public License as published by** the Free Software Foundation; either version 2.1 of the License, or** (at your option) any later version.** ** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU Lesser General Public License for more details.** ** You should have received a copy of the GNU Lesser General Public License** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/#include <stdarg.h>#include <string.h>#include <math.h>#include "sndfile.h"#include "sfendian.h"#include "common.h"/*-----------------------------------------------------------------------------------------------** Generic functions for performing endian swapping on short and int arrays.*/voidendswap_short_array (short *ptr, int len){ int k ; for (k = 0 ; k < len ; k++) ptr[k] = ((((ptr[k])>>8)&0xFF)|(((ptr[k])&0xFF)<<8)) ;} /* endswap_short_array */voidendswap_int_array (int *ptr, int len){ int k ; for (k = 0 ; k < len ; k++) ptr[k] = ((((ptr[k])>>24)&0xFF)|(((ptr[k])>>8)&0xFF00)| (((ptr[k])&0xFF00)<<8)|(((ptr[k])&0xFF)<<24)) ; } /* endswap_int_array *//*-----------------------------------------------------------------------------------------------** psf_log_printf allows libsndfile internal functions to print to an internal logbuffer which** can later be displayed. ** The format specifiers are as for printf but without the field width and other modifiers.** Printing is performed to the logbuffer char array of the SF_PRIVATE struct. ** Printing is done in such a way as to guarantee that the log never overflows the end of the** logbuffer array. */#define psf_putchar(a,b) \ if ((a)->logindex < SF_BUFFER_LEN - 1) \ { (a)->logbuffer [(a)->logindex++] = (b) ; \ (a)->logbuffer [(a)->logindex] = 0 ; \ } ;voidpsf_log_printf (SF_PRIVATE *psf, char *format, ...){ va_list ap ; int d, tens, shift ; char c, *strptr, istr [5] ; va_start(ap, format); /* printf ("psf_log_printf : %s\n", format) ; */ while ((c = *format++)) { if (c != '%') { psf_putchar (psf, c) ; continue ; } ; switch((c = *format++)) { case 's': /* string */ strptr = va_arg (ap, char *) ; while (*strptr) psf_putchar (psf, *strptr++) ; break; case 'd': /* int */ d = va_arg (ap, int) ; if (d == 0) { psf_putchar (psf, '0') ; break ; } if (d < 0) { psf_putchar (psf, '-') ; d = -d ; } ; tens = 1 ; while (d / tens >= 10) tens *= 10 ; while (tens > 0) { psf_putchar (psf, '0' + d / tens) ; d %= tens ; tens /= 10 ; } ; break; case 'X': /* hex */ d = va_arg (ap, int) ; if (d == 0) { psf_putchar (psf, '0') ; break ; } ; shift = 28 ; while (! ((0xF << shift) & d)) shift -= 4 ; while (shift >= 0) { c = (d >> shift) & 0xF ; psf_putchar (psf, (c > 9) ? c + 'A' - 10 : c + '0') ; shift -= 4 ; } ; break; case 'c': /* char */ c = va_arg (ap, int) & 0xFF ; psf_putchar (psf, c); break; case 'D': /* int2str */ d = va_arg (ap, int); if (CPU_IS_LITTLE_ENDIAN) { istr [0] = d & 0xFF ; istr [1] = (d >> 8) & 0xFF ; istr [2] = (d >> 16) & 0xFF ; istr [3] = (d >> 24) & 0xFF ; } else { istr [3] = d & 0xFF ; istr [2] = (d >> 8) & 0xFF ; istr [1] = (d >> 16) & 0xFF ; istr [0] = (d >> 24) & 0xFF ; } ; istr [4] = 0 ; strptr = istr ; while (*strptr) { c = *strptr++ ; psf_putchar (psf, c) ; } ; break; default : psf_putchar (psf, '*') ; psf_putchar (psf, c) ; psf_putchar (psf, '*') ; break ; } /* switch */ } /* while */ va_end(ap); return ;} /* psf_log_printf *//*-----------------------------------------------------------------------------------------------** ASCII header printf functions.** Some formats (ie NIST) use ascii text in their headers.** Format specifiers are the same as the standard printf specifiers (uses vsnprintf).** If this generates a compile error on any system, the author should be notified** so an alternative vsnprintf can be provided.*/voidpsf_asciiheader_printf (SF_PRIVATE *psf, char *format, ...){ va_list argptr ; int maxlen ; char *start ; start = (char*) psf->header + strlen ((char*) psf->header) ; maxlen = sizeof (psf->header) - strlen ((char*) psf->header) ; va_start (argptr, format) ; vsnprintf (start, maxlen, format, argptr) ; va_end (argptr) ; /* Make sure the string is properly terminated. */ start [maxlen - 1] = 0 ; return ;} /* psf_asciiheader_printf *//*-----------------------------------------------------------------------------------------------** Binary header writing functions. Returns number of bytes written.**** Format specifiers for psf_binheader_writef are as follows** m - marker - four bytes - no endian manipulation**** b - byte**** w - two byte value - little endian** W - two byte value - big endian** l - four byte value - little endian** L - four byte value - big endian**** s - string preceded by a little endian four byte length** S - string preceded by a big endian four byte length**** f - little endian 32 bit float** F - big endian 32 bit float**** B - binary data (see below)** z - zero bytes (se below)**** To write a word followed by a long (both little endian) use:** psf_binheader_writef ("wl", wordval, longval) ;**** To write binary data use:** psf_binheader_writef ("B", &bindata, sizeof (bindata)) ;**** To write N zero bytes use:** psf_binheader_writef ("z", N) ;*//* These macros may seem a bit messy but do prevent problems with processors which ** seg. fault when asked to write an int or short to a non-int/short aligned address.*/#if (CPU_IS_BIG_ENDIAN == 1)#define PUT_INT(psf,x) if ((psf)->headindex < sizeof ((psf)->header) - 4) \ { (psf)->header [(psf)->headindex++] = ((x) >> 24) & 0xFF ; \ (psf)->header [(psf)->headindex++] = ((x) >> 16) & 0xFF ; \ (psf)->header [(psf)->headindex++] = ((x) >> 8) & 0xFF ; \ (psf)->header [(psf)->headindex++] = (x) & 0xFF ; } #define PUT_SHORT(psf,x) if ((psf)->headindex < sizeof ((psf)->header) - 2) \ { (psf)->header [(psf)->headindex++] = ((x) >> 8) & 0xFF ; \ (psf)->header [(psf)->headindex++] = (x) & 0xFF ; }#elif (CPU_IS_LITTLE_ENDIAN == 1)#define PUT_INT(psf,x) if ((psf)->headindex < sizeof ((psf)->header) - 4) \ { (psf)->header [(psf)->headindex++] = (x) & 0xFF ; \ (psf)->header [(psf)->headindex++] = ((x) >> 8) & 0xFF ; \ (psf)->header [(psf)->headindex++] = ((x) >> 16) & 0xFF ; \ (psf)->header [(psf)->headindex++] = ((x) >> 24) & 0xFF ; } #define PUT_SHORT(psf,x) if ((psf)->headindex < sizeof ((psf)->header) - 2) \ { (psf)->header [(psf)->headindex++] = (x) & 0xFF ; \ (psf)->header [(psf)->headindex++] = ((x) >> 8) & 0xFF ; }#else# error "Cannot determine endian-ness of processor."#endif#define PUT_BYTE(psf,x) if ((psf)->headindex < sizeof ((psf)->header) - 1) \ { (psf)->header [(psf)->headindex++] = (x) & 0xFF ; }intpsf_binheader_writef (SF_PRIVATE *psf, char *format, ...){ va_list argptr ; unsigned int data ; float floatdata ; void *bindata ; size_t size ; char c, *strptr ; int count = 0 ; va_start(argptr, format); while ((c = *format++)) { switch (c) { case 'm' : data = va_arg (argptr, unsigned int) ; PUT_INT (psf, data) ; count += 4 ; break ; case 'b' : data = va_arg (argptr, unsigned int) ; PUT_BYTE (psf, data) ; count += 1 ; break ; case 'w' : data = va_arg (argptr, unsigned int) ; data = H2LE_SHORT (data) ; PUT_SHORT (psf, data) ; count += 2 ; break ; case 'W' : data = va_arg (argptr, unsigned int) ; data = H2BE_SHORT (data) ; PUT_SHORT (psf, data) ; count += 2 ; break ; case 'l' : data = va_arg (argptr, unsigned int) ; data = H2LE_INT (data) ; PUT_INT (psf, data) ; count += 4 ; break ; case 'L' : data = va_arg (argptr, unsigned int) ; data = H2BE_INT (data) ; PUT_INT (psf, data) ; count += 4 ; break ; case 'f' : floatdata = (float) va_arg (argptr, double) ; float32_write (floatdata, (unsigned char *) &data) ; data = H2LE_INT (data) ; PUT_INT (psf, data) ; count += 4 ; break ; case 'F' : floatdata = (float) va_arg (argptr, double) ; float32_write (floatdata, (unsigned char *) &data) ; data = H2BE_INT (data) ; PUT_INT (psf, data) ; count += 4 ; break ; case 's' : strptr = va_arg (argptr, char *) ; size = strlen (strptr) + 1 ; size += (size & 1) ; data = H2LE_INT (size) ; PUT_INT (psf, data) ; memcpy (&(psf->header [psf->headindex]), strptr, size) ; psf->headindex += size ; count += 4 + size ; break ; case 'S' : strptr = va_arg (argptr, char *) ; size = strlen (strptr) + 1 ; size += (size & 1) ; data = H2BE_INT (size) ; PUT_INT (psf, data) ; memcpy (&(psf->header [psf->headindex]), strptr, size) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -