3 * Silicon Graphics Computer Systems, Inc.
8 * This material is provided "as is", with absolutely no warranty expressed
9 * or implied. Any use is at your own risk.
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.
18 #ifndef _STLP_TIME_FACETS_C
19 #define _STLP_TIME_FACETS_C
21 #ifndef _STLP_INTERNAL_TIME_FACETS_H
22 # include <stl/_time_facets.h>
25 #ifndef _STLP_INTERNAL_NUM_PUT_H
26 # include <stl/_num_put.h>
29 #ifndef _STLP_INTERNAL_NUM_GET_H
30 # include <stl/_num_get.h>
35 //----------------------------------------------------------------------
36 // Declarations of static template members.
38 template <class _CharT
, class _InputIterator
>
39 locale::id time_get
<_CharT
, _InputIterator
>::id
;
41 template <class _CharT
, class _OutputIterator
>
42 locale::id time_put
<_CharT
, _OutputIterator
>::id
;
44 _STLP_MOVE_TO_PRIV_NAMESPACE
46 /* Matching input against a list of names
48 * Alphabetic input of the names of months and the names
49 * of weekdays requires matching input against a list of names.
50 * We use a simple generic algorithm to accomplish this. This
51 * algorithm is not very efficient, especially for longer lists
52 * of names, but it probably does not matter for the initial
53 * implementation and it may never matter, since we do not expect
54 * this kind of input to be used very often. The algorithm
55 * could be improved fairly simply by creating a new list of
56 * names still in the running at each iteration. A more sophisticated
57 * approach would be to build a tree to do the matching.
59 * We compare each character of the input to the corresponding
60 * character of each name on the list that has not been eliminated,
61 * either because every character in the name has already been
62 * matched, or because some character has not been matched. We
63 * continue only as long as there are some names that have not been
66 * We do not really need a random access iterator (a forward iterator
67 * would do), but the extra generality makes the notation clumsier,
68 * and we don't really need it.
70 * We can recognize a failed match by the fact that the return value
76 template <class _InIt
, class _NameIt
>
78 __match(_InIt
& __first
, _InIt
& __last
, _NameIt __name
, _NameIt __name_end
) {
79 typedef ptrdiff_t difference_type
;
80 difference_type __n
= __name_end
- __name
;
81 difference_type __i
, __start
= 0;
83 difference_type __check_count
= __n
;
84 bool __do_not_check
[_MAXNAMES
];
85 size_t __matching_name_index
= __n
;
87 memset(__do_not_check
, 0, sizeof(__do_not_check
));
89 while (__first
!= __last
) {
90 difference_type __new_n
= __n
;
91 for (__i
= __start
; __i
< __n
; ++__i
) {
92 if (!__do_not_check
[__i
]) {
93 if (*__first
== __name
[__i
][__pos
]) {
94 if (__pos
== (__name
[__i
].size() - 1)) {
95 __matching_name_index
= __i
;
96 __do_not_check
[__i
] = true;
97 if (__i
== __start
) ++__start
;
99 if (__check_count
== 0) {
101 return __matching_name_index
;
107 __do_not_check
[__i
] = true;
108 if (__i
== __start
) ++__start
;
110 if (__check_count
== 0)
111 return __matching_name_index
;
115 if (__i
== __start
) ++ __start
;
123 return __matching_name_index
;
126 // __get_formatted_time reads input that is assumed to be formatted
127 // according to the rules for the C strftime function (C standard,
128 // 7.12.3.5). This function is used to implement the do_get_time
129 // and do_get_date virtual functions, which depend on the locale
130 // specifications for the time and day formats respectively.
131 // Note the catchall default case, intended mainly for the '%Z'
132 // format designator, which does not make sense here since the
133 // representation of timezones is not part of the locale.
135 // The case branches are implemented either by doing a match using
136 // the appopriate name table or by doing a __get_integer_nogroup.
138 // 'y' format is assumed to mean that the input represents years
139 // since 1900. That is, 2002 should be represented as 102. There
140 // is no century-guessing.
142 // The match is successful if and only if the second component of the
143 // return value is format_end.
145 // Note that the antepenultimate parameter is being used only to determine
146 // the correct overloading for the calls to __get_integer_nogroup.
147 template <class _InIt1
, class _Ch
, class _TimeInfo
>
148 string::const_iterator _STLP_CALL
149 __get_formatted_time
_STLP_WEAK (_InIt1 __first
, _InIt1 __last
,
150 string::const_iterator __format
, string::const_iterator __format_end
,
151 _Ch
*, const _TimeInfo
& __table
,
152 const ios_base
& __s
, ios_base::iostate
& __err
, tm
* __t
) {
153 const ctype
<_Ch
>& __ct
= use_facet
<ctype
<_Ch
> >(__s
.getloc());
154 typedef basic_string
<_Ch
, char_traits
<_Ch
>, allocator
<_Ch
> > string_type
;
157 while (__first
!= __last
&& __format
!= __format_end
) {
159 if (*__format
== '%') {
161 char __c
= *__format
;
162 if (__c
== '#') { //MS extension
171 size_t __index
= __match(__first
, __last
,
172 __table
._M_dayname
+ offset
, __table
._M_dayname
+ offset
+ 7);
175 __t
->tm_wday
= __STATIC_CAST(int, __index
);
182 size_t __index
= __match(__first
, __last
,
183 __table
._M_monthname
+ offset
, __table
._M_monthname
+ offset
+ 12);
186 __t
->tm_mon
= __STATIC_CAST(int, __index
);
191 bool __pr
= __get_decimal_integer(__first
, __last
, __t
->tm_mday
, __STATIC_CAST(_Ch
*, 0));
192 if (!__pr
|| __t
->tm_mday
< 1 || __t
->tm_mday
> 31) {
193 __err
|= ios_base::failbit
;
199 case 'H': case 'I': {
200 bool __pr
= __get_decimal_integer(__first
, __last
, __t
->tm_hour
, __STATIC_CAST(_Ch
*, 0));
207 bool __pr
= __get_decimal_integer(__first
, __last
, __t
->tm_yday
, __STATIC_CAST(_Ch
*, 0));
214 bool __pr
= __get_decimal_integer(__first
, __last
, __t
->tm_mon
, __STATIC_CAST(_Ch
*, 0));
216 if (!__pr
|| __t
->tm_mon
< 0 || __t
->tm_mon
> 11) {
217 __err
|= ios_base::failbit
;
224 bool __pr
= __get_decimal_integer(__first
, __last
, __t
->tm_min
, __STATIC_CAST(_Ch
*, 0));
231 size_t __index
= __match(__first
, __last
,
232 __table
._M_am_pm
+ 0, __table
._M_am_pm
+ 2);
235 // 12:00 PM <=> 12:00, 12:00 AM <=> 00:00
236 if (__index
== 1 && __t
->tm_hour
!= 12 )
238 if (__index
== 0 && __t
->tm_hour
== 12 )
244 bool __pr
= __get_decimal_integer(__first
, __last
, __t
->tm_sec
, __STATIC_CAST(_Ch
*, 0));
251 bool __pr
= __get_decimal_integer(__first
, __last
, __t
->tm_year
, __STATIC_CAST(_Ch
*, 0));
258 bool __pr
= __get_decimal_integer(__first
, __last
, __t
->tm_year
, __STATIC_CAST(_Ch
*, 0));
259 __t
->tm_year
-= 1900;
270 if (*__first
++ != __ct
.widen(*__format
)) break;
279 template <class _InIt
, class _TimeInfo
>
281 __get_short_or_long_dayname(_InIt
& __first
, _InIt
& __last
, const _TimeInfo
& __table
, tm
* __t
) {
282 size_t __index
= __match(__first
, __last
, __table
._M_dayname
+ 0, __table
._M_dayname
+ 14);
284 __t
->tm_wday
= __STATIC_CAST(int, __index
% 7);
290 template <class _InIt
, class _TimeInfo
>
292 __get_short_or_long_monthname(_InIt
& __first
, _InIt
& __last
, const _TimeInfo
& __table
, tm
* __t
) {
293 size_t __index
= __match(__first
, __last
, __table
._M_monthname
+ 0, __table
._M_monthname
+ 24);
295 __t
->tm_mon
= __STATIC_CAST(int, __index
% 12);
301 _STLP_MOVE_TO_STD_NAMESPACE
303 template <class _Ch
, class _InIt
>
305 time_get
<_Ch
, _InIt
>::do_get_date(_InIt __s
, _InIt __end
,
306 ios_base
& __str
, ios_base::iostate
& __err
,
308 typedef string::const_iterator string_iterator
;
310 string_iterator __format
= this->_M_timeinfo
._M_date_format
.begin();
311 string_iterator __format_end
= this->_M_timeinfo
._M_date_format
.end();
313 string_iterator __result
314 = _STLP_PRIV
__get_formatted_time(__s
, __end
, __format
, __format_end
,
315 __STATIC_CAST(_Ch
*, 0), this->_M_timeinfo
,
317 if (__result
== __format_end
)
318 __err
= ios_base::goodbit
;
320 __err
= ios_base::failbit
;
322 __err
|= ios_base::eofbit
;
327 template <class _Ch
, class _InIt
>
329 time_get
<_Ch
, _InIt
>::do_get_time(_InIt __s
, _InIt __end
,
330 ios_base
& __str
, ios_base::iostate
& __err
,
332 typedef string::const_iterator string_iterator
;
333 string_iterator __format
= this->_M_timeinfo
._M_time_format
.begin();
334 string_iterator __format_end
= this->_M_timeinfo
._M_time_format
.end();
336 string_iterator __result
337 = _STLP_PRIV
__get_formatted_time(__s
, __end
, __format
, __format_end
,
338 __STATIC_CAST(_Ch
*, 0), this->_M_timeinfo
,
340 __err
= __result
== __format_end
? ios_base::goodbit
343 __err
|= ios_base::eofbit
;
347 template <class _Ch
, class _InIt
>
349 time_get
<_Ch
, _InIt
>::do_get_year(_InIt __s
, _InIt __end
,
350 ios_base
&, ios_base::iostate
& __err
,
353 __err
= ios_base::failbit
| ios_base::eofbit
;
357 bool __pr
= _STLP_PRIV
__get_decimal_integer(__s
, __end
, __t
->tm_year
, __STATIC_CAST(_Ch
*, 0));
358 __t
->tm_year
-= 1900;
359 __err
= __pr
? ios_base::goodbit
: ios_base::failbit
;
361 __err
|= ios_base::eofbit
;
366 template <class _Ch
, class _InIt
>
368 time_get
<_Ch
, _InIt
>::do_get_weekday(_InIt __s
, _InIt __end
,
369 ios_base
&__str
, ios_base::iostate
&__err
,
372 _STLP_PRIV
__get_short_or_long_dayname(__s
, __end
, this->_M_timeinfo
, __t
);
374 __err
= ios_base::goodbit
;
376 __err
= ios_base::failbit
;
378 __err
|= ios_base::eofbit
;
383 template <class _Ch
, class _InIt
>
385 time_get
<_Ch
, _InIt
>::do_get_monthname(_InIt __s
, _InIt __end
,
386 ios_base
&__str
, ios_base::iostate
&__err
,
389 _STLP_PRIV
__get_short_or_long_monthname(__s
, __end
, this->_M_timeinfo
, __t
);
391 __err
= ios_base::goodbit
;
393 __err
= ios_base::failbit
;
395 __err
|= ios_base::eofbit
;
400 template<class _Ch
, class _OutputIter
>
402 time_put
<_Ch
,_OutputIter
>::put(_OutputIter __s
, ios_base
& __f
, _Ch __fill
,
403 const tm
* __tmb
, const _Ch
* __pat
,
404 const _Ch
* __pat_end
) const {
405 const ctype
<_Ch
>& _Ct
= use_facet
<ctype
<_Ch
> >(__f
.getloc());
406 while (__pat
!= __pat_end
) {
407 char __c
= _Ct
.narrow(*__pat
, 0);
411 __c
= _Ct
.narrow(*__pat
++, 0);
412 if (__c
== '#') { // MS extension
414 __c
= _Ct
.narrow(*__pat
++, 0);
416 __s
= do_put(__s
, __f
, __fill
, __tmb
, __c
, __mod
);
424 template<class _Ch
, class _OutputIter
>
426 time_put
<_Ch
,_OutputIter
>::do_put(_OutputIter __s
, ios_base
& __f
, _Ch
/* __fill */,
427 const tm
* __tmb
, char __format
,
428 char __modifier
) const {
429 const ctype
<_Ch
>& __ct
= use_facet
<ctype
<_Ch
> >(__f
.getloc());
430 _STLP_BASIC_IOSTRING(_Ch
) __buf
;
431 _STLP_PRIV
__write_formatted_time(__buf
, __ct
, __format
, __modifier
, this->_M_timeinfo
, __tmb
);
432 return copy(__buf
.begin(), __buf
.end(), __s
);
437 #endif /* _STLP_TIME_FACETS_C */