1#include "locale_test.h"
2
3#if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS)
4#  include <locale>
5#  include <sstream>
6#  include <memory>
7#  include <stdexcept>
8
9#  if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
10using namespace std;
11#  endif
12
13static const char* tested_locales[] = {
14// name,
15#  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
16   "fr_FR",
17   "ru_RU.koi8r",
18   "en_GB",
19   "en_US",
20#  endif
21   "",
22   "C"
23};
24
25void LocaleTest::_time_put_get( const locale& loc )
26{
27  {
28    typedef time_put<char, ostreambuf_iterator<char, char_traits<char> > > time_put_facet;
29    CPPUNIT_ASSERT( has_facet<time_put_facet>(loc) );
30    const time_put_facet& tmp = use_facet<time_put_facet>(loc);
31
32    struct tm xmas = { 0, 0, 12, 25, 11, 93 };
33    ostringstream ostr;
34    ostr.imbue(loc);
35    string format = "%B %d %Y";
36
37    time_put_facet::iter_type ret = tmp.put(ostr, ostr, ' ', &xmas, format.data(), format.data() + format.size());
38    CPPUNIT_ASSERT( !ret.failed() );
39
40    /*
41     * In other words, user conformation is required for reliable parsing
42     * of user-entered dates and times, but machine-generated formats can be
43     * parsed reliably. This allows parsers to be aggressive about interpreting
44     * user variations on standard format.
45     *
46     *                                             ISO/IEC 14882, 22.2.5.1
47     */
48    typedef time_get<char, istreambuf_iterator<char, char_traits<char> > > time_get_facet;
49    CPPUNIT_ASSERT( has_facet<time_get_facet>(loc) );
50    const time_get_facet& tmg = use_facet<time_get_facet>(loc);
51    basic_ios<char> io(0);
52    io.imbue(loc);
53
54    istringstream istr( ostr.str() );
55    istreambuf_iterator<char, char_traits<char> > i( istr );
56    istreambuf_iterator<char, char_traits<char> > e;
57    ios_base::iostate err = ios_base::goodbit;
58    struct tm other = { 15, 20, 9, 14, 7, 105 };
59
60    i = tmg.get_monthname( i, e, io, err, &other );
61    CPPUNIT_ASSERT( err == ios_base::goodbit );
62    CPPUNIT_ASSERT( other.tm_mon == xmas.tm_mon );
63
64    ++i; ++i; ++i; ++i; // skip day of month and spaces around it
65    i = tmg.get_year( i, e, io, err, &other );
66
67    CPPUNIT_ASSERT( err == ios_base::eofbit );
68    CPPUNIT_ASSERT( other.tm_year == xmas.tm_year );
69
70    ostringstream ostrX;
71    ostrX.imbue(loc);
72    format = "%x %X";
73
74    ret = tmp.put(ostrX, ostrX, ' ', &xmas, format.data(), format.data() + format.size());
75    CPPUNIT_ASSERT( !ret.failed() );
76
77    istringstream istrX( ostrX.str() );
78    istreambuf_iterator<char, char_traits<char> > j( istrX );
79
80    err = ios_base::goodbit;
81
82    struct tm yet_more = { 15, 20, 9, 14, 7, 105 };
83
84    j = tmg.get_date( j, e, io, err, &yet_more );
85
86    CPPUNIT_ASSERT( err == ios_base::goodbit );
87
88    CPPUNIT_ASSERT( yet_more.tm_sec != xmas.tm_sec );
89    CPPUNIT_ASSERT( yet_more.tm_min != xmas.tm_min );
90    CPPUNIT_ASSERT( yet_more.tm_hour != xmas.tm_hour );
91    CPPUNIT_ASSERT( yet_more.tm_mday == xmas.tm_mday );
92    CPPUNIT_ASSERT( yet_more.tm_mon == xmas.tm_mon );
93    CPPUNIT_ASSERT( yet_more.tm_year == xmas.tm_year );
94
95    ++j; // skip space
96
97    j = tmg.get_time( j, e, io, err, &yet_more );
98
99    CPPUNIT_ASSERT( err == ios_base::eofbit || err == ios_base::goodbit );
100
101    CPPUNIT_ASSERT( yet_more.tm_sec == xmas.tm_sec );
102    CPPUNIT_ASSERT( yet_more.tm_min == xmas.tm_min );
103    CPPUNIT_ASSERT( yet_more.tm_hour == xmas.tm_hour );
104    CPPUNIT_ASSERT( yet_more.tm_mday == xmas.tm_mday );
105    CPPUNIT_ASSERT( yet_more.tm_mon == xmas.tm_mon );
106    CPPUNIT_ASSERT( yet_more.tm_year == xmas.tm_year );
107  }
108#  if !defined (STLPORT) || !defined (_STLP_NO_WCHAR_T)
109  {
110    typedef time_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > > time_put_facet;
111    CPPUNIT_ASSERT( has_facet<time_put_facet>(loc) );
112    const time_put_facet& tmp = use_facet<time_put_facet>(loc);
113
114    struct tm xmas = { 0, 0, 12, 25, 11, 93 };
115    wostringstream ostr;
116    ostr.imbue(loc);
117    wstring format = L"%B %d %Y";
118
119    time_put_facet::iter_type ret = tmp.put(ostr, ostr, ' ', &xmas, format.data(), format.data() + format.size());
120    CPPUNIT_ASSERT( !ret.failed() );
121
122    /*
123     * In other words, user conformation is required for reliable parsing
124     * of user-entered dates and times, but machine-generated formats can be
125     * parsed reliably. This allows parsers to be aggressive about interpreting
126     * user variations on standard format.
127     *
128     *                                             ISO/IEC 14882, 22.2.5.1
129     */
130    typedef time_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > > time_get_facet;
131    CPPUNIT_ASSERT( has_facet<time_get_facet>(loc) );
132    const time_get_facet& tmg = use_facet<time_get_facet>(loc);
133    // Intentional instantiation with char to show a bug in a previous STLport version.
134    basic_ios<char> io(0);
135    io.imbue(loc);
136
137    wistringstream istr( ostr.str() );
138    istreambuf_iterator<wchar_t, char_traits<wchar_t> > i( istr );
139    istreambuf_iterator<wchar_t, char_traits<wchar_t> > e;
140    ios_base::iostate err = ios_base::goodbit;
141    struct tm other = { 15, 20, 9, 14, 7, 105 };
142
143    i = tmg.get_monthname( i, e, io, err, &other );
144    CPPUNIT_ASSERT( err == ios_base::goodbit );
145    CPPUNIT_ASSERT( other.tm_mon == xmas.tm_mon );
146
147    ++i; ++i; ++i; ++i; // skip day of month and spaces around it
148    i = tmg.get_year( i, e, io, err, &other );
149
150    CPPUNIT_ASSERT( err == ios_base::eofbit );
151    CPPUNIT_ASSERT( other.tm_year == xmas.tm_year );
152
153    wostringstream ostrX;
154    ostrX.imbue(loc);
155    format = L"%x %X";
156
157    ret = tmp.put(ostrX, ostrX, ' ', &xmas, format.data(), format.data() + format.size());
158    CPPUNIT_ASSERT( !ret.failed() );
159
160    wistringstream istrX( ostrX.str() );
161    istreambuf_iterator<wchar_t, char_traits<wchar_t> > j( istrX );
162
163    err = ios_base::goodbit;
164
165    struct tm yet_more = { 15, 20, 9, 14, 7, 105 };
166
167    j = tmg.get_date( j, e, io, err, &yet_more );
168
169    CPPUNIT_ASSERT( err == ios_base::goodbit );
170
171    CPPUNIT_ASSERT( yet_more.tm_sec != xmas.tm_sec );
172    CPPUNIT_ASSERT( yet_more.tm_min != xmas.tm_min );
173    CPPUNIT_ASSERT( yet_more.tm_hour != xmas.tm_hour );
174    CPPUNIT_ASSERT( yet_more.tm_mday == xmas.tm_mday );
175    CPPUNIT_ASSERT( yet_more.tm_mon == xmas.tm_mon );
176    CPPUNIT_ASSERT( yet_more.tm_year == xmas.tm_year );
177
178    ++j; // skip space
179
180    j = tmg.get_time( j, e, io, err, &yet_more );
181
182    CPPUNIT_ASSERT( err == ios_base::eofbit || err == ios_base::goodbit );
183
184    CPPUNIT_ASSERT( yet_more.tm_sec == xmas.tm_sec );
185    CPPUNIT_ASSERT( yet_more.tm_min == xmas.tm_min );
186    CPPUNIT_ASSERT( yet_more.tm_hour == xmas.tm_hour );
187    CPPUNIT_ASSERT( yet_more.tm_mday == xmas.tm_mday );
188    CPPUNIT_ASSERT( yet_more.tm_mon == xmas.tm_mon );
189    CPPUNIT_ASSERT( yet_more.tm_year == xmas.tm_year );
190  }
191#  endif
192}
193
194typedef void (LocaleTest::*_Test) (const locale&);
195static void test_supported_locale(LocaleTest& inst, _Test __test) {
196  size_t n = sizeof(tested_locales) / sizeof(tested_locales[0]);
197  for (size_t i = 0; i < n; ++i) {
198    locale loc;
199#  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
200    try
201#  endif
202    {
203      locale tmp(tested_locales[i]);
204      loc = tmp;
205    }
206#  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
207    catch (runtime_error const&) {
208      //This locale is not supported.
209      continue;
210    }
211#  endif
212    CPPUNIT_MESSAGE( loc.name().c_str() );
213    (inst.*__test)(loc);
214
215    {
216      locale tmp(locale::classic(), tested_locales[i], locale::time);
217      loc = tmp;
218    }
219    (inst.*__test)(loc);
220
221    {
222      typedef time_put_byname<char, ostreambuf_iterator<char, char_traits<char> > > time_put_facet;
223      locale tmp0(locale::classic(), new time_put_facet(tested_locales[i]));
224      typedef time_get_byname<char, istreambuf_iterator<char, char_traits<char> > > time_get_facet;
225      locale tmp1(tmp0, new time_get_facet(tested_locales[i]));
226      loc = tmp1;
227    }
228    (inst.*__test)(loc);
229  }
230}
231
232void LocaleTest::time_put_get()
233{ test_supported_locale(*this, &LocaleTest::_time_put_get); }
234
235void LocaleTest::time_by_name()
236{
237#  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
238  /*
239   * Check of the 22.1.1.2.7 standard point. Construction of a locale
240   * instance from a null pointer or an unknown name should result in
241   * a runtime_error exception.
242   */
243#    if defined (STLPORT) || !defined (_MSC_VER) || (_MSC_VER > 1400)
244  try {
245    locale loc(locale::classic(), new time_put_byname<char, ostreambuf_iterator<char, char_traits<char> > >(static_cast<char const*>(0)));
246    CPPUNIT_FAIL;
247  }
248  catch (runtime_error const&) {
249  }
250  catch (...) {
251    CPPUNIT_FAIL;
252  }
253#    endif
254
255  try {
256    locale loc(locale::classic(), new time_put_byname<char, ostreambuf_iterator<char, char_traits<char> > >("yasli_language"));
257    CPPUNIT_FAIL;
258  }
259  catch (runtime_error const&) {
260  }
261  catch (...) {
262    CPPUNIT_FAIL;
263  }
264
265  try {
266    string veryLongFacetName("LC_TIME=");
267    veryLongFacetName.append(512, '?');
268    locale loc(locale::classic(), new time_put_byname<char, ostreambuf_iterator<char, char_traits<char> > >(veryLongFacetName.c_str()));
269    CPPUNIT_FAIL;
270  }
271  catch (runtime_error const& /* e */) {
272    //CPPUNIT_MESSAGE( e.what() );
273  }
274  catch (...) {
275    CPPUNIT_FAIL;
276  }
277
278  try {
279    locale loc(locale::classic(), new time_get_byname<char, istreambuf_iterator<char, char_traits<char> > >(static_cast<char const*>(0)));
280    CPPUNIT_FAIL;
281  }
282  catch (runtime_error const&) {
283  }
284  catch (...) {
285    CPPUNIT_FAIL;
286  }
287
288  try {
289    locale loc(locale::classic(), new time_get_byname<char, istreambuf_iterator<char, char_traits<char> > >("yasli_language"));
290    CPPUNIT_FAIL;
291  }
292  catch (runtime_error const&) {
293  }
294  catch (...) {
295    CPPUNIT_FAIL;
296  }
297
298  try {
299    string veryLongFacetName("LC_TIME=");
300    veryLongFacetName.append(512, '?');
301    locale loc(locale::classic(), new time_get_byname<char, istreambuf_iterator<char, char_traits<char> > >(veryLongFacetName.c_str()));
302    CPPUNIT_FAIL;
303  }
304  catch (runtime_error const& /* e */) {
305    //CPPUNIT_MESSAGE( e.what() );
306  }
307  catch (...) {
308    CPPUNIT_FAIL;
309  }
310
311  try {
312    locale loc(locale::classic(), "C", locale::time);
313  }
314  catch (runtime_error const& /* e */) {
315    /* CPPUNIT_MESSAGE( e.what() ); */
316    CPPUNIT_FAIL;
317  }
318  catch (...) {
319    CPPUNIT_FAIL;
320  }
321
322  try {
323    // On platform without real localization support we should rely on the "C" facet.
324    locale loc(locale::classic(), "", locale::time);
325  }
326  catch (runtime_error const& /* e */) {
327    /* CPPUNIT_MESSAGE( e.what() ); */
328    CPPUNIT_FAIL;
329  }
330  catch (...) {
331    CPPUNIT_FAIL;
332  }
333
334  try {
335    locale loc(locale::classic(), new time_get_byname<char, istreambuf_iterator<char, char_traits<char> > >("C"));
336  }
337  catch (runtime_error const& /* e */) {
338    /* CPPUNIT_MESSAGE( e.what() ); */
339    CPPUNIT_FAIL;
340  }
341  catch (...) {
342    CPPUNIT_FAIL;
343  }
344
345  try {
346    // On platform without real localization support we should rely on the "C" locale facet.
347    locale loc(locale::classic(), new time_get_byname<char, istreambuf_iterator<char, char_traits<char> > >(""));
348  }
349  catch (runtime_error const& /* e */) {
350    /* CPPUNIT_MESSAGE( e.what() ); */
351    CPPUNIT_FAIL;
352  }
353  catch (...) {
354    CPPUNIT_FAIL;
355  }
356
357#    if !defined (STLPORT) || !defined (_STLP_NO_WCHAR_T)
358  try {
359    locale loc(locale::classic(), new time_put_byname<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >(static_cast<char const*>(0)));
360    CPPUNIT_FAIL;
361  }
362  catch (runtime_error const&) {
363  }
364  catch (...) {
365    CPPUNIT_FAIL;
366    }
367
368  try {
369    locale loc(locale::classic(), new time_put_byname<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >("yasli_language"));
370    CPPUNIT_FAIL;
371  }
372  catch (runtime_error const&) {
373  }
374  catch (...) {
375    CPPUNIT_FAIL;
376  }
377
378  try {
379    locale loc(locale::classic(), new time_get_byname<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >(static_cast<char const*>(0)));
380    CPPUNIT_FAIL;
381  }
382  catch (runtime_error const&) {
383  }
384  catch (...) {
385    CPPUNIT_FAIL;
386  }
387
388  try {
389    locale loc(locale::classic(), new time_get_byname<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >("yasli_language"));
390    CPPUNIT_FAIL;
391  }
392  catch (runtime_error const&) {
393  }
394  catch (...) {
395    CPPUNIT_FAIL;
396  }
397
398#    endif
399#  endif
400}
401
402#endif
403