Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
_time_get.cc
Go to the documentation of this file.
1
30#include <streambuf>
31#include <loc/_ctype.h>
32#include <loc/_punct.h>
33#include <loc/_locale.h>
34
35
37
38_RWSTD_EXPORT _RWSTD_SIZE_T
39__rw_get_timepunct (const __rw_facet *pfacet,
40 int data [4], _RWSTD_C::tm *tmb, int **pmem,
41 const void *names[], _RWSTD_SIZE_T sizes[]);
42
43} // namespace __rw
44
45
47
48
49template <class _CharT, class _InputIter>
50_RW::__rw_facet_id time_get<_CharT, _InputIter>::id;
51
52
53// outlined to avoid generating a vtable in each translation unit
54// that uses the class
55template <class _CharT, class _InputIter>
56/* virtual */ time_get<_CharT, _InputIter>::
57~time_get ()
58{
59 // no-op
60}
61
62
63template <class _CharT, class _InputIter>
64typename time_get<_CharT, _InputIter>::iter_type
65time_get<_CharT, _InputIter>::
66get (iter_type __it, iter_type __end, ios_base &__fl, _RWSTD_IOSTATE &__err,
67 tm *__tmb, const char_type *__pat, const char_type *__pat_end) const
68{
69 _RWSTD_ASSERT (0 != __pat);
70 _RWSTD_ASSERT (__pat <= __pat_end);
71
72 const ctype<char_type> &__ctp =
73 _RWSTD_USE_FACET (ctype<char_type>, __fl.getloc ());
74
75 // extension: `tmb' may be 0
76 tm __tmp = __tmb ? *__tmb : tm ();
77
78 _RWSTD_IOSTATE __errtmp = _RW::__rw_goodbit;
79
80 char __fmt [] = { '\0', '\0' };
81
82 for (; __pat != __pat_end; ++__pat) {
83
84 if (__errtmp) {
85 // failed to match the whole pattern
86 __errtmp |= _RW::__rw_failbit;
87 break;
88 }
89
90 const char __ch = __ctp.narrow (*__pat, '\0');
91
92 if (__fmt [0]) {
93 if ('E' == __ch || 'O' == __ch)
94 __fmt [1] = __ch;
95 else if ('.' == __ch || __ch >= '0' && __ch <= '9') {
96 // FIXME: handle the "%.[0-9]*" HP-UX extension
97 }
98 else {
99 __it = do_get (__it, __end, __fl, __errtmp, &__tmp, __ch,
100 __fmt [1]);
101 __fmt [0] = __fmt [1] = '\0'; // reset
102 }
103 }
104 else if ('%' == __ch) {
105 __fmt [0] = __ch;
106 }
107 else if (__ctp.is (ctype_base::space, *__pat)) {
108 // skip all whitespace characters
109 while (__it != __end && __ctp.is (ctype_base::space, *__it))
110 ++__it;
111 }
112 else {
113 if (__it != __end && __ch == __ctp.narrow (*__it, '\0'))
114 ++__it;
115 else {
116 // mismatch between pattern and input
117 __errtmp |= _RW::__rw_failbit;
118 break;
119 }
120 }
121 }
122
123 // store value only on success
124 if (!(__errtmp & ~_RW::__rw_eofbit) && __tmb)
125 *__tmb = __tmp;
126
127 __err |= __errtmp;
128
129 return __it;
130}
131
132
133template <class _CharT, class _InputIter>
134/* virtual */ typename time_get<_CharT, _InputIter>::iter_type
135time_get<_CharT, _InputIter>::
136do_get (iter_type __it, iter_type __end, ios_base &__fl,
137 _RWSTD_IOSTATE &__err, tm *__tmb,
138 char __fmt, char __modifier /* = '\0' */) const
139{
140 // enough pointers for 100 alternative numeric symbols and their sizes
141 const char_type* __names [100];
142 _RWSTD_SIZE_T __sizes [sizeof __names / sizeof *__names];
143
144 const void** __pv =
145 _RWSTD_REINTERPRET_CAST (const void**, __names);
146
147 tm __tmp = __tmb ? *__tmb : tm ();
148
149 int *__pmem = 0; // pointer to std::tm member
150
151 _RWSTD_SIZE_T __dup; // number of allowed duplicates
152
153 const ctype<char_type> &__ctp =
154 _RWSTD_USE_FACET (ctype<char_type>, __fl.getloc ());
155
156 switch (__fmt) {
157
158 case 'A': case 'a': case 'B': case 'b': case 'h':
159 // names of days and months can have duplicates (i.e.,
160 // it can be either a full name aor an abbreviation)
161 __dup = 2;
162 break;
163
164 case 'n': case 't': { // any whitespace
165
166 for ( ; ; ++__it) {
167
168 if (__it == __end) {
169 __err |= _RW::__rw_eofbit;
170 break;
171 }
172
173 if (!__ctp.is (ctype_base::space, *__it))
174 break;
175 }
176
177 return __it;
178 }
179
180 default: __dup = 1;
181 }
182
183 int __data [4] = {
184 // array of input data for __rw_get_timepunct will on output
185 // contain data needed to interpret values parsed below
186 __fmt, __modifier, sizeof (char_type) > sizeof (char), 0
187 };
188
189 // get the number of punctuator (or format) string(s) and their values
190 const _RWSTD_SIZE_T __cnt =
191 _RW::__rw_get_timepunct (this, __data, &__tmp,
192 &__pmem, __pv, __sizes);
193
194 if (1 == __cnt) {
195 _RWSTD_ASSERT (0 != __names [0]);
196
197 // single punctuator string stored in `names [0]'
198 // e.g., "%m/%d/%y" for the format of "%D" (`fmt' == 'D')
199 return get (__it, __end, __fl, __err, __tmb,
200 __names [0], __names [0] + __sizes [0]);
201 }
202
203 _RWSTD_IOSTATE __errtmp = _RW::__rw_goodbit;
204
205 if (__cnt > 1) {
206
207 // parse string on input
208
209 // set `inx' to 0 to allow numeric input, SIZE_MAX otherwise
210 _RWSTD_SIZE_T __inx = 'O' == __modifier ? 0 : _RWSTD_SIZE_MAX;
211
212 // on function input, `interr' contains the maximum number
213 // of duplicates; on output, it contains an iostate value
214 // and `inx' contains the index of the parsed name within
215 // the `names' array
216 int __interr = int (__dup);
217
218 __it = _RW::__rw_match_name (__it, __end, __names, __sizes,
219 __cnt, __inx, __interr, &__fl);
220
221 __errtmp = _RWSTD_IOSTATE (__interr);
222
223 if (__inx == _RWSTD_SIZE_MAX) {
224
225 // if no name matches, and the first name is the empty
226 // (i.e., alt_digits 0 is not defined), try to match
227 // and extract all zeros
228 if ( !__errtmp && 0 == __sizes [0]
229 && __it != __end && '0' == __ctp.narrow (*__it, '\0')) {
230
231 while ('0' == __ctp.narrow (*__it, '\0')) {
232
233 if (++__it == __end) {
234 __errtmp |= _RW::__rw_eofbit;
235 break;
236 }
237 }
238 }
239 else {
240 __errtmp |= _RW::__rw_failbit;
241 }
242 }
243 else if ('p' == __fmt) {
244 if (__pmem) {
245 if (!__inx && 11 == *__pmem)
246 *__pmem = 0;
247 else if (*__pmem < 12) {
248 if (!__inx || 11 != *__pmem)
249 *__pmem += int (__inx * 12) + 1;
250 else
251 *__pmem += 1;
252 }
253 else {
254 // invalid data
255 __errtmp |= _RW::__rw_failbit;
256 }
257 }
258 else {
259 // invalid (or unimplemented) format
260 __errtmp |= _RW::__rw_failbit;
261 }
262 }
263 else if (__pmem) {
264 _RWSTD_ASSERT (0 != __pmem);
265
266 if (__inx == __cnt && !__sizes [0] || __inx >= 2 * __cnt)
267 *__pmem = int (__inx - __cnt);
268 else if (__inx < __cnt)
269 *__pmem = int (__inx % (__cnt / __dup));
270 else
271 __errtmp |= _RW::__rw_failbit;
272
273 const int __adj = __data [0]; // value to increment result by
274 const int __fac = __data [1]; // value to multiply result by
275
276 *__pmem = *__pmem * __fac + __adj;
277
278 const int __lob = __data [2]; // lower bound on valid input
279 const int __hib = __data [3]; // upper bound on valid input
280
281 // validate input value
282 if (*__pmem < __lob || *__pmem > __hib)
283 __errtmp |= _RW::__rw_failbit;
284 }
285 else {
286 // invalid (or unimplemented) format
287 __errtmp |= _RW::__rw_failbit;
288 }
289 }
290 else if (__pmem) {
291
292 // parse numeric input
293
294 _RWSTD_SIZE_T __nread = 0;
295
296 int __mem = 0;
297
298 for ( ; ; ++__it, ++__nread) {
299 if (__it == __end) {
300 __err |= _RW::__rw_eofbit;
301 break;
302 }
303
304 const char_type __c = *__it;
305 if (!__ctp.is (ctype_base::digit, __c))
306 break;
307
308 const char __ch = __ctp.narrow (__c, '\0');
309 if (__ch < '0' || __ch > '9')
310 break;
311
312 __mem = 10 * __mem + __ch - '0';
313 }
314
315 if (__nread) {
316
317 const int __adj = __data [0]; // value to increment result by
318 const int __fac = __data [1]; // value to multiply result by
319
320 int __lob = __data [2]; // lower bound on valid input
321 int __hib = __data [3]; // upper bound on valid input
322
323 if ('y' == __fmt) {
324
325 // IEEE Std 1003.1-2001: When a century is not otherwise
326 // specified, values in the range [69,99] shall refer to
327 // years 1969 to 1999 inclusive, and values in the range
328 // [00,68] shall refer to years 2000 to 2068 inclusive.
329
330 if (__mem > 99) {
331 __lob = -1900;
332 __hib = _RWSTD_INT_MAX - 1900;
333 __mem -= 1900;
334 }
335 else {
336 __lob = 69;
337 __hib = 168;
338
339 if (__mem < 69)
340 __mem += 100;
341 }
342 }
343
344 *__pmem = __mem * __fac + __adj;
345
346 // validate input value
347 if (*__pmem < __lob || *__pmem > __hib)
348 __errtmp |= _RW::__rw_failbit;
349 }
350 else {
351 // invalid data
352 __errtmp |= _RW::__rw_failbit;
353 }
354 }
355 else {
356 // invalid (or unimplemented) format
357 __errtmp |= _RW::__rw_failbit;
358 }
359
360 if (!(__errtmp & ~_RW::__rw_eofbit) && __tmb)
361 *__tmb = __tmp;
362
363 __err |= __errtmp;
364
365 return __it;
366}
367
368
369// outlined to avoid generating a vtable in each translation unit
370// that uses the class
371template <class _CharT, class _InputIter>
372/* virtual */ time_get_byname<_CharT, _InputIter>::
373~time_get_byname ()
374{
375 // no-op
376}
377
378
379} // namespace std
const char *const data[]
#define _RWSTD_EXPORT
Definition _defs.h:485
#define _RWSTD_USE_FACET(type, arg)
Definition _defs.h:949
#define _RWSTD_REINTERPRET_CAST(T, x)
Definition _defs.h:535
#define _RWSTD_NAMESPACE(name)
Definition _defs.h:567
#define _RWSTD_ASSERT(ignore)
Definition _defs.h:1108
#define _RWSTD_IOSTATE
Definition _iosfwd.h:91
Definition json.h:5363