Reactos
at master 199 lines 5.8 kB view raw
1// 2// strftime.cpp 3// 4// Copyright (c) Microsoft Corporation. All rights reserved. 5// 6// The strftime family of functions, which format time data into a string, and 7// related functionality. 8// 9#include <corecrt_internal_time.h> 10#include <locale.h> 11 12//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 13// 14// Day and Month Name and Time Locale Information Fetching Functions 15// 16//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 17extern "C" char* __cdecl _Getdays_l(_locale_t const locale) 18{ 19 _LocaleUpdate locale_update(locale); 20 __crt_lc_time_data const* const time_data = locale_update.GetLocaleT()->locinfo->lc_time_curr; 21 22 size_t length = 0; 23 for (size_t n = 0; n < 7; ++n) 24 { 25 length += strlen(time_data->wday_abbr[n]) + strlen(time_data->wday[n]) + 2; 26 } 27 28 __crt_unique_heap_ptr<char> buffer(_malloc_crt_t(char, length + 1)); 29 if (buffer.get() == nullptr) 30 return nullptr; 31 32 33 char* it = buffer.get(); 34 for (size_t n = 0; n < 7; ++n) 35 { 36 *it++ = ':'; 37 _ERRCHECK(strcpy_s(it, (length + 1) - (it - buffer.get()), time_data->wday_abbr[n])); 38 it += strlen(it); 39 *it++ = ':'; 40 _ERRCHECK(strcpy_s(it, (length + 1) - (it - buffer.get()), time_data->wday[n])); 41 it += strlen(it); 42 } 43 *it++ = '\0'; 44 45 return buffer.detach(); 46} 47 48extern "C" char* __cdecl _Getdays() 49{ 50 return _Getdays_l(nullptr); 51} 52 53 54 55extern "C" char* __cdecl _Getmonths_l(_locale_t const locale) 56{ 57 _LocaleUpdate locale_update(locale); 58 __crt_lc_time_data const* time_data = locale_update.GetLocaleT()->locinfo->lc_time_curr; 59 60 size_t length = 0; 61 for (size_t n = 0; n < 12; ++n) 62 { 63 length += strlen(time_data->month_abbr[n]) + strlen(time_data->month[n]) + 2; 64 } 65 66 __crt_unique_heap_ptr<char> buffer(_malloc_crt_t(char, length + 1)); 67 if (buffer.get() == nullptr) 68 return nullptr; 69 70 char* it = buffer.get(); 71 for (size_t n = 0; n < 12; ++n) 72 { 73 *it++ = ':'; 74 _ERRCHECK(strcpy_s(it, (length + 1) - (it - buffer.get()), time_data->month_abbr[n])); 75 it += strlen(it); 76 *it++ = ':'; 77 _ERRCHECK(strcpy_s(it, (length + 1) - (it - buffer.get()), time_data->month[n])); 78 it += strlen(it); 79 } 80 *it++ = '\0'; 81 82 return buffer.detach(); 83} 84 85 86 87extern "C" char* __cdecl _Getmonths() 88{ 89 return _Getmonths_l(nullptr); 90} 91 92extern "C" void* __cdecl _W_Gettnames(); 93 94extern "C" void* __cdecl _Gettnames() 95{ 96 return _W_Gettnames(); 97} 98 99 100 101//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 102// 103// The strftime family of functions 104// 105//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 106// These functions format a time as a string using a given locale. They place 107// characters into the user's output buffer, expanding time format directives as 108// described in the provided control string. The lc_time_arg and locale are 109// used for locale data. 110// 111// If the total number of characters that need to be written (including the null 112// terminator) is less than the max_size, then the number of characters written 113// (not including the null terminator) is returned. Otherwise, zero is returned. 114// 115// These functions simply delegate to the corresponding wide string functions 116// (e.g. _wcsftime). 117_Success_(return > 0) 118extern "C" size_t __cdecl _Strftime_l ( 119 _Out_writes_z_(maxsize) char * const string, 120 _In_ size_t const maxsize, 121 _In_z_ const char * const format, 122 _In_ const tm * const timeptr, 123 _In_ void * const lc_time_arg, 124 _In_opt_ _locale_t const locale 125 ) 126{ 127 _LocaleUpdate locale_update(locale); 128 unsigned int const lc_time_cp = locale_update.GetLocaleT()->locinfo->lc_time_cp; 129 130 _VALIDATE_RETURN(string != nullptr, EINVAL, 0) 131 _VALIDATE_RETURN(maxsize != 0, EINVAL, 0) 132 *string = '\0'; 133 134 _VALIDATE_RETURN(format != nullptr, EINVAL, 0) 135 _VALIDATE_RETURN(timeptr != nullptr, EINVAL, 0) 136 137 __crt_internal_win32_buffer<wchar_t> wformat; 138 139 errno_t const cvt1 = __acrt_mbs_to_wcs_cp(format, wformat, lc_time_cp); 140 141 if (cvt1 != 0) { 142 return 0; 143 } 144 145 // Allocate a new wide-char output string with the same size as the char* 146 // string one passed in as argument 147 __crt_unique_heap_ptr<wchar_t> const wstring(_malloc_crt_t(wchar_t, maxsize)); 148 if (wstring.get() == nullptr) 149 { 150 // malloc should set the errno, if any 151 return 0; 152 } 153 154 size_t const wcsftime_result = _Wcsftime_l(wstring.get(), maxsize, wformat.data(), timeptr, lc_time_arg, locale); 155 if (wcsftime_result == 0) 156 { 157 return 0; 158 } 159 160 __crt_no_alloc_win32_buffer<char> copy_back(string, maxsize); 161 errno_t const cvt2 = __acrt_wcs_to_mbs_cp(wstring.get(), copy_back, lc_time_cp); 162 163 if (cvt2 != 0) { 164 return 0; 165 } 166 167 return copy_back.size(); 168} 169 170extern "C" size_t __cdecl _Strftime( 171 char* const string, 172 size_t const max_size, 173 char const* const format, 174 tm const* const timeptr, 175 void* const lc_time_arg 176 ) 177{ 178 return _Strftime_l(string, max_size, format, timeptr, lc_time_arg, nullptr); 179} 180 181extern "C" size_t __cdecl _strftime_l( 182 char* const string, 183 size_t const max_size, 184 char const* const format, 185 tm const* const timeptr, 186 _locale_t const locale 187 ) 188{ 189 return _Strftime_l(string, max_size, format, timeptr, nullptr, locale); 190} 191extern "C" size_t __cdecl strftime( 192 char* const string, 193 size_t const max_size, 194 char const* const format, 195 tm const* const timeptr 196 ) 197{ 198 return _Strftime_l(string, max_size, format, timeptr, nullptr, nullptr); 199}