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