xref: /openbsd-src/lib/libc/citrus/citrus_none.c (revision 4c1e55dc91edd6e69ccc60ce855900fbc12cf34f)
1 /*	$OpenBSD: citrus_none.c,v 1.3 2012/06/06 16:58:02 matthew 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/cdefs.h>
31 #include <sys/types.h>
32 
33 #include <errno.h>
34 #include <limits.h>
35 #include <string.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <stddef.h>
39 #include <wchar.h>
40 
41 #include "citrus_ctype.h"
42 #include "citrus_none.h"
43 
44 _CITRUS_CTYPE_DEF_OPS(none);
45 
46 /*
47  * Convert an unsigned char value into a char value without relying on
48  * signed overflow behavior.
49  */
50 static inline char
51 wrapv(unsigned char ch)
52 {
53 	if (ch >= 0x80)
54 		return ((int)ch - 0x100);
55 	else
56 		return (ch);
57 }
58 
59 size_t
60 /*ARGSUSED*/
61 _citrus_none_ctype_mbrtowc(wchar_t * __restrict pwc,
62 			   const char * __restrict s, size_t n,
63 			   void * __restrict pspriv)
64 {
65 	/* pwc may be NULL */
66 	/* s may be NULL */
67 	/* pspriv appears to be unused */
68 
69 	if (s == NULL)
70 		return 0;
71 	if (n == 0)
72 		return (size_t)-2;
73 	if (pwc)
74 		*pwc = (wchar_t)(unsigned char)*s;
75 	return (*s != '\0');
76 }
77 
78 int
79 /*ARGSUSED*/
80 _citrus_none_ctype_mbsinit(const void * __restrict pspriv)
81 {
82 	return (1);  /* always initial state */
83 }
84 
85 size_t
86 /*ARGSUSED*/
87 _citrus_none_ctype_mbsnrtowcs(wchar_t * __restrict dst,
88 			      const char ** __restrict src,
89 			      size_t nmc, size_t len,
90 			      void * __restrict pspriv)
91 {
92 	size_t i;
93 
94 	/* dst may be NULL */
95 	/* pspriv appears to be unused */
96 
97 	if (dst == NULL)
98 		return strnlen(*src, nmc);
99 
100 	for (i = 0; i < nmc && i < len; i++)
101 		if ((dst[i] = (wchar_t)(unsigned char)(*src)[i]) == L'\0') {
102 			*src = NULL;
103 			return (i);
104 		}
105 
106 	*src += i;
107 	return (i);
108 }
109 
110 size_t
111 /*ARGSUSED*/
112 _citrus_none_ctype_wcrtomb(char * __restrict s,
113 			   wchar_t wc, void * __restrict pspriv)
114 {
115 	/* s may be NULL */
116 	/* ps appears to be unused */
117 
118 	if (s == NULL)
119 		return (0);
120 
121 	if (wc < 0 || wc > 0xff) {
122 		errno = EILSEQ;
123 		return (-1);
124 	}
125 
126 	*s = wrapv(wc);
127 	return (1);
128 }
129 
130 size_t
131 /*ARGSUSED*/
132 _citrus_none_ctype_wcsnrtombs(char * __restrict dst,
133 			      const wchar_t ** __restrict src,
134 			      size_t nwc, size_t len,
135 			      void * __restrict pspriv)
136 {
137 	size_t i;
138 
139 	/* dst may be NULL */
140 	/* pspriv appears to be unused */
141 
142 	if (dst == NULL) {
143 		for (i = 0; i < nwc; i++) {
144 			wchar_t wc = (*src)[i];
145 			if (wc < 0 || wc > 0xff) {
146 				errno = EILSEQ;
147 				return (-1);
148 			}
149 			if (wc == L'\0')
150 				return (i);
151 		}
152 		return (i);
153 	}
154 
155 	for (i = 0; i < nwc && i < len; i++) {
156 		wchar_t wc = (*src)[i];
157 		if (wc < 0 || wc > 0xff) {
158 			*src += i;
159 			errno = EILSEQ;
160 			return (-1);
161 		}
162 		dst[i] = wrapv(wc);
163 		if (wc == L'\0') {
164 			*src = NULL;
165 			return (i);
166 		}
167 	}
168 	*src += i;
169 	return (i);
170 }
171