xref: /freebsd/lib/libc/iconv/citrus_none.c (revision 1d386b48)
1 /* $NetBSD: citrus_none.c,v 1.18 2008/06/14 16:01:07 tnozaki Exp $ */
2 
3 /*-
4  * SPDX-License-Identifier: BSD-2-Clause
5  *
6  * Copyright (c) 2002 Citrus Project,
7  * Copyright (c) 2010 Gabor Kovesdan <gabor@FreeBSD.org>,
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #include <sys/types.h>
34 
35 #include <assert.h>
36 #include <errno.h>
37 #include <iconv.h>
38 #include <stddef.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <wchar.h>
43 
44 #include "citrus_namespace.h"
45 #include "citrus_types.h"
46 #include "citrus_module.h"
47 #include "citrus_none.h"
48 #include "citrus_stdenc.h"
49 
50 _CITRUS_STDENC_DECLS(NONE);
51 _CITRUS_STDENC_DEF_OPS(NONE);
52 struct _citrus_stdenc_traits _citrus_NONE_stdenc_traits = {
53 	0,	/* et_state_size */
54 	1,	/* mb_cur_max */
55 };
56 
57 static int
58 _citrus_NONE_stdenc_init(struct _citrus_stdenc * __restrict ce,
59     const void *var __unused, size_t lenvar __unused,
60     struct _citrus_stdenc_traits * __restrict et)
61 {
62 
63 	et->et_state_size = 0;
64 	et->et_mb_cur_max = 1;
65 
66 	ce->ce_closure = NULL;
67 
68 	return (0);
69 }
70 
71 static void
72 _citrus_NONE_stdenc_uninit(struct _citrus_stdenc *ce __unused)
73 {
74 
75 }
76 
77 static int
78 _citrus_NONE_stdenc_init_state(struct _citrus_stdenc * __restrict ce __unused,
79     void * __restrict ps __unused)
80 {
81 
82 	return (0);
83 }
84 
85 static int
86 _citrus_NONE_stdenc_mbtocs(struct _citrus_stdenc * __restrict ce __unused,
87     _csid_t *csid, _index_t *idx, char **s, size_t n,
88     void *ps __unused, size_t *nresult, struct iconv_hooks *hooks)
89 {
90 
91 	if (n < 1) {
92 		*nresult = (size_t)-2;
93 		return (0);
94 	}
95 
96 	*csid = 0;
97 	*idx = (_index_t)(unsigned char)*(*s)++;
98 	*nresult = *idx == 0 ? 0 : 1;
99 
100 	if ((hooks != NULL) && (hooks->uc_hook != NULL))
101 		hooks->uc_hook((unsigned int)*idx, hooks->data);
102 
103 	return (0);
104 }
105 
106 static int
107 _citrus_NONE_stdenc_cstomb(struct _citrus_stdenc * __restrict ce __unused,
108     char *s, size_t n, _csid_t csid, _index_t idx, void *ps __unused,
109     size_t *nresult, struct iconv_hooks *hooks __unused)
110 {
111 
112 	if (csid == _CITRUS_CSID_INVALID) {
113 		*nresult = 0;
114 		return (0);
115 	}
116 	if (csid != 0)
117 		return (EILSEQ);
118 
119 	if ((idx & 0x000000FF) == idx) {
120 		if (n < 1) {
121 			*nresult = (size_t)-1;
122 			return (E2BIG);
123 		}
124 		*s = (char)idx;
125 		*nresult = 1;
126 	} else if ((idx & 0x0000FFFF) == idx) {
127 		if (n < 2) {
128 			*nresult = (size_t)-1;
129 			return (E2BIG);
130 		}
131 		s[0] = (char)idx;
132 		/* XXX: might be endian dependent */
133 		s[1] = (char)(idx >> 8);
134 		*nresult = 2;
135 	} else if ((idx & 0x00FFFFFF) == idx) {
136 		if (n < 3) {
137 			*nresult = (size_t)-1;
138 			return (E2BIG);
139 		}
140 		s[0] = (char)idx;
141 		/* XXX: might be endian dependent */
142 		s[1] = (char)(idx >> 8);
143 		s[2] = (char)(idx >> 16);
144 		*nresult = 3;
145 	} else {
146 		if (n < 4) {
147 			*nresult = (size_t)-1;
148 			return (E2BIG);
149 		}
150 		s[0] = (char)idx;
151 		/* XXX: might be endian dependent */
152 		s[1] = (char)(idx >> 8);
153 		s[2] = (char)(idx >> 16);
154 		s[3] = (char)(idx >> 24);
155 		*nresult = 4;
156 	}
157 
158 	return (0);
159 }
160 
161 static int
162 _citrus_NONE_stdenc_mbtowc(struct _citrus_stdenc * __restrict ce __unused,
163     _wc_t * __restrict pwc, char ** __restrict s, size_t n,
164     void * __restrict pspriv __unused, size_t * __restrict nresult,
165     struct iconv_hooks *hooks)
166 {
167 
168 	if (*s == NULL) {
169 		*nresult = 0;
170 		return (0);
171 	}
172 	if (n == 0) {
173 		*nresult = (size_t)-2;
174 		return (0);
175 	}
176 
177 	if (pwc != NULL)
178 		*pwc = (_wc_t)(unsigned char) **s;
179 
180 	*nresult = **s == '\0' ? 0 : 1;
181 
182 	if ((hooks != NULL) && (hooks->wc_hook != NULL))
183 		hooks->wc_hook(*pwc, hooks->data);
184 
185 	return (0);
186 }
187 
188 static int
189 _citrus_NONE_stdenc_wctomb(struct _citrus_stdenc * __restrict ce __unused,
190     char * __restrict s, size_t n, _wc_t wc,
191     void * __restrict pspriv __unused, size_t * __restrict nresult,
192     struct iconv_hooks *hooks __unused)
193 {
194 
195 	if ((wc & ~0xFFU) != 0) {
196 		*nresult = (size_t)-1;
197 		return (EILSEQ);
198 	}
199 	if (n == 0) {
200 		*nresult = (size_t)-1;
201 		return (E2BIG);
202 	}
203 
204 	*nresult = 1;
205 	if (s != NULL && n > 0)
206 		*s = (char)wc;
207 
208 	return (0);
209 }
210 
211 static int
212 _citrus_NONE_stdenc_put_state_reset(struct _citrus_stdenc * __restrict ce __unused,
213     char * __restrict s __unused, size_t n __unused,
214     void * __restrict pspriv __unused, size_t * __restrict nresult)
215 {
216 
217 	*nresult = 0;
218 
219 	return (0);
220 }
221 
222 static int
223 _citrus_NONE_stdenc_get_state_desc(struct _stdenc * __restrict ce __unused,
224     void * __restrict ps __unused, int id,
225     struct _stdenc_state_desc * __restrict d)
226 {
227 	int ret = 0;
228 
229 	switch (id) {
230 	case _STDENC_SDID_GENERIC:
231 		d->u.generic.state = _STDENC_SDGEN_INITIAL;
232 		break;
233 	default:
234 		ret = EOPNOTSUPP;
235 	}
236 
237 	return (ret);
238 }
239