wcsnrtombs.c revision 132497
1203288Srnoland/*- 2203288Srnoland * Copyright (c) 2002-2004 Tim J. Robbins. 3203288Srnoland * All rights reserved. 4203288Srnoland * 5203288Srnoland * Redistribution and use in source and binary forms, with or without 6203288Srnoland * modification, are permitted provided that the following conditions 7203288Srnoland * are met: 8203288Srnoland * 1. Redistributions of source code must retain the above copyright 9203288Srnoland * notice, this list of conditions and the following disclaimer. 10203288Srnoland * 2. Redistributions in binary form must reproduce the above copyright 11203288Srnoland * notice, this list of conditions and the following disclaimer in the 12203288Srnoland * documentation and/or other materials provided with the distribution. 13203288Srnoland * 14203288Srnoland * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15203288Srnoland * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16203288Srnoland * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17203288Srnoland * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18203288Srnoland * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19203288Srnoland * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20203288Srnoland * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21203288Srnoland * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22203288Srnoland * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23203288Srnoland * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24203288Srnoland * SUCH DAMAGE. 25203288Srnoland */ 26203288Srnoland 27203288Srnoland#include <sys/cdefs.h> 28203288Srnoland__FBSDID("$FreeBSD: head/lib/libc/locale/wcsnrtombs.c 132497 2004-07-21 10:54:57Z tjr $"); 29203288Srnoland 30203288Srnoland#include <limits.h> 31203288Srnoland#include <stdlib.h> 32203288Srnoland#include <string.h> 33203288Srnoland#include <wchar.h> 34203288Srnoland#include "mblocal.h" 35203288Srnoland 36203288Srnolandsize_t 37203288Srnolandwcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc, 38203288Srnoland size_t len, mbstate_t * __restrict ps) 39203288Srnoland{ 40203288Srnoland static mbstate_t mbs; 41203288Srnoland 42203288Srnoland if (ps == NULL) 43203288Srnoland ps = &mbs; 44203288Srnoland return (__wcsnrtombs(dst, src, nwc, len, ps)); 45203288Srnoland} 46203288Srnoland 47203288Srnolandsize_t 48203288Srnoland__wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src, 49203288Srnoland size_t nwc, size_t len, mbstate_t * __restrict ps) 50203288Srnoland{ 51203288Srnoland mbstate_t mbsbak; 52203288Srnoland char buf[MB_LEN_MAX]; 53203288Srnoland const wchar_t *s; 54203288Srnoland size_t nbytes; 55203288Srnoland size_t nb; 56203288Srnoland 57203288Srnoland s = *src; 58203288Srnoland nbytes = 0; 59203288Srnoland 60203288Srnoland if (dst == NULL) { 61203288Srnoland while (nwc-- > 0) { 62203288Srnoland if ((nb = __wcrtomb(buf, *s, ps)) == (size_t)-1) 63203288Srnoland /* Invalid character - wcrtomb() sets errno. */ 64203288Srnoland return ((size_t)-1); 65203288Srnoland else if (*s == L'\0') 66203288Srnoland break; 67203288Srnoland s++; 68203288Srnoland nbytes += nb; 69203288Srnoland } 70203288Srnoland return (nbytes + nb - 1); 71203288Srnoland } 72203288Srnoland 73203288Srnoland while (len > 0 && nwc-- > 0) { 74203288Srnoland if (len > (size_t)MB_CUR_MAX) { 75203288Srnoland /* Enough space to translate in-place. */ 76203288Srnoland if ((nb = (int)__wcrtomb(dst, *s, ps)) < 0) { 77203288Srnoland *src = s; 78203288Srnoland return ((size_t)-1); 79203288Srnoland } 80203288Srnoland } else { 81203288Srnoland /* 82203288Srnoland * May not be enough space; use temp. buffer. 83203288Srnoland * 84203288Srnoland * We need to save a copy of the conversion state 85203288Srnoland * here so we can restore it if the multibyte 86203288Srnoland * character is too long for the buffer. 87203288Srnoland */ 88203288Srnoland mbsbak = *ps; 89203288Srnoland if ((nb = (int)__wcrtomb(buf, *s, ps)) < 0) { 90203288Srnoland *src = s; 91203288Srnoland return ((size_t)-1); 92203288Srnoland } 93203288Srnoland if (nb > (int)len) { 94203288Srnoland /* MB sequence for character won't fit. */ 95203288Srnoland *ps = mbsbak; 96203288Srnoland break; 97203288Srnoland } 98203288Srnoland memcpy(dst, buf, nb); 99203288Srnoland } 100203288Srnoland if (*s == L'\0') { 101203288Srnoland *src = NULL; 102203288Srnoland return (nbytes + nb - 1); 103203288Srnoland } 104203288Srnoland s++; 105203288Srnoland dst += nb; 106203288Srnoland len -= nb; 107203288Srnoland nbytes += nb; 108203288Srnoland } 109203288Srnoland *src = s; 110203288Srnoland return (nbytes); 111203288Srnoland} 112203288Srnoland