1 /* $NetBSD: citrus_none.c,v 1.18 2008/06/14 16:01:07 tnozaki Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Copyright (c) 2002 Citrus Project, 7 * Copyright (c) 2010 Gabor Kovesdan <gabor@FreeBSD.org>, 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #include <sys/types.h> 34 35 #include <assert.h> 36 #include <errno.h> 37 #include <iconv.h> 38 #include <stddef.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <wchar.h> 43 44 #include "citrus_namespace.h" 45 #include "citrus_types.h" 46 #include "citrus_module.h" 47 #include "citrus_none.h" 48 #include "citrus_stdenc.h" 49 50 _CITRUS_STDENC_DECLS(NONE); 51 _CITRUS_STDENC_DEF_OPS(NONE); 52 struct _citrus_stdenc_traits _citrus_NONE_stdenc_traits = { 53 0, /* et_state_size */ 54 1, /* mb_cur_max */ 55 }; 56 57 static int 58 _citrus_NONE_stdenc_init(struct _citrus_stdenc * __restrict ce, 59 const void *var __unused, size_t lenvar __unused, 60 struct _citrus_stdenc_traits * __restrict et) 61 { 62 63 et->et_state_size = 0; 64 et->et_mb_cur_max = 1; 65 66 ce->ce_closure = NULL; 67 68 return (0); 69 } 70 71 static void 72 _citrus_NONE_stdenc_uninit(struct _citrus_stdenc *ce __unused) 73 { 74 75 } 76 77 static int 78 _citrus_NONE_stdenc_init_state(struct _citrus_stdenc * __restrict ce __unused, 79 void * __restrict ps __unused) 80 { 81 82 return (0); 83 } 84 85 static int 86 _citrus_NONE_stdenc_mbtocs(struct _citrus_stdenc * __restrict ce __unused, 87 _csid_t *csid, _index_t *idx, char **s, size_t n, 88 void *ps __unused, size_t *nresult, struct iconv_hooks *hooks) 89 { 90 91 if (n < 1) { 92 *nresult = (size_t)-2; 93 return (0); 94 } 95 96 *csid = 0; 97 *idx = (_index_t)(unsigned char)*(*s)++; 98 *nresult = *idx == 0 ? 0 : 1; 99 100 if ((hooks != NULL) && (hooks->uc_hook != NULL)) 101 hooks->uc_hook((unsigned int)*idx, hooks->data); 102 103 return (0); 104 } 105 106 static int 107 _citrus_NONE_stdenc_cstomb(struct _citrus_stdenc * __restrict ce __unused, 108 char *s, size_t n, _csid_t csid, _index_t idx, void *ps __unused, 109 size_t *nresult, struct iconv_hooks *hooks __unused) 110 { 111 112 if (csid == _CITRUS_CSID_INVALID) { 113 *nresult = 0; 114 return (0); 115 } 116 if (csid != 0) 117 return (EILSEQ); 118 119 if ((idx & 0x000000FF) == idx) { 120 if (n < 1) { 121 *nresult = (size_t)-1; 122 return (E2BIG); 123 } 124 *s = (char)idx; 125 *nresult = 1; 126 } else if ((idx & 0x0000FFFF) == idx) { 127 if (n < 2) { 128 *nresult = (size_t)-1; 129 return (E2BIG); 130 } 131 s[0] = (char)idx; 132 /* XXX: might be endian dependent */ 133 s[1] = (char)(idx >> 8); 134 *nresult = 2; 135 } else if ((idx & 0x00FFFFFF) == idx) { 136 if (n < 3) { 137 *nresult = (size_t)-1; 138 return (E2BIG); 139 } 140 s[0] = (char)idx; 141 /* XXX: might be endian dependent */ 142 s[1] = (char)(idx >> 8); 143 s[2] = (char)(idx >> 16); 144 *nresult = 3; 145 } else { 146 if (n < 4) { 147 *nresult = (size_t)-1; 148 return (E2BIG); 149 } 150 s[0] = (char)idx; 151 /* XXX: might be endian dependent */ 152 s[1] = (char)(idx >> 8); 153 s[2] = (char)(idx >> 16); 154 s[3] = (char)(idx >> 24); 155 *nresult = 4; 156 } 157 158 return (0); 159 } 160 161 static int 162 _citrus_NONE_stdenc_mbtowc(struct _citrus_stdenc * __restrict ce __unused, 163 _wc_t * __restrict pwc, char ** __restrict s, size_t n, 164 void * __restrict pspriv __unused, size_t * __restrict nresult, 165 struct iconv_hooks *hooks) 166 { 167 168 if (*s == NULL) { 169 *nresult = 0; 170 return (0); 171 } 172 if (n == 0) { 173 *nresult = (size_t)-2; 174 return (0); 175 } 176 177 if (pwc != NULL) 178 *pwc = (_wc_t)(unsigned char) **s; 179 180 *nresult = **s == '\0' ? 0 : 1; 181 182 if ((hooks != NULL) && (hooks->wc_hook != NULL)) 183 hooks->wc_hook(*pwc, hooks->data); 184 185 return (0); 186 } 187 188 static int 189 _citrus_NONE_stdenc_wctomb(struct _citrus_stdenc * __restrict ce __unused, 190 char * __restrict s, size_t n, _wc_t wc, 191 void * __restrict pspriv __unused, size_t * __restrict nresult, 192 struct iconv_hooks *hooks __unused) 193 { 194 195 if ((wc & ~0xFFU) != 0) { 196 *nresult = (size_t)-1; 197 return (EILSEQ); 198 } 199 if (n == 0) { 200 *nresult = (size_t)-1; 201 return (E2BIG); 202 } 203 204 *nresult = 1; 205 if (s != NULL && n > 0) 206 *s = (char)wc; 207 208 return (0); 209 } 210 211 static int 212 _citrus_NONE_stdenc_put_state_reset(struct _citrus_stdenc * __restrict ce __unused, 213 char * __restrict s __unused, size_t n __unused, 214 void * __restrict pspriv __unused, size_t * __restrict nresult) 215 { 216 217 *nresult = 0; 218 219 return (0); 220 } 221 222 static int 223 _citrus_NONE_stdenc_get_state_desc(struct _stdenc * __restrict ce __unused, 224 void * __restrict ps __unused, int id, 225 struct _stdenc_state_desc * __restrict d) 226 { 227 int ret = 0; 228 229 switch (id) { 230 case _STDENC_SDID_GENERIC: 231 d->u.generic.state = _STDENC_SDGEN_INITIAL; 232 break; 233 default: 234 ret = EOPNOTSUPP; 235 } 236 237 return (ret); 238 } 239