wcsrtombs.c revision 129179
1102050Stjr/*- 2127944Stjr * Copyright (c) 2002-2004 Tim J. Robbins. 3102050Stjr * All rights reserved. 4102050Stjr * 5102050Stjr * Redistribution and use in source and binary forms, with or without 6102050Stjr * modification, are permitted provided that the following conditions 7102050Stjr * are met: 8102050Stjr * 1. Redistributions of source code must retain the above copyright 9102050Stjr * notice, this list of conditions and the following disclaimer. 10102050Stjr * 2. Redistributions in binary form must reproduce the above copyright 11102050Stjr * notice, this list of conditions and the following disclaimer in the 12102050Stjr * documentation and/or other materials provided with the distribution. 13102050Stjr * 14102050Stjr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15102050Stjr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16102050Stjr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17102050Stjr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18102050Stjr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19102050Stjr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20102050Stjr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21102050Stjr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22102050Stjr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23102050Stjr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24102050Stjr * SUCH DAMAGE. 25102050Stjr */ 26102050Stjr 27102050Stjr#include <sys/cdefs.h> 28102050Stjr__FBSDID("$FreeBSD: head/lib/libc/locale/wcsrtombs.c 129179 2004-05-13 11:20:27Z tjr $"); 29102050Stjr 30102050Stjr#include <limits.h> 31102050Stjr#include <stdlib.h> 32102050Stjr#include <string.h> 33102050Stjr#include <wchar.h> 34129154Stjr#include "mblocal.h" 35102050Stjr 36102050Stjrsize_t 37103012Stjrwcsrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t len, 38127944Stjr mbstate_t * __restrict ps) 39102050Stjr{ 40127944Stjr static mbstate_t mbs; 41129179Stjr 42129179Stjr if (ps == NULL) 43129179Stjr ps = &mbs; 44129179Stjr return (__wcsrtombs(dst, src, len, ps)); 45129179Stjr} 46129179Stjr 47129179Stjrsize_t 48129179Stjr__wcsrtombs_std(char * __restrict dst, const wchar_t ** __restrict src, 49129179Stjr size_t len, mbstate_t * __restrict ps) 50129179Stjr{ 51127944Stjr mbstate_t mbsbak; 52102050Stjr char buf[MB_LEN_MAX]; 53102050Stjr const wchar_t *s; 54102050Stjr size_t nbytes; 55102050Stjr int nb; 56102050Stjr 57102050Stjr s = *src; 58102050Stjr nbytes = 0; 59102050Stjr 60102050Stjr if (dst == NULL) { 61102050Stjr for (;;) { 62129154Stjr if ((nb = (int)__wcrtomb(buf, *s, ps)) < 0) 63102050Stjr /* Invalid character - wcrtomb() sets errno. */ 64102050Stjr return ((size_t)-1); 65102050Stjr else if (*s == L'\0') 66102050Stjr return (nbytes + nb - 1); 67102050Stjr s++; 68102050Stjr nbytes += nb; 69102050Stjr } 70102050Stjr /*NOTREACHED*/ 71102050Stjr } 72102050Stjr 73102050Stjr while (len > 0) { 74102050Stjr if (len > (size_t)MB_CUR_MAX) { 75102050Stjr /* Enough space to translate in-place. */ 76129154Stjr if ((nb = (int)__wcrtomb(dst, *s, ps)) < 0) { 77102050Stjr *src = s; 78102050Stjr return ((size_t)-1); 79102050Stjr } 80102050Stjr } else { 81127944Stjr /* 82127944Stjr * May not be enough space; use temp. buffer. 83127944Stjr * 84127944Stjr * We need to save a copy of the conversion state 85127944Stjr * here so we can restore it if the multibyte 86127944Stjr * character is too long for the buffer. 87127944Stjr */ 88127944Stjr mbsbak = *ps; 89129154Stjr if ((nb = (int)__wcrtomb(buf, *s, ps)) < 0) { 90102050Stjr *src = s; 91102050Stjr return ((size_t)-1); 92102050Stjr } 93127944Stjr if (nb > (int)len) { 94102050Stjr /* MB sequence for character won't fit. */ 95127944Stjr *ps = mbsbak; 96102050Stjr break; 97127944Stjr } 98102050Stjr memcpy(dst, buf, nb); 99102050Stjr } 100102050Stjr if (*s == L'\0') { 101102050Stjr *src = NULL; 102102050Stjr return (nbytes + nb - 1); 103102050Stjr } 104102050Stjr s++; 105102050Stjr dst += nb; 106102050Stjr len -= nb; 107102050Stjr nbytes += nb; 108102050Stjr } 109102050Stjr *src = s; 110102050Stjr return (nbytes); 111102050Stjr} 112