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