|
1 /* |
|
2 * © Portions copyright (c) 2006-2007 Nokia Corporation. All rights reserved. |
|
3 * |
|
4 * Copyright (c) 1999 |
|
5 * Silicon Graphics Computer Systems, Inc. |
|
6 * |
|
7 * Copyright (c) 1999 |
|
8 * Boris Fomitchev |
|
9 * |
|
10 * This material is provided "as is", with absolutely no warranty expressed |
|
11 * or implied. Any use is at your own risk. |
|
12 * |
|
13 * Permission to use or copy this software for any purpose is hereby granted |
|
14 * without fee, provided the above notices are retained on all copies. |
|
15 * Permission to modify the code and to distribute modified code is granted, |
|
16 * provided the above notices are retained, and a notice that the code was |
|
17 * modified is included with the above copyright notice. |
|
18 * |
|
19 */ |
|
20 |
|
21 |
|
22 #include "stlport_prefix.h" |
|
23 #include <stl/_time_facets.h> |
|
24 #include <stl/_istream.h> |
|
25 #include "c_locale.h" |
|
26 |
|
27 #if defined(__LIBSTD_CPP_SYMBIAN32_WSD__) || defined(_STLP_LIBSTD_CPP_NO_STATIC_VAR_) |
|
28 #include "libstdcppwsd.h" |
|
29 # endif |
|
30 |
|
31 _STLP_BEGIN_NAMESPACE |
|
32 |
|
33 char* _STLP_CALL |
|
34 __write_integer(char* buf, ios_base::fmtflags flags, long x); |
|
35 |
|
36 // The function copy_cstring is used to initialize a string |
|
37 // with a C-style string. Used to initialize the month and weekday |
|
38 // tables in time_get and time_put. Called only by _Init_timeinfo |
|
39 // so its name does not require leading underscores. |
|
40 |
|
41 static inline void copy_cstring(const char * s, string& v) { |
|
42 copy(s, s + strlen(s), back_insert_iterator<string >(v)); |
|
43 } |
|
44 |
|
45 // default "C" values for month and day names |
|
46 |
|
47 const char default_dayname[][14] = { |
|
48 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", |
|
49 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", |
|
50 "Friday", "Saturday"}; |
|
51 |
|
52 const char default_monthname[][24] = { |
|
53 "Jan", "Feb", "Mar", "Apr", "May", "Jun", |
|
54 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", |
|
55 "January", "February", "March", "April", "May", "June", |
|
56 "July", "August", "September", "October", "November", "December"}; |
|
57 |
|
58 // _Init_time_info: initialize table with |
|
59 // "C" values (note these are not defined in the C standard, so this |
|
60 // is somewhat arbitrary). |
|
61 |
|
62 _STLP_EXP_DECLSPEC void _STLP_CALL _Init_timeinfo(_Time_Info& table) { |
|
63 int i; |
|
64 for (i = 0; i < 14; ++i) |
|
65 copy_cstring(default_dayname[i], table._M_dayname[i]); |
|
66 for (i = 0; i < 24; ++i) |
|
67 copy_cstring(default_monthname[i], table._M_monthname[i]); |
|
68 copy_cstring("AM", table._M_am_pm[0]); |
|
69 copy_cstring("PM", table._M_am_pm[1]); |
|
70 copy_cstring("%H:%M:%S", table._M_time_format); |
|
71 #ifdef __SYMBIAN32__ |
|
72 copy_cstring("%m/%d/%Y", table._M_date_format); //linux follows the same default. Y = year in 4 digit |
|
73 #else |
|
74 copy_cstring("%m/%d/%y", table._M_date_format); |
|
75 #endif |
|
76 copy_cstring("%a %b %e %H:%M:%S %Y", table._M_date_time_format); |
|
77 } |
|
78 |
|
79 _STLP_EXP_DECLSPEC void _STLP_CALL _Init_timeinfo(_Time_Info& table, _Locale_time * time) { |
|
80 int i; |
|
81 for (i = 0; i < 7; ++i) |
|
82 copy_cstring(_Locale_abbrev_dayofweek(time, i), |
|
83 table._M_dayname[i]); |
|
84 for (i = 0; i < 7; ++i) |
|
85 copy_cstring(_Locale_full_dayofweek(time, i), |
|
86 table._M_dayname[i+7]); |
|
87 for (i = 0; i < 12; ++i) |
|
88 copy_cstring(_Locale_abbrev_monthname(time, i), |
|
89 table._M_monthname[i]); |
|
90 for (i = 0; i < 12; ++i) |
|
91 copy_cstring(_Locale_full_monthname(time, i), |
|
92 table._M_monthname[i+12]); |
|
93 copy_cstring(_Locale_am_str(time), |
|
94 table._M_am_pm[0]); |
|
95 copy_cstring(_Locale_pm_str(time), |
|
96 table._M_am_pm[1]); |
|
97 copy_cstring(_Locale_t_fmt(time), table._M_time_format); |
|
98 copy_cstring(_Locale_d_fmt(time), table._M_date_format); |
|
99 copy_cstring(_Locale_d_t_fmt(time), table._M_date_time_format); |
|
100 copy_cstring(_Locale_long_d_fmt(time), table._M_long_date_format); |
|
101 copy_cstring(_Locale_long_d_t_fmt(time), table._M_long_date_time_format); |
|
102 } |
|
103 |
|
104 inline char* __subformat(string format, char*& buf, |
|
105 const _Time_Info& table, const tm* t) { |
|
106 const char * cp = format.data(); |
|
107 const char * cp_end = cp + format.size(); |
|
108 while (cp != cp_end) { |
|
109 if (*cp == '%') { |
|
110 char mod = 0; |
|
111 ++cp; |
|
112 if(*cp == '#') { |
|
113 mod = *cp; ++cp; |
|
114 } |
|
115 buf = __write_formatted_time(buf, *cp++, mod, table, t); |
|
116 } else |
|
117 *buf++ = *cp++; |
|
118 } |
|
119 return buf; |
|
120 } |
|
121 |
|
122 /* The number of days from the first day of the first ISO week of this |
|
123 year to the year day YDAY with week day WDAY. ISO weeks start on |
|
124 Monday; the first ISO week has the year's first Thursday. YDAY may |
|
125 be as small as YDAY_MINIMUM. */ |
|
126 #define __ISO_WEEK_START_WDAY 1 /* Monday */ |
|
127 #define __ISO_WEEK1_WDAY 4 /* Thursday */ |
|
128 #define __YDAY_MINIMUM (-366) |
|
129 #define __TM_YEAR_BASE 1900 |
|
130 #if defined(__GNUC__) |
|
131 static int |
|
132 __iso_week_days (int yday, int wday) |
|
133 { |
|
134 /* Add enough to the first operand of % to make it nonnegative. */ |
|
135 int big_enough_multiple_of_7 = (-__YDAY_MINIMUM / 7 + 2) * 7; |
|
136 return (yday |
|
137 - (yday - wday + __ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7 |
|
138 + __ISO_WEEK1_WDAY - __ISO_WEEK_START_WDAY); |
|
139 } |
|
140 #endif |
|
141 |
|
142 #define __is_leap(year) \ |
|
143 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) |
|
144 |
|
145 #define __hour12(hour) \ |
|
146 (((hour) % 12 == 0) ? (12) : (hour) % 12) |
|
147 |
|
148 _STLP_EXP_DECLSPEC char * __write_formatted_time(char* buf, char format, char modifier, |
|
149 const _Time_Info& table, const tm* t) { |
|
150 switch(format) { |
|
151 case 'a': |
|
152 return copy(table._M_dayname[t->tm_wday].begin(), |
|
153 table._M_dayname[t->tm_wday].end(), |
|
154 buf); |
|
155 |
|
156 case 'A': |
|
157 return copy(table._M_dayname[t->tm_wday+7].begin(), |
|
158 table._M_dayname[t->tm_wday+7].end(), |
|
159 buf); |
|
160 |
|
161 case 'b': |
|
162 return copy(table._M_monthname[t->tm_mon].begin(), |
|
163 table._M_monthname[t->tm_mon].end(), |
|
164 buf); |
|
165 |
|
166 case 'B': |
|
167 return copy(table._M_monthname[t->tm_mon+12].begin(), |
|
168 table._M_monthname[t->tm_mon+12].end(), |
|
169 buf); |
|
170 |
|
171 case 'c': { |
|
172 const char * cp = (modifier != '#') ? table._M_date_time_format.data():\ |
|
173 table._M_long_date_time_format.data(); |
|
174 const char* cp_end = (modifier != '#') ? cp + table._M_date_time_format.size():\ |
|
175 cp + table._M_long_date_time_format.size(); |
|
176 char mod = 0; |
|
177 while (cp != cp_end) { |
|
178 if (*cp == '%') { |
|
179 ++cp; if(*cp == '#') mod = *cp++; else mod = 0; |
|
180 buf = __write_formatted_time(buf, *cp++, mod, table, t); |
|
181 } |
|
182 else |
|
183 *buf++ = *cp++; |
|
184 } |
|
185 return buf; |
|
186 } |
|
187 |
|
188 case 'd': |
|
189 sprintf(buf, (modifier != '#')?"%.2ld":"%ld", (long)t->tm_mday); |
|
190 return ((long)t->tm_mday < 10L && modifier == '#')?buf+1:buf + 2; |
|
191 |
|
192 case 'e': |
|
193 sprintf(buf, "%2ld", (long)t->tm_mday); |
|
194 return buf + 2; |
|
195 |
|
196 case 'H': |
|
197 sprintf(buf, (modifier != '#')?"%.2ld":"%ld", (long)t->tm_hour); |
|
198 return ((long)t->tm_hour < 10L && modifier == '#')?buf+1:buf + 2; |
|
199 |
|
200 case 'I': |
|
201 sprintf(buf, (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 sprintf(buf, (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 sprintf(buf, (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 sprintf(buf, (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 ? |
|
236 (t->tm_yday + 1) / 7 : |
|
237 (t->tm_yday + 8 - t->tm_wday) / 7)); |
|
238 |
|
239 case'x': { |
|
240 const char * cp = (modifier != '#') ? table._M_date_format.data():\ |
|
241 table._M_long_date_format.data(); |
|
242 const char* cp_end = (modifier != '#') ? cp + table._M_date_format.size():\ |
|
243 cp + table._M_long_date_format.size(); |
|
244 char mod = 0; |
|
245 while (cp != cp_end) { |
|
246 if (*cp == '%') { |
|
247 ++cp; if(*cp == '#') mod = *cp++; else mod = 0; |
|
248 buf = __write_formatted_time(buf, *cp++, mod, table, t); |
|
249 } |
|
250 else |
|
251 *buf++ = *cp++; |
|
252 } |
|
253 return buf; |
|
254 } |
|
255 |
|
256 case 'X': { |
|
257 const char * cp = table._M_time_format.data(); |
|
258 const char* cp_end = cp + table._M_time_format.size(); |
|
259 char mod = 0; |
|
260 while (cp != cp_end) { |
|
261 if (*cp == '%') { |
|
262 ++cp; if(*cp == '#') mod = *cp++; else mod = 0; |
|
263 buf = __write_formatted_time(buf, *cp++, mod, table, t); |
|
264 } |
|
265 else |
|
266 *buf++ = *cp++; |
|
267 } |
|
268 return buf; |
|
269 } |
|
270 case 'y': |
|
271 return __write_integer(buf, 0, (long)((long)(t->tm_year + 1900) % 100)); |
|
272 |
|
273 case 'Y': |
|
274 return __write_integer(buf, 0, (long)((long)t->tm_year + 1900)); |
|
275 |
|
276 case '%': |
|
277 *buf++ = '%'; |
|
278 return buf; |
|
279 |
|
280 #ifdef __GNUC__ |
|
281 |
|
282 // fbp : at least on SUN |
|
283 # if defined ( _STLP_UNIX ) && ! defined (__linux__) |
|
284 # define __USE_BSD 1 |
|
285 # endif |
|
286 |
|
287 /********************************************* |
|
288 * JGS, handle various extensions * |
|
289 *********************************************/ |
|
290 |
|
291 case 'h': /* POSIX.2 extension */ |
|
292 // same as 'b', abbrev month name |
|
293 return copy(table._M_monthname[t->tm_mon].begin(), |
|
294 table._M_monthname[t->tm_mon].end(), |
|
295 buf); |
|
296 |
|
297 case 'C': /* POSIX.2 extension */ |
|
298 // same as 'd', the day |
|
299 sprintf(buf, "%2ld", (long)t->tm_mday); |
|
300 return buf + 2; |
|
301 |
|
302 case 'D': /* POSIX.2 extension */ |
|
303 // same as 'x' |
|
304 return __subformat(table._M_date_format, buf, table, t); |
|
305 |
|
306 case 'k': /* GNU extension */ |
|
307 sprintf(buf, "%2ld", (long)t->tm_hour); |
|
308 return buf + 2; |
|
309 |
|
310 case 'l': /* GNU extension */ |
|
311 sprintf(buf, "%2ld", (long)t->tm_hour % 12); |
|
312 return buf + 2; |
|
313 |
|
314 case 'n': /* POSIX.2 extension */ |
|
315 *buf++ = '\n'; |
|
316 return buf; |
|
317 |
|
318 case 'R': /* GNU extension */ |
|
319 return __subformat("%H:%M", buf, table, t); |
|
320 |
|
321 case 'r': /* POSIX.2 extension */ |
|
322 return __subformat("%I:%M:%S %p", buf, table, t); |
|
323 |
|
324 case 'T': /* POSIX.2 extension. */ |
|
325 return __subformat("%H:%M:%S", buf, table, t); |
|
326 |
|
327 case 't': /* POSIX.2 extension. */ |
|
328 *buf++ = '\t'; |
|
329 return buf; |
|
330 |
|
331 case 'u': /* POSIX.2 extension. */ |
|
332 return __write_integer(buf, 0, long((t->tm_wday - 1 + 7)) % 7 + 1); |
|
333 |
|
334 case 's': { |
|
335 time_t __t; |
|
336 __t = mktime ((tm*)t); |
|
337 return __write_integer(buf, 0, (long)__t ); |
|
338 } |
|
339 case 'g': /* GNU extension */ |
|
340 case 'G': { |
|
341 int year = t->tm_year + __TM_YEAR_BASE; |
|
342 int days = __iso_week_days (t->tm_yday, t->tm_wday); |
|
343 if (days < 0) { |
|
344 /* This ISO week belongs to the previous year. */ |
|
345 year--; |
|
346 days = __iso_week_days (t->tm_yday + (365 + __is_leap (year)), |
|
347 t->tm_wday); |
|
348 } else { |
|
349 int d = __iso_week_days (t->tm_yday - (365 + __is_leap (year)), |
|
350 t->tm_wday); |
|
351 if (0 <= d) { |
|
352 /* This ISO week belongs to the next year. */ |
|
353 year++; |
|
354 days = d; |
|
355 } |
|
356 } |
|
357 switch (format) { |
|
358 case 'g': |
|
359 return __write_integer(buf, 0, (long)(year % 100 + 100) % 100); |
|
360 case 'G': |
|
361 return __write_integer(buf, 0, (long)year); |
|
362 default: |
|
363 return __write_integer(buf, 0, (long)days / 7 + 1); |
|
364 } |
|
365 } |
|
366 |
|
367 # if defined ( _STLP_USE_GLIBC ) && ! defined (__CYGWIN__) |
|
368 case 'z': /* GNU extension. */ |
|
369 if (t->tm_isdst < 0) |
|
370 break; |
|
371 { |
|
372 int diff; |
|
373 #if defined(__USE_BSD) || defined(__BEOS__) |
|
374 diff = t->tm_gmtoff; |
|
375 #else |
|
376 diff = t->__tm_gmtoff; |
|
377 #endif |
|
378 if (diff < 0) { |
|
379 *buf++ = '-'; |
|
380 diff = -diff; |
|
381 } else |
|
382 *buf++ = '+'; |
|
383 |
|
384 diff /= 60; |
|
385 sprintf(buf, "%.4d", (diff / 60) * 100 + diff % 60); |
|
386 return buf + 4; |
|
387 } |
|
388 # endif /* __GLIBC__ */ |
|
389 #endif /* __GNUC__ */ |
|
390 |
|
391 default: |
|
392 // return buf; |
|
393 break; |
|
394 } |
|
395 return buf; |
|
396 } |
|
397 |
|
398 _STLP_EXP_DECLSPEC time_base::dateorder _STLP_CALL |
|
399 __get_date_order(_Locale_time* time) |
|
400 { |
|
401 const char * fmt = _Locale_d_fmt(time); |
|
402 char first, second, third; |
|
403 |
|
404 while (*fmt != 0 && *fmt != '%') ++fmt; |
|
405 if (*fmt == 0) |
|
406 return time_base::no_order; |
|
407 first = *++fmt; |
|
408 while (*fmt != 0 && *fmt != '%') ++fmt; |
|
409 if (*fmt == 0) |
|
410 return time_base::no_order; |
|
411 second = *++fmt; |
|
412 while (*fmt != 0 && *fmt != '%') ++fmt; |
|
413 if (*fmt == 0) |
|
414 return time_base::no_order; |
|
415 third = *++fmt; |
|
416 |
|
417 switch (first) { |
|
418 case 'd': |
|
419 return (second == 'm' && third == 'y') ? time_base::dmy |
|
420 : time_base::no_order; |
|
421 case 'm': |
|
422 return (second == 'd' && third == 'y') ? time_base::mdy |
|
423 : time_base::no_order; |
|
424 case 'y': |
|
425 switch (second) { |
|
426 case 'd': |
|
427 return third == 'm' ? time_base::ydm : time_base::no_order; |
|
428 case 'm': |
|
429 return third == 'd' ? time_base::ymd : time_base::no_order; |
|
430 default: |
|
431 return time_base::no_order; |
|
432 } |
|
433 default: |
|
434 return time_base::no_order; |
|
435 } |
|
436 } |
|
437 |
|
438 #if !defined(_STLP_NO_FORCE_INSTANTIATE) |
|
439 template class time_get<char, istreambuf_iterator<char, char_traits<char> > >; |
|
440 // template class time_get<char, const char*>; |
|
441 template class time_put<char, ostreambuf_iterator<char, char_traits<char> > >; |
|
442 // template class time_put<char, char*>; |
|
443 |
|
444 #ifndef _STLP_NO_WCHAR_T |
|
445 template class time_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >; |
|
446 // template class time_get<wchar_t, const wchar_t*>; |
|
447 template class time_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >; |
|
448 // template class time_put<wchar_t, wchar_t*>; |
|
449 #endif /* INSTANTIATE_WIDE_STREAMS */ |
|
450 |
|
451 #endif |
|
452 |
|
453 _STLP_END_NAMESPACE |