193d5af20SJoerg Sonnenberger /*- 293d5af20SJoerg Sonnenberger * Copyright (c) 2002 Tim J. Robbins 393d5af20SJoerg Sonnenberger * All rights reserved. 493d5af20SJoerg Sonnenberger * 593d5af20SJoerg Sonnenberger * Redistribution and use in source and binary forms, with or without 693d5af20SJoerg Sonnenberger * modification, are permitted provided that the following conditions 793d5af20SJoerg Sonnenberger * are met: 893d5af20SJoerg Sonnenberger * 1. Redistributions of source code must retain the above copyright 993d5af20SJoerg Sonnenberger * notice, this list of conditions and the following disclaimer. 1093d5af20SJoerg Sonnenberger * 2. Redistributions in binary form must reproduce the above copyright 1193d5af20SJoerg Sonnenberger * notice, this list of conditions and the following disclaimer in the 1293d5af20SJoerg Sonnenberger * documentation and/or other materials provided with the distribution. 1393d5af20SJoerg Sonnenberger * 1493d5af20SJoerg Sonnenberger * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1593d5af20SJoerg Sonnenberger * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1693d5af20SJoerg Sonnenberger * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1793d5af20SJoerg Sonnenberger * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1893d5af20SJoerg Sonnenberger * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1993d5af20SJoerg Sonnenberger * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2093d5af20SJoerg Sonnenberger * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2193d5af20SJoerg Sonnenberger * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2293d5af20SJoerg Sonnenberger * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2393d5af20SJoerg Sonnenberger * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2493d5af20SJoerg Sonnenberger * SUCH DAMAGE. 2593d5af20SJoerg Sonnenberger * 2693d5af20SJoerg Sonnenberger * $FreeBSD: src/lib/libc/locale/wcsftime.c,v 1.4 2004/04/07 09:47:56 tjr Exp $ 2793d5af20SJoerg Sonnenberger * $DragonFly: src/lib/libc/locale/wcsftime.c,v 1.1 2005/08/10 13:42:28 joerg Exp $ 2893d5af20SJoerg Sonnenberger */ 2993d5af20SJoerg Sonnenberger 3093d5af20SJoerg Sonnenberger #include <errno.h> 3193d5af20SJoerg Sonnenberger #include <limits.h> 3293d5af20SJoerg Sonnenberger #include <stdlib.h> 3393d5af20SJoerg Sonnenberger #include <time.h> 3493d5af20SJoerg Sonnenberger #include <wchar.h> 3593d5af20SJoerg Sonnenberger 3693d5af20SJoerg Sonnenberger /* 3793d5af20SJoerg Sonnenberger * Convert date and time to a wide-character string. 3893d5af20SJoerg Sonnenberger * 3993d5af20SJoerg Sonnenberger * This is the wide-character counterpart of strftime(). So that we do not 4093d5af20SJoerg Sonnenberger * have to duplicate the code of strftime(), we convert the format string to 4193d5af20SJoerg Sonnenberger * multibyte, call strftime(), then convert the result back into wide 4293d5af20SJoerg Sonnenberger * characters. 4393d5af20SJoerg Sonnenberger * 4493d5af20SJoerg Sonnenberger * This technique loses in the presence of stateful multibyte encoding if any 4593d5af20SJoerg Sonnenberger * of the conversions in the format string change conversion state. When 4693d5af20SJoerg Sonnenberger * stateful encoding is implemented, we will need to reset the state between 4793d5af20SJoerg Sonnenberger * format specifications in the format string. 4893d5af20SJoerg Sonnenberger */ 4993d5af20SJoerg Sonnenberger size_t 5093d5af20SJoerg Sonnenberger wcsftime(wchar_t * __restrict wcs, size_t maxsize, 5193d5af20SJoerg Sonnenberger const wchar_t * __restrict format, const struct tm * __restrict timeptr) 5293d5af20SJoerg Sonnenberger { 5393d5af20SJoerg Sonnenberger static const mbstate_t initial; 5493d5af20SJoerg Sonnenberger mbstate_t mbs; 5593d5af20SJoerg Sonnenberger char *dst, *dstp, *sformat; 56*761342f8SSascha Wildner const wchar_t *formatp; 5793d5af20SJoerg Sonnenberger size_t n, sflen; 5893d5af20SJoerg Sonnenberger int sverrno; 5993d5af20SJoerg Sonnenberger 6093d5af20SJoerg Sonnenberger sformat = dst = NULL; 6193d5af20SJoerg Sonnenberger 6293d5af20SJoerg Sonnenberger /* 6393d5af20SJoerg Sonnenberger * Convert the supplied format string to a multibyte representation 6493d5af20SJoerg Sonnenberger * for strftime(), which only handles single-byte characters. 6593d5af20SJoerg Sonnenberger */ 6693d5af20SJoerg Sonnenberger mbs = initial; 67*761342f8SSascha Wildner formatp = format; 68*761342f8SSascha Wildner sflen = wcsrtombs(NULL, &formatp, 0, &mbs); 6993d5af20SJoerg Sonnenberger if (sflen == (size_t)-1) 7093d5af20SJoerg Sonnenberger goto error; 7193d5af20SJoerg Sonnenberger if ((sformat = malloc(sflen + 1)) == NULL) 7293d5af20SJoerg Sonnenberger goto error; 7393d5af20SJoerg Sonnenberger mbs = initial; 74*761342f8SSascha Wildner wcsrtombs(sformat, &formatp, sflen + 1, &mbs); 7593d5af20SJoerg Sonnenberger 7693d5af20SJoerg Sonnenberger /* 7793d5af20SJoerg Sonnenberger * Allocate memory for longest multibyte sequence that will fit 7893d5af20SJoerg Sonnenberger * into the caller's buffer and call strftime() to fill it. 7993d5af20SJoerg Sonnenberger * Then, copy and convert the result back into wide characters in 8093d5af20SJoerg Sonnenberger * the caller's buffer. 8193d5af20SJoerg Sonnenberger */ 8293d5af20SJoerg Sonnenberger if (SIZE_T_MAX / MB_CUR_MAX <= maxsize) { 8393d5af20SJoerg Sonnenberger /* maxsize is prepostorously large - avoid int. overflow. */ 8493d5af20SJoerg Sonnenberger errno = EINVAL; 8593d5af20SJoerg Sonnenberger goto error; 8693d5af20SJoerg Sonnenberger } 8793d5af20SJoerg Sonnenberger if ((dst = malloc(maxsize * MB_CUR_MAX)) == NULL) 8893d5af20SJoerg Sonnenberger goto error; 8993d5af20SJoerg Sonnenberger if (strftime(dst, maxsize, sformat, timeptr) == 0) 9093d5af20SJoerg Sonnenberger goto error; 9193d5af20SJoerg Sonnenberger dstp = dst; 9293d5af20SJoerg Sonnenberger mbs = initial; 9393d5af20SJoerg Sonnenberger n = mbsrtowcs(wcs, (const char **)&dstp, maxsize, &mbs); 9493d5af20SJoerg Sonnenberger if (n == (size_t)-2 || n == (size_t)-1 || dstp != NULL) 9593d5af20SJoerg Sonnenberger goto error; 9693d5af20SJoerg Sonnenberger 9793d5af20SJoerg Sonnenberger free(sformat); 9893d5af20SJoerg Sonnenberger free(dst); 9993d5af20SJoerg Sonnenberger return (n); 10093d5af20SJoerg Sonnenberger 10193d5af20SJoerg Sonnenberger error: 10293d5af20SJoerg Sonnenberger sverrno = errno; 10393d5af20SJoerg Sonnenberger free(sformat); 10493d5af20SJoerg Sonnenberger free(dst); 10593d5af20SJoerg Sonnenberger errno = sverrno; 10693d5af20SJoerg Sonnenberger return (0); 10793d5af20SJoerg Sonnenberger } 108