xref: /freebsd-src/sys/libkern/iconv_xlat.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
1c0587701SJoel Dahl /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
38a36da99SPedro F. Giffuni  *
4d122d784SJoel Dahl  * Copyright (c) 2000-2001 Boris Popov
56f2d8adbSBoris Popov  * All rights reserved.
66f2d8adbSBoris Popov  *
76f2d8adbSBoris Popov  * Redistribution and use in source and binary forms, with or without
86f2d8adbSBoris Popov  * modification, are permitted provided that the following conditions
96f2d8adbSBoris Popov  * are met:
106f2d8adbSBoris Popov  * 1. Redistributions of source code must retain the above copyright
116f2d8adbSBoris Popov  *    notice, this list of conditions and the following disclaimer.
126f2d8adbSBoris Popov  * 2. Redistributions in binary form must reproduce the above copyright
136f2d8adbSBoris Popov  *    notice, this list of conditions and the following disclaimer in the
146f2d8adbSBoris Popov  *    documentation and/or other materials provided with the distribution.
156f2d8adbSBoris Popov  *
166f2d8adbSBoris Popov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
176f2d8adbSBoris Popov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
186f2d8adbSBoris Popov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
196f2d8adbSBoris Popov  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
206f2d8adbSBoris Popov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
216f2d8adbSBoris Popov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
226f2d8adbSBoris Popov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
236f2d8adbSBoris Popov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
246f2d8adbSBoris Popov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
256f2d8adbSBoris Popov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
266f2d8adbSBoris Popov  * SUCH DAMAGE.
276f2d8adbSBoris Popov  */
28ab0de15bSDavid E. O'Brien 
296f2d8adbSBoris Popov #include <sys/param.h>
306f2d8adbSBoris Popov #include <sys/kernel.h>
316f2d8adbSBoris Popov #include <sys/systm.h>
326f2d8adbSBoris Popov #include <sys/malloc.h>
336f2d8adbSBoris Popov #include <sys/iconv.h>
346f2d8adbSBoris Popov 
356f2d8adbSBoris Popov #include "iconv_converter_if.h"
366f2d8adbSBoris Popov 
376f2d8adbSBoris Popov /*
386f2d8adbSBoris Popov  * "XLAT" converter
396f2d8adbSBoris Popov  */
406f2d8adbSBoris Popov 
416f2d8adbSBoris Popov #ifdef MODULE_DEPEND
42c4f02a89SMax Khon MODULE_DEPEND(iconv_xlat, libiconv, 2, 2, 2);
436f2d8adbSBoris Popov #endif
446f2d8adbSBoris Popov 
456f2d8adbSBoris Popov /*
466f2d8adbSBoris Popov  * XLAT converter instance
476f2d8adbSBoris Popov  */
486f2d8adbSBoris Popov struct iconv_xlat {
496f2d8adbSBoris Popov 	KOBJ_FIELDS;
506f2d8adbSBoris Popov 	u_char *		d_table;
516f2d8adbSBoris Popov 	struct iconv_cspair *	d_csp;
526f2d8adbSBoris Popov };
536f2d8adbSBoris Popov 
546f2d8adbSBoris Popov static int
iconv_xlat_open(struct iconv_converter_class * dcp,struct iconv_cspair * csp,struct iconv_cspair * cspf,void ** dpp)556f2d8adbSBoris Popov iconv_xlat_open(struct iconv_converter_class *dcp,
566f2d8adbSBoris Popov 	struct iconv_cspair *csp, struct iconv_cspair *cspf, void **dpp)
576f2d8adbSBoris Popov {
586f2d8adbSBoris Popov 	struct iconv_xlat *dp;
596f2d8adbSBoris Popov 
60a163d034SWarner Losh 	dp = (struct iconv_xlat *)kobj_create((struct kobj_class*)dcp, M_ICONV, M_WAITOK);
616f2d8adbSBoris Popov 	dp->d_table = csp->cp_data;
626f2d8adbSBoris Popov 	dp->d_csp = csp;
636f2d8adbSBoris Popov 	csp->cp_refcount++;
646f2d8adbSBoris Popov 	*dpp = (void*)dp;
656f2d8adbSBoris Popov 	return 0;
666f2d8adbSBoris Popov }
676f2d8adbSBoris Popov 
686f2d8adbSBoris Popov static int
iconv_xlat_close(void * data)696f2d8adbSBoris Popov iconv_xlat_close(void *data)
706f2d8adbSBoris Popov {
716f2d8adbSBoris Popov 	struct iconv_xlat *dp = data;
726f2d8adbSBoris Popov 
736f2d8adbSBoris Popov 	dp->d_csp->cp_refcount--;
746f2d8adbSBoris Popov 	kobj_delete((struct kobj*)data, M_ICONV);
756f2d8adbSBoris Popov 	return 0;
766f2d8adbSBoris Popov }
776f2d8adbSBoris Popov 
786f2d8adbSBoris Popov static int
iconv_xlat_conv(void * d2p,const char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft,int convchar,int casetype)796f2d8adbSBoris Popov iconv_xlat_conv(void *d2p, const char **inbuf,
80c4f02a89SMax Khon 	size_t *inbytesleft, char **outbuf, size_t *outbytesleft,
81c4f02a89SMax Khon 	int convchar, int casetype)
826f2d8adbSBoris Popov {
836f2d8adbSBoris Popov 	struct iconv_xlat *dp = (struct iconv_xlat*)d2p;
846f2d8adbSBoris Popov 	const char *src;
856f2d8adbSBoris Popov 	char *dst;
866f2d8adbSBoris Popov 	int n, r;
876f2d8adbSBoris Popov 
886f2d8adbSBoris Popov 	if (inbuf == NULL || *inbuf == NULL || outbuf == NULL || *outbuf == NULL)
896f2d8adbSBoris Popov 		return 0;
90c4f02a89SMax Khon 	if (casetype != 0)
91c4f02a89SMax Khon 		return -1;
92c4f02a89SMax Khon 	if (convchar == 1)
93c4f02a89SMax Khon 		r = n = 1;
94c4f02a89SMax Khon 	else
956f2d8adbSBoris Popov 		r = n = min(*inbytesleft, *outbytesleft);
966f2d8adbSBoris Popov 	src = *inbuf;
976f2d8adbSBoris Popov 	dst = *outbuf;
986f2d8adbSBoris Popov 	while(r--)
996f2d8adbSBoris Popov 		*dst++ = dp->d_table[(u_char)*src++];
1006f2d8adbSBoris Popov 	*inbuf += n;
1016f2d8adbSBoris Popov 	*outbuf += n;
102c4f02a89SMax Khon 	*inbytesleft -= n;
1036f2d8adbSBoris Popov 	*outbytesleft -= n;
1046f2d8adbSBoris Popov 	return 0;
1056f2d8adbSBoris Popov }
1066f2d8adbSBoris Popov 
1076f2d8adbSBoris Popov static const char *
iconv_xlat_name(struct iconv_converter_class * dcp)1086f2d8adbSBoris Popov iconv_xlat_name(struct iconv_converter_class *dcp)
1096f2d8adbSBoris Popov {
1106f2d8adbSBoris Popov 	return "xlat";
1116f2d8adbSBoris Popov }
1126f2d8adbSBoris Popov 
1136f2d8adbSBoris Popov static kobj_method_t iconv_xlat_methods[] = {
1146f2d8adbSBoris Popov 	KOBJMETHOD(iconv_converter_open,	iconv_xlat_open),
1156f2d8adbSBoris Popov 	KOBJMETHOD(iconv_converter_close,	iconv_xlat_close),
1166f2d8adbSBoris Popov 	KOBJMETHOD(iconv_converter_conv,	iconv_xlat_conv),
1176f2d8adbSBoris Popov #if 0
1186f2d8adbSBoris Popov 	KOBJMETHOD(iconv_converter_init,	iconv_xlat_init),
1196f2d8adbSBoris Popov 	KOBJMETHOD(iconv_converter_done,	iconv_xlat_done),
1206f2d8adbSBoris Popov #endif
1216f2d8adbSBoris Popov 	KOBJMETHOD(iconv_converter_name,	iconv_xlat_name),
1226f2d8adbSBoris Popov 	{0, 0}
1236f2d8adbSBoris Popov };
1246f2d8adbSBoris Popov 
1256f2d8adbSBoris Popov KICONV_CONVERTER(xlat, sizeof(struct iconv_xlat));
126