1b815c7f3Sopenharmony_ci/*
2b815c7f3Sopenharmony_ci** Copyright (C) 1999-2019 Erik de Castro Lopo <erikd@mega-nerd.com>
3b815c7f3Sopenharmony_ci**
4b815c7f3Sopenharmony_ci** This program is free software; you can redistribute it and/or modify
5b815c7f3Sopenharmony_ci** it under the terms of the GNU Lesser General Public License as published by
6b815c7f3Sopenharmony_ci** the Free Software Foundation; either version 2.1 of the License, or
7b815c7f3Sopenharmony_ci** (at your option) any later version.
8b815c7f3Sopenharmony_ci**
9b815c7f3Sopenharmony_ci** This program is distributed in the hope that it will be useful,
10b815c7f3Sopenharmony_ci** but WITHOUT ANY WARRANTY; without even the implied warranty of
11b815c7f3Sopenharmony_ci** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12b815c7f3Sopenharmony_ci** GNU Lesser General Public License for more details.
13b815c7f3Sopenharmony_ci**
14b815c7f3Sopenharmony_ci** You should have received a copy of the GNU Lesser General Public License
15b815c7f3Sopenharmony_ci** along with this program; if not, write to the Free Software
16b815c7f3Sopenharmony_ci** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17b815c7f3Sopenharmony_ci*/
18b815c7f3Sopenharmony_ci
19b815c7f3Sopenharmony_ci#include <config.h>
20b815c7f3Sopenharmony_ci
21b815c7f3Sopenharmony_ci#include <stdarg.h>
22b815c7f3Sopenharmony_ci#include <string.h>
23b815c7f3Sopenharmony_ci#if HAVE_UNISTD_H
24b815c7f3Sopenharmony_ci#include <unistd.h>
25b815c7f3Sopenharmony_ci#else
26b815c7f3Sopenharmony_ci#include "sf_unistd.h"
27b815c7f3Sopenharmony_ci#endif
28b815c7f3Sopenharmony_ci#include <ctype.h>
29b815c7f3Sopenharmony_ci#include <math.h>
30b815c7f3Sopenharmony_ci#include <time.h>
31b815c7f3Sopenharmony_ci#if HAVE_SYS_TIME_H
32b815c7f3Sopenharmony_ci#include <sys/time.h>
33b815c7f3Sopenharmony_ci#endif
34b815c7f3Sopenharmony_ci#include "sndfile.h"
35b815c7f3Sopenharmony_ci#include "sfendian.h"
36b815c7f3Sopenharmony_ci#include "common.h"
37b815c7f3Sopenharmony_ci
38b815c7f3Sopenharmony_ci#define	INITIAL_HEADER_SIZE	256
39b815c7f3Sopenharmony_ci
40b815c7f3Sopenharmony_ci/* Allocate and initialize the SF_PRIVATE struct. */
41b815c7f3Sopenharmony_ciSF_PRIVATE *
42b815c7f3Sopenharmony_cipsf_allocate (void)
43b815c7f3Sopenharmony_ci{	SF_PRIVATE * psf ;
44b815c7f3Sopenharmony_ci
45b815c7f3Sopenharmony_ci	if ((psf = calloc (1, sizeof (SF_PRIVATE))) == NULL)
46b815c7f3Sopenharmony_ci		return	NULL ;
47b815c7f3Sopenharmony_ci
48b815c7f3Sopenharmony_ci	if ((psf->header.ptr = calloc (1, INITIAL_HEADER_SIZE)) == NULL)
49b815c7f3Sopenharmony_ci	{	free (psf) ;
50b815c7f3Sopenharmony_ci		return	NULL ;
51b815c7f3Sopenharmony_ci		} ;
52b815c7f3Sopenharmony_ci	psf->header.len = INITIAL_HEADER_SIZE ;
53b815c7f3Sopenharmony_ci
54b815c7f3Sopenharmony_ci	return psf ;
55b815c7f3Sopenharmony_ci} /* psf_allocate */
56b815c7f3Sopenharmony_ci
57b815c7f3Sopenharmony_cistatic int
58b815c7f3Sopenharmony_cipsf_bump_header_allocation (SF_PRIVATE * psf, sf_count_t needed)
59b815c7f3Sopenharmony_ci{
60b815c7f3Sopenharmony_ci	sf_count_t newlen, smallest = INITIAL_HEADER_SIZE ;
61b815c7f3Sopenharmony_ci	void * ptr ;
62b815c7f3Sopenharmony_ci
63b815c7f3Sopenharmony_ci	newlen = (needed > psf->header.len) ? 2 * SF_MAX (needed, smallest) : 2 * psf->header.len ;
64b815c7f3Sopenharmony_ci
65b815c7f3Sopenharmony_ci	if (newlen > 100 * 1024)
66b815c7f3Sopenharmony_ci	{	psf_log_printf (psf, "Request for header allocation of %D denied.\n", newlen) ;
67b815c7f3Sopenharmony_ci		return 1 ;
68b815c7f3Sopenharmony_ci		}
69b815c7f3Sopenharmony_ci
70b815c7f3Sopenharmony_ci	if ((ptr = realloc (psf->header.ptr, newlen)) == NULL)
71b815c7f3Sopenharmony_ci	{	psf_log_printf (psf, "realloc (%p, %D) failed\n", psf->header.ptr, newlen) ;
72b815c7f3Sopenharmony_ci		psf->error = SFE_MALLOC_FAILED ;
73b815c7f3Sopenharmony_ci		return 1 ;
74b815c7f3Sopenharmony_ci		} ;
75b815c7f3Sopenharmony_ci
76b815c7f3Sopenharmony_ci	/* Always zero-out new header memory to avoid un-initializer memory accesses. */
77b815c7f3Sopenharmony_ci	if (newlen > psf->header.len)
78b815c7f3Sopenharmony_ci		memset ((char *) ptr + psf->header.len, 0, newlen - psf->header.len) ;
79b815c7f3Sopenharmony_ci
80b815c7f3Sopenharmony_ci	psf->header.ptr = ptr ;
81b815c7f3Sopenharmony_ci	psf->header.len = newlen ;
82b815c7f3Sopenharmony_ci	return 0 ;
83b815c7f3Sopenharmony_ci} /* psf_bump_header_allocation */
84b815c7f3Sopenharmony_ci
85b815c7f3Sopenharmony_ci/*-----------------------------------------------------------------------------------------------
86b815c7f3Sopenharmony_ci** psf_log_printf allows libsndfile internal functions to print to an internal parselog which
87b815c7f3Sopenharmony_ci** can later be displayed.
88b815c7f3Sopenharmony_ci** The format specifiers are as for printf but without the field width and other modifiers.
89b815c7f3Sopenharmony_ci** Printing is performed to the parselog char array of the SF_PRIVATE struct.
90b815c7f3Sopenharmony_ci** Printing is done in such a way as to guarantee that the log never overflows the end of the
91b815c7f3Sopenharmony_ci** parselog array.
92b815c7f3Sopenharmony_ci*/
93b815c7f3Sopenharmony_ci
94b815c7f3Sopenharmony_cistatic inline void
95b815c7f3Sopenharmony_cilog_putchar (SF_PRIVATE *psf, char ch)
96b815c7f3Sopenharmony_ci{	if (psf->parselog.indx < SIGNED_SIZEOF (psf->parselog.buf) - 1)
97b815c7f3Sopenharmony_ci	{	psf->parselog.buf [psf->parselog.indx++] = ch ;
98b815c7f3Sopenharmony_ci		psf->parselog.buf [psf->parselog.indx] = 0 ;
99b815c7f3Sopenharmony_ci		} ;
100b815c7f3Sopenharmony_ci	return ;
101b815c7f3Sopenharmony_ci} /* log_putchar */
102b815c7f3Sopenharmony_ci
103b815c7f3Sopenharmony_civoid
104b815c7f3Sopenharmony_cipsf_log_printf (SF_PRIVATE *psf, const char *format, ...)
105b815c7f3Sopenharmony_ci{	va_list		ap ;
106b815c7f3Sopenharmony_ci	uint32_t	u, tens ;
107b815c7f3Sopenharmony_ci	int			d, shift, width, width_specifier, left_align, slen, precision ;
108b815c7f3Sopenharmony_ci	char		c, *strptr, istr [5], lead_char, sign_char ;
109b815c7f3Sopenharmony_ci
110b815c7f3Sopenharmony_ci	va_start (ap, format) ;
111b815c7f3Sopenharmony_ci
112b815c7f3Sopenharmony_ci	while ((c = *format++))
113b815c7f3Sopenharmony_ci	{	if (c != '%')
114b815c7f3Sopenharmony_ci		{	log_putchar (psf, c) ;
115b815c7f3Sopenharmony_ci			continue ;
116b815c7f3Sopenharmony_ci			} ;
117b815c7f3Sopenharmony_ci
118b815c7f3Sopenharmony_ci		if (format [0] == '%') /* Handle %% */
119b815c7f3Sopenharmony_ci		{ 	log_putchar (psf, '%') ;
120b815c7f3Sopenharmony_ci			format ++ ;
121b815c7f3Sopenharmony_ci			continue ;
122b815c7f3Sopenharmony_ci			} ;
123b815c7f3Sopenharmony_ci
124b815c7f3Sopenharmony_ci		sign_char = 0 ;
125b815c7f3Sopenharmony_ci		left_align = SF_FALSE ;
126b815c7f3Sopenharmony_ci		while (1)
127b815c7f3Sopenharmony_ci		{	switch (format [0])
128b815c7f3Sopenharmony_ci			{	case ' ' :
129b815c7f3Sopenharmony_ci				case '+' :
130b815c7f3Sopenharmony_ci					sign_char = format [0] ;
131b815c7f3Sopenharmony_ci					format ++ ;
132b815c7f3Sopenharmony_ci					continue ;
133b815c7f3Sopenharmony_ci
134b815c7f3Sopenharmony_ci				case '-' :
135b815c7f3Sopenharmony_ci					left_align = SF_TRUE ;
136b815c7f3Sopenharmony_ci					format ++ ;
137b815c7f3Sopenharmony_ci					continue ;
138b815c7f3Sopenharmony_ci
139b815c7f3Sopenharmony_ci				default : break ;
140b815c7f3Sopenharmony_ci				} ;
141b815c7f3Sopenharmony_ci
142b815c7f3Sopenharmony_ci			break ;
143b815c7f3Sopenharmony_ci			} ;
144b815c7f3Sopenharmony_ci
145b815c7f3Sopenharmony_ci		if (format [0] == 0)
146b815c7f3Sopenharmony_ci			break ;
147b815c7f3Sopenharmony_ci
148b815c7f3Sopenharmony_ci		lead_char = ' ' ;
149b815c7f3Sopenharmony_ci		if (format [0] == '0')
150b815c7f3Sopenharmony_ci			lead_char = '0' ;
151b815c7f3Sopenharmony_ci
152b815c7f3Sopenharmony_ci		width_specifier = 0 ;
153b815c7f3Sopenharmony_ci		while ((c = *format++) && isdigit (c))
154b815c7f3Sopenharmony_ci			width_specifier = width_specifier * 10 + (c - '0') ;
155b815c7f3Sopenharmony_ci
156b815c7f3Sopenharmony_ci		precision = 0 ;
157b815c7f3Sopenharmony_ci		if (c == '.')
158b815c7f3Sopenharmony_ci		{	while ((c = *format++) && isdigit (c))
159b815c7f3Sopenharmony_ci				precision = precision * 10 + (c - '0') ;
160b815c7f3Sopenharmony_ci			} ;
161b815c7f3Sopenharmony_ci
162b815c7f3Sopenharmony_ci		switch (c)
163b815c7f3Sopenharmony_ci		{	case 0 : /* NULL character. */
164b815c7f3Sopenharmony_ci					va_end (ap) ;
165b815c7f3Sopenharmony_ci					return ;
166b815c7f3Sopenharmony_ci
167b815c7f3Sopenharmony_ci			case 's': /* string */
168b815c7f3Sopenharmony_ci					strptr = va_arg (ap, char *) ;
169b815c7f3Sopenharmony_ci					if (strptr == NULL)
170b815c7f3Sopenharmony_ci						break ;
171b815c7f3Sopenharmony_ci					if (precision > 0)
172b815c7f3Sopenharmony_ci						slen = strnlen (strptr, precision) ;
173b815c7f3Sopenharmony_ci					else
174b815c7f3Sopenharmony_ci						slen = strlen (strptr) ;
175b815c7f3Sopenharmony_ci					width_specifier = width_specifier >= slen ? width_specifier - slen : 0 ;
176b815c7f3Sopenharmony_ci					if (left_align == SF_FALSE)
177b815c7f3Sopenharmony_ci						while (width_specifier -- > 0)
178b815c7f3Sopenharmony_ci							log_putchar (psf, ' ') ;
179b815c7f3Sopenharmony_ci					while (slen--)
180b815c7f3Sopenharmony_ci						log_putchar (psf, *strptr++) ;
181b815c7f3Sopenharmony_ci					while (width_specifier -- > 0)
182b815c7f3Sopenharmony_ci						log_putchar (psf, ' ') ;
183b815c7f3Sopenharmony_ci					break ;
184b815c7f3Sopenharmony_ci
185b815c7f3Sopenharmony_ci			case 'd': /* int */
186b815c7f3Sopenharmony_ci					d = va_arg (ap, int) ;
187b815c7f3Sopenharmony_ci
188b815c7f3Sopenharmony_ci					if (d < 0)
189b815c7f3Sopenharmony_ci					{	sign_char = '-' ;
190b815c7f3Sopenharmony_ci						if (lead_char != '0' && left_align == SF_FALSE)
191b815c7f3Sopenharmony_ci							width_specifier -- ;
192b815c7f3Sopenharmony_ci
193b815c7f3Sopenharmony_ci						u = - ((unsigned) d) ;
194b815c7f3Sopenharmony_ci						}
195b815c7f3Sopenharmony_ci					else
196b815c7f3Sopenharmony_ci					{	u = (unsigned) d ;
197b815c7f3Sopenharmony_ci						}
198b815c7f3Sopenharmony_ci
199b815c7f3Sopenharmony_ci					tens = 1 ;
200b815c7f3Sopenharmony_ci					width = 1 ;
201b815c7f3Sopenharmony_ci					while (u / tens >= 10)
202b815c7f3Sopenharmony_ci					{	tens *= 10 ;
203b815c7f3Sopenharmony_ci						width ++ ;
204b815c7f3Sopenharmony_ci						} ;
205b815c7f3Sopenharmony_ci
206b815c7f3Sopenharmony_ci					width_specifier -= width ;
207b815c7f3Sopenharmony_ci
208b815c7f3Sopenharmony_ci					if (sign_char == ' ')
209b815c7f3Sopenharmony_ci					{	log_putchar (psf, ' ') ;
210b815c7f3Sopenharmony_ci						width_specifier -- ;
211b815c7f3Sopenharmony_ci						} ;
212b815c7f3Sopenharmony_ci
213b815c7f3Sopenharmony_ci					if (left_align == SF_FALSE && lead_char != '0')
214b815c7f3Sopenharmony_ci					{	if (sign_char == '+')
215b815c7f3Sopenharmony_ci							width_specifier -- ;
216b815c7f3Sopenharmony_ci
217b815c7f3Sopenharmony_ci						while (width_specifier -- > 0)
218b815c7f3Sopenharmony_ci							log_putchar (psf, lead_char) ;
219b815c7f3Sopenharmony_ci						} ;
220b815c7f3Sopenharmony_ci
221b815c7f3Sopenharmony_ci					if (sign_char == '+' || sign_char == '-')
222b815c7f3Sopenharmony_ci					{	log_putchar (psf, sign_char) ;
223b815c7f3Sopenharmony_ci						width_specifier -- ;
224b815c7f3Sopenharmony_ci						} ;
225b815c7f3Sopenharmony_ci
226b815c7f3Sopenharmony_ci					if (left_align == SF_FALSE)
227b815c7f3Sopenharmony_ci						while (width_specifier -- > 0)
228b815c7f3Sopenharmony_ci							log_putchar (psf, lead_char) ;
229b815c7f3Sopenharmony_ci
230b815c7f3Sopenharmony_ci					while (tens > 0)
231b815c7f3Sopenharmony_ci					{	log_putchar (psf, '0' + u / tens) ;
232b815c7f3Sopenharmony_ci						u %= tens ;
233b815c7f3Sopenharmony_ci						tens /= 10 ;
234b815c7f3Sopenharmony_ci						} ;
235b815c7f3Sopenharmony_ci
236b815c7f3Sopenharmony_ci					while (width_specifier -- > 0)
237b815c7f3Sopenharmony_ci						log_putchar (psf, lead_char) ;
238b815c7f3Sopenharmony_ci					break ;
239b815c7f3Sopenharmony_ci
240b815c7f3Sopenharmony_ci			case 'D': /* sf_count_t */
241b815c7f3Sopenharmony_ci					{	sf_count_t	D ;
242b815c7f3Sopenharmony_ci						uint64_t	U, Tens ;
243b815c7f3Sopenharmony_ci
244b815c7f3Sopenharmony_ci						D = va_arg (ap, sf_count_t) ;
245b815c7f3Sopenharmony_ci
246b815c7f3Sopenharmony_ci						if (D == 0)
247b815c7f3Sopenharmony_ci						{	while (-- width_specifier > 0)
248b815c7f3Sopenharmony_ci								log_putchar (psf, lead_char) ;
249b815c7f3Sopenharmony_ci							log_putchar (psf, '0') ;
250b815c7f3Sopenharmony_ci							break ;
251b815c7f3Sopenharmony_ci							}
252b815c7f3Sopenharmony_ci						else
253b815c7f3Sopenharmony_ci						{	if (D < 0)
254b815c7f3Sopenharmony_ci							{	log_putchar (psf, '-') ;
255b815c7f3Sopenharmony_ci								U = -((uint64_t) D) ;
256b815c7f3Sopenharmony_ci								}
257b815c7f3Sopenharmony_ci							else
258b815c7f3Sopenharmony_ci							{	U = (uint64_t) D;
259b815c7f3Sopenharmony_ci								}
260b815c7f3Sopenharmony_ci							}
261b815c7f3Sopenharmony_ci
262b815c7f3Sopenharmony_ci						Tens = 1 ;
263b815c7f3Sopenharmony_ci						width = 1 ;
264b815c7f3Sopenharmony_ci						while (U / Tens >= 10)
265b815c7f3Sopenharmony_ci						{	Tens *= 10 ;
266b815c7f3Sopenharmony_ci							width ++ ;
267b815c7f3Sopenharmony_ci							} ;
268b815c7f3Sopenharmony_ci
269b815c7f3Sopenharmony_ci						while (width_specifier > width)
270b815c7f3Sopenharmony_ci						{	log_putchar (psf, lead_char) ;
271b815c7f3Sopenharmony_ci							width_specifier-- ;
272b815c7f3Sopenharmony_ci							} ;
273b815c7f3Sopenharmony_ci
274b815c7f3Sopenharmony_ci						while (Tens > 0)
275b815c7f3Sopenharmony_ci						{	log_putchar (psf, '0' + U / Tens) ;
276b815c7f3Sopenharmony_ci							U %= Tens ;
277b815c7f3Sopenharmony_ci							Tens /= 10 ;
278b815c7f3Sopenharmony_ci							} ;
279b815c7f3Sopenharmony_ci						} ;
280b815c7f3Sopenharmony_ci					break ;
281b815c7f3Sopenharmony_ci
282b815c7f3Sopenharmony_ci			case 'u': /* unsigned int */
283b815c7f3Sopenharmony_ci					u = va_arg (ap, unsigned int) ;
284b815c7f3Sopenharmony_ci
285b815c7f3Sopenharmony_ci					tens = 1 ;
286b815c7f3Sopenharmony_ci					width = 1 ;
287b815c7f3Sopenharmony_ci					while (u / tens >= 10)
288b815c7f3Sopenharmony_ci					{	tens *= 10 ;
289b815c7f3Sopenharmony_ci						width ++ ;
290b815c7f3Sopenharmony_ci						} ;
291b815c7f3Sopenharmony_ci
292b815c7f3Sopenharmony_ci					width_specifier -= width ;
293b815c7f3Sopenharmony_ci
294b815c7f3Sopenharmony_ci					if (sign_char == ' ')
295b815c7f3Sopenharmony_ci					{	log_putchar (psf, ' ') ;
296b815c7f3Sopenharmony_ci						width_specifier -- ;
297b815c7f3Sopenharmony_ci						} ;
298b815c7f3Sopenharmony_ci
299b815c7f3Sopenharmony_ci					if (left_align == SF_FALSE && lead_char != '0')
300b815c7f3Sopenharmony_ci					{	if (sign_char == '+')
301b815c7f3Sopenharmony_ci							width_specifier -- ;
302b815c7f3Sopenharmony_ci
303b815c7f3Sopenharmony_ci						while (width_specifier -- > 0)
304b815c7f3Sopenharmony_ci							log_putchar (psf, lead_char) ;
305b815c7f3Sopenharmony_ci						} ;
306b815c7f3Sopenharmony_ci
307b815c7f3Sopenharmony_ci					if (sign_char == '+' || sign_char == '-')
308b815c7f3Sopenharmony_ci					{	log_putchar (psf, sign_char) ;
309b815c7f3Sopenharmony_ci						width_specifier -- ;
310b815c7f3Sopenharmony_ci						} ;
311b815c7f3Sopenharmony_ci
312b815c7f3Sopenharmony_ci					if (left_align == SF_FALSE)
313b815c7f3Sopenharmony_ci						while (width_specifier -- > 0)
314b815c7f3Sopenharmony_ci							log_putchar (psf, lead_char) ;
315b815c7f3Sopenharmony_ci
316b815c7f3Sopenharmony_ci					while (tens > 0)
317b815c7f3Sopenharmony_ci					{	log_putchar (psf, '0' + u / tens) ;
318b815c7f3Sopenharmony_ci						u %= tens ;
319b815c7f3Sopenharmony_ci						tens /= 10 ;
320b815c7f3Sopenharmony_ci						} ;
321b815c7f3Sopenharmony_ci
322b815c7f3Sopenharmony_ci					while (width_specifier -- > 0)
323b815c7f3Sopenharmony_ci						log_putchar (psf, lead_char) ;
324b815c7f3Sopenharmony_ci					break ;
325b815c7f3Sopenharmony_ci
326b815c7f3Sopenharmony_ci			case 'c': /* char */
327b815c7f3Sopenharmony_ci					c = va_arg (ap, int) & 0xFF ;
328b815c7f3Sopenharmony_ci					log_putchar (psf, c) ;
329b815c7f3Sopenharmony_ci					break ;
330b815c7f3Sopenharmony_ci
331b815c7f3Sopenharmony_ci			case 'x': /* hex */
332b815c7f3Sopenharmony_ci			case 'X': /* hex */
333b815c7f3Sopenharmony_ci					d = va_arg (ap, int) ;
334b815c7f3Sopenharmony_ci
335b815c7f3Sopenharmony_ci					if (d == 0)
336b815c7f3Sopenharmony_ci					{	while (--width_specifier > 0)
337b815c7f3Sopenharmony_ci							log_putchar (psf, lead_char) ;
338b815c7f3Sopenharmony_ci						log_putchar (psf, '0') ;
339b815c7f3Sopenharmony_ci						break ;
340b815c7f3Sopenharmony_ci						} ;
341b815c7f3Sopenharmony_ci					shift = 28 ;
342b815c7f3Sopenharmony_ci					width = (width_specifier < 8) ? 8 : width_specifier ;
343b815c7f3Sopenharmony_ci					while (! ((((uint32_t) 0xF) << shift) & d))
344b815c7f3Sopenharmony_ci					{	shift -= 4 ;
345b815c7f3Sopenharmony_ci						width -- ;
346b815c7f3Sopenharmony_ci						} ;
347b815c7f3Sopenharmony_ci
348b815c7f3Sopenharmony_ci					while (width > 0 && width_specifier > width)
349b815c7f3Sopenharmony_ci					{	log_putchar (psf, lead_char) ;
350b815c7f3Sopenharmony_ci						width_specifier-- ;
351b815c7f3Sopenharmony_ci						} ;
352b815c7f3Sopenharmony_ci
353b815c7f3Sopenharmony_ci					while (shift >= 0)
354b815c7f3Sopenharmony_ci					{	c = (d >> shift) & 0xF ;
355b815c7f3Sopenharmony_ci						log_putchar (psf, (c > 9) ? c + 'A' - 10 : c + '0') ;
356b815c7f3Sopenharmony_ci						shift -= 4 ;
357b815c7f3Sopenharmony_ci						} ;
358b815c7f3Sopenharmony_ci					break ;
359b815c7f3Sopenharmony_ci
360b815c7f3Sopenharmony_ci			case 'M': /* int2str */
361b815c7f3Sopenharmony_ci					d = va_arg (ap, int) ;
362b815c7f3Sopenharmony_ci					if (CPU_IS_LITTLE_ENDIAN)
363b815c7f3Sopenharmony_ci					{	istr [0] = d & 0xFF ;
364b815c7f3Sopenharmony_ci						istr [1] = (d >> 8) & 0xFF ;
365b815c7f3Sopenharmony_ci						istr [2] = (d >> 16) & 0xFF ;
366b815c7f3Sopenharmony_ci						istr [3] = (d >> 24) & 0xFF ;
367b815c7f3Sopenharmony_ci						}
368b815c7f3Sopenharmony_ci					else
369b815c7f3Sopenharmony_ci					{	istr [3] = d & 0xFF ;
370b815c7f3Sopenharmony_ci						istr [2] = (d >> 8) & 0xFF ;
371b815c7f3Sopenharmony_ci						istr [1] = (d >> 16) & 0xFF ;
372b815c7f3Sopenharmony_ci						istr [0] = (d >> 24) & 0xFF ;
373b815c7f3Sopenharmony_ci						} ;
374b815c7f3Sopenharmony_ci					istr [4] = 0 ;
375b815c7f3Sopenharmony_ci					strptr = istr ;
376b815c7f3Sopenharmony_ci					while (*strptr)
377b815c7f3Sopenharmony_ci					{	c = *strptr++ ;
378b815c7f3Sopenharmony_ci						log_putchar (psf, psf_isprint (c) ? c : '.') ;
379b815c7f3Sopenharmony_ci						} ;
380b815c7f3Sopenharmony_ci					break ;
381b815c7f3Sopenharmony_ci
382b815c7f3Sopenharmony_ci			default :
383b815c7f3Sopenharmony_ci					log_putchar (psf, '*') ;
384b815c7f3Sopenharmony_ci					log_putchar (psf, c) ;
385b815c7f3Sopenharmony_ci					log_putchar (psf, '*') ;
386b815c7f3Sopenharmony_ci					break ;
387b815c7f3Sopenharmony_ci			} /* switch */
388b815c7f3Sopenharmony_ci		} /* while */
389b815c7f3Sopenharmony_ci
390b815c7f3Sopenharmony_ci	va_end (ap) ;
391b815c7f3Sopenharmony_ci	return ;
392b815c7f3Sopenharmony_ci} /* psf_log_printf */
393b815c7f3Sopenharmony_ci
394b815c7f3Sopenharmony_ci/*-----------------------------------------------------------------------------------------------
395b815c7f3Sopenharmony_ci**  ASCII header printf functions.
396b815c7f3Sopenharmony_ci**  Some formats (ie NIST) use ascii text in their headers.
397b815c7f3Sopenharmony_ci**  Format specifiers are the same as the standard printf specifiers (uses vsnprintf).
398b815c7f3Sopenharmony_ci**  If this generates a compile error on any system, the author should be notified
399b815c7f3Sopenharmony_ci**  so an alternative vsnprintf can be provided.
400b815c7f3Sopenharmony_ci*/
401b815c7f3Sopenharmony_ci
402b815c7f3Sopenharmony_civoid
403b815c7f3Sopenharmony_cipsf_asciiheader_printf (SF_PRIVATE *psf, const char *format, ...)
404b815c7f3Sopenharmony_ci{	va_list	argptr ;
405b815c7f3Sopenharmony_ci	int		maxlen ;
406b815c7f3Sopenharmony_ci	char	*start ;
407b815c7f3Sopenharmony_ci
408b815c7f3Sopenharmony_ci	if (! format)
409b815c7f3Sopenharmony_ci		return ;
410b815c7f3Sopenharmony_ci
411b815c7f3Sopenharmony_ci	maxlen = strlen ((char*) psf->header.ptr) ;
412b815c7f3Sopenharmony_ci	start	= ((char*) psf->header.ptr) + maxlen ;
413b815c7f3Sopenharmony_ci	maxlen	= psf->header.len - maxlen ;
414b815c7f3Sopenharmony_ci
415b815c7f3Sopenharmony_ci	va_start (argptr, format) ;
416b815c7f3Sopenharmony_ci	vsnprintf (start, maxlen, format, argptr) ;
417b815c7f3Sopenharmony_ci	va_end (argptr) ;
418b815c7f3Sopenharmony_ci
419b815c7f3Sopenharmony_ci	/* Make sure the string is properly terminated. */
420b815c7f3Sopenharmony_ci	start [maxlen - 1] = 0 ;
421b815c7f3Sopenharmony_ci
422b815c7f3Sopenharmony_ci	psf->header.indx = strlen ((char*) psf->header.ptr) ;
423b815c7f3Sopenharmony_ci
424b815c7f3Sopenharmony_ci	return ;
425b815c7f3Sopenharmony_ci} /* psf_asciiheader_printf */
426b815c7f3Sopenharmony_ci
427b815c7f3Sopenharmony_ci/*-----------------------------------------------------------------------------------------------
428b815c7f3Sopenharmony_ci**  Binary header writing functions. Returns number of bytes written.
429b815c7f3Sopenharmony_ci**
430b815c7f3Sopenharmony_ci**  Format specifiers for psf_binheader_writef are as follows
431b815c7f3Sopenharmony_ci**		m	- marker - four bytes - no endian manipulation
432b815c7f3Sopenharmony_ci**
433b815c7f3Sopenharmony_ci**		e   - all following numerical values will be little endian
434b815c7f3Sopenharmony_ci**		E   - all following numerical values will be big endian
435b815c7f3Sopenharmony_ci**
436b815c7f3Sopenharmony_ci**		t   - all following O types will be truncated to 4 bytes
437b815c7f3Sopenharmony_ci**		T   - switch off truncation of all following O types
438b815c7f3Sopenharmony_ci**
439b815c7f3Sopenharmony_ci**		1	- single byte value
440b815c7f3Sopenharmony_ci**		2	- two byte value
441b815c7f3Sopenharmony_ci**		3	- three byte value
442b815c7f3Sopenharmony_ci**		4	- four byte value
443b815c7f3Sopenharmony_ci**		8	- eight byte value (sometimes written as 4 bytes)
444b815c7f3Sopenharmony_ci**
445b815c7f3Sopenharmony_ci**		s   - string preceded by a four byte length
446b815c7f3Sopenharmony_ci**		S   - string including null terminator
447b815c7f3Sopenharmony_ci**      p   - a Pascal string
448b815c7f3Sopenharmony_ci**
449b815c7f3Sopenharmony_ci**		f	- floating point data
450b815c7f3Sopenharmony_ci**		d	- double precision floating point data
451b815c7f3Sopenharmony_ci**		h	- 16 binary bytes value
452b815c7f3Sopenharmony_ci**
453b815c7f3Sopenharmony_ci**		b	- binary data (see below)
454b815c7f3Sopenharmony_ci**		z   - zero bytes (ses below)
455b815c7f3Sopenharmony_ci**		j	- jump forwards or backwards
456b815c7f3Sopenharmony_ci**
457b815c7f3Sopenharmony_ci**	To write a word followed by an int (both little endian) use:
458b815c7f3Sopenharmony_ci**		psf_binheader_writef ("e24", wordval, longval) ;
459b815c7f3Sopenharmony_ci**
460b815c7f3Sopenharmony_ci**	To write binary data use:
461b815c7f3Sopenharmony_ci**		psf_binheader_writef ("b", &bindata, sizeof (bindata)) ;
462b815c7f3Sopenharmony_ci**
463b815c7f3Sopenharmony_ci**	To write N zero bytes use:
464b815c7f3Sopenharmony_ci**			NOTE: due to platform issues (ie x86-64) you should cast the
465b815c7f3Sopenharmony_ci**			argument to size_t or ensure the variable type is size_t.
466b815c7f3Sopenharmony_ci**		psf_binheader_writef ("z", N) ;
467b815c7f3Sopenharmony_ci*/
468b815c7f3Sopenharmony_ci
469b815c7f3Sopenharmony_ci/* These macros may seem a bit messy but do prevent problems with processors which
470b815c7f3Sopenharmony_ci** seg. fault when asked to write an int or short to a non-int/short aligned address.
471b815c7f3Sopenharmony_ci*/
472b815c7f3Sopenharmony_ci
473b815c7f3Sopenharmony_cistatic inline void
474b815c7f3Sopenharmony_ciheader_put_byte (SF_PRIVATE *psf, char x)
475b815c7f3Sopenharmony_ci{	psf->header.ptr [psf->header.indx++] = x ;
476b815c7f3Sopenharmony_ci} /* header_put_byte */
477b815c7f3Sopenharmony_ci
478b815c7f3Sopenharmony_ci#if (CPU_IS_BIG_ENDIAN == 1)
479b815c7f3Sopenharmony_cistatic inline void
480b815c7f3Sopenharmony_ciheader_put_marker (SF_PRIVATE *psf, int x)
481b815c7f3Sopenharmony_ci{	psf->header.ptr [psf->header.indx++] = (x >> 24) ;
482b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (x >> 16) ;
483b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (x >> 8) ;
484b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = x ;
485b815c7f3Sopenharmony_ci} /* header_put_marker */
486b815c7f3Sopenharmony_ci
487b815c7f3Sopenharmony_ci#elif (CPU_IS_LITTLE_ENDIAN == 1)
488b815c7f3Sopenharmony_cistatic inline void
489b815c7f3Sopenharmony_ciheader_put_marker (SF_PRIVATE *psf, int x)
490b815c7f3Sopenharmony_ci{	psf->header.ptr [psf->header.indx++] = x ;
491b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (x >> 8) ;
492b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (x >> 16) ;
493b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (x >> 24) ;
494b815c7f3Sopenharmony_ci} /* header_put_marker */
495b815c7f3Sopenharmony_ci
496b815c7f3Sopenharmony_ci#else
497b815c7f3Sopenharmony_ci#	error "Cannot determine endian-ness of processor."
498b815c7f3Sopenharmony_ci#endif
499b815c7f3Sopenharmony_ci
500b815c7f3Sopenharmony_ci
501b815c7f3Sopenharmony_cistatic inline void
502b815c7f3Sopenharmony_ciheader_put_be_short (SF_PRIVATE *psf, int x)
503b815c7f3Sopenharmony_ci{	psf->header.ptr [psf->header.indx++] = (x >> 8) ;
504b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = x ;
505b815c7f3Sopenharmony_ci} /* header_put_be_short */
506b815c7f3Sopenharmony_ci
507b815c7f3Sopenharmony_cistatic inline void
508b815c7f3Sopenharmony_ciheader_put_le_short (SF_PRIVATE *psf, int x)
509b815c7f3Sopenharmony_ci{	psf->header.ptr [psf->header.indx++] = x ;
510b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (x >> 8) ;
511b815c7f3Sopenharmony_ci} /* header_put_le_short */
512b815c7f3Sopenharmony_ci
513b815c7f3Sopenharmony_cistatic inline void
514b815c7f3Sopenharmony_ciheader_put_be_3byte (SF_PRIVATE *psf, int x)
515b815c7f3Sopenharmony_ci{	psf->header.ptr [psf->header.indx++] = (x >> 16) ;
516b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (x >> 8) ;
517b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = x ;
518b815c7f3Sopenharmony_ci} /* header_put_be_3byte */
519b815c7f3Sopenharmony_ci
520b815c7f3Sopenharmony_cistatic inline void
521b815c7f3Sopenharmony_ciheader_put_le_3byte (SF_PRIVATE *psf, int x)
522b815c7f3Sopenharmony_ci{	psf->header.ptr [psf->header.indx++] = x ;
523b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (x >> 8) ;
524b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (x >> 16) ;
525b815c7f3Sopenharmony_ci} /* header_put_le_3byte */
526b815c7f3Sopenharmony_ci
527b815c7f3Sopenharmony_cistatic inline void
528b815c7f3Sopenharmony_ciheader_put_be_int (SF_PRIVATE *psf, int x)
529b815c7f3Sopenharmony_ci{	psf->header.ptr [psf->header.indx++] = (x >> 24) ;
530b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (x >> 16) ;
531b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (x >> 8) ;
532b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = x ;
533b815c7f3Sopenharmony_ci} /* header_put_be_int */
534b815c7f3Sopenharmony_ci
535b815c7f3Sopenharmony_cistatic inline void
536b815c7f3Sopenharmony_ciheader_put_le_int (SF_PRIVATE *psf, int x)
537b815c7f3Sopenharmony_ci{	psf->header.ptr [psf->header.indx++] = x ;
538b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (x >> 8) ;
539b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (x >> 16) ;
540b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (x >> 24) ;
541b815c7f3Sopenharmony_ci} /* header_put_le_int */
542b815c7f3Sopenharmony_ci
543b815c7f3Sopenharmony_cistatic inline void
544b815c7f3Sopenharmony_ciheader_put_be_8byte (SF_PRIVATE *psf, sf_count_t x)
545b815c7f3Sopenharmony_ci{	psf->header.ptr [psf->header.indx++] = (x >> 56) ;
546b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 48) ;
547b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 40) ;
548b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 32) ;
549b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 24) ;
550b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 16) ;
551b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 8) ;
552b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (unsigned char) x ;
553b815c7f3Sopenharmony_ci} /* header_put_be_8byte */
554b815c7f3Sopenharmony_ci
555b815c7f3Sopenharmony_cistatic inline void
556b815c7f3Sopenharmony_ciheader_put_le_8byte (SF_PRIVATE *psf, sf_count_t x)
557b815c7f3Sopenharmony_ci{	psf->header.ptr [psf->header.indx++] = (unsigned char) x ;
558b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 8) ;
559b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 16) ;
560b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 24) ;
561b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 32) ;
562b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 40) ;
563b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 48) ;
564b815c7f3Sopenharmony_ci	psf->header.ptr [psf->header.indx++] = (x >> 56) ;
565b815c7f3Sopenharmony_ci} /* header_put_le_8byte */
566b815c7f3Sopenharmony_ci
567b815c7f3Sopenharmony_ciint
568b815c7f3Sopenharmony_cipsf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
569b815c7f3Sopenharmony_ci{	va_list	argptr ;
570b815c7f3Sopenharmony_ci	sf_count_t 		countdata ;
571b815c7f3Sopenharmony_ci	unsigned long 	longdata ;
572b815c7f3Sopenharmony_ci	unsigned int 	data ;
573b815c7f3Sopenharmony_ci	float			floatdata ;
574b815c7f3Sopenharmony_ci	double			doubledata ;
575b815c7f3Sopenharmony_ci	void			*bindata ;
576b815c7f3Sopenharmony_ci	size_t			size ;
577b815c7f3Sopenharmony_ci	char			c, *strptr ;
578b815c7f3Sopenharmony_ci	int				count = 0, trunc_8to4 = SF_FALSE ;
579b815c7f3Sopenharmony_ci
580b815c7f3Sopenharmony_ci	if (! format)
581b815c7f3Sopenharmony_ci		return psf_ftell (psf) ;
582b815c7f3Sopenharmony_ci
583b815c7f3Sopenharmony_ci	va_start (argptr, format) ;
584b815c7f3Sopenharmony_ci
585b815c7f3Sopenharmony_ci	while ((c = *format++))
586b815c7f3Sopenharmony_ci	{
587b815c7f3Sopenharmony_ci		if (psf->header.indx + 16 >= psf->header.len && psf_bump_header_allocation (psf, 16))
588b815c7f3Sopenharmony_ci			break ;
589b815c7f3Sopenharmony_ci
590b815c7f3Sopenharmony_ci		switch (c)
591b815c7f3Sopenharmony_ci		{	case ' ' : /* Do nothing. Just used to space out format string. */
592b815c7f3Sopenharmony_ci					break ;
593b815c7f3Sopenharmony_ci
594b815c7f3Sopenharmony_ci			case 'e' : /* All conversions are now from LE to host. */
595b815c7f3Sopenharmony_ci					psf->rwf_endian = SF_ENDIAN_LITTLE ;
596b815c7f3Sopenharmony_ci					break ;
597b815c7f3Sopenharmony_ci
598b815c7f3Sopenharmony_ci			case 'E' : /* All conversions are now from BE to host. */
599b815c7f3Sopenharmony_ci					psf->rwf_endian = SF_ENDIAN_BIG ;
600b815c7f3Sopenharmony_ci					break ;
601b815c7f3Sopenharmony_ci
602b815c7f3Sopenharmony_ci			case 't' : /* All 8 byte values now get written as 4 bytes. */
603b815c7f3Sopenharmony_ci					trunc_8to4 = SF_TRUE ;
604b815c7f3Sopenharmony_ci					break ;
605b815c7f3Sopenharmony_ci
606b815c7f3Sopenharmony_ci			case 'T' : /* All 8 byte values now get written as 8 bytes. */
607b815c7f3Sopenharmony_ci					trunc_8to4 = SF_FALSE ;
608b815c7f3Sopenharmony_ci					break ;
609b815c7f3Sopenharmony_ci
610b815c7f3Sopenharmony_ci			case 'm' :
611b815c7f3Sopenharmony_ci					data = va_arg (argptr, unsigned int) ;
612b815c7f3Sopenharmony_ci					header_put_marker (psf, data) ;
613b815c7f3Sopenharmony_ci					count += 4 ;
614b815c7f3Sopenharmony_ci					break ;
615b815c7f3Sopenharmony_ci
616b815c7f3Sopenharmony_ci			case '1' :
617b815c7f3Sopenharmony_ci					data = va_arg (argptr, unsigned int) ;
618b815c7f3Sopenharmony_ci					header_put_byte (psf, data) ;
619b815c7f3Sopenharmony_ci					count += 1 ;
620b815c7f3Sopenharmony_ci					break ;
621b815c7f3Sopenharmony_ci
622b815c7f3Sopenharmony_ci			case '2' :
623b815c7f3Sopenharmony_ci					data = va_arg (argptr, unsigned int) ;
624b815c7f3Sopenharmony_ci					if (psf->rwf_endian == SF_ENDIAN_BIG)
625b815c7f3Sopenharmony_ci					{	header_put_be_short (psf, data) ;
626b815c7f3Sopenharmony_ci						}
627b815c7f3Sopenharmony_ci					else
628b815c7f3Sopenharmony_ci					{	header_put_le_short (psf, data) ;
629b815c7f3Sopenharmony_ci						} ;
630b815c7f3Sopenharmony_ci					count += 2 ;
631b815c7f3Sopenharmony_ci					break ;
632b815c7f3Sopenharmony_ci
633b815c7f3Sopenharmony_ci			case '3' : /* tribyte */
634b815c7f3Sopenharmony_ci					data = va_arg (argptr, unsigned int) ;
635b815c7f3Sopenharmony_ci					if (psf->rwf_endian == SF_ENDIAN_BIG)
636b815c7f3Sopenharmony_ci					{	header_put_be_3byte (psf, data) ;
637b815c7f3Sopenharmony_ci						}
638b815c7f3Sopenharmony_ci					else
639b815c7f3Sopenharmony_ci					{	header_put_le_3byte (psf, data) ;
640b815c7f3Sopenharmony_ci						} ;
641b815c7f3Sopenharmony_ci					count += 3 ;
642b815c7f3Sopenharmony_ci					break ;
643b815c7f3Sopenharmony_ci
644b815c7f3Sopenharmony_ci			case '4' :
645b815c7f3Sopenharmony_ci					data = va_arg (argptr, unsigned int) ;
646b815c7f3Sopenharmony_ci					if (psf->rwf_endian == SF_ENDIAN_BIG)
647b815c7f3Sopenharmony_ci					{	header_put_be_int (psf, data) ;
648b815c7f3Sopenharmony_ci						}
649b815c7f3Sopenharmony_ci					else
650b815c7f3Sopenharmony_ci					{	header_put_le_int (psf, data) ;
651b815c7f3Sopenharmony_ci						} ;
652b815c7f3Sopenharmony_ci					count += 4 ;
653b815c7f3Sopenharmony_ci					break ;
654b815c7f3Sopenharmony_ci
655b815c7f3Sopenharmony_ci			case '8' :
656b815c7f3Sopenharmony_ci					countdata = va_arg (argptr, sf_count_t) ;
657b815c7f3Sopenharmony_ci					if (psf->rwf_endian == SF_ENDIAN_BIG && trunc_8to4 == SF_FALSE)
658b815c7f3Sopenharmony_ci					{	header_put_be_8byte (psf, countdata) ;
659b815c7f3Sopenharmony_ci						count += 8 ;
660b815c7f3Sopenharmony_ci						}
661b815c7f3Sopenharmony_ci					else if (psf->rwf_endian == SF_ENDIAN_LITTLE && trunc_8to4 == SF_FALSE)
662b815c7f3Sopenharmony_ci					{	header_put_le_8byte (psf, countdata) ;
663b815c7f3Sopenharmony_ci						count += 8 ;
664b815c7f3Sopenharmony_ci						}
665b815c7f3Sopenharmony_ci					else if (psf->rwf_endian == SF_ENDIAN_BIG && trunc_8to4 == SF_TRUE)
666b815c7f3Sopenharmony_ci					{	longdata = countdata & 0xFFFFFFFF ;
667b815c7f3Sopenharmony_ci						header_put_be_int (psf, longdata) ;
668b815c7f3Sopenharmony_ci						count += 4 ;
669b815c7f3Sopenharmony_ci						}
670b815c7f3Sopenharmony_ci					else if (psf->rwf_endian == SF_ENDIAN_LITTLE && trunc_8to4 == SF_TRUE)
671b815c7f3Sopenharmony_ci					{	longdata = countdata & 0xFFFFFFFF ;
672b815c7f3Sopenharmony_ci						header_put_le_int (psf, longdata) ;
673b815c7f3Sopenharmony_ci						count += 4 ;
674b815c7f3Sopenharmony_ci						}
675b815c7f3Sopenharmony_ci					break ;
676b815c7f3Sopenharmony_ci
677b815c7f3Sopenharmony_ci			case 'f' :
678b815c7f3Sopenharmony_ci					/* Floats are passed as doubles. Is this always true? */
679b815c7f3Sopenharmony_ci					floatdata = (float) va_arg (argptr, double) ;
680b815c7f3Sopenharmony_ci					if (psf->rwf_endian == SF_ENDIAN_BIG)
681b815c7f3Sopenharmony_ci						float32_be_write (floatdata, psf->header.ptr + psf->header.indx) ;
682b815c7f3Sopenharmony_ci					else
683b815c7f3Sopenharmony_ci						float32_le_write (floatdata, psf->header.ptr + psf->header.indx) ;
684b815c7f3Sopenharmony_ci					psf->header.indx += 4 ;
685b815c7f3Sopenharmony_ci					count += 4 ;
686b815c7f3Sopenharmony_ci					break ;
687b815c7f3Sopenharmony_ci
688b815c7f3Sopenharmony_ci			case 'd' :
689b815c7f3Sopenharmony_ci					doubledata = va_arg (argptr, double) ;
690b815c7f3Sopenharmony_ci					if (psf->rwf_endian == SF_ENDIAN_BIG)
691b815c7f3Sopenharmony_ci						double64_be_write (doubledata, psf->header.ptr + psf->header.indx) ;
692b815c7f3Sopenharmony_ci					else
693b815c7f3Sopenharmony_ci						double64_le_write (doubledata, psf->header.ptr + psf->header.indx) ;
694b815c7f3Sopenharmony_ci					psf->header.indx += 8 ;
695b815c7f3Sopenharmony_ci					count += 8 ;
696b815c7f3Sopenharmony_ci					break ;
697b815c7f3Sopenharmony_ci
698b815c7f3Sopenharmony_ci			case 's' :
699b815c7f3Sopenharmony_ci					/* Write a C string (guaranteed to have a zero terminator). */
700b815c7f3Sopenharmony_ci					strptr = va_arg (argptr, char *) ;
701b815c7f3Sopenharmony_ci					size = strlen (strptr) + 1 ;
702b815c7f3Sopenharmony_ci
703b815c7f3Sopenharmony_ci					if (psf->header.indx + 4 + (sf_count_t) size + (sf_count_t) (size & 1) > psf->header.len && psf_bump_header_allocation (psf, 4 + size + (size & 1)))
704b815c7f3Sopenharmony_ci						break ;
705b815c7f3Sopenharmony_ci
706b815c7f3Sopenharmony_ci					if (psf->rwf_endian == SF_ENDIAN_BIG)
707b815c7f3Sopenharmony_ci						header_put_be_int (psf, size + (size & 1)) ;
708b815c7f3Sopenharmony_ci					else
709b815c7f3Sopenharmony_ci						header_put_le_int (psf, size + (size & 1)) ;
710b815c7f3Sopenharmony_ci					memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size) ;
711b815c7f3Sopenharmony_ci					size += (size & 1) ;
712b815c7f3Sopenharmony_ci					psf->header.indx += size ;
713b815c7f3Sopenharmony_ci					psf->header.ptr [psf->header.indx - 1] = 0 ;
714b815c7f3Sopenharmony_ci					count += 4 + size ;
715b815c7f3Sopenharmony_ci					break ;
716b815c7f3Sopenharmony_ci
717b815c7f3Sopenharmony_ci			case 'S' :
718b815c7f3Sopenharmony_ci					/*
719b815c7f3Sopenharmony_ci					**	Write an AIFF style string (no zero terminator but possibly
720b815c7f3Sopenharmony_ci					**	an extra pad byte if the string length is odd).
721b815c7f3Sopenharmony_ci					*/
722b815c7f3Sopenharmony_ci					strptr = va_arg (argptr, char *) ;
723b815c7f3Sopenharmony_ci					size = strlen (strptr) ;
724b815c7f3Sopenharmony_ci					if (psf->header.indx + 4 + (sf_count_t) size + (sf_count_t) (size & 1) > psf->header.len && psf_bump_header_allocation (psf, 4 + size + (size & 1)))
725b815c7f3Sopenharmony_ci						break ;
726b815c7f3Sopenharmony_ci					if (psf->rwf_endian == SF_ENDIAN_BIG)
727b815c7f3Sopenharmony_ci						header_put_be_int (psf, size) ;
728b815c7f3Sopenharmony_ci					else
729b815c7f3Sopenharmony_ci						header_put_le_int (psf, size) ;
730b815c7f3Sopenharmony_ci					memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size + (size & 1)) ;
731b815c7f3Sopenharmony_ci					size += (size & 1) ;
732b815c7f3Sopenharmony_ci					psf->header.indx += size ;
733b815c7f3Sopenharmony_ci					count += 4 + size ;
734b815c7f3Sopenharmony_ci					break ;
735b815c7f3Sopenharmony_ci
736b815c7f3Sopenharmony_ci			case 'p' :
737b815c7f3Sopenharmony_ci					/* Write a PASCAL string (as used by AIFF files).
738b815c7f3Sopenharmony_ci					*/
739b815c7f3Sopenharmony_ci					strptr = va_arg (argptr, char *) ;
740b815c7f3Sopenharmony_ci					size = strlen (strptr) ;
741b815c7f3Sopenharmony_ci					size = (size & 1) ? size : size + 1 ;
742b815c7f3Sopenharmony_ci					size = (size > 254) ? 254 : size ;
743b815c7f3Sopenharmony_ci
744b815c7f3Sopenharmony_ci					if (psf->header.indx + 1 + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, 1 + size))
745b815c7f3Sopenharmony_ci						break ;
746b815c7f3Sopenharmony_ci
747b815c7f3Sopenharmony_ci					header_put_byte (psf, size) ;
748b815c7f3Sopenharmony_ci					memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size) ;
749b815c7f3Sopenharmony_ci					psf->header.indx += size ;
750b815c7f3Sopenharmony_ci					count += 1 + size ;
751b815c7f3Sopenharmony_ci					break ;
752b815c7f3Sopenharmony_ci
753b815c7f3Sopenharmony_ci			case 'b' :
754b815c7f3Sopenharmony_ci					bindata	= va_arg (argptr, void *) ;
755b815c7f3Sopenharmony_ci					size	= va_arg (argptr, size_t) ;
756b815c7f3Sopenharmony_ci
757b815c7f3Sopenharmony_ci					if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size))
758b815c7f3Sopenharmony_ci						break ;
759b815c7f3Sopenharmony_ci
760b815c7f3Sopenharmony_ci					memcpy (&(psf->header.ptr [psf->header.indx]), bindata, size) ;
761b815c7f3Sopenharmony_ci					psf->header.indx += size ;
762b815c7f3Sopenharmony_ci					count += size ;
763b815c7f3Sopenharmony_ci					break ;
764b815c7f3Sopenharmony_ci
765b815c7f3Sopenharmony_ci			case 'z' :
766b815c7f3Sopenharmony_ci					size = va_arg (argptr, size_t) ;
767b815c7f3Sopenharmony_ci
768b815c7f3Sopenharmony_ci					if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size))
769b815c7f3Sopenharmony_ci						break ;
770b815c7f3Sopenharmony_ci
771b815c7f3Sopenharmony_ci					count += size ;
772b815c7f3Sopenharmony_ci					while (size)
773b815c7f3Sopenharmony_ci					{	psf->header.ptr [psf->header.indx] = 0 ;
774b815c7f3Sopenharmony_ci						psf->header.indx ++ ;
775b815c7f3Sopenharmony_ci						size -- ;
776b815c7f3Sopenharmony_ci						} ;
777b815c7f3Sopenharmony_ci					break ;
778b815c7f3Sopenharmony_ci
779b815c7f3Sopenharmony_ci			case 'h' :
780b815c7f3Sopenharmony_ci					bindata = va_arg (argptr, void *) ;
781b815c7f3Sopenharmony_ci					memcpy (&(psf->header.ptr [psf->header.indx]), bindata, 16) ;
782b815c7f3Sopenharmony_ci					psf->header.indx += 16 ;
783b815c7f3Sopenharmony_ci					count += 16 ;
784b815c7f3Sopenharmony_ci					break ;
785b815c7f3Sopenharmony_ci
786b815c7f3Sopenharmony_ci			case 'j' :	/* Jump forwards/backwards by specified amount. */
787b815c7f3Sopenharmony_ci					size = va_arg (argptr, size_t) ;
788b815c7f3Sopenharmony_ci
789b815c7f3Sopenharmony_ci					if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size))
790b815c7f3Sopenharmony_ci						break ;
791b815c7f3Sopenharmony_ci
792b815c7f3Sopenharmony_ci					psf->header.indx += size ;
793b815c7f3Sopenharmony_ci					count += size ;
794b815c7f3Sopenharmony_ci					break ;
795b815c7f3Sopenharmony_ci
796b815c7f3Sopenharmony_ci			case 'o' :	/* Jump to specified offset. */
797b815c7f3Sopenharmony_ci					size = va_arg (argptr, size_t) ;
798b815c7f3Sopenharmony_ci
799b815c7f3Sopenharmony_ci					if ((sf_count_t) size >= psf->header.len && psf_bump_header_allocation (psf, size))
800b815c7f3Sopenharmony_ci						break ;
801b815c7f3Sopenharmony_ci
802b815c7f3Sopenharmony_ci					psf->header.indx = size ;
803b815c7f3Sopenharmony_ci					break ;
804b815c7f3Sopenharmony_ci
805b815c7f3Sopenharmony_ci			default :
806b815c7f3Sopenharmony_ci				psf_log_printf (psf, "*** Invalid format specifier `%c'\n", c) ;
807b815c7f3Sopenharmony_ci				psf->error = SFE_INTERNAL ;
808b815c7f3Sopenharmony_ci				break ;
809b815c7f3Sopenharmony_ci			} ;
810b815c7f3Sopenharmony_ci		} ;
811b815c7f3Sopenharmony_ci
812b815c7f3Sopenharmony_ci	va_end (argptr) ;
813b815c7f3Sopenharmony_ci	return count ;
814b815c7f3Sopenharmony_ci} /* psf_binheader_writef */
815b815c7f3Sopenharmony_ci
816b815c7f3Sopenharmony_ci/*-----------------------------------------------------------------------------------------------
817b815c7f3Sopenharmony_ci**  Binary header reading functions. Returns number of bytes read.
818b815c7f3Sopenharmony_ci**
819b815c7f3Sopenharmony_ci**	Format specifiers are the same as for header write function above with the following
820b815c7f3Sopenharmony_ci**	additions:
821b815c7f3Sopenharmony_ci**
822b815c7f3Sopenharmony_ci**		p   - jump a given number of position from start of file.
823b815c7f3Sopenharmony_ci**
824b815c7f3Sopenharmony_ci**	If format is NULL, psf_binheader_readf returns the current offset.
825b815c7f3Sopenharmony_ci*/
826b815c7f3Sopenharmony_ci
827b815c7f3Sopenharmony_ci#if (CPU_IS_BIG_ENDIAN == 1)
828b815c7f3Sopenharmony_ci#define	GET_MARKER(ptr)	(	(((uint32_t) (ptr) [0]) << 24)	| ((ptr) [1] << 16) |	\
829b815c7f3Sopenharmony_ci							((ptr) [2] << 8)	| ((ptr) [3]))
830b815c7f3Sopenharmony_ci
831b815c7f3Sopenharmony_ci#elif (CPU_IS_LITTLE_ENDIAN == 1)
832b815c7f3Sopenharmony_ci#define	GET_MARKER(ptr)	(	((ptr) [0])			| ((ptr) [1] << 8) |	\
833b815c7f3Sopenharmony_ci							((ptr) [2] << 16)	| (((uint32_t) (ptr) [3]) << 24))
834b815c7f3Sopenharmony_ci
835b815c7f3Sopenharmony_ci#else
836b815c7f3Sopenharmony_ci#	error "Cannot determine endian-ness of processor."
837b815c7f3Sopenharmony_ci#endif
838b815c7f3Sopenharmony_ci
839b815c7f3Sopenharmony_ci#define	GET_LE_SHORT(ptr)	(((ptr) [1] << 8) | ((ptr) [0]))
840b815c7f3Sopenharmony_ci#define	GET_BE_SHORT(ptr)	(((ptr) [0] << 8) | ((ptr) [1]))
841b815c7f3Sopenharmony_ci
842b815c7f3Sopenharmony_ci#define	GET_LE_3BYTE(ptr)	(	((ptr) [2] << 16) | ((ptr) [1] << 8) | ((ptr) [0]))
843b815c7f3Sopenharmony_ci#define	GET_BE_3BYTE(ptr)	(	((ptr) [0] << 16) | ((ptr) [1] << 8) | ((ptr) [2]))
844b815c7f3Sopenharmony_ci
845b815c7f3Sopenharmony_ci#define	GET_LE_INT(ptr)		(	((ptr) [3] << 24)	| ((ptr) [2] << 16) |	\
846b815c7f3Sopenharmony_ci								((ptr) [1] << 8)	| ((ptr) [0]))
847b815c7f3Sopenharmony_ci
848b815c7f3Sopenharmony_ci#define	GET_BE_INT(ptr)		(	((ptr) [0] << 24)	| ((ptr) [1] << 16) |	\
849b815c7f3Sopenharmony_ci								((ptr) [2] << 8)	| ((ptr) [3]))
850b815c7f3Sopenharmony_ci
851b815c7f3Sopenharmony_ci#define	GET_LE_8BYTE(ptr)	(	(((sf_count_t) (ptr) [7]) << 56)	| (((sf_count_t) (ptr) [6]) << 48) |	\
852b815c7f3Sopenharmony_ci								(((sf_count_t) (ptr) [5]) << 40)	| (((sf_count_t) (ptr) [4]) << 32) |	\
853b815c7f3Sopenharmony_ci								(((sf_count_t) (ptr) [3]) << 24)	| (((sf_count_t) (ptr) [2]) << 16) |	\
854b815c7f3Sopenharmony_ci								(((sf_count_t) (ptr) [1]) << 8)		| ((ptr) [0]))
855b815c7f3Sopenharmony_ci
856b815c7f3Sopenharmony_ci#define	GET_BE_8BYTE(ptr)	(	(((sf_count_t) (ptr) [0]) << 56)	| (((sf_count_t) (ptr) [1]) << 48) |	\
857b815c7f3Sopenharmony_ci								(((sf_count_t) (ptr) [2]) << 40)	| (((sf_count_t) (ptr) [3]) << 32) |	\
858b815c7f3Sopenharmony_ci								(((sf_count_t) (ptr) [4]) << 24)	| (((sf_count_t) (ptr) [5]) << 16) |	\
859b815c7f3Sopenharmony_ci								(((sf_count_t) (ptr) [6]) << 8)		| ((ptr) [7]))
860b815c7f3Sopenharmony_ci
861b815c7f3Sopenharmony_ci
862b815c7f3Sopenharmony_ci
863b815c7f3Sopenharmony_cistatic int
864b815c7f3Sopenharmony_ciheader_read (SF_PRIVATE *psf, void *ptr, int bytes)
865b815c7f3Sopenharmony_ci{	int count = 0 ;
866b815c7f3Sopenharmony_ci
867b815c7f3Sopenharmony_ci	if (psf->header.indx + bytes >= psf->header.len && psf_bump_header_allocation (psf, bytes))
868b815c7f3Sopenharmony_ci		return count ;
869b815c7f3Sopenharmony_ci
870b815c7f3Sopenharmony_ci	if (psf->header.indx + bytes > psf->header.end)
871b815c7f3Sopenharmony_ci	{	count = psf_fread (psf->header.ptr + psf->header.end, 1, bytes - (psf->header.end - psf->header.indx), psf) ;
872b815c7f3Sopenharmony_ci		if (count != bytes - (int) (psf->header.end - psf->header.indx))
873b815c7f3Sopenharmony_ci		{	psf_log_printf (psf, "Error : psf_fread returned short count.\n") ;
874b815c7f3Sopenharmony_ci			return count ;
875b815c7f3Sopenharmony_ci			} ;
876b815c7f3Sopenharmony_ci		psf->header.end += count ;
877b815c7f3Sopenharmony_ci		} ;
878b815c7f3Sopenharmony_ci
879b815c7f3Sopenharmony_ci	memcpy (ptr, psf->header.ptr + psf->header.indx, bytes) ;
880b815c7f3Sopenharmony_ci	psf->header.indx += bytes ;
881b815c7f3Sopenharmony_ci
882b815c7f3Sopenharmony_ci	return bytes ;
883b815c7f3Sopenharmony_ci} /* header_read */
884b815c7f3Sopenharmony_ci
885b815c7f3Sopenharmony_cistatic void
886b815c7f3Sopenharmony_ciheader_seek (SF_PRIVATE *psf, sf_count_t position, int whence)
887b815c7f3Sopenharmony_ci{
888b815c7f3Sopenharmony_ci	switch (whence)
889b815c7f3Sopenharmony_ci	{	case SEEK_SET :
890b815c7f3Sopenharmony_ci			if (psf->header.indx + position >= psf->header.len)
891b815c7f3Sopenharmony_ci				psf_bump_header_allocation (psf, position) ;
892b815c7f3Sopenharmony_ci			if (position > psf->header.len)
893b815c7f3Sopenharmony_ci			{	/* Too much header to cache so just seek instead. */
894b815c7f3Sopenharmony_ci				psf->header.indx = psf->header.end = 0 ;
895b815c7f3Sopenharmony_ci				psf_fseek (psf, position, whence) ;
896b815c7f3Sopenharmony_ci				return ;
897b815c7f3Sopenharmony_ci				} ;
898b815c7f3Sopenharmony_ci			if (position > psf->header.end)
899b815c7f3Sopenharmony_ci				psf->header.end += psf_fread (psf->header.ptr + psf->header.end, 1, position - psf->header.end, psf) ;
900b815c7f3Sopenharmony_ci			psf->header.indx = position ;
901b815c7f3Sopenharmony_ci			break ;
902b815c7f3Sopenharmony_ci
903b815c7f3Sopenharmony_ci		case SEEK_CUR :
904b815c7f3Sopenharmony_ci			if (psf->header.indx + position >= psf->header.len)
905b815c7f3Sopenharmony_ci				psf_bump_header_allocation (psf, position) ;
906b815c7f3Sopenharmony_ci
907b815c7f3Sopenharmony_ci			if (psf->header.indx + position < 0)
908b815c7f3Sopenharmony_ci				break ;
909b815c7f3Sopenharmony_ci
910b815c7f3Sopenharmony_ci			if (psf->header.indx >= psf->header.len)
911b815c7f3Sopenharmony_ci			{	psf_fseek (psf, position, whence) ;
912b815c7f3Sopenharmony_ci				return ;
913b815c7f3Sopenharmony_ci				} ;
914b815c7f3Sopenharmony_ci
915b815c7f3Sopenharmony_ci			if (psf->header.indx + position <= psf->header.end)
916b815c7f3Sopenharmony_ci			{	psf->header.indx += position ;
917b815c7f3Sopenharmony_ci				break ;
918b815c7f3Sopenharmony_ci				} ;
919b815c7f3Sopenharmony_ci
920b815c7f3Sopenharmony_ci			if (psf->header.indx + position > psf->header.len)
921b815c7f3Sopenharmony_ci			{	/* Need to jump this without caching it. */
922b815c7f3Sopenharmony_ci				position -= (psf->header.end - psf->header.indx) ;
923b815c7f3Sopenharmony_ci				psf->header.indx = psf->header.end ;
924b815c7f3Sopenharmony_ci				if (psf->is_pipe)
925b815c7f3Sopenharmony_ci				{
926b815c7f3Sopenharmony_ci					/* seeking is not supported on pipe input, so we read instead */
927b815c7f3Sopenharmony_ci					size_t skip = position ;
928b815c7f3Sopenharmony_ci					while (skip)
929b815c7f3Sopenharmony_ci					{	char junk [16 * 1024] ;
930b815c7f3Sopenharmony_ci						size_t to_skip = SF_MIN (skip, sizeof (junk)) ;
931b815c7f3Sopenharmony_ci						psf_fread (junk, 1, to_skip, psf) ;
932b815c7f3Sopenharmony_ci						skip -= to_skip ;
933b815c7f3Sopenharmony_ci						}
934b815c7f3Sopenharmony_ci					}
935b815c7f3Sopenharmony_ci				else
936b815c7f3Sopenharmony_ci				{	psf_fseek (psf, position, SEEK_CUR) ;
937b815c7f3Sopenharmony_ci					}
938b815c7f3Sopenharmony_ci				break ;
939b815c7f3Sopenharmony_ci				} ;
940b815c7f3Sopenharmony_ci
941b815c7f3Sopenharmony_ci			psf->header.end += psf_fread (psf->header.ptr + psf->header.end, 1, position - (psf->header.end - psf->header.indx), psf) ;
942b815c7f3Sopenharmony_ci			psf->header.indx = psf->header.end ;
943b815c7f3Sopenharmony_ci			break ;
944b815c7f3Sopenharmony_ci
945b815c7f3Sopenharmony_ci		case SEEK_END :
946b815c7f3Sopenharmony_ci		default :
947b815c7f3Sopenharmony_ci			psf_log_printf (psf, "Bad whence param in header_seek().\n") ;
948b815c7f3Sopenharmony_ci			break ;
949b815c7f3Sopenharmony_ci		} ;
950b815c7f3Sopenharmony_ci
951b815c7f3Sopenharmony_ci	return ;
952b815c7f3Sopenharmony_ci} /* header_seek */
953b815c7f3Sopenharmony_ci
954b815c7f3Sopenharmony_cistatic int
955b815c7f3Sopenharmony_ciheader_gets (SF_PRIVATE *psf, char *ptr, int bufsize)
956b815c7f3Sopenharmony_ci{	int		k ;
957b815c7f3Sopenharmony_ci
958b815c7f3Sopenharmony_ci	if (psf->header.indx + bufsize >= psf->header.len && psf_bump_header_allocation (psf, bufsize))
959b815c7f3Sopenharmony_ci		return 0 ;
960b815c7f3Sopenharmony_ci
961b815c7f3Sopenharmony_ci	for (k = 0 ; k < bufsize - 1 ; k++)
962b815c7f3Sopenharmony_ci	{	if (psf->header.indx < psf->header.end)
963b815c7f3Sopenharmony_ci		{	ptr [k] = psf->header.ptr [psf->header.indx] ;
964b815c7f3Sopenharmony_ci			psf->header.indx ++ ;
965b815c7f3Sopenharmony_ci			}
966b815c7f3Sopenharmony_ci		else
967b815c7f3Sopenharmony_ci		{	psf->header.end += psf_fread (psf->header.ptr + psf->header.end, 1, 1, psf) ;
968b815c7f3Sopenharmony_ci			ptr [k] = psf->header.ptr [psf->header.indx] ;
969b815c7f3Sopenharmony_ci			psf->header.indx = psf->header.end ;
970b815c7f3Sopenharmony_ci			} ;
971b815c7f3Sopenharmony_ci
972b815c7f3Sopenharmony_ci		if (ptr [k] == '\n')
973b815c7f3Sopenharmony_ci			break ;
974b815c7f3Sopenharmony_ci		} ;
975b815c7f3Sopenharmony_ci
976b815c7f3Sopenharmony_ci	ptr [k] = 0 ;
977b815c7f3Sopenharmony_ci
978b815c7f3Sopenharmony_ci	return k ;
979b815c7f3Sopenharmony_ci} /* header_gets */
980b815c7f3Sopenharmony_ci
981b815c7f3Sopenharmony_ciint
982b815c7f3Sopenharmony_cipsf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
983b815c7f3Sopenharmony_ci{	va_list			argptr ;
984b815c7f3Sopenharmony_ci	sf_count_t		*countptr, countdata ;
985b815c7f3Sopenharmony_ci	unsigned char	*ucptr, sixteen_bytes [16] = { 0 } ;
986b815c7f3Sopenharmony_ci	unsigned int 	*intptr, intdata ;
987b815c7f3Sopenharmony_ci	unsigned short	*shortptr ;
988b815c7f3Sopenharmony_ci	char			*charptr ;
989b815c7f3Sopenharmony_ci	float			*floatptr ;
990b815c7f3Sopenharmony_ci	double			*doubleptr ;
991b815c7f3Sopenharmony_ci	char			c ;
992b815c7f3Sopenharmony_ci	int				byte_count = 0, count = 0 ;
993b815c7f3Sopenharmony_ci
994b815c7f3Sopenharmony_ci	if (! format)
995b815c7f3Sopenharmony_ci		return psf_ftell (psf) ;
996b815c7f3Sopenharmony_ci
997b815c7f3Sopenharmony_ci	va_start (argptr, format) ;
998b815c7f3Sopenharmony_ci
999b815c7f3Sopenharmony_ci	while ((c = *format++))
1000b815c7f3Sopenharmony_ci	{
1001b815c7f3Sopenharmony_ci		if (psf->header.indx + 16 >= psf->header.len && psf_bump_header_allocation (psf, 16))
1002b815c7f3Sopenharmony_ci			break ;
1003b815c7f3Sopenharmony_ci
1004b815c7f3Sopenharmony_ci		switch (c)
1005b815c7f3Sopenharmony_ci		{	case 'e' : /* All conversions are now from LE to host. */
1006b815c7f3Sopenharmony_ci					psf->rwf_endian = SF_ENDIAN_LITTLE ;
1007b815c7f3Sopenharmony_ci					break ;
1008b815c7f3Sopenharmony_ci
1009b815c7f3Sopenharmony_ci			case 'E' : /* All conversions are now from BE to host. */
1010b815c7f3Sopenharmony_ci					psf->rwf_endian = SF_ENDIAN_BIG ;
1011b815c7f3Sopenharmony_ci					break ;
1012b815c7f3Sopenharmony_ci
1013b815c7f3Sopenharmony_ci			case 'm' : /* 4 byte marker value eg 'RIFF' */
1014b815c7f3Sopenharmony_ci					intptr = va_arg (argptr, unsigned int*) ;
1015b815c7f3Sopenharmony_ci					*intptr = 0 ;
1016b815c7f3Sopenharmony_ci					ucptr = (unsigned char*) intptr ;
1017b815c7f3Sopenharmony_ci					byte_count += header_read (psf, ucptr, sizeof (int)) ;
1018b815c7f3Sopenharmony_ci					*intptr = GET_MARKER (ucptr) ;
1019b815c7f3Sopenharmony_ci					break ;
1020b815c7f3Sopenharmony_ci
1021b815c7f3Sopenharmony_ci			case 'h' :
1022b815c7f3Sopenharmony_ci					intptr = va_arg (argptr, unsigned int*) ;
1023b815c7f3Sopenharmony_ci					*intptr = 0 ;
1024b815c7f3Sopenharmony_ci					ucptr = (unsigned char*) intptr ;
1025b815c7f3Sopenharmony_ci					byte_count += header_read (psf, sixteen_bytes, sizeof (sixteen_bytes)) ;
1026b815c7f3Sopenharmony_ci					{	int k ;
1027b815c7f3Sopenharmony_ci						intdata = 0 ;
1028b815c7f3Sopenharmony_ci						for (k = 0 ; k < 16 ; k++)
1029b815c7f3Sopenharmony_ci							intdata ^= sixteen_bytes [k] << k ;
1030b815c7f3Sopenharmony_ci						}
1031b815c7f3Sopenharmony_ci					*intptr = intdata ;
1032b815c7f3Sopenharmony_ci					break ;
1033b815c7f3Sopenharmony_ci
1034b815c7f3Sopenharmony_ci			case '1' :
1035b815c7f3Sopenharmony_ci					charptr = va_arg (argptr, char*) ;
1036b815c7f3Sopenharmony_ci					*charptr = 0 ;
1037b815c7f3Sopenharmony_ci					byte_count += header_read (psf, charptr, sizeof (char)) ;
1038b815c7f3Sopenharmony_ci					break ;
1039b815c7f3Sopenharmony_ci
1040b815c7f3Sopenharmony_ci			case '2' : /* 2 byte value with the current endian-ness */
1041b815c7f3Sopenharmony_ci					shortptr = va_arg (argptr, unsigned short*) ;
1042b815c7f3Sopenharmony_ci					*shortptr = 0 ;
1043b815c7f3Sopenharmony_ci					ucptr = (unsigned char*) shortptr ;
1044b815c7f3Sopenharmony_ci					byte_count += header_read (psf, ucptr, sizeof (short)) ;
1045b815c7f3Sopenharmony_ci					if (psf->rwf_endian == SF_ENDIAN_BIG)
1046b815c7f3Sopenharmony_ci						*shortptr = GET_BE_SHORT (ucptr) ;
1047b815c7f3Sopenharmony_ci					else
1048b815c7f3Sopenharmony_ci						*shortptr = GET_LE_SHORT (ucptr) ;
1049b815c7f3Sopenharmony_ci					break ;
1050b815c7f3Sopenharmony_ci
1051b815c7f3Sopenharmony_ci			case '3' : /* 3 byte value with the current endian-ness */
1052b815c7f3Sopenharmony_ci					intptr = va_arg (argptr, unsigned int*) ;
1053b815c7f3Sopenharmony_ci					*intptr = 0 ;
1054b815c7f3Sopenharmony_ci					byte_count += header_read (psf, sixteen_bytes, 3) ;
1055b815c7f3Sopenharmony_ci					if (psf->rwf_endian == SF_ENDIAN_BIG)
1056b815c7f3Sopenharmony_ci						*intptr = GET_BE_3BYTE (sixteen_bytes) ;
1057b815c7f3Sopenharmony_ci					else
1058b815c7f3Sopenharmony_ci						*intptr = GET_LE_3BYTE (sixteen_bytes) ;
1059b815c7f3Sopenharmony_ci					break ;
1060b815c7f3Sopenharmony_ci
1061b815c7f3Sopenharmony_ci			case '4' : /* 4 byte value with the current endian-ness */
1062b815c7f3Sopenharmony_ci					intptr = va_arg (argptr, unsigned int*) ;
1063b815c7f3Sopenharmony_ci					*intptr = 0 ;
1064b815c7f3Sopenharmony_ci					ucptr = (unsigned char*) intptr ;
1065b815c7f3Sopenharmony_ci					byte_count += header_read (psf, ucptr, sizeof (int)) ;
1066b815c7f3Sopenharmony_ci					if (psf->rwf_endian == SF_ENDIAN_BIG)
1067b815c7f3Sopenharmony_ci						*intptr = psf_get_be32 (ucptr, 0) ;
1068b815c7f3Sopenharmony_ci					else
1069b815c7f3Sopenharmony_ci						*intptr = psf_get_le32 (ucptr, 0) ;
1070b815c7f3Sopenharmony_ci					break ;
1071b815c7f3Sopenharmony_ci
1072b815c7f3Sopenharmony_ci			case '8' : /* 8 byte value with the current endian-ness */
1073b815c7f3Sopenharmony_ci					countptr = va_arg (argptr, sf_count_t *) ;
1074b815c7f3Sopenharmony_ci					*countptr = 0 ;
1075b815c7f3Sopenharmony_ci					byte_count += header_read (psf, sixteen_bytes, 8) ;
1076b815c7f3Sopenharmony_ci					if (psf->rwf_endian == SF_ENDIAN_BIG)
1077b815c7f3Sopenharmony_ci						countdata = psf_get_be64 (sixteen_bytes, 0) ;
1078b815c7f3Sopenharmony_ci					else
1079b815c7f3Sopenharmony_ci						countdata = psf_get_le64 (sixteen_bytes, 0) ;
1080b815c7f3Sopenharmony_ci					*countptr = countdata ;
1081b815c7f3Sopenharmony_ci					break ;
1082b815c7f3Sopenharmony_ci
1083b815c7f3Sopenharmony_ci			case 'f' : /* Float conversion */
1084b815c7f3Sopenharmony_ci					floatptr = va_arg (argptr, float *) ;
1085b815c7f3Sopenharmony_ci					*floatptr = 0.0 ;
1086b815c7f3Sopenharmony_ci					byte_count += header_read (psf, floatptr, sizeof (float)) ;
1087b815c7f3Sopenharmony_ci					if (psf->rwf_endian == SF_ENDIAN_BIG)
1088b815c7f3Sopenharmony_ci						*floatptr = float32_be_read ((unsigned char*) floatptr) ;
1089b815c7f3Sopenharmony_ci					else
1090b815c7f3Sopenharmony_ci						*floatptr = float32_le_read ((unsigned char*) floatptr) ;
1091b815c7f3Sopenharmony_ci					break ;
1092b815c7f3Sopenharmony_ci
1093b815c7f3Sopenharmony_ci			case 'd' : /* double conversion */
1094b815c7f3Sopenharmony_ci					doubleptr = va_arg (argptr, double *) ;
1095b815c7f3Sopenharmony_ci					*doubleptr = 0.0 ;
1096b815c7f3Sopenharmony_ci					byte_count += header_read (psf, doubleptr, sizeof (double)) ;
1097b815c7f3Sopenharmony_ci					if (psf->rwf_endian == SF_ENDIAN_BIG)
1098b815c7f3Sopenharmony_ci						*doubleptr = double64_be_read ((unsigned char*) doubleptr) ;
1099b815c7f3Sopenharmony_ci					else
1100b815c7f3Sopenharmony_ci						*doubleptr = double64_le_read ((unsigned char*) doubleptr) ;
1101b815c7f3Sopenharmony_ci					break ;
1102b815c7f3Sopenharmony_ci
1103b815c7f3Sopenharmony_ci			case 's' :
1104b815c7f3Sopenharmony_ci					psf_log_printf (psf, "Format conversion 's' not implemented yet.\n") ;
1105b815c7f3Sopenharmony_ci					/*
1106b815c7f3Sopenharmony_ci					strptr = va_arg (argptr, char *) ;
1107b815c7f3Sopenharmony_ci					size   = strlen (strptr) + 1 ;
1108b815c7f3Sopenharmony_ci					size  += (size & 1) ;
1109b815c7f3Sopenharmony_ci					longdata = H2LE_32 (size) ;
1110b815c7f3Sopenharmony_ci					get_int (psf, longdata) ;
1111b815c7f3Sopenharmony_ci					memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size) ;
1112b815c7f3Sopenharmony_ci					psf->header.indx += size ;
1113b815c7f3Sopenharmony_ci					*/
1114b815c7f3Sopenharmony_ci					break ;
1115b815c7f3Sopenharmony_ci
1116b815c7f3Sopenharmony_ci			case 'b' : /* Raw bytes */
1117b815c7f3Sopenharmony_ci					charptr = va_arg (argptr, char*) ;
1118b815c7f3Sopenharmony_ci					count = va_arg (argptr, size_t) ;
1119b815c7f3Sopenharmony_ci					memset (charptr, 0, count) ;
1120b815c7f3Sopenharmony_ci					byte_count += header_read (psf, charptr, count) ;
1121b815c7f3Sopenharmony_ci					break ;
1122b815c7f3Sopenharmony_ci
1123b815c7f3Sopenharmony_ci			case 'G' :
1124b815c7f3Sopenharmony_ci					charptr = va_arg (argptr, char*) ;
1125b815c7f3Sopenharmony_ci					count = va_arg (argptr, size_t) ;
1126b815c7f3Sopenharmony_ci					memset (charptr, 0, count) ;
1127b815c7f3Sopenharmony_ci
1128b815c7f3Sopenharmony_ci					if (psf->header.indx + count >= psf->header.len && psf_bump_header_allocation (psf, count))
1129b815c7f3Sopenharmony_ci						break ;
1130b815c7f3Sopenharmony_ci
1131b815c7f3Sopenharmony_ci					byte_count += header_gets (psf, charptr, count) ;
1132b815c7f3Sopenharmony_ci					break ;
1133b815c7f3Sopenharmony_ci
1134b815c7f3Sopenharmony_ci			case 'z' :
1135b815c7f3Sopenharmony_ci					psf_log_printf (psf, "Format conversion 'z' not implemented yet.\n") ;
1136b815c7f3Sopenharmony_ci					/*
1137b815c7f3Sopenharmony_ci					size    = va_arg (argptr, size_t) ;
1138b815c7f3Sopenharmony_ci					while (size)
1139b815c7f3Sopenharmony_ci					{	psf->header.ptr [psf->header.indx] = 0 ;
1140b815c7f3Sopenharmony_ci						psf->header.indx ++ ;
1141b815c7f3Sopenharmony_ci						size -- ;
1142b815c7f3Sopenharmony_ci						} ;
1143b815c7f3Sopenharmony_ci					*/
1144b815c7f3Sopenharmony_ci					break ;
1145b815c7f3Sopenharmony_ci
1146b815c7f3Sopenharmony_ci			case 'p' :	/* Seek to position from start. */
1147b815c7f3Sopenharmony_ci					count = va_arg (argptr, size_t) ;
1148b815c7f3Sopenharmony_ci					header_seek (psf, count, SEEK_SET) ;
1149b815c7f3Sopenharmony_ci					byte_count = count ;
1150b815c7f3Sopenharmony_ci					break ;
1151b815c7f3Sopenharmony_ci
1152b815c7f3Sopenharmony_ci			case 'j' :	/* Seek to position from current position. */
1153b815c7f3Sopenharmony_ci					count = va_arg (argptr, size_t) ;
1154b815c7f3Sopenharmony_ci					header_seek (psf, count, SEEK_CUR) ;
1155b815c7f3Sopenharmony_ci					byte_count += count ;
1156b815c7f3Sopenharmony_ci					break ;
1157b815c7f3Sopenharmony_ci
1158b815c7f3Sopenharmony_ci			case '!' : /* Clear buffer, forcing re-read. */
1159b815c7f3Sopenharmony_ci					psf->header.end = psf->header.indx = 0 ;
1160b815c7f3Sopenharmony_ci					break ;
1161b815c7f3Sopenharmony_ci
1162b815c7f3Sopenharmony_ci			default :
1163b815c7f3Sopenharmony_ci				psf_log_printf (psf, "*** Invalid format specifier `%c'\n", c) ;
1164b815c7f3Sopenharmony_ci				psf->error = SFE_INTERNAL ;
1165b815c7f3Sopenharmony_ci				break ;
1166b815c7f3Sopenharmony_ci			} ;
1167b815c7f3Sopenharmony_ci		} ;
1168b815c7f3Sopenharmony_ci
1169b815c7f3Sopenharmony_ci	va_end (argptr) ;
1170b815c7f3Sopenharmony_ci
1171b815c7f3Sopenharmony_ci	return byte_count ;
1172b815c7f3Sopenharmony_ci} /* psf_binheader_readf */
1173b815c7f3Sopenharmony_ci
1174b815c7f3Sopenharmony_ci/*-----------------------------------------------------------------------------------------------
1175b815c7f3Sopenharmony_ci*/
1176b815c7f3Sopenharmony_ci
1177b815c7f3Sopenharmony_cisf_count_t
1178b815c7f3Sopenharmony_cipsf_default_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t samples_from_start)
1179b815c7f3Sopenharmony_ci{	sf_count_t position, retval ;
1180b815c7f3Sopenharmony_ci
1181b815c7f3Sopenharmony_ci	if (! (psf->blockwidth && psf->dataoffset >= 0))
1182b815c7f3Sopenharmony_ci	{	psf->error = SFE_BAD_SEEK ;
1183b815c7f3Sopenharmony_ci		return	PSF_SEEK_ERROR ;
1184b815c7f3Sopenharmony_ci		} ;
1185b815c7f3Sopenharmony_ci
1186b815c7f3Sopenharmony_ci	if (! psf->sf.seekable)
1187b815c7f3Sopenharmony_ci	{	psf->error = SFE_NOT_SEEKABLE ;
1188b815c7f3Sopenharmony_ci		return	PSF_SEEK_ERROR ;
1189b815c7f3Sopenharmony_ci		} ;
1190b815c7f3Sopenharmony_ci
1191b815c7f3Sopenharmony_ci	position = psf->dataoffset + psf->blockwidth * samples_from_start ;
1192b815c7f3Sopenharmony_ci
1193b815c7f3Sopenharmony_ci	if ((retval = psf_fseek (psf, position, SEEK_SET)) != position)
1194b815c7f3Sopenharmony_ci	{	psf->error = SFE_SEEK_FAILED ;
1195b815c7f3Sopenharmony_ci		return PSF_SEEK_ERROR ;
1196b815c7f3Sopenharmony_ci		} ;
1197b815c7f3Sopenharmony_ci
1198b815c7f3Sopenharmony_ci	return samples_from_start ;
1199b815c7f3Sopenharmony_ci} /* psf_default_seek */
1200b815c7f3Sopenharmony_ci
1201b815c7f3Sopenharmony_ci/*-----------------------------------------------------------------------------------------------
1202b815c7f3Sopenharmony_ci*/
1203b815c7f3Sopenharmony_ci
1204b815c7f3Sopenharmony_civoid
1205b815c7f3Sopenharmony_cipsf_hexdump (const void *ptr, int len)
1206b815c7f3Sopenharmony_ci{	const char *data ;
1207b815c7f3Sopenharmony_ci	char	ascii [17] ;
1208b815c7f3Sopenharmony_ci	int		k, m ;
1209b815c7f3Sopenharmony_ci
1210b815c7f3Sopenharmony_ci	if ((data = ptr) == NULL)
1211b815c7f3Sopenharmony_ci		return ;
1212b815c7f3Sopenharmony_ci	if (len <= 0)
1213b815c7f3Sopenharmony_ci		return ;
1214b815c7f3Sopenharmony_ci
1215b815c7f3Sopenharmony_ci	puts ("") ;
1216b815c7f3Sopenharmony_ci	for (k = 0 ; k < len ; k += 16)
1217b815c7f3Sopenharmony_ci	{	memset (ascii, ' ', sizeof (ascii)) ;
1218b815c7f3Sopenharmony_ci
1219b815c7f3Sopenharmony_ci		printf ("%08X: ", k) ;
1220b815c7f3Sopenharmony_ci		for (m = 0 ; m < 16 && k + m < len ; m++)
1221b815c7f3Sopenharmony_ci		{	printf (m == 8 ? " %02X " : "%02X ", data [k + m] & 0xFF) ;
1222b815c7f3Sopenharmony_ci			ascii [m] = psf_isprint (data [k + m]) ? data [k + m] : '.' ;
1223b815c7f3Sopenharmony_ci			} ;
1224b815c7f3Sopenharmony_ci
1225b815c7f3Sopenharmony_ci		if (m <= 8) printf (" ") ;
1226b815c7f3Sopenharmony_ci		for ( ; m < 16 ; m++) printf ("   ") ;
1227b815c7f3Sopenharmony_ci
1228b815c7f3Sopenharmony_ci		ascii [16] = 0 ;
1229b815c7f3Sopenharmony_ci		printf (" %s\n", ascii) ;
1230b815c7f3Sopenharmony_ci		} ;
1231b815c7f3Sopenharmony_ci
1232b815c7f3Sopenharmony_ci	puts ("") ;
1233b815c7f3Sopenharmony_ci} /* psf_hexdump */
1234b815c7f3Sopenharmony_ci
1235b815c7f3Sopenharmony_civoid
1236b815c7f3Sopenharmony_cipsf_log_SF_INFO (SF_PRIVATE *psf)
1237b815c7f3Sopenharmony_ci{	psf_log_printf (psf, "---------------------------------\n") ;
1238b815c7f3Sopenharmony_ci
1239b815c7f3Sopenharmony_ci	psf_log_printf (psf, " Sample rate :   %d\n", psf->sf.samplerate) ;
1240b815c7f3Sopenharmony_ci	if (psf->sf.frames == SF_COUNT_MAX)
1241b815c7f3Sopenharmony_ci		psf_log_printf (psf, " Frames      :   unknown\n") ;
1242b815c7f3Sopenharmony_ci	else
1243b815c7f3Sopenharmony_ci		psf_log_printf (psf, " Frames      :   %D\n", psf->sf.frames) ;
1244b815c7f3Sopenharmony_ci	psf_log_printf (psf, " Channels    :   %d\n", psf->sf.channels) ;
1245b815c7f3Sopenharmony_ci
1246b815c7f3Sopenharmony_ci	psf_log_printf (psf, " Format      :   0x%X\n", psf->sf.format) ;
1247b815c7f3Sopenharmony_ci	psf_log_printf (psf, " Sections    :   %d\n", psf->sf.sections) ;
1248b815c7f3Sopenharmony_ci	psf_log_printf (psf, " Seekable    :   %s\n", psf->sf.seekable ? "TRUE" : "FALSE") ;
1249b815c7f3Sopenharmony_ci
1250b815c7f3Sopenharmony_ci	psf_log_printf (psf, "---------------------------------\n") ;
1251b815c7f3Sopenharmony_ci} /* psf_dump_SFINFO */
1252b815c7f3Sopenharmony_ci
1253b815c7f3Sopenharmony_ci/*========================================================================================
1254b815c7f3Sopenharmony_ci*/
1255b815c7f3Sopenharmony_ci
1256b815c7f3Sopenharmony_ciint
1257b815c7f3Sopenharmony_cipsf_isprint (int ch)
1258b815c7f3Sopenharmony_ci{	return (ch >= ' ' && ch <= '~') ;
1259b815c7f3Sopenharmony_ci} /* psf_isprint */
1260b815c7f3Sopenharmony_ci
1261b815c7f3Sopenharmony_civoid
1262b815c7f3Sopenharmony_cipsf_strlcat (char *dest, size_t n, const char *src)
1263b815c7f3Sopenharmony_ci{	strncat (dest, src, n - strlen (dest) - 1) ;
1264b815c7f3Sopenharmony_ci	dest [n - 1] = 0 ;
1265b815c7f3Sopenharmony_ci} /* psf_strlcat */
1266b815c7f3Sopenharmony_ci
1267b815c7f3Sopenharmony_civoid
1268b815c7f3Sopenharmony_cipsf_strlcpy (char *dest, size_t n, const char *src)
1269b815c7f3Sopenharmony_ci{	strncpy (dest, src, n - 1) ;
1270b815c7f3Sopenharmony_ci	dest [n - 1] = 0 ;
1271b815c7f3Sopenharmony_ci} /* psf_strlcpy */
1272b815c7f3Sopenharmony_ci
1273b815c7f3Sopenharmony_ci/*========================================================================================
1274b815c7f3Sopenharmony_ci*/
1275b815c7f3Sopenharmony_ci
1276b815c7f3Sopenharmony_civoid *
1277b815c7f3Sopenharmony_cipsf_memdup (const void *src, size_t n)
1278b815c7f3Sopenharmony_ci{	if (src == NULL)
1279b815c7f3Sopenharmony_ci		return NULL ;
1280b815c7f3Sopenharmony_ci
1281b815c7f3Sopenharmony_ci	void * mem = calloc (1, n & 3 ? n + 4 - (n & 3) : n) ;
1282b815c7f3Sopenharmony_ci	if (mem != NULL)
1283b815c7f3Sopenharmony_ci		memcpy (mem, src, n) ;
1284b815c7f3Sopenharmony_ci	return mem ;
1285b815c7f3Sopenharmony_ci} /* psf_memdup */
1286b815c7f3Sopenharmony_ci
1287b815c7f3Sopenharmony_civoid*
1288b815c7f3Sopenharmony_cipsf_memset (void *s, int c, sf_count_t len)
1289b815c7f3Sopenharmony_ci{	char	*ptr ;
1290b815c7f3Sopenharmony_ci	int 	setcount ;
1291b815c7f3Sopenharmony_ci
1292b815c7f3Sopenharmony_ci	ptr = (char *) s ;
1293b815c7f3Sopenharmony_ci
1294b815c7f3Sopenharmony_ci	while (len > 0)
1295b815c7f3Sopenharmony_ci	{	setcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
1296b815c7f3Sopenharmony_ci
1297b815c7f3Sopenharmony_ci		memset (ptr, c, setcount) ;
1298b815c7f3Sopenharmony_ci
1299b815c7f3Sopenharmony_ci		ptr += setcount ;
1300b815c7f3Sopenharmony_ci		len -= setcount ;
1301b815c7f3Sopenharmony_ci		} ;
1302b815c7f3Sopenharmony_ci
1303b815c7f3Sopenharmony_ci	return s ;
1304b815c7f3Sopenharmony_ci} /* psf_memset */
1305b815c7f3Sopenharmony_ci
1306b815c7f3Sopenharmony_ci
1307b815c7f3Sopenharmony_ci/*
1308b815c7f3Sopenharmony_ci** Clang refuses to do sizeof (SF_CUES_VAR (cue_count)) so we have to manually
1309b815c7f3Sopenharmony_ci** bodgy something up instead.
1310b815c7f3Sopenharmony_ci*/
1311b815c7f3Sopenharmony_ci
1312b815c7f3Sopenharmony_ci#ifdef _MSC_VER
1313b815c7f3Sopenharmony_citypedef SF_CUES_VAR (0) SF_CUES_0 ;
1314b815c7f3Sopenharmony_ci#else
1315b815c7f3Sopenharmony_citypedef SF_CUES_VAR () SF_CUES_0 ;
1316b815c7f3Sopenharmony_ci#endif
1317b815c7f3Sopenharmony_ci
1318b815c7f3Sopenharmony_ci/* calculate size of SF_CUES struct given number of cues */
1319b815c7f3Sopenharmony_ci#define SF_CUES_VAR_SIZE(count)	(sizeof (SF_CUES_0) + count * sizeof (SF_CUE_POINT))
1320b815c7f3Sopenharmony_ci
1321b815c7f3Sopenharmony_ci/* calculate number of cues in SF_CUES struct given data size */
1322b815c7f3Sopenharmony_ci#define SF_CUES_COUNT(datasize) (((datasize) - sizeof (uint32_t)) / sizeof (SF_CUE_POINT))
1323b815c7f3Sopenharmony_ci
1324b815c7f3Sopenharmony_ciSF_CUES *
1325b815c7f3Sopenharmony_cipsf_cues_alloc (uint32_t cue_count)
1326b815c7f3Sopenharmony_ci{	SF_CUES *pcues = calloc (1, SF_CUES_VAR_SIZE (cue_count)) ;
1327b815c7f3Sopenharmony_ci	if (pcues)
1328b815c7f3Sopenharmony_ci	{	pcues->cue_count = cue_count ;
1329b815c7f3Sopenharmony_ci		} ;
1330b815c7f3Sopenharmony_ci	return pcues ;
1331b815c7f3Sopenharmony_ci} /* psf_cues_alloc */
1332b815c7f3Sopenharmony_ci
1333b815c7f3Sopenharmony_ciSF_CUES *
1334b815c7f3Sopenharmony_cipsf_cues_dup (const void * ptr, size_t datasize)
1335b815c7f3Sopenharmony_ci{	const SF_CUES *pcues = ptr ;
1336b815c7f3Sopenharmony_ci	SF_CUES *pnew = NULL ;
1337b815c7f3Sopenharmony_ci
1338b815c7f3Sopenharmony_ci	if (pcues->cue_count <= SF_CUES_COUNT (datasize))
1339b815c7f3Sopenharmony_ci	{	/* check that passed-in datasize is consistent with cue_count in passed-in SF_CUES struct */
1340b815c7f3Sopenharmony_ci		pnew = psf_cues_alloc (pcues->cue_count) ;
1341b815c7f3Sopenharmony_ci		memcpy (pnew, pcues, SF_CUES_VAR_SIZE (pcues->cue_count)) ;
1342b815c7f3Sopenharmony_ci	}
1343b815c7f3Sopenharmony_ci
1344b815c7f3Sopenharmony_ci	return pnew ;
1345b815c7f3Sopenharmony_ci} /* psf_cues_dup */
1346b815c7f3Sopenharmony_ci
1347b815c7f3Sopenharmony_civoid
1348b815c7f3Sopenharmony_cipsf_get_cues (SF_PRIVATE * psf, void * data, size_t datasize)
1349b815c7f3Sopenharmony_ci{
1350b815c7f3Sopenharmony_ci	if (psf->cues)
1351b815c7f3Sopenharmony_ci	{	uint32_t cue_count = SF_CUES_COUNT (datasize) ;
1352b815c7f3Sopenharmony_ci
1353b815c7f3Sopenharmony_ci		cue_count = SF_MIN (cue_count, psf->cues->cue_count) ;
1354b815c7f3Sopenharmony_ci		memcpy (data, psf->cues, SF_CUES_VAR_SIZE (cue_count)) ;
1355b815c7f3Sopenharmony_ci		((SF_CUES*) data)->cue_count = cue_count ;
1356b815c7f3Sopenharmony_ci		} ;
1357b815c7f3Sopenharmony_ci
1358b815c7f3Sopenharmony_ci	return ;
1359b815c7f3Sopenharmony_ci} /* psf_get_cues */
1360b815c7f3Sopenharmony_ci
1361b815c7f3Sopenharmony_ci
1362b815c7f3Sopenharmony_ciSF_INSTRUMENT *
1363b815c7f3Sopenharmony_cipsf_instrument_alloc (void)
1364b815c7f3Sopenharmony_ci{	SF_INSTRUMENT *instr ;
1365b815c7f3Sopenharmony_ci
1366b815c7f3Sopenharmony_ci	instr = calloc (1, sizeof (SF_INSTRUMENT)) ;
1367b815c7f3Sopenharmony_ci
1368b815c7f3Sopenharmony_ci	if (instr == NULL)
1369b815c7f3Sopenharmony_ci		return NULL ;
1370b815c7f3Sopenharmony_ci
1371b815c7f3Sopenharmony_ci	/* Set non-zero default values. */
1372b815c7f3Sopenharmony_ci	instr->basenote = -1 ;
1373b815c7f3Sopenharmony_ci	instr->velocity_lo = -1 ;
1374b815c7f3Sopenharmony_ci	instr->velocity_hi = -1 ;
1375b815c7f3Sopenharmony_ci	instr->key_lo = -1 ;
1376b815c7f3Sopenharmony_ci	instr->key_hi = -1 ;
1377b815c7f3Sopenharmony_ci
1378b815c7f3Sopenharmony_ci	return instr ;
1379b815c7f3Sopenharmony_ci} /* psf_instrument_alloc */
1380b815c7f3Sopenharmony_ci
1381b815c7f3Sopenharmony_civoid
1382b815c7f3Sopenharmony_cipsf_sanitize_string (char * cptr, int len)
1383b815c7f3Sopenharmony_ci{
1384b815c7f3Sopenharmony_ci	do
1385b815c7f3Sopenharmony_ci	{
1386b815c7f3Sopenharmony_ci		len -- ;
1387b815c7f3Sopenharmony_ci		cptr [len] = psf_isprint (cptr [len]) ? cptr [len] : '.' ;
1388b815c7f3Sopenharmony_ci	}
1389b815c7f3Sopenharmony_ci	while (len > 0) ;
1390b815c7f3Sopenharmony_ci} /* psf_sanitize_string */
1391b815c7f3Sopenharmony_ci
1392b815c7f3Sopenharmony_civoid
1393b815c7f3Sopenharmony_cipsf_get_date_str (char *str, int maxlen)
1394b815c7f3Sopenharmony_ci{	time_t		current ;
1395b815c7f3Sopenharmony_ci	struct tm	timedata, *tmptr ;
1396b815c7f3Sopenharmony_ci
1397b815c7f3Sopenharmony_ci	time (&current) ;
1398b815c7f3Sopenharmony_ci
1399b815c7f3Sopenharmony_ci#if defined (HAVE_GMTIME_R)
1400b815c7f3Sopenharmony_ci	/* If the re-entrant version is available, use it. */
1401b815c7f3Sopenharmony_ci	tmptr = gmtime_r (&current, &timedata) ;
1402b815c7f3Sopenharmony_ci#elif defined (HAVE_GMTIME)
1403b815c7f3Sopenharmony_ci	/* Otherwise use the standard one and copy the data to local storage. */
1404b815c7f3Sopenharmony_ci	tmptr = gmtime (&current) ;
1405b815c7f3Sopenharmony_ci	memcpy (&timedata, tmptr, sizeof (timedata)) ;
1406b815c7f3Sopenharmony_ci#else
1407b815c7f3Sopenharmony_ci	tmptr = NULL ;
1408b815c7f3Sopenharmony_ci#endif
1409b815c7f3Sopenharmony_ci
1410b815c7f3Sopenharmony_ci	if (tmptr)
1411b815c7f3Sopenharmony_ci		snprintf (str, maxlen, "%4d-%02d-%02d %02d:%02d:%02d UTC",
1412b815c7f3Sopenharmony_ci			1900 + timedata.tm_year, timedata.tm_mon, timedata.tm_mday,
1413b815c7f3Sopenharmony_ci			timedata.tm_hour, timedata.tm_min, timedata.tm_sec) ;
1414b815c7f3Sopenharmony_ci	else
1415b815c7f3Sopenharmony_ci		snprintf (str, maxlen, "Unknown date") ;
1416b815c7f3Sopenharmony_ci
1417b815c7f3Sopenharmony_ci	return ;
1418b815c7f3Sopenharmony_ci} /* psf_get_date_str */
1419b815c7f3Sopenharmony_ci
1420b815c7f3Sopenharmony_ciint
1421b815c7f3Sopenharmony_cisubformat_to_bytewidth (int format)
1422b815c7f3Sopenharmony_ci{
1423b815c7f3Sopenharmony_ci	switch (format)
1424b815c7f3Sopenharmony_ci	{	case SF_FORMAT_PCM_U8 :
1425b815c7f3Sopenharmony_ci		case SF_FORMAT_PCM_S8 :
1426b815c7f3Sopenharmony_ci				return 1 ;
1427b815c7f3Sopenharmony_ci		case SF_FORMAT_PCM_16 :
1428b815c7f3Sopenharmony_ci				return 2 ;
1429b815c7f3Sopenharmony_ci		case SF_FORMAT_PCM_24 :
1430b815c7f3Sopenharmony_ci				return 3 ;
1431b815c7f3Sopenharmony_ci		case SF_FORMAT_PCM_32 :
1432b815c7f3Sopenharmony_ci		case SF_FORMAT_FLOAT :
1433b815c7f3Sopenharmony_ci				return 4 ;
1434b815c7f3Sopenharmony_ci		case SF_FORMAT_DOUBLE :
1435b815c7f3Sopenharmony_ci				return 8 ;
1436b815c7f3Sopenharmony_ci		} ;
1437b815c7f3Sopenharmony_ci
1438b815c7f3Sopenharmony_ci	return 0 ;
1439b815c7f3Sopenharmony_ci} /* subformat_to_bytewidth */
1440b815c7f3Sopenharmony_ci
1441b815c7f3Sopenharmony_ciint
1442b815c7f3Sopenharmony_cis_bitwidth_to_subformat (int bits)
1443b815c7f3Sopenharmony_ci{	static int array [] =
1444b815c7f3Sopenharmony_ci	{	SF_FORMAT_PCM_S8, SF_FORMAT_PCM_16, SF_FORMAT_PCM_24, SF_FORMAT_PCM_32
1445b815c7f3Sopenharmony_ci		} ;
1446b815c7f3Sopenharmony_ci
1447b815c7f3Sopenharmony_ci	if (bits < 8 || bits > 32)
1448b815c7f3Sopenharmony_ci		return 0 ;
1449b815c7f3Sopenharmony_ci
1450b815c7f3Sopenharmony_ci	return array [((bits + 7) / 8) - 1] ;
1451b815c7f3Sopenharmony_ci} /* bitwidth_to_subformat */
1452b815c7f3Sopenharmony_ci
1453b815c7f3Sopenharmony_ciint
1454b815c7f3Sopenharmony_ciu_bitwidth_to_subformat (int bits)
1455b815c7f3Sopenharmony_ci{	static int array [] =
1456b815c7f3Sopenharmony_ci	{	SF_FORMAT_PCM_U8, SF_FORMAT_PCM_16, SF_FORMAT_PCM_24, SF_FORMAT_PCM_32
1457b815c7f3Sopenharmony_ci		} ;
1458b815c7f3Sopenharmony_ci
1459b815c7f3Sopenharmony_ci	if (bits < 8 || bits > 32)
1460b815c7f3Sopenharmony_ci		return 0 ;
1461b815c7f3Sopenharmony_ci
1462b815c7f3Sopenharmony_ci	return array [((bits + 7) / 8) - 1] ;
1463b815c7f3Sopenharmony_ci} /* bitwidth_to_subformat */
1464b815c7f3Sopenharmony_ci
1465b815c7f3Sopenharmony_ci/*
1466b815c7f3Sopenharmony_ci**	psf_rand_int32 : Not crypto quality, but more than adequate for things
1467b815c7f3Sopenharmony_ci**	like stream serial numbers in Ogg files or the unique_id field of the
1468b815c7f3Sopenharmony_ci**	SF_PRIVATE struct.
1469b815c7f3Sopenharmony_ci*/
1470b815c7f3Sopenharmony_ci
1471b815c7f3Sopenharmony_ciint32_t
1472b815c7f3Sopenharmony_cipsf_rand_int32 (void)
1473b815c7f3Sopenharmony_ci{	static uint64_t value = 0 ;
1474b815c7f3Sopenharmony_ci	int k, count ;
1475b815c7f3Sopenharmony_ci
1476b815c7f3Sopenharmony_ci	if (value == 0)
1477b815c7f3Sopenharmony_ci	{
1478b815c7f3Sopenharmony_ci#if HAVE_GETTIMEOFDAY
1479b815c7f3Sopenharmony_ci		struct timeval tv ;
1480b815c7f3Sopenharmony_ci		gettimeofday (&tv, NULL) ;
1481b815c7f3Sopenharmony_ci		value = tv.tv_sec + tv.tv_usec ;
1482b815c7f3Sopenharmony_ci#else
1483b815c7f3Sopenharmony_ci		value = time (NULL) ;
1484b815c7f3Sopenharmony_ci#endif
1485b815c7f3Sopenharmony_ci		} ;
1486b815c7f3Sopenharmony_ci
1487b815c7f3Sopenharmony_ci	count = 4 + (value & 7) ;
1488b815c7f3Sopenharmony_ci	for (k = 0 ; k < count ; k++)
1489b815c7f3Sopenharmony_ci		value = (11117 * value + 211231) & 0x7fffffff ;
1490b815c7f3Sopenharmony_ci
1491b815c7f3Sopenharmony_ci	return (int32_t) value ;
1492b815c7f3Sopenharmony_ci} /* psf_rand_int32 */
1493b815c7f3Sopenharmony_ci
1494b815c7f3Sopenharmony_civoid
1495b815c7f3Sopenharmony_ciappend_snprintf (char * dest, size_t maxlen, const char * fmt, ...)
1496b815c7f3Sopenharmony_ci{	size_t len = strlen (dest) ;
1497b815c7f3Sopenharmony_ci
1498b815c7f3Sopenharmony_ci	if (len < maxlen)
1499b815c7f3Sopenharmony_ci	{	va_list ap ;
1500b815c7f3Sopenharmony_ci
1501b815c7f3Sopenharmony_ci		va_start (ap, fmt) ;
1502b815c7f3Sopenharmony_ci		vsnprintf (dest + len, maxlen - len, fmt, ap) ;
1503b815c7f3Sopenharmony_ci		va_end (ap) ;
1504b815c7f3Sopenharmony_ci		} ;
1505b815c7f3Sopenharmony_ci
1506b815c7f3Sopenharmony_ci	return ;
1507b815c7f3Sopenharmony_ci} /* append_snprintf */
1508b815c7f3Sopenharmony_ci
1509b815c7f3Sopenharmony_ci
1510b815c7f3Sopenharmony_civoid
1511b815c7f3Sopenharmony_cipsf_strlcpy_crlf (char *dest, const char *src, size_t destmax, size_t srcmax)
1512b815c7f3Sopenharmony_ci{	/* Must be minus 2 so it can still expand a single trailing '\n' or '\r'. */
1513b815c7f3Sopenharmony_ci	char * destend = dest + destmax - 2 ;
1514b815c7f3Sopenharmony_ci	const char * srcend = src + srcmax ;
1515b815c7f3Sopenharmony_ci
1516b815c7f3Sopenharmony_ci	while (dest < destend && src < srcend)
1517b815c7f3Sopenharmony_ci	{	if ((src [0] == '\r' && src [1] == '\n') || (src [0] == '\n' && src [1] == '\r'))
1518b815c7f3Sopenharmony_ci		{	*dest++ = '\r' ;
1519b815c7f3Sopenharmony_ci			*dest++ = '\n' ;
1520b815c7f3Sopenharmony_ci			src += 2 ;
1521b815c7f3Sopenharmony_ci			continue ;
1522b815c7f3Sopenharmony_ci			} ;
1523b815c7f3Sopenharmony_ci
1524b815c7f3Sopenharmony_ci		if (src [0] == '\r')
1525b815c7f3Sopenharmony_ci		{	*dest++ = '\r' ;
1526b815c7f3Sopenharmony_ci			*dest++ = '\n' ;
1527b815c7f3Sopenharmony_ci			src += 1 ;
1528b815c7f3Sopenharmony_ci			continue ;
1529b815c7f3Sopenharmony_ci			} ;
1530b815c7f3Sopenharmony_ci
1531b815c7f3Sopenharmony_ci		if (src [0] == '\n')
1532b815c7f3Sopenharmony_ci		{	*dest++ = '\r' ;
1533b815c7f3Sopenharmony_ci			*dest++ = '\n' ;
1534b815c7f3Sopenharmony_ci			src += 1 ;
1535b815c7f3Sopenharmony_ci			continue ;
1536b815c7f3Sopenharmony_ci			} ;
1537b815c7f3Sopenharmony_ci
1538b815c7f3Sopenharmony_ci		*dest++ = *src++ ;
1539b815c7f3Sopenharmony_ci		} ;
1540b815c7f3Sopenharmony_ci
1541b815c7f3Sopenharmony_ci	/* Make sure dest is terminated. */
1542b815c7f3Sopenharmony_ci	*dest = 0 ;
1543b815c7f3Sopenharmony_ci} /* psf_strlcpy_crlf */
1544b815c7f3Sopenharmony_ci
1545b815c7f3Sopenharmony_cisf_count_t
1546b815c7f3Sopenharmony_cipsf_decode_frame_count (SF_PRIVATE *psf)
1547b815c7f3Sopenharmony_ci{	sf_count_t count, readlen, total = 0 ;
1548b815c7f3Sopenharmony_ci	BUF_UNION	ubuf ;
1549b815c7f3Sopenharmony_ci
1550b815c7f3Sopenharmony_ci	/* If we're reading from a pipe or the file is too long, just return SF_COUNT_MAX. */
1551b815c7f3Sopenharmony_ci	if (psf_is_pipe (psf) || psf->datalength > 0x1000000)
1552b815c7f3Sopenharmony_ci		return SF_COUNT_MAX ;
1553b815c7f3Sopenharmony_ci
1554b815c7f3Sopenharmony_ci	psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
1555b815c7f3Sopenharmony_ci
1556b815c7f3Sopenharmony_ci	readlen = ARRAY_LEN (ubuf.ibuf) / psf->sf.channels ;
1557b815c7f3Sopenharmony_ci	readlen *= psf->sf.channels ;
1558b815c7f3Sopenharmony_ci
1559b815c7f3Sopenharmony_ci	while ((count = psf->read_int (psf, ubuf.ibuf, readlen)) > 0)
1560b815c7f3Sopenharmony_ci		total += count ;
1561b815c7f3Sopenharmony_ci
1562b815c7f3Sopenharmony_ci	psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
1563b815c7f3Sopenharmony_ci
1564b815c7f3Sopenharmony_ci	return total / psf->sf.channels ;
1565b815c7f3Sopenharmony_ci} /* psf_decode_frame_count */
1566b815c7f3Sopenharmony_ci
1567b815c7f3Sopenharmony_ci/*==============================================================================
1568b815c7f3Sopenharmony_ci*/
1569b815c7f3Sopenharmony_ci
1570b815c7f3Sopenharmony_ci#define CASE_NAME(x)		case x : return #x ; break ;
1571b815c7f3Sopenharmony_ci
1572b815c7f3Sopenharmony_ciconst char *
1573b815c7f3Sopenharmony_cistr_of_major_format (int format)
1574b815c7f3Sopenharmony_ci{	switch (SF_CONTAINER (format))
1575b815c7f3Sopenharmony_ci	{	CASE_NAME (SF_FORMAT_WAV) ;
1576b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_AIFF) ;
1577b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_AU) ;
1578b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_RAW) ;
1579b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_PAF) ;
1580b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_SVX) ;
1581b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_NIST) ;
1582b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_VOC) ;
1583b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_IRCAM) ;
1584b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_W64) ;
1585b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_MAT4) ;
1586b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_MAT5) ;
1587b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_PVF) ;
1588b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_XI) ;
1589b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_HTK) ;
1590b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_SDS) ;
1591b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_AVR) ;
1592b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_WAVEX) ;
1593b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_SD2) ;
1594b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_FLAC) ;
1595b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_CAF) ;
1596b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_WVE) ;
1597b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_OGG) ;
1598b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_MPEG) ;
1599b815c7f3Sopenharmony_ci		default :
1600b815c7f3Sopenharmony_ci			break ;
1601b815c7f3Sopenharmony_ci		} ;
1602b815c7f3Sopenharmony_ci
1603b815c7f3Sopenharmony_ci	return "BAD_MAJOR_FORMAT" ;
1604b815c7f3Sopenharmony_ci} /* str_of_major_format */
1605b815c7f3Sopenharmony_ci
1606b815c7f3Sopenharmony_ciconst char *
1607b815c7f3Sopenharmony_cistr_of_minor_format (int format)
1608b815c7f3Sopenharmony_ci{	switch (SF_CODEC (format))
1609b815c7f3Sopenharmony_ci	{	CASE_NAME (SF_FORMAT_PCM_S8) ;
1610b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_PCM_16) ;
1611b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_PCM_24) ;
1612b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_PCM_32) ;
1613b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_PCM_U8) ;
1614b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_FLOAT) ;
1615b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_DOUBLE) ;
1616b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_ULAW) ;
1617b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_ALAW) ;
1618b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_IMA_ADPCM) ;
1619b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_MS_ADPCM) ;
1620b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_GSM610) ;
1621b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_VOX_ADPCM) ;
1622b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_NMS_ADPCM_16) ;
1623b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_NMS_ADPCM_24) ;
1624b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_NMS_ADPCM_32) ;
1625b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_G721_32) ;
1626b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_G723_24) ;
1627b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_G723_40) ;
1628b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_DWVW_12) ;
1629b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_DWVW_16) ;
1630b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_DWVW_24) ;
1631b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_DWVW_N) ;
1632b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_DPCM_8) ;
1633b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_DPCM_16) ;
1634b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_VORBIS) ;
1635b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_MPEG_LAYER_I) ;
1636b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_MPEG_LAYER_II) ;
1637b815c7f3Sopenharmony_ci		CASE_NAME (SF_FORMAT_MPEG_LAYER_III) ;
1638b815c7f3Sopenharmony_ci		default :
1639b815c7f3Sopenharmony_ci			break ;
1640b815c7f3Sopenharmony_ci		} ;
1641b815c7f3Sopenharmony_ci
1642b815c7f3Sopenharmony_ci	return "BAD_MINOR_FORMAT" ;
1643b815c7f3Sopenharmony_ci} /* str_of_minor_format */
1644b815c7f3Sopenharmony_ci
1645b815c7f3Sopenharmony_ciconst char *
1646b815c7f3Sopenharmony_cistr_of_open_mode (int mode)
1647b815c7f3Sopenharmony_ci{	switch (mode)
1648b815c7f3Sopenharmony_ci	{	CASE_NAME (SFM_READ) ;
1649b815c7f3Sopenharmony_ci		CASE_NAME (SFM_WRITE) ;
1650b815c7f3Sopenharmony_ci		CASE_NAME (SFM_RDWR) ;
1651b815c7f3Sopenharmony_ci
1652b815c7f3Sopenharmony_ci		default :
1653b815c7f3Sopenharmony_ci			break ;
1654b815c7f3Sopenharmony_ci		} ;
1655b815c7f3Sopenharmony_ci
1656b815c7f3Sopenharmony_ci	return "BAD_MODE" ;
1657b815c7f3Sopenharmony_ci} /* str_of_open_mode */
1658b815c7f3Sopenharmony_ci
1659b815c7f3Sopenharmony_ciconst char *
1660b815c7f3Sopenharmony_cistr_of_endianness (int end)
1661b815c7f3Sopenharmony_ci{	switch (end)
1662b815c7f3Sopenharmony_ci	{	CASE_NAME (SF_ENDIAN_BIG) ;
1663b815c7f3Sopenharmony_ci		CASE_NAME (SF_ENDIAN_LITTLE) ;
1664b815c7f3Sopenharmony_ci		CASE_NAME (SF_ENDIAN_CPU) ;
1665b815c7f3Sopenharmony_ci		default :
1666b815c7f3Sopenharmony_ci			break ;
1667b815c7f3Sopenharmony_ci		} ;
1668b815c7f3Sopenharmony_ci
1669b815c7f3Sopenharmony_ci	/* Zero length string for SF_ENDIAN_FILE. */
1670b815c7f3Sopenharmony_ci	return "" ;
1671b815c7f3Sopenharmony_ci} /* str_of_endianness */
1672b815c7f3Sopenharmony_ci
1673b815c7f3Sopenharmony_ci/*==============================================================================
1674b815c7f3Sopenharmony_ci*/
1675b815c7f3Sopenharmony_ci
1676b815c7f3Sopenharmony_civoid
1677b815c7f3Sopenharmony_cipsf_f2s_array (const float *src, short *dest, int count, int normalize)
1678b815c7f3Sopenharmony_ci{	float 			normfact ;
1679b815c7f3Sopenharmony_ci
1680b815c7f3Sopenharmony_ci	normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
1681b815c7f3Sopenharmony_ci	for (int i = 0 ; i < count ; i++)
1682b815c7f3Sopenharmony_ci		dest [i] = psf_lrintf (src [i] * normfact) ;
1683b815c7f3Sopenharmony_ci
1684b815c7f3Sopenharmony_ci	return ;
1685b815c7f3Sopenharmony_ci} /* psf_f2s_array */
1686b815c7f3Sopenharmony_ci
1687b815c7f3Sopenharmony_civoid
1688b815c7f3Sopenharmony_cipsf_f2s_clip_array (const float *src, short *dest, int count, int normalize)
1689b815c7f3Sopenharmony_ci{	float			normfact, scaled_value ;
1690b815c7f3Sopenharmony_ci
1691b815c7f3Sopenharmony_ci	normfact = normalize ? (1.0 * 0x8000) : 1.0 ;
1692b815c7f3Sopenharmony_ci
1693b815c7f3Sopenharmony_ci	for (int i = 0 ; i < count ; i++)
1694b815c7f3Sopenharmony_ci	{	scaled_value = src [i] * normfact ;
1695b815c7f3Sopenharmony_ci		if (scaled_value >= (1.0 * 0x7FFF))
1696b815c7f3Sopenharmony_ci		{	dest [i] = 0x7FFF ;
1697b815c7f3Sopenharmony_ci			continue ;
1698b815c7f3Sopenharmony_ci			} ;
1699b815c7f3Sopenharmony_ci		if (scaled_value <= (-8.0 * 0x1000))
1700b815c7f3Sopenharmony_ci		{	dest [i] = -0x7FFF - 1 ;
1701b815c7f3Sopenharmony_ci			continue ;
1702b815c7f3Sopenharmony_ci			} ;
1703b815c7f3Sopenharmony_ci
1704b815c7f3Sopenharmony_ci		dest [i] = psf_lrintf (scaled_value) ;
1705b815c7f3Sopenharmony_ci		} ;
1706b815c7f3Sopenharmony_ci
1707b815c7f3Sopenharmony_ci	return ;
1708b815c7f3Sopenharmony_ci} /* psf_f2s_clip_array */
1709b815c7f3Sopenharmony_ci
1710b815c7f3Sopenharmony_civoid
1711b815c7f3Sopenharmony_cipsf_d2s_array (const double *src, short *dest, int count, int normalize)
1712b815c7f3Sopenharmony_ci{	double 			normfact ;
1713b815c7f3Sopenharmony_ci
1714b815c7f3Sopenharmony_ci	normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
1715b815c7f3Sopenharmony_ci	for (int i = 0 ; i < count ; i++)
1716b815c7f3Sopenharmony_ci		dest [i] = psf_lrint (src [i] * normfact) ;
1717b815c7f3Sopenharmony_ci
1718b815c7f3Sopenharmony_ci	return ;
1719b815c7f3Sopenharmony_ci} /* psf_f2s_array */
1720b815c7f3Sopenharmony_ci
1721b815c7f3Sopenharmony_civoid
1722b815c7f3Sopenharmony_cipsf_d2s_clip_array (const double *src, short *dest, int count, int normalize)
1723b815c7f3Sopenharmony_ci{	double			normfact, scaled_value ;
1724b815c7f3Sopenharmony_ci
1725b815c7f3Sopenharmony_ci	normfact = normalize ? (1.0 * 0x8000) : 1.0 ;
1726b815c7f3Sopenharmony_ci
1727b815c7f3Sopenharmony_ci	for (int i = 0 ; i < count ; i++)
1728b815c7f3Sopenharmony_ci	{	scaled_value = src [i] * normfact ;
1729b815c7f3Sopenharmony_ci		if (scaled_value >= (1.0 * 0x7FFF))
1730b815c7f3Sopenharmony_ci		{	dest [i] = 0x7FFF ;
1731b815c7f3Sopenharmony_ci			continue ;
1732b815c7f3Sopenharmony_ci			} ;
1733b815c7f3Sopenharmony_ci		if (scaled_value <= (-8.0 * 0x1000))
1734b815c7f3Sopenharmony_ci		{	dest [i] = -0x7FFF - 1 ;
1735b815c7f3Sopenharmony_ci			continue ;
1736b815c7f3Sopenharmony_ci			} ;
1737b815c7f3Sopenharmony_ci
1738b815c7f3Sopenharmony_ci		dest [i] = psf_lrint (scaled_value) ;
1739b815c7f3Sopenharmony_ci		} ;
1740b815c7f3Sopenharmony_ci
1741b815c7f3Sopenharmony_ci	return ;
1742b815c7f3Sopenharmony_ci} /* psf_d2s_clip_array */
1743b815c7f3Sopenharmony_ci
1744b815c7f3Sopenharmony_ci
1745b815c7f3Sopenharmony_civoid
1746b815c7f3Sopenharmony_cipsf_f2i_array (const float *src, int *dest, int count, int normalize)
1747b815c7f3Sopenharmony_ci{	float 			normfact ;
1748b815c7f3Sopenharmony_ci
1749b815c7f3Sopenharmony_ci	normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ;
1750b815c7f3Sopenharmony_ci	for (int i = 0 ; i < count ; i++)
1751b815c7f3Sopenharmony_ci		dest [i] = psf_lrintf (src [i] * normfact) ;
1752b815c7f3Sopenharmony_ci
1753b815c7f3Sopenharmony_ci	return ;
1754b815c7f3Sopenharmony_ci} /* psf_f2i_array */
1755b815c7f3Sopenharmony_ci
1756b815c7f3Sopenharmony_civoid
1757b815c7f3Sopenharmony_cipsf_f2i_clip_array (const float *src, int *dest, int count, int normalize)
1758b815c7f3Sopenharmony_ci{	float			normfact, scaled_value ;
1759b815c7f3Sopenharmony_ci
1760b815c7f3Sopenharmony_ci	normfact = normalize ? (8.0 * 0x10000000) : 1.0 ;
1761b815c7f3Sopenharmony_ci
1762b815c7f3Sopenharmony_ci	for (int i = 0 ; i < count ; i++)
1763b815c7f3Sopenharmony_ci	{	scaled_value = src [i] * normfact ;
1764b815c7f3Sopenharmony_ci#if CPU_CLIPS_POSITIVE == 0
1765b815c7f3Sopenharmony_ci		if (scaled_value >= (1.0 * 0x7FFFFFFF))
1766b815c7f3Sopenharmony_ci		{	dest [i] = 0x7FFFFFFF ;
1767b815c7f3Sopenharmony_ci			continue ;
1768b815c7f3Sopenharmony_ci			} ;
1769b815c7f3Sopenharmony_ci#endif
1770b815c7f3Sopenharmony_ci#if CPU_CLIPS_NEGATIVE == 0
1771b815c7f3Sopenharmony_ci		if (scaled_value <= (-8.0 * 0x10000000))
1772b815c7f3Sopenharmony_ci		{	dest [i] = 0x80000000 ;
1773b815c7f3Sopenharmony_ci			continue ;
1774b815c7f3Sopenharmony_ci			} ;
1775b815c7f3Sopenharmony_ci#endif
1776b815c7f3Sopenharmony_ci
1777b815c7f3Sopenharmony_ci		dest [i] = psf_lrintf (scaled_value) ;
1778b815c7f3Sopenharmony_ci		} ;
1779b815c7f3Sopenharmony_ci
1780b815c7f3Sopenharmony_ci	return ;
1781b815c7f3Sopenharmony_ci} /* psf_f2i_clip_array */
1782b815c7f3Sopenharmony_ci
1783b815c7f3Sopenharmony_civoid
1784b815c7f3Sopenharmony_cipsf_d2i_array (const double *src, int *dest, int count, int normalize)
1785b815c7f3Sopenharmony_ci{	double 			normfact ;
1786b815c7f3Sopenharmony_ci
1787b815c7f3Sopenharmony_ci	normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ;
1788b815c7f3Sopenharmony_ci	for (int i = 0 ; i < count ; i++)
1789b815c7f3Sopenharmony_ci		dest [i] = psf_lrint (src [i] * normfact) ;
1790b815c7f3Sopenharmony_ci
1791b815c7f3Sopenharmony_ci	return ;
1792b815c7f3Sopenharmony_ci} /* psf_f2i_array */
1793b815c7f3Sopenharmony_ci
1794b815c7f3Sopenharmony_civoid
1795b815c7f3Sopenharmony_cipsf_d2i_clip_array (const double *src, int *dest, int count, int normalize)
1796b815c7f3Sopenharmony_ci{	double			normfact, scaled_value ;
1797b815c7f3Sopenharmony_ci
1798b815c7f3Sopenharmony_ci	normfact = normalize ? (8.0 * 0x10000000) : 1.0 ;
1799b815c7f3Sopenharmony_ci
1800b815c7f3Sopenharmony_ci	for (int i = 0 ; i < count ; i++)
1801b815c7f3Sopenharmony_ci	{	scaled_value = src [i] * normfact ;
1802b815c7f3Sopenharmony_ci#if CPU_CLIPS_POSITIVE == 0
1803b815c7f3Sopenharmony_ci		if (scaled_value >= (1.0 * 0x7FFFFFFF))
1804b815c7f3Sopenharmony_ci		{	dest [i] = 0x7FFFFFFF ;
1805b815c7f3Sopenharmony_ci			continue ;
1806b815c7f3Sopenharmony_ci			} ;
1807b815c7f3Sopenharmony_ci#endif
1808b815c7f3Sopenharmony_ci#if CPU_CLIPS_NEGATIVE == 0
1809b815c7f3Sopenharmony_ci		if (scaled_value <= (-8.0 * 0x10000000))
1810b815c7f3Sopenharmony_ci		{	dest [i] = 0x80000000 ;
1811b815c7f3Sopenharmony_ci			continue ;
1812b815c7f3Sopenharmony_ci			} ;
1813b815c7f3Sopenharmony_ci#endif
1814b815c7f3Sopenharmony_ci
1815b815c7f3Sopenharmony_ci		dest [i] = psf_lrint (scaled_value) ;
1816b815c7f3Sopenharmony_ci		} ;
1817b815c7f3Sopenharmony_ci
1818b815c7f3Sopenharmony_ci	return ;
1819b815c7f3Sopenharmony_ci} /* psf_d2i_clip_array */
1820b815c7f3Sopenharmony_ci
1821b815c7f3Sopenharmony_ciFILE *
1822b815c7f3Sopenharmony_cipsf_open_tmpfile (char * fname, size_t fnamelen)
1823b815c7f3Sopenharmony_ci{	const char * tmpdir ;
1824b815c7f3Sopenharmony_ci	FILE * file ;
1825b815c7f3Sopenharmony_ci
1826b815c7f3Sopenharmony_ci	if (OS_IS_WIN32)
1827b815c7f3Sopenharmony_ci		tmpdir = getenv ("TEMP") ;
1828b815c7f3Sopenharmony_ci	else
1829b815c7f3Sopenharmony_ci	{	tmpdir = getenv ("TMPDIR") ;
1830b815c7f3Sopenharmony_ci		tmpdir = tmpdir == NULL ? "/tmp" : tmpdir ;
1831b815c7f3Sopenharmony_ci		} ;
1832b815c7f3Sopenharmony_ci
1833b815c7f3Sopenharmony_ci	if (tmpdir && access (tmpdir, R_OK | W_OK | X_OK) == 0)
1834b815c7f3Sopenharmony_ci	{	snprintf (fname, fnamelen, "%s/%x%x-alac.tmp", tmpdir, psf_rand_int32 (), psf_rand_int32 ()) ;
1835b815c7f3Sopenharmony_ci		if ((file = fopen (fname, "wb+")) != NULL)
1836b815c7f3Sopenharmony_ci			return file ;
1837b815c7f3Sopenharmony_ci		} ;
1838b815c7f3Sopenharmony_ci
1839b815c7f3Sopenharmony_ci	snprintf (fname, fnamelen, "%x%x-alac.tmp", psf_rand_int32 (), psf_rand_int32 ()) ;
1840b815c7f3Sopenharmony_ci	if ((file = fopen (fname, "wb+")) != NULL)
1841b815c7f3Sopenharmony_ci		return file ;
1842b815c7f3Sopenharmony_ci
1843b815c7f3Sopenharmony_ci	memset (fname, 0, fnamelen) ;
1844b815c7f3Sopenharmony_ci	return NULL ;
1845b815c7f3Sopenharmony_ci} /* psf_open_tmpfile */
1846