1206360Sjoel/*-
2206361Sjoel * Copyright (c) 2000-2001 Boris Popov
375332Sbp * All rights reserved.
475332Sbp *
575332Sbp * Redistribution and use in source and binary forms, with or without
675332Sbp * modification, are permitted provided that the following conditions
775332Sbp * are met:
875332Sbp * 1. Redistributions of source code must retain the above copyright
975332Sbp *    notice, this list of conditions and the following disclaimer.
1075332Sbp * 2. Redistributions in binary form must reproduce the above copyright
1175332Sbp *    notice, this list of conditions and the following disclaimer in the
1275332Sbp *    documentation and/or other materials provided with the distribution.
1375332Sbp *
1475332Sbp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1575332Sbp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1675332Sbp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1775332Sbp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1875332Sbp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1975332Sbp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2075332Sbp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2175332Sbp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2275332Sbp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2375332Sbp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2475332Sbp * SUCH DAMAGE.
2575332Sbp */
26116189Sobrien
27116189Sobrien#include <sys/cdefs.h>
28116189Sobrien__FBSDID("$FreeBSD$");
29116189Sobrien
3075332Sbp#include <sys/param.h>
3175332Sbp#include <sys/kernel.h>
3275332Sbp#include <sys/systm.h>
3375332Sbp#include <sys/malloc.h>
3475332Sbp#include <sys/iconv.h>
3575332Sbp
3675332Sbp#include "iconv_converter_if.h"
3775332Sbp
3875332Sbp/*
3975332Sbp * "XLAT" converter
4075332Sbp */
4175332Sbp
4275332Sbp#ifdef MODULE_DEPEND
43120492SfjoeMODULE_DEPEND(iconv_xlat, libiconv, 2, 2, 2);
4475332Sbp#endif
4575332Sbp
4675332Sbp/*
4775332Sbp * XLAT converter instance
4875332Sbp */
4975332Sbpstruct iconv_xlat {
5075332Sbp	KOBJ_FIELDS;
5175332Sbp	u_char *		d_table;
5275332Sbp	struct iconv_cspair *	d_csp;
5375332Sbp};
5475332Sbp
5575332Sbpstatic int
5675332Sbpiconv_xlat_open(struct iconv_converter_class *dcp,
5775332Sbp	struct iconv_cspair *csp, struct iconv_cspair *cspf, void **dpp)
5875332Sbp{
5975332Sbp	struct iconv_xlat *dp;
6075332Sbp
61111119Simp	dp = (struct iconv_xlat *)kobj_create((struct kobj_class*)dcp, M_ICONV, M_WAITOK);
6275332Sbp	dp->d_table = csp->cp_data;
6375332Sbp	dp->d_csp = csp;
6475332Sbp	csp->cp_refcount++;
6575332Sbp	*dpp = (void*)dp;
6675332Sbp	return 0;
6775332Sbp}
6875332Sbp
6975332Sbpstatic int
7075332Sbpiconv_xlat_close(void *data)
7175332Sbp{
7275332Sbp	struct iconv_xlat *dp = data;
7375332Sbp
7475332Sbp	dp->d_csp->cp_refcount--;
7575332Sbp	kobj_delete((struct kobj*)data, M_ICONV);
7675332Sbp	return 0;
7775332Sbp}
7875332Sbp
7975332Sbpstatic int
8075332Sbpiconv_xlat_conv(void *d2p, const char **inbuf,
81120492Sfjoe	size_t *inbytesleft, char **outbuf, size_t *outbytesleft,
82120492Sfjoe	int convchar, int casetype)
8375332Sbp{
8475332Sbp	struct iconv_xlat *dp = (struct iconv_xlat*)d2p;
8575332Sbp	const char *src;
8675332Sbp	char *dst;
8775332Sbp	int n, r;
8875332Sbp
8975332Sbp	if (inbuf == NULL || *inbuf == NULL || outbuf == NULL || *outbuf == NULL)
9075332Sbp		return 0;
91120492Sfjoe	if (casetype != 0)
92120492Sfjoe		return -1;
93120492Sfjoe	if (convchar == 1)
94120492Sfjoe		r = n = 1;
95120492Sfjoe	else
96120492Sfjoe		r = n = min(*inbytesleft, *outbytesleft);
9775332Sbp	src = *inbuf;
9875332Sbp	dst = *outbuf;
9975332Sbp	while(r--)
10075332Sbp		*dst++ = dp->d_table[(u_char)*src++];
10175332Sbp	*inbuf += n;
10275332Sbp	*outbuf += n;
103120492Sfjoe	*inbytesleft -= n;
10475332Sbp	*outbytesleft -= n;
10575332Sbp	return 0;
10675332Sbp}
10775332Sbp
10875332Sbpstatic const char *
10975332Sbpiconv_xlat_name(struct iconv_converter_class *dcp)
11075332Sbp{
11175332Sbp	return "xlat";
11275332Sbp}
11375332Sbp
11475332Sbpstatic kobj_method_t iconv_xlat_methods[] = {
11575332Sbp	KOBJMETHOD(iconv_converter_open,	iconv_xlat_open),
11675332Sbp	KOBJMETHOD(iconv_converter_close,	iconv_xlat_close),
11775332Sbp	KOBJMETHOD(iconv_converter_conv,	iconv_xlat_conv),
11875332Sbp#if 0
11975332Sbp	KOBJMETHOD(iconv_converter_init,	iconv_xlat_init),
12075332Sbp	KOBJMETHOD(iconv_converter_done,	iconv_xlat_done),
12175332Sbp#endif
12275332Sbp	KOBJMETHOD(iconv_converter_name,	iconv_xlat_name),
12375332Sbp	{0, 0}
12475332Sbp};
12575332Sbp
12675332SbpKICONV_CONVERTER(xlat, sizeof(struct iconv_xlat));
127