common.c
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:10k
- /*
- ** Copyright (C) 1999-2000 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 "sndfile.h"
- #include "sfendian.h"
- #include "common.h"
- /*-----------------------------------------------------------------------------------------------
- */
- void endswap_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 */
- void endswap_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 */
- /*-----------------------------------------------------------------------------------------------
- */
- #define psf_putchar(a,b)
- if ((a)->strindex < SF_BUFFER_LEN - 1)
- { (a)->strbuffer [(a)->strindex++] = (b) ;
- (a)->strbuffer [(a)->strindex] = 0 ;
- } ;
- void psf_sprintf (SF_PRIVATE *psf, char *format, ...)
- { va_list ap ;
- int d, tens, shift ;
- char c, *strptr, istr [5] ;
- va_start(ap, format);
-
- /* printf ("psf_sprintf : %sn", 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_sprintf */
- /*------------------------------------------------------------------------------
- ** Format specifiers for psf_hprintf are as follows
- ** m - marker - four bytes - no endian problems
- ** 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
- ** b - binary data (see below)
- **
- ** To write a word followed by a long (both little endian) use:
- ** psf_hprintf ("wl", wordval, longval) ;
- **
- ** To write binary data use:
- ** psf_hprintf ("b", &bindata, sizeof (bindata)) ;
- */
- /* 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) { (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) { (psf)->header [(psf)->headindex++] = ((x) >> 8) & 0xFF ;
- (psf)->header [(psf)->headindex++] = (x) & 0xFF ; }
- #elif (CPU_IS_LITTLE_ENDIAN == 1)
- #define put_int(psf,x) { (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) { (psf)->header [(psf)->headindex++] = (x) & 0xFF ;
- (psf)->header [(psf)->headindex++] = ((x) >> 8) & 0xFF ; }
- #else
- # error "Cannot determine endian-ness of processor."
- #endif
- void psf_hprintf (SF_PRIVATE *psf, char *format, ...)
- { va_list argptr ;
- unsigned int longdata ;
- unsigned short worddata ;
- void *bindata ;
- size_t size ;
- char c, *strptr ;
-
- va_start(argptr, format);
-
- while ((c = *format++))
- { switch (c)
- { case 'm' :
- longdata = va_arg (argptr, unsigned int) ;
- put_int (psf, longdata) ;
- break ;
-
- case 'l' :
- longdata = va_arg (argptr, unsigned int) ;
- longdata = H2LE_INT (longdata) ;
- put_int (psf, longdata) ;
- break ;
- case 'L' :
- longdata = va_arg (argptr, unsigned int) ;
- longdata = H2BE_INT (longdata) ;
- put_int (psf, longdata) ;
- break ;
-
- case 'w' :
- worddata = va_arg (argptr, int) & 0xFFFF ;
- worddata = H2LE_SHORT (worddata) ;
- put_short (psf, worddata) ;
- break ;
- case 'W' :
- worddata = va_arg (argptr, int) & 0xFFFF ;
- worddata = H2BE_SHORT (worddata) ;
- put_short (psf, worddata) ;
- break ;
-
- case 'b' :
- bindata = va_arg (argptr, void *) ;
- size = va_arg (argptr, size_t) ;
- memcpy (&(psf->header [psf->headindex]), bindata, size) ;
- psf->headindex += size ;
- break ;
-
- case 's' :
- strptr = va_arg (argptr, char *) ;
- size = strlen (strptr) + 1 ;
- size += (size & 1) ;
- longdata = H2LE_INT (size) ;
- put_int (psf, longdata) ;
- memcpy (&(psf->header [psf->headindex]), strptr, size) ;
- psf->headindex += size ;
- break ;
-
- case 'S' :
- strptr = va_arg (argptr, char *) ;
- size = strlen (strptr) + 1 ;
- size += (size & 1) ;
- longdata = H2BE_INT (size) ;
- put_int (psf, longdata) ;
- memcpy (&(psf->header [psf->headindex]), strptr, size) ;
- psf->headindex += size ;
- break ;
-
- default : break ;
- } ;
- } ;
-
- va_end(argptr);
- return ;
- } /* psf_hprintf */
- /*-----------------------------------------------------------------------------------------------
- */
- void psf_hsetf (SF_PRIVATE *psf, unsigned int marker, char *format, ...)
- { va_list argptr ;
- unsigned int longdata, oldheadindex ;
- unsigned short worddata ;
- void *bindata ;
- size_t size ;
- char c, *strptr ;
-
- /* Save old head index. */
- oldheadindex = psf->headindex ;
- psf->headindex = 0 ;
-
- /* Find the marker. */
- while (psf->headindex < oldheadindex)
- { if (*((unsigned int*) &(psf->header[psf->headindex])) == marker)
- break ;
- psf->headindex += 4 ;
- } ;
-
- /* If not found return. */
- if (psf->headindex >= oldheadindex)
- return ;
- /* Move past marker. */
- psf->headindex += 4 ;
- va_start(argptr, format);
-
- while ((c = *format++))
- { switch (c)
- { case 'm' :
- longdata = va_arg (argptr, unsigned int) ;
- put_int (psf, longdata) ;
- break ;
-
- case 'l' :
- longdata = va_arg (argptr, unsigned int) ;
- longdata = H2LE_INT (longdata) ;
- put_int (psf, longdata) ;
- break ;
- case 'L' :
- longdata = va_arg (argptr, unsigned int) ;
- longdata = H2BE_INT (longdata) ;
- put_int (psf, longdata) ;
- break ;
-
- case 'w' :
- worddata = va_arg (argptr, int) & 0xFFFF ;
- worddata = H2LE_SHORT (worddata) ;
- put_short (psf, worddata) ;
- break ;
- case 'W' :
- worddata = va_arg (argptr, int) & 0xFFFF ;
- worddata = H2BE_SHORT (worddata) ;
- put_short (psf, worddata) ;
- break ;
-
- case 'b' :
- bindata = va_arg (argptr, void *) ;
- size = va_arg (argptr, size_t) ;
- memcpy (&(psf->header [psf->headindex]), bindata, size) ;
- psf->headindex += size ;
- break ;
-
- case 's' :
- strptr = va_arg (argptr, char *) ;
- size = strlen (strptr) + 1 ;
- size += (size & 1) ;
- longdata = H2LE_INT (size) ;
- put_int (psf, longdata) ;
- memcpy (&(psf->header [psf->headindex]), strptr, size) ;
- psf->headindex += size ;
- break ;
-
- case 'S' :
- strptr = va_arg (argptr, char *) ;
- size = strlen (strptr) + 1 ;
- size += (size & 1) ;
- longdata = H2BE_INT (size) ;
- put_int (psf, longdata) ;
- memcpy (&(psf->header [psf->headindex]), strptr, size) ;
- psf->headindex += size ;
- break ;
-
- default : break ;
- } ;
- } ;
-
- va_end(argptr);
-
- psf->headindex = oldheadindex ;
- return ;
- } /* psf_hsetf */