wcsrtombs.c revision 102050
1193326Sed/*-
2193326Sed * Copyright (c) 2002 Tim J. Robbins.
3193326Sed * All rights reserved.
4193326Sed *
5193326Sed * Redistribution and use in source and binary forms, with or without
6193326Sed * modification, are permitted provided that the following conditions
7193326Sed * are met:
8193326Sed * 1. Redistributions of source code must retain the above copyright
9193326Sed *    notice, this list of conditions and the following disclaimer.
10193326Sed * 2. Redistributions in binary form must reproduce the above copyright
11193326Sed *    notice, this list of conditions and the following disclaimer in the
12193326Sed *    documentation and/or other materials provided with the distribution.
13193326Sed *
14193326Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15193326Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16193326Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17193326Sed * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18193326Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19204643Srdivacky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20210299Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21198092Srdivacky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22204643Srdivacky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23193326Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24210299Sed * SUCH DAMAGE.
25198092Srdivacky */
26193326Sed
27221345Sdim#include <sys/cdefs.h>
28239462Sdim__FBSDID("$FreeBSD: head/lib/libc/locale/wcsrtombs.c 102050 2002-08-18 06:30:10Z tjr $");
29234353Sdim
30234353Sdim#include <errno.h>
31234353Sdim#include <limits.h>
32234353Sdim#include <stdlib.h>
33234353Sdim#include <string.h>
34234353Sdim#include <wchar.h>
35234353Sdim
36239462Sdimsize_t
37234353Sdimwcsrtombs(char *__restrict dst, const wchar_t **__restrict src, size_t len,
38227737Sdim    mbstate_t *__restrict ps __unused)
39212904Sdim{
40212904Sdim	char buf[MB_LEN_MAX];
41193326Sed	const wchar_t *s;
42193326Sed	size_t nbytes;
43193326Sed	int nb;
44199482Srdivacky
45193326Sed	s = *src;
46223017Sdim	nbytes = 0;
47206084Srdivacky
48212904Sdim	if (dst == NULL) {
49223017Sdim		for (;;) {
50223017Sdim			if ((nb = (int)wcrtomb(buf, *s, NULL)) < 0)
51212904Sdim				/* Invalid character - wcrtomb() sets errno. */
52218893Sdim				return ((size_t)-1);
53212904Sdim			else if (*s == L'\0')
54212904Sdim				return (nbytes + nb - 1);
55212904Sdim			s++;
56218893Sdim			nbytes += nb;
57218893Sdim		}
58193326Sed		/*NOTREACHED*/
59193326Sed	}
60194613Sed
61239462Sdim	while (len > 0) {
62239462Sdim		if (len > (size_t)MB_CUR_MAX) {
63239462Sdim			/* Enough space to translate in-place. */
64193380Sed			if ((nb = (int)wcrtomb(dst, *s, NULL)) < 0) {
65193326Sed				*src = s;
66239462Sdim				return ((size_t)-1);
67239462Sdim			}
68193326Sed		} else {
69193326Sed			/* May not be enough space; use temp. buffer. */
70193326Sed			if ((nb = (int)wcrtomb(buf, *s, NULL)) < 0) {
71193326Sed				*src = s;
72234353Sdim				return ((size_t)-1);
73234353Sdim			}
74234353Sdim			if (nb > (int)len)
75234353Sdim				/* MB sequence for character won't fit. */
76234353Sdim				break;
77234353Sdim			memcpy(dst, buf, nb);
78234353Sdim		}
79234353Sdim		if (*s == L'\0') {
80234353Sdim			*src = NULL;
81234353Sdim			return (nbytes + nb - 1);
82234353Sdim		}
83226633Sdim		s++;
84226633Sdim		dst += nb;
85208600Srdivacky		len -= nb;
86226633Sdim		nbytes += nb;
87234353Sdim	}
88234353Sdim	*src = s;
89226633Sdim	return (nbytes);
90226633Sdim}
91234353Sdim