| /*************************************************************************** |
| * |
| * 22.locale.time.get.cpp - tests exercising the std::time_get facet |
| * |
| * $Id$ |
| * |
| *************************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed |
| * with this work for additional information regarding copyright |
| * ownership. The ASF licenses this file to you under the Apache |
| * License, Version 2.0 (the "License"); you may not use this file |
| * except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| * implied. See the License for the specific language governing |
| * permissions and limitations under the License. |
| * |
| * Copyright 2001-2006 Rogue Wave Software. |
| * |
| **************************************************************************/ |
| |
| #include <locale> |
| #include <sstream> // for stringstream |
| |
| #include <climits> // for INT_{MIN,MAX} |
| #include <clocale> // for LC_ALL |
| #include <cstdio> // for fprintf() |
| #include <cstdlib> // for getenv() |
| #include <cstring> // for memcmp(), strlen() |
| #include <ctime> // for struct tm |
| |
| #include <driver.h> // for rw_test() |
| #include <file.h> // for rw_nextfd() |
| #include <rw_locale.h> // for rw_locales() |
| |
| /**************************************************************************/ |
| |
| template <class charT> |
| void do_test (int lineno, charT, const char *cname, |
| std::tm val, const char *pat, int consumed, |
| const char *fmt, int flags, int err_expect = -1) |
| { |
| std::basic_ostringstream<charT> ostrm; |
| |
| typedef std::istreambuf_iterator<charT> InIter; |
| typedef std::ostreambuf_iterator<charT> OutIter; |
| |
| const std::time_get<charT, InIter> &tg = |
| std::use_facet<std::time_get<charT, InIter> >(ostrm.getloc ()); |
| |
| const std::time_put<charT, OutIter> &tp = |
| std::use_facet<std::time_put<charT, OutIter> >(ostrm.getloc ()); |
| |
| ostrm.flags (std::ios_base::fmtflags (flags)); |
| |
| charT wpatbuf [256]; |
| for (std::size_t j = 0; !!(wpatbuf [j] = pat [j]); ++j); |
| |
| const charT *wpat = wpatbuf; |
| const charT *wpatend = wpat + std::char_traits<charT>::length (wpat); |
| |
| // format string |
| OutIter it (ostrm); |
| tp.put (it, ostrm, charT (' '), &val, wpat, wpatend); |
| |
| // working around dumb compilers such as MSVC 6.0 that |
| // do not zero initialize POD structs when using tm() |
| static std::tm zero_tm; |
| std::tm x = zero_tm; |
| |
| std::basic_istringstream<charT> istrm (ostrm.str ()); |
| |
| istrm.flags (std::ios_base::fmtflags (flags)); |
| |
| std::ios_base::iostate err = std::ios_base::goodbit; |
| |
| const char *fname = 0; |
| |
| InIter ibeg = InIter (istrm); |
| InIter iend; |
| |
| _TRY { |
| if ( '\0' == fmt [1] |
| || ('E' == fmt [0] || 'O' == fmt [0] && '\0' == fmt [2])) { |
| |
| // single-character format strings "a", "b", "x", "X", and "Y" |
| // exercise the standard time_get interface, i.e., get_weekday(), |
| // get_monthname(), and get_year() |
| |
| // other single or two character format strings, e.g., "Ec" or "Ex" |
| // exercise the single character extension (format specifier and |
| // an optional modifier) |
| |
| switch (*fmt) { |
| case 'a': |
| fname = "get_weekday"; |
| iend = tg.get_weekday (ibeg, iend, istrm, err, &x); |
| break; |
| |
| case 'b': |
| fname = "get_monthname"; |
| iend = tg.get_monthname (ibeg, iend, istrm, err, &x); |
| break; |
| |
| case 'x': |
| fname = "get_date"; |
| iend = tg.get_date (ibeg, iend, istrm, err, &x); |
| break; |
| |
| case 'X': |
| fname = "get_time"; |
| iend = tg.get_time (ibeg, iend, istrm, err, &x); |
| break; |
| |
| case 'Y': |
| fname = "get_year"; |
| iend = tg.get_year (ibeg, iend, istrm, err, &x); |
| break; |
| |
| default: |
| fname = "get"; |
| if ('E' == fmt [0] || 'O' == fmt [0]) |
| iend = tg.get (ibeg, iend, istrm, err, &x, |
| fmt [1], fmt [0]); |
| else |
| iend = tg.get (ibeg, iend, istrm, err, &x, *fmt); |
| break; |
| } |
| } |
| else { |
| // multi-character format strings exercise the pattern |
| // extensions to time_get, ala strptime() |
| |
| charT fmtstr [256]; |
| charT *end; |
| |
| const char *pfmt = fmt; |
| for (end = fmtstr; *pfmt; *end++ = *pfmt++); |
| |
| fname = "get"; |
| iend = tg.get (ibeg, iend, istrm, err, &x, fmtstr, end); |
| } |
| } |
| _CATCH (...) { |
| rw_error (0, 0, lineno, |
| "line %d. time_get<%s>::%s (%{*Ac}, ..., \"%s\") " |
| "unexpectedly threw an exception", |
| __LINE__, cname, fname, |
| int (sizeof (charT)), ostrm.str ().data (), fmt); |
| |
| return; |
| } |
| |
| int extracted = -1 == consumed ? -1 |
| : int (istrm.rdbuf ()->pubseekoff (0, std::ios::cur, std::ios::in)); |
| |
| if (extracted == -1) |
| consumed = -1; |
| |
| int success = |
| extracted == consumed && (-1 == err_expect || err == err_expect); |
| |
| rw_assert (success, __FILE__, lineno, |
| "line %d. time_get<%s>::%s (%{*Ac}, ..., \"%s\") " |
| "ate %d, expected %d, rdstate() == %{Is}, got %{Is}", |
| __LINE__, cname, fname, |
| int (sizeof (charT)), ostrm.str ().data (), fmt, |
| extracted, consumed, err_expect, err); |
| |
| success = 0 == std::memcmp (&x, &val, sizeof x); |
| |
| rw_assert (success, __FILE__, lineno, |
| "line %d. time_get<%s>::%s (%{*Ac}, ..., \"%s\") got %{t}, " |
| "expected %{t}, flags = %{If}, locale (%s)", |
| __LINE__, cname, fname, |
| int (sizeof (charT)), ostrm.str ().data (), fmt, &x, |
| &val, flags, std::locale ().name ().data ()); |
| } |
| |
| |
| /**************************************************************************/ |
| |
| std::tm mktm (int sec = 0, int min = 0, int hour = 0, |
| int mday = 0, int mon = 0, int year = 0, |
| int wday = 0, int yday = 0, int isdst = 0) |
| { |
| std::tm tmp = std::tm (); |
| |
| if (sec < 0) { |
| // get the current local time |
| std::time_t t = std::time (0); |
| std::tm *ptm = std::localtime (&t); |
| return ptm ? *ptm : tmp; |
| } |
| |
| // use arguments to initialize struct |
| tmp.tm_sec = sec; // seconds after the minute [0, 60] |
| tmp.tm_min = min; // minutes after the hour [0, 59] |
| tmp.tm_hour = hour; // hours since midnight [0, 23] |
| tmp.tm_mday = mday; // day of the month [1, 31] |
| tmp.tm_mon = mon; // months since January [0, 11] |
| tmp.tm_year = year; // years since 1900 |
| tmp.tm_wday = wday; // days since Sunday [0, 6] |
| tmp.tm_yday = yday; // days since January 1 [0, 365] |
| tmp.tm_isdst = isdst; // Daylight Saving Time flag |
| |
| return tmp; |
| } |
| |
| |
| // for convenience |
| #define Boolalpha std::ios_base::boolalpha |
| #define Dec std::ios_base::dec |
| #define Fixed std::ios_base::fixed |
| #define Hex std::ios_base::hex |
| #define Internal std::ios_base::internal |
| #define Left std::ios_base::left |
| #define Oct std::ios_base::oct |
| #define Right std::ios_base::right |
| #define Scientific std::ios_base::scientific |
| #define Showbase std::ios_base::showbase |
| #define Showpoint std::ios_base::showpoint |
| #define Showpos std::ios_base::showpos |
| #define Skipws std::ios_base::skipws |
| #define Unitbuf std::ios_base::unitbuf |
| #define Uppercase std::ios_base::uppercase |
| #define Bin std::ios_base::bin |
| #define Adjustfield std::ios_base::adjustfield |
| #define Basefield std::ios_base::basefield |
| #define Floatfield std::ios_base::floatfield |
| #define Nolock std::ios_base::nolock |
| #define Nolockbuf std::ios_base::nolockbuf |
| |
| // capitalize to prevent EDG eccp from expanding the macros |
| // in .cc files when implicit inclusion is used (causes errors |
| // in constructs such as traits_type::eof ()) |
| #define Bad std::ios_base::badbit |
| #define Eof std::ios_base::eofbit |
| #define Fail std::ios_base::failbit |
| #define Good std::ios_base::goodbit |
| |
| |
| #define T __LINE__, charT (), cname, mktm |
| #define TEST do_test |
| |
| #define FUNCTION(fun) \ |
| rw_info (0, 0, __LINE__, \ |
| "std::time_get<%s>::%s() in locale (\"%s\")", \ |
| cname, fun, std::locale ().name ().c_str ()) |
| |
| #define STEP(desc) rw_info (0, 0, __LINE__, "%s", desc) |
| |
| |
| template <class charT> |
| void test_posix (charT, const char *cname) |
| { |
| // set the global locale object |
| std::locale::global (std::locale ("C")); |
| |
| // exercise abbreviated weekday names (time_get::get_weekday()) |
| FUNCTION ("get_weekday"); |
| |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "%a", -1, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "%a", -1, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 2), "%a", -1, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 3), "%a", -1, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 4), "%a", -1, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 5), "%a", -1, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 6), "%a", -1, "a", 0, Eof); |
| |
| // comparison is case insensitive |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "Sun", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "SUN", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "sun", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "Mon", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 2), "Tue", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 3), "Wed", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 4), "Thu", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 5), "Fri", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 6), "Sat", 3, "a", 0, Eof); |
| |
| // abbreviation followed by a letter other than the one |
| // that follows in a full name is acepted |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "suna", 3, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "monb", 3, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 2), "tuec", 3, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 3), "wedd", 3, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 4), "thue", 3, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 5), "frif", 3, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 6), "satg", 3, "a", 0, Good); |
| |
| // exercise failure on invalid input including incomplete |
| // full names (other than valid cases exercised above) |
| TEST (T (0, 0, 0, 0, 0, 0, 0), " Sun", 0, "a", 0, Fail); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "Mond", 4, "a", 0, Eof | Fail); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "Tuesd", 5, "a", 0, Eof | Fail); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "Wednesd", 7, "a", 0, Eof | Fail); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "Thursda.", 7, "a", 0, Fail); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "Fridax", 5, "a", 0, Fail); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "6Saturday", 0, "a", 0, Fail); |
| |
| // exercise full weekday names |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "%A", -1, "a", 0, -1); |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "%A", -1, "a", 0, -1); |
| TEST (T (0, 0, 0, 0, 0, 0, 2), "%A", -1, "a", 0, -1); |
| TEST (T (0, 0, 0, 0, 0, 0, 3), "%A", -1, "a", 0, -1); |
| TEST (T (0, 0, 0, 0, 0, 0, 4), "%A", -1, "a", 0, -1); |
| TEST (T (0, 0, 0, 0, 0, 0, 5), "%A", -1, "a", 0, -1); |
| TEST (T (0, 0, 0, 0, 0, 0, 6), "%A", -1, "a", 0, -1); |
| |
| // comparison is case insensitive |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "Sunday", 6, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "SUNDAY", 6, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "sunday", 6, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "Monday", 6, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 2), "Tuesday", 7, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 3), "Wednesday", 9, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 4), "Thursday", 8, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 5), "Friday", 6, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 6), "Saturday", 8, "a", 0, Good); |
| |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "Sunday ", 6, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "Monday 0", 6, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 2), "Tuesdayy", 7, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 3), "Wednesday.", 9, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 4), "Thursday,", 8, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 5), "Friday/", 6, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 6), "Saturday:", 8, "a", 0, Good); |
| |
| // exercise abbreviated month names (time_get::get_monthname()) |
| FUNCTION ("get_monthname"); |
| TEST (T (0, 0, 0, 0, 0), "%b", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 1), "%b", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 2), "%b", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 3), "%b", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 4), "%b", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 5), "%b", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 6), "%b", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 7), "%b", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 8), "%b", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 9), "%b", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 10), "%b", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 11), "%b", -1, "b", 0, -1); |
| |
| TEST (T (0, 0, 0, 0, 0), "Jan", 3, "b", 0, Eof); |
| TEST (T (0, 0, 0, 0, 1), "Feb", 3, "b", 0, Eof); |
| TEST (T (0, 0, 0, 0, 2), "Mar", 3, "b", 0, Eof); |
| TEST (T (0, 0, 0, 0, 3), "Apr", 3, "b", 0, Eof); |
| TEST (T (0, 0, 0, 0, 4), "May", 3, "b", 0, Good); |
| TEST (T (0, 0, 0, 0, 5), "Jun", 3, "b", 0, Eof); |
| TEST (T (0, 0, 0, 0, 6), "Jul", 3, "b", 0, Eof); |
| TEST (T (0, 0, 0, 0, 7), "Aug", 3, "b", 0, Eof); |
| TEST (T (0, 0, 0, 0, 8), "Sep", 3, "b", 0, Eof); |
| TEST (T (0, 0, 0, 0, 9), "Oct", 3, "b", 0, Eof); |
| TEST (T (0, 0, 0, 0, 10), "Nov", 3, "b", 0, Eof); |
| TEST (T (0, 0, 0, 0, 11), "Dec", 3, "b", 0, Eof); |
| |
| // exercise invalid abbreviated month names |
| TEST (T (0, 0, 0, 0, 0), "J", 1, "b", 0, Eof | Fail); |
| TEST (T (0, 0, 0, 0, 0), "J ", 1, "b", 0, Fail); |
| TEST (T (0, 0, 0, 0, 0), "Ja", 2, "b", 0, Eof | Fail); |
| TEST (T (0, 0, 0, 0, 0), "Ju", 2, "b", 0, Eof | Fail); |
| |
| // exercise full month names |
| TEST (T (0, 0, 0, 0, 0), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 1), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 2), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 3), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 4), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 5), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 6), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 7), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 8), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 9), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 10), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 11), "%B", -1, "b", 0, -1); |
| |
| TEST (T (0, 0, 0, 0, 0), "January", 7, "b", 0, Good); |
| TEST (T (0, 0, 0, 0, 0), "January ", 7, "b", 0, Good); |
| TEST (T (0, 0, 0, 0, 1), "February", 8, "b", 0, Good); |
| TEST (T (0, 0, 0, 0, 2), "March", 5, "b", 0, Good); |
| TEST (T (0, 0, 0, 0, 2), "Marchh", 5, "b", 0, Good); |
| TEST (T (0, 0, 0, 0, 3), "April", 5, "b", 0, Good); |
| TEST (T (0, 0, 0, 0, 4), "May", 3, "b", 0, Good); |
| TEST (T (0, 0, 0, 0, 5), "June", 4, "b", 0, Good); |
| TEST (T (0, 0, 0, 0, 6), "July", 4, "b", 0, Good); |
| TEST (T (0, 0, 0, 0, 6), "Jull", 3, "b", 0, Good); |
| TEST (T (0, 0, 0, 0, 7), "August", 6, "b", 0, Good); |
| TEST (T (0, 0, 0, 0, 8), "September", 9, "b", 0, Good); |
| TEST (T (0, 0, 0, 0, 9), "October", 7, "b", 0, Good); |
| TEST (T (0, 0, 0, 0, 10), "November", 8, "b", 0, Good); |
| TEST (T (0, 0, 0, 0, 11), "December", 8, "b", 0, Good); |
| |
| // exercise invalid full month names |
| TEST (T (0, 0, 0, 0, 0), "Januar", 6, "b", 0, Eof | Fail); |
| TEST (T (0, 0, 0, 0, 0), "Februar", 7, "b", 0, Eof | Fail); |
| TEST (T (0, 0, 0, 0, 0), " March", 0, "b", 0, Fail); |
| TEST (T (0, 0, 0, 0, 0), "apri/", 4, "b", 0, Fail); |
| TEST (T (0, 0, 0, 0, 0), "/MAY", 0, "b", 0, Fail); |
| TEST (T (0, 0, 0, 0, 0), ":Jun", 0, "b", 0, Fail); |
| TEST (T (0, 0, 0, 0, 0), "Ju ", 2, "b", 0, Fail); |
| |
| // exercise date (time_get::get_date()) |
| FUNCTION ("get_date"); |
| TEST (T (0, 0, 0, 1, 0, 100), "%x", 8, "x", 0, Eof); |
| TEST (T (0, 0, 0, 2, 1, 111), "%x", 8, "x", 0, Eof); |
| TEST (T (0, 0, 0, 3, 2, 122), "%x", 8, "x", 0, Eof); |
| TEST (T (0, 0, 0, 4, 3, 133), "%x", 8, "x", 0, Eof); |
| TEST (T (0, 0, 0, 5, 4, 144), "%x", 8, "x", 0, Eof); |
| TEST (T (0, 0, 0, 6, 5, 155), "%x", 8, "x", 0, Eof); |
| TEST (T (0, 0, 0, 7, 6, 166), "%x", 8, "x", 0, Eof); |
| TEST (T (0, 0, 0, 8, 7, 168), "%x", 8, "x", 0, Eof); |
| TEST (T (0, 0, 0, 9, 8, 69), "%x", 8, "x", 0, Eof); |
| TEST (T (0, 0, 0, 10, 9, 99), "%x", 8, "x", 0, Eof); |
| |
| TEST (T (0, 0, 0, 11, 5, 155), "06/11/55", 8, "x", 0, Eof); |
| TEST (T (0, 0, 0, 12, 6, 167), "07/12/67", 8, "x", 0, Eof); |
| TEST (T (0, 0, 0, 23, 7, 78), "08/23/78", 8, "x", 0, Eof); |
| TEST (T (0, 0, 0, 31, 11, 89), "12/31/89", 8, "x", 0, Eof); |
| |
| // exercise time (time_get::get_time()) |
| FUNCTION ("get_time"); |
| TEST (T ( 0, 0, 0), "%X", 8, "X", 0, Eof); |
| TEST (T ( 1, 59, 11), "%X", 8, "X", 0, Eof); |
| TEST (T (12, 48, 10), "%X", 8, "X", 0, Eof); |
| TEST (T (23, 37, 9), "%X", 8, "X", 0, Eof); |
| TEST (T (34, 26, 8), "%X", 8, "X", 0, Eof); |
| TEST (T (45, 15, 7), "%X", 8, "X", 0, Eof); |
| TEST (T (56, 4, 6), "%X", 8, "X", 0, Eof); |
| |
| TEST (T ( 0, 0, 0), "00:00:00", 8, "X", 0, Eof); |
| TEST (T (60, 9, 23), "23:09:60", 8, "X", 0, Eof); |
| TEST (T (59, 18, 22), "22:18:59", 8, "X", 0, Eof); |
| TEST (T (58, 27, 21), "21:27:58", 8, "X", 0, Eof); |
| TEST (T (57, 36, 20), "20:36:57", 8, "X", 0, Eof); |
| TEST (T (56, 45, 19), "19:45:56", 8, "X", 0, Eof); |
| TEST (T (55, 54, 18), "18:54:55", 8, "X", 0, Eof); |
| |
| // exercise year (time_get::get_year()) |
| FUNCTION ("get_year"); |
| TEST (T (0, 0, 0, 0, 0, -1900), "0", 1, "Y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, -1900), "00", 2, "Y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, -1899), "001", 3, "Y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, -124), "1776", 4, "Y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0), "1900", 4, "Y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 1), "1901", 4, "Y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 99), "1999", 4, "Y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 102), "2002", 4, "Y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 98099), "99999", 5, "Y", 0, Eof); |
| |
| FUNCTION ("get"); |
| |
| // exercise extensions implementing complete IEEE Std 1003.1-2001 support |
| // http://www.opengroup.org/onlinepubs/007904975/functions/strptime.html |
| |
| // capital format specifier (other than "X") implies the |
| // testing of std::time_get<>::get (..., char, char) |
| |
| // %a The day of the week, using the locale's weekday names; |
| // either the abbreviated or full name may be specified. |
| // %A Equivalent to %a. |
| STEP ("%a, %A: the day of the week"); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "Sun", 3, "A", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "Mon", 3, "A", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 2), "Tue", 3, "A", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 3), "Wed", 3, "A", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 4), "Thu", 3, "A", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 5), "Fri", 3, "A", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 6), "Sat", 3, "A", 0, Eof); |
| |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "Sunday", 6, "A", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "Monday", 6, "A", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 2), "Tuesday", 7, "A", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 3), "Wednesday", 9, "A", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 4), "Thursday", 8, "A", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 5), "Friday", 6, "A", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 6), "Saturday", 8, "A", 0, Good); |
| |
| // %b The month, using the locale's month names; |
| // either the abbreviated or full name may be specified. |
| // %B Equivalent to %b. |
| STEP ("%b, %B: the month"); |
| TEST (T (0, 0, 0, 0, 0), "January", 7, "B", 0, Good); |
| TEST (T (0, 0, 0, 0, 1), "February", 8, "B", 0, Good); |
| TEST (T (0, 0, 0, 0, 2), "March", 5, "B", 0, Good); |
| TEST (T (0, 0, 0, 0, 3), "April", 5, "B", 0, Good); |
| TEST (T (0, 0, 0, 0, 4), "May", 3, "B", 0, Good); |
| TEST (T (0, 0, 0, 0, 5), "June", 4, "B", 0, Good); |
| TEST (T (0, 0, 0, 0, 6), "July", 4, "B", 0, Good); |
| TEST (T (0, 0, 0, 0, 7), "August", 6, "B", 0, Good); |
| TEST (T (0, 0, 0, 0, 8), "September", 9, "B", 0, Good); |
| TEST (T (0, 0, 0, 0, 9), "October", 7, "B", 0, Good); |
| TEST (T (0, 0, 0, 0, 10), "November", 8, "B", 0, Good); |
| TEST (T (0, 0, 0, 0, 11), "December", 8, "B", 0, Good); |
| |
| // %c Replaced by the locale's appropriate date and time representation. |
| STEP ("%c: date and time representation"); |
| rw_warn (0, 0, __LINE__, "%%c not being exercised"); |
| |
| |
| // %C: The century number [00,99]; leading zeros are permitted |
| // but not required. |
| STEP ("%C: the century number"); |
| TEST (T (0, 0, 0, 0, 0, -1900), "0", 1, "C", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, -1800), "1", 1, "C", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, -1700), "2", 1, "C", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, -1600), "3", 1, "C", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, -1500), "04", 2, "C", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0), "19", 2, "C", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 100), "20", 2, "C", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 200), "21", 2, "C", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 1300), "32", 2, "C", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 8000), "99", 2, "C", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0), "100", 3, "C", 0, Eof | Fail); |
| |
| // %d The day of the month [01,31]; leading zeros are permitted but not |
| // required. |
| STEP ("%d: day of the month"); |
| TEST (T (0, 0, 0, 1), "1", 1, "d", 0, Eof); |
| TEST (T (0, 0, 0, 2), "02", 2, "d", 0, Eof); |
| TEST (T (0, 0, 0, 28), "28", 2, "d", 0, Eof); |
| TEST (T (0, 0, 0, 29), "29", 2, "d", 0, Eof); |
| TEST (T (0, 0, 0, 30), "030", 3, "d", 0, Eof); |
| TEST (T (0, 0, 0, 31), "0031", 4, "d", 0, Eof); |
| TEST (T (0, 0, 0, 0), "0", 1, "d", 0, Eof | Fail); |
| // leading whitespace not allowed |
| TEST (T (0, 0, 0, 0), " 3", 0, "d", 0, Fail); |
| TEST (T (0, 0, 0, 0), "32", 2, "d", 0, Eof | Fail); |
| |
| // %D The date as %m/%d/%y. |
| STEP ("%D: the date as %m/%d/%y"); |
| TEST (T (0, 0, 0, 14, 3, 102), "4/14/2", 6, "D", 0, Eof); |
| TEST (T (0, 0, 0, 14, 3, 102), "04/14/02", 8, "D", 0, Eof); |
| TEST (T (0, 0, 0, 14, 3, 102), "04/14/002", 9, "D", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0), "0/1/2002", 1, "D", 0, Fail); |
| TEST (T (0, 0, 0, 0, 0, 0), "4/0/2002", 3, "D", 0, Fail); |
| TEST (T (0, 0, 0, 0, 0, 0), "4/32/2002", 4, "D", 0, Fail); |
| |
| // %e Equivalent to %d; leading zeros are permitted but not required. |
| STEP ("%e: equivalent to %d"); |
| TEST (T (0, 0, 0, 1), "01", 2, "e", 0, Eof); |
| TEST (T (0, 0, 0, 9), "9", 1, "e", 0, Eof); |
| TEST (T (0, 0, 0, 31), "31", 2, "e", 0, Eof); |
| TEST (T (0, 0, 0, 0), "0", 1, "e", 0, Eof | Fail); |
| // leading whitespace not allowed |
| TEST (T (0, 0, 0, 0), " 2", 0, "e", 0, Fail); |
| TEST (T (0, 0, 0, 0), "99", 2, "e", 0, Eof | Fail); |
| |
| // %h Equivalent to %b. |
| STEP ("%h: equivalent to %b"); |
| TEST (T (0, 0, 0, 0, 0), "Jan", 3, "h", 0, Eof); |
| TEST (T (0, 0, 0, 0, 1), "February", 8, "h", 0, Good); |
| TEST (T (0, 0, 0, 0, 2), "Mar", 3, "h", 0, Eof); |
| TEST (T (0, 0, 0, 0, 3), "April", 5, "h", 0, Good); |
| TEST (T (0, 0, 0, 0, 4), "May", 3, "h", 0, Good); |
| TEST (T (0, 0, 0, 0, 5), "June", 4, "h", 0, Good); |
| TEST (T (0, 0, 0, 0, 6), "Jul", 3, "h", 0, Eof); |
| TEST (T (0, 0, 0, 0, 7), "August", 6, "h", 0, Good); |
| TEST (T (0, 0, 0, 0, 8), "Sep", 3, "h", 0, Eof); |
| TEST (T (0, 0, 0, 0, 9), "October", 7, "h", 0, Good); |
| TEST (T (0, 0, 0, 0, 10), "Nov", 3, "h", 0, Eof); |
| TEST (T (0, 0, 0, 0, 11), "December", 8, "h", 0, Good); |
| |
| // %H The hour (24-hour clock) [00,23]; leading zeros are permitted |
| // but not required. |
| STEP ("%H: the hour (24-hour clock)"); |
| TEST (T (0, 0, 0), "0", 1, "H", 0, Eof); |
| TEST (T (0, 0, 0), "00", 2, "H", 0, Eof); |
| TEST (T (0, 0, 0), "000", 3, "H", 0, Eof); |
| TEST (T (0, 0, 1), "1", 1, "H", 0, Eof); |
| TEST (T (0, 0, 2), "2", 1, "H", 0, Eof); |
| TEST (T (0, 0, 3), "3", 1, "H", 0, Eof); |
| TEST (T (0, 0, 11), "11", 2, "H", 0, Eof); |
| TEST (T (0, 0, 12), "12", 2, "H", 0, Eof); |
| TEST (T (0, 0, 13), "13", 2, "H", 0, Eof); |
| TEST (T (0, 0, 23), "23", 2, "H", 0, Eof); |
| TEST (T (0, 0, 23), "023", 3, "H", 0, Eof); |
| TEST (T (0, 0, 0), "024", 3, "H", 0, Eof | Fail); |
| TEST (T (0, 0, 0), "987", 3, "H", 0, Eof | Fail); |
| |
| // %I The hour (12-hour clock) [01,12]; leading zeros are permitted |
| // but not required. |
| STEP ("%I: the hour (12-hour clock)"); |
| TEST (T (0, 0, 0), "1", 1, "I", 0, Eof); |
| TEST (T (0, 0, 1), "2", 1, "I", 0, Eof); |
| TEST (T (0, 0, 2), "3", 1, "I", 0, Eof); |
| TEST (T (0, 0, 3), "4", 1, "I", 0, Eof); |
| TEST (T (0, 0, 4), "5", 1, "I", 0, Eof); |
| TEST (T (0, 0, 5), "6", 1, "I", 0, Eof); |
| TEST (T (0, 0, 6), "7", 1, "I", 0, Eof); |
| TEST (T (0, 0, 7), "8", 1, "I", 0, Eof); |
| TEST (T (0, 0, 8), "9", 1, "I", 0, Eof); |
| TEST (T (0, 0, 9), "10", 2, "I", 0, Eof); |
| TEST (T (0, 0, 10), "11", 2, "I", 0, Eof); |
| TEST (T (0, 0, 11), "12", 2, "I", 0, Eof); |
| TEST (T (0, 0, 0), "13", 2, "I", 0, Eof | Fail); |
| TEST (T (0, 0, 0), "013", 3, "I", 0, Eof | Fail); |
| TEST (T (0, 0, 0), "123", 3, "I", 0, Eof | Fail); |
| TEST (T (0, 0, 0), "0", 1, "I", 0, Eof | Fail); |
| |
| // %j The day number of the year [001,366]; leading zeros are permitted |
| // but not required. |
| TEST (T (0, 0, 0, 0, 0, 0, 0, 0), "1", 1, "j", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 0, 1), "2", 1, "j", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 0, 2), "03", 2, "j", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 0, 9), "10", 2, "j", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 0, 364), "365", 3, "j", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 0, 365), "366", 3, "j", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 0, 0), "0", 1, "j", 0, Eof | Fail); |
| TEST (T (0, 0, 0, 0, 0, 0, 0, 0), "367", 3, "j", 0, Eof | Fail); |
| |
| #ifdef __GLIBC__ |
| |
| STEP ("%k: equivalent to %H (GNU glibc extension)"); |
| |
| TEST (T (0, 0, 0), "0", 1, "k", 0, Eof); |
| TEST (T (0, 0, 1), "1", 1, "k", 0, Eof); |
| TEST (T (0, 0, 9), "9", 1, "k", 0, Eof); |
| TEST (T (0, 0, 10), "10", 2, "k", 0, Eof); |
| TEST (T (0, 0, 11), "11", 2, "k", 0, Eof); |
| TEST (T (0, 0, 12), "12", 2, "k", 0, Eof); |
| TEST (T (0, 0, 13), "13", 2, "k", 0, Eof); |
| TEST (T (0, 0, 23), "23", 2, "k", 0, Eof); |
| TEST (T (0, 0, 23), "023", 3, "k", 0, Eof); |
| TEST (T (0, 0, 0), "024", 3, "k", 0, Eof | Fail); |
| TEST (T (0, 0, 0), "987", 3, "k", 0, Eof | Fail); |
| |
| #endif // __GLIBC__ |
| |
| // %m The month number [01,12]; leading zeros are permitted |
| // but not required. |
| STEP ("%m: the month number"); |
| TEST (T (0, 0, 0, 0, 0, 0), "1", 1, "m", 0, Eof); |
| TEST (T (0, 0, 0, 0, 1, 0), "2", 1, "m", 0, Eof); |
| TEST (T (0, 0, 0, 0, 2, 0), "3", 1, "m", 0, Eof); |
| TEST (T (0, 0, 0, 0, 3, 0), "4", 1, "m", 0, Eof); |
| TEST (T (0, 0, 0, 0, 4, 0), "5", 1, "m", 0, Eof); |
| TEST (T (0, 0, 0, 0, 5, 0), "6", 1, "m", 0, Eof); |
| TEST (T (0, 0, 0, 0, 6, 0), "7", 1, "m", 0, Eof); |
| TEST (T (0, 0, 0, 0, 7, 0), "8", 1, "m", 0, Eof); |
| TEST (T (0, 0, 0, 0, 8, 0), "9", 1, "m", 0, Eof); |
| TEST (T (0, 0, 0, 0, 9, 0), "10", 2, "m", 0, Eof); |
| TEST (T (0, 0, 0, 0, 10, 0), "11", 2, "m", 0, Eof); |
| TEST (T (0, 0, 0, 0, 11, 0), "12", 2, "m", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0), "01", 2, "m", 0, Eof); |
| TEST (T (0, 0, 0, 0, 1, 0), "02", 2, "m", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0), "0", 1, "m", 0, Eof | Fail); |
| TEST (T (0, 0, 0, 0, 0, 0), "13", 2, "m", 0, Eof | Fail); |
| |
| // %M The minute [00,59]; leading zeros are permitted but not required. |
| STEP ("%M: the minute"); |
| TEST (T (0, 0), "0", 1, "M", 0, Eof); |
| TEST (T (0, 0), "00", 2, "M", 0, Eof); |
| TEST (T (0, 0), "000", 3, "M", 0, Eof); |
| TEST (T (0, 1), "1", 1, "M", 0, Eof); |
| TEST (T (0, 2), "2", 1, "M", 0, Eof); |
| TEST (T (0, 19), "19", 2, "M", 0, Eof); |
| TEST (T (0, 29), "29", 2, "M", 0, Eof); |
| TEST (T (0, 59), "59", 2, "M", 0, Eof); |
| TEST (T (0, 0), "60", 2, "M", 0, Eof | Fail); |
| |
| // %n Any white space. |
| STEP ("%n: any whitespace"); |
| TEST (T (), "", 0, "n", 0, Eof); |
| TEST (T (), " ", 1, "n", 0, Eof); |
| TEST (T (), " ", 2, "n", 0, Eof); |
| TEST (T (), " ", 3, "n", 0, Eof); |
| TEST (T (), "\n ", 2, "n", 0, Eof); |
| TEST (T (), " \t", 2, "n", 0, Eof); |
| TEST (T (), "\n\t", 2, "n", 0, Eof); |
| TEST (T (), ".", 0, "n", 0, Good); |
| TEST (T (), " 1", 1, "n", 0, Good); |
| TEST (T (), "\t 2", 2, "n", 0, Good); |
| |
| // %p The locale's equivalent of a.m or p.m. |
| STEP ("%p: the equivalent of AM/PM"); |
| TEST (T (0, 0, 1), "AM", 2, "p", 0, Good); |
| TEST (T (0, 0, 13), "PM", 2, "p", 0, Good); |
| TEST (T (0, 0, 0), "", 0, "p", 0, Eof | Fail); |
| TEST (T (0, 0, 0), "A", 1, "p", 0, Eof | Fail); |
| TEST (T (0, 0, 0), "P", 1, "p", 0, Eof | Fail); |
| TEST (T (0, 0, 0), "M", 0, "p", 0, Fail); |
| TEST (T (0, 0, 0), "A ", 1, "p", 0, Fail); |
| TEST (T (0, 0, 0), "P ", 1, "p", 0, Fail); |
| |
| // %r 12-hour clock time using the AM/PM notation if t_fmt_ampm is |
| // not an empty string in the LC_TIME portion of the current locale; |
| // in the POSIX locale, this shall be equivalent to %I:%M:%S %p. |
| STEP ("%r: 12-hour clock time using the AM/PM notation"); |
| rw_warn (0, 0, __LINE__, "%%r not being exercised"); |
| |
| |
| // %R The time as %H:%M. |
| STEP ("%R: the time as %H:%M"); |
| TEST (T (0, 0, 0), "0:0", 3, "R", 0, Eof); |
| TEST (T (0, 1, 0), "0:1", 3, "R", 0, Eof); |
| TEST (T (0, 2, 0), "0:02", 4, "R", 0, Eof); |
| TEST (T (0, 59, 0), "0:59", 4, "R", 0, Eof); |
| TEST (T (0, 48, 1), "1:48", 4, "R", 0, Eof); |
| TEST (T (0, 37, 11), "11:37", 5, "R", 0, Eof); |
| TEST (T (0, 26, 19), "19:26", 5, "R", 0, Eof); |
| TEST (T (0, 15, 22), "22:15", 5, "R", 0, Eof); |
| TEST (T (0, 4, 23), "23:04", 5, "R", 0, Eof); |
| TEST (T (0, 3, 23), "23:03:00", 5, "R", 0, Good); |
| TEST (T (0, 2, 23), "23:2:01", 4, "R", 0, Good); |
| TEST (T (0, 0, 0), "23:60", 5, "R", 0, Eof | Fail); |
| TEST (T (0, 0, 0), "24:00", 2, "R", 0, Fail); |
| |
| // %S The seconds [00,60]; leading zeros are permitted but not required. |
| STEP ("%S: the seconds"); |
| TEST (T ( 0), "0", 1, "S", 0, Eof); |
| TEST (T ( 1), "01", 2, "S", 0, Eof); |
| TEST (T ( 2), "002", 3, "S", 0, Eof); |
| TEST (T (13), "13", 2, "S", 0, Eof); |
| TEST (T (24), "24", 2, "S", 0, Eof); |
| TEST (T (34), "34", 2, "S", 0, Eof); |
| TEST (T (45), "45", 2, "S", 0, Eof); |
| TEST (T (56), "56", 2, "S", 0, Eof); |
| TEST (T (60), "60", 2, "S", 0, Eof); |
| TEST (T ( 0), "61", 2, "S", 0, Eof | Fail); |
| |
| // %t Any white space. |
| STEP ("%t: any whitespace"); |
| TEST (T (), "\t", 1, "t", 0, Eof); |
| TEST (T (), " ", 1, "t", 0, Eof); |
| TEST (T (), " ", 2, "t", 0, Eof); |
| TEST (T (), "\n ", 2, "t", 0, Eof); |
| |
| // %T The time as %H:%M:%S. |
| STEP ("%T: the time as %H:%M:%S"); |
| TEST (T ( 0, 0, 0), "0:0:00", 6, "T", 0, Eof); |
| TEST (T ( 1, 1, 0), "0:1:1", 5, "T", 0, Eof); |
| TEST (T ( 2, 2, 0), "0:02:2", 6, "T", 0, Eof); |
| TEST (T ( 3, 59, 0), "0:59:3", 6, "T", 0, Eof); |
| TEST (T ( 4, 48, 1), "1:48:04", 7, "T", 0, Eof); |
| TEST (T ( 5, 37, 11), "11:37:5", 7, "T", 0, Eof); |
| TEST (T ( 6, 26, 19), "19:26:006", 9, "T", 0, Eof); |
| TEST (T ( 7, 15, 22), "22:015:7", 8, "T", 0, Eof); |
| TEST (T ( 8, 4, 23), "023:004:8", 9, "T", 0, Eof); |
| TEST (T (60, 59, 23), "023:59:60", 9, "T", 0, Eof); |
| TEST (T ( 0, 0, 0), "23:59:61", 8, "T", 0, Eof | Fail); |
| TEST (T ( 0, 0, 0), "0:0:62", 6, "T", 0, Eof | Fail); |
| TEST (T ( 0, 0, 0), "0:0", 3, "T", 0, Eof | Fail); |
| TEST (T ( 0, 0, 0), "999", 3, "T", 0, Eof | Fail); |
| |
| // %U The week number of the year (Sunday as the first day of the week) |
| // as a decimal number [00,53]; leading zeros are permitted but not |
| // required. |
| STEP ("%U: the Sunday-based week of the year"); |
| TEST (T (0, 0, 0, 0, 0, 320, 2, 60), "9", 1, "U", 0, Eof); |
| |
| // %w The weekday as a decimal number [0,6], with 0 representing |
| // Sunday; leading zeros are permitted but not required. |
| STEP ("%w: the Sunday-based weekday as a decimal number"); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "0", 1, "w", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "00", 2, "w", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "1", 1, "w", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "01", 2, "w", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 2), "2", 1, "w", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 3), "3", 1, "w", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 4), "4", 1, "w", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 5), "5", 1, "w", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 6), "6", 1, "w", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "7", 1, "w", 0, Eof | Fail); |
| |
| // %W The week number of the year (Monday as the first day of the |
| // week) as a decimal number [00,53]; leading zeros are permitted |
| // but not required. |
| STEP ("%W: the Monday-based week of the year"); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "0", 1, "W", 0, Eof); |
| |
| // rw_warn (0, 0, __LINE__, "%%W specifier not being exercised"); |
| |
| // %x The date, using the locale's date format. |
| STEP ("%x: the date"); |
| TEST (T (0, 0, 0, 25, 6, 67), "7/25/1967", 9, "%x", 0, Eof); |
| |
| // %X The time, using the locale's time format. |
| STEP ("%X: the time"); |
| TEST (T (12, 34, 5), "5:34:12", 7, "%X", 0, Eof); |
| TEST (T (23, 45, 6), " 6:45:23", 8, " %X", 0, Eof); |
| |
| // %y The year within century. When a century is not otherwise |
| // specified, values in the range [69,99] shall refer to years 1969 |
| // to 1999 inclusive, and values in the range [00,68] shall refer |
| // to years 2000 to 2068 inclusive; leading zeros shall be permitted |
| // but shall not be required. |
| // Note: It is expected that in a future version of |
| // IEEE Std 1003.1-2001 the default century inferred from a |
| // 2-digit year will change. (This would apply to all commands |
| // accepting a 2-digit year as input.) |
| STEP ("%y: the year within century"); |
| TEST (T (0, 0, 0, 0, 0, 100), "0", 1, "%y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 100), "00", 2, "%y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 101), "1", 1, "%y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 102), "2", 1, "%y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 103), "03", 2, "%y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 168), "68", 2, "%y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 69), "69", 2, "%y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 99), "99", 2, "%y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, -1800), "100", 3, "%y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 102), "2002", 4, "%y", 0, Eof); |
| |
| // %Y The year, including the century (for example, 1988). |
| STEP ("%Y: the year, including the century"); |
| TEST (T (0, 0, 0, 0, 0, -1900), "0", 1, "%Y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, -1900), " 0", 2, " %Y", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 99), "\t1999", 5, " %Y", 0, Eof); |
| |
| STEP ("invalid pattern"); |
| TEST (T (0), "0", 0, "E", 0, Fail); |
| TEST (T (0), "0", 0, "i", 0, Fail); |
| TEST (T (0), "0", 0, "J", 0, Fail); |
| TEST (T (0), "0", 0, "N", 0, Fail); |
| TEST (T (0), "0", 0, "P", 0, Fail); |
| TEST (T (0), "0", 0, "s", 0, Fail); |
| TEST (T (0), "0", 0, "u", 0, Fail); |
| TEST (T (0), "0", 0, "z", 0, Fail); |
| TEST (T (0), "0", 0, "Z", 0, Fail); |
| |
| |
| // %Ec The locale's alternative date and time representation. |
| // %EC The name of the base year (period) in the locale's alternative |
| // representation. |
| // %Ex The locale's alternative date representation. |
| // %EX The locale's alternative time representation. |
| // %Ey The offset from %EC (year only) in the locale's alternative |
| // representation. |
| // %EY The full alternative year representation. |
| // %Od The day of the month using the locale's alternative numeric |
| // symbols; leading zeros are permitted but not required. |
| // %Oe Equivalent to %Od. |
| // %OH The hour (24-hour clock) using the locale's alternative numeric |
| // symbols. |
| // %OI The hour (12-hour clock) using the locale's alternative numeric |
| // symbols. |
| // %Om The month using the locale's alternative numeric symbols. |
| // %OM The minutes using the locale's alternative numeric symbols. |
| // %OS The seconds using the locale's alternative numeric symbols. |
| // %OU The week number of the year (Sunday as the first day of the week) |
| // using the locale's alternative numeric symbols. |
| // %Ow The number of the weekday (Sunday=0) using the locale's |
| // alternative numeric symbols. |
| // %OW The week number of the year (Monday as the first day of the |
| // week) using the locale's alternative numeric symbols. |
| // %Oy The year (offset from %C ) using the locale's alternative numeric |
| // symbols. |
| rw_warn (0, 0, __LINE__, "E modifier not being exercised"); |
| rw_warn (0, 0, __LINE__, "O modifier not being exercised"); |
| |
| // exercise pattern strings containing multiple format specifiers |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "Sun Jan", 7, "%a %b", 0, Eof); |
| TEST (T (0, 0, 0, 0, 1, 0, 1), "Mon Feb", 8, "%a %b", 0, Eof); |
| TEST (T (0, 0, 0, 0, 2, 0, 2), "Tue%nMar", 7, "%a %b", 0, Eof); |
| TEST (T (0, 0, 0, 0, 3, 0, 3), "Wed%t Apr", 8, "%a %b", 0, Eof); |
| TEST (T (0, 0, 0, 0, 2, 0, 5), "Friday March", 12, "%a %b", 0, Good); |
| } |
| |
| /**************************************************************************/ |
| |
| |
| template <class charT> |
| void test_english (charT, const char *cname, const char *locname) |
| { |
| _TRY { |
| // set the global locale object to the german locale |
| std::locale::global (std::locale (locname)); |
| } |
| _CATCH (...) { |
| rw_error (0, 0, __LINE__, |
| "locale(%#s) unexpectedly threw an exception", locname); |
| |
| return; |
| } |
| |
| // exercise abbreviated weekday names |
| FUNCTION ("get_weekday"); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "Sun", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "Mon", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 2), "Tue", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 3), "Wed", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 4), "Thu", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 5), "Fri", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 6), "Sat", 3, "a", 0, Eof); |
| |
| // exercise full weekday names |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "Sunday", 6, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "Monday", 6, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 2), "Tuesday", 7, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 3), "Wednesday", 9, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 4), "Thursday", 8, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 5), "Friday", 6, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 6), "Saturday", 8, "a", 0, Good); |
| |
| // exercise full month names |
| FUNCTION ("get_monthname"); |
| TEST (T (0, 0, 0, 0, 0), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 1), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 2), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 3), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 4), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 5), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 6), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 7), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 8), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 9), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 10), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 11), "%B", -1, "b", 0, -1); |
| |
| // exercise date (time_get::get_date()) |
| FUNCTION ("get_date"); |
| TEST (T (0, 0, 0, 1, 0, 100), "%x", 8, "x", 0, Eof); |
| |
| // exercise time (time_get::get_time()) |
| FUNCTION ("get_time"); |
| |
| int len; |
| |
| { |
| // determine whether "%X" is equivalent to "%I:%M:%S %p" |
| // (e.g., HP-UX or Linux) or to "%I:%M:%S" (e.g., Compaq |
| // Tru64 UNIX) |
| char buf [32]; |
| const std::tm tmb = mktm (0, 0, 1); |
| len = std::strftime (buf, sizeof buf, "%X", &tmb); |
| } |
| |
| const int hour = 11 == len ? 12 : 0; |
| |
| TEST (T ( 0, 0, 0), "%X", len, "X", 0, 11 == len ? Good : Eof); |
| TEST (T ( 0, 0, 1), "%X", len, "X", 0, 11 == len ? Good : Eof); |
| TEST (T ( 0, 0, 11), "%X", len, "X", 0, 11 == len ? Good : Eof); |
| TEST (T ( 0, 0, 12), "%X", len, "X", 0, 11 == len ? Good : Eof); |
| TEST (T ( 0, 0, 13), "%X", len, "X", 0, 11 == len ? Good : Eof); |
| TEST (T ( 0, 0, 23), "%X", len, "X", 0, 11 == len ? Good : Eof); |
| |
| TEST (T ( 0, 0, 12 - hour), "12:00:00 AM", len, "X", 0, Good); |
| TEST (T ( 0, 0, 1), "01:00:00 AM", len, "X", 0, Good); |
| TEST (T ( 0, 0, 2), "02:00:00 AM", len, "X", 0, Good); |
| TEST (T ( 0, 0, 3), "03:00:00 AM", len, "X", 0, Good); |
| TEST (T ( 0, 0, 4), "04:00:00 AM", len, "X", 0, Good); |
| TEST (T ( 0, 0, 5), "05:00:00 AM", len, "X", 0, Good); |
| TEST (T ( 0, 0, 6), "06:00:00 AM", len, "X", 0, Good); |
| TEST (T ( 0, 0, 7), "07:00:00 AM", len, "X", 0, Good); |
| TEST (T ( 0, 0, 8), "08:00:00 AM", len, "X", 0, Good); |
| TEST (T ( 0, 0, 9), "09:00:00 AM", len, "X", 0, Good); |
| TEST (T ( 0, 0, 10), "10:00:00 AM", len, "X", 0, Good); |
| TEST (T ( 0, 0, 11), "11:00:00 AM", len, "X", 0, Good); |
| |
| TEST (T ( 0, 0, 12), "12:00:00 PM", len, "X", 0, Good); |
| TEST (T ( 0, 0, hour + 1), "01:00:00 PM", len, "X", 0, Good); |
| TEST (T ( 0, 0, hour + 2), "02:00:00 PM", len, "X", 0, Good); |
| TEST (T ( 0, 0, hour + 3), "03:00:00 PM", len, "X", 0, Good); |
| TEST (T ( 0, 0, hour + 4), "04:00:00 PM", len, "X", 0, Good); |
| TEST (T ( 0, 0, hour + 5), "05:00:00 PM", len, "X", 0, Good); |
| TEST (T ( 0, 0, hour + 6), "06:00:00 PM", len, "X", 0, Good); |
| TEST (T ( 0, 0, hour + 7), "07:00:00 PM", len, "X", 0, Good); |
| TEST (T ( 0, 0, hour + 8), "08:00:00 PM", len, "X", 0, Good); |
| TEST (T ( 0, 0, hour + 9), "09:00:00 PM", len, "X", 0, Good); |
| TEST (T ( 0, 0, hour + 10), "10:00:00 PM", len, "X", 0, Good); |
| TEST (T ( 0, 0, hour + 11), "11:00:00 PM", len, "X", 0, Good); |
| |
| TEST (T (60, 9, hour + 11), "11:09:60 PM", len, "X", 0, Good); |
| } |
| |
| /**************************************************************************/ |
| |
| |
| template <class charT> |
| void test_german (charT, const char *cname, const char *locname) |
| { |
| _TRY { |
| // set the global locale object to the german locale |
| std::locale::global (std::locale (locname)); |
| } |
| _CATCH (...) { |
| rw_error (0, 0, __LINE__, |
| "locale(%#s) unexpectedly threw an exception", locname); |
| |
| return; |
| } |
| |
| // exercise abbreviated weekday names |
| // these may be { So, Mo, Di, Mi, Do, Sa } (e.g., Compaq Tru64 UNIX) |
| // or { Son, Mon, Die, Mit, Don, Sam } (e.g., Linux, SunOS, or Win32) |
| FUNCTION ("get_weekday"); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "%a", -1, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "%a", -1, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 2), "%a", -1, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 3), "%a", -1, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 4), "%a", -1, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 5), "%a", -1, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 6), "%a", -1, "a", 0, Eof); |
| |
| // exercise full weekday names |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "Sonntag", 7, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "Montag", 6, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 2), "Dienstag", 8, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 3), "Mittwoch", 8, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 4), "Donnerstag", 10, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 5), "Freitag", 7, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 6), "Samstag", 7, "a", 0, Good); |
| |
| // exercise full month names |
| FUNCTION ("get_monthname"); |
| TEST (T (0, 0, 0, 0, 0), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 1), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 2), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 3), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 4), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 5), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 6), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 7), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 8), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 9), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 10), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 11), "%B", -1, "b", 0, -1); |
| } |
| |
| /**************************************************************************/ |
| |
| |
| template <class charT> |
| void test_danish (charT, const char *cname, const char *locname) |
| { |
| _TRY { |
| // set the global locale object to the german locale |
| std::locale::global (std::locale (locname)); |
| } |
| _CATCH (...) { |
| rw_error (0, 0, __LINE__, |
| "locale(%#s) unexpectedly threw an exception", locname); |
| |
| return; |
| } |
| |
| // exercise abbreviated weekday names |
| FUNCTION ("get_weekday"); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "%a", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "%a", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 2), "%a", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 3), "%a", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 4), "%a", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 5), "%a", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 6), "%a", 3, "a", 0, Eof); |
| |
| // avoid using <s><o/><n> or <s><o/><n><d><a><g> since it |
| // contains the non-ASCII character <o/> (o with a slash) |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "man", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 2), "tir", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 3), "ons", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 4), "tor", 3, "a", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 5), "fre", 3, "a", 0, Eof); |
| |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "mandag", 6, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 2), "tirsdag", 7, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 3), "onsdag", 6, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 4), "torsdag", 7, "a", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 5), "fredag", 6, "a", 0, Good); |
| |
| // exercise full month names |
| FUNCTION ("get_monthname"); |
| TEST (T (0, 0, 0, 0, 0), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 1), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 2), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 3), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 4), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 5), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 6), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 7), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 8), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 9), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 10), "%B", -1, "b", 0, -1); |
| TEST (T (0, 0, 0, 0, 11), "%B", -1, "b", 0, -1); |
| } |
| |
| /**************************************************************************/ |
| |
| |
| struct time_data |
| { |
| const char* abday [7]; // %a abbreviated day name |
| const char* day [7]; // %A full day name |
| const char* abmon [12]; // %b abbreviated month name |
| const char* mon [12]; // %B full month name |
| const char* am_pm [2]; // %p AM/PM designator |
| const char* d_t_fmt; // %c date and time |
| const char* d_fmt; // %x date |
| const char* t_fmt; // %X time |
| const char* t_fmt_ampm; // %r time with the AM/PM designaror |
| const char* era_d_t_fmt; // %Ec alternative date and time |
| const char* era_d_fmt; // %EX alternative date |
| const char* era_t_fmt; // %Ex alternative time |
| const char* const* alt_digits; // alternative numeric symbols |
| |
| struct era_data { |
| int offset; |
| int start_day; // [1..31] |
| int start_mon; // [0..11] |
| int start_year; |
| int end_day; // [1..31] |
| int end_mon; // [0..11] |
| int end_year; // INT_MIN, [0..9999], INT_MAX |
| const char *name; |
| const char *format; |
| }; |
| |
| const era_data* era; |
| }; |
| |
| |
| // the root of the locale directory (RWSTD_LOCALE_ROOT) |
| // set in main() instead of here to avoid Solaris 7 putenv() bug (PR #30017) |
| static const char* |
| locale_root; |
| |
| |
| static const char* |
| make_LC_TIME (const time_data *td) |
| { |
| static char locnamebuf [L_tmpnam + 32]; |
| |
| if (*locnamebuf) |
| return locnamebuf; |
| |
| // create a temporary locale definition file |
| char srcfname [L_tmpnam + 32]; |
| std::sprintf (srcfname, "%s" SLASH "LC_TIME.src", locale_root); |
| |
| std::FILE *fout = std::fopen (srcfname, "w"); |
| |
| std::fprintf (fout, "LC_TIME\n"); |
| |
| unsigned i; |
| |
| std::fprintf (fout, "abday "); |
| |
| for (i = 0; i != sizeof td->abday / sizeof *td->abday; ++i) { |
| std::fprintf (fout, "\""); |
| pcs_write (fout, td->abday [i]); |
| std::fprintf (fout, "\"%c", i < 6 ? ';' : '\n'); |
| } |
| |
| std::fprintf (fout, "day "); |
| |
| for (i = 0; i != sizeof td->day / sizeof *td->day; ++i) { |
| std::fprintf (fout, "\""); |
| pcs_write (fout, td->day [i]); |
| std::fprintf (fout, "\"%c", i < 6 ? ';' : '\n'); |
| } |
| |
| std::fprintf (fout, "abmon "); |
| |
| for (i = 0; i != sizeof td->abmon / sizeof *td->abmon; ++i) { |
| std::fprintf (fout, "\""); |
| pcs_write (fout, td->abmon [i]); |
| std::fprintf (fout, "\"%c", i < 11 ? ';' : '\n'); |
| } |
| |
| std::fprintf (fout, "mon "); |
| |
| for (i = 0; i != sizeof td->mon / sizeof *td->mon; ++i) { |
| std::fprintf (fout, "\""); |
| pcs_write (fout, td->mon [i]); |
| std::fprintf (fout, "\"%c", i < 11 ? ';' : '\n'); |
| } |
| |
| std::fprintf (fout, "am_pm "); |
| |
| for (i = 0; i != sizeof td->am_pm / sizeof *td->am_pm; ++i) { |
| std::fprintf (fout, "\""); |
| pcs_write (fout, td->am_pm [i]); |
| std::fprintf (fout, "\"%c", i < 1 ? ';' : '\n'); |
| } |
| |
| // write out d_t_fmt, d_fmt, t_fmt, etc. |
| // preface each line with a comment giving |
| // the specification in a human-readable format |
| std::fprintf (fout, "\n# d_t_fmt \"%s\"\nd_t_fmt \"", |
| td->d_t_fmt); |
| pcs_write (fout, td->d_t_fmt); |
| |
| std::fprintf (fout, "\"\n\n# d_fmt \"%s\"\nd_fmt \"", |
| td->d_fmt); |
| pcs_write (fout, td->d_fmt); |
| |
| std::fprintf (fout, "\"\n\n# t_fmt \"%s\"\nt_fmt \"", |
| td->t_fmt); |
| pcs_write (fout, td->t_fmt); |
| |
| std::fprintf (fout, "\"\n\n# t_fmt_ampm \"%s\"\nt_fmt_ampm \"", |
| td->t_fmt_ampm); |
| pcs_write (fout, td->t_fmt_ampm); |
| |
| std::fprintf (fout, "\"\n\n# era_d_t_fmt \"%s\"\nera_d_t_fmt \"", |
| td->era_d_t_fmt); |
| pcs_write (fout, td->era_d_t_fmt); |
| |
| std::fprintf (fout, "\"\n\n# era_d_fmt \"%s\"\nera_d_fmt \"", |
| td->era_d_fmt); |
| pcs_write (fout, td->era_d_fmt); |
| |
| std::fprintf (fout, "\"\n\n# era_t_fmt \"%s\"\nera_t_fmt \"", |
| td->era_t_fmt); |
| pcs_write (fout, td->era_t_fmt); |
| |
| std::fprintf (fout, "\"\nalt_digits "); |
| |
| for (i = 0; td->alt_digits [i]; ++i) { |
| std::fprintf (fout, "\""); |
| pcs_write (fout, td->alt_digits [i]); |
| std::fprintf (fout, "\"%c", td->alt_digits [i + 1] ? ';' : '\n'); |
| } |
| |
| std::fprintf (fout, "\n\nera "); |
| |
| for (i = 0; INT_MIN != td->era [i].offset; ++i) { |
| |
| char segment [256]; |
| |
| std::sprintf (segment, "%c:%u:%04d/%02d/%02d:", |
| td->era [i].offset < 0 ? '-' : '+', |
| td->era [i].offset < 0 ? -td->era [i].offset |
| : td->era [i].offset, |
| td->era [i].start_year + 1900, |
| td->era [i].start_mon + 1, |
| td->era [i].start_day); |
| |
| const char *end_date = 0; |
| |
| if (INT_MIN == td->era [i].end_year) |
| end_date = "-*"; // beginning of time |
| else if (INT_MAX == td->era [i].end_year) |
| end_date = "+*"; // end of time |
| |
| if (end_date) { |
| std::sprintf (segment + std::strlen (segment), "%s:%s:%s", |
| end_date, td->era [i].name, td->era [i].format); |
| } |
| else { |
| std::sprintf (segment + std::strlen (segment), |
| "%04d/%02d/%02d:%s:%s", |
| td->era [i].end_year + 1900, |
| td->era [i].end_mon + 1, |
| td->era [i].end_day, |
| td->era [i].name, |
| td->era [i].format); |
| } |
| |
| std::fprintf (fout, "\""); |
| pcs_write (fout, segment); |
| std::fprintf (fout, "\"%c", |
| INT_MIN == td->era [i + 1].offset ? '\n' : ';'); |
| } |
| |
| std::fprintf (fout, "\nEND LC_TIME\n"); |
| |
| std::fclose (fout); |
| |
| // create a temporary character map file |
| char cmfname [L_tmpnam + 32]; |
| std::sprintf (cmfname, "%s" SLASH "pcs.cm", locale_root); |
| |
| fout = std::fopen (cmfname, "w"); |
| pcs_write (fout, 0); |
| |
| std::fclose (fout); |
| |
| // process the locale definition file and the character map |
| const char* const locname = |
| rw_localedef ("-w ", srcfname, cmfname, "test-locale"); |
| |
| return locname; |
| } |
| |
| |
| static const char* |
| make_LC_TIME () |
| { |
| const char* const alt_digits[] = { |
| "", "1st", "2nd", "3rd", "4th", |
| "5th", "6th", "7th", "8th", "9th", |
| "10th", "11th", "12th", "13th", "14th", |
| "15th", "16th", "17th", "18th", "19th", |
| "20th", "21st", "22nd", "23rd", "24th", |
| "25th", "26th", "27th", "28th", "29th", |
| "30th", "31st", 0 // sentinel |
| }; |
| |
| const time_data::era_data era[] = { |
| // some entries copied and modified from HP-UX 11.11 ja_JP.utf8 |
| // |
| // # 1990-01-02 and onward: "Heisei%EyNen" (1990 is Heisei 2 Nen.) |
| // # 1990-01-01 to 1990-01-02: "%C" (no era specified) |
| // # 1989-01-08 to 1989-12-31: "HeiseiGannen" |
| // # 1927-01-01 to 1989-01-07: "Showa%EyNen" (1927 is Showa 2 Nen.) |
| // # 1927-01-01 and prior: "foo" |
| // era "+:2:1990/01/02:+*:<U????><U????>:%EC%Ey<U????>"; |
| // "+:1:1989/01/08:1989/12/31:<U????>:%EC<U????><U????>"; |
| // "+:2:1927/01/01:1989/01/07:<U????><U????>:%EC%Ey<U????>"; |
| // "-:7:1926/12/31:-*:foo:bar%EC%Ey" |
| |
| // 7|2 |1 | |2 starting year in an era |
| // <<<|>>>>>>>>>|>>>>>>>>>|.|>>> direction in which years increase |
| // ^ ^ ^ ^ |
| // | | | | |
| // | | | +-> Jan 2, 1990 (Heisei %Ey Nen) |
| // | | +-> Dec 31, 1989 (%C) |
| // | +-> Jan 7, 1989 (Heisei Gannen) |
| // +-> Jan 1, 1927 (Showa %Ey Nen) |
| // +-< Dec 31, 1926 (foobar %Ey) |
| |
| { 2, 2, 0, 90, 0, 0, INT_MAX, "Heisei", "%EC %Ey Nen" }, |
| { 1, 8, 0, 89, 31, 11, 89, "Heisei", "%EC Gannen" }, |
| { 2, 1, 0, 27, 7, 0, 89, "Showa", "%EC %Ey Nen" }, |
| { -7, 31, 11, 26, 0, 0, INT_MIN, "bar", "foo%EC %Ey" }, |
| { INT_MIN /* sentinel entry */, 0, 0, 0, 0, 0, 0, 0, 0 } |
| }; |
| |
| const time_data td = { |
| // %a |
| { "[Sun]", "[Mon]", "[Tue]", "[Wed]", "[Thu]", "[Fri]", "[Sat]" }, |
| |
| // %A |
| { |
| "[Sunday]", "[Monday]", "[Tuesday]", "[Wednesday]", "[Thursday]", |
| "[Friday]", "[Saturday]" |
| }, |
| |
| // %b |
| { |
| "[Jan]", "[Feb]", "[Mar]", "[Apr]", "[May]", "[Jun]", |
| "[Jul]", "[Aug]", "[Sep]", "[Oct]", "[Nov]", "[Dec]", |
| }, |
| |
| // %B |
| { |
| "[January]", "[February]", "[March]", "[April]", "[May]", "[June]", |
| "[July]", "[August]", "[September]", "[October]", "[November]", |
| "[December]", |
| }, |
| |
| { "[A.M.]", "[P.M.]" }, // %p |
| |
| "[[%a][%b][%d][%H][%M][%S][%y]]", // %c |
| "[[%3m][%.4d][%4.3y]]", // %x |
| "[[%3H][%.4M][%4.3S]]", // %X |
| "[[%I][%M][%S][%p]]", // %r |
| "[[%A][%B][%Od][%H][%M][%S][%Y]]", // %Ec |
| "%Ow weekday, %OU week, %Oy year", // %Ex |
| "%OH hour, %OM minute, %OS second", // %EX |
| |
| alt_digits, era |
| }; |
| |
| const char* const locname = make_LC_TIME (&td); |
| |
| return locname; |
| } |
| |
| /**************************************************************************/ |
| |
| |
| template <class charT> |
| void test_user (charT, const char *cname, const char *locname) |
| { |
| const char* const envar = std::getenv (LOCALE_ROOT_ENVAR); |
| |
| rw_info (0, 0, __LINE__, |
| "std::time_get<%s>, in locale(\"%s\") " |
| "created from a generated LC_TIME file; " |
| LOCALE_ROOT_ENVAR "=%s", |
| cname, locname, envar); |
| |
| // construct a locale object from the binary database |
| std::locale loc; |
| |
| _TRY { |
| loc = std::locale (loc, locname, std::locale::time); |
| } |
| _CATCH (...) { |
| rw_error (0, 0, __LINE__, |
| "locale (locale (), \"%s\", locale::time) " |
| "unexpectedly threw an exception", locname); |
| return; |
| } |
| |
| // set the global locale (used by the test function) |
| std::locale::global (loc); |
| |
| |
| // %Ec: The locale's alternative date and time representation. |
| STEP ("%Ec: alternative date and time representation"); |
| TEST (T (0, 0, 0, 1, 0, 0, 0), |
| // "[[%A][%B][%Od][%H][%M][%S][%Y]]" |
| "[[[Sunday]][[January]][1st][00][00][00][1900]]", 46, |
| "%Ec", 0, Good); |
| |
| TEST (T (5, 4, 3, 2, 1, 1, 1), |
| "[[[monday]][[february]][2nd][03][04][05][1901]]", 47, |
| "%Ec", 0, Good); |
| |
| TEST (T (60, 59, 23, 31, 2, -1898, 2), |
| // %Y requires a four digit year, 02 is not treated as 2002 |
| "[[[TUE]][[MAR]][31st][23][59][60][02]]", 38, |
| "%Ec", 0, Good); |
| |
| // %EC: The name of the base year (period) in the locale's |
| // alternative representation. |
| |
| // %Ex: The locale's alternative date representation. |
| STEP ("%Ex: alternative date representation"); |
| |
| // verify that facet computes the remaining tm members from |
| // the supplied data |
| TEST (T (0, 0, 0, 21, 4, 2002, 2, 141), |
| // "%Ow weekday, %OU week, %Oy year" |
| "2nd weekday, 21st week, 2nd year", 32, |
| // i.e., May 21, 2002 |
| "%Ex", 0, Good); |
| |
| // %EX: The locale's alternative time representation. |
| STEP ("%EX: alternative time representation"); |
| // verify that 0 is correctly parsed if alternative numeric |
| // symbols are expected and the symbol for zero is empty |
| TEST (T (0, 1, 2), |
| // "%OH hour, %OM minute, %OS second" |
| "2nd hour, 1st minute, 0 second", 30, |
| "%EX", 0, Good); |
| |
| TEST (T (21, 22, 23), |
| // "%OH hour, %OM minute, %OS second" |
| "23rd hour, 22nd minute, 21st second", 35, |
| "%EX", 0, Good); |
| |
| // %Ey: The offset from %EC (year only) in the locale's |
| // alternative representation. |
| STEP ("%Ey: offset from %EC in alternative representation."); |
| rw_warn (0, 0, __LINE__, "%%Ey not being exercised"); |
| |
| // %EY: The full alternative year representation. |
| STEP ("%EY: the full alternative year representation"); |
| rw_warn (0, 0, __LINE__, "%%EY not being exercised"); |
| |
| // %Od: The day of the month using the locale's alternative |
| // numeric symbols; leading zeros are permitted but not required. |
| STEP ("%Od: the day of the month using alternative numeric symbols"); |
| TEST (T (0, 0, 0, 1), "1st", 3, "%Od", 0, Good); |
| TEST (T (0, 0, 0, 2), "2nd", 3, "%Od", 0, Good); |
| TEST (T (0, 0, 0, 11), "11th", 4, "%Od", 0, Good); |
| TEST (T (0, 0, 0, 21), "21st", 4, "%Od", 0, Good); |
| TEST (T (0, 0, 0, 30), "30th", 4, "%Od", 0, Good); |
| TEST (T (0, 0, 0, 31), "31st", 4, "%Od", 0, Good); |
| TEST (T (0, 0, 0, 0), "32", 2, "%Od", 0, Eof | Fail); |
| |
| // %Oe: Equivalent to %Od. |
| STEP ("%Oe: equivalent to %Od"); |
| TEST (T (0, 0, 0, 3), "3rd", 3, "%Oe", 0, Good); |
| TEST (T (0, 0, 0, 4), "4th", 3, "%Oe", 0, Good); |
| TEST (T (0, 0, 0, 9), "9th", 3, "%Oe", 0, Good); |
| TEST (T (0, 0, 0, 10), "10th", 4, "%Oe", 0, Good); |
| TEST (T (0, 0, 0, 0), "32nd", 2, "%Oe", 0, Fail); |
| TEST (T (0, 0, 0, 0), "33", 2, "%Oe", 0, Eof | Fail); |
| |
| // %OH: The hour (24-hour clock) using the locale's alternative |
| // numeric symbols. |
| STEP ("%OH: the hour (24-hour clock) using alternative numeric symbols"); |
| TEST (T (0, 0, 0), "0", 1, "%OH", 0, Eof); |
| TEST (T (0, 0, 0), "00", 2, "%OH", 0, Eof); |
| TEST (T (0, 0, 1), "1st", 3, "%OH", 0, Good); |
| TEST (T (0, 0, 2), "2nd", 3, "%OH", 0, Good); |
| TEST (T (0, 0, 11), "11th", 4, "%OH", 0, Good); |
| TEST (T (0, 0, 12), "12th", 4, "%OH", 0, Good); |
| TEST (T (0, 0, 13), "13th", 4, "%OH", 0, Good); |
| TEST (T (0, 0, 23), "23rd", 4, "%OH", 0, Good); |
| |
| // %OI: The hour (12-hour clock) using the locale's alternative |
| // numeric symbols. |
| STEP ("%OI: the hour (12-hour clock) using alternative numeric symbols"); |
| TEST (T (0, 0, 0), "0", 1, "%OI", 0, Eof); |
| TEST (T (0, 0, 0), "000", 3, "%OI", 0, Eof); |
| TEST (T (0, 0, 3), "3rd", 3, "%OI", 0, Good); |
| TEST (T (0, 0, 11), "11th", 4, "%OI", 0, Good); |
| TEST (T (0, 0, 12), "12th", 4, "%OI", 0, Good); |
| TEST (T (0, 0, 0), "13th", 4, "%OI", 0, Fail); |
| TEST (T (0, 0, 0), "14", 2, "%OI", 0, Eof | Fail); |
| |
| // %Om: The month using the locale's alternative numeric symbols. |
| STEP ("%Om: the month using alternative numeric symbols"); |
| TEST (T (0, 0, 0, 0, 0), "1st", 3, "%Om", 0, Good); |
| TEST (T (0, 0, 0, 0, 1), "2nd", 3, "%Om", 0, Good); |
| TEST (T (0, 0, 0, 0, 2), "3rd", 3, "%Om", 0, Good); |
| TEST (T (0, 0, 0, 0, 3), "4th", 3, "%Om", 0, Good); |
| TEST (T (0, 0, 0, 0, 4), "5th", 3, "%Om", 0, Good); |
| TEST (T (0, 0, 0, 0, 5), "6th", 3, "%Om", 0, Good); |
| TEST (T (0, 0, 0, 0, 6), "7th", 3, "%Om", 0, Good); |
| TEST (T (0, 0, 0, 0, 7), "8th", 3, "%Om", 0, Good); |
| TEST (T (0, 0, 0, 0, 8), "9th", 3, "%Om", 0, Good); |
| TEST (T (0, 0, 0, 0, 9), "10th", 4, "%Om", 0, Good); |
| TEST (T (0, 0, 0, 0, 10), "11th", 4, "%Om", 0, Good); |
| TEST (T (0, 0, 0, 0, 11), "12th", 4, "%Om", 0, Good); |
| TEST (T (0, 0, 0, 0, 0), "13th", 4, "%Om", 0, Fail); |
| TEST (T (0, 0, 0, 0, 0), "0", 1, "%Om", 0, Eof | Fail); |
| TEST (T (0, 0, 0, 0, 0), "00", 2, "%Om", 0, Eof | Fail); |
| TEST (T (0, 0, 0, 0, 0), "01", 2, "%Om", 0, Eof | Fail); |
| |
| // %OM: The minutes using the locale's alternative numeric symbols. |
| STEP ("%OM: the minutes using alternative numeric symbols"); |
| TEST (T (0, 0), "0", 1, "%OM", 0, Eof); |
| TEST (T (0, 1), "1st", 3, "%OM", 0, Good); |
| TEST (T (0, 2), "2nd", 3, "%OM", 0, Good); |
| TEST (T (0, 3), "3rd", 3, "%OM", 0, Good); |
| TEST (T (0, 4), "4th", 3, "%OM", 0, Good); |
| TEST (T (0, 29), "29th", 4, "%OM", 0, Good); |
| TEST (T (0, 30), "30th", 4, "%OM", 0, Good); |
| TEST (T (0, 31), "31st", 4, "%OM", 0, Good); |
| TEST (T (0, 32), "32", 2, "%OM", 0, Eof); |
| TEST (T (0, 0), "60", 2, "%OM", 0, Eof | Fail); |
| TEST (T (0, 0), "2", 1, "%OM", 0, Eof | Fail); |
| |
| // %OS: The seconds using the locale's alternative numeric symbols. |
| STEP ("%OS: the seconds using alternative numeric symbols"); |
| TEST (T ( 0), "0", 1, "%OS", 0, Eof); |
| TEST (T ( 1), "1st", 3, "%OS", 0, Good); |
| TEST (T ( 2), "2nd", 3, "%OS", 0, Good); |
| TEST (T ( 3), "3rd", 3, "%OS", 0, Good); |
| TEST (T ( 4), "4th", 3, "%OS", 0, Good); |
| TEST (T (29), "29th", 4, "%OS", 0, Good); |
| TEST (T (30), "30th", 4, "%OS", 0, Good); |
| TEST (T (31), "31st", 4, "%OS", 0, Good); |
| TEST (T (32), "32", 2, "%OS", 0, Eof); |
| TEST (T (59), "059", 3, "%OS", 0, Eof); |
| TEST (T (60), "0060", 4, "%OS", 0, Eof); |
| TEST (T ( 0), "61", 2, "%OS", 0, Eof | Fail); |
| TEST (T ( 0), "21", 2, "%OS", 0, Eof | Fail); |
| |
| // %OU: The week number of the year (Sunday as the first day of the week) |
| // using the locale's alternative numeric symbols. |
| STEP ("%OU: the Sunday-based week using alternative numeric symbols"); |
| rw_warn (0, 0, __LINE__, "%%OU not being exercised"); |
| |
| // %Ow: The number of the weekday (Sunday=0) using the locale's |
| // alternative numeric symbols. |
| STEP ("%Ow: Sunday-based weekday using alternative numeric symbols"); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "0", 1, "%Ow", 0, Eof); |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "1st", 3, "%Ow", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 2), "2nd", 3, "%Ow", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 6), "6th", 3, "%Ow", 0, Good); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "7th", 3, "%Ow", 0, Fail); |
| TEST (T (0, 0, 0, 0, 0, 0, 0), "8", 1, "%Ow", 0, Eof | Fail); |
| |
| // %OW: The week number of the year (Monday as the first day of the week) |
| // using the locale's alternative numeric symbols. |
| STEP ("%OW: the Monday-based week using alternative numeric symbols"); |
| |
| TEST (T (0, 0, 0, 0, 0, 0, 1), "1st", 3, "%OW", 0, Good); |
| // rw_warn (0, 0, __LINE__, "%%OW not being exercised"); |
| |
| // %Oy: The year (offset from %C ) using the locale's alternative |
| // numeric symbols. |
| STEP ("%Oy: year offset from %C using alternative numeric symbols"); |
| rw_warn (0, 0, __LINE__, "%%Oy not being exercised"); |
| } |
| |
| /**************************************************************************/ |
| |
| |
| // try to find a named locale (use a grep expression if available) |
| static const char* |
| find_locale (const char *name) |
| { |
| #if !defined (_WIN32) && !defined (_WIN64) |
| |
| rw_locales (_UNUSED_CAT, name); |
| return rw_locales (LC_ALL, name); |
| |
| #else // _WIN{32,64} |
| |
| // FIXME: handle non-UNIX systems |
| for (const char *loc = rw_locales (); loc && *loc; |
| loc += std::strlen (loc) + 1) { |
| |
| if (!std::strcmp (loc, name)) |
| return loc; |
| } |
| |
| return 0; |
| |
| #endif // _WIN{32,64} |
| } |
| |
| /**************************************************************************/ |
| |
| static int |
| run_test (int, char**) |
| { |
| // set up RWSTD_LOCALE_ROOT and other environment variables |
| // here as opposed to at program startup to work around a |
| // SunOS 5.7 bug in putenv() (PR ##30017) |
| locale_root = rw_set_locale_root (); |
| |
| // store the next available file descriptor |
| // in order to detect file descriptor leaks |
| const int fd0 = rw_nextfd (0); |
| |
| test_posix (char (), "char"); |
| |
| const char *locname; |
| |
| #if !defined (_WIN32) && !defined (_WIN64) |
| |
| const char en_US[] = "en_US"; |
| const char de[] = "^de[^a-z1-9]*"; |
| const char da[] = "^da[^a-z1-9]*"; |
| |
| #else // dumbass Windows |
| |
| const char en_US[] = "ENU"; |
| const char de[] = "DEU"; |
| const char da[] = "DAN"; |
| |
| #endif |
| |
| int nnamed = 0; |
| |
| // try to find and exercise the english locale |
| if ((locname = find_locale (en_US)) && *locname) { |
| test_english (char (), "char", locname); |
| ++nnamed; |
| } |
| |
| // try to find and exercise the german locale |
| if ((locname = find_locale (de)) && *locname) { |
| test_german (char (), "char", locname); |
| ++nnamed; |
| } |
| |
| // try to find and exercise the danish locale |
| if ((locname = find_locale (da)) && *locname) { |
| test_danish (char (), "char", locname); |
| ++nnamed; |
| } |
| |
| ////////////////////////////////////////////////////////////////// |
| // exercise the time_get facets with a user-defined locale |
| std::locale::global (std::locale ("C")); |
| |
| // create a LC_TIME database based on user-defined data |
| locname = make_LC_TIME (); |
| |
| if (!locname) { |
| rw_error (0, 0, __LINE__, "failed to generate LC_TIME locale data"); |
| return 0; |
| } |
| |
| test_user (char (), "char", locname); |
| |
| #ifndef _RWSTD_NO_WCHAR_T |
| |
| test_posix (wchar_t (), "wchar_t"); |
| |
| test_user (wchar_t (), "wchar_t", locname); |
| |
| #endif // _RWSTD_NO_WCHAR_T |
| |
| // reset the gloab locale to free up resources (such as file |
| // descriptors used by time_get_byname to map locale databases) |
| std::locale::global (std::locale ("C")); |
| |
| const int fd1 = rw_nextfd (0); |
| |
| rw_assert (0 == fd1 - fd0, 0, __LINE__, |
| "%d file descriptor leaks detected", fd1 - fd0); |
| |
| rw_assert (0 != nnamed, 0, __LINE__, |
| "time_get not exercised in named locales"); |
| |
| return 0; |
| } |
| |
| /**************************************************************************/ |
| |
| int main (int argc, char *argv[]) |
| { |
| return rw_test (argc, argv, __FILE__, |
| "lib.locale.time.get", |
| 0 /* no comment */, |
| run_test, |
| "", |
| 0); |
| } |