2022-08-26 15:15:16 +00:00
|
|
|
#ifndef LIBXMP_CALLBACKIO_H
|
|
|
|
#define LIBXMP_CALLBACKIO_H
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
#include "common.h"
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
void *priv;
|
|
|
|
struct xmp_callbacks callbacks;
|
|
|
|
int eof;
|
|
|
|
} CBFILE;
|
|
|
|
|
2023-06-17 08:37:50 +00:00
|
|
|
LIBXMP_BEGIN_DECLS
|
2022-08-26 15:15:16 +00:00
|
|
|
|
|
|
|
static inline uint8 cbread8(CBFILE *f, int *err)
|
|
|
|
{
|
|
|
|
uint8 x = 0xff;
|
|
|
|
size_t r = f->callbacks.read_func(&x, 1, 1, f->priv);
|
|
|
|
f->eof = (r == 1) ? 0 : EOF;
|
|
|
|
|
|
|
|
if (err) *err = f->eof;
|
|
|
|
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int8 cbread8s(CBFILE *f, int *err)
|
|
|
|
{
|
|
|
|
return (int8)cbread8(f, err);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline uint16 cbread16l(CBFILE *f, int *err)
|
|
|
|
{
|
|
|
|
uint8 buf[2];
|
2023-06-17 08:37:50 +00:00
|
|
|
uint16 x = 0xffff;
|
2022-08-26 15:15:16 +00:00
|
|
|
size_t r = f->callbacks.read_func(buf, 2, 1, f->priv);
|
|
|
|
f->eof = (r == 1) ? 0 : EOF;
|
|
|
|
|
|
|
|
if (r) x = readmem16l(buf);
|
|
|
|
if (err) *err = f->eof;
|
|
|
|
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline uint16 cbread16b(CBFILE *f, int *err)
|
|
|
|
{
|
|
|
|
uint8 buf[2];
|
2023-06-17 08:37:50 +00:00
|
|
|
uint16 x = 0xffff;
|
2022-08-26 15:15:16 +00:00
|
|
|
size_t r = f->callbacks.read_func(buf, 2, 1, f->priv);
|
|
|
|
f->eof = (r == 1) ? 0 : EOF;
|
|
|
|
|
|
|
|
if (r) x = readmem16b(buf);
|
|
|
|
if (err) *err = f->eof;
|
|
|
|
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline uint32 cbread24l(CBFILE *f, int *err)
|
|
|
|
{
|
|
|
|
uint8 buf[3];
|
2023-06-17 08:37:50 +00:00
|
|
|
uint32 x = 0xffffffff;
|
2022-08-26 15:15:16 +00:00
|
|
|
size_t r = f->callbacks.read_func(buf, 3, 1, f->priv);
|
|
|
|
f->eof = (r == 1) ? 0 : EOF;
|
|
|
|
|
|
|
|
if (r) x = readmem24l(buf);
|
|
|
|
if (err) *err = f->eof;
|
|
|
|
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline uint32 cbread24b(CBFILE *f, int *err)
|
|
|
|
{
|
|
|
|
uint8 buf[3];
|
2023-06-17 08:37:50 +00:00
|
|
|
uint32 x = 0xffffffff;
|
2022-08-26 15:15:16 +00:00
|
|
|
size_t r = f->callbacks.read_func(buf, 3, 1, f->priv);
|
|
|
|
f->eof = (r == 1) ? 0 : EOF;
|
|
|
|
|
|
|
|
if (r) x = readmem24b(buf);
|
|
|
|
if (err) *err = f->eof;
|
|
|
|
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline uint32 cbread32l(CBFILE *f, int *err)
|
|
|
|
{
|
|
|
|
uint8 buf[4];
|
2023-06-17 08:37:50 +00:00
|
|
|
uint32 x = 0xffffffff;
|
2022-08-26 15:15:16 +00:00
|
|
|
size_t r = f->callbacks.read_func(buf, 4, 1, f->priv);
|
|
|
|
f->eof = (r == 1) ? 0 : EOF;
|
|
|
|
|
|
|
|
if (r) x = readmem32l(buf);
|
|
|
|
if (err) *err = f->eof;
|
|
|
|
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline uint32 cbread32b(CBFILE *f, int *err)
|
|
|
|
{
|
|
|
|
uint8 buf[4];
|
2023-06-17 08:37:50 +00:00
|
|
|
uint32 x = 0xffffffff;
|
2022-08-26 15:15:16 +00:00
|
|
|
size_t r = f->callbacks.read_func(buf, 4, 1, f->priv);
|
|
|
|
f->eof = (r == 1) ? 0 : EOF;
|
|
|
|
|
|
|
|
if (r) x = readmem32b(buf);
|
|
|
|
if (err) *err = f->eof;
|
|
|
|
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t cbread(void *dest, size_t len, size_t nmemb, CBFILE *f)
|
|
|
|
{
|
2023-06-17 08:37:50 +00:00
|
|
|
size_t r = f->callbacks.read_func(dest, (unsigned long)len,
|
|
|
|
(unsigned long)nmemb, f->priv);
|
2022-08-26 15:15:16 +00:00
|
|
|
f->eof = (r < nmemb) ? EOF : 0;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int cbseek(CBFILE *f, long offset, int whence)
|
|
|
|
{
|
|
|
|
f->eof = 0;
|
|
|
|
return f->callbacks.seek_func(f->priv, offset, whence);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline long cbtell(CBFILE *f)
|
|
|
|
{
|
|
|
|
return f->callbacks.tell_func(f->priv);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int cbeof(CBFILE *f)
|
|
|
|
{
|
|
|
|
return f->eof;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline long cbfilelength(CBFILE *f)
|
|
|
|
{
|
|
|
|
long pos = f->callbacks.tell_func(f->priv);
|
|
|
|
long length;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if (pos < 0)
|
|
|
|
return EOF;
|
|
|
|
|
|
|
|
r = f->callbacks.seek_func(f->priv, 0, SEEK_END);
|
|
|
|
if (r < 0)
|
|
|
|
return EOF;
|
|
|
|
|
|
|
|
length = f->callbacks.tell_func(f->priv);
|
|
|
|
r = f->callbacks.seek_func(f->priv, pos, SEEK_SET);
|
|
|
|
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline CBFILE *cbopen(void *priv, struct xmp_callbacks callbacks)
|
|
|
|
{
|
|
|
|
CBFILE *f;
|
|
|
|
if (priv == NULL || callbacks.read_func == NULL ||
|
|
|
|
callbacks.seek_func == NULL || callbacks.tell_func == NULL)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
f = (CBFILE *)calloc(1, sizeof(CBFILE));
|
|
|
|
if (f == NULL)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
f->priv = priv;
|
|
|
|
f->callbacks = callbacks;
|
|
|
|
f->eof = 0;
|
|
|
|
return f;
|
|
|
|
|
|
|
|
err:
|
|
|
|
if (priv && callbacks.close_func)
|
|
|
|
callbacks.close_func(priv);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int cbclose(CBFILE *f)
|
|
|
|
{
|
|
|
|
int r = 0;
|
|
|
|
if (f->callbacks.close_func != NULL)
|
|
|
|
r = f->callbacks.close_func(f->priv);
|
|
|
|
|
|
|
|
free(f);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2023-06-17 08:37:50 +00:00
|
|
|
LIBXMP_END_DECLS
|
2022-08-26 15:15:16 +00:00
|
|
|
|
|
|
|
#endif /* LIBXMP_CALLBACKIO_H */
|