Bug 3330205 Thread safe strptime implementation
Change-Id: I03e72b0253a7a2e015455ab81dbf155ed1e574d2
This commit is contained in:
parent
015610e64e
commit
b138e4f90f
@ -89,29 +89,31 @@ static const struct {
|
|||||||
#define _LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); }
|
#define _LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); }
|
||||||
|
|
||||||
|
|
||||||
|
struct century_relyear {
|
||||||
|
int century;
|
||||||
|
int relyear;
|
||||||
|
};
|
||||||
static int _conv_num(const unsigned char **, int *, int, int);
|
static int _conv_num(const unsigned char **, int *, int, int);
|
||||||
static unsigned char *_strptime(const unsigned char *, const char *, struct tm *, int);
|
static unsigned char *_strptime(const unsigned char *, const char *, struct tm *,
|
||||||
|
struct century_relyear *);
|
||||||
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
strptime(const char *buf, const char *fmt, struct tm *tm)
|
strptime(const char *buf, const char *fmt, struct tm *tm)
|
||||||
{
|
{
|
||||||
return (char*)(_strptime((const unsigned char*)buf, fmt, tm, 1));
|
struct century_relyear cr;
|
||||||
|
cr.century = TM_YEAR_BASE;
|
||||||
|
cr.relyear = -1;
|
||||||
|
return (char*)(_strptime((const unsigned char*)buf, fmt, tm, &cr));
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char *
|
static unsigned char *
|
||||||
_strptime(const unsigned char *buf, const char *fmt, struct tm *tm, int initialize)
|
_strptime(const unsigned char *buf, const char *fmt, struct tm *tm, struct century_relyear *cr)
|
||||||
{
|
{
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
const unsigned char *bp;
|
const unsigned char *bp;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
int alt_format, i;
|
int alt_format, i;
|
||||||
static int century, relyear;
|
|
||||||
|
|
||||||
if (initialize) {
|
|
||||||
century = TM_YEAR_BASE;
|
|
||||||
relyear = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bp = (unsigned char *)buf;
|
bp = (unsigned char *)buf;
|
||||||
while ((c = *fmt) != '\0') {
|
while ((c = *fmt) != '\0') {
|
||||||
@ -158,43 +160,43 @@ literal:
|
|||||||
*/
|
*/
|
||||||
case 'c': /* Date and time, using the locale's format. */
|
case 'c': /* Date and time, using the locale's format. */
|
||||||
_LEGAL_ALT(_ALT_E);
|
_LEGAL_ALT(_ALT_E);
|
||||||
if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, 0)))
|
if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'D': /* The date as "%m/%d/%y". */
|
case 'D': /* The date as "%m/%d/%y". */
|
||||||
_LEGAL_ALT(0);
|
_LEGAL_ALT(0);
|
||||||
if (!(bp = _strptime(bp, "%m/%d/%y", tm, 0)))
|
if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'R': /* The time as "%H:%M". */
|
case 'R': /* The time as "%H:%M". */
|
||||||
_LEGAL_ALT(0);
|
_LEGAL_ALT(0);
|
||||||
if (!(bp = _strptime(bp, "%H:%M", tm, 0)))
|
if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r': /* The time as "%I:%M:%S %p". */
|
case 'r': /* The time as "%I:%M:%S %p". */
|
||||||
_LEGAL_ALT(0);
|
_LEGAL_ALT(0);
|
||||||
if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, 0)))
|
if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'T': /* The time as "%H:%M:%S". */
|
case 'T': /* The time as "%H:%M:%S". */
|
||||||
_LEGAL_ALT(0);
|
_LEGAL_ALT(0);
|
||||||
if (!(bp = _strptime(bp, "%H:%M:%S", tm, 0)))
|
if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'X': /* The time, using the locale's format. */
|
case 'X': /* The time, using the locale's format. */
|
||||||
_LEGAL_ALT(_ALT_E);
|
_LEGAL_ALT(_ALT_E);
|
||||||
if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, 0)))
|
if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'x': /* The date, using the locale's format. */
|
case 'x': /* The date, using the locale's format. */
|
||||||
_LEGAL_ALT(_ALT_E);
|
_LEGAL_ALT(_ALT_E);
|
||||||
if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, 0)))
|
if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -253,7 +255,7 @@ literal:
|
|||||||
if (!(_conv_num(&bp, &i, 0, 99)))
|
if (!(_conv_num(&bp, &i, 0, 99)))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
century = i * 100;
|
cr->century = i * 100;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd': /* The day of month. */
|
case 'd': /* The day of month. */
|
||||||
@ -359,13 +361,13 @@ literal:
|
|||||||
if (!(_conv_num(&bp, &i, 0, 9999)))
|
if (!(_conv_num(&bp, &i, 0, 9999)))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
relyear = -1;
|
cr->relyear = -1;
|
||||||
tm->tm_year = i - TM_YEAR_BASE;
|
tm->tm_year = i - TM_YEAR_BASE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'y': /* The year within the century (2 digits). */
|
case 'y': /* The year within the century (2 digits). */
|
||||||
_LEGAL_ALT(_ALT_E | _ALT_O);
|
_LEGAL_ALT(_ALT_E | _ALT_O);
|
||||||
if (!(_conv_num(&bp, &relyear, 0, 99)))
|
if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -391,14 +393,14 @@ literal:
|
|||||||
* We need to evaluate the two digit year spec (%y)
|
* We need to evaluate the two digit year spec (%y)
|
||||||
* last as we can get a century spec (%C) at any time.
|
* last as we can get a century spec (%C) at any time.
|
||||||
*/
|
*/
|
||||||
if (relyear != -1) {
|
if (cr->relyear != -1) {
|
||||||
if (century == TM_YEAR_BASE) {
|
if (cr->century == TM_YEAR_BASE) {
|
||||||
if (relyear <= 68)
|
if (cr->relyear <= 68)
|
||||||
tm->tm_year = relyear + 2000 - TM_YEAR_BASE;
|
tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
|
||||||
else
|
else
|
||||||
tm->tm_year = relyear + 1900 - TM_YEAR_BASE;
|
tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
|
||||||
} else {
|
} else {
|
||||||
tm->tm_year = relyear + century - TM_YEAR_BASE;
|
tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user