#ifdef HAVE_CONFIG_H
# include "config.h"
# define __CDIO_CONFIG_H__ 1
#endif
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif
#include "cdio_assert.h"
#include <cdio/logging.h>
#include <cdio/util.h>
#include "_cdio_stream.h"
struct _CdioDataSource {
void* user_data;
cdio_stream_io_functions op;
int is_open;
off_t position;
};
void
cdio_stream_close(CdioDataSource_t *p_obj)
{
if (!p_obj) return;
if (p_obj->is_open) {
cdio_debug ("closed source...");
p_obj->op.close(p_obj->user_data);
p_obj->is_open = 0;
p_obj->position = 0;
}
}
void
cdio_stream_destroy(CdioDataSource_t *p_obj)
{
if (!p_obj) return;
cdio_stream_close(p_obj);
p_obj->op.free(p_obj->user_data);
p_obj->user_data = NULL;
free(p_obj);
}
off_t
cdio_stream_getpos(CdioDataSource_t* p_obj, off_t *i_offset)
{
if (!p_obj || !p_obj->is_open) return DRIVER_OP_UNINIT;
return *i_offset = p_obj->position;
}
CdioDataSource_t *
cdio_stream_new(void *user_data, const cdio_stream_io_functions *funcs)
{
CdioDataSource_t *new_obj;
new_obj = calloc (1, sizeof (CdioDataSource_t));
cdio_assert (new_obj != NULL);
new_obj->user_data = user_data;
memcpy(&(new_obj->op), funcs, sizeof(cdio_stream_io_functions));
return new_obj;
}
static bool
_cdio_stream_open_if_necessary(CdioDataSource_t *p_obj)
{
if (!p_obj) return false;
if (!p_obj->is_open) {
if (p_obj->op.open(p_obj->user_data)) {
cdio_warn ("could not open input stream...");
return false;
} else {
cdio_debug ("opened source...");
p_obj->is_open = 1;
p_obj->position = 0;
}
}
return true;
}
ssize_t
cdio_stream_read(CdioDataSource_t* p_obj, void *ptr, size_t size, size_t nmemb)
{
long read_bytes;
if (!p_obj) return 0;
if (!_cdio_stream_open_if_necessary(p_obj)) return 0;
read_bytes = (p_obj->op.read)(p_obj->user_data, ptr, size*nmemb);
p_obj->position += read_bytes;
return read_bytes;
}
int
cdio_stream_seek(CdioDataSource_t* p_obj, off_t offset, int whence)
{
if (!p_obj) return DRIVER_OP_UNINIT;
if (!_cdio_stream_open_if_necessary(p_obj))
return DRIVER_OP_ERROR;
if (offset < 0) return DRIVER_OP_ERROR;
if (p_obj->position < 0) return DRIVER_OP_ERROR;
if (p_obj->position != offset) {
#ifdef STREAM_DEBUG
cdio_warn("had to reposition DataSource from %ld to %ld!", p_obj->position, offset);
#endif
p_obj->position = offset;
return p_obj->op.seek(p_obj->user_data, offset, whence);
}
return 0;
}
off_t
cdio_stream_stat(CdioDataSource_t *p_obj)
{
if (!p_obj) return -1;
if (!_cdio_stream_open_if_necessary(p_obj)) return -1;
return p_obj->op.stat(p_obj->user_data);
}