1 /* $NetBSD: citrus_stdenc.c,v 1.3 2005/10/29 18:02:04 tshiozak Exp $ */ 2 /* $DragonFly: src/lib/libc/citrus/citrus_stdenc.c,v 1.2 2008/04/10 10:21:01 hasso 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/types.h> 31 #include <assert.h> 32 #include <errno.h> 33 #include <stdlib.h> 34 #include <string.h> 35 36 #include "citrus_namespace.h" 37 #include "citrus_types.h" 38 #include "citrus_module.h" 39 #include "citrus_stdenc.h" 40 #include "citrus_none.h" 41 42 struct _citrus_stdenc _citrus_stdenc_default = { 43 &_citrus_NONE_stdenc_ops, /* ce_ops */ 44 NULL, /* ce_closure */ 45 NULL, /* ce_module */ 46 &_citrus_NONE_stdenc_traits, /* ce_traits */ 47 }; 48 49 #ifdef _I18N_DYNAMIC 50 51 static int 52 /*ARGSUSED*/ 53 get_state_desc_default(struct _citrus_stdenc * __restrict ce, 54 void * __restrict ps, 55 int id, 56 struct _citrus_stdenc_state_desc * __restrict d) 57 { 58 return EOPNOTSUPP; 59 } 60 61 int 62 _citrus_stdenc_open(struct _citrus_stdenc * __restrict * __restrict rce, 63 char const * __restrict encname, 64 const void * __restrict variable, size_t lenvar) 65 { 66 int ret; 67 _citrus_module_t handle; 68 struct _citrus_stdenc *ce; 69 _citrus_stdenc_getops_t getops; 70 71 _DIAGASSERT(encname != NULL); 72 _DIAGASSERT(!lenvar || variable!=NULL); 73 _DIAGASSERT(rce != NULL); 74 75 if (!strcmp(encname, _CITRUS_DEFAULT_STDENC_NAME)) { 76 *rce = &_citrus_stdenc_default; 77 return (0); 78 } 79 ce = malloc(sizeof(*ce)); 80 if (ce==NULL) { 81 ret = errno; 82 goto bad; 83 } 84 ce->ce_ops = NULL; 85 ce->ce_closure = NULL; 86 ce->ce_module = NULL; 87 ce->ce_traits = NULL; 88 89 ret = _citrus_load_module(&handle, encname); 90 if (ret) 91 goto bad; 92 93 ce->ce_module = handle; 94 95 getops = 96 (_citrus_stdenc_getops_t)_citrus_find_getops(ce->ce_module, 97 encname, "stdenc"); 98 if (getops == NULL) { 99 ret = EINVAL; 100 goto bad; 101 } 102 103 ce->ce_ops = (struct _citrus_stdenc_ops *)malloc(sizeof(*ce->ce_ops)); 104 if (ce->ce_ops == NULL) { 105 ret = errno; 106 goto bad; 107 } 108 109 ret = (*getops)(ce->ce_ops, sizeof(*ce->ce_ops), 110 _CITRUS_STDENC_ABI_VERSION); 111 if (ret) 112 goto bad; 113 114 /* If return ABI version is not expected, should fixup it */ 115 if (ce->ce_ops->eo_abi_version < 0x00000002) { 116 ce->ce_ops->eo_get_state_desc = &get_state_desc_default; 117 } 118 119 /* validation check */ 120 if (ce->ce_ops->eo_init == NULL || 121 ce->ce_ops->eo_uninit == NULL || 122 ce->ce_ops->eo_init_state == NULL || 123 ce->ce_ops->eo_mbtocs == NULL || 124 ce->ce_ops->eo_cstomb == NULL || 125 ce->ce_ops->eo_mbtowc == NULL || 126 ce->ce_ops->eo_wctomb == NULL || 127 ce->ce_ops->eo_get_state_desc == NULL) 128 goto bad; 129 130 /* allocate traits */ 131 ce->ce_traits = malloc(sizeof(*ce->ce_traits)); 132 if (ce->ce_traits == NULL) { 133 ret = errno; 134 goto bad; 135 } 136 /* init and get closure */ 137 ret = (*ce->ce_ops->eo_init)(ce, variable, lenvar, ce->ce_traits); 138 if (ret) 139 goto bad; 140 141 *rce = ce; 142 143 return (0); 144 145 bad: 146 _citrus_stdenc_close(ce); 147 return (ret); 148 } 149 150 void 151 _citrus_stdenc_close(struct _citrus_stdenc *ce) 152 { 153 154 _DIAGASSERT(ce != NULL); 155 156 if (ce == &_citrus_stdenc_default) 157 return; 158 159 if (ce->ce_module) { 160 if (ce->ce_ops) { 161 if (ce->ce_closure && ce->ce_ops->eo_uninit) 162 (*ce->ce_ops->eo_uninit)(ce); 163 free(ce->ce_ops); 164 } 165 free(ce->ce_traits); 166 _citrus_unload_module(ce->ce_module); 167 } 168 free(ce); 169 } 170 171 #else 172 /* !_I18N_DYNAMIC */ 173 174 int 175 /*ARGSUSED*/ 176 _citrus_stdenc_open(struct _citrus_stdenc * __restrict * __restrict rce, 177 char const * __restrict encname, 178 const void * __restrict variable, size_t lenvar) 179 { 180 if (!strcmp(encname, _CITRUS_DEFAULT_STDENC_NAME)) { 181 *rce = &_citrus_stdenc_default; 182 return (0); 183 } 184 return (EINVAL); 185 } 186 187 void 188 /*ARGSUSED*/ 189 _citrus_stdenc_close(struct _citrus_stdenc *ce) 190 { 191 } 192 193 #endif 194