wcsrtombs.c revision 127944
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 127944 2004-04-06 13:14:03Z tjr $"); 29102050Stjr 30102050Stjr#include <limits.h> 31102050Stjr#include <stdlib.h> 32102050Stjr#include <string.h> 33102050Stjr#include <wchar.h> 34102050Stjr 35102050Stjrsize_t 36103012Stjrwcsrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t len, 37127944Stjr mbstate_t * __restrict ps) 38102050Stjr{ 39127944Stjr static mbstate_t mbs; 40127944Stjr mbstate_t mbsbak; 41102050Stjr char buf[MB_LEN_MAX]; 42102050Stjr const wchar_t *s; 43102050Stjr size_t nbytes; 44102050Stjr int nb; 45102050Stjr 46102050Stjr s = *src; 47102050Stjr nbytes = 0; 48102050Stjr 49127944Stjr if (ps == NULL) 50127944Stjr ps = &mbs; 51102050Stjr if (dst == NULL) { 52102050Stjr for (;;) { 53127944Stjr if ((nb = (int)wcrtomb(buf, *s, ps)) < 0) 54102050Stjr /* Invalid character - wcrtomb() sets errno. */ 55102050Stjr return ((size_t)-1); 56102050Stjr else if (*s == L'\0') 57102050Stjr return (nbytes + nb - 1); 58102050Stjr s++; 59102050Stjr nbytes += nb; 60102050Stjr } 61102050Stjr /*NOTREACHED*/ 62102050Stjr } 63102050Stjr 64102050Stjr while (len > 0) { 65102050Stjr if (len > (size_t)MB_CUR_MAX) { 66102050Stjr /* Enough space to translate in-place. */ 67127944Stjr if ((nb = (int)wcrtomb(dst, *s, ps)) < 0) { 68102050Stjr *src = s; 69102050Stjr return ((size_t)-1); 70102050Stjr } 71102050Stjr } else { 72127944Stjr /* 73127944Stjr * May not be enough space; use temp. buffer. 74127944Stjr * 75127944Stjr * We need to save a copy of the conversion state 76127944Stjr * here so we can restore it if the multibyte 77127944Stjr * character is too long for the buffer. 78127944Stjr */ 79127944Stjr mbsbak = *ps; 80127944Stjr if ((nb = (int)wcrtomb(buf, *s, ps)) < 0) { 81102050Stjr *src = s; 82102050Stjr return ((size_t)-1); 83102050Stjr } 84127944Stjr if (nb > (int)len) { 85102050Stjr /* MB sequence for character won't fit. */ 86127944Stjr *ps = mbsbak; 87102050Stjr break; 88127944Stjr } 89102050Stjr memcpy(dst, buf, nb); 90102050Stjr } 91102050Stjr if (*s == L'\0') { 92102050Stjr *src = NULL; 93102050Stjr return (nbytes + nb - 1); 94102050Stjr } 95102050Stjr s++; 96102050Stjr dst += nb; 97102050Stjr len -= nb; 98102050Stjr nbytes += nb; 99102050Stjr } 100102050Stjr *src = s; 101102050Stjr return (nbytes); 102102050Stjr} 103