xref: /freebsd/lib/libc/locale/ascii.c (revision fbbd9655e5107c68e4e0146ff22b73d7350475bc)
149c44073SBaptiste Daroussin /*-
222b87a35SBaptiste Daroussin  * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
322b87a35SBaptiste Daroussin  * Copyright (c) 1993
422b87a35SBaptiste Daroussin  *	The Regents of the University of California.  All rights reserved.
522b87a35SBaptiste Daroussin  *
622b87a35SBaptiste Daroussin  * This code is derived from software contributed to Berkeley by
722b87a35SBaptiste Daroussin  * Paul Borman at Krystal Technologies.
822b87a35SBaptiste Daroussin  *
922b87a35SBaptiste Daroussin  * Copyright (c) 2011 The FreeBSD Foundation
1022b87a35SBaptiste Daroussin  * All rights reserved.
1122b87a35SBaptiste Daroussin  * Portions of this software were developed by David Chisnall
1222b87a35SBaptiste Daroussin  * under sponsorship from the FreeBSD Foundation.
1322b87a35SBaptiste Daroussin  *
1422b87a35SBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
1522b87a35SBaptiste Daroussin  * modification, are permitted provided that the following conditions
1622b87a35SBaptiste Daroussin  * are met:
1722b87a35SBaptiste Daroussin  * 1. Redistributions of source code must retain the above copyright
1822b87a35SBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer.
1922b87a35SBaptiste Daroussin  * 2. Redistributions in binary form must reproduce the above copyright
2022b87a35SBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer in the
2122b87a35SBaptiste Daroussin  *    documentation and/or other materials provided with the distribution.
22*fbbd9655SWarner Losh  * 3. Neither the name of the University nor the names of its contributors
2322b87a35SBaptiste Daroussin  *    may be used to endorse or promote products derived from this software
2422b87a35SBaptiste Daroussin  *    without specific prior written permission.
2522b87a35SBaptiste Daroussin  *
2622b87a35SBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2722b87a35SBaptiste Daroussin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2822b87a35SBaptiste Daroussin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2922b87a35SBaptiste Daroussin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3022b87a35SBaptiste Daroussin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3122b87a35SBaptiste Daroussin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3222b87a35SBaptiste Daroussin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3322b87a35SBaptiste Daroussin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3422b87a35SBaptiste Daroussin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3522b87a35SBaptiste Daroussin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3622b87a35SBaptiste Daroussin  * SUCH DAMAGE.
3722b87a35SBaptiste Daroussin  */
3822b87a35SBaptiste Daroussin 
3922b87a35SBaptiste Daroussin #include <sys/cdefs.h>
4022b87a35SBaptiste Daroussin __FBSDID("$FreeBSD$");
4122b87a35SBaptiste Daroussin 
4222b87a35SBaptiste Daroussin #include <errno.h>
4322b87a35SBaptiste Daroussin #include <limits.h>
4422b87a35SBaptiste Daroussin #include <runetype.h>
4522b87a35SBaptiste Daroussin #include <stddef.h>
4622b87a35SBaptiste Daroussin #include <stdio.h>
4722b87a35SBaptiste Daroussin #include <stdlib.h>
4822b87a35SBaptiste Daroussin #include <string.h>
4922b87a35SBaptiste Daroussin #include <wchar.h>
5022b87a35SBaptiste Daroussin #include "mblocal.h"
5122b87a35SBaptiste Daroussin 
5222b87a35SBaptiste Daroussin static size_t	_ascii_mbrtowc(wchar_t * __restrict, const char * __restrict,
5322b87a35SBaptiste Daroussin 		    size_t, mbstate_t * __restrict);
5422b87a35SBaptiste Daroussin static int	_ascii_mbsinit(const mbstate_t *);
5522b87a35SBaptiste Daroussin static size_t	_ascii_mbsnrtowcs(wchar_t * __restrict dst,
5622b87a35SBaptiste Daroussin 		    const char ** __restrict src, size_t nms, size_t len,
5722b87a35SBaptiste Daroussin 		    mbstate_t * __restrict ps __unused);
5822b87a35SBaptiste Daroussin static size_t	_ascii_wcrtomb(char * __restrict, wchar_t,
5922b87a35SBaptiste Daroussin 		    mbstate_t * __restrict);
6022b87a35SBaptiste Daroussin static size_t	_ascii_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
6122b87a35SBaptiste Daroussin 		    size_t, size_t, mbstate_t * __restrict);
6222b87a35SBaptiste Daroussin 
6322b87a35SBaptiste Daroussin int
6422b87a35SBaptiste Daroussin _ascii_init(struct xlocale_ctype *l,_RuneLocale *rl)
6522b87a35SBaptiste Daroussin {
6622b87a35SBaptiste Daroussin 
6722b87a35SBaptiste Daroussin 	l->__mbrtowc = _ascii_mbrtowc;
6822b87a35SBaptiste Daroussin 	l->__mbsinit = _ascii_mbsinit;
6922b87a35SBaptiste Daroussin 	l->__mbsnrtowcs = _ascii_mbsnrtowcs;
7022b87a35SBaptiste Daroussin 	l->__wcrtomb = _ascii_wcrtomb;
7122b87a35SBaptiste Daroussin 	l->__wcsnrtombs = _ascii_wcsnrtombs;
7222b87a35SBaptiste Daroussin 	l->runes = rl;
7322b87a35SBaptiste Daroussin 	l->__mb_cur_max = 1;
7422b87a35SBaptiste Daroussin 	l->__mb_sb_limit = 128;
7522b87a35SBaptiste Daroussin 	return(0);
7622b87a35SBaptiste Daroussin }
7722b87a35SBaptiste Daroussin 
7822b87a35SBaptiste Daroussin static int
7922b87a35SBaptiste Daroussin _ascii_mbsinit(const mbstate_t *ps __unused)
8022b87a35SBaptiste Daroussin {
8149c44073SBaptiste Daroussin 
8222b87a35SBaptiste Daroussin 	/*
8322b87a35SBaptiste Daroussin 	 * Encoding is not state dependent - we are always in the
8422b87a35SBaptiste Daroussin 	 * initial state.
8522b87a35SBaptiste Daroussin 	 */
8622b87a35SBaptiste Daroussin 	return (1);
8722b87a35SBaptiste Daroussin }
8822b87a35SBaptiste Daroussin 
8922b87a35SBaptiste Daroussin static size_t
9022b87a35SBaptiste Daroussin _ascii_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
9122b87a35SBaptiste Daroussin     mbstate_t * __restrict ps __unused)
9222b87a35SBaptiste Daroussin {
9349c44073SBaptiste Daroussin 
9422b87a35SBaptiste Daroussin 	if (s == NULL)
9522b87a35SBaptiste Daroussin 		/* Reset to initial shift state (no-op) */
9622b87a35SBaptiste Daroussin 		return (0);
9722b87a35SBaptiste Daroussin 	if (n == 0)
9822b87a35SBaptiste Daroussin 		/* Incomplete multibyte sequence */
9922b87a35SBaptiste Daroussin 		return ((size_t)-2);
10022b87a35SBaptiste Daroussin 	if (*s & 0x80) {
10122b87a35SBaptiste Daroussin 		errno = EILSEQ;
10222b87a35SBaptiste Daroussin 		return ((size_t)-1);
10322b87a35SBaptiste Daroussin 	}
10422b87a35SBaptiste Daroussin 	if (pwc != NULL)
10522b87a35SBaptiste Daroussin 		*pwc = (unsigned char)*s;
10622b87a35SBaptiste Daroussin 	return (*s == '\0' ? 0 : 1);
10722b87a35SBaptiste Daroussin }
10822b87a35SBaptiste Daroussin 
10922b87a35SBaptiste Daroussin static size_t
11022b87a35SBaptiste Daroussin _ascii_wcrtomb(char * __restrict s, wchar_t wc,
11122b87a35SBaptiste Daroussin     mbstate_t * __restrict ps __unused)
11222b87a35SBaptiste Daroussin {
11322b87a35SBaptiste Daroussin 
11422b87a35SBaptiste Daroussin 	if (s == NULL)
11522b87a35SBaptiste Daroussin 		/* Reset to initial shift state (no-op) */
11622b87a35SBaptiste Daroussin 		return (1);
11722b87a35SBaptiste Daroussin 	if (wc < 0 || wc > 127) {
11822b87a35SBaptiste Daroussin 		errno = EILSEQ;
11922b87a35SBaptiste Daroussin 		return ((size_t)-1);
12022b87a35SBaptiste Daroussin 	}
12122b87a35SBaptiste Daroussin 	*s = (unsigned char)wc;
12222b87a35SBaptiste Daroussin 	return (1);
12322b87a35SBaptiste Daroussin }
12422b87a35SBaptiste Daroussin 
12522b87a35SBaptiste Daroussin static size_t
12622b87a35SBaptiste Daroussin _ascii_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
12722b87a35SBaptiste Daroussin     size_t nms, size_t len, mbstate_t * __restrict ps __unused)
12822b87a35SBaptiste Daroussin {
12922b87a35SBaptiste Daroussin 	const char *s;
13022b87a35SBaptiste Daroussin 	size_t nchr;
13122b87a35SBaptiste Daroussin 
13222b87a35SBaptiste Daroussin 	if (dst == NULL) {
13349c44073SBaptiste Daroussin 		for (s = *src; nms > 0 && *s != '\0'; s++, nms--) {
13422b87a35SBaptiste Daroussin 			if (*s & 0x80) {
13522b87a35SBaptiste Daroussin 				errno = EILSEQ;
13622b87a35SBaptiste Daroussin 				return ((size_t)-1);
13722b87a35SBaptiste Daroussin 			}
13849c44073SBaptiste Daroussin 		}
139d3591d68SBaptiste Daroussin 		return (s - *src);
14022b87a35SBaptiste Daroussin 	}
14122b87a35SBaptiste Daroussin 
14222b87a35SBaptiste Daroussin 	s = *src;
14322b87a35SBaptiste Daroussin 	nchr = 0;
14422b87a35SBaptiste Daroussin 	while (len-- > 0 && nms-- > 0) {
14522b87a35SBaptiste Daroussin 		if (*s & 0x80) {
1462f423a26SAndrey A. Chernov 			*src = s;
14722b87a35SBaptiste Daroussin 			errno = EILSEQ;
14822b87a35SBaptiste Daroussin 			return ((size_t)-1);
14922b87a35SBaptiste Daroussin 		}
15022b87a35SBaptiste Daroussin 		if ((*dst++ = (unsigned char)*s++) == L'\0') {
15122b87a35SBaptiste Daroussin 			*src = NULL;
15222b87a35SBaptiste Daroussin 			return (nchr);
15322b87a35SBaptiste Daroussin 		}
15422b87a35SBaptiste Daroussin 		nchr++;
15522b87a35SBaptiste Daroussin 	}
15622b87a35SBaptiste Daroussin 	*src = s;
15722b87a35SBaptiste Daroussin 	return (nchr);
15822b87a35SBaptiste Daroussin }
15922b87a35SBaptiste Daroussin 
16022b87a35SBaptiste Daroussin static size_t
16122b87a35SBaptiste Daroussin _ascii_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
16222b87a35SBaptiste Daroussin     size_t nwc, size_t len, mbstate_t * __restrict ps __unused)
16322b87a35SBaptiste Daroussin {
16422b87a35SBaptiste Daroussin 	const wchar_t *s;
16522b87a35SBaptiste Daroussin 	size_t nchr;
16622b87a35SBaptiste Daroussin 
16722b87a35SBaptiste Daroussin 	if (dst == NULL) {
16822b87a35SBaptiste Daroussin 		for (s = *src; nwc > 0 && *s != L'\0'; s++, nwc--) {
16922b87a35SBaptiste Daroussin 			if (*s < 0 || *s > 127) {
17022b87a35SBaptiste Daroussin 				errno = EILSEQ;
17122b87a35SBaptiste Daroussin 				return ((size_t)-1);
17222b87a35SBaptiste Daroussin 			}
17322b87a35SBaptiste Daroussin 		}
17422b87a35SBaptiste Daroussin 		return (s - *src);
17522b87a35SBaptiste Daroussin 	}
17622b87a35SBaptiste Daroussin 
17722b87a35SBaptiste Daroussin 	s = *src;
17822b87a35SBaptiste Daroussin 	nchr = 0;
17922b87a35SBaptiste Daroussin 	while (len-- > 0 && nwc-- > 0) {
18022b87a35SBaptiste Daroussin 		if (*s < 0 || *s > 127) {
1812f423a26SAndrey A. Chernov 			*src = s;
18222b87a35SBaptiste Daroussin 			errno = EILSEQ;
18322b87a35SBaptiste Daroussin 			return ((size_t)-1);
18422b87a35SBaptiste Daroussin 		}
18522b87a35SBaptiste Daroussin 		if ((*dst++ = *s++) == '\0') {
18622b87a35SBaptiste Daroussin 			*src = NULL;
18722b87a35SBaptiste Daroussin 			return (nchr);
18822b87a35SBaptiste Daroussin 		}
18922b87a35SBaptiste Daroussin 		nchr++;
19022b87a35SBaptiste Daroussin 	}
19122b87a35SBaptiste Daroussin 	*src = s;
19222b87a35SBaptiste Daroussin 	return (nchr);
19322b87a35SBaptiste Daroussin }
19449c44073SBaptiste Daroussin 
195