Remove building with NOCRYPTO option
[minix3.git] / lib / libc / citrus / modules / citrus_gbk2k.c
blob9223e0354151cf75b0adb9070248c34193c108a3
1 /* $NetBSD: citrus_gbk2k.c,v 1.8 2013/05/28 16:57:56 joerg Exp $ */
3 /*-
4 * Copyright (c)2003 Citrus Project,
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
29 #include <sys/cdefs.h>
30 #if defined(LIBC_SCCS) && !defined(lint)
31 __RCSID("$NetBSD: citrus_gbk2k.c,v 1.8 2013/05/28 16:57:56 joerg Exp $");
32 #endif /* LIBC_SCCS and not lint */
34 #include <assert.h>
35 #include <errno.h>
36 #include <string.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <stddef.h>
40 #include <wchar.h>
41 #include <sys/types.h>
42 #include <limits.h>
44 #include "citrus_namespace.h"
45 #include "citrus_types.h"
46 #include "citrus_bcs.h"
47 #include "citrus_module.h"
48 #include "citrus_ctype.h"
49 #include "citrus_stdenc.h"
50 #include "citrus_gbk2k.h"
53 /* ----------------------------------------------------------------------
54 * private stuffs used by templates
57 typedef struct _GBK2KState {
58 char ch[4];
59 int chlen;
60 } _GBK2KState;
62 typedef struct {
63 int mb_cur_max;
64 } _GBK2KEncodingInfo;
66 typedef struct {
67 _GBK2KEncodingInfo ei;
68 struct {
69 /* for future multi-locale facility */
70 _GBK2KState s_mblen;
71 _GBK2KState s_mbrlen;
72 _GBK2KState s_mbrtowc;
73 _GBK2KState s_mbtowc;
74 _GBK2KState s_mbsrtowcs;
75 _GBK2KState s_mbsnrtowcs;
76 _GBK2KState s_wcrtomb;
77 _GBK2KState s_wcsrtombs;
78 _GBK2KState s_wcsnrtombs;
79 _GBK2KState s_wctomb;
80 } states;
81 } _GBK2KCTypeInfo;
83 #define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
84 #define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
86 #define _FUNCNAME(m) _citrus_GBK2K_##m
87 #define _ENCODING_INFO _GBK2KEncodingInfo
88 #define _CTYPE_INFO _GBK2KCTypeInfo
89 #define _ENCODING_STATE _GBK2KState
90 #define _ENCODING_MB_CUR_MAX(_ei_) (_ei_)->mb_cur_max
91 #define _ENCODING_IS_STATE_DEPENDENT 0
92 #define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
94 static __inline void
95 /*ARGSUSED*/
96 _citrus_GBK2K_init_state(_GBK2KEncodingInfo * __restrict ei,
97 _GBK2KState * __restrict s)
99 memset(s, 0, sizeof(*s));
102 static __inline void
103 /*ARGSUSED*/
104 _citrus_GBK2K_pack_state(_GBK2KEncodingInfo * __restrict ei,
105 void * __restrict pspriv,
106 const _GBK2KState * __restrict s)
108 memcpy(pspriv, (const void *)s, sizeof(*s));
111 static __inline void
112 /*ARGSUSED*/
113 _citrus_GBK2K_unpack_state(_GBK2KEncodingInfo * __restrict ei,
114 _GBK2KState * __restrict s,
115 const void * __restrict pspriv)
117 memcpy((void *)s, pspriv, sizeof(*s));
120 static __inline int
121 _mb_singlebyte(int c)
123 c &= 0xff;
124 return (c <= 0x7f);
127 static __inline int
128 _mb_leadbyte(int c)
130 c &= 0xff;
131 return (0x81 <= c && c <= 0xfe);
134 static __inline int
135 _mb_trailbyte(int c)
137 c &= 0xff;
138 return ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfe));
141 static __inline int
142 _mb_surrogate(int c)
144 c &= 0xff;
145 return (0x30 <= c && c <= 0x39);
148 static __inline int
149 _mb_count(wchar_t v)
151 u_int32_t c;
153 c = (u_int32_t)v; /* XXX */
154 if (!(c & 0xffffff00))
155 return (1);
156 if (!(c & 0xffff0000))
157 return (2);
158 return (4);
161 #define _PSENC (psenc->ch[psenc->chlen - 1])
162 #define _PUSH_PSENC(c) (psenc->ch[psenc->chlen++] = (c))
164 static int
165 _citrus_GBK2K_mbrtowc_priv(_GBK2KEncodingInfo * __restrict ei,
166 wchar_t * __restrict pwc,
167 const char ** __restrict s, size_t n,
168 _GBK2KState * __restrict psenc,
169 size_t * __restrict nresult)
171 int chlenbak, len;
172 const char *s0, *s1;
173 wchar_t wc;
175 _DIAGASSERT(ei != NULL);
176 /* pwc may be NULL */
177 _DIAGASSERT(s != NULL);
178 _DIAGASSERT(psenc != NULL);
180 s0 = *s;
182 if (s0 == NULL) {
183 /* _citrus_GBK2K_init_state(ei, psenc); */
184 psenc->chlen = 0;
185 *nresult = 0;
186 return (0);
189 chlenbak = psenc->chlen;
191 switch (psenc->chlen) {
192 case 3:
193 if (!_mb_leadbyte (_PSENC))
194 goto invalid;
195 /* FALLTHROUGH */
196 case 2:
197 if (!_mb_surrogate(_PSENC) || _mb_trailbyte(_PSENC))
198 goto invalid;
199 /* FALLTHROUGH */
200 case 1:
201 if (!_mb_leadbyte (_PSENC))
202 goto invalid;
203 /* FALLTHOROUGH */
204 case 0:
205 break;
206 default:
207 goto invalid;
210 for (;;) {
211 if (n-- < 1)
212 goto restart;
214 _PUSH_PSENC(*s0++);
216 switch (psenc->chlen) {
217 case 1:
218 if (_mb_singlebyte(_PSENC))
219 goto convert;
220 if (_mb_leadbyte (_PSENC))
221 continue;
222 goto ilseq;
223 case 2:
224 if (_mb_trailbyte (_PSENC))
225 goto convert;
226 if (ei->mb_cur_max == 4 &&
227 _mb_surrogate (_PSENC))
228 continue;
229 goto ilseq;
230 case 3:
231 if (_mb_leadbyte (_PSENC))
232 continue;
233 goto ilseq;
234 case 4:
235 if (_mb_surrogate (_PSENC))
236 goto convert;
237 goto ilseq;
241 convert:
242 len = psenc->chlen;
243 s1 = &psenc->ch[0];
244 wc = 0;
245 while (len-- > 0)
246 wc = (wc << 8) | (*s1++ & 0xff);
248 if (pwc != NULL)
249 *pwc = wc;
250 *s = s0;
251 *nresult = (wc == 0) ? 0 : psenc->chlen - chlenbak;
252 /* _citrus_GBK2K_init_state(ei, psenc); */
253 psenc->chlen = 0;
255 return (0);
257 restart:
258 *s = s0;
259 *nresult = (size_t)-2;
261 return (0);
263 invalid:
264 return (EINVAL);
266 ilseq:
267 *nresult = (size_t)-1;
268 return (EILSEQ);
271 static int
272 _citrus_GBK2K_wcrtomb_priv(_GBK2KEncodingInfo * __restrict ei,
273 char * __restrict s, size_t n, wchar_t wc,
274 _GBK2KState * __restrict psenc,
275 size_t * __restrict nresult)
277 int len, ret;
279 _DIAGASSERT(ei != NULL);
280 _DIAGASSERT(s != NULL);
281 _DIAGASSERT(psenc != NULL);
283 if (psenc->chlen != 0) {
284 ret = EINVAL;
285 goto err;
288 len = _mb_count(wc);
289 if (n < len) {
290 ret = E2BIG;
291 goto err;
294 switch (len) {
295 case 1:
296 if (!_mb_singlebyte(_PUSH_PSENC(wc ))) {
297 ret = EILSEQ;
298 goto err;
300 break;
301 case 2:
302 if (!_mb_leadbyte (_PUSH_PSENC(wc >> 8)) ||
303 !_mb_trailbyte (_PUSH_PSENC(wc ))) {
304 ret = EILSEQ;
305 goto err;
307 break;
308 case 4:
309 if (ei->mb_cur_max != 4 ||
310 !_mb_leadbyte (_PUSH_PSENC(wc >> 24)) ||
311 !_mb_surrogate (_PUSH_PSENC(wc >> 16)) ||
312 !_mb_leadbyte (_PUSH_PSENC(wc >> 8)) ||
313 !_mb_surrogate (_PUSH_PSENC(wc ))) {
314 ret = EILSEQ;
315 goto err;
317 break;
320 _DIAGASSERT(len == psenc->chlen);
322 memcpy(s, psenc->ch, psenc->chlen);
323 *nresult = psenc->chlen;
324 /* _citrus_GBK2K_init_state(ei, psenc); */
325 psenc->chlen = 0;
327 return (0);
329 err:
330 *nresult = (size_t)-1;
331 return ret;
334 static __inline int
335 /*ARGSUSED*/
336 _citrus_GBK2K_stdenc_wctocs(_GBK2KEncodingInfo * __restrict ei,
337 _csid_t * __restrict csid,
338 _index_t * __restrict idx, wchar_t wc)
340 u_int8_t ch, cl;
342 _DIAGASSERT(csid != NULL && idx != NULL);
344 if ((u_int32_t)wc<0x80) {
345 /* ISO646 */
346 *csid = 0;
347 *idx = (_index_t)wc;
348 } else if ((u_int32_t)wc>=0x10000) {
349 /* GBKUCS : XXX */
350 *csid = 3;
351 *idx = (_index_t)wc;
352 } else {
353 ch = (u_int8_t)(wc >> 8);
354 cl = (u_int8_t)wc;
355 if (ch>=0xA1 && cl>=0xA1) {
356 /* EUC G1 */
357 *csid = 1;
358 *idx = (_index_t)wc & 0x7F7FU;
359 } else {
360 /* extended area (0x8140-) */
361 *csid = 2;
362 *idx = (_index_t)wc;
366 return 0;
369 static __inline int
370 /*ARGSUSED*/
371 _citrus_GBK2K_stdenc_cstowc(_GBK2KEncodingInfo * __restrict ei,
372 wchar_t * __restrict wc,
373 _csid_t csid, _index_t idx)
376 _DIAGASSERT(wc != NULL);
378 switch (csid) {
379 case 0:
380 /* ISO646 */
381 *wc = (wchar_t)idx;
382 break;
383 case 1:
384 /* EUC G1 */
385 *wc = (wchar_t)idx | 0x8080U;
386 break;
387 case 2:
388 /* extended area */
389 *wc = (wchar_t)idx;
390 break;
391 case 3:
392 /* GBKUCS : XXX */
393 if (ei->mb_cur_max != 4)
394 return EINVAL;
395 *wc = (wchar_t)idx;
396 break;
397 default:
398 return EILSEQ;
401 return 0;
404 static __inline int
405 /*ARGSUSED*/
406 _citrus_GBK2K_stdenc_get_state_desc_generic(_GBK2KEncodingInfo * __restrict ei,
407 _GBK2KState * __restrict psenc,
408 int * __restrict rstate)
411 if (psenc->chlen == 0)
412 *rstate = _STDENC_SDGEN_INITIAL;
413 else
414 *rstate = _STDENC_SDGEN_INCOMPLETE_CHAR;
416 return 0;
419 static int
420 /*ARGSUSED*/
421 _citrus_GBK2K_encoding_module_init(_GBK2KEncodingInfo * __restrict ei,
422 const void * __restrict var, size_t lenvar)
424 const char *p;
426 _DIAGASSERT(ei != NULL);
428 p = var;
429 #define MATCH(x, act) \
430 do { \
431 if (lenvar >= (sizeof(#x)-1) && \
432 _bcs_strncasecmp(p, #x, sizeof(#x)-1) == 0) { \
433 act; \
434 lenvar -= sizeof(#x)-1; \
435 p += sizeof(#x)-1; \
437 } while (/*CONSTCOND*/0)
438 memset((void *)ei, 0, sizeof(*ei));
439 ei->mb_cur_max = 4;
440 while (lenvar>0) {
441 switch (_bcs_tolower(*p)) {
442 case '2':
443 MATCH("2byte", ei->mb_cur_max = 2);
444 break;
446 p++;
447 lenvar--;
450 return (0);
453 static void
454 /*ARGSUSED*/
455 _citrus_GBK2K_encoding_module_uninit(_GBK2KEncodingInfo *ei)
460 /* ----------------------------------------------------------------------
461 * public interface for ctype
464 _CITRUS_CTYPE_DECLS(GBK2K);
465 _CITRUS_CTYPE_DEF_OPS(GBK2K);
467 #include "citrus_ctype_template.h"
469 /* ----------------------------------------------------------------------
470 * public interface for stdenc
473 _CITRUS_STDENC_DECLS(GBK2K);
474 _CITRUS_STDENC_DEF_OPS(GBK2K);
476 #include "citrus_stdenc_template.h"