1 /* $NetBSD: citrus_ctype_fallback.c,v 1.3 2013/05/28 16:57:56 joerg 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/cdefs.h> 30 #if defined(LIBC_SCCS) && !defined(lint) 31 __RCSID("$NetBSD: citrus_ctype_fallback.c,v 1.3 2013/05/28 16:57:56 joerg Exp $"); 32 #endif /* LIBC_SCCS and not lint */ 33 34 #include "namespace.h" 35 36 #include <sys/types.h> 37 #include <assert.h> 38 #include <errno.h> 39 #include <wchar.h> 40 #include <stdio.h> 41 #include <string.h> 42 #include <limits.h> 43 44 #include "citrus_module.h" 45 #include "citrus_ctype.h" 46 #include "citrus_ctype_fallback.h" 47 48 /* 49 * for ABI version >= 0x00000002 50 */ 51 52 int 53 _citrus_ctype_btowc_fallback(_citrus_ctype_rec_t * __restrict cc, 54 int c, wint_t * __restrict wcresult) 55 { 56 char mb; 57 /* 58 * what we need is _PRIVSIZE 59 * and we know that it's smaller than sizeof(mbstate_t). 60 */ 61 char pspriv[sizeof(mbstate_t)]; 62 wchar_t wc; 63 size_t nr; 64 int err; 65 66 _DIAGASSERT(cc != NULL && cc->cc_closure != NULL); 67 68 if (c == EOF) { 69 *wcresult = WEOF; 70 return 0; 71 } 72 73 memset(&pspriv, 0, sizeof(pspriv)); 74 mb = (char)(unsigned)c; 75 err = _citrus_ctype_mbrtowc(cc, &wc, &mb, 1, (void *)&pspriv, &nr); 76 if (!err && (nr == 0 || nr == 1)) 77 *wcresult = wc; 78 else 79 *wcresult = WEOF; 80 81 return 0; 82 } 83 84 int 85 _citrus_ctype_wctob_fallback(_citrus_ctype_rec_t * __restrict cc, 86 wint_t wc, int * __restrict cresult) 87 { 88 /* 89 * what we need is _PRIVSIZE 90 * and we know that it's smaller than sizeof(mbstate_t). 91 */ 92 char pspriv[sizeof(mbstate_t)]; 93 char buf[MB_LEN_MAX]; 94 size_t nr; 95 int err; 96 97 _DIAGASSERT(cc != NULL && cc->cc_closure != NULL); 98 99 if (wc == WEOF) { 100 *cresult = EOF; 101 return 0; 102 } 103 memset(&pspriv, 0, sizeof(pspriv)); 104 err = _citrus_ctype_wcrtomb(cc, buf, (wchar_t)wc, (void *)&pspriv, &nr); 105 if (!err && nr == 1) 106 *cresult = buf[0]; 107 else 108 *cresult = EOF; 109 110 return 0; 111 } 112 113 /* 114 * for ABI version >= 0x00000003 115 */ 116 117 int 118 _citrus_ctype_mbsnrtowcs_fallback(_citrus_ctype_rec_t * __restrict cc, 119 wchar_t * __restrict pwcs, const char ** __restrict s, size_t in, 120 size_t n, void * __restrict psenc, size_t * __restrict nresult) 121 { 122 int err; 123 size_t cnt, siz; 124 const char *s0, *se; 125 126 _DIAGASSERT(nresult != 0); 127 _DIAGASSERT(psenc != NULL); 128 _DIAGASSERT(s != NULL); 129 _DIAGASSERT(*s != NULL); 130 131 /* if pwcs is NULL, ignore n */ 132 if (pwcs == NULL) 133 n = 1; /* arbitrary >0 value */ 134 135 err = 0; 136 cnt = 0; 137 se = *s + in; 138 s0 = *s; /* to keep *s unchanged for now, use copy instead. */ 139 while (s0 < se && n > 0) { 140 err = _citrus_ctype_mbrtowc(cc, pwcs, s0, (size_t)(se - s0), 141 psenc, &siz); 142 if (err) { 143 cnt = (size_t)-1; 144 goto bye; 145 } 146 if (siz == (size_t)-2) { 147 s0 = se; 148 goto bye; 149 } 150 switch (siz) { 151 case 0: 152 if (pwcs) { 153 size_t dum; 154 _citrus_ctype_mbrtowc(cc, NULL, NULL, 0, psenc, 155 &dum); 156 } 157 s0 = 0; 158 goto bye; 159 default: 160 if (pwcs) { 161 pwcs++; 162 n--; 163 } 164 s0 += siz; 165 cnt++; 166 break; 167 } 168 } 169 bye: 170 if (pwcs) 171 *s = s0; 172 173 *nresult = cnt; 174 175 return err; 176 } 177 178 int 179 _citrus_ctype_wcsnrtombs_fallback(_citrus_ctype_rec_t * __restrict cc, 180 char * __restrict s, const wchar_t ** __restrict pwcs, size_t in, 181 size_t n, void * __restrict psenc, size_t * __restrict nresult) 182 { 183 size_t cnt = 0; 184 int err; 185 char buf[MB_LEN_MAX]; 186 size_t siz; 187 const wchar_t* pwcs0; 188 mbstate_t state; 189 190 pwcs0 = *pwcs; 191 192 if (!s) 193 n = 1; 194 195 while (in > 0 && n > 0) { 196 memcpy(&state, psenc, sizeof(state)); 197 err = _citrus_ctype_wcrtomb(cc, buf, *pwcs0, psenc, &siz); 198 if (siz == (size_t)-1) { 199 *nresult = siz; 200 return (err); 201 } 202 203 if (s) { 204 if (n < siz) { 205 memcpy(psenc, &state, sizeof(state)); 206 break; 207 } 208 memcpy(s, buf, siz); 209 s += siz; 210 n -= siz; 211 } 212 cnt += siz; 213 if (!*pwcs0) { 214 if (s) { 215 memset(psenc, 0, sizeof(state)); 216 } 217 pwcs0 = 0; 218 cnt--; /* don't include terminating null */ 219 break; 220 } 221 pwcs0++; 222 --in; 223 } 224 if (s) 225 *pwcs = pwcs0; 226 227 *nresult = cnt; 228 return (0); 229 } 230