xref: /freebsd/lib/libc/locale/ascii.c (revision 559a218c9b257775fb249b67945fe4a05b7a6b9f)
149c44073SBaptiste Daroussin /*-
28a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
38a16b7a1SPedro 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
12*5b5fa75aSEd Maste  *
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 <errno.h>
4222b87a35SBaptiste Daroussin #include <limits.h>
4322b87a35SBaptiste Daroussin #include <runetype.h>
4422b87a35SBaptiste Daroussin #include <stddef.h>
4522b87a35SBaptiste Daroussin #include <stdio.h>
4622b87a35SBaptiste Daroussin #include <stdlib.h>
4722b87a35SBaptiste Daroussin #include <string.h>
4822b87a35SBaptiste Daroussin #include <wchar.h>
4922b87a35SBaptiste Daroussin #include "mblocal.h"
5022b87a35SBaptiste Daroussin 
5122b87a35SBaptiste Daroussin static size_t	_ascii_mbrtowc(wchar_t * __restrict, const char * __restrict,
5222b87a35SBaptiste Daroussin 		    size_t, mbstate_t * __restrict);
5322b87a35SBaptiste Daroussin static int	_ascii_mbsinit(const mbstate_t *);
5422b87a35SBaptiste Daroussin static size_t	_ascii_mbsnrtowcs(wchar_t * __restrict dst,
5522b87a35SBaptiste Daroussin 		    const char ** __restrict src, size_t nms, size_t len,
5622b87a35SBaptiste Daroussin 		    mbstate_t * __restrict ps __unused);
5722b87a35SBaptiste Daroussin static size_t	_ascii_wcrtomb(char * __restrict, wchar_t,
5822b87a35SBaptiste Daroussin 		    mbstate_t * __restrict);
5922b87a35SBaptiste Daroussin static size_t	_ascii_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
6022b87a35SBaptiste Daroussin 		    size_t, size_t, mbstate_t * __restrict);
6122b87a35SBaptiste Daroussin 
6222b87a35SBaptiste Daroussin int
_ascii_init(struct xlocale_ctype * l,_RuneLocale * rl)6322b87a35SBaptiste Daroussin _ascii_init(struct xlocale_ctype *l,_RuneLocale *rl)
6422b87a35SBaptiste Daroussin {
6522b87a35SBaptiste Daroussin 
6622b87a35SBaptiste Daroussin 	l->__mbrtowc = _ascii_mbrtowc;
6722b87a35SBaptiste Daroussin 	l->__mbsinit = _ascii_mbsinit;
6822b87a35SBaptiste Daroussin 	l->__mbsnrtowcs = _ascii_mbsnrtowcs;
6922b87a35SBaptiste Daroussin 	l->__wcrtomb = _ascii_wcrtomb;
7022b87a35SBaptiste Daroussin 	l->__wcsnrtombs = _ascii_wcsnrtombs;
7122b87a35SBaptiste Daroussin 	l->runes = rl;
7222b87a35SBaptiste Daroussin 	l->__mb_cur_max = 1;
7322b87a35SBaptiste Daroussin 	l->__mb_sb_limit = 128;
7422b87a35SBaptiste Daroussin 	return(0);
7522b87a35SBaptiste Daroussin }
7622b87a35SBaptiste Daroussin 
7722b87a35SBaptiste Daroussin static int
_ascii_mbsinit(const mbstate_t * ps __unused)7822b87a35SBaptiste Daroussin _ascii_mbsinit(const mbstate_t *ps __unused)
7922b87a35SBaptiste Daroussin {
8049c44073SBaptiste Daroussin 
8122b87a35SBaptiste Daroussin 	/*
8222b87a35SBaptiste Daroussin 	 * Encoding is not state dependent - we are always in the
8322b87a35SBaptiste Daroussin 	 * initial state.
8422b87a35SBaptiste Daroussin 	 */
8522b87a35SBaptiste Daroussin 	return (1);
8622b87a35SBaptiste Daroussin }
8722b87a35SBaptiste Daroussin 
8822b87a35SBaptiste Daroussin static size_t
_ascii_mbrtowc(wchar_t * __restrict pwc,const char * __restrict s,size_t n,mbstate_t * __restrict ps __unused)8922b87a35SBaptiste Daroussin _ascii_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
9022b87a35SBaptiste Daroussin     mbstate_t * __restrict ps __unused)
9122b87a35SBaptiste Daroussin {
9249c44073SBaptiste Daroussin 
9322b87a35SBaptiste Daroussin 	if (s == NULL)
9422b87a35SBaptiste Daroussin 		/* Reset to initial shift state (no-op) */
9522b87a35SBaptiste Daroussin 		return (0);
9622b87a35SBaptiste Daroussin 	if (n == 0)
9722b87a35SBaptiste Daroussin 		/* Incomplete multibyte sequence */
9822b87a35SBaptiste Daroussin 		return ((size_t)-2);
9922b87a35SBaptiste Daroussin 	if (*s & 0x80) {
10022b87a35SBaptiste Daroussin 		errno = EILSEQ;
10122b87a35SBaptiste Daroussin 		return ((size_t)-1);
10222b87a35SBaptiste Daroussin 	}
10322b87a35SBaptiste Daroussin 	if (pwc != NULL)
10422b87a35SBaptiste Daroussin 		*pwc = (unsigned char)*s;
10522b87a35SBaptiste Daroussin 	return (*s == '\0' ? 0 : 1);
10622b87a35SBaptiste Daroussin }
10722b87a35SBaptiste Daroussin 
10822b87a35SBaptiste Daroussin static size_t
_ascii_wcrtomb(char * __restrict s,wchar_t wc,mbstate_t * __restrict ps __unused)10922b87a35SBaptiste Daroussin _ascii_wcrtomb(char * __restrict s, wchar_t wc,
11022b87a35SBaptiste Daroussin     mbstate_t * __restrict ps __unused)
11122b87a35SBaptiste Daroussin {
11222b87a35SBaptiste Daroussin 
11322b87a35SBaptiste Daroussin 	if (s == NULL)
11422b87a35SBaptiste Daroussin 		/* Reset to initial shift state (no-op) */
11522b87a35SBaptiste Daroussin 		return (1);
11622b87a35SBaptiste Daroussin 	if (wc < 0 || wc > 127) {
11722b87a35SBaptiste Daroussin 		errno = EILSEQ;
11822b87a35SBaptiste Daroussin 		return ((size_t)-1);
11922b87a35SBaptiste Daroussin 	}
12022b87a35SBaptiste Daroussin 	*s = (unsigned char)wc;
12122b87a35SBaptiste Daroussin 	return (1);
12222b87a35SBaptiste Daroussin }
12322b87a35SBaptiste Daroussin 
12422b87a35SBaptiste Daroussin static size_t
_ascii_mbsnrtowcs(wchar_t * __restrict dst,const char ** __restrict src,size_t nms,size_t len,mbstate_t * __restrict ps __unused)12522b87a35SBaptiste Daroussin _ascii_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
12622b87a35SBaptiste Daroussin     size_t nms, size_t len, mbstate_t * __restrict ps __unused)
12722b87a35SBaptiste Daroussin {
12822b87a35SBaptiste Daroussin 	const char *s;
12922b87a35SBaptiste Daroussin 	size_t nchr;
13022b87a35SBaptiste Daroussin 
13122b87a35SBaptiste Daroussin 	if (dst == NULL) {
13249c44073SBaptiste Daroussin 		for (s = *src; nms > 0 && *s != '\0'; s++, nms--) {
13322b87a35SBaptiste Daroussin 			if (*s & 0x80) {
13422b87a35SBaptiste Daroussin 				errno = EILSEQ;
13522b87a35SBaptiste Daroussin 				return ((size_t)-1);
13622b87a35SBaptiste Daroussin 			}
13749c44073SBaptiste Daroussin 		}
138d3591d68SBaptiste Daroussin 		return (s - *src);
13922b87a35SBaptiste Daroussin 	}
14022b87a35SBaptiste Daroussin 
14122b87a35SBaptiste Daroussin 	s = *src;
14222b87a35SBaptiste Daroussin 	nchr = 0;
14322b87a35SBaptiste Daroussin 	while (len-- > 0 && nms-- > 0) {
14422b87a35SBaptiste Daroussin 		if (*s & 0x80) {
1452f423a26SAndrey A. Chernov 			*src = s;
14622b87a35SBaptiste Daroussin 			errno = EILSEQ;
14722b87a35SBaptiste Daroussin 			return ((size_t)-1);
14822b87a35SBaptiste Daroussin 		}
14922b87a35SBaptiste Daroussin 		if ((*dst++ = (unsigned char)*s++) == L'\0') {
15022b87a35SBaptiste Daroussin 			*src = NULL;
15122b87a35SBaptiste Daroussin 			return (nchr);
15222b87a35SBaptiste Daroussin 		}
15322b87a35SBaptiste Daroussin 		nchr++;
15422b87a35SBaptiste Daroussin 	}
15522b87a35SBaptiste Daroussin 	*src = s;
15622b87a35SBaptiste Daroussin 	return (nchr);
15722b87a35SBaptiste Daroussin }
15822b87a35SBaptiste Daroussin 
15922b87a35SBaptiste Daroussin static size_t
_ascii_wcsnrtombs(char * __restrict dst,const wchar_t ** __restrict src,size_t nwc,size_t len,mbstate_t * __restrict ps __unused)16022b87a35SBaptiste Daroussin _ascii_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
16122b87a35SBaptiste Daroussin     size_t nwc, size_t len, mbstate_t * __restrict ps __unused)
16222b87a35SBaptiste Daroussin {
16322b87a35SBaptiste Daroussin 	const wchar_t *s;
16422b87a35SBaptiste Daroussin 	size_t nchr;
16522b87a35SBaptiste Daroussin 
16622b87a35SBaptiste Daroussin 	if (dst == NULL) {
16722b87a35SBaptiste Daroussin 		for (s = *src; nwc > 0 && *s != L'\0'; s++, nwc--) {
16822b87a35SBaptiste Daroussin 			if (*s < 0 || *s > 127) {
16922b87a35SBaptiste Daroussin 				errno = EILSEQ;
17022b87a35SBaptiste Daroussin 				return ((size_t)-1);
17122b87a35SBaptiste Daroussin 			}
17222b87a35SBaptiste Daroussin 		}
17322b87a35SBaptiste Daroussin 		return (s - *src);
17422b87a35SBaptiste Daroussin 	}
17522b87a35SBaptiste Daroussin 
17622b87a35SBaptiste Daroussin 	s = *src;
17722b87a35SBaptiste Daroussin 	nchr = 0;
17822b87a35SBaptiste Daroussin 	while (len-- > 0 && nwc-- > 0) {
17922b87a35SBaptiste Daroussin 		if (*s < 0 || *s > 127) {
1802f423a26SAndrey A. Chernov 			*src = s;
18122b87a35SBaptiste Daroussin 			errno = EILSEQ;
18222b87a35SBaptiste Daroussin 			return ((size_t)-1);
18322b87a35SBaptiste Daroussin 		}
18422b87a35SBaptiste Daroussin 		if ((*dst++ = *s++) == '\0') {
18522b87a35SBaptiste Daroussin 			*src = NULL;
18622b87a35SBaptiste Daroussin 			return (nchr);
18722b87a35SBaptiste Daroussin 		}
18822b87a35SBaptiste Daroussin 		nchr++;
18922b87a35SBaptiste Daroussin 	}
19022b87a35SBaptiste Daroussin 	*src = s;
19122b87a35SBaptiste Daroussin 	return (nchr);
19222b87a35SBaptiste Daroussin }
19349c44073SBaptiste Daroussin 
194