/* $NetBSD: wcsftime.c,v 1.2 2006/10/04 14:19:16 tnozaki Exp $ */ | |
/*- | |
* Copyright (c) 2002 Tim J. Robbins | |
* All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
* are met: | |
* 1. Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* 2. Redistributions in binary form must reproduce the above copyright | |
* notice, this list of conditions and the following disclaimer in the | |
* documentation and/or other materials provided with the distribution. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
* SUCH DAMAGE. | |
*/ | |
#include <LibConfig.h> | |
#include <sys/EfiCdefs.h> | |
#if defined(LIBC_SCCS) && !defined(lint) | |
#if 0 | |
__FBSDID("$FreeBSD: src/lib/libc/locale/wcsftime.c,v 1.4 2004/04/07 09:47:56 tjr Exp $"); | |
#else | |
__RCSID("$NetBSD: wcsftime.c,v 1.2 2006/10/04 14:19:16 tnozaki Exp $"); | |
#endif | |
#endif /* LIBC_SCCS and not lint */ | |
#include <errno.h> | |
#include <limits.h> | |
#include <stdlib.h> | |
#include <time.h> | |
#include <wchar.h> | |
#include <machine/int_limits.h> | |
/* | |
* Convert date and time to a wide-character string. | |
* | |
* This is the wide-character counterpart of strftime(). So that we do not | |
* have to duplicate the code of strftime(), we convert the format string to | |
* multibyte, call strftime(), then convert the result back into wide | |
* characters. | |
* | |
* This technique loses in the presence of stateful multibyte encoding if any | |
* of the conversions in the format string change conversion state. When | |
* stateful encoding is implemented, we will need to reset the state between | |
* format specifications in the format string. | |
*/ | |
size_t | |
wcsftime(wchar_t *wcs, size_t maxsize, | |
const wchar_t *format, const struct tm *timeptr) | |
{ | |
char *dst, *dstp, *sformat; | |
size_t n, sflen; | |
int sverrno; | |
sformat = dst = NULL; | |
/* | |
* Convert the supplied format string to a multibyte representation | |
* for strftime(), which only handles single-byte characters. | |
*/ | |
sflen = wcstombs(NULL, format, 0); | |
if (sflen == (size_t)-1) | |
goto error; | |
if ((sformat = malloc(sflen + 1)) == NULL) | |
goto error; | |
wcstombs(sformat, format, sflen + 1); | |
/* | |
* Allocate memory for longest multibyte sequence that will fit | |
* into the caller's buffer and call strftime() to fill it. | |
* Then, copy and convert the result back into wide characters in | |
* the caller's buffer. | |
*/ | |
if (SIZE_T_MAX / MB_CUR_MAX <= maxsize) { | |
/* maxsize is preposturously large - avoid int. overflow. */ | |
errno = EINVAL; | |
goto error; | |
} | |
dst = malloc(maxsize * MB_CUR_MAX); | |
if (dst == NULL) | |
goto error; | |
if (strftime(dst, maxsize, sformat, timeptr) == 0) | |
goto error; | |
dstp = dst; | |
n = mbstowcs(wcs, dstp, maxsize); | |
if (n == (size_t)-2 || n == (size_t)-1) | |
goto error; | |
free(sformat); | |
free(dst); | |
return n; | |
error: | |
sverrno = errno; | |
free(sformat); | |
free(dst); | |
errno = sverrno; | |
return 0; | |
} |