Hi Chuck,
I'll comment on 'h' and 'G' formats that are not implemented in wine (and there are no patches for them to be reviewed).
- case 'h': > case 'b':The 'h' format was introduced in ucrtbase. All
other options that were introduced in newer version of crt library are implemented inside #if _MSVCR_VER >= 140 block.
- case 'G':
- {
+#ifdef _WIN64
- MSVCRT___time64_t firstmontime = 0;
- MSVCRT___time64_t temp_time = 0;
+#else
- MSVCRT___time32_t firstmontime = 0;
- MSVCRT___time32_t temp_time = 0;
+#endif
- struct MSVCRT_tm* tmp_mstm = 0;
- struct MSVCRT_tm* oldstate = 0;
- struct MSVCRT_tm* firstmontm = 0;
- int iso8601yr = -1;
- int iso8601wk = -1;
- char* tmp_str = 0;
- if(!(tmp_mstm = MSVCRT_malloc(sizeof(struct MSVCRT_tm))))
- return 0;
- if(msvcrt_get_thread_data()->time_buffer &&
- !(oldstate = MSVCRT_malloc(sizeof(struct
MSVCRT_tm)))) {
- MSVCRT_free(tmp_mstm);
- return 0;
- }
- if(oldstate)
- memcpy(oldstate, msvcrt_get_thread_data()->time_buffer,
- sizeof(struct MSVCRT_tm));
- memcpy(tmp_mstm, mstm, sizeof(struct MSVCRT_tm));
- temp_time = MSVCRT_mktime(tmp_mstm);
- MSVCRT_free(tmp_mstm);
- tmp_mstm = MSVCRT_gmtime(&temp_time);
- iso8601yr = tmp_mstm->tm_year + 1900;
- iso8601wk =
(tmp_mstm->tm_yday+1-(tmp_mstm->tm_wday==0?7:tmp_mstm->tm_wday)+10)/7;
- if(iso8601wk == 53) {
- if(!(firstmontm = MSVCRT_malloc(sizeof(struct
MSVCRT_tm)))) {
- MSVCRT_free(oldstate);
- return 0;
- }
- memset(firstmontm, '\0', sizeof(struct MSVCRT_tm));
- firstmontm->tm_mon = 0;
- firstmontm->tm_mday = 4;
- firstmontm->tm_year = tmp_mstm->tm_year+1;
- firstmontime = MSVCRT_mktime(firstmontm);
- MSVCRT_free(firstmontm);
- firstmontm = MSVCRT_gmtime(&firstmontime);
- firstmontime =
firstmontime-((firstmontm->tm_wday-1==-1?6:firstmontm->tm_wday-1)*86400);
- if(firstmontime <= temp_time)
- iso8601yr += 1;
- }
- if(iso8601wk == 0)
- iso8601yr -= 1;
- if(!(tmp_str = MSVCRT_malloc(6))) {
- MSVCRT_free(oldstate);
- return 0;
- }
- memset(tmp_str, '\0', 6);
- MSVCRT__snprintf(tmp_str, 6, "%d", iso8601yr);
- if(!strftime_str(str, &ret, max, tmp_str)) {
- if(oldstate) {
- memcpy(msvcrt_get_thread_data()->time_buffer,
oldstate,
- sizeof(struct MSVCRT_tm));
- MSVCRT_free(oldstate);
- }
- MSVCRT_free(tmp_str);
- return 0;
- }
- if(oldstate) {
- memcpy(msvcrt_get_thread_data()->time_buffer, oldstate,
- sizeof(struct MSVCRT_tm));
- MSVCRT_free(oldstate);
- }
- MSVCRT_free(tmp_str);
- }
- break;
It's not the simplest way of implementing it. There's no need for any allocations, the value returned by this format is in tm_year-1...tm_year range+1.
I think that the code should look like this: tmp = 1900 + mstm->tm_year; if (mstm->tm_yday - mstm->tm_wday + 4 < 0) tmp--; else if(mstm->tm_yday + mstm->tm_wday - X > 365 + IsLeapYear(tmp)) tmp++; if (!strftime_int(str, &ret, max, tmp, 4, 0, 9999)) return 0; break;
It also needs some tests.
Thanks, Piotr