1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
5 * Copyright (c) 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Paul Borman at Krystal Technologies.
10 *
11 * Copyright (c) 2011 The FreeBSD Foundation
12 *
13 * Portions of this software were developed by David Chisnall
14 * under sponsorship from the FreeBSD Foundation.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 *    notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 *    notice, this list of conditions and the following disclaimer in the
23 *    documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of the University nor the names of its contributors
25 *    may be used to endorse or promote products derived from this software
26 *    without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 */
40
41#include <errno.h>
42#include <limits.h>
43#include <runetype.h>
44#include <stddef.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#include <wchar.h>
49#include "mblocal.h"
50
51static size_t	_ascii_mbrtowc(wchar_t * __restrict, const char * __restrict,
52		    size_t, mbstate_t * __restrict);
53static int	_ascii_mbsinit(const mbstate_t *);
54static size_t	_ascii_mbsnrtowcs(wchar_t * __restrict dst,
55		    const char ** __restrict src, size_t nms, size_t len,
56		    mbstate_t * __restrict ps __unused);
57static size_t	_ascii_wcrtomb(char * __restrict, wchar_t,
58		    mbstate_t * __restrict);
59static size_t	_ascii_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
60		    size_t, size_t, mbstate_t * __restrict);
61
62int
63_ascii_init(struct xlocale_ctype *l,_RuneLocale *rl)
64{
65
66	l->__mbrtowc = _ascii_mbrtowc;
67	l->__mbsinit = _ascii_mbsinit;
68	l->__mbsnrtowcs = _ascii_mbsnrtowcs;
69	l->__wcrtomb = _ascii_wcrtomb;
70	l->__wcsnrtombs = _ascii_wcsnrtombs;
71	l->runes = rl;
72	l->__mb_cur_max = 1;
73	l->__mb_sb_limit = 128;
74	return(0);
75}
76
77static int
78_ascii_mbsinit(const mbstate_t *ps __unused)
79{
80
81	/*
82	 * Encoding is not state dependent - we are always in the
83	 * initial state.
84	 */
85	return (1);
86}
87
88static size_t
89_ascii_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
90    mbstate_t * __restrict ps __unused)
91{
92
93	if (s == NULL)
94		/* Reset to initial shift state (no-op) */
95		return (0);
96	if (n == 0)
97		/* Incomplete multibyte sequence */
98		return ((size_t)-2);
99	if (*s & 0x80) {
100		errno = EILSEQ;
101		return ((size_t)-1);
102	}
103	if (pwc != NULL)
104		*pwc = (unsigned char)*s;
105	return (*s == '\0' ? 0 : 1);
106}
107
108static size_t
109_ascii_wcrtomb(char * __restrict s, wchar_t wc,
110    mbstate_t * __restrict ps __unused)
111{
112
113	if (s == NULL)
114		/* Reset to initial shift state (no-op) */
115		return (1);
116	if (wc < 0 || wc > 127) {
117		errno = EILSEQ;
118		return ((size_t)-1);
119	}
120	*s = (unsigned char)wc;
121	return (1);
122}
123
124static size_t
125_ascii_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
126    size_t nms, size_t len, mbstate_t * __restrict ps __unused)
127{
128	const char *s;
129	size_t nchr;
130
131	if (dst == NULL) {
132		for (s = *src; nms > 0 && *s != '\0'; s++, nms--) {
133			if (*s & 0x80) {
134				errno = EILSEQ;
135				return ((size_t)-1);
136			}
137		}
138		return (s - *src);
139	}
140
141	s = *src;
142	nchr = 0;
143	while (len-- > 0 && nms-- > 0) {
144		if (*s & 0x80) {
145			*src = s;
146			errno = EILSEQ;
147			return ((size_t)-1);
148		}
149		if ((*dst++ = (unsigned char)*s++) == L'\0') {
150			*src = NULL;
151			return (nchr);
152		}
153		nchr++;
154	}
155	*src = s;
156	return (nchr);
157}
158
159static size_t
160_ascii_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
161    size_t nwc, size_t len, mbstate_t * __restrict ps __unused)
162{
163	const wchar_t *s;
164	size_t nchr;
165
166	if (dst == NULL) {
167		for (s = *src; nwc > 0 && *s != L'\0'; s++, nwc--) {
168			if (*s < 0 || *s > 127) {
169				errno = EILSEQ;
170				return ((size_t)-1);
171			}
172		}
173		return (s - *src);
174	}
175
176	s = *src;
177	nchr = 0;
178	while (len-- > 0 && nwc-- > 0) {
179		if (*s < 0 || *s > 127) {
180			*src = s;
181			errno = EILSEQ;
182			return ((size_t)-1);
183		}
184		if ((*dst++ = *s++) == '\0') {
185			*src = NULL;
186			return (nchr);
187		}
188		nchr++;
189	}
190	*src = s;
191	return (nchr);
192}
193
194