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