xref: /dflybsd-src/lib/libc/locale/wcsftime.c (revision 0d5acd7467c4e95f792ef49fceb3ab8e917ce86b)
193d5af20SJoerg Sonnenberger /*-
293d5af20SJoerg Sonnenberger  * Copyright (c) 2002 Tim J. Robbins
393d5af20SJoerg Sonnenberger  * All rights reserved.
493d5af20SJoerg Sonnenberger  *
5*0d5acd74SJohn Marino  * Copyright (c) 2011 The FreeBSD Foundation
6*0d5acd74SJohn Marino  * All rights reserved.
7*0d5acd74SJohn Marino  * Portions of this software were developed by David Chisnall
8*0d5acd74SJohn Marino  * under sponsorship from the FreeBSD Foundation.
9*0d5acd74SJohn Marino  *
1093d5af20SJoerg Sonnenberger  * Redistribution and use in source and binary forms, with or without
1193d5af20SJoerg Sonnenberger  * modification, are permitted provided that the following conditions
1293d5af20SJoerg Sonnenberger  * are met:
1393d5af20SJoerg Sonnenberger  * 1. Redistributions of source code must retain the above copyright
1493d5af20SJoerg Sonnenberger  *    notice, this list of conditions and the following disclaimer.
1593d5af20SJoerg Sonnenberger  * 2. Redistributions in binary form must reproduce the above copyright
1693d5af20SJoerg Sonnenberger  *    notice, this list of conditions and the following disclaimer in the
1793d5af20SJoerg Sonnenberger  *    documentation and/or other materials provided with the distribution.
1893d5af20SJoerg Sonnenberger  *
1993d5af20SJoerg Sonnenberger  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2093d5af20SJoerg Sonnenberger  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2193d5af20SJoerg Sonnenberger  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2293d5af20SJoerg Sonnenberger  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2393d5af20SJoerg Sonnenberger  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2493d5af20SJoerg Sonnenberger  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2593d5af20SJoerg Sonnenberger  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2693d5af20SJoerg Sonnenberger  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2793d5af20SJoerg Sonnenberger  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2893d5af20SJoerg Sonnenberger  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2993d5af20SJoerg Sonnenberger  * SUCH DAMAGE.
3093d5af20SJoerg Sonnenberger  *
31*0d5acd74SJohn Marino  * $FreeBSD: head/lib/libc/locale/wcsftime.c 227753 2011-11-20 14:45:42Z theraven $
3293d5af20SJoerg Sonnenberger  */
3393d5af20SJoerg Sonnenberger 
34*0d5acd74SJohn Marino 
3593d5af20SJoerg Sonnenberger #include <errno.h>
3693d5af20SJoerg Sonnenberger #include <limits.h>
3793d5af20SJoerg Sonnenberger #include <stdlib.h>
3893d5af20SJoerg Sonnenberger #include <time.h>
3993d5af20SJoerg Sonnenberger #include <wchar.h>
40*0d5acd74SJohn Marino #include "xlocale_private.h"
4193d5af20SJoerg Sonnenberger 
4293d5af20SJoerg Sonnenberger /*
4393d5af20SJoerg Sonnenberger  * Convert date and time to a wide-character string.
4493d5af20SJoerg Sonnenberger  *
4593d5af20SJoerg Sonnenberger  * This is the wide-character counterpart of strftime(). So that we do not
4693d5af20SJoerg Sonnenberger  * have to duplicate the code of strftime(), we convert the format string to
4793d5af20SJoerg Sonnenberger  * multibyte, call strftime(), then convert the result back into wide
4893d5af20SJoerg Sonnenberger  * characters.
4993d5af20SJoerg Sonnenberger  *
5093d5af20SJoerg Sonnenberger  * This technique loses in the presence of stateful multibyte encoding if any
5193d5af20SJoerg Sonnenberger  * of the conversions in the format string change conversion state. When
5293d5af20SJoerg Sonnenberger  * stateful encoding is implemented, we will need to reset the state between
5393d5af20SJoerg Sonnenberger  * format specifications in the format string.
5493d5af20SJoerg Sonnenberger  */
5593d5af20SJoerg Sonnenberger size_t
wcsftime_l(wchar_t * __restrict wcs,size_t maxsize,const wchar_t * __restrict format,const struct tm * __restrict timeptr,locale_t locale)56*0d5acd74SJohn Marino wcsftime_l(wchar_t * __restrict wcs, size_t maxsize,
57*0d5acd74SJohn Marino 	const wchar_t * __restrict format, const struct tm * __restrict timeptr,
58*0d5acd74SJohn Marino 	locale_t locale)
5993d5af20SJoerg Sonnenberger {
6093d5af20SJoerg Sonnenberger 	static const mbstate_t initial;
6193d5af20SJoerg Sonnenberger 	mbstate_t mbs;
62*0d5acd74SJohn Marino 	char *dst, *sformat;
63*0d5acd74SJohn Marino 	const char *dstp;
64761342f8SSascha Wildner 	const wchar_t *formatp;
6593d5af20SJoerg Sonnenberger 	size_t n, sflen;
6693d5af20SJoerg Sonnenberger 	int sverrno;
67*0d5acd74SJohn Marino 	FIX_LOCALE(locale);
6893d5af20SJoerg Sonnenberger 
6993d5af20SJoerg Sonnenberger 	sformat = dst = NULL;
7093d5af20SJoerg Sonnenberger 
7193d5af20SJoerg Sonnenberger 	/*
7293d5af20SJoerg Sonnenberger 	 * Convert the supplied format string to a multibyte representation
7393d5af20SJoerg Sonnenberger 	 * for strftime(), which only handles single-byte characters.
7493d5af20SJoerg Sonnenberger 	 */
7593d5af20SJoerg Sonnenberger 	mbs = initial;
76761342f8SSascha Wildner 	formatp = format;
77*0d5acd74SJohn Marino 	sflen = wcsrtombs_l(NULL, &formatp, 0, &mbs, locale);
7893d5af20SJoerg Sonnenberger 	if (sflen == (size_t)-1)
7993d5af20SJoerg Sonnenberger 		goto error;
8093d5af20SJoerg Sonnenberger 	if ((sformat = malloc(sflen + 1)) == NULL)
8193d5af20SJoerg Sonnenberger 		goto error;
8293d5af20SJoerg Sonnenberger 	mbs = initial;
83*0d5acd74SJohn Marino 	wcsrtombs_l(sformat, &formatp, sflen + 1, &mbs, locale);
8493d5af20SJoerg Sonnenberger 
8593d5af20SJoerg Sonnenberger 	/*
8693d5af20SJoerg Sonnenberger 	 * Allocate memory for longest multibyte sequence that will fit
8793d5af20SJoerg Sonnenberger 	 * into the caller's buffer and call strftime() to fill it.
8893d5af20SJoerg Sonnenberger 	 * Then, copy and convert the result back into wide characters in
8993d5af20SJoerg Sonnenberger 	 * the caller's buffer.
9093d5af20SJoerg Sonnenberger 	 */
9193d5af20SJoerg Sonnenberger 	if (SIZE_T_MAX / MB_CUR_MAX <= maxsize) {
9293d5af20SJoerg Sonnenberger 		/* maxsize is prepostorously large - avoid int. overflow. */
9393d5af20SJoerg Sonnenberger 		errno = EINVAL;
9493d5af20SJoerg Sonnenberger 		goto error;
9593d5af20SJoerg Sonnenberger 	}
9693d5af20SJoerg Sonnenberger 	if ((dst = malloc(maxsize * MB_CUR_MAX)) == NULL)
9793d5af20SJoerg Sonnenberger 		goto error;
98*0d5acd74SJohn Marino 	if (strftime_l(dst, maxsize, sformat, timeptr, locale) == 0)
9993d5af20SJoerg Sonnenberger 		goto error;
10093d5af20SJoerg Sonnenberger 	dstp = dst;
10193d5af20SJoerg Sonnenberger 	mbs = initial;
102*0d5acd74SJohn Marino 	n = mbsrtowcs_l(wcs, &dstp, maxsize, &mbs, locale);
10393d5af20SJoerg Sonnenberger 	if (n == (size_t)-2 || n == (size_t)-1 || dstp != NULL)
10493d5af20SJoerg Sonnenberger 		goto error;
10593d5af20SJoerg Sonnenberger 
10693d5af20SJoerg Sonnenberger 	free(sformat);
10793d5af20SJoerg Sonnenberger 	free(dst);
10893d5af20SJoerg Sonnenberger 	return (n);
10993d5af20SJoerg Sonnenberger 
11093d5af20SJoerg Sonnenberger error:
11193d5af20SJoerg Sonnenberger 	sverrno = errno;
11293d5af20SJoerg Sonnenberger 	free(sformat);
11393d5af20SJoerg Sonnenberger 	free(dst);
11493d5af20SJoerg Sonnenberger 	errno = sverrno;
11593d5af20SJoerg Sonnenberger 	return (0);
11693d5af20SJoerg Sonnenberger }
117*0d5acd74SJohn Marino size_t
wcsftime(wchar_t * __restrict wcs,size_t maxsize,const wchar_t * __restrict format,const struct tm * __restrict timeptr)118*0d5acd74SJohn Marino wcsftime(wchar_t * __restrict wcs, size_t maxsize,
119*0d5acd74SJohn Marino 	const wchar_t * __restrict format, const struct tm * __restrict timeptr)
120*0d5acd74SJohn Marino {
121*0d5acd74SJohn Marino 	return wcsftime_l(wcs, maxsize, format, timeptr, __get_locale());
122*0d5acd74SJohn Marino }
123