1219019Sgabor/* $FreeBSD$ */
2264497Stijl/*	$NetBSD: citrus_stdenc.c,v 1.4 2011/11/19 18:39:58 tnozaki Exp $	*/
3219019Sgabor
4219019Sgabor/*-
5219019Sgabor * Copyright (c)2003 Citrus Project,
6219019Sgabor * All rights reserved.
7219019Sgabor *
8219019Sgabor * Redistribution and use in source and binary forms, with or without
9219019Sgabor * modification, are permitted provided that the following conditions
10219019Sgabor * are met:
11219019Sgabor * 1. Redistributions of source code must retain the above copyright
12219019Sgabor *    notice, this list of conditions and the following disclaimer.
13219019Sgabor * 2. Redistributions in binary form must reproduce the above copyright
14219019Sgabor *    notice, this list of conditions and the following disclaimer in the
15219019Sgabor *    documentation and/or other materials provided with the distribution.
16219019Sgabor *
17219019Sgabor * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18219019Sgabor * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19219019Sgabor * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20219019Sgabor * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21219019Sgabor * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22219019Sgabor * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23219019Sgabor * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24219019Sgabor * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25219019Sgabor * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26219019Sgabor * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27219019Sgabor * SUCH DAMAGE.
28219019Sgabor */
29219019Sgabor
30219019Sgabor#include <sys/cdefs.h>
31219019Sgabor
32219019Sgabor#include <assert.h>
33219019Sgabor#include <errno.h>
34219019Sgabor#include <stdlib.h>
35219019Sgabor#include <string.h>
36219019Sgabor
37219019Sgabor#include "citrus_namespace.h"
38219019Sgabor#include "citrus_types.h"
39219019Sgabor#include "citrus_module.h"
40219019Sgabor#include "citrus_none.h"
41219019Sgabor#include "citrus_stdenc.h"
42219019Sgabor
43219019Sgaborstruct _citrus_stdenc _citrus_stdenc_default = {
44219019Sgabor	&_citrus_NONE_stdenc_ops,	/* ce_ops */
45219019Sgabor	NULL,				/* ce_closure */
46219019Sgabor	NULL,				/* ce_module */
47219019Sgabor	&_citrus_NONE_stdenc_traits,	/* ce_traits */
48219019Sgabor};
49219019Sgabor
50219019Sgaborint
51219019Sgabor_citrus_stdenc_open(struct _citrus_stdenc * __restrict * __restrict rce,
52219019Sgabor    char const * __restrict encname, const void * __restrict variable,
53219019Sgabor    size_t lenvar)
54219019Sgabor{
55219019Sgabor	struct _citrus_stdenc *ce;
56219019Sgabor	_citrus_module_t handle;
57219019Sgabor	_citrus_stdenc_getops_t getops;
58219019Sgabor	int ret;
59219019Sgabor
60219019Sgabor	if (!strcmp(encname, _CITRUS_DEFAULT_STDENC_NAME)) {
61219019Sgabor		*rce = &_citrus_stdenc_default;
62219019Sgabor		return (0);
63219019Sgabor	}
64219019Sgabor	ce = malloc(sizeof(*ce));
65219019Sgabor	if (ce == NULL) {
66219019Sgabor		ret = errno;
67219019Sgabor		goto bad;
68219019Sgabor	}
69219019Sgabor	ce->ce_ops = NULL;
70219019Sgabor	ce->ce_closure = NULL;
71219019Sgabor	ce->ce_module = NULL;
72219019Sgabor	ce->ce_traits = NULL;
73219019Sgabor
74219019Sgabor	ret = _citrus_load_module(&handle, encname);
75219019Sgabor	if (ret)
76219019Sgabor		goto bad;
77219019Sgabor
78219019Sgabor	ce->ce_module = handle;
79219019Sgabor
80219019Sgabor	getops = (_citrus_stdenc_getops_t)_citrus_find_getops(ce->ce_module,
81219019Sgabor	    encname, "stdenc");
82219019Sgabor	if (getops == NULL) {
83219019Sgabor		ret = EINVAL;
84219019Sgabor		goto bad;
85219019Sgabor	}
86219019Sgabor
87219019Sgabor	ce->ce_ops = (struct _citrus_stdenc_ops *)malloc(sizeof(*ce->ce_ops));
88219019Sgabor	if (ce->ce_ops == NULL) {
89219019Sgabor		ret = errno;
90219019Sgabor		goto bad;
91219019Sgabor	}
92219019Sgabor
93219019Sgabor	ret = (*getops)(ce->ce_ops, sizeof(*ce->ce_ops));
94219019Sgabor	if (ret)
95219019Sgabor		goto bad;
96219019Sgabor
97219019Sgabor	/* validation check */
98219019Sgabor	if (ce->ce_ops->eo_init == NULL ||
99219019Sgabor	    ce->ce_ops->eo_uninit == NULL ||
100219019Sgabor	    ce->ce_ops->eo_init_state == NULL ||
101219019Sgabor	    ce->ce_ops->eo_mbtocs == NULL ||
102219019Sgabor	    ce->ce_ops->eo_cstomb == NULL ||
103219019Sgabor	    ce->ce_ops->eo_mbtowc == NULL ||
104219019Sgabor	    ce->ce_ops->eo_wctomb == NULL ||
105264497Stijl	    ce->ce_ops->eo_get_state_desc == NULL) {
106264497Stijl		ret = EINVAL;
107219019Sgabor		goto bad;
108264497Stijl	}
109219019Sgabor
110219019Sgabor	/* allocate traits */
111219019Sgabor	ce->ce_traits = malloc(sizeof(*ce->ce_traits));
112219019Sgabor	if (ce->ce_traits == NULL) {
113219019Sgabor		ret = errno;
114219019Sgabor		goto bad;
115219019Sgabor	}
116219019Sgabor	/* init and get closure */
117219019Sgabor	ret = (*ce->ce_ops->eo_init)(ce, variable, lenvar, ce->ce_traits);
118219019Sgabor	if (ret)
119219019Sgabor		goto bad;
120219019Sgabor
121219019Sgabor	*rce = ce;
122219019Sgabor
123219019Sgabor	return (0);
124219019Sgabor
125219019Sgaborbad:
126219019Sgabor	_citrus_stdenc_close(ce);
127219019Sgabor	return (ret);
128219019Sgabor}
129219019Sgabor
130219019Sgaborvoid
131219019Sgabor_citrus_stdenc_close(struct _citrus_stdenc *ce)
132219019Sgabor{
133219019Sgabor
134219019Sgabor	if (ce == &_citrus_stdenc_default)
135219019Sgabor		return;
136219019Sgabor
137219019Sgabor	if (ce->ce_module) {
138219019Sgabor		if (ce->ce_ops) {
139219019Sgabor			if (ce->ce_closure && ce->ce_ops->eo_uninit)
140219019Sgabor				(*ce->ce_ops->eo_uninit)(ce);
141219019Sgabor			free(ce->ce_ops);
142219019Sgabor		}
143219019Sgabor		free(ce->ce_traits);
144219019Sgabor		_citrus_unload_module(ce->ce_module);
145219019Sgabor	}
146219019Sgabor	free(ce);
147219019Sgabor}
148