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