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
_citrus_ctype_btowc_fallback(_citrus_ctype_rec_t * __restrict cc,int c,wint_t * __restrict wcresult)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
_citrus_ctype_wctob_fallback(_citrus_ctype_rec_t * __restrict cc,wint_t wc,int * __restrict cresult)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
_citrus_ctype_mbsnrtowcs_fallback(_citrus_ctype_rec_t * __restrict cc,wchar_t * __restrict pwcs,const char ** __restrict s,size_t in,size_t n,void * __restrict psenc,size_t * __restrict nresult)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
_citrus_ctype_wcsnrtombs_fallback(_citrus_ctype_rec_t * __restrict cc,char * __restrict s,const wchar_t ** __restrict pwcs,size_t in,size_t n,void * __restrict psenc,size_t * __restrict nresult)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