]> git.buserror.net Git - polintos/scott/priv.git/blob - lib/c++/stlport/time_facets.cpp
Add STLport 5.1.4
[polintos/scott/priv.git] / lib / c++ / stlport / 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 #include <cstdio>
25
26 #include "c_locale.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 // _Init_time_info: initialize table with
46 // "C" values (note these are not defined in the C standard, so this
47 // is somewhat arbitrary).
48
49 void _STLP_CALL _Init_timeinfo(_Time_Info& table) {
50   int i;
51   for (i = 0; i < 14; ++i)
52     table._M_dayname[i] = default_dayname[i];
53   for (i = 0; i < 24; ++i)
54     table._M_monthname[i] = default_monthname[i];
55   table._M_am_pm[0] = "AM";
56   table._M_am_pm[1] = "PM";
57   table._M_time_format = "%H:%M:%S";
58   table._M_date_format = "%m/%d/%y";
59   table._M_date_time_format = "%m/%d/%y";
60 }
61
62 void _STLP_CALL _Init_timeinfo(_Time_Info& table, _Locale_time * time) {
63   if(!time)
64     locale::_M_throw_runtime_error();
65
66   int i;
67   for (i = 0; i < 7; ++i)
68     table._M_dayname[i] = _Locale_abbrev_dayofweek(time, i);
69   for (i = 0; i < 7; ++i)
70     table._M_dayname[i+7] = _Locale_full_dayofweek(time, i);
71   for (i = 0; i < 12; ++i)
72     table._M_monthname[i] = _Locale_abbrev_monthname(time, i);
73   for (i = 0; i < 12; ++i)
74     table._M_monthname[i+12] = _Locale_full_monthname(time, i);
75   table._M_am_pm[0] = _Locale_am_str(time);
76   table._M_am_pm[1] = _Locale_pm_str(time);
77   table._M_time_format = _Locale_t_fmt(time);
78   if ( table._M_time_format == "%T" ) {
79     table._M_time_format = "%H:%M:%S";
80   } else if ( table._M_time_format == "%r" ) {
81     table._M_time_format = "%I:%M:%S %p";
82   } else if ( table._M_time_format == "%R" ) {
83     table._M_time_format = "%H:%M";
84   }
85   table._M_date_format = _Locale_d_fmt(time);
86   table._M_date_time_format = _Locale_d_t_fmt(time);
87   table._M_long_date_format = _Locale_long_d_fmt(time);
88   table._M_long_date_time_format = _Locale_long_d_t_fmt(time);
89 }
90
91 inline char* __subformat(const string& format, char*& buf, size_t buf_size,
92                          const _Time_Info&  table, const tm* t) {
93   const char * cp = format.data();
94   const char * cp_end = cp + format.size();
95   while (cp != cp_end) {
96     if (*cp == '%') {
97       char mod = 0;
98       ++cp;
99       if(*cp == '#') {
100         mod = *cp; ++cp;
101       }
102       char *former_buf = buf;
103       buf = __write_formatted_time(buf, buf_size, *cp++, mod, table, t);
104       buf_size -= (buf - former_buf);
105     } else
106       *buf++ = *cp++;
107   }
108   return buf;
109 }
110
111 #if defined (__GNUC__)
112 /* The number of days from the first day of the first ISO week of this
113    year to the year day YDAY with week day WDAY.  ISO weeks start on
114    Monday; the first ISO week has the year's first Thursday.  YDAY may
115    be as small as YDAY_MINIMUM.  */
116 #  define __ISO_WEEK_START_WDAY 1 /* Monday */
117 #  define __ISO_WEEK1_WDAY 4 /* Thursday */
118 #  define __YDAY_MINIMUM (-366)
119 #  define __TM_YEAR_BASE 1900
120 static int
121 __iso_week_days(int yday, int wday) {
122   /* Add enough to the first operand of % to make it nonnegative.  */
123   int big_enough_multiple_of_7 = (-__YDAY_MINIMUM / 7 + 2) * 7;
124   return (yday
125           - (yday - wday + __ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
126           + __ISO_WEEK1_WDAY - __ISO_WEEK_START_WDAY);
127 }
128
129 #  define __is_leap(year)\
130   ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
131
132 #endif
133
134 #define __hour12(hour) \
135   (((hour) % 12 == 0) ? (12) : (hour) % 12)
136
137 #if !defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
138 #  define _STLP_SPRINTF(B, BS, F, D) sprintf(B, F, D)
139 #else
140 #  define _STLP_SPRINTF(B, BS, F, D) sprintf_s(B, BS, F, D)
141 #endif
142
143 char * _STLP_CALL __write_formatted_time(char* buf, size_t buf_size, char format, char modifier,
144                                          const _Time_Info& table, const tm* t) {
145   switch (format) {
146     case 'a':
147       return copy(table._M_dayname[t->tm_wday].begin(),
148                   table._M_dayname[t->tm_wday].end(),
149                   buf);
150
151     case 'A':
152       return copy(table._M_dayname[t->tm_wday+7].begin(),
153                   table._M_dayname[t->tm_wday+7].end(),
154                   buf);
155
156     case 'b':
157       return copy(table._M_monthname[t->tm_mon].begin(),
158                   table._M_monthname[t->tm_mon].end(),
159                   buf);
160
161     case 'B':
162       return copy(table._M_monthname[t->tm_mon+12].begin(),
163                   table._M_monthname[t->tm_mon+12].end(),
164                   buf);
165
166     case 'c': {
167       const char *cp = (modifier != '#') ?
168         table._M_date_time_format.data() :
169         table._M_long_date_time_format.data();
170       const char* cp_end = cp +
171         ((modifier != '#') ? table._M_date_time_format.size() :
172          table._M_long_date_time_format.size() );
173       char mod;
174       while (cp != cp_end) {
175         if (*cp == '%') {
176           ++cp; if(*cp == '#') mod = *cp++; else mod = 0;
177           char *buf_pos = buf;
178           buf = __write_formatted_time(buf, buf_size, *cp++, mod, table, t);
179           buf_size -= (buf - buf_pos);
180         }
181         else {
182           *buf++ = *cp++; --buf_size;
183         }
184       }
185       return buf;
186     }
187
188     case 'd':
189       _STLP_SPRINTF(buf, buf_size, (modifier != '#')?"%.2ld":"%ld", (long)t->tm_mday);
190       return ((long)t->tm_mday < 10L && modifier == '#')?buf+1:buf + 2;
191
192     case 'e':
193       _STLP_SPRINTF(buf, buf_size, "%2ld", (long)t->tm_mday);
194       return buf + 2;
195
196     case 'H':
197       _STLP_SPRINTF(buf, buf_size, (modifier != '#')?"%.2ld":"%ld", (long)t->tm_hour);
198       return ((long)t->tm_hour < 10L && modifier == '#')?buf+1:buf + 2;
199
200     case 'I':
201       _STLP_SPRINTF(buf, buf_size, (modifier != '#')?"%.2ld":"%ld", (long)__hour12(t->tm_hour));
202       return ((long)__hour12(t->tm_hour) < 10L && modifier == '#')?buf+1:buf + 2;
203
204     case 'j':
205       return __write_integer(buf, 0, (long)((long)t->tm_yday + 1));
206
207     case 'm':
208       _STLP_SPRINTF(buf, buf_size, (modifier != '#')?"%.2ld":"%ld", (long)t->tm_mon + 1);
209       return ((long)(t->tm_mon + 1) < 10L && modifier == '#')?buf+1:buf + 2;
210
211     case 'M':
212       _STLP_SPRINTF(buf, buf_size, (modifier != '#')?"%.2ld":"%ld", (long)t->tm_min);
213       return ((long)t->tm_min < 10L && modifier == '#')?buf+1:buf + 2;
214
215     case 'p':
216       return copy(table._M_am_pm[t->tm_hour/12].begin(),
217                   table._M_am_pm[t->tm_hour/12].end(),
218                   buf);
219
220     case 'S': // pad with zeros
221        _STLP_SPRINTF(buf, buf_size, (modifier != '#')?"%.2ld":"%ld", (long)t->tm_sec);
222        return ((long)t->tm_sec < 10L && modifier == '#')?buf+1:buf + 2;
223
224     case 'U':
225       return __write_integer(buf, 0,
226                              long((t->tm_yday - t->tm_wday + 7) / 7));
227       //      break;
228
229     case 'w':
230       return __write_integer(buf, 0, (long)t->tm_wday);
231       //      break;
232
233     case 'W':
234       return __write_integer(buf, 0,
235                              (long)(t->tm_wday == 0 ? (t->tm_yday + 1) / 7 :
236                                                       (t->tm_yday + 8 - t->tm_wday) / 7));
237
238     case'x': {
239       const char * cp = (modifier != '#') ? table._M_date_format.data():
240                                             table._M_long_date_format.data();
241       const char* cp_end = (modifier != '#') ? cp + table._M_date_format.size():
242                                                cp + table._M_long_date_format.size();
243       char mod;
244       while (cp != cp_end) {
245         if (*cp == '%') {
246           ++cp; if(*cp == '#') mod = *cp++; else mod = 0;
247           char *buf_pos = buf;
248           buf = __write_formatted_time(buf, buf_size, *cp++, mod, table, t);
249           buf_size -= (buf - buf_pos);
250         }
251         else {
252           *buf++ = *cp++; --buf_size;
253         }
254       }
255       return buf;
256     }
257
258     case 'X': {
259       const char * cp = table._M_time_format.data();
260       const char* cp_end = cp + table._M_time_format.size();
261       char mod;
262       while (cp != cp_end) {
263         if (*cp == '%') {
264           ++cp; if(*cp == '#') mod = *cp++; else mod = 0;
265           char *buf_pos = buf;
266           buf = __write_formatted_time(buf, buf_size, *cp++, mod, table, t);
267           buf_size -= (buf - buf_pos);
268         }
269         else {
270           *buf++ = *cp++; --buf_size;
271         }
272       }
273       return buf;
274     }
275     case 'y':
276       return __write_integer(buf, 0, (long)((long)(t->tm_year + 1900) % 100));
277
278     case 'Y':
279       return __write_integer(buf, 0, (long)((long)t->tm_year + 1900));
280
281     case '%':
282       *buf++ = '%';
283       return buf;
284
285 #if defined (__GNUC__)
286       // fbp : at least on SUN
287 #  if defined (_STLP_UNIX) && !defined (__linux__)
288 #    define __USE_BSD 1
289 #  endif
290
291    /*********************************************
292     *     JGS, handle various extensions        *
293     *********************************************/
294
295     case 'h': /* POSIX.2 extension */
296       // same as 'b', abbrev month name
297       return copy(table._M_monthname[t->tm_mon].begin(),
298                   table._M_monthname[t->tm_mon].end(),
299                   buf);
300
301     case 'C': /* POSIX.2 extension */
302       // same as 'd', the day
303       _STLP_SPRINTF(buf, buf_size, "%2ld", (long)t->tm_mday);
304       return buf + 2;
305
306     case 'D': /* POSIX.2 extension */
307       // same as 'x'
308       return __subformat(table._M_date_format, buf, buf_size, table, t);
309
310     case 'k': /* GNU extension */
311       _STLP_SPRINTF(buf, buf_size, "%2ld", (long)t->tm_hour);
312       return buf + 2;
313
314     case 'l': /* GNU extension */
315       _STLP_SPRINTF(buf, buf_size, "%2ld", (long)t->tm_hour % 12);
316       return buf + 2;
317
318     case 'n': /* POSIX.2 extension */
319       *buf++ = '\n';
320       return buf;
321
322     case 'R': /* GNU extension */
323       return __subformat("%H:%M", buf, buf_size, table, t);
324
325     case 'r': /* POSIX.2 extension */
326       return __subformat("%I:%M:%S %p", buf, buf_size, table, t);
327
328     case 'T': /* POSIX.2 extension.  */
329       return __subformat("%H:%M:%S", buf, buf_size, table, t);
330
331     case 't': /* POSIX.2 extension.  */
332       *buf++ = '\t';
333       return buf;
334
335     case 'u': /* POSIX.2 extension.  */
336       return __write_integer(buf, 0, long((t->tm_wday - 1 + 7)) % 7 + 1);
337
338     case 's': {
339       time_t __t;
340       __t = mktime(__CONST_CAST(tm*, t));
341       return __write_integer(buf, 0, (long)__t );
342     }
343     case 'g': /* GNU extension */
344     case 'G': {
345       int year = t->tm_year + __TM_YEAR_BASE;
346       int days = __iso_week_days (t->tm_yday, t->tm_wday);
347       if (days < 0) {
348         /* This ISO week belongs to the previous year.  */
349         year--;
350         days = __iso_week_days (t->tm_yday + (365 + __is_leap (year)), t->tm_wday);
351       }
352       else {
353         int d = __iso_week_days (t->tm_yday - (365 + __is_leap (year)), t->tm_wday);
354         if (0 <= d) {
355           /* This ISO week belongs to the next year.  */
356           ++year;
357           days = d;
358         }
359       }
360       switch (format) {
361       case 'g':
362         return __write_integer(buf, 0, (long)(year % 100 + 100) % 100);
363       case 'G':
364         return __write_integer(buf, 0, (long)year);
365       default:
366         return __write_integer(buf, 0, (long)days / 7 + 1);
367       }
368     }
369
370 #  if defined (_STLP_USE_GLIBC) && ! defined (__CYGWIN__)
371     case 'z':   /* GNU extension.  */
372       if (t->tm_isdst < 0)
373         break;
374       {
375         int diff;
376 #    if defined (__USE_BSD) || defined (__BEOS__)
377         diff = t->tm_gmtoff;
378 #    else
379         diff = t->__tm_gmtoff;
380 #    endif
381         if (diff < 0) {
382           *buf++ = '-';
383           diff = -diff;
384         } else
385           *buf++ = '+';
386         diff /= 60;
387         _STLP_SPRINTF(buf, buf_size, "%.4d", (diff / 60) * 100 + diff % 60);
388         return buf + 4;
389       }
390 #  endif /* __GLIBC__ */
391 #endif /* __GNUC__ */
392
393     default:
394       //      return buf;
395       break;
396   }
397   return buf;
398 }
399
400 time_base::dateorder _STLP_CALL
401 __get_date_order(_Locale_time* time) {
402   const char * fmt = _Locale_d_fmt(time);
403   char first, second, third;
404
405   while (*fmt != 0 && *fmt != '%') ++fmt;
406   if (*fmt == 0)
407     return time_base::no_order;
408   first = *++fmt;
409   while (*fmt != 0 && *fmt != '%') ++fmt;
410   if (*fmt == 0)
411     return time_base::no_order;
412   second = *++fmt;
413   while (*fmt != 0 && *fmt != '%') ++fmt;
414   if (*fmt == 0)
415     return time_base::no_order;
416   third = *++fmt;
417
418   switch (first) {
419     case 'd':
420       return (second == 'm' && third == 'y') ? time_base::dmy
421                                              : time_base::no_order;
422     case 'm':
423       return (second == 'd' && third == 'y') ? time_base::mdy
424                                              : time_base::no_order;
425     case 'y':
426       switch (second) {
427         case 'd':
428           return third == 'm' ? time_base::ydm : time_base::no_order;
429         case 'm':
430           return third == 'd' ? time_base::ymd : time_base::no_order;
431         default:
432           return time_base::no_order;
433       }
434     default:
435       return time_base::no_order;
436   }
437 }
438
439 _STLP_MOVE_TO_STD_NAMESPACE
440
441 #if !defined(_STLP_NO_FORCE_INSTANTIATE)
442 template class time_get<char, istreambuf_iterator<char, char_traits<char> > >;
443 template class time_put<char, ostreambuf_iterator<char, char_traits<char> > >;
444
445 #  if !defined (_STLP_NO_WCHAR_T)
446 template class time_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
447 template class time_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
448 #  endif
449
450 #endif
451
452 _STLP_END_NAMESPACE