citrus_stdenc.c revision 331722
1/* $FreeBSD: stable/11/lib/libc/iconv/citrus_stdenc.c 331722 2018-03-29 02:50:57Z eadler $ */
2/*	$NetBSD: citrus_stdenc.c,v 1.4 2011/11/19 18:39:58 tnozaki Exp $	*/
3
4/*-
5 * Copyright (c)2003 Citrus Project,
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31
32#include <assert.h>
33#include <errno.h>
34#include <stdlib.h>
35#include <string.h>
36
37#include "citrus_namespace.h"
38#include "citrus_types.h"
39#include "citrus_module.h"
40#include "citrus_none.h"
41#include "citrus_stdenc.h"
42
43struct _citrus_stdenc _citrus_stdenc_default = {
44	&_citrus_NONE_stdenc_ops,	/* ce_ops */
45	NULL,				/* ce_closure */
46	NULL,				/* ce_module */
47	&_citrus_NONE_stdenc_traits,	/* ce_traits */
48};
49
50int
51_citrus_stdenc_open(struct _citrus_stdenc * __restrict * __restrict rce,
52    char const * __restrict encname, const void * __restrict variable,
53    size_t lenvar)
54{
55	struct _citrus_stdenc *ce;
56	_citrus_module_t handle;
57	_citrus_stdenc_getops_t getops;
58	int ret;
59
60	if (!strcmp(encname, _CITRUS_DEFAULT_STDENC_NAME)) {
61		*rce = &_citrus_stdenc_default;
62		return (0);
63	}
64	ce = malloc(sizeof(*ce));
65	if (ce == NULL) {
66		ret = errno;
67		goto bad;
68	}
69	ce->ce_ops = NULL;
70	ce->ce_closure = NULL;
71	ce->ce_module = NULL;
72	ce->ce_traits = NULL;
73
74	ret = _citrus_load_module(&handle, encname);
75	if (ret)
76		goto bad;
77
78	ce->ce_module = handle;
79
80	getops = (_citrus_stdenc_getops_t)_citrus_find_getops(ce->ce_module,
81	    encname, "stdenc");
82	if (getops == NULL) {
83		ret = EINVAL;
84		goto bad;
85	}
86
87	ce->ce_ops = (struct _citrus_stdenc_ops *)malloc(sizeof(*ce->ce_ops));
88	if (ce->ce_ops == NULL) {
89		ret = errno;
90		goto bad;
91	}
92
93	ret = (*getops)(ce->ce_ops, sizeof(*ce->ce_ops));
94	if (ret)
95		goto bad;
96
97	/* validation check */
98	if (ce->ce_ops->eo_init == NULL ||
99	    ce->ce_ops->eo_uninit == NULL ||
100	    ce->ce_ops->eo_init_state == NULL ||
101	    ce->ce_ops->eo_mbtocs == NULL ||
102	    ce->ce_ops->eo_cstomb == NULL ||
103	    ce->ce_ops->eo_mbtowc == NULL ||
104	    ce->ce_ops->eo_wctomb == NULL ||
105	    ce->ce_ops->eo_get_state_desc == NULL) {
106		ret = EINVAL;
107		goto bad;
108	}
109
110	/* allocate traits */
111	ce->ce_traits = malloc(sizeof(*ce->ce_traits));
112	if (ce->ce_traits == NULL) {
113		ret = errno;
114		goto bad;
115	}
116	/* init and get closure */
117	ret = (*ce->ce_ops->eo_init)(ce, variable, lenvar, ce->ce_traits);
118	if (ret)
119		goto bad;
120
121	*rce = ce;
122
123	return (0);
124
125bad:
126	_citrus_stdenc_close(ce);
127	return (ret);
128}
129
130void
131_citrus_stdenc_close(struct _citrus_stdenc *ce)
132{
133
134	if (ce == &_citrus_stdenc_default)
135		return;
136
137	if (ce->ce_module) {
138		if (ce->ce_ops) {
139			if (ce->ce_closure && ce->ce_ops->eo_uninit)
140				(*ce->ce_ops->eo_uninit)(ce);
141			free(ce->ce_ops);
142		}
143		free(ce->ce_traits);
144		_citrus_unload_module(ce->ce_module);
145	}
146	free(ce);
147}
148