xref: /reactos/sdk/lib/ucrt/locale/inittime.cpp (revision 04e0dc4a)
1 //
2 // inittime.cpp
3 //
4 //      Copyright (c) Microsoft Corporation.  All rights reserved.
5 //
6 // Functionality for initializing and destroying LC_TIME category data structures
7 //
8 #include <corecrt_internal.h>
9 #include <locale.h>
10 #include <stdlib.h>
11 
12 
13 // Enclaves have no ability to create new locales.
14 #ifndef _UCRT_ENCLAVE_BUILD
15 
16 _Success_(return != false)
initialize_lc_time(_Inout_ __crt_lc_time_data * const lc_time,_In_ __crt_locale_data * const locale_data)17 static bool __cdecl initialize_lc_time(
18     _Inout_ __crt_lc_time_data* const lc_time,
19     _In_    __crt_locale_data*  const locale_data
20     ) throw()
21 {
22     wchar_t const* const locale_name = locale_data->locale_name[LC_TIME];
23 
24     __crt_locale_pointers locinfo = { locale_data, nullptr };
25 
26     lc_time->_W_ww_locale_name = __acrt_copy_locale_name(locale_name);
27 
28     int ret = 0;
29 
30     // The days of the week.  Note that the OS days are numbered 1-7, starting
31     // with Monday, whereas the lc_time days are numbered (indexed, really) 0-6
32     // starting with Sunday (thus the adjustment to the index in the loop).
33     for (unsigned int i = 0; i != 7; ++i)
34     {
35         unsigned int const result_index = (i + 1) % 7;
36         ret |= __acrt_GetLocaleInfoA(&locinfo, LC_STR_TYPE, locale_name, LOCALE_SABBREVDAYNAME1 + i, &lc_time->wday_abbr[result_index]);
37         ret |= __acrt_GetLocaleInfoA(&locinfo, LC_STR_TYPE, locale_name, LOCALE_SDAYNAME1       + i, &lc_time->wday     [result_index]);
38 
39         ret |= __acrt_GetLocaleInfoA(&locinfo, LC_WSTR_TYPE, locale_name, LOCALE_SABBREVDAYNAME1 + i, &lc_time->_W_wday_abbr[result_index]);
40         ret |= __acrt_GetLocaleInfoA(&locinfo, LC_WSTR_TYPE, locale_name, LOCALE_SDAYNAME1       + i, &lc_time->_W_wday     [result_index]);
41     }
42 
43     // The months of the year
44     for (unsigned int i = 0; i != 12; ++i)
45     {
46         ret |= __acrt_GetLocaleInfoA(&locinfo, LC_STR_TYPE,  locale_name, LOCALE_SABBREVMONTHNAME1 + i, &lc_time->month_abbr[i]);
47         ret |= __acrt_GetLocaleInfoA(&locinfo, LC_STR_TYPE,  locale_name, LOCALE_SMONTHNAME1       + i, &lc_time->month     [i]);
48 
49         ret |= __acrt_GetLocaleInfoA(&locinfo, LC_WSTR_TYPE, locale_name, LOCALE_SABBREVMONTHNAME1 + i, &lc_time->_W_month_abbr[i]);
50         ret |= __acrt_GetLocaleInfoA(&locinfo, LC_WSTR_TYPE, locale_name, LOCALE_SMONTHNAME1       + i, &lc_time->_W_month     [i]);
51     }
52 
53     ret |= __acrt_GetLocaleInfoA(&locinfo, LC_STR_TYPE, locale_name, LOCALE_S1159, &lc_time->ampm[0]);
54     ret |= __acrt_GetLocaleInfoA(&locinfo, LC_STR_TYPE, locale_name, LOCALE_S2359, &lc_time->ampm[1]);
55 
56     ret |= __acrt_GetLocaleInfoA(&locinfo, LC_WSTR_TYPE, locale_name, LOCALE_S1159, &lc_time->_W_ampm[0]);
57     ret |= __acrt_GetLocaleInfoA(&locinfo, LC_WSTR_TYPE, locale_name, LOCALE_S2359, &lc_time->_W_ampm[1]);
58 
59     ret |= __acrt_GetLocaleInfoA(&locinfo, LC_STR_TYPE, locale_name, LOCALE_SSHORTDATE,    &lc_time->ww_sdatefmt);
60     ret |= __acrt_GetLocaleInfoA(&locinfo, LC_STR_TYPE, locale_name, LOCALE_SLONGDATE,     &lc_time->ww_ldatefmt);
61     ret |= __acrt_GetLocaleInfoA(&locinfo, LC_STR_TYPE, locale_name, LOCALE_STIMEFORMAT,   &lc_time->ww_timefmt);
62     ret |= __acrt_GetLocaleInfoA(&locinfo, LC_INT_TYPE, locale_name, LOCALE_ICALENDARTYPE, &lc_time->ww_caltype);
63 
64     ret |= __acrt_GetLocaleInfoA(&locinfo, LC_WSTR_TYPE, locale_name, LOCALE_SSHORTDATE,  &lc_time->_W_ww_sdatefmt);
65     ret |= __acrt_GetLocaleInfoA(&locinfo, LC_WSTR_TYPE, locale_name, LOCALE_SLONGDATE,   &lc_time->_W_ww_ldatefmt);
66     ret |= __acrt_GetLocaleInfoA(&locinfo, LC_WSTR_TYPE, locale_name, LOCALE_STIMEFORMAT, &lc_time->_W_ww_timefmt);
67 
68     return ret == 0;
69 }
70 
71 
72 
73 _Success_(return != nullptr)
get_or_create_lc_time(_In_ __crt_locale_data * const locale_data)74 static __crt_lc_time_data const* __cdecl get_or_create_lc_time(
75     _In_ __crt_locale_data* const locale_data
76     ) throw()
77 {
78     // C Locale
79     if (!locale_data->locale_name[LC_TIME])
80     {
81         return &__lc_time_c;
82     }
83 
84     // Non-C Locale
85     __crt_unique_heap_ptr<__crt_lc_time_data> lc_time = _calloc_crt_t(__crt_lc_time_data, 1);
86     if (!lc_time)
87     {
88         return nullptr;
89     }
90 
91     if (!initialize_lc_time(lc_time.get(), locale_data))
92     {
93         __acrt_locale_free_time(lc_time.get());
94         return nullptr;
95     }
96 
97     lc_time.get()->refcount = 1;
98 
99     return lc_time.detach();
100 }
101 
102 
103 
__acrt_locale_initialize_time(__crt_locale_data * const locale_data)104 extern "C" int __cdecl __acrt_locale_initialize_time(
105     __crt_locale_data* const locale_data
106     )
107 {
108     __crt_lc_time_data const* const lc_time = get_or_create_lc_time(locale_data);
109     if (!lc_time)
110     {
111         return 1;
112     }
113 
114     if (__acrt_locale_release_lc_time_reference(locale_data->lc_time_curr) == 0)
115     {
116         _ASSERTE(("lc_time_curr unexpectedly has no remaining references", 0));
117     }
118 
119     locale_data->lc_time_curr = lc_time;
120     return 0;
121 }
122 
123 #endif /* _UCRT_ENCLAVE_BUILD */
124 
125 
free_crt_array_internal(_Inout_updates_ (array_count)void const ** const array,_In_ size_t const array_count)126 static void __cdecl free_crt_array_internal(
127     _Inout_updates_(array_count) void const** const array,
128     _In_                         size_t       const array_count
129     ) throw()
130 {
131     for (void const* const* it = array; it != array + array_count; ++it)
132     {
133         _free_crt(const_cast<void*>(*it));
134     }
135 }
136 
137 
138 
139 template <typename T, size_t N>
free_crt_array(_Inout_ T * (& array)[N])140 static void __cdecl free_crt_array(_Inout_ T* (&array)[N]) throw()
141 {
142     return free_crt_array_internal(const_cast<void const**>(reinterpret_cast<void const* const*>(array)), N);
143 }
144 
145 
146 
__acrt_locale_free_time(__crt_lc_time_data * const lc_time)147 extern "C" void __cdecl __acrt_locale_free_time(
148     __crt_lc_time_data* const lc_time
149     )
150 {
151     if (!lc_time)
152     {
153         return;
154     }
155 
156     free_crt_array(lc_time->wday_abbr);
157     free_crt_array(lc_time->wday);
158     free_crt_array(lc_time->month_abbr);
159     free_crt_array(lc_time->month);
160     free_crt_array(lc_time->ampm);
161 
162     _free_crt(lc_time->ww_sdatefmt);
163     _free_crt(lc_time->ww_ldatefmt);
164     _free_crt(lc_time->ww_timefmt);
165 
166     free_crt_array(lc_time->_W_wday_abbr);
167     free_crt_array(lc_time->_W_wday);
168     free_crt_array(lc_time->_W_month_abbr);
169     free_crt_array(lc_time->_W_month);
170     free_crt_array(lc_time->_W_ampm);
171 
172     _free_crt(lc_time->_W_ww_sdatefmt);
173     _free_crt(lc_time->_W_ww_ldatefmt);
174     _free_crt(lc_time->_W_ww_timefmt);
175 
176     _free_crt(lc_time->_W_ww_locale_name);
177 }
178