parseutils: make av_parse_time() check for failure.
Until now, av_parse_time() would accept "1:00" as "1" and silently ignore ":00". This patch also includes a few cosmetic changes.
This commit is contained in:
parent
9246896f77
commit
43b7068070
1 changed files with 39 additions and 51 deletions
|
@ -522,9 +522,11 @@ time_t av_timegm(struct tm *tm)
|
||||||
|
|
||||||
int av_parse_time(int64_t *timeval, const char *timestr, int duration)
|
int av_parse_time(int64_t *timeval, const char *timestr, int duration)
|
||||||
{
|
{
|
||||||
const char *p;
|
const char *p, *q;
|
||||||
int64_t t;
|
int64_t t;
|
||||||
|
time_t now;
|
||||||
struct tm dt = { 0 };
|
struct tm dt = { 0 };
|
||||||
|
int today = 0, negative = 0, microseconds = 0;
|
||||||
int i;
|
int i;
|
||||||
static const char * const date_fmt[] = {
|
static const char * const date_fmt[] = {
|
||||||
"%Y-%m-%d",
|
"%Y-%m-%d",
|
||||||
|
@ -534,25 +536,15 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration)
|
||||||
"%H:%M:%S",
|
"%H:%M:%S",
|
||||||
"%H%M%S",
|
"%H%M%S",
|
||||||
};
|
};
|
||||||
const char *q;
|
|
||||||
int is_utc, len;
|
|
||||||
char lastch;
|
|
||||||
int negative = 0;
|
|
||||||
|
|
||||||
#undef time
|
|
||||||
time_t now = time(0);
|
|
||||||
|
|
||||||
len = strlen(timestr);
|
|
||||||
if (len > 0)
|
|
||||||
lastch = timestr[len - 1];
|
|
||||||
else
|
|
||||||
lastch = '\0';
|
|
||||||
is_utc = (lastch == 'z' || lastch == 'Z');
|
|
||||||
|
|
||||||
p = timestr;
|
p = timestr;
|
||||||
q = NULL;
|
q = NULL;
|
||||||
|
*timeval = INT64_MIN;
|
||||||
if (!duration) {
|
if (!duration) {
|
||||||
if (!av_strncasecmp(timestr, "now", len)) {
|
#undef time
|
||||||
|
now = time(0);
|
||||||
|
|
||||||
|
if (!av_strcasecmp(timestr, "now")) {
|
||||||
*timeval = (int64_t) now * 1000000;
|
*timeval = (int64_t) now * 1000000;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -560,23 +552,17 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration)
|
||||||
/* parse the year-month-day part */
|
/* parse the year-month-day part */
|
||||||
for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) {
|
for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) {
|
||||||
q = small_strptime(p, date_fmt[i], &dt);
|
q = small_strptime(p, date_fmt[i], &dt);
|
||||||
if (q) {
|
if (q)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* if the year-month-day part is missing, then take the
|
/* if the year-month-day part is missing, then take the
|
||||||
* current year-month-day time */
|
* current year-month-day time */
|
||||||
if (!q) {
|
if (!q) {
|
||||||
if (is_utc) {
|
today = 1;
|
||||||
dt = *gmtime(&now);
|
q = p;
|
||||||
} else {
|
|
||||||
dt = *localtime(&now);
|
|
||||||
}
|
}
|
||||||
dt.tm_hour = dt.tm_min = dt.tm_sec = 0;
|
|
||||||
} else {
|
|
||||||
p = q;
|
p = q;
|
||||||
}
|
|
||||||
|
|
||||||
if (*p == 'T' || *p == 't' || *p == ' ')
|
if (*p == 'T' || *p == 't' || *p == ' ')
|
||||||
p++;
|
p++;
|
||||||
|
@ -584,10 +570,9 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration)
|
||||||
/* parse the hour-minute-second part */
|
/* parse the hour-minute-second part */
|
||||||
for (i = 0; i < FF_ARRAY_ELEMS(time_fmt); i++) {
|
for (i = 0; i < FF_ARRAY_ELEMS(time_fmt); i++) {
|
||||||
q = small_strptime(p, time_fmt[i], &dt);
|
q = small_strptime(p, time_fmt[i], &dt);
|
||||||
if (q) {
|
if (q)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* parse timestr as a duration */
|
/* parse timestr as a duration */
|
||||||
if (p[0] == '-') {
|
if (p[0] == '-') {
|
||||||
|
@ -599,46 +584,49 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration)
|
||||||
if (!q) {
|
if (!q) {
|
||||||
/* parse timestr as S+ */
|
/* parse timestr as S+ */
|
||||||
dt.tm_sec = strtol(p, (void *)&q, 10);
|
dt.tm_sec = strtol(p, (void *)&q, 10);
|
||||||
if (q == p) {
|
if (q == p) /* the parsing didn't succeed */
|
||||||
/* the parsing didn't succeed */
|
|
||||||
*timeval = INT64_MIN;
|
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
}
|
|
||||||
dt.tm_min = 0;
|
dt.tm_min = 0;
|
||||||
dt.tm_hour = 0;
|
dt.tm_hour = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now we have all the fields that we can get */
|
/* Now we have all the fields that we can get */
|
||||||
if (!q) {
|
if (!q)
|
||||||
*timeval = INT64_MIN;
|
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
|
|
||||||
|
/* parse the .m... part */
|
||||||
|
if (*q == '.') {
|
||||||
|
int n;
|
||||||
|
q++;
|
||||||
|
for (n = 100000; n >= 1; n /= 10, q++) {
|
||||||
|
if (!isdigit(*q))
|
||||||
|
break;
|
||||||
|
microseconds += n * (*q - '0');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (duration) {
|
if (duration) {
|
||||||
t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
|
t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
|
||||||
} else {
|
} else {
|
||||||
dt.tm_isdst = -1; /* unknown */
|
int is_utc = *q == 'Z' || *q == 'z';
|
||||||
if (is_utc) {
|
q += is_utc;
|
||||||
t = av_timegm(&dt);
|
if (today) { /* fill in today's date */
|
||||||
} else {
|
struct tm dt2 = is_utc ? *gmtime(&now) : *localtime(&now);
|
||||||
t = mktime(&dt);
|
dt2.tm_hour = dt.tm_hour;
|
||||||
|
dt2.tm_min = dt.tm_min;
|
||||||
|
dt2.tm_sec = dt.tm_sec;
|
||||||
|
dt = dt2;
|
||||||
}
|
}
|
||||||
|
t = is_utc ? av_timegm(&dt) : mktime(&dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check that we are at the end of the string */
|
||||||
|
if (*q)
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
|
||||||
t *= 1000000;
|
t *= 1000000;
|
||||||
|
t += microseconds;
|
||||||
/* parse the .m... part */
|
|
||||||
if (*q == '.') {
|
|
||||||
int val, n;
|
|
||||||
q++;
|
|
||||||
for (val = 0, n = 100000; n >= 1; n /= 10, q++) {
|
|
||||||
if (!isdigit(*q))
|
|
||||||
break;
|
|
||||||
val += n * (*q - '0');
|
|
||||||
}
|
|
||||||
t += val;
|
|
||||||
}
|
|
||||||
*timeval = negative ? -t : t;
|
*timeval = negative ? -t : t;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue