1132497Stjr/*- 2132497Stjr * Copyright (c) 2002-2004 Tim J. Robbins. 3132497Stjr * All rights reserved. 4132497Stjr * 5227753Stheraven * Copyright (c) 2011 The FreeBSD Foundation 6227753Stheraven * All rights reserved. 7227753Stheraven * Portions of this software were developed by David Chisnall 8227753Stheraven * under sponsorship from the FreeBSD Foundation. 9227753Stheraven * 10132497Stjr * Redistribution and use in source and binary forms, with or without 11132497Stjr * modification, are permitted provided that the following conditions 12132497Stjr * are met: 13132497Stjr * 1. Redistributions of source code must retain the above copyright 14132497Stjr * notice, this list of conditions and the following disclaimer. 15132497Stjr * 2. Redistributions in binary form must reproduce the above copyright 16132497Stjr * notice, this list of conditions and the following disclaimer in the 17132497Stjr * documentation and/or other materials provided with the distribution. 18132497Stjr * 19132497Stjr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20132497Stjr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21132497Stjr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22132497Stjr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23132497Stjr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24132497Stjr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25132497Stjr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26132497Stjr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27132497Stjr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28132497Stjr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29132497Stjr * SUCH DAMAGE. 30132497Stjr */ 31132497Stjr 32132497Stjr#include <sys/cdefs.h> 33132497Stjr__FBSDID("$FreeBSD$"); 34132497Stjr 35132497Stjr#include <limits.h> 36132497Stjr#include <stdlib.h> 37132497Stjr#include <string.h> 38132497Stjr#include <wchar.h> 39132497Stjr#include "mblocal.h" 40132497Stjr 41132497Stjrsize_t 42227753Stheravenwcsnrtombs_l(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc, 43227753Stheraven size_t len, mbstate_t * __restrict ps, locale_t locale) 44227753Stheraven{ 45227753Stheraven FIX_LOCALE(locale); 46227753Stheraven if (ps == NULL) 47227753Stheraven ps = &locale->wcsnrtombs; 48227753Stheraven return (XLOCALE_CTYPE(locale)->__wcsnrtombs(dst, src, nwc, len, ps)); 49227753Stheraven} 50227753Stheravensize_t 51132497Stjrwcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc, 52132497Stjr size_t len, mbstate_t * __restrict ps) 53132497Stjr{ 54227753Stheraven return wcsnrtombs_l(dst, src, nwc, len, ps, __get_locale()); 55132497Stjr} 56132497Stjr 57227753Stheraven 58132497Stjrsize_t 59132497Stjr__wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src, 60132497Stjr size_t nwc, size_t len, mbstate_t * __restrict ps) 61132497Stjr{ 62132497Stjr mbstate_t mbsbak; 63132497Stjr char buf[MB_LEN_MAX]; 64132497Stjr const wchar_t *s; 65132497Stjr size_t nbytes; 66132497Stjr size_t nb; 67227753Stheraven struct xlocale_ctype *l = XLOCALE_CTYPE(__get_locale()); 68132497Stjr 69132497Stjr s = *src; 70132497Stjr nbytes = 0; 71132497Stjr 72132497Stjr if (dst == NULL) { 73132497Stjr while (nwc-- > 0) { 74227753Stheraven if ((nb = l->__wcrtomb(buf, *s, ps)) == (size_t)-1) 75132497Stjr /* Invalid character - wcrtomb() sets errno. */ 76132497Stjr return ((size_t)-1); 77132497Stjr else if (*s == L'\0') 78132525Stjr return (nbytes + nb - 1); 79132497Stjr s++; 80132497Stjr nbytes += nb; 81132497Stjr } 82132525Stjr return (nbytes); 83132497Stjr } 84132497Stjr 85132497Stjr while (len > 0 && nwc-- > 0) { 86132497Stjr if (len > (size_t)MB_CUR_MAX) { 87132497Stjr /* Enough space to translate in-place. */ 88227753Stheraven if ((nb = l->__wcrtomb(dst, *s, ps)) == (size_t)-1) { 89132497Stjr *src = s; 90132497Stjr return ((size_t)-1); 91132497Stjr } 92132497Stjr } else { 93132497Stjr /* 94132497Stjr * May not be enough space; use temp. buffer. 95132497Stjr * 96132497Stjr * We need to save a copy of the conversion state 97132497Stjr * here so we can restore it if the multibyte 98132497Stjr * character is too long for the buffer. 99132497Stjr */ 100132497Stjr mbsbak = *ps; 101227753Stheraven if ((nb = l->__wcrtomb(buf, *s, ps)) == (size_t)-1) { 102132497Stjr *src = s; 103132497Stjr return ((size_t)-1); 104132497Stjr } 105132497Stjr if (nb > (int)len) { 106132497Stjr /* MB sequence for character won't fit. */ 107132497Stjr *ps = mbsbak; 108132497Stjr break; 109132497Stjr } 110132497Stjr memcpy(dst, buf, nb); 111132497Stjr } 112132497Stjr if (*s == L'\0') { 113132497Stjr *src = NULL; 114132497Stjr return (nbytes + nb - 1); 115132497Stjr } 116132497Stjr s++; 117132497Stjr dst += nb; 118132497Stjr len -= nb; 119132497Stjr nbytes += nb; 120132497Stjr } 121132497Stjr *src = s; 122132497Stjr return (nbytes); 123132497Stjr} 124