2 Copyright © 1995-2008, 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] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
14 static const UBYTE monthday
[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
16 BOOL
_getnum(LONG numchars
,
19 CONST_STRPTR
*fmtTemplatePtr
,
21 const struct Locale
*locale
,
22 const struct Hook
*getCharFunc
,
23 struct LocaleBase
*LocaleBase
);
24 #define get2num(x) _getnum(2, (x), &c, &fmtTemplate, &checkEOF, locale, getCharFunc, LocaleBase)
25 #define get4num(x) _getnum(4, (x), &c, &fmtTemplate, &checkEOF, locale, getCharFunc, LocaleBase)
27 /*****************************************************************************
30 #include <proto/locale.h>
32 AROS_LH4(BOOL
, ParseDate
,
35 AROS_LHA(const struct Locale
*, locale
, A0
),
36 AROS_LHA(struct DateStamp
*, date
, A1
),
37 AROS_LHA(CONST_STRPTR
, fmtTemplate
, A2
),
38 AROS_LHA(const struct Hook
*, getCharFunc
, A3
),
41 struct LocaleBase
*, LocaleBase
, 27, Locale
)
44 This function will convert a stream of characters into an AmigaDOS
45 DateStamp structure. It will obtain its characters from the
46 getCharFunc callback hook, and the given formatting template will
47 be used to direct the parse.
50 locale - the locale to use for the formatting
51 date - where to put the converted date. If this is NULL,
52 then this function can be used to verify a date
54 fmtTemplate - the date template used to direct the parse of the
55 data. The following FormatDate() formatting
57 %a %A %b %B %d %e %h %H %I %m %M %p %S %y %Y
59 See FormatDate() autodoc for more information.
60 getCharFunc - A callback Hook which is used to read the data
61 from a stream. The hook is called with:
63 A0 - address of the Hook structure
67 BTW: The AmigaOS autodocs which state that A1
68 gets locale pointer and A2 NULL are wrong!!
70 The read character should be returned in D0. Note
71 that this is a 32 bit character not an 8 bit
72 character. Return a NULL character if you reach the
76 TRUE - If the parse could be performed.
77 FALSE - If the format of the data did not match the formatting
81 This has a few differences from the implementation in locale.library
83 - %p does not have to be at the end of the line.
84 - %d and %e are not effectively the same: leading spaces are
85 allowed before %e, but not before %d.
90 %p, %b, %A and probably others accept substrings and superstrings of
98 *****************************************************************************/
103 LONG day
= 0, month
= 0, hour
= 0, min
= 0, sec
= 0;
105 BOOL leap
, ampm
= FALSE
, checkEOF
= TRUE
;
106 if ( (fmtTemplate
== NULL
)
107 || (getCharFunc
== NULL
)
109 || (*fmtTemplate
== '\0')
114 AROS_UFC3(ULONG, getCharFunc->h_Entry, \
115 AROS_UFCA(const struct Hook *, getCharFunc, A0), \
116 AROS_UFCA(const struct Locale *, locale, A2), \
117 AROS_UFCA(ULONG, 0, A1))
121 /* Check for EOF if we leave the loop */
124 if (*fmtTemplate
== '%')
129 switch(*fmtTemplate
++)
131 /* abbreviated weekday name */
137 CONST_STRPTR dayStr
[7];
141 for (i
= 0; i
< 7; i
++)
144 dayStr
[i
] = GetLocaleStr(locale
, i
+ strOffs
+ 1);
148 while ((c
!= '\0') && (c
!= *fmtTemplate
))
150 for (i
=0; i
< 7; i
++)
152 a
= ConvToUpper(locale
, *(dayStr
[i
])++);
153 c
= ConvToUpper(locale
, c
);
156 if (a
!= c
) dayOk
[i
] = FALSE
;
161 /* End of stream in wrong place, or invalid */
162 if (((c
== '\0') && *fmtTemplate
) || (c
!= *fmtTemplate
))
165 /* If we didn't get a valid day, fail */
167 while ((i
< 7) && !dayOk
[i
++])
169 if ((i
== 7) && !dayOk
[6])
172 if (*fmtTemplate
) fmtTemplate
++;
174 } break; /* case 'A': */
176 /* abbreviated month name */
178 /* abbreviated month name */
184 CONST_STRPTR monthStr
[12];
188 for (i
= 0; i
< 12; i
++)
191 monthStr
[i
] = GetLocaleStr(locale
, i
+ strOffs
+ MON_1
);
195 while ((c
!= '\0') && (c
!= *fmtTemplate
))
197 for (i
=0; i
< 12; i
++)
199 a
= ConvToUpper(locale
, *(monthStr
[i
])++);
200 c
= ConvToUpper(locale
, c
);
203 if (a
!= c
) monthOk
[i
] = FALSE
;
208 /* End of stream in wrong place, or invalid */
209 if (((c
== '\0') && *fmtTemplate
) || (c
!= *fmtTemplate
))
212 /* If we didn't get a valid month, fail */
214 while ((i
< 12) && !monthOk
[i
++])
216 if ((i
== 12) && !monthOk
[11])
220 if (*fmtTemplate
) fmtTemplate
++;
236 /* Day no., leading spaces. */
240 while (IsSpace(locale
, c
))
249 /* hour 24-hr style */
255 if (hour
> 23) return FALSE
;
258 /* hour 12-hr style */
263 if (hour
> 11) return FALSE
;
269 if (!get2num(&month
))
271 if ((month
> 12) || (month
== 0))
281 if (min
> 59) return FALSE
;
284 /* AM or PM string */
287 CONST_STRPTR amStr
, pmStr
;
288 BOOL amOk
= TRUE
, pmOk
= TRUE
;
290 amStr
= GetLocaleStr(locale
, AM_STR
);
291 pmStr
= GetLocaleStr(locale
, PM_STR
);
294 while ((c
!= '\0') && (c
!= *fmtTemplate
))
296 a
= ConvToUpper(locale
, *amStr
++);
297 b
= ConvToUpper(locale
, *pmStr
++);
298 c
= ConvToUpper(locale
, c
);
301 if (a
!= c
) amOk
= FALSE
;
304 if (b
!= c
) pmOk
= FALSE
;
309 /* End of stream in wrong place, or invalid */
310 if (c
!= *fmtTemplate
)
313 /* Check whether we got AM or PM */
316 if (*fmtTemplate
) fmtTemplate
++;
321 /* the number of seconds */
326 if (sec
> 59) return FALSE
;
329 /* the year using two or four digits */
335 if (year
>= 100 && year
< 1978)
343 /* the year using four digits */
346 if (IsDigit(locale
, c
) == FALSE
)
348 year
= (c
- '0') * 1000;
351 if (IsDigit(locale
, c
) == FALSE
)
353 year
+= (c
- '0') * 100;
356 if (IsDigit(locale
, c
) == FALSE
)
358 year
+= (c
- '0') * 10;
361 if (IsDigit(locale
, c
) == FALSE
)
373 } /* if (char == '%') */
377 if (c
!= *fmtTemplate
++)
380 } /* while (*fmtTemplate) */
382 /* Reached end of fmtTemplate, end of input stream? */
384 if ((GetChar() != 0)) return FALSE
;
386 /* Is this year a leap year ? */
387 leap
= (((year
% 400) == 0) ||
388 (((year
% 4) == 0) && !((year
% 100) == 0)));
391 if (month
!= 0 && day
>=
392 (monthday
[month
- 1] + ((leap
&& (month
== 2)) ? 1 : 0)))
399 /* Add the days for all years (without leap years) */
400 day
+= (year
- 1978) * 365;
405 day
+= ((year
/ 4) - (year
/ 100) + (year
/ 400)
408 /* Add days of months */
409 day
+= monthdays
[month
- 1];
412 in monthdays, February has 28 days. Correct this in
413 leap years if month is >= March.
416 if (leap
&& (month
>= 3)) day
++;
420 date
->ds_Minute
= hour
* 60 + min
;
421 if ((hour
< 12) && ampm
)
422 date
->ds_Minute
+= 720;
423 date
->ds_Tick
= sec
* TICKS_PER_SECOND
;
431 BOOL
_getnum(LONG numchars
,
434 CONST_STRPTR
*fmtTemplatePtr
,
436 const struct Locale
*locale
,
437 const struct Hook
*getCharFunc
,
438 struct LocaleBase
*LocaleBase
)
445 if (IsDigit(locale
, c
) == FALSE
)
450 while (--numchars
>= 1)
453 if (IsDigit(locale
, c
))
454 val
= val
* 10 + c
- '0';
458 if (c
!= **fmtTemplatePtr
)
461 *checkEOFPtr
= FALSE
;