📄 common.c
字号:
/*** Copyright (C) 1999-2004 Erik de Castro Lopo <erikd@mega-nerd.com>**** 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 <ctype.h>#include <math.h>#include <time.h>#include "sndfile.h"#include "sfendian.h"#include "common.h"/*-----------------------------------------------------------------------------------------------** 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 LOG_PUTCHAR(a,b) \ { if ((a)->logindex < SIGNED_SIZEOF ((a)->logbuffer) - 1) \ { (a)->logbuffer [(a)->logindex++] = (b) ; \ (a)->logbuffer [(a)->logindex] = 0 ; \ } \ }voidpsf_log_printf (SF_PRIVATE *psf, const char *format, ...){ va_list ap ; unsigned int u ; int d, tens, shift, width, width_specifier, left_align ; char c, *strptr, istr [5], lead_char, sign_char ; va_start (ap, format) ; while ((c = *format++)) { if (c != '%') { LOG_PUTCHAR (psf, c) ; continue ; } ; if (format [0] == '%') /* Handle %% */ { LOG_PUTCHAR (psf, '%') ; format ++ ; continue ; } ; sign_char = 0 ; left_align = SF_FALSE ; while (1) { switch (format [0]) { case ' ' : case '+' : sign_char = format [0] ; format ++ ; continue ; case '-' : left_align = SF_TRUE ; format ++ ; continue ; default : break ; } ; break ; } ; if (format [0] == 0) break ; lead_char = ' ' ; if (format [0] == '0') lead_char = '0' ; width_specifier = 0 ; while ((c = *format++) && isdigit (c)) width_specifier = width_specifier * 10 + (c - '0') ; switch (c) { case 0 : /* NULL character. */ va_end (ap) ; return ; case 's': /* string */ strptr = va_arg (ap, char *) ; if (strptr == NULL) break ; width_specifier -= strlen (strptr) ; if (left_align == SF_FALSE) while (width_specifier -- > 0) LOG_PUTCHAR (psf, ' ') ; while (*strptr) LOG_PUTCHAR (psf, *strptr++) ; while (width_specifier -- > 0) LOG_PUTCHAR (psf, ' ') ; break ; case 'd': /* int */ d = va_arg (ap, int) ; if (d < 0) { d = -d ; sign_char = '-' ; if (lead_char != '0' && left_align == SF_FALSE) width_specifier -- ; } ; tens = 1 ; width = 1 ; while (d / tens >= 10) { tens *= 10 ; width ++ ; } ; width_specifier -= width ; if (sign_char == ' ') { LOG_PUTCHAR (psf, ' ') ; width_specifier -- ; } ; if (left_align == SF_FALSE && lead_char != '0') { if (sign_char == '+') width_specifier -- ; while (width_specifier -- > 0) LOG_PUTCHAR (psf, lead_char) ; } ; if (sign_char == '+' || sign_char == '-') { LOG_PUTCHAR (psf, sign_char) ; width_specifier -- ; } ; if (left_align == SF_FALSE) while (width_specifier -- > 0) LOG_PUTCHAR (psf, lead_char) ; while (tens > 0) { LOG_PUTCHAR (psf, '0' + d / tens) ; d %= tens ; tens /= 10 ; } ; while (width_specifier -- > 0) LOG_PUTCHAR (psf, lead_char) ; break ; case 'D': /* sf_count_t */ { sf_count_t D, Tens ; D = va_arg (ap, sf_count_t) ; if (D == 0) { while (-- width_specifier > 0) LOG_PUTCHAR (psf, lead_char) ; LOG_PUTCHAR (psf, '0') ; break ; } if (D < 0) { LOG_PUTCHAR (psf, '-') ; D = -D ; } ; Tens = 1 ; width = 1 ; while (D / Tens >= 10) { Tens *= 10 ; width ++ ; } ; while (width_specifier > width) { LOG_PUTCHAR (psf, lead_char) ; width_specifier-- ; } ; while (Tens > 0) { LOG_PUTCHAR (psf, '0' + D / Tens) ; D %= Tens ; Tens /= 10 ; } ; } ; break ; case 'u': /* unsigned int */ u = va_arg (ap, unsigned int) ; tens = 1 ; width = 1 ; while (u / tens >= 10) { tens *= 10 ; width ++ ; } ; width_specifier -= width ; if (sign_char == ' ') { LOG_PUTCHAR (psf, ' ') ; width_specifier -- ; } ; if (left_align == SF_FALSE && lead_char != '0') { if (sign_char == '+') width_specifier -- ; while (width_specifier -- > 0) LOG_PUTCHAR (psf, lead_char) ; } ; if (sign_char == '+' || sign_char == '-') { LOG_PUTCHAR (psf, sign_char) ; width_specifier -- ; } ; if (left_align == SF_FALSE) while (width_specifier -- > 0) LOG_PUTCHAR (psf, lead_char) ; while (tens > 0) { LOG_PUTCHAR (psf, '0' + u / tens) ; u %= tens ; tens /= 10 ; } ; while (width_specifier -- > 0) LOG_PUTCHAR (psf, lead_char) ; break ; case 'c': /* char */ c = va_arg (ap, int) & 0xFF ; LOG_PUTCHAR (psf, c) ; break ; case 'x': /* hex */ case 'X': /* hex */ d = va_arg (ap, int) ; if (d == 0) { while (--width_specifier > 0) LOG_PUTCHAR (psf, lead_char) ; LOG_PUTCHAR (psf, '0') ; break ; } ; shift = 28 ; width = (width_specifier < 8) ? 8 : width_specifier ; while (! ((0xF << shift) & d)) { shift -= 4 ; width -- ; } ; while (width > 0 && width_specifier > width) { LOG_PUTCHAR (psf, lead_char) ; width_specifier-- ; } ; while (shift >= 0) { c = (d >> shift) & 0xF ; LOG_PUTCHAR (psf, (c > 9) ? c + 'A' - 10 : c + '0') ; shift -= 4 ; } ; break ; case 'M': /* 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++ ; LOG_PUTCHAR (psf, c) ; } ; break ; default : LOG_PUTCHAR (psf, '*') ; LOG_PUTCHAR (psf, c) ; LOG_PUTCHAR (psf, '*') ; break ; } /* switch */ } /* while */ va_end (ap) ; return ;} /* psf_log_printf */#ifndef PSF_LOG_PRINTF_ONLY/*-----------------------------------------------------------------------------------------------** 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, const char *format, ...){ va_list argptr ; int maxlen ; char *start ; maxlen = strlen ((char*) psf->header) ; start = ((char*) psf->header) + maxlen ; maxlen = sizeof (psf->header) - maxlen ; va_start (argptr, format) ; LSF_VSNPRINTF (start, maxlen, format, argptr) ; va_end (argptr) ; /* Make sure the string is properly terminated. */ start [maxlen - 1] = 0 ; psf->headindex = strlen ((char*) psf->header) ; 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**** e - all following numerical values will be little endian** E - all following numerical values will be big endian**** t - all following O types will be truncated to 4 bytes** T - switch off truncation of all following O types**** 1 - single byte value** 2 - two byte value** 3 - three byte value** 4 - four byte value** 8 - eight byte value (sometimes written as 4 bytes)**** s - string preceded by a four byte length** S - string including null terminator** f - floating point data** d - double precision floating point data** h - 16 binary bytes value**** b - binary data (see below)** z - zero bytes (ses below)** j - jump forwards or backwards**** To write a word followed by an int (both little endian) use:** psf_binheader_writef ("e24", wordval, longval) ;**** To write binary data use:** psf_binheader_writef ("b", &bindata, sizeof (bindata)) ;**** To write N zero bytes use:** NOTE: due to platform issues (ie x86-64) you should cast the** argument to size_t or ensure the variable type is size_t.** 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.*/#define PUT_BYTE(psf,x) if ((psf)->headindex < SIGNED_SIZEOF ((psf)->header) - 1) \ { (psf)->header [(psf)->headindex++] = (x) ; }#if (CPU_IS_BIG_ENDIAN == 1)#define PUT_MARKER(psf,x) if ((psf)->headindex < SIGNED_SIZEOF ((psf)->header) - 4) \ { (psf)->header [(psf)->headindex++] = ((x) >> 24) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 16) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 8) ; \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -