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