nrelease - fix/improve livecd
[dragonfly.git] / lib / libc / citrus / citrus_stdenc.c
1 /* $FreeBSD: head/lib/libc/iconv/citrus_stdenc.c 263986 2014-04-01 10:36:11Z tijl $ */
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
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                 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
125 bad:
126         _citrus_stdenc_close(ce);
127         return (ret);
128 }
129
130 void
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 }