xref: /dragonfly/lib/libc/citrus/citrus_stdenc.c (revision b4f25088)
1 /* $NetBSD: citrus_stdenc.c,v 1.3 2005/10/29 18:02:04 tshiozak Exp $ */
2 
3 /*-
4  * Copyright (c)2003 Citrus Project,
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/types.h>
30 #include <assert.h>
31 #include <errno.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include "citrus_namespace.h"
36 #include "citrus_types.h"
37 #include "citrus_module.h"
38 #include "citrus_stdenc.h"
39 #include "citrus_none.h"
40 
41 struct _citrus_stdenc _citrus_stdenc_default = {
42 	&_citrus_NONE_stdenc_ops,	/* ce_ops */
43 	NULL,				/* ce_closure */
44 	NULL,				/* ce_module */
45 	&_citrus_NONE_stdenc_traits,	/* ce_traits */
46 };
47 
48 #ifdef _I18N_DYNAMIC
49 
50 static int
51 /*ARGSUSED*/
52 get_state_desc_default(struct _citrus_stdenc * __restrict ce __unused,
53 		       void * __restrict ps __unused,
54 		       int id __unused,
55 		       struct _citrus_stdenc_state_desc * __restrict d __unused)
56 {
57 	return EOPNOTSUPP;
58 }
59 
60 int
61 _citrus_stdenc_open(struct _citrus_stdenc * __restrict * __restrict rce,
62 		    char const * __restrict encname,
63 		    const void * __restrict variable, size_t lenvar)
64 {
65 	int ret;
66 	_citrus_module_t handle;
67 	struct _citrus_stdenc *ce;
68 	_citrus_stdenc_getops_t getops;
69 
70 	_DIAGASSERT(encname != NULL);
71 	_DIAGASSERT(!lenvar || variable!=NULL);
72 	_DIAGASSERT(rce != NULL);
73 
74 	if (!strcmp(encname, _CITRUS_DEFAULT_STDENC_NAME)) {
75 		*rce = &_citrus_stdenc_default;
76 		return (0);
77 	}
78 	ce = malloc(sizeof(*ce));
79 	if (ce==NULL) {
80 		ret = errno;
81 		goto bad;
82 	}
83 	ce->ce_ops = NULL;
84 	ce->ce_closure = NULL;
85 	ce->ce_module = NULL;
86 	ce->ce_traits = NULL;
87 
88 	ret = _citrus_load_module(&handle, encname);
89 	if (ret)
90 		goto bad;
91 
92 	ce->ce_module = handle;
93 
94 	getops =
95 	    (_citrus_stdenc_getops_t)_citrus_find_getops(ce->ce_module,
96 							 encname, "stdenc");
97 	if (getops == NULL) {
98 		ret = EINVAL;
99 		goto bad;
100 	}
101 
102 	ce->ce_ops = (struct _citrus_stdenc_ops *)malloc(sizeof(*ce->ce_ops));
103 	if (ce->ce_ops == NULL) {
104 		ret = errno;
105 		goto bad;
106 	}
107 
108 	ret = (*getops)(ce->ce_ops, sizeof(*ce->ce_ops),
109 			_CITRUS_STDENC_ABI_VERSION);
110 	if (ret)
111 		goto bad;
112 
113 	/* If return ABI version is not expected, should fixup it */
114 	if (ce->ce_ops->eo_abi_version < 0x00000002) {
115 		ce->ce_ops->eo_get_state_desc = &get_state_desc_default;
116 	}
117 
118 	/* validation check */
119 	if (ce->ce_ops->eo_init == NULL ||
120 	    ce->ce_ops->eo_uninit == NULL ||
121 	    ce->ce_ops->eo_init_state == NULL ||
122 	    ce->ce_ops->eo_mbtocs == NULL ||
123 	    ce->ce_ops->eo_cstomb == NULL ||
124 	    ce->ce_ops->eo_mbtowc == NULL ||
125 	    ce->ce_ops->eo_wctomb == NULL ||
126 	    ce->ce_ops->eo_get_state_desc == NULL)
127 		goto bad;
128 
129 	/* allocate traits */
130 	ce->ce_traits = malloc(sizeof(*ce->ce_traits));
131 	if (ce->ce_traits == NULL) {
132 		ret = errno;
133 		goto bad;
134 	}
135 	/* init and get closure */
136 	ret = (*ce->ce_ops->eo_init)(ce, variable, lenvar, ce->ce_traits);
137 	if (ret)
138 		goto bad;
139 
140 	*rce = ce;
141 
142 	return (0);
143 
144 bad:
145 	_citrus_stdenc_close(ce);
146 	return (ret);
147 }
148 
149 void
150 _citrus_stdenc_close(struct _citrus_stdenc *ce)
151 {
152 
153 	_DIAGASSERT(ce != NULL);
154 
155 	if (ce == &_citrus_stdenc_default)
156 		return;
157 
158 	if (ce->ce_module) {
159 		if (ce->ce_ops) {
160 			if (ce->ce_closure && ce->ce_ops->eo_uninit)
161 				(*ce->ce_ops->eo_uninit)(ce);
162 			free(ce->ce_ops);
163 		}
164 		free(ce->ce_traits);
165 		_citrus_unload_module(ce->ce_module);
166 	}
167 	free(ce);
168 }
169 
170 #else
171 /* !_I18N_DYNAMIC */
172 
173 int
174 /*ARGSUSED*/
175 _citrus_stdenc_open(struct _citrus_stdenc * __restrict * __restrict rce,
176 		    char const * __restrict encname,
177 		    const void * __restrict variable, size_t lenvar)
178 {
179 	if (!strcmp(encname, _CITRUS_DEFAULT_STDENC_NAME)) {
180 		*rce = &_citrus_stdenc_default;
181 		return (0);
182 	}
183 	return (EINVAL);
184 }
185 
186 void
187 /*ARGSUSED*/
188 _citrus_stdenc_close(struct _citrus_stdenc *ce)
189 {
190 }
191 
192 #endif
193