1 /* $NetBSD: citrus_ctype_template.h,v 1.35 2008/02/09 14:56:20 junyoung Exp $ */
2 /* $DragonFly: src/lib/libc/citrus/citrus_ctype_template.h,v 1.2 2008/04/10 10:21:01 hasso Exp $ */
6 * Copyright (c)2002 Citrus Project,
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * The Regents of the University of California. All rights reserved.
35 * This code is derived from software contributed to Berkeley by
36 * Paul Borman at Krystal Technologies.
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. Neither the name of the University nor the names of its contributors
47 * may be used to endorse or promote products derived from this software
48 * without specific prior written permission.
50 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 * CAUTION: THIS IS NOT STANDALONE FILE
67 * function templates of ctype encoding handler for each encodings.
69 * you need to define the macros below:
72 * It should convine the real function name for the method.
73 * e.g. _FUNCNAME(mbrtowc) should be expanded to
77 * _CEI_TO_STATE(cei, method) :
78 * It should be expanded to the pointer of the method-internal state
80 * e.g. _CEI_TO_STATE(cei, mbrtowc) might be expanded to
81 * (cei)->states.s_mbrtowc
82 * This structure may use if the function is called as
83 * mbrtowc(&wc, s, n, NULL);
84 * Such individual structures are needed by:
93 * These need to be keeped in the ctype encoding information structure,
97 * It should be expanded to the name of the encoding information structure.
98 * e.g. For EUC encoding, this macro is expanded to _EUCInfo.
99 * Encoding information structure need to contain the common informations
103 * It should be expanded to the name of the encoding state structure.
104 * e.g. For EUC encoding, this macro is expanded to _EUCState.
105 * Encoding state structure need to contain the context-dependent states,
106 * which are "unpacked-form" of mbstate_t type and keeped during sequent
107 * calls of mb/wc functions,
109 * _ENCODING_IS_STATE_DEPENDENT :
110 * If the encoding is state dependent, this should be expanded to
111 * non-zero integral value. Otherwise, 0.
113 * _STATE_NEEDS_EXPLICIT_INIT(ps) :
114 * some encodings, states needs some explicit initialization.
115 * (ie. initialization with memset isn't enough.)
116 * If the encoding state pointed by "ps" needs to be initialized
117 * explicitly, return non-zero. Otherwize, 0.
125 static void _FUNCNAME(init_state
)(_ENCODING_INFO
* __restrict
,
126 _ENCODING_STATE
* __restrict
);
127 static void _FUNCNAME(pack_state
)(_ENCODING_INFO
* __restrict
,
129 const _ENCODING_STATE
* __restrict
);
130 static void _FUNCNAME(unpack_state
)(_ENCODING_INFO
* __restrict
,
131 _ENCODING_STATE
* __restrict
,
132 const void * __restrict
);
133 #if _ENCODING_IS_STATE_DEPENDENT
134 static int _FUNCNAME(put_state_reset
)(_ENCODING_INFO
* __restrict
,
135 char * __restrict
, size_t,
136 _ENCODING_STATE
* __restrict
,
137 size_t * __restrict
);
141 * standard form of mbrtowc_priv.
143 * note (differences from real mbrtowc):
144 * - 3rd parameter is not "const char *s" but "const char **s".
145 * after the call of the function, *s will point the first byte of
146 * the next character.
147 * - additional 4th parameter is the size of src buffer.
148 * - 5th parameter is unpacked encoding-dependent state structure.
149 * - additional 6th parameter is the storage to be stored
150 * the return value in the real mbrtowc context.
151 * - return value means "errno" in the real mbrtowc context.
154 static int _FUNCNAME(mbrtowc_priv
)(_ENCODING_INFO
* __restrict
,
155 wchar_t * __restrict
,
156 const char ** __restrict
,
157 size_t, _ENCODING_STATE
* __restrict
,
158 size_t * __restrict
);
161 * standard form of wcrtomb_priv.
163 * note (differences from real wcrtomb):
164 * - additional 3th parameter is the size of src buffer.
165 * - 5th parameter is unpacked encoding-dependent state structure.
166 * - additional 6th parameter is the storage to be stored
167 * the return value in the real mbrtowc context.
168 * - return value means "errno" in the real wcrtomb context.
169 * - caller should ensure that 2nd parameter isn't NULL.
170 * (XXX inconsist with mbrtowc_priv)
173 static int _FUNCNAME(wcrtomb_priv
)(_ENCODING_INFO
* __restrict
,
174 char * __restrict
, size_t, wchar_t,
175 _ENCODING_STATE
* __restrict
,
176 size_t * __restrict
);
184 #define _TO_CEI(_cl_) ((_CTYPE_INFO*)(_cl_))
191 /* internal routines */
194 _FUNCNAME(mbtowc_priv
)(_ENCODING_INFO
* __restrict ei
,
195 wchar_t * __restrict pwc
, const char * __restrict s
,
196 size_t n
, _ENCODING_STATE
* __restrict psenc
,
197 int * __restrict nresult
)
199 _ENCODING_STATE state
;
203 _DIAGASSERT(ei
!= NULL
);
204 _DIAGASSERT(psenc
!= NULL
);
207 _FUNCNAME(init_state
)(ei
, psenc
);
208 *nresult
= _ENCODING_IS_STATE_DEPENDENT
;
213 err
= _FUNCNAME(mbrtowc_priv
)(ei
, pwc
, (const char **)&s
, n
, psenc
, &nr
);
214 if (nr
== (size_t)-2)
217 /* In error case, we should restore the state. */
229 _FUNCNAME(mbsrtowcs_priv
)(_ENCODING_INFO
* __restrict ei
,
230 wchar_t * __restrict pwcs
,
231 const char ** __restrict s
,
232 size_t n
, _ENCODING_STATE
* __restrict psenc
,
233 size_t * __restrict nresult
)
240 _DIAGASSERT(nresult
!= 0);
241 _DIAGASSERT(ei
!= NULL
);
242 _DIAGASSERT(psenc
!= NULL
);
243 _DIAGASSERT(s
== NULL
);
244 _DIAGASSERT(*s
== NULL
);
246 /* if pwcs is NULL, ignore n */
248 n
= 1; /* arbitrary >0 value */
251 s0
= *s
; /* to keep *s unchanged for now, use copy instead. */
252 mbcurmax
= _ENCODING_MB_CUR_MAX(ei
);
254 err
= _FUNCNAME(mbrtowc_priv
)(ei
, pwcs
, &s0
, mbcurmax
,
256 if (siz
== (size_t)-2)
265 _FUNCNAME(init_state
)(ei
, psenc
);
282 *nresult
= (size_t)cnt
;
289 _FUNCNAME(wcsrtombs_priv
)(_ENCODING_INFO
* __restrict ei
, char * __restrict s
,
290 const wchar_t ** __restrict pwcs
,
291 size_t n
, _ENCODING_STATE
* __restrict psenc
,
292 size_t * __restrict nresult
)
295 char buf
[MB_LEN_MAX
];
297 const wchar_t* pwcs0
;
298 #if _ENCODING_IS_STATE_DEPENDENT
299 _ENCODING_STATE state
;
308 #if _ENCODING_IS_STATE_DEPENDENT
311 err
= _FUNCNAME(wcrtomb_priv
)(ei
, buf
, sizeof(buf
),
312 *pwcs0
, psenc
, &siz
);
313 if (siz
== (size_t)-1) {
320 #if _ENCODING_IS_STATE_DEPENDENT
332 _FUNCNAME(init_state
)(ei
, psenc
);
335 cnt
--; /* don't include terminating null */
343 *nresult
= (size_t)cnt
;
348 /* ----------------------------------------------------------------------
349 * templates for public functions
352 #define _RESTART_BEGIN(_func_, _cei_, _pspriv_, _pse_) \
354 _ENCODING_STATE _state; \
356 if (_pspriv_ == NULL) { \
357 _pse_ = &_CEI_TO_STATE(_cei_, _func_); \
358 if (_STATE_NEEDS_EXPLICIT_INIT(_pse_)) \
359 _FUNCNAME(init_state)(_CEI_TO_EI(_cei_), \
363 _FUNCNAME(unpack_state)(_CEI_TO_EI(_cei_), \
366 } while (/*CONSTCOND*/0)
368 #define _RESTART_END(_func_, _cei_, _pspriv_, _pse_) \
369 if (_pspriv_ != NULL) { \
370 _FUNCNAME(pack_state)(_CEI_TO_EI(_cei_), _pspriv_, \
373 } while (/*CONSTCOND*/0)
376 _FUNCNAME(ctype_getops
)(_citrus_ctype_ops_rec_t
*ops
, size_t lenops
,
377 uint32_t expected_version
)
379 if (expected_version
<_CITRUS_CTYPE_ABI_VERSION
|| lenops
<sizeof(*ops
))
382 memcpy(ops
, &_FUNCNAME(ctype_ops
), sizeof(_FUNCNAME(ctype_ops
)));
388 _FUNCNAME(ctype_init
)(void ** __restrict cl
,
389 void * __restrict var
, size_t lenvar
, size_t lenps
)
393 _DIAGASSERT(cl
!= NULL
);
395 /* sanity check to avoid overruns */
396 if (sizeof(_ENCODING_STATE
) > lenps
)
399 cei
= calloc(1, sizeof(_CTYPE_INFO
));
405 return _FUNCNAME(encoding_module_init
)(_CEI_TO_EI(cei
), var
, lenvar
);
409 _FUNCNAME(ctype_uninit
)(void *cl
)
412 _FUNCNAME(encoding_module_uninit
)(_CEI_TO_EI(_TO_CEI(cl
)));
419 _FUNCNAME(ctype_get_mb_cur_max
)(void *cl
)
421 return _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl
)));
425 _FUNCNAME(ctype_mblen
)(void * __restrict cl
,
426 const char * __restrict s
, size_t n
,
427 int * __restrict nresult
)
429 _ENCODING_STATE
*psenc
;
432 _DIAGASSERT(cl
!= NULL
);
434 psenc
= &_CEI_TO_STATE(_TO_CEI(cl
), mblen
);
435 ei
= _CEI_TO_EI(_TO_CEI(cl
));
436 if (_STATE_NEEDS_EXPLICIT_INIT(psenc
))
437 _FUNCNAME(init_state
)(ei
, psenc
);
438 return _FUNCNAME(mbtowc_priv
)(ei
, NULL
, s
, n
, psenc
, nresult
);
442 _FUNCNAME(ctype_mbrlen
)(void * __restrict cl
, const char * __restrict s
,
443 size_t n
, void * __restrict pspriv
,
444 size_t * __restrict nresult
)
446 _ENCODING_STATE
*psenc
;
450 _DIAGASSERT(cl
!= NULL
);
452 ei
= _CEI_TO_EI(_TO_CEI(cl
));
453 _RESTART_BEGIN(mbrlen
, _TO_CEI(cl
), pspriv
, psenc
);
455 _FUNCNAME(init_state
)(ei
, psenc
);
458 err
= _FUNCNAME(mbrtowc_priv
)(ei
, NULL
, (const char **)&s
, n
,
459 (void *)psenc
, nresult
);
461 _RESTART_END(mbrlen
, _TO_CEI(cl
), pspriv
, psenc
);
467 _FUNCNAME(ctype_mbrtowc
)(void * __restrict cl
, wchar_t * __restrict pwc
,
468 const char * __restrict s
, size_t n
,
469 void * __restrict pspriv
, size_t * __restrict nresult
)
471 _ENCODING_STATE
*psenc
;
475 _DIAGASSERT(cl
!= NULL
);
477 ei
= _CEI_TO_EI(_TO_CEI(cl
));
478 _RESTART_BEGIN(mbrtowc
, _TO_CEI(cl
), pspriv
, psenc
);
480 _FUNCNAME(init_state
)(ei
, psenc
);
483 err
= _FUNCNAME(mbrtowc_priv
)(ei
, pwc
, (const char **)&s
, n
,
484 (void *)psenc
, nresult
);
486 _RESTART_END(mbrtowc
, _TO_CEI(cl
), pspriv
, psenc
);
493 _FUNCNAME(ctype_mbsinit
)(void * __restrict cl
, const void * __restrict pspriv
,
494 int * __restrict nresult
)
496 _ENCODING_STATE state
;
498 if (pspriv
== NULL
) {
503 _FUNCNAME(unpack_state
)(_CEI_TO_EI(_TO_CEI(cl
)), &state
, pspriv
);
505 *nresult
= (state
.chlen
== 0); /* XXX: FIXME */
511 _FUNCNAME(ctype_mbsrtowcs
)(void * __restrict cl
, wchar_t * __restrict pwcs
,
512 const char ** __restrict s
, size_t n
,
513 void * __restrict pspriv
,
514 size_t * __restrict nresult
)
516 _ENCODING_STATE
*psenc
;
520 _DIAGASSERT(cl
!= NULL
);
522 ei
= _CEI_TO_EI(_TO_CEI(cl
));
523 _RESTART_BEGIN(mbsrtowcs
, _TO_CEI(cl
), pspriv
, psenc
);
524 err
= _FUNCNAME(mbsrtowcs_priv
)(ei
, pwcs
, s
, n
, psenc
, nresult
);
525 _RESTART_END(mbsrtowcs
, _TO_CEI(cl
), pspriv
, psenc
);
531 _FUNCNAME(ctype_mbstowcs
)(void * __restrict cl
, wchar_t * __restrict pwcs
,
532 const char * __restrict s
, size_t n
,
533 size_t * __restrict nresult
)
536 _ENCODING_STATE state
;
539 _DIAGASSERT(cl
!= NULL
);
541 ei
= _CEI_TO_EI(_TO_CEI(cl
));
542 _FUNCNAME(init_state
)(ei
, &state
);
543 err
= _FUNCNAME(mbsrtowcs_priv
)(ei
, pwcs
, (const char **)&s
, n
,
545 if (*nresult
== (size_t)-2) {
547 *nresult
= (size_t)-1;
554 _FUNCNAME(ctype_mbtowc
)(void * __restrict cl
, wchar_t * __restrict pwc
,
555 const char * __restrict s
, size_t n
,
556 int * __restrict nresult
)
558 _ENCODING_STATE
*psenc
;
561 _DIAGASSERT(cl
!= NULL
);
563 psenc
= &_CEI_TO_STATE(_TO_CEI(cl
), mbtowc
);
564 ei
= _CEI_TO_EI(_TO_CEI(cl
));
565 if (_STATE_NEEDS_EXPLICIT_INIT(psenc
))
566 _FUNCNAME(init_state
)(ei
, psenc
);
567 return _FUNCNAME(mbtowc_priv
)(ei
, pwc
, s
, n
, psenc
, nresult
);
571 _FUNCNAME(ctype_wcrtomb
)(void * __restrict cl
, char * __restrict s
, wchar_t wc
,
572 void * __restrict pspriv
, size_t * __restrict nresult
)
574 _ENCODING_STATE
*psenc
;
575 char buf
[MB_LEN_MAX
];
578 #if _ENCODING_IS_STATE_DEPENDENT
582 _DIAGASSERT(cl
!= NULL
);
586 * use internal buffer.
589 wc
= L
'\0'; /* SUSv3 */
592 _RESTART_BEGIN(wcrtomb
, _TO_CEI(cl
), pspriv
, psenc
);
593 sz
= _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl
)));
594 #if _ENCODING_IS_STATE_DEPENDENT
597 err
= _FUNCNAME(put_state_reset
)(_CEI_TO_EI(_TO_CEI(cl
)), s
,
607 err
= _FUNCNAME(wcrtomb_priv
)(_CEI_TO_EI(_TO_CEI(cl
)), s
, sz
,
609 #if _ENCODING_IS_STATE_DEPENDENT
616 _RESTART_END(wcrtomb
, _TO_CEI(cl
), pspriv
, psenc
);
623 _FUNCNAME(ctype_wcsrtombs
)(void * __restrict cl
, char * __restrict s
,
624 const wchar_t ** __restrict pwcs
, size_t n
,
625 void * __restrict pspriv
,
626 size_t * __restrict nresult
)
628 _ENCODING_STATE
*psenc
;
632 _DIAGASSERT(cl
!= NULL
);
634 ei
= _CEI_TO_EI(_TO_CEI(cl
));
635 _RESTART_BEGIN(wcsrtombs
, _TO_CEI(cl
), pspriv
, psenc
);
636 err
= _FUNCNAME(wcsrtombs_priv
)(ei
, s
, pwcs
, n
, psenc
, nresult
);
637 _RESTART_END(wcsrtombs
, _TO_CEI(cl
), pspriv
, psenc
);
644 _FUNCNAME(ctype_wcstombs
)(void * __restrict cl
, char * __restrict s
,
645 const wchar_t * __restrict pwcs
, size_t n
,
646 size_t * __restrict nresult
)
648 _ENCODING_STATE state
;
652 _DIAGASSERT(cl
!= NULL
);
654 ei
= _CEI_TO_EI(_TO_CEI(cl
));
655 _FUNCNAME(init_state
)(ei
, &state
);
656 err
= _FUNCNAME(wcsrtombs_priv
)(ei
, s
, (const wchar_t **)&pwcs
, n
,
663 _FUNCNAME(ctype_wctomb
)(void * __restrict cl
, char * __restrict s
, wchar_t wc
,
664 int * __restrict nresult
)
666 _ENCODING_STATE
*psenc
;
669 #if _ENCODING_IS_STATE_DEPENDENT
674 _DIAGASSERT(cl
!= NULL
);
676 ei
= _CEI_TO_EI(_TO_CEI(cl
));
677 psenc
= &_CEI_TO_STATE(_TO_CEI(cl
), wctomb
);
678 if (_STATE_NEEDS_EXPLICIT_INIT(psenc
))
679 _FUNCNAME(init_state
)(ei
, psenc
);
681 _FUNCNAME(init_state
)(ei
, psenc
);
682 *nresult
= _ENCODING_IS_STATE_DEPENDENT
;
685 sz
= _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl
)));
686 #if _ENCODING_IS_STATE_DEPENDENT
689 err
= _FUNCNAME(put_state_reset
)(_CEI_TO_EI(_TO_CEI(cl
)), s
,
692 *nresult
= -1; /* XXX */
699 err
= _FUNCNAME(wcrtomb_priv
)(ei
, s
, sz
, wc
, psenc
, &nr
);
700 #if _ENCODING_IS_STATE_DEPENDENT
702 *nresult
= (int)(nr
+ rsz
);
712 _FUNCNAME(ctype_btowc
)(_citrus_ctype_rec_t
* __restrict cc
,
713 int c
, wint_t * __restrict wcresult
)
715 _ENCODING_STATE state
;
723 _DIAGASSERT(cc
!= NULL
&& cc
->cc_closure
!= NULL
);
729 ei
= _CEI_TO_EI(_TO_CEI(cc
->cc_closure
));
730 _FUNCNAME(init_state
)(ei
, &state
);
731 mb
= (char)(unsigned)c
;
733 err
= _FUNCNAME(mbrtowc_priv
)(ei
, &wc
, &s
, 1, &state
, &nr
);
734 if (!err
&& (nr
== 0 || nr
== 1))
735 *wcresult
= (wint_t)wc
;
744 _FUNCNAME(ctype_wctob
)(_citrus_ctype_rec_t
* __restrict cc
,
745 wint_t wc
, int * __restrict cresult
)
747 _ENCODING_STATE state
;
749 char buf
[MB_LEN_MAX
];
753 _DIAGASSERT(cc
!= NULL
&& cc
->cc_closure
!= NULL
);
759 ei
= _CEI_TO_EI(_TO_CEI(cc
->cc_closure
));
760 _FUNCNAME(init_state
)(ei
, &state
);
761 err
= _FUNCNAME(wcrtomb_priv
)(ei
, buf
, _ENCODING_MB_CUR_MAX(ei
),
762 (wchar_t)wc
, &state
, &nr
);