#define ICONV_INTERNAL
#include "iconv.h"

#include <stdlib.h>
#include <string.h>

struct iconv_uc {
	struct iconv_ces *	from;
	struct iconv_ces *	to;
	int			ignore_ilseq;
	ucs_t			missing;
};

static iconv_open_t iconv_uc_open;
static iconv_close_t iconv_uc_close;
static iconv_conv_t iconv_uc_conv;

struct iconv_converter_desc iconv_uc_desc = {
	iconv_uc_open,
	iconv_uc_close,
	iconv_uc_conv
};

/*
 * It is call by apr_iconv_open: (*idesc)->icd_open()
 */
apr_status_t
iconv_uc_open(const char *to, const char *from, void **data, apr_pool_t *ctx)
{
	struct iconv_uc *ic;
	int error;

	ic = malloc(sizeof(*ic));
	if (ic == NULL)
		return APR_ENOMEM;
	memset(ic, 0, sizeof(*ic));
	error = apr_iconv_ces_open(from, &ic->from, ctx);
	if (error!=APR_SUCCESS) {
		goto bad;
	}
	error = apr_iconv_ces_open(to, &ic->to, ctx);
	if (error!=APR_SUCCESS) {
		goto bad;
	}
	ic->ignore_ilseq = 0;
	ic->missing = '_';
	*data = (void*)ic;
	return APR_SUCCESS;
bad:
	iconv_uc_close(ic,ctx);
	return error;
}

apr_status_t
iconv_uc_close(void *data, apr_pool_t *ctx)
{
	struct iconv_uc *ic = (struct iconv_uc *)data;

	if (ic == NULL)
		return APR_EBADF;
	if (ic->from)
		apr_iconv_ces_close(ic->from, ctx);
	if (ic->to)
		apr_iconv_ces_close(ic->to, ctx);
	free(ic);
	return APR_SUCCESS;
}

apr_status_t
iconv_uc_conv(void *data, const unsigned char **inbuf, apr_size_t *inbytesleft,
	unsigned char **outbuf, apr_size_t *outbytesleft, apr_size_t *res)
{
	struct iconv_uc *ic = (struct iconv_uc *)data;
	const unsigned char *ptr;
	ucs_t ch;
        apr_ssize_t size;

	*res = (apr_size_t)(0);
	if (data == NULL) {
		*res = (apr_size_t) -1;
		return APR_EBADF;
	}

	if (inbuf == NULL || *inbuf == NULL) {
		if (ICONV_CES_CONVERT_FROM_UCS(ic->to, UCS_CHAR_NONE,
		    outbuf, outbytesleft) <= 0) {
			*res = (apr_size_t) -1;
			return APR_BADARG; /* too big */
		}
		ICONV_CES_RESET(ic->from);
		ICONV_CES_RESET(ic->to);
		return APR_SUCCESS;
	}
	if (inbytesleft == NULL || *inbytesleft == 0)
		return APR_SUCCESS;
	while (*inbytesleft > 0 && *outbytesleft > 0) {
		ptr = *inbuf;
		ch = ICONV_CES_CONVERT_TO_UCS(ic->from, inbuf, inbytesleft);
		if (ch == UCS_CHAR_NONE)
			return APR_EINVAL;
		if (ch == UCS_CHAR_INVALID) { /* Invalid character in source buffer */
			if (ic->ignore_ilseq)
				continue;
			*inbytesleft += *inbuf - ptr;
			*inbuf = ptr;
			return APR_BADCH; /* eilseq invalid */
		}
		size = ICONV_CES_CONVERT_FROM_UCS(ic->to, ch,
		    outbuf, outbytesleft);
		if (size < 0) {		 /* No equivalent in destination charset */
			size = ICONV_CES_CONVERT_FROM_UCS(ic->to, ic->missing,
			    outbuf, outbytesleft);
			if (size)
				(*res)++;
		}
		if (!size) {		 /* No space to write to */
			*inbytesleft += *inbuf - ptr;
			*inbuf = ptr; 
			return APR_BADARG; /* too big */
		}
	}
	return APR_SUCCESS;
}

#if 0
/* iconv_byteratio(cd) returns the byte ratio between OUTPUT and INPUT
 *                     stream lengths
 * -1: unknown
 *  0: 1/2
 *  1: 1/1
 *  2: 2/1
 */
int
iconv_byteratio(apr_iconv_t cd)
{
	iconv_data *idata = (iconv_data *)cd;
	int from, to;

	to = (*idata->to->data->nbytes)(idata->to);
	if (to == 0)
		return -1;
	from = (*idata->from->data->nbytes)(idata->from);
	return (from) ? to / from : -1;
}
#endif
