#include <iconv.h>
#include "lists.h"

static char * (*ext_pos_) (const char *);
static void * (*xmalloc_) (size_t);
static void * (*xcalloc_) (size_t, size_t);
static void * (*xrealloc_) (void *, const size_t);
static char * (*xstrdup_) (const char *);
static char * (*xstrerror_) (int);
static void (*internal_error_) (const char *, int, const char *,
	const char *, ...);
static void (*internal_fatal_) (const char *, int, const char *,
	const char *, ...);
static char * (*format_msg_va_) (const char *, va_list);
static void (*decoder_error_init_) (struct decoder_error *);
static void (*decoder_error_) (struct decoder_error *,
		const enum decoder_error_type, const int, const char *, ...);
static void (*decoder_error_clear_) (struct decoder_error *);
static void (*decoder_error_copy_) (struct decoder_error *,
		const struct decoder_error *);
static ssize_t (*io_read_) (struct io_stream *, void *, size_t);
static int (*io_eof_) (struct io_stream *);
static char * (*io_strerror_) (struct io_stream *);
static struct io_stream * (*io_open_) (const char *, const int);
static int (*io_ok_) (struct io_stream *);
static off_t (*io_file_size_) (const struct io_stream *);
static off_t (*io_seek_) (struct io_stream *, off_t, int);
static ssize_t (*io_peek_) (struct io_stream *, void *, size_t);
static void (*io_close_) (struct io_stream *);
static off_t (*io_tell_) (struct io_stream *);
static int (*options_get_int_) (const char *);
static char * (*options_get_str_) (const char *);
static char * (*options_get_symb_) (const char *);
static bool (*options_get_bool_) (const char *);
static void (*internal_logit_) (const char *, const int, const char *,
		const char *, ...);
static char * (*iconv_str_) (const iconv_t desc, const char *str);
static void (*tags_free_) (struct file_tags *);
static struct file_tags * (*tags_new_) ();
static void (*tags_copy_) (struct file_tags *, const struct file_tags *);
static int (*sfmt_Bps_) (const long);
static bool (*lists_strs_exists_) (lists_t_strs *, const char *);
static lists_t_strs * (*lists_strs_new_) (int);
static int (*lists_strs_split_) (lists_t_strs *, const char *, const char *);
static char * (*lists_strs_at_) (const lists_t_strs *, int);
static void (*lists_strs_free_) (lists_t_strs *);
static void (*lists_strs_append_) (lists_t_strs *, const char *);

inline static void copy_undefs(const struct decoder_undefs_t *undefs)
{
	ext_pos_ = undefs->ext_pos;
	xmalloc_ = undefs->xmalloc;
	xcalloc_ = undefs->xcalloc;
	xrealloc_ = undefs->xrealloc;
	xstrdup_ = undefs->xstrdup;
	xstrerror_ = undefs->xstrerror;
	internal_error_ = undefs->internal_error;
	internal_fatal_ = undefs->internal_fatal;
	format_msg_va_ = undefs->format_msg_va;
	decoder_error_init_ = undefs->decoder_error_init;
	decoder_error_ = undefs->decoder_error;
	decoder_error_clear_ = undefs->decoder_error_clear;
	decoder_error_copy_ = undefs->decoder_error_copy;
	io_read_ = undefs->io_read;
	io_eof_ = undefs->io_eof;
	io_strerror_ = undefs->io_strerror;
	io_open_ = undefs->io_open;
	io_ok_ = undefs->io_ok;
	io_file_size_ = undefs->io_file_size;
	io_seek_ = undefs->io_seek;
	io_peek_ = undefs->io_peek;
	io_close_ = undefs->io_close;
	io_tell_ = undefs->io_tell;
	options_get_int_ = undefs->options_get_int;
	options_get_str_ = undefs->options_get_str;
	options_get_symb_ = undefs->options_get_symb;
	options_get_bool_ = undefs->options_get_bool;
	internal_logit_ = undefs->internal_logit;
	iconv_str_ = undefs->iconv_str;
	tags_free_ = undefs->tags_free;
	tags_new_ = undefs->tags_new;
	tags_copy_ = undefs->tags_copy;
	sfmt_Bps_ = undefs->sfmt_Bps;
	lists_strs_exists_ = undefs->lists_strs_exists;
	lists_strs_new_ = undefs->lists_strs_new;
	lists_strs_split_ = undefs->lists_strs_split;
	lists_strs_at_ = undefs->lists_strs_at;
	lists_strs_free_ = undefs->lists_strs_free;
	lists_strs_append_ = undefs->lists_strs_append;
}

#define ext_pos ext_pos_
#define xmalloc xmalloc_
#define xcalloc xcalloc_
#define xrealloc xrealloc_
#define xstrdup xstrdup_
#define xstrerror xstrerror_
#define internal_error internal_error_
#define internal_fatal internal_fatal_
#define format_msg_va format_msg_va_
#define decoder_error_init decoder_error_init_
#define decoder_error(e, t, a, f, ...) \
	decoder_error_(e, t, a, f, ## __VA_ARGS__)
#define decoder_error_clear decoder_error_clear_
#define decoder_error_copy decoder_error_copy_
#define io_read io_read_
#define io_eof io_eof_
#define io_strerror io_strerror_
#define io_open io_open_
#define io_ok io_ok_
#define io_file_size io_file_size_
#define io_seek io_seek_
#define io_peek io_peek_
#define io_close io_close_
#define io_tell io_tell_
#define options_get_int options_get_int_
#define options_get_str options_get_str_
#define options_get_symb options_get_symb_
#define options_get_bool options_get_bool_
#ifndef NDEBUG
# undef logit
# define logit(format, ...) \
	internal_logit_ (__FILE__, __LINE__, __FUNCTION__, format, \
	## __VA_ARGS__)
#else
# define logit fake_logit_
#endif
#define fake_logit fake_logit_
#define iconv_str iconv_str_
#define tags_free tags_free_
#define tags_new tags_new_
#define tags_copy tags_copy_
#define sfmt_Bps sfmt_Bps_
#define lists_strs_exists lists_strs_exists_
#define lists_strs_new lists_strs_new_
#define lists_strs_split lists_strs_split_
#define lists_strs_at lists_strs_at_
#define lists_strs_free lists_strs_free_
#define lists_strs_append lists_strs_append_

const char *decoder_error_text (const struct decoder_error *error)
{
	return error->err;
}

/* Return a non-zero value if the stream is seekable. */
int io_seekable (const struct io_stream *s)
{
    return s->source == IO_SOURCE_FD || s->source == IO_SOURCE_MMAP;
}
