2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
6 #include <exec/types.h>
10 #include <aros/asmcall.h>
11 #include "locale_intern.h"
13 static const UWORD monthdays
[12] =
14 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
15 static const UBYTE monthday
[12] =
16 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
18 BOOL
_getnum(LONG numchars
,
21 CONST_STRPTR
* fmtTemplatePtr
,
23 const struct Locale
*locale
,
24 const struct Hook
*getCharFunc
, struct LocaleBase
*LocaleBase
);
25 #define get2num(x) _getnum(2, (x), &c, &fmtTemplate, &checkEOF, locale, getCharFunc, LocaleBase)
26 #define get4num(x) _getnum(4, (x), &c, &fmtTemplate, &checkEOF, locale, getCharFunc, LocaleBase)
28 /*****************************************************************************
31 #include <proto/locale.h>
33 AROS_LH4(BOOL
, ParseDate
,
36 AROS_LHA(const struct Locale
*, locale
, A0
),
37 AROS_LHA(struct DateStamp
*, date
, A1
),
38 AROS_LHA(CONST_STRPTR
, fmtTemplate
, A2
),
39 AROS_LHA(const struct Hook
*, getCharFunc
, A3
),
42 struct LocaleBase
*, LocaleBase
, 27, Locale
)
45 This function will convert a stream of characters into an AmigaDOS
46 DateStamp structure. It will obtain its characters from the
47 getCharFunc callback hook, and the given formatting template will
48 be used to direct the parse.
51 locale - the locale to use for the formatting
52 date - where to put the converted date. If this is NULL,
53 then this function can be used to verify a date
55 fmtTemplate - the date template used to direct the parse of the
56 data. The following FormatDate() formatting
58 %a %A %b %B %d %e %h %H %I %m %M %p %S %y %Y
60 See FormatDate() autodoc for more information.
61 getCharFunc - A callback Hook which is used to read the data
62 from a stream. The hook is called with:
64 A0 - address of the Hook structure
68 BTW: The AmigaOS autodocs which state that A1
69 gets locale pointer and A2 NULL are wrong!!
71 The read character should be returned in D0. Note
72 that this is a 32 bit character not an 8 bit
73 character. Return a NULL character if you reach the
77 TRUE - If the parse could be performed.
78 FALSE - If the format of the data did not match the formatting
82 This has a few differences from the implementation in locale.library
84 - %p does not have to be at the end of the line.
85 - %d and %e are not effectively the same: leading spaces are
86 allowed before %e, but not before %d.
91 %p, %b, %A and probably others accept substrings and superstrings of
99 *****************************************************************************/
104 LONG day
= 0, month
= 0, hour
= 0, min
= 0, sec
= 0;
106 BOOL leap
, am
= FALSE
, pm
= FALSE
, checkEOF
= TRUE
;
107 if ((fmtTemplate
== NULL
)
108 || (getCharFunc
== NULL
)
109 || (locale
== NULL
) || (*fmtTemplate
== '\0'))
113 AROS_UFC3(ULONG, getCharFunc->h_Entry, \
114 AROS_UFCA(const struct Hook *, getCharFunc, A0), \
115 AROS_UFCA(const struct Locale *, locale, A2), \
116 AROS_UFCA(ULONG, 0, A1))
120 /* Check for EOF if we leave the loop */
123 if (*fmtTemplate
== '%')
128 switch (*fmtTemplate
++)
130 /* abbreviated weekday name */
136 CONST_STRPTR dayStr
[7];
140 for (i
= 0; i
< 7; i
++)
143 dayStr
[i
] = GetLocaleStr(locale
, i
+ strOffs
+ 1);
147 while ((c
!= '\0') && (c
!= *fmtTemplate
))
149 for (i
= 0; i
< 7; i
++)
151 a
= ConvToUpper(locale
, *(dayStr
[i
])++);
152 c
= ConvToUpper(locale
, c
);
161 /* End of stream in wrong place, or invalid */
162 if (((c
== '\0') && *fmtTemplate
)
163 || (c
!= *fmtTemplate
))
166 /* If we didn't get a valid day, fail */
168 while ((i
< 7) && !dayOk
[i
++])
170 if ((i
== 7) && !dayOk
[6])
177 break; /* case 'A': */
179 /* abbreviated month name */
181 /* abbreviated month name */
186 CONST_STRPTR monthStr
[24];
190 for (i
= 0; i
< 24; i
++)
194 GetLocaleStr(locale
, i
+ strOffs
+ MON_1
);
198 while ((c
!= '\0') && (c
!= *fmtTemplate
))
200 for (i
= 0; i
< 24; i
++)
202 a
= ConvToUpper(locale
, *monthStr
[i
]);
205 c
= ConvToUpper(locale
, c
);
213 for (i
= 0; i
< 24; i
++)
215 if (monthOk
[i
] && *monthStr
[i
] == '\0')
219 /* If we didn't get a valid month, fail */
223 /* End of stream in wrong place, or invalid */
224 if (((c
== '\0') && *fmtTemplate
)
225 || (c
!= *fmtTemplate
))
245 /* Day no., leading spaces. */
249 while (IsSpace(locale
, c
))
258 /* hour 24-hr style */
268 /* hour 12-hr style */
273 if ((hour
> 12) || (hour
== 0))
280 if (!get2num(&month
))
282 if ((month
> 12) || (month
== 0))
296 /* AM or PM string */
299 CONST_STRPTR amStr
, pmStr
;
300 BOOL amOk
= TRUE
, pmOk
= TRUE
;
302 amStr
= GetLocaleStr(locale
, AM_STR
);
303 pmStr
= GetLocaleStr(locale
, PM_STR
);
306 while ((c
!= '\0') && (c
!= *fmtTemplate
))
308 a
= ConvToUpper(locale
, *amStr
++);
309 b
= ConvToUpper(locale
, *pmStr
++);
310 c
= ConvToUpper(locale
, c
);
323 /* End of stream in wrong place, or invalid */
324 if (c
!= *fmtTemplate
)
327 /* Check whether we got AM or PM */
337 /* the number of seconds */
346 /* the year using two or four digits */
352 if (year
>= 100 && year
< 1978)
360 /* the year using four digits */
363 if (IsDigit(locale
, c
) == FALSE
)
365 year
= (c
- '0') * 1000;
368 if (IsDigit(locale
, c
) == FALSE
)
370 year
+= (c
- '0') * 100;
373 if (IsDigit(locale
, c
) == FALSE
)
375 year
+= (c
- '0') * 10;
378 if (IsDigit(locale
, c
) == FALSE
)
390 } /* if (char == '%') */
394 if (c
!= *fmtTemplate
++)
397 } /* while (*fmtTemplate) */
399 /* Reached end of fmtTemplate, end of input stream? */
401 if ((GetChar() != 0))
404 /* Is this year a leap year ? */
405 leap
= (((year
% 400) == 0) ||
406 (((year
% 4) == 0) && !((year
% 100) == 0)));
409 if (month
!= 0 && day
>=
410 (monthday
[month
- 1] + ((leap
&& (month
== 2)) ? 1 : 0)))
417 /* Add the days for all years (without leap years) */
418 day
+= (year
- 1978) * 365;
423 day
+= ((year
/ 4) - (year
/ 100) + (year
/ 400) - (494 - 19 + 4));
425 /* Add days of months */
426 day
+= monthdays
[month
- 1];
429 in monthdays, February has 28 days. Correct this in
430 leap years if month is >= March.
433 if (leap
&& (month
>= 3))
438 date
->ds_Minute
= hour
* 60 + min
;
439 if ((hour
== 12) && am
)
440 date
->ds_Minute
-= 720;
441 if ((hour
< 12) && pm
)
442 date
->ds_Minute
+= 720;
443 date
->ds_Tick
= sec
* TICKS_PER_SECOND
;
451 BOOL
_getnum(LONG numchars
,
454 CONST_STRPTR
* fmtTemplatePtr
,
456 const struct Locale
* locale
,
457 const struct Hook
* getCharFunc
, struct LocaleBase
* LocaleBase
)
464 if (IsDigit(locale
, c
) == FALSE
)
469 while (--numchars
>= 1)
472 if (IsDigit(locale
, c
))
473 val
= val
* 10 + c
- '0';
477 if (c
!= **fmtTemplatePtr
)
480 *checkEOFPtr
= FALSE
;