1 /* $NetBSD: citrus_zw.c,v 1.3 2006/11/24 17:27:52 tnozaki Exp $ */
4 * Copyright (c)2004, 2006 Citrus Project,
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
30 #include <sys/cdefs.h>
31 #if defined(LIB_SCCS) && !defined(lint)
32 __RCSID("$NetBSD: citrus_zw.c,v 1.3 2006/11/24 17:27:52 tnozaki Exp $");
33 #endif /* LIB_SCCS and not lint */
35 #include <sys/types.h>
46 #include "citrus_namespace.h"
47 #include "citrus_types.h"
48 #include "citrus_module.h"
49 #include "citrus_ctype.h"
50 #include "citrus_stdenc.h"
51 #include "citrus_zw.h"
53 /* ----------------------------------------------------------------------
54 * private stuffs used by templates
62 NONE
, AMBIGIOUS
, ASCII
, GB2312
74 /* for future multi-locale facility */
86 #define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
87 #define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
89 #define _FUNCNAME(m) _citrus_ZW_##m
90 #define _ENCODING_INFO _ZWEncodingInfo
91 #define _CTYPE_INFO _ZWCTypeInfo
92 #define _ENCODING_STATE _ZWState
93 #define _ENCODING_MB_CUR_MAX(_ei_) MB_LEN_MAX
94 #define _ENCODING_IS_STATE_DEPENDENT 1
95 #define _STATE_NEEDS_EXPLICIT_INIT(_ps_) ((_ps_)->charset != NONE)
99 _citrus_ZW_init_state(_ZWEncodingInfo
* __restrict ei
,
100 _ZWState
* __restrict psenc
)
102 /* ei my be unused */
103 _DIAGASSERT(psenc
!= NULL
);
106 psenc
->charset
= NONE
;
111 _citrus_ZW_pack_state(_ZWEncodingInfo
* __restrict ei
,
112 void *__restrict pspriv
, const _ZWState
* __restrict psenc
)
114 /* ei may be unused */
115 _DIAGASSERT(pspriv
!= NULL
);
116 _DIAGASSERT(psenc
!= NULL
);
118 memcpy(pspriv
, (const void *)psenc
, sizeof(*psenc
));
123 _citrus_ZW_unpack_state(_ZWEncodingInfo
* __restrict ei
,
124 _ZWState
* __restrict psenc
, const void * __restrict pspriv
)
126 /* ei may be unused */
127 _DIAGASSERT(psenc
!= NULL
);
128 _DIAGASSERT(pspriv
!= NULL
);
130 memcpy((void *)psenc
, pspriv
, sizeof(*psenc
));
134 _citrus_ZW_mbrtowc_priv(_ZWEncodingInfo
* __restrict ei
,
135 wchar_t * __restrict pwc
, const char **__restrict s
, size_t n
,
136 _ZWState
* __restrict psenc
, size_t * __restrict nresult
)
142 /* ei may be unused */
143 /* pwc may be null */
144 _DIAGASSERT(s
!= NULL
);
145 _DIAGASSERT(psenc
!= NULL
);
146 _DIAGASSERT(nresult
!= NULL
);
149 _citrus_ZW_init_state(ei
, psenc
);
150 *nresult
= (size_t)_ENCODING_IS_STATE_DEPENDENT
;
159 *nresult = (size_t)-2; \
163 ch = (unsigned char)*s0++; \
164 if (len++ > MB_LEN_MAX || ch > 0x7F)\
166 psenc->ch[psenc->chlen++] = ch; \
167 } while (/*CONSTCOND*/0)
170 switch (psenc
->charset
) {
172 switch (psenc
->chlen
) {
175 switch (psenc
->ch
[0]) {
176 case '\0': case '\n':
177 psenc
->charset
= NONE
;
185 ch
= (unsigned char)psenc
->ch
[0];
192 if (psenc
->chlen
!= 0)
195 ch
= (unsigned char)psenc
->ch
[0];
197 if (ch
!= '\n' && ch
!= '\0')
198 psenc
->charset
= ASCII
;
203 psenc
->charset
= AMBIGIOUS
;
207 if (psenc
->chlen
!= 0)
210 if (psenc
->ch
[0] != 'W') {
211 psenc
->charset
= ASCII
;
215 psenc
->charset
= GB2312
;
219 switch (psenc
->chlen
) {
222 ch
= (unsigned char)psenc
->ch
[0];
224 psenc
->charset
= NONE
;
228 } else if (ch
== '\n') {
229 psenc
->charset
= NONE
;
236 if (psenc
->ch
[0] == ' ') {
237 ch
= (unsigned char)psenc
->ch
[1];
241 } else if (psenc
->ch
[0] == '#') {
242 ch
= (unsigned char)psenc
->ch
[1];
244 psenc
->charset
= NONE
;
248 } else if (ch
== ' ') {
254 ch
= (unsigned char)psenc
->ch
[0];
255 if (ch
< 0x21 || ch
> 0x7E)
257 wc
= (wchar_t)(ch
<< 8);
258 ch
= (unsigned char)psenc
->ch
[1];
259 if (ch
< 0x21 || ch
> 0x7E) {
261 *nresult
= (size_t)-1;
277 *nresult
= (size_t)(wc
== 0 ? 0 : len
);
285 _citrus_ZW_wcrtomb_priv(_ZWEncodingInfo
* __restrict ei
,
286 char *__restrict s
, size_t n
, wchar_t wc
,
287 _ZWState
* __restrict psenc
, size_t * __restrict nresult
)
292 _DIAGASSERT(s
!= NULL
);
293 _DIAGASSERT(psenc
!= NULL
);
294 _DIAGASSERT(nresult
!= NULL
);
296 if (psenc
->chlen
!= 0)
298 if ((uint32_t)wc
<= 0x7F) {
299 ch
= (unsigned char)wc
;
300 switch (psenc
->charset
) {
302 if (ch
== '\0' || ch
== '\n') {
303 psenc
->ch
[psenc
->chlen
++] = ch
;
308 psenc
->ch
[psenc
->chlen
++] = 'z';
309 psenc
->ch
[psenc
->chlen
++] = 'W';
310 psenc
->ch
[psenc
->chlen
++] = ' ';
311 psenc
->ch
[psenc
->chlen
++] = ch
;
312 psenc
->charset
= GB2312
;
320 psenc
->ch
[psenc
->chlen
++] = '\n';
321 psenc
->ch
[psenc
->chlen
++] = '\0';
322 psenc
->charset
= NONE
;
323 } else if (ch
== '\n') {
324 psenc
->ch
[psenc
->chlen
++] = '#';
325 psenc
->ch
[psenc
->chlen
++] = '\n';
326 psenc
->charset
= NONE
;
328 psenc
->ch
[psenc
->chlen
++] = ' ';
329 psenc
->ch
[psenc
->chlen
++] = ch
;
335 } else if ((uint32_t)wc
<= 0x7E7E) {
336 switch (psenc
->charset
) {
341 psenc
->ch
[psenc
->chlen
++] = 'z';
342 psenc
->ch
[psenc
->chlen
++] = 'W';
343 psenc
->charset
= GB2312
;
349 ch
= (wc
>> 8) & 0xFF;
350 if (ch
< 0x21 || ch
> 0x7E)
352 psenc
->ch
[psenc
->chlen
++] = ch
;
354 if (ch
< 0x21 || ch
> 0x7E)
356 psenc
->ch
[psenc
->chlen
++] = ch
;
363 *nresult
= (size_t)-1;
366 memcpy(s
, psenc
->ch
, psenc
->chlen
);
367 *nresult
= psenc
->chlen
;
375 _citrus_ZW_put_state_reset(_ZWEncodingInfo
* __restrict ei
,
376 char * __restrict s
, size_t n
,
377 _ZWState
* __restrict psenc
, size_t * __restrict nresult
)
379 /* ei may be unused */
380 _DIAGASSERT(s
!= NULL
);
381 _DIAGASSERT(psenc
!= NULL
);
382 _DIAGASSERT(nresult
!= NULL
);
384 if (psenc
->chlen
!= 0)
386 switch (psenc
->charset
) {
390 psenc
->ch
[psenc
->chlen
++] = '\n';
391 psenc
->charset
= NONE
;
394 *nresult
= psenc
->chlen
;
395 if (psenc
->chlen
> 0) {
396 memcpy(s
, psenc
->ch
, psenc
->chlen
);
409 _citrus_ZW_stdenc_get_state_desc_generic(_ZWEncodingInfo
* __restrict ei
,
410 _ZWState
* __restrict psenc
, int * __restrict rstate
)
412 /* ei may be unused */
413 _DIAGASSERT(psenc
!= NULL
);
414 _DIAGASSERT(rstate
!= NULL
);
416 switch (psenc
->charset
) {
418 if (psenc
->chlen
!= 0)
420 *rstate
= _STDENC_SDGEN_INITIAL
;
423 if (psenc
->chlen
!= 0)
425 *rstate
= _STDENC_SDGEN_INCOMPLETE_SHIFT
;
429 switch (psenc
->chlen
) {
431 *rstate
= _STDENC_SDGEN_STABLE
;
434 *rstate
= (psenc
->ch
[0] == '#')
435 ? _STDENC_SDGEN_INCOMPLETE_SHIFT
436 : _STDENC_SDGEN_INCOMPLETE_CHAR
;
450 _citrus_ZW_stdenc_wctocs(_ZWEncodingInfo
* __restrict ei
,
451 _csid_t
* __restrict csid
, _index_t
* __restrict idx
, wchar_t wc
)
453 /* ei seems to be unused */
454 _DIAGASSERT(csid
!= NULL
);
455 _DIAGASSERT(idx
!= NULL
);
457 *csid
= (_csid_t
)(wc
<= 0x7FU
) ? 0 : 1;
465 _citrus_ZW_stdenc_cstowc(_ZWEncodingInfo
* __restrict ei
,
466 wchar_t * __restrict wc
, _csid_t csid
, _index_t idx
)
468 /* ei seems to be unused */
469 _DIAGASSERT(wc
!= NULL
);
484 _citrus_ZW_encoding_module_uninit(_ZWEncodingInfo
*ei
)
490 _citrus_ZW_encoding_module_init(_ZWEncodingInfo
* __restrict ei
,
491 const void *__restrict var
, size_t lenvar
)
496 /* ----------------------------------------------------------------------
497 * public interface for ctype
500 _CITRUS_CTYPE_DECLS(ZW
);
501 _CITRUS_CTYPE_DEF_OPS(ZW
);
503 #include "citrus_ctype_template.h"
505 /* ----------------------------------------------------------------------
506 * public interface for stdenc
509 _CITRUS_STDENC_DECLS(ZW
);
510 _CITRUS_STDENC_DEF_OPS(ZW
);
512 #include "citrus_stdenc_template.h"