OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / ndk / sources / cxx-stl / stlport / src / time_facets.cpp
1 /*
2  * Copyright (c) 1999
3  * Silicon Graphics Computer Systems, Inc.
4  *
5  * Copyright (c) 1999
6  * Boris Fomitchev
7  *
8  * This material is provided "as is", with absolutely no warranty expressed
9  * or implied. Any use is at your own risk.
10  *
11  * Permission to use or copy this software for any purpose is hereby granted
12  * without fee, provided the above notices are retained on all copies.
13  * Permission to modify the code and to distribute modified code is granted,
14  * provided the above notices are retained, and a notice that the code was
15  * modified is included with the above copyright notice.
16  *
17  */
18
19 #include "stlport_prefix.h"
20
21 #include <cstdio>
22 #include <locale>
23 #include <istream>
24
25 #include "c_locale.h"
26 #include "acquire_release.h"
27
28 _STLP_BEGIN_NAMESPACE
29
30 _STLP_MOVE_TO_PRIV_NAMESPACE
31
32 // default "C" values for month and day names
33
34 const char default_dayname[][14] = {
35   "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
36   "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
37   "Friday", "Saturday"};
38
39 const char default_monthname[][24] = {
40   "Jan", "Feb", "Mar", "Apr", "May", "Jun",
41   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
42   "January", "February", "March", "April", "May", "June",
43   "July", "August", "September", "October", "November", "December"};
44
45 #ifndef _STLP_NO_WCHAR_T
46 const wchar_t default_wdayname[][14] = {
47   L"Sun", L"Mon", L"Tue", L"Wed", L"Thu", L"Fri", L"Sat",
48   L"Sunday", L"Monday", L"Tuesday", L"Wednesday", L"Thursday",
49   L"Friday", L"Saturday"};
50
51 const wchar_t default_wmonthname[][24] = {
52   L"Jan", L"Feb", L"Mar", L"Apr", L"May", L"Jun",
53   L"Jul", L"Aug", L"Sep", L"Oct", L"Nov", L"Dec",
54   L"January", L"February", L"March", L"April", L"May", L"June",
55   L"July", L"August", L"September", L"October", L"November", L"December"};
56 #endif
57
58 #if defined (__BORLANDC__)
59 _Time_Info time_init<char>::_M_timeinfo;
60 #  ifndef _STLP_NO_WCHAR_T
61 _WTime_Info time_init<wchar_t>::_M_timeinfo;
62 #  endif
63 #endif
64
65 // _Init_time_info: initialize table with
66 // "C" values (note these are not defined in the C standard, so this
67 // is somewhat arbitrary).
68
69 static void _Init_timeinfo_base(_Time_Info_Base& table) {
70   table._M_time_format = "%H:%M:%S";
71   table._M_date_format = "%m/%d/%y";
72   table._M_date_time_format = "%m/%d/%y";
73 }
74
75 static void _Init_timeinfo(_Time_Info& table) {
76   int i;
77   for (i = 0; i < 14; ++i)
78     table._M_dayname[i] = default_dayname[i];
79   for (i = 0; i < 24; ++i)
80     table._M_monthname[i] = default_monthname[i];
81   table._M_am_pm[0] = "AM";
82   table._M_am_pm[1] = "PM";
83   _Init_timeinfo_base(table);
84 }
85
86 #ifndef _STLP_NO_WCHAR_T
87 static void _Init_timeinfo(_WTime_Info& table) {
88   int i;
89   for (i = 0; i < 14; ++i)
90     table._M_dayname[i] = default_wdayname[i];
91   for (i = 0; i < 24; ++i)
92     table._M_monthname[i] = default_wmonthname[i];
93   table._M_am_pm[0] = L"AM";
94   table._M_am_pm[1] = L"PM";
95   _Init_timeinfo_base(table);
96 }
97 #endif
98
99 static void _Init_timeinfo_base(_Time_Info_Base& table, _Locale_time * time) {
100   table._M_time_format = _Locale_t_fmt(time);
101   if ( table._M_time_format == "%T" ) {
102     table._M_time_format = "%H:%M:%S";
103   } else if ( table._M_time_format == "%r" ) {
104     table._M_time_format = "%I:%M:%S %p";
105   } else if ( table._M_time_format == "%R" ) {
106     table._M_time_format = "%H:%M";
107   }
108   table._M_date_format = _Locale_d_fmt(time);
109   table._M_date_time_format = _Locale_d_t_fmt(time);
110   table._M_long_date_format = _Locale_long_d_fmt(time);
111   table._M_long_date_time_format = _Locale_long_d_t_fmt(time);
112 }
113
114 static void _Init_timeinfo(_Time_Info& table, _Locale_time * time) {
115   int i;
116   for (i = 0; i < 7; ++i)
117     table._M_dayname[i] = _Locale_abbrev_dayofweek(time, i);
118   for (i = 0; i < 7; ++i)
119     table._M_dayname[i+7] = _Locale_full_dayofweek(time, i);
120   for (i = 0; i < 12; ++i)
121     table._M_monthname[i] = _Locale_abbrev_monthname(time, i);
122   for (i = 0; i < 12; ++i)
123     table._M_monthname[i+12] = _Locale_full_monthname(time, i);
124   table._M_am_pm[0] = _Locale_am_str(time);
125   table._M_am_pm[1] = _Locale_pm_str(time);
126   _Init_timeinfo_base(table, time);
127 }
128
129 #ifndef _STLP_NO_WCHAR_T
130 static void _Init_timeinfo(_WTime_Info& table, _Locale_time * time) {
131   wchar_t buf[128];
132   int i;
133   for (i = 0; i < 7; ++i)
134     table._M_dayname[i] = _WLocale_abbrev_dayofweek(time, i, _STLP_ARRAY_AND_SIZE(buf));
135   for (i = 0; i < 7; ++i)
136     table._M_dayname[i+7] = _WLocale_full_dayofweek(time, i, _STLP_ARRAY_AND_SIZE(buf));
137   for (i = 0; i < 12; ++i)
138     table._M_monthname[i] = _WLocale_abbrev_monthname(time, i, _STLP_ARRAY_AND_SIZE(buf));
139   for (i = 0; i < 12; ++i)
140     table._M_monthname[i+12] = _WLocale_full_monthname(time, i, _STLP_ARRAY_AND_SIZE(buf));
141   table._M_am_pm[0] = _WLocale_am_str(time, _STLP_ARRAY_AND_SIZE(buf));
142   table._M_am_pm[1] = _WLocale_pm_str(time, _STLP_ARRAY_AND_SIZE(buf));
143   _Init_timeinfo_base(table, time);
144 }
145 #endif
146
147 template <class _Ch, class _TimeInfo>
148 void __subformat(_STLP_BASIC_IOSTRING(_Ch) &buf, const ctype<_Ch>& ct,
149                  const string& format, const _TimeInfo& table, const tm* t) {
150   const char * cp = format.data();
151   const char * cp_end = cp + format.size();
152   while (cp != cp_end) {
153     if (*cp == '%') {
154       char mod = 0;
155       ++cp;
156       if (*cp == '#') {
157         mod = *cp; ++cp;
158       }
159       __write_formatted_timeT(buf, ct, *cp++, mod, table, t);
160     } else
161       buf.append(1, *cp++);
162   }
163 }
164
165 static void __append(__iostring &buf, const string& name)
166 { buf.append(name.data(), name.data() + name.size()); }
167
168 static void __append(__iowstring &buf, const wstring& name)
169 { buf.append(name.data(), name.data() + name.size()); }
170
171 static void __append(__iostring &buf, char *first, char *last, const ctype<char>& /* ct */)
172 { buf.append(first, last); }
173
174 static void __append(__iowstring &buf, char *first, char *last, const ctype<wchar_t>& ct) {
175   wchar_t _wbuf[64];
176   ct.widen(first, last, _wbuf);
177   buf.append(_wbuf, _wbuf + (last - first));
178 }
179
180 #if defined (__GNUC__)
181 /* The number of days from the first day of the first ISO week of this
182    year to the year day YDAY with week day WDAY.  ISO weeks start on
183    Monday; the first ISO week has the year's first Thursday.  YDAY may
184    be as small as YDAY_MINIMUM.  */
185 #  define __ISO_WEEK_START_WDAY 1 /* Monday */
186 #  define __ISO_WEEK1_WDAY 4 /* Thursday */
187 #  define __YDAY_MINIMUM (-366)
188 #  define __TM_YEAR_BASE 1900
189 static int
190 __iso_week_days(int yday, int wday) {
191   /* Add enough to the first operand of % to make it nonnegative.  */
192   int big_enough_multiple_of_7 = (-__YDAY_MINIMUM / 7 + 2) * 7;
193   return (yday
194           - (yday - wday + __ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
195           + __ISO_WEEK1_WDAY - __ISO_WEEK_START_WDAY);
196 }
197
198 #  define __is_leap(year)\
199   ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
200
201 #endif
202
203 #define __hour12(hour) \
204   (((hour) % 12 == 0) ? (12) : (hour) % 12)
205
206 #if !defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
207 #  define _STLP_SPRINTF sprintf
208 #else
209 #  define _STLP_SPRINTF sprintf_s
210 #endif
211
212 template <class _Ch, class _TimeInfo>
213 void _STLP_CALL __write_formatted_timeT(_STLP_BASIC_IOSTRING(_Ch) &buf,
214                                         const ctype<_Ch>& ct,
215                                         char format, char modifier,
216                                         const _TimeInfo& table, const tm* t) {
217   char _buf[64];
218   char *_bend;
219
220   switch (format) {
221     case 'a':
222       __append(buf, table._M_dayname[t->tm_wday]);
223       break;
224
225     case 'A':
226       __append(buf, table._M_dayname[t->tm_wday + 7]);
227       break;
228
229     case 'b':
230       __append(buf, table._M_monthname[t->tm_mon]);
231       break;
232
233     case 'B':
234       __append(buf, table._M_monthname[t->tm_mon + 12]);
235       break;
236
237     case 'c':
238       __subformat(buf, ct, (modifier != '#') ? table._M_date_time_format
239                                              : table._M_long_date_time_format, table, t);
240       break;
241
242     case 'd':
243       _STLP_SPRINTF(_buf, (modifier != '#') ? "%.2ld" : "%ld", (long)t->tm_mday);
244       __append(buf, _buf, ((long)t->tm_mday < 10L && modifier == '#') ? _buf + 1 : _buf + 2, ct);
245       break;
246
247     case 'e':
248       _STLP_SPRINTF(_buf, "%2ld", (long)t->tm_mday);
249       __append(buf, _buf, _buf + 2, ct);
250       break;
251
252     case 'H':
253       _STLP_SPRINTF(_buf, (modifier != '#') ? "%.2ld" : "%ld", (long)t->tm_hour);
254       __append(buf, _buf, ((long)t->tm_hour < 10L && modifier == '#') ? _buf + 1 : _buf + 2, ct);
255       break;
256
257     case 'I':
258       _STLP_SPRINTF(_buf, (modifier != '#') ? "%.2ld" : "%ld", (long)__hour12(t->tm_hour));
259       __append(buf, _buf, ((long)__hour12(t->tm_hour) < 10L && modifier == '#') ? _buf + 1 : _buf + 2, ct);
260       break;
261
262     case 'j':
263       _bend = __write_integer(_buf, 0, (long)((long)t->tm_yday + 1));
264       __append(buf, _buf, _bend, ct);
265       break;
266
267     case 'm':
268       _STLP_SPRINTF(_buf, (modifier != '#') ? "%.2ld" : "%ld", (long)t->tm_mon + 1);
269       __append(buf, _buf, ((long)(t->tm_mon + 1) < 10L && modifier == '#') ? _buf + 1 : _buf + 2, ct);
270       break;
271
272     case 'M':
273       _STLP_SPRINTF(_buf, (modifier != '#') ? "%.2ld" : "%ld", (long)t->tm_min);
274       __append(buf, _buf, ((long)t->tm_min < 10L && modifier == '#') ? _buf + 1 : _buf + 2, ct);
275       break;
276
277     case 'p':
278       __append(buf, table._M_am_pm[t->tm_hour / 12]);
279       break;
280
281     case 'S': // pad with zeros
282        _STLP_SPRINTF(_buf, (modifier != '#') ? "%.2ld" : "%ld", (long)t->tm_sec);
283        __append(buf, _buf, ((long)t->tm_sec < 10L && modifier == '#') ? _buf + 1 : _buf + 2, ct);
284        break;
285
286     case 'U':
287       _bend = __write_integer(_buf, 0, long((t->tm_yday - t->tm_wday + 7) / 7));
288       __append(buf, _buf, _bend, ct);
289       break;
290
291     case 'w':
292       _bend = __write_integer(_buf, 0, (long)t->tm_wday);
293       __append(buf, _buf, _bend, ct);
294       break;
295
296     case 'W':
297       _bend = __write_integer(_buf, 0,
298                              (long)(t->tm_wday == 0 ? (t->tm_yday + 1) / 7 :
299                                                       (t->tm_yday + 8 - t->tm_wday) / 7));
300       __append(buf, _buf, _bend, ct);
301       break;
302
303     case'x':
304       __subformat(buf, ct, (modifier != '#') ? table._M_date_format
305                                              : table._M_long_date_format, table, t);
306       break;
307
308     case 'X':
309       __subformat(buf, ct, table._M_time_format, table, t);
310       break;
311
312     case 'y':
313       _bend = __write_integer(_buf, 0, (long)((long)(t->tm_year + 1900) % 100));
314       __append(buf, _buf, _bend, ct);
315       break;
316
317     case 'Y':
318       _bend = __write_integer(_buf, 0, (long)((long)t->tm_year + 1900));
319       __append(buf, _buf, _bend, ct);
320       break;
321
322     case '%':
323       buf.append(1, ct.widen('%'));
324       break;
325
326 #if defined (__GNUC__)
327       // fbp : at least on SUN
328 #  if defined (_STLP_UNIX) && !defined (__linux__)
329 #    define __USE_BSD 1
330 #  endif
331
332    /*********************************************
333     *     JGS, handle various extensions        *
334     *********************************************/
335
336     case 'h': /* POSIX.2 extension */
337       // same as 'b', abbrev month name
338       __append(buf, table._M_monthname[t->tm_mon]);
339       break;
340     case 'C': /* POSIX.2 extension */
341       // same as 'd', the day
342       _STLP_SPRINTF(_buf, "%2ld", (long)t->tm_mday);
343       __append(buf, _buf, _buf + 2, ct);
344       break;
345
346     case 'D': /* POSIX.2 extension */
347       // same as 'x'
348       __subformat(buf, ct, table._M_date_format, table, t);
349       break;
350
351     case 'k': /* GNU extension */
352       _STLP_SPRINTF(_buf, "%2ld", (long)t->tm_hour);
353       __append(buf, _buf, _buf + 2, ct);
354       break;
355
356     case 'l': /* GNU extension */
357       _STLP_SPRINTF(_buf, "%2ld", (long)t->tm_hour % 12);
358       __append(buf, _buf, _buf + 2, ct);
359       break;
360
361     case 'n': /* POSIX.2 extension */
362       buf.append(1, ct.widen('\n'));
363       break;
364
365     case 'R': /* GNU extension */
366       __subformat(buf, ct, "%H:%M", table, t);
367       break;
368
369     case 'r': /* POSIX.2 extension */
370       __subformat(buf, ct, "%I:%M:%S %p", table, t);
371       break;
372
373     case 'T': /* POSIX.2 extension.  */
374       __subformat(buf, ct, "%H:%M:%S", table, t);
375       break;
376
377     case 't': /* POSIX.2 extension.  */
378       buf.append(1, ct.widen('\t'));
379
380     case 'u': /* POSIX.2 extension.  */
381       _bend = __write_integer(_buf, 0, long((t->tm_wday - 1 + 7)) % 7 + 1);
382       __append(buf, _buf, _bend, ct);
383       break;
384
385     case 's': {
386       time_t __t = mktime(__CONST_CAST(tm*, t));
387       _bend = __write_integer(_buf, 0, (long)__t );
388       __append(buf, _buf, _bend, ct);
389       break;
390     }
391     case 'g': /* GNU extension */
392     case 'G': {
393       int year = t->tm_year + __TM_YEAR_BASE;
394       int days = __iso_week_days (t->tm_yday, t->tm_wday);
395       if (days < 0) {
396         /* This ISO week belongs to the previous year.  */
397         year--;
398         days = __iso_week_days (t->tm_yday + (365 + __is_leap (year)), t->tm_wday);
399       }
400       else {
401         int d = __iso_week_days (t->tm_yday - (365 + __is_leap (year)), t->tm_wday);
402         if (0 <= d) {
403           /* This ISO week belongs to the next year.  */
404           ++year;
405           days = d;
406         }
407       }
408       long val;
409       switch (format) {
410       case 'g':
411         val = (long)(year % 100 + 100) % 100;
412         break;
413       case 'G':
414         val = (long)year;
415         break;
416       default:
417         val = (long)days / 7 + 1;
418         break;
419       }
420       _bend = __write_integer(_buf, 0, val);
421       __append(buf, _buf, _bend, ct);
422       break;
423     }
424
425 #  if defined (_STLP_USE_GLIBC)
426     case 'z':   /* GNU extension.  */
427       if (t->tm_isdst < 0)
428         break;
429       {
430         int diff;
431 #    if defined (__USE_BSD) || defined (__BEOS__)
432         diff = t->tm_gmtoff;
433 #    else
434         diff = t->__tm_gmtoff;
435 #    endif
436         if (diff < 0) {
437           buf.append(1, ct.widen('-'));
438           diff = -diff;
439         } else
440           buf.append(1, ct.widen('+'));
441         diff /= 60;
442         _STLP_SPRINTF(_buf, "%.4d", (diff / 60) * 100 + diff % 60);
443         __append(buf, _buf, _buf + 4, ct);
444         break;
445       }
446 #  endif /* __GLIBC__ */
447 #endif /* __GNUC__ */
448
449     default:
450       break;
451   }
452 }
453
454 void _STLP_CALL __write_formatted_time(__iostring &buf, const ctype<char>& ct,
455                                        char format, char modifier,
456                                        const _Time_Info& table, const tm* t)
457 { __write_formatted_timeT(buf, ct, format, modifier, table, t); }
458
459 void _STLP_CALL __write_formatted_time(__iowstring &buf, const ctype<wchar_t>& ct,
460                                        char format, char modifier,
461                                        const _WTime_Info& table, const tm* t)
462 { __write_formatted_timeT(buf, ct, format, modifier, table, t); }
463
464 static time_base::dateorder __get_date_order(_Locale_time* time) {
465   const char * fmt = _Locale_d_fmt(time);
466   char first, second, third;
467
468   while (*fmt != 0 && *fmt != '%') ++fmt;
469   if (*fmt == 0)
470     return time_base::no_order;
471   first = *++fmt;
472   while (*fmt != 0 && *fmt != '%') ++fmt;
473   if (*fmt == 0)
474     return time_base::no_order;
475   second = *++fmt;
476   while (*fmt != 0 && *fmt != '%') ++fmt;
477   if (*fmt == 0)
478     return time_base::no_order;
479   third = *++fmt;
480
481   switch (first) {
482     case 'd':
483       return (second == 'm' && third == 'y') ? time_base::dmy
484                                              : time_base::no_order;
485     case 'm':
486       return (second == 'd' && third == 'y') ? time_base::mdy
487                                              : time_base::no_order;
488     case 'y':
489       switch (second) {
490         case 'd':
491           return third == 'm' ? time_base::ydm : time_base::no_order;
492         case 'm':
493           return third == 'd' ? time_base::ymd : time_base::no_order;
494         default:
495           return time_base::no_order;
496       }
497     default:
498       return time_base::no_order;
499   }
500 }
501
502 time_init<char>::time_init()
503   : _M_dateorder(time_base::no_order)
504 { _Init_timeinfo(_M_timeinfo); }
505
506 time_init<char>::time_init(const char* __name) {
507   if (!__name)
508     locale::_M_throw_on_null_name();
509
510   int __err_code;
511   char buf[_Locale_MAX_SIMPLE_NAME];
512   _Locale_time *__time = __acquire_time(__name, buf, 0, &__err_code);
513   if (!__time)
514     locale::_M_throw_on_creation_failure(__err_code, __name, "time");
515
516   _Init_timeinfo(this->_M_timeinfo, __time);
517   _M_dateorder = __get_date_order(__time);
518   __release_time(__time);
519 }
520
521 time_init<char>::time_init(_Locale_time *__time) {
522   _Init_timeinfo(this->_M_timeinfo, __time);
523   _M_dateorder = __get_date_order(__time);
524 }
525
526 #ifndef _STLP_NO_WCHAR_T
527 time_init<wchar_t>::time_init()
528   : _M_dateorder(time_base::no_order)
529 { _Init_timeinfo(_M_timeinfo); }
530
531 time_init<wchar_t>::time_init(const char* __name) {
532   if (!__name)
533     locale::_M_throw_on_null_name();
534
535   int __err_code;
536   char buf[_Locale_MAX_SIMPLE_NAME];
537   _Locale_time *__time = __acquire_time(__name, buf, 0, &__err_code);
538   if (!__time)
539     locale::_M_throw_on_creation_failure(__err_code, __name, "time");
540
541   _Init_timeinfo(this->_M_timeinfo, __time);
542   _M_dateorder = __get_date_order(__time);
543   __release_time(__time);
544 }
545
546 time_init<wchar_t>::time_init(_Locale_time *__time) {
547   _Init_timeinfo(this->_M_timeinfo, __time);
548   _M_dateorder = __get_date_order(__time);
549 }
550 #endif
551
552 _STLP_MOVE_TO_STD_NAMESPACE
553
554 #if !defined (_STLP_NO_FORCE_INSTANTIATE)
555 template class time_get<char, istreambuf_iterator<char, char_traits<char> > >;
556 template class time_put<char, ostreambuf_iterator<char, char_traits<char> > >;
557
558 #  ifndef _STLP_NO_WCHAR_T
559 template class time_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
560 template class time_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
561 #  endif
562
563 #endif
564
565 _STLP_END_NAMESPACE