]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libc/locale/wcsftime.c
libc/locale: don't expose nonexistant __collate_load_error
[FreeBSD/FreeBSD.git] / lib / libc / locale / wcsftime.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2002 Tim J. Robbins
5  * All rights reserved.
6  *
7  * Copyright (c) 2011 The FreeBSD Foundation
8  *
9  * Portions of this software were developed by David Chisnall
10  * under sponsorship from the FreeBSD Foundation.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #include <errno.h>
35 #include <limits.h>
36 #include <stdlib.h>
37 #include <time.h>
38 #include <wchar.h>
39 #include "xlocale_private.h"
40
41 /*
42  * Convert date and time to a wide-character string.
43  *
44  * This is the wide-character counterpart of strftime(). So that we do not
45  * have to duplicate the code of strftime(), we convert the format string to
46  * multibyte, call strftime(), then convert the result back into wide
47  * characters.
48  *
49  * This technique loses in the presence of stateful multibyte encoding if any
50  * of the conversions in the format string change conversion state. When
51  * stateful encoding is implemented, we will need to reset the state between
52  * format specifications in the format string.
53  */
54 size_t
55 wcsftime_l(wchar_t * __restrict wcs, size_t maxsize,
56         const wchar_t * __restrict format, const struct tm * __restrict timeptr,
57         locale_t locale)
58 {
59         static const mbstate_t initial;
60         mbstate_t mbs;
61         char *dst, *sformat;
62         const char *dstp;
63         const wchar_t *formatp;
64         size_t n, sflen;
65         int sverrno;
66         FIX_LOCALE(locale);
67
68         sformat = dst = NULL;
69
70         /*
71          * Convert the supplied format string to a multibyte representation
72          * for strftime(), which only handles single-byte characters.
73          */
74         mbs = initial;
75         formatp = format;
76         sflen = wcsrtombs_l(NULL, &formatp, 0, &mbs, locale);
77         if (sflen == (size_t)-1)
78                 goto error;
79         if ((sformat = malloc(sflen + 1)) == NULL)
80                 goto error;
81         mbs = initial;
82         wcsrtombs_l(sformat, &formatp, sflen + 1, &mbs, locale);
83
84         /*
85          * Allocate memory for longest multibyte sequence that will fit
86          * into the caller's buffer and call strftime() to fill it.
87          * Then, copy and convert the result back into wide characters in
88          * the caller's buffer.
89          */
90         if (SIZE_T_MAX / MB_CUR_MAX <= maxsize) {
91                 /* maxsize is prepostorously large - avoid int. overflow. */
92                 errno = EINVAL;
93                 goto error;
94         }
95         if ((dst = malloc(maxsize * MB_CUR_MAX)) == NULL)
96                 goto error;
97         if (strftime_l(dst, maxsize, sformat, timeptr, locale) == 0)
98                 goto error;
99         dstp = dst;
100         mbs = initial;
101         n = mbsrtowcs_l(wcs, &dstp, maxsize, &mbs, locale);
102         if (n == (size_t)-2 || n == (size_t)-1 || dstp != NULL)
103                 goto error;
104
105         free(sformat);
106         free(dst);
107         return (n);
108
109 error:
110         sverrno = errno;
111         free(sformat);
112         free(dst);
113         errno = sverrno;
114         return (0);
115 }
116 size_t
117 wcsftime(wchar_t * __restrict wcs, size_t maxsize,
118         const wchar_t * __restrict format, const struct tm * __restrict timeptr)
119 {
120         return wcsftime_l(wcs, maxsize, format, timeptr, __get_locale());
121 }