From faada59567f8cb252f4a909116595ce309ff5828 Mon Sep 17 00:00:00 2001 From: "N.N." Date: Fri, 23 May 2003 12:29:55 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r647, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/miXed/; revision=648 --- shared/common/bifi.c | 217 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 shared/common/bifi.c (limited to 'shared/common/bifi.c') diff --git a/shared/common/bifi.c b/shared/common/bifi.c new file mode 100644 index 0000000..22f3df3 --- /dev/null +++ b/shared/common/bifi.c @@ -0,0 +1,217 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* generic helpers for binary file reading and writing */ + +#ifdef NT +#include +#else +#include +#endif +#include +#include +#include +#include +#include "m_pd.h" +#include "shared.h" +#include "common/bifi.h" + +#if 1 +#define BIFI_VERBOSE +#if 0 +#define BIFI_DEBUG +#endif +#endif + +static int bifi_swapping = 1; /* set in bifi_clear() */ + +/* one helper from g_array.c (the original is global, but since + garray_ambigendian() lacks EXTERN specifier, .dll externs cannot see it; + btw. it has a comment: ``this should be renamed and moved...'') +*/ +static int ambigendian(void) +{ + unsigned short s = 1; + unsigned char c = *(char *)(&s); + return (c==0); +} + +/* two helpers from d_soundfile.c */ +uint32 bifi_swap4(uint32 n) +{ + if (bifi_swapping) + return (((n & 0xff) << 24) | ((n & 0xff00) << 8) | + ((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24)); + else return (n); +} + +uint16 bifi_swap2(uint16 n) +{ + if (bifi_swapping) + return (((n & 0xff) << 8) | ((n & 0xff00) >> 8)); + else return (n); +} + +static void bifi_error_clear(t_bifi *x) +{ + x->b_err = BIFI_ERR_OK; + x->b_syserrno = 0; + errno = 0; +} + +static void bifi_error_set(t_bifi *x, int errcode) +{ + x->b_err = errcode; + x->b_syserrno = errno; + if (errcode != BIFI_ERR_OK && x->b_fp) + { + fclose(x->b_fp); + x->b_fp = 0; + } +#if 0 /* LATER use Pd's own error logging mechanism, maybe by calling this: */ + sys_unixerror((char *)x); /* sys_logerror((char *)x, "...")? */ +#endif +} + +void bifi_clear(t_bifi *x) +{ + bifi_swapping = !ambigendian(); + x->b_fp = 0; + x->b_filename[0] = '\0'; + bifi_error_clear(x); +} + +t_bifi *bifi_new(t_bifi *x, char *hdr, size_t hdrsz) +{ + t_bifi *result = x; + if (result) result->b_selfalloc = 0; + else { + if (!(result = getbytes(sizeof(*result)))) return (0); + result->b_selfalloc = 1; + } + if (hdr || !hdrsz) result->b_hdralloc = 0; + else { + if (!(hdr = getbytes(hdrsz))) + { + if (result->b_selfalloc) freebytes(result, sizeof(*result)); + return (0); + } + result->b_hdralloc = 1; + } + result->b_header = hdr; + result->b_headersize = hdrsz; + bifi_clear(result); + return (result); +} + +void bifi_free(t_bifi *x) +{ + if (x->b_fp) fclose(x->b_fp); + if (x->b_hdralloc) freebytes(x->b_header, x->b_headersize); + if (x->b_selfalloc) freebytes(x, sizeof(*x)); +} + +void bifi_error_report(t_bifi *x) +{ + char *errmess = 0; + switch (x->b_err) + { + case BIFI_ERR_OK: + break; + case BIFI_ERR_OPEN: + errmess = "cannot open"; + break; + case BIFI_ERR_READ: + errmess = "error reading"; + break; + case BIFI_ERR_WRITE: + errmess = "error writing"; + break; + case BIFI_ERR_BADHEADER: + errmess = "missing header of"; + break; + default: + post("binary file i/o unknown error"); + } + if (errmess) + post("%s binary file `%s\' (errno %d: %s)", errmess, + x->b_filename, x->b_syserrno, strerror(x->b_syserrno)); + bifi_error_clear(x); +} + +/* Open file and read in its header (x must be a valid t_bifi pointer, + no checks are being made...) +*/ +int bifi_read_start(t_bifi *x, const char *filename, const char *dirname) +{ + int fd; + char dirbuf[MAXPDSTRING], *nameptr; + + bifi_clear(x); + strcpy(x->b_filename, filename); + if ((fd = open_via_path(dirname, filename, + "", dirbuf, &nameptr, MAXPDSTRING, 1)) < 0) + { + bifi_error_set(x, BIFI_ERR_OPEN); + return (0); + } + + /* Closing/reopening dance. This is unnecessary under linux, and we + could have tried to convert fd to fp (since we prefer using streams), + but under windows open_via_path() returns what seems to be an invalid + fd. LATER try to understand what is going on here... */ + close(fd); + if (dirbuf != nameptr) + { + char *slashpos = dirbuf + strlen(dirbuf); + *slashpos++ = '/'; + /* try not to be dependent on current open_via_path() implementation */ + if (nameptr != slashpos) + strcpy(slashpos, nameptr); + } + sys_unbashfilename(dirbuf, dirbuf); + if (!(x->b_fp = fopen(dirbuf, "rb"))) + { + bifi_error_set(x, BIFI_ERR_OPEN); + return (0); + } + + if (x->b_headersize && + fread(x->b_header, 1, x->b_headersize, x->b_fp) < x->b_headersize) + { + bifi_error_set(x, BIFI_ERR_BADHEADER); + return (0); + } + return (1); +} + +/* Open file and write the supplied header (x must be a valid t_bifi pointer + with header data properly filled, no checks are being made...) +*/ +int bifi_write_start(t_bifi *x, const char *filename, const char *dirname) +{ + char fnamebuf[MAXPDSTRING]; + + bifi_clear(x); + strcpy(x->b_filename, filename); + + fnamebuf[0] = 0; + if (*dirname) + strcat(fnamebuf, dirname), strcat(fnamebuf, "/"); + strcat(fnamebuf, filename); + sys_bashfilename(fnamebuf, fnamebuf); + if (!(x->b_fp = fopen(fnamebuf, "wb"))) + { + bifi_error_set(x, BIFI_ERR_OPEN); + return (0); + } + + if (x->b_headersize && + fwrite(x->b_header, 1, x->b_headersize, x->b_fp) < x->b_headersize) + { + bifi_error_set(x, BIFI_ERR_WRITE); + return (0); + } + return (1); +} -- cgit v1.2.1