Home | History | Annotate | Line # | Download | only in citrus
      1 /*	$NetBSD: citrus_ctype_fallback.c,v 1.3 2013/05/28 16:57:56 joerg Exp $	*/
      2 
      3 /*-
      4  * Copyright (c)2003 Citrus Project,
      5  * All rights reserved.
      6  *
      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.
     15  *
     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.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 #if defined(LIBC_SCCS) && !defined(lint)
     31 __RCSID("$NetBSD: citrus_ctype_fallback.c,v 1.3 2013/05/28 16:57:56 joerg Exp $");
     32 #endif /* LIBC_SCCS and not lint */
     33 
     34 #include "namespace.h"
     35 
     36 #include <sys/types.h>
     37 #include <assert.h>
     38 #include <errno.h>
     39 #include <wchar.h>
     40 #include <stdio.h>
     41 #include <string.h>
     42 #include <limits.h>
     43 
     44 #include "citrus_module.h"
     45 #include "citrus_ctype.h"
     46 #include "citrus_ctype_fallback.h"
     47 
     48 /*
     49  * for ABI version >= 0x00000002
     50  */
     51 
     52 int
     53 _citrus_ctype_btowc_fallback(_citrus_ctype_rec_t * __restrict cc,
     54 			     int c, wint_t * __restrict wcresult)
     55 {
     56 	char mb;
     57 	/*
     58 	 * what we need is _PRIVSIZE
     59 	 * and we know that it's smaller than sizeof(mbstate_t).
     60 	 */
     61 	char pspriv[sizeof(mbstate_t)];
     62 	wchar_t wc;
     63 	size_t nr;
     64 	int err;
     65 
     66 	_DIAGASSERT(cc != NULL && cc->cc_closure != NULL);
     67 
     68 	if (c == EOF) {
     69 		*wcresult = WEOF;
     70 		return 0;
     71 	}
     72 
     73 	memset(&pspriv, 0, sizeof(pspriv));
     74 	mb = (char)(unsigned)c;
     75 	err = _citrus_ctype_mbrtowc(cc, &wc, &mb, 1, (void *)&pspriv, &nr);
     76 	if (!err && (nr == 0 || nr == 1))
     77 		*wcresult = wc;
     78 	else
     79 		*wcresult = WEOF;
     80 
     81 	return 0;
     82 }
     83 
     84 int
     85 _citrus_ctype_wctob_fallback(_citrus_ctype_rec_t * __restrict cc,
     86 			     wint_t wc, int * __restrict cresult)
     87 {
     88 	/*
     89 	 * what we need is _PRIVSIZE
     90 	 * and we know that it's smaller than sizeof(mbstate_t).
     91 	 */
     92 	char pspriv[sizeof(mbstate_t)];
     93 	char buf[MB_LEN_MAX];
     94 	size_t nr;
     95 	int err;
     96 
     97 	_DIAGASSERT(cc != NULL && cc->cc_closure != NULL);
     98 
     99 	if (wc == WEOF) {
    100 		*cresult = EOF;
    101 		return 0;
    102 	}
    103 	memset(&pspriv, 0, sizeof(pspriv));
    104 	err = _citrus_ctype_wcrtomb(cc, buf, (wchar_t)wc, (void *)&pspriv, &nr);
    105 	if (!err && nr == 1)
    106 		*cresult = buf[0];
    107 	else
    108 		*cresult = EOF;
    109 
    110 	return 0;
    111 }
    112 
    113 /*
    114  * for ABI version >= 0x00000003
    115  */
    116 
    117 int
    118 _citrus_ctype_mbsnrtowcs_fallback(_citrus_ctype_rec_t * __restrict cc,
    119     wchar_t * __restrict pwcs, const char ** __restrict s, size_t in,
    120     size_t n, void * __restrict psenc, size_t * __restrict nresult)
    121 {
    122 	int err;
    123 	size_t cnt, siz;
    124 	const char *s0, *se;
    125 
    126 	_DIAGASSERT(nresult != 0);
    127 	_DIAGASSERT(psenc != NULL);
    128 	_DIAGASSERT(s != NULL);
    129 	_DIAGASSERT(*s != NULL);
    130 
    131 	/* if pwcs is NULL, ignore n */
    132 	if (pwcs == NULL)
    133 		n = 1; /* arbitrary >0 value */
    134 
    135 	err = 0;
    136 	cnt = 0;
    137 	se = *s + in;
    138 	s0 = *s; /* to keep *s unchanged for now, use copy instead. */
    139 	while (s0 < se && n > 0) {
    140 		err = _citrus_ctype_mbrtowc(cc, pwcs, s0, (size_t)(se - s0),
    141 		    psenc, &siz);
    142 		if (err) {
    143 			cnt = (size_t)-1;
    144 			goto bye;
    145 		}
    146 		if (siz == (size_t)-2) {
    147 			s0 = se;
    148 			goto bye;
    149 		}
    150 		switch (siz) {
    151 		case 0:
    152 			if (pwcs) {
    153 				size_t dum;
    154 				_citrus_ctype_mbrtowc(cc, NULL, NULL, 0, psenc,
    155 				    &dum);
    156 			}
    157 			s0 = 0;
    158 			goto bye;
    159 		default:
    160 			if (pwcs) {
    161 				pwcs++;
    162 				n--;
    163 			}
    164 			s0 += siz;
    165 			cnt++;
    166 			break;
    167 		}
    168 	}
    169 bye:
    170 	if (pwcs)
    171 		*s = s0;
    172 
    173 	*nresult = cnt;
    174 
    175 	return err;
    176 }
    177 
    178 int
    179 _citrus_ctype_wcsnrtombs_fallback(_citrus_ctype_rec_t * __restrict cc,
    180     char * __restrict s, const wchar_t ** __restrict pwcs, size_t in,
    181     size_t n, void * __restrict psenc, size_t * __restrict nresult)
    182 {
    183 	size_t cnt = 0;
    184 	int err;
    185 	char buf[MB_LEN_MAX];
    186 	size_t siz;
    187 	const wchar_t* pwcs0;
    188 	mbstate_t state;
    189 
    190 	pwcs0 = *pwcs;
    191 
    192 	if (!s)
    193 		n = 1;
    194 
    195 	while (in > 0 && n > 0) {
    196 		memcpy(&state, psenc, sizeof(state));
    197 		err = _citrus_ctype_wcrtomb(cc, buf, *pwcs0, psenc, &siz);
    198 		if (siz == (size_t)-1) {
    199 			*nresult = siz;
    200 			return (err);
    201 		}
    202 
    203 		if (s) {
    204 			if (n < siz) {
    205 				memcpy(psenc, &state, sizeof(state));
    206 				break;
    207 			}
    208 			memcpy(s, buf, siz);
    209 			s += siz;
    210 			n -= siz;
    211 		}
    212 		cnt += siz;
    213 		if (!*pwcs0) {
    214 			if (s) {
    215 				memset(psenc, 0, sizeof(state));
    216 			}
    217 			pwcs0 = 0;
    218 			cnt--; /* don't include terminating null */
    219 			break;
    220 		}
    221 		pwcs0++;
    222 		--in;
    223 	}
    224 	if (s)
    225 		*pwcs = pwcs0;
    226 
    227 	*nresult = cnt;
    228 	return (0);
    229 }
    230