1247128Sbrooks/*- 2247128Sbrooks * Copyright (c) 2013 Ed Schouten <ed@FreeBSD.org> 3247128Sbrooks * All rights reserved. 4247128Sbrooks * 5247128Sbrooks * Redistribution and use in source and binary forms, with or without 6247128Sbrooks * modification, are permitted provided that the following conditions 7247128Sbrooks * are met: 8247128Sbrooks * 1. Redistributions of source code must retain the above copyright 9247128Sbrooks * notice, this list of conditions and the following disclaimer. 10247128Sbrooks * 2. Redistributions in binary form must reproduce the above copyright 11247128Sbrooks * notice, this list of conditions and the following disclaimer in the 12247128Sbrooks * documentation and/or other materials provided with the distribution. 13247128Sbrooks * 14247128Sbrooks * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15247128Sbrooks * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16247128Sbrooks * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17247128Sbrooks * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18247128Sbrooks * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19247128Sbrooks * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20247128Sbrooks * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21247128Sbrooks * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22247128Sbrooks * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23247128Sbrooks * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24247128Sbrooks * SUCH DAMAGE. 25247128Sbrooks */ 26247128Sbrooks 27247128Sbrooks#include <sys/cdefs.h> 28247128Sbrooks__FBSDID("$FreeBSD: releng/11.0/lib/libc/locale/cXXrtomb_iconv.h 281550 2015-04-15 09:09:20Z tijl $"); 29247128Sbrooks 30247128Sbrooks#include <sys/queue.h> 31247128Sbrooks 32247128Sbrooks#include <assert.h> 33247128Sbrooks#include <errno.h> 34247128Sbrooks#include <langinfo.h> 35247128Sbrooks#include <uchar.h> 36247128Sbrooks 37247128Sbrooks#include "../iconv/citrus_hash.h" 38247128Sbrooks#include "../iconv/citrus_module.h" 39247128Sbrooks#include "../iconv/citrus_iconv.h" 40247128Sbrooks#include "xlocale_private.h" 41247128Sbrooks 42247128Sbrookstypedef struct { 43247128Sbrooks bool initialized; 44247128Sbrooks struct _citrus_iconv iconv; 45247128Sbrooks union { 46247128Sbrooks charXX_t widechar[SRCBUF_LEN]; 47247128Sbrooks char bytes[sizeof(charXX_t) * SRCBUF_LEN]; 48247128Sbrooks } srcbuf; 49247128Sbrooks size_t srcbuf_len; 50247128Sbrooks} _ConversionState; 51247128Sbrooks_Static_assert(sizeof(_ConversionState) <= sizeof(mbstate_t), 52247128Sbrooks "Size of _ConversionState must not exceed mbstate_t's size."); 53247128Sbrooks 54247128Sbrookssize_t 55247128SbrookscXXrtomb_l(char * __restrict s, charXX_t c, mbstate_t * __restrict ps, 56247128Sbrooks locale_t locale) 57247128Sbrooks{ 58247128Sbrooks _ConversionState *cs; 59247128Sbrooks struct _citrus_iconv *handle; 60247128Sbrooks char *src, *dst; 61247128Sbrooks size_t srcleft, dstleft, invlen; 62247128Sbrooks int err; 63247128Sbrooks 64247128Sbrooks FIX_LOCALE(locale); 65247128Sbrooks if (ps == NULL) 66247128Sbrooks ps = &locale->cXXrtomb; 67247128Sbrooks cs = (_ConversionState *)ps; 68247128Sbrooks handle = &cs->iconv; 69247128Sbrooks 70247128Sbrooks /* Reinitialize mbstate_t. */ 71247128Sbrooks if (s == NULL || !cs->initialized) { 72247128Sbrooks if (_citrus_iconv_open(&handle, UTF_XX_INTERNAL, 73247128Sbrooks nl_langinfo_l(CODESET, locale)) != 0) { 74247128Sbrooks cs->initialized = false; 75247128Sbrooks errno = EINVAL; 76247128Sbrooks return (-1); 77247128Sbrooks } 78247128Sbrooks handle->cv_shared->ci_discard_ilseq = true; 79247128Sbrooks handle->cv_shared->ci_hooks = NULL; 80247128Sbrooks cs->srcbuf_len = 0; 81247128Sbrooks cs->initialized = true; 82247128Sbrooks if (s == NULL) 83247128Sbrooks return (1); 84247128Sbrooks } 85247128Sbrooks 86247128Sbrooks assert(cs->srcbuf_len < sizeof(cs->srcbuf.widechar) / sizeof(charXX_t)); 87247128Sbrooks cs->srcbuf.widechar[cs->srcbuf_len++] = c; 88247128Sbrooks 89247128Sbrooks /* Perform conversion. */ 90247128Sbrooks src = cs->srcbuf.bytes; 91247128Sbrooks srcleft = cs->srcbuf_len * sizeof(charXX_t); 92247128Sbrooks dst = s; 93247128Sbrooks dstleft = MB_CUR_MAX_L(locale); 94247128Sbrooks err = _citrus_iconv_convert(handle, &src, &srcleft, &dst, &dstleft, 95247128Sbrooks 0, &invlen); 96247128Sbrooks 97247128Sbrooks /* Character is part of a surrogate pair. We need more input. */ 98247128Sbrooks if (err == EINVAL) 99247128Sbrooks return (0); 100247128Sbrooks cs->srcbuf_len = 0; 101247128Sbrooks 102247128Sbrooks /* Illegal sequence. */ 103247128Sbrooks if (dst == s) { 104247128Sbrooks errno = EILSEQ; 105247128Sbrooks return ((size_t)-1); 106247128Sbrooks } 107247128Sbrooks return (dst - s); 108247128Sbrooks} 109247128Sbrooks 110247128Sbrookssize_t 111247128SbrookscXXrtomb(char * __restrict s, charXX_t c, mbstate_t * __restrict ps) 112247128Sbrooks{ 113247128Sbrooks 114247128Sbrooks return (cXXrtomb_l(s, c, ps, __get_locale())); 115247128Sbrooks} 116247128Sbrooks