Author: sebor Date: Thu Dec 6 16:27:56 2007 New Revision: 601927 URL: http://svn.apache.org/viewvc?rev=601927&view=rev Log: 2007-12-05 Travis Vitek <[EMAIL PROTECTED]>
STDCXX-676 * tests/locale/22.locale.time.put.cpp [_MSC_VER] (rw_strftime): Avoid passing unsupported format specifiers to strftime(). Modified: incubator/stdcxx/trunk/tests/localization/22.locale.time.put.cpp Modified: incubator/stdcxx/trunk/tests/localization/22.locale.time.put.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/localization/22.locale.time.put.cpp?rev=601927&r1=601926&r2=601927&view=diff ============================================================================== --- incubator/stdcxx/trunk/tests/localization/22.locale.time.put.cpp (original) +++ incubator/stdcxx/trunk/tests/localization/22.locale.time.put.cpp Thu Dec 6 16:27:56 2007 @@ -35,6 +35,7 @@ #include <cstring> // for memcpy(), strlen() #include <ctime> // for tm #include <cwchar> // for wcsftime(), wcslen() +#include <cassert> // for assert() #include <driver.h> // for rw_test(), ... #include <environ.h> // for rw_putenv() @@ -127,7 +128,153 @@ { static const std::tm tmp = std::tm (); - const std::size_t n = std::strftime (buf, bufsize, pat, tmb ? tmb : &tmp); + if (!tmb) + tmb = &tmp; + +#ifdef _MSC_VER + + // ms crt aborts if you use out of range values in debug + if (tmb->tm_hour < 0 || 24 <= tmb->tm_hour) + return 0; + + if (tmb->tm_min < 0 || 60 <= tmb->tm_min) + return 0; + + if (tmb->tm_sec < 0 || 60 <= tmb->tm_sec) + return 0; + + // create a new pattern buffer that is windows strftime compatible... + char patbuf [512]; + char *fpat = patbuf; + + // assumes tm_year is relative to 1900 + const int year = (tmb->tm_year + 1900); + const int century = (tmb->tm_year + 1900) / 100; + + while (*pat) { + + if (*pat == '%') { + + // ensure we are not within 16 chars of the end of the + // local pattern buffer to avoid overflow + assert ((fpat + 16) < (patbuf + 512)); + + pat += 1; // step past % + switch (*pat) + { + case '\0': + // fails miserably if the last char is % + *fpat++ = '%'; *fpat++ = '%'; + break; + case 'C': + // %C is replaced by the century number (the year divided by + // 100 and truncated to an integer) as a decimal number. + *fpat++ = '0' + (century / 10) % 10; + *fpat++ = '0' + (century % 10); + pat += 1; + break; + case 'D': + // %D same as %m/%d/%y. + *fpat++ = '%'; *fpat++ = 'm'; *fpat++ = '/'; + *fpat++ = '%'; *fpat++ = 'd'; *fpat++ = '/'; + *fpat++ = '%'; *fpat++ = 'y'; pat += 1; + break; + case 'e': + // %e is replaced by the day of the month as a decimal + // number [1,31]; a single digit is preceded by a space. + if (tmb->tm_mday < 10) + *fpat++ = ' '; + else + *fpat++ = '0' + (tmb->tm_mday / 10) % 10; + *fpat++ = '0' + (tmb->tm_mday % 10); + pat += 1; + break; + case 'F': + // %F Equivalent to %Y - %m - %d (the ISO 8601:2000 standard + // date format). [ tm_year, tm_mon, tm_mday] + *fpat++ = '%'; *fpat++ = 'Y'; + *fpat++ = ' '; *fpat++ = '-'; *fpat++ = ' '; + *fpat++ = '%'; *fpat++ = 'm'; + *fpat++ = ' '; *fpat++ = '-'; *fpat++ = ' '; + *fpat++ = '%'; *fpat++ = 'd'; pat += 1; + break; + case 'g': + // %g Replaced by the last 2 digits of the week-based year + // as a decimal number [00,99]. [ tm_year, tm_wday, tm_yday] + return 0; + case 'G': + // %G Replaced by the week-based year as a decimal number + // (for example, 1977). [ tm_year, tm_wday, tm_yday] + return 0; + case 'h': + // %h same as %b. + *fpat++ = '%'; *fpat++ = 'b'; pat += 1; + break; + case 'n': + // %n is replaced by a newline character. + *fpat++ = '\n'; pat += 1; + break; + case 'r': + // %r is replaced by the time in a.m. and p.m. notation; in + // the POSIX locale this is equivalent to %I:%M:%S %p. + *fpat++ = '%'; *fpat++ = 'I'; *fpat++ = ':'; + *fpat++ = '%'; *fpat++ = 'M'; *fpat++ = ':'; + *fpat++ = '%'; *fpat++ = 'S'; *fpat++ = ' '; + *fpat++ = '%'; *fpat++ = 'p'; pat += 1; + break; + case 'R': + // %R is replaced by the time in 24 hour notation (%H:%M). + *fpat++ = '%'; *fpat++ = 'H'; *fpat++ = ':'; + *fpat++ = '%'; *fpat++ = 'M'; pat += 1; + break; + case 't': + // %t is replaced by a tab character. + *fpat++ = '\t'; pat += 1; + break; + case 'T': + // %T is replaced by the time (%H:%M:%S). + *fpat++ = '%'; *fpat++ = 'H'; *fpat++ = ':'; + *fpat++ = '%'; *fpat++ = 'M'; *fpat++ = ':'; + *fpat++ = '%'; *fpat++ = 'S'; pat += 1; + break; + case 'u': + // %u is replaced by the weekday as a decimal number [1,7], + // with 1 representing Monday. + *fpat++ = '0' + (tmb->tm_wday + 1); + pat += 1; + break; + case 'V': + // %V is replaced by the week number of the year (Monday as + // the first day of the week) as a decimal number [01,53]. + // If the week containing 1 January has four or more days + // in the new year, then it is considered week 1. Otherwise, + // it is the last week of the previous year, and the next + // week is week 1. + return 0; + default: + // copy percent and format + *fpat++ = '%'; + *fpat++ = *pat++; + break; + } + + *fpat = 0; // null terminate + } + else { + *fpat++ = *pat++; + } + } + + // copy the null + *fpat = *pat; + + const std::size_t n = std::strftime (buf, bufsize, patbuf, tmb); + +#else // if !defined (_MSC_VER) + + const std::size_t n = std::strftime (buf, bufsize, pat, tmb); + +#endif // _MSC_VER RW_ASSERT (n < bufsize); @@ -140,21 +287,20 @@ { static const std::tm tmp = std::tm (); -#ifndef _RWSTD_NO_WCSFTIME_WCHAR_T_FMAT +#if !defined (_RWSTD_NO_WCSFTIME_WCHAR_T_FMAT) && !defined (_MSC_VER) std::size_t n = std::wcsftime (wbuf, bufsize, wpat, tmb ? tmb : &tmp); -#else // if defined (_RWSTD_NO_WCSFTIME) +#else // if defined (_RWSTD_NO_WCSFTIME) || defined (_MSC_VER) char pat [1024]; char buf [1024]; narrow (pat, wpat); - std::size_t n = std::strftime (buf, bufsize, pat, tmb ? tmb : &tmp); - + std::size_t n = rw_strftime (buf, bufsize, pat, tmb ? tmb : &tmp); widen (wbuf, buf); -#endif // _RWSTD_NO_WCSFTIME +#endif // _RWSTD_NO_WCSFTIME, _MSC_VER RW_ASSERT (n < bufsize);