xref: /openbsd/lib/libc/citrus/citrus_none.c (revision 3cab2bb3)
1 /*	$OpenBSD: citrus_none.c,v 1.9 2016/09/07 17:10:43 schwarze Exp $ */
2 /*	$NetBSD: citrus_none.c,v 1.18 2008/06/14 16:01:07 tnozaki Exp $	*/
3 
4 /*-
5  * Copyright (c)2002 Citrus Project,
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include <sys/types.h>
31 
32 #include <errno.h>
33 #include <string.h>
34 #include <wchar.h>
35 
36 #include "citrus_ctype.h"
37 
38 static char	 wrapv(unsigned char);
39 
40 
41 /*
42  * Convert an unsigned char value into a char value without relying on
43  * signed overflow behavior.
44  */
45 static char
46 wrapv(unsigned char ch)
47 {
48 	if (ch >= 0x80)
49 		return (int)ch - 0x100;
50 	else
51 		return ch;
52 }
53 
54 size_t
55 _citrus_none_ctype_mbrtowc(wchar_t * __restrict pwc,
56     const char * __restrict s, size_t n)
57 {
58 	if (s == NULL)
59 		return 0;
60 	if (n == 0)
61 		return -2;
62 	if (pwc != NULL)
63 		*pwc = (wchar_t)(unsigned char)*s;
64 	return *s != '\0';
65 }
66 
67 size_t
68 _citrus_none_ctype_mbsnrtowcs(wchar_t * __restrict dst,
69     const char ** __restrict src, size_t nmc, size_t len)
70 {
71 	size_t i;
72 
73 	if (dst == NULL)
74 		return strnlen(*src, nmc);
75 
76 	for (i = 0; i < nmc && i < len; i++)
77 		if ((dst[i] = (wchar_t)(unsigned char)(*src)[i]) == L'\0') {
78 			*src = NULL;
79 			return i;
80 		}
81 
82 	*src += i;
83 	return i;
84 }
85 
86 size_t
87 _citrus_none_ctype_wcrtomb(char * __restrict s, wchar_t wc)
88 {
89 	if (s == NULL)
90 		return 1;
91 
92 	if (wc < 0 || wc > 0xff) {
93 		errno = EILSEQ;
94 		return -1;
95 	}
96 
97 	*s = wrapv(wc);
98 	return 1;
99 }
100 
101 size_t
102 _citrus_none_ctype_wcsnrtombs(char * __restrict dst,
103     const wchar_t ** __restrict src, size_t nwc, size_t len)
104 {
105 	size_t i;
106 
107 	if (dst == NULL) {
108 		for (i = 0; i < nwc; i++) {
109 			wchar_t wc = (*src)[i];
110 			if (wc < 0 || wc > 0xff) {
111 				errno = EILSEQ;
112 				return -1;
113 			}
114 			if (wc == L'\0')
115 				return i;
116 		}
117 		return i;
118 	}
119 
120 	for (i = 0; i < nwc && i < len; i++) {
121 		wchar_t wc = (*src)[i];
122 		if (wc < 0 || wc > 0xff) {
123 			*src += i;
124 			errno = EILSEQ;
125 			return -1;
126 		}
127 		dst[i] = wrapv(wc);
128 		if (wc == L'\0') {
129 			*src = NULL;
130 			return i;
131 		}
132 	}
133 	*src += i;
134 	return i;
135 }
136