405613df4e7ac0954cb6b8218da2a08eb2053b2e
[dragonfly.git] / lib / libc / citrus / citrus_stdenc.c
1 /* $FreeBSD: head/lib/libc/iconv/citrus_stdenc.c 219019 2011-02-25 00:04:39Z gabor $ */
2 /* $NetBSD: citrus_stdenc.c,v 1.3 2005/10/29 18:02:04 tshiozak 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
43 struct _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
50 int
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                 goto bad;
107
108         /* allocate traits */
109         ce->ce_traits = malloc(sizeof(*ce->ce_traits));
110         if (ce->ce_traits == NULL) {
111                 ret = errno;
112                 goto bad;
113         }
114         /* init and get closure */
115         ret = (*ce->ce_ops->eo_init)(ce, variable, lenvar, ce->ce_traits);
116         if (ret)
117                 goto bad;
118
119         *rce = ce;
120
121         return (0);
122
123 bad:
124         _citrus_stdenc_close(ce);
125         return (ret);
126 }
127
128 void
129 _citrus_stdenc_close(struct _citrus_stdenc *ce)
130 {
131
132         if (ce == &_citrus_stdenc_default)
133                 return;
134
135         if (ce->ce_module) {
136                 if (ce->ce_ops) {
137                         if (ce->ce_closure && ce->ce_ops->eo_uninit)
138                                 (*ce->ce_ops->eo_uninit)(ce);
139                         free(ce->ce_ops);
140                 }
141                 free(ce->ce_traits);
142                 _citrus_unload_module(ce->ce_module);
143         }
144         free(ce);
145 }