xref: /dragonfly/lib/libc/citrus/citrus_none.c (revision cecb9aae)
1 /* $NetBSD: citrus_none.c,v 1.17 2005/12/02 11:14:20 yamt Exp $ */
2 
3 /*-
4  * Copyright (c)2002 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 <assert.h>
30 #include <errno.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <stddef.h>
35 #include <locale.h>
36 #include <wchar.h>
37 #include <sys/types.h>
38 
39 #include "citrus_namespace.h"
40 #include "citrus_types.h"
41 #include "citrus_module.h"
42 #include "citrus_ctype.h"
43 #include "citrus_none.h"
44 #include "citrus_stdenc.h"
45 
46 /* ---------------------------------------------------------------------- */
47 static int
48 _citrus_NONE_ctype_getops(_citrus_ctype_ops_rec_t *, size_t, uint32_t);
49 static int
50 _citrus_NONE_stdenc_getops(struct _citrus_stdenc_ops *, size_t, uint32_t);
51 
52 _CITRUS_CTYPE_DECLS(NONE);
53 _CITRUS_CTYPE_DEF_OPS(NONE);
54 
55 
56 /* ---------------------------------------------------------------------- */
57 
58 static int
59 _citrus_NONE_ctype_getops(_citrus_ctype_ops_rec_t *ops, size_t lenops,
60 			uint32_t expected_version)
61 {
62 	if (expected_version<_CITRUS_CTYPE_ABI_VERSION || lenops<sizeof(*ops))
63 		return (EINVAL);
64 
65 	memcpy(ops, &_citrus_NONE_ctype_ops, sizeof(_citrus_NONE_ctype_ops));
66 
67 	return (0);
68 }
69 
70 static int
71 _citrus_NONE_stdenc_getops(struct _citrus_stdenc_ops *ops, size_t lenops,
72 			 uint32_t expected_version)
73 {
74 	if (expected_version<_CITRUS_STDENC_ABI_VERSION || lenops<sizeof(*ops))
75 		return (EINVAL);
76 
77 	memcpy(ops, &_citrus_NONE_stdenc_ops, sizeof(_citrus_NONE_stdenc_ops));
78 
79 	return (0);
80 }
81 
82 static int
83 /*ARGSUSED*/
84 _citrus_NONE_ctype_init(void ** __restrict cl, void * __restrict var __unused,
85 			size_t lenvar __unused, size_t lenps __unused)
86 {
87 	*cl = NULL;
88 	return (0);
89 }
90 
91 static void
92 /*ARGSUSED*/
93 _citrus_NONE_ctype_uninit(void *cl __unused)
94 {
95 }
96 
97 static unsigned
98 /*ARGSUSED*/
99 _citrus_NONE_ctype_get_mb_cur_max(void *cl __unused)
100 {
101 	return (1);
102 }
103 
104 static int
105 /*ARGSUSED*/
106 _citrus_NONE_ctype_mblen(void * __restrict cl __unused,
107 			 const char * __restrict s, size_t n,
108 			 int * __restrict nresult)
109 {
110 	if (!s) {
111 		*nresult = 0; /* state independent */
112 		return (0);
113 	}
114 	if (n==0) {
115 		*nresult = -1;
116 		return (EILSEQ);
117 	}
118 	*nresult = (*s == 0) ? 0 : 1;
119 	return (0);
120 }
121 
122 static int
123 /*ARGSUSED*/
124 _citrus_NONE_ctype_mbrlen(void * __restrict cl __unused,
125 			  const char * __restrict s, size_t n,
126 			  void * __restrict pspriv __unused,
127 			  size_t * __restrict nresult)
128 {
129 	if (!s) {
130 		*nresult = 0;
131 		return (0);
132 	}
133 	if (n==0) {
134 		*nresult = (size_t)-2;
135 		return (0);
136 	}
137 	*nresult = (*s == 0) ? 0 : 1;
138 	return (0);
139 }
140 
141 static int
142 /*ARGSUSED*/
143 _citrus_NONE_ctype_mbrtowc(void * __restrict cl __unused,
144 			   wchar_t * __restrict pwc,
145 			   const char * __restrict s, size_t n,
146 			   void * __restrict pspriv __unused,
147 			   size_t * __restrict nresult)
148 {
149 	if (s == NULL) {
150 		*nresult = 0;
151 		return (0);
152 	}
153 	if (n == 0) {
154 		*nresult = (size_t)-2;
155 		return (0);
156 	}
157 
158 	if (pwc != NULL)
159 		*pwc = (wchar_t)(unsigned char) *s;
160 
161 	*nresult = *s == '\0' ? 0 : 1;
162 	return (0);
163 }
164 
165 static int
166 /*ARGSUSED*/
167 _citrus_NONE_ctype_mbsinit(void * __restrict cl __unused,
168 			   const void * __restrict pspriv __unused,
169 			   int * __restrict nresult)
170 {
171 	*nresult = 1;  /* always initial state */
172 	return (0);
173 }
174 
175 static int
176 /*ARGSUSED*/
177 _citrus_NONE_ctype_mbsrtowcs(void * __restrict cl __unused,
178 			     wchar_t * __restrict pwcs,
179 			     const char ** __restrict s, size_t n,
180 			     void * __restrict pspriv __unused,
181 			     size_t * __restrict nresult)
182 {
183 	int cnt;
184 	const char *s0;
185 
186 	/* if pwcs is NULL, ignore n */
187 	if (pwcs == NULL)
188 		n = 1; /* arbitrary >0 value */
189 
190 	cnt = 0;
191 	s0 = *s; /* to keep *s unchanged for now, use copy instead. */
192 	while (n > 0) {
193 		if (pwcs != NULL) {
194 			*pwcs = (wchar_t)(unsigned char)*s0;
195 		}
196 		if (*s0 == '\0') {
197 			s0 = NULL;
198 			break;
199 		}
200 		s0++;
201 		if (pwcs != NULL) {
202 			pwcs++;
203 			n--;
204 		}
205 		cnt++;
206 	}
207 	if (pwcs)
208 		*s = s0;
209 
210 	*nresult = (size_t)cnt;
211 
212 	return (0);
213 }
214 
215 static int
216 _citrus_NONE_ctype_mbstowcs(void * __restrict cl, wchar_t * __restrict wcs,
217 			    const char * __restrict s, size_t n,
218 			    size_t * __restrict nresult)
219 {
220 	const char *tmp_s = __DEQUALIFY(const char *, s);
221 
222 	return (_citrus_NONE_ctype_mbsrtowcs(cl, wcs, &tmp_s, n, NULL, nresult));
223 }
224 
225 static int
226 /*ARGSUSED*/
227 _citrus_NONE_ctype_mbtowc(void * __restrict cl __unused,
228 			  wchar_t * __restrict pwc,
229 			  const char * __restrict s, size_t n,
230 			  int * __restrict nresult)
231 {
232 
233 	if (s == NULL) {
234 		*nresult = 0; /* state independent */
235 		return (0);
236 	}
237 	if (n == 0) {
238 		return (EILSEQ);
239 	}
240 	if (pwc == NULL) {
241 		if (*s == '\0') {
242 			*nresult = 0;
243 		} else {
244 			*nresult = 1;
245 		}
246 		return (0);
247 	}
248 
249 	*pwc = (wchar_t)(unsigned char)*s;
250 	*nresult = *s == '\0' ? 0 : 1;
251 
252 	return (0);
253 }
254 
255 static int
256 /*ARGSUSED*/
257 _citrus_NONE_ctype_wcrtomb(void * __restrict cl __unused,
258 			   char * __restrict s, wchar_t wc,
259 			   void * __restrict pspriv __unused,
260 			   size_t * __restrict nresult)
261 {
262 	if ((wc&~0xFFU) != 0) {
263 		*nresult = (size_t)-1;
264 		return (EILSEQ);
265 	}
266 
267 	*nresult = 1;
268 	if (s!=NULL)
269 		*s = (char)wc;
270 
271 	return (0);
272 }
273 
274 static int
275 /*ARGSUSED*/
276 _citrus_NONE_ctype_wcsrtombs(void * __restrict cl __unused,
277 			     char * __restrict s,
278 			     const wchar_t ** __restrict pwcs, size_t n,
279 			     void * __restrict pspriv __unused,
280 			     size_t * __restrict nresult)
281 {
282 	size_t count;
283 	const wchar_t *pwcs0;
284 
285 	pwcs0 = *pwcs;
286 	count = 0;
287 
288 	if (s == NULL)
289 		n = 1;
290 
291 	while (n > 0) {
292 		if ((*pwcs0 & ~0xFFU) != 0) {
293 			*nresult = (size_t)-1;
294 			return (EILSEQ);
295 		}
296 		if (s != NULL) {
297 			*s++ = (char)*pwcs0;
298 			n--;
299 		}
300 		if (*pwcs0 == L'\0') {
301 			pwcs0 = NULL;
302 			break;
303 		}
304 		count++;
305 		pwcs0++;
306 	}
307 	if (s != NULL)
308 		*pwcs = pwcs0;
309 
310 	*nresult = count;
311 
312 	return (0);
313 }
314 
315 static int
316 _citrus_NONE_ctype_wcstombs(void * __restrict cl, char * __restrict s,
317 			    const wchar_t * __restrict pwcs, size_t n,
318 			    size_t * __restrict nresult)
319 {
320 	const wchar_t *tmp_pwcs = __DEQUALIFY(const wchar_t *, pwcs);
321 
322 	return (_citrus_NONE_ctype_wcsrtombs(cl, s, &tmp_pwcs, n, NULL, nresult));
323 }
324 
325 static int
326 _citrus_NONE_ctype_wctomb(void * __restrict cl, char * __restrict s,
327 			  wchar_t wc, int * __restrict nresult)
328 {
329 	int ret;
330 	size_t nr;
331 
332 	if (s == NULL) {
333 		/*
334 		 * initialize state here.
335 		 * (nothing to do for us.)
336 		 */
337 		*nresult = 0; /* we're state independent */
338 		return (0);
339 	}
340 
341 	ret = _citrus_NONE_ctype_wcrtomb(cl, s, wc, NULL, &nr);
342 	*nresult = (int)nr;
343 
344 	return (ret);
345 }
346 
347 static int
348 /*ARGSUSED*/
349 _citrus_NONE_ctype_btowc(_citrus_ctype_rec_t * __restrict cc __unused,
350 			 int c, wint_t * __restrict wcresult)
351 {
352 	if (c == EOF || c & ~0xFF)
353 		*wcresult = WEOF;
354 	else
355 		*wcresult = (wint_t)c;
356 	return (0);
357 }
358 
359 static int
360 /*ARGSUSED*/
361 _citrus_NONE_ctype_wctob(_citrus_ctype_rec_t * __restrict cc __unused,
362 			 wint_t wc, int * __restrict cresult)
363 {
364 	if (wc == WEOF || wc & ~0xFF)
365 		*cresult = EOF;
366 	else
367 		*cresult = (int)wc;
368 	return (0);
369 }
370 
371 /* ---------------------------------------------------------------------- */
372 
373 _CITRUS_STDENC_DECLS(NONE);
374 _CITRUS_STDENC_DEF_OPS(NONE);
375 struct _citrus_stdenc_traits _citrus_NONE_stdenc_traits = {
376 	0,	/* et_state_size */
377 	1,	/* mb_cur_max */
378 };
379 
380 static int
381 /*ARGSUSED*/
382 _citrus_NONE_stdenc_init(struct _citrus_stdenc * __restrict ce,
383 			 const void *var __unused, size_t lenvar __unused,
384 			 struct _citrus_stdenc_traits * __restrict et)
385 {
386 
387 	et->et_state_size = 0;
388 	et->et_mb_cur_max = 1;
389 
390 	ce->ce_closure = NULL;
391 
392 	return (0);
393 }
394 
395 static void
396 /*ARGSUSED*/
397 _citrus_NONE_stdenc_uninit(struct _citrus_stdenc *ce __unused)
398 {
399 }
400 
401 static int
402 /*ARGSUSED*/
403 _citrus_NONE_stdenc_init_state(struct _citrus_stdenc * __restrict ce __unused,
404 			       void * __restrict ps __unused)
405 {
406 	return (0);
407 }
408 
409 static int
410 /*ARGSUSED*/
411 _citrus_NONE_stdenc_mbtocs(struct _citrus_stdenc * __restrict ce __unused,
412 			   _csid_t *csid, _index_t *idx,
413 			   const char **s, size_t n,
414 			   void *ps __unused, size_t *nresult)
415 {
416 
417 	_DIAGASSERT(csid != NULL && idx != NULL);
418 
419 	if (n<1) {
420 		*nresult = (size_t)-2;
421 		return (0);
422 	}
423 
424 	*csid = 0;
425 	*idx = (_index_t)(unsigned char)*(*s)++;
426 	*nresult = *idx == 0 ? 0 : 1;
427 
428 	return (0);
429 }
430 
431 static int
432 /*ARGSUSED*/
433 _citrus_NONE_stdenc_cstomb(struct _citrus_stdenc * __restrict ce __unused,
434 			   char *s, size_t n,
435 			   _csid_t csid, _index_t idx,
436 			   void *ps __unused, size_t *nresult)
437 {
438 
439 	if (csid == _CITRUS_CSID_INVALID) {
440 		*nresult = 0;
441 		return (0);
442 	}
443 	if (n<1) {
444 		*nresult = (size_t)-1;
445 		return (E2BIG);
446 	}
447 	if (csid != 0 || (idx&0xFF) != idx)
448 		return (EILSEQ);
449 
450 	*s = (char)idx;
451 	*nresult = 1;
452 
453 	return (0);
454 }
455 
456 static int
457 /*ARGSUSED*/
458 _citrus_NONE_stdenc_mbtowc(struct _citrus_stdenc * __restrict ce __unused,
459 			   _wc_t * __restrict pwc,
460 			   const char ** __restrict s, size_t n,
461 			   void * __restrict pspriv __unused,
462 			   size_t * __restrict nresult)
463 {
464 	if (s == NULL) {
465 		*nresult = 0;
466 		return (0);
467 	}
468 	if (n == 0) {
469 		*nresult = (size_t)-2;
470 		return (0);
471 	}
472 
473 	if (pwc != NULL)
474 		*pwc = (_wc_t)(unsigned char) **s;
475 
476 	*nresult = *s == '\0' ? 0 : 1;
477 	return (0);
478 }
479 
480 static int
481 /*ARGSUSED*/
482 _citrus_NONE_stdenc_wctomb(struct _citrus_stdenc * __restrict ce __unused,
483 			   char * __restrict s, size_t n, _wc_t wc,
484 			   void * __restrict pspriv __unused,
485 			   size_t * __restrict nresult)
486 {
487 	if ((wc&~0xFFU) != 0) {
488 		*nresult = (size_t)-1;
489 		return (EILSEQ);
490 	}
491 	if (n==0) {
492 		*nresult = (size_t)-1;
493 		return (E2BIG);
494 	}
495 
496 	*nresult = 1;
497 	if (s!=NULL && n>0)
498 		*s = (char)wc;
499 
500 	return (0);
501 }
502 
503 static int
504 /*ARGSUSED*/
505 _citrus_NONE_stdenc_put_state_reset(struct _citrus_stdenc * __restrict ce __unused,
506 				    char * __restrict s __unused,
507 				    size_t n __unused,
508 				    void * __restrict pspriv __unused,
509 				    size_t * __restrict nresult)
510 {
511 
512 	*nresult = 0;
513 
514 	return (0);
515 }
516 
517 static int
518 /*ARGSUSED*/
519 _citrus_NONE_stdenc_get_state_desc(struct _stdenc * __restrict ce __unused,
520 				   void * __restrict ps __unused,
521 				   int id,
522 				   struct _stdenc_state_desc * __restrict d)
523 {
524 	int ret = 0;
525 
526 	switch (id) {
527 	case _STDENC_SDID_GENERIC:
528 		d->u.generic.state = _STDENC_SDGEN_INITIAL;
529 		break;
530 	default:
531 		ret = EOPNOTSUPP;
532 	}
533 
534 	return ret;
535 }
536