diff options
author | Stefano Sabatini | 2011-02-16 08:52:36 +0000 |
---|---|---|
committer | Mans Rullgard | 2011-02-16 23:39:56 +0000 |
commit | f6c7375a175ac649558aefab14f3895b2cb469aa (patch) | |
tree | 759bc4cc9757e5d1d9ab5d0cb661c96862d87737 /libavutil | |
parent | 610219a598095f938705f200dfe3946455ef871a (diff) |
Deprecate parse_date() in favor of av_parse_time().
The new av_parse_time() is created in libavutil/parseutils.h, all the
internal functions used by parse_date are moved to
libavutil/parseutils.c and made static.
Signed-off-by: Mans Rullgard <mans@mansr.com>
Diffstat (limited to 'libavutil')
-rw-r--r-- | libavutil/parseutils.c | 237 | ||||
-rw-r--r-- | libavutil/parseutils.h | 34 |
2 files changed, 271 insertions, 0 deletions
diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c index 09eebcf56f..8e09dade62 100644 --- a/libavutil/parseutils.c +++ b/libavutil/parseutils.c @@ -22,6 +22,8 @@ */ #include <strings.h> +#include <sys/time.h> +#include <time.h> #include "parseutils.h" #include "libavutil/avutil.h" #include "libavutil/eval.h" @@ -371,6 +373,241 @@ int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, return 0; } +/* get a positive number between n_min and n_max, for a maximum length + of len_max. Return -1 if error. */ +static int date_get_num(const char **pp, + int n_min, int n_max, int len_max) +{ + int i, val, c; + const char *p; + + p = *pp; + val = 0; + for(i = 0; i < len_max; i++) { + c = *p; + if (!isdigit(c)) + break; + val = (val * 10) + c - '0'; + p++; + } + /* no number read ? */ + if (p == *pp) + return -1; + if (val < n_min || val > n_max) + return -1; + *pp = p; + return val; +} + +/* small strptime for ffmpeg */ +static +const char *small_strptime(const char *p, const char *fmt, + struct tm *dt) +{ + int c, val; + + for(;;) { + c = *fmt++; + if (c == '\0') { + return p; + } else if (c == '%') { + c = *fmt++; + switch(c) { + case 'H': + val = date_get_num(&p, 0, 23, 2); + if (val == -1) + return NULL; + dt->tm_hour = val; + break; + case 'M': + val = date_get_num(&p, 0, 59, 2); + if (val == -1) + return NULL; + dt->tm_min = val; + break; + case 'S': + val = date_get_num(&p, 0, 59, 2); + if (val == -1) + return NULL; + dt->tm_sec = val; + break; + case 'Y': + val = date_get_num(&p, 0, 9999, 4); + if (val == -1) + return NULL; + dt->tm_year = val - 1900; + break; + case 'm': + val = date_get_num(&p, 1, 12, 2); + if (val == -1) + return NULL; + dt->tm_mon = val - 1; + break; + case 'd': + val = date_get_num(&p, 1, 31, 2); + if (val == -1) + return NULL; + dt->tm_mday = val; + break; + case '%': + goto match; + default: + return NULL; + } + } else { + match: + if (c != *p) + return NULL; + p++; + } + } + return p; +} + +static time_t mktimegm(struct tm *tm) +{ + time_t t; + + int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday; + + if (m < 3) { + m += 12; + y--; + } + + t = 86400 * + (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469); + + t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec; + + return t; +} + +int av_parse_time(int64_t *timeval, const char *datestr, int duration) +{ + const char *p; + int64_t t; + struct tm dt; + int i; + static const char * const date_fmt[] = { + "%Y-%m-%d", + "%Y%m%d", + }; + static const char * const time_fmt[] = { + "%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(datestr); + if (len > 0) + lastch = datestr[len - 1]; + else + lastch = '\0'; + is_utc = (lastch == 'z' || lastch == 'Z'); + + memset(&dt, 0, sizeof(dt)); + + p = datestr; + q = NULL; + if (!duration) { + if (!strncasecmp(datestr, "now", len)) { + *timeval = (int64_t) now * 1000000; + return 0; + } + + /* parse the year-month-day part */ + for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) { + q = small_strptime(p, date_fmt[i], &dt); + if (q) { + break; + } + } + + /* if the year-month-day part is missing, then take the + * current year-month-day time */ + if (!q) { + if (is_utc) { + dt = *gmtime(&now); + } else { + dt = *localtime(&now); + } + dt.tm_hour = dt.tm_min = dt.tm_sec = 0; + } else { + p = q; + } + + if (*p == 'T' || *p == 't' || *p == ' ') + p++; + + /* parse the hour-minute-second part */ + for (i = 0; i < FF_ARRAY_ELEMS(time_fmt); i++) { + q = small_strptime(p, time_fmt[i], &dt); + if (q) { + break; + } + } + } else { + /* parse datestr as a duration */ + if (p[0] == '-') { + negative = 1; + ++p; + } + /* parse datestr as HH:MM:SS */ + q = small_strptime(p, time_fmt[0], &dt); + if (!q) { + /* parse datestr as S+ */ + dt.tm_sec = strtol(p, (char **)&q, 10); + if (q == p) { + /* the parsing didn't succeed */ + *timeval = INT64_MIN; + return AVERROR(EINVAL); + } + dt.tm_min = 0; + dt.tm_hour = 0; + } + } + + /* Now we have all the fields that we can get */ + if (!q) { + *timeval = INT64_MIN; + return AVERROR(EINVAL); + } + + if (duration) { + t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec; + } else { + dt.tm_isdst = -1; /* unknown */ + if (is_utc) { + t = mktimegm(&dt); + } else { + t = mktime(&dt); + } + } + + t *= 1000000; + + /* 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; + return 0; +} + #ifdef TEST #undef printf diff --git a/libavutil/parseutils.h b/libavutil/parseutils.h index 2c99872289..517f125a63 100644 --- a/libavutil/parseutils.h +++ b/libavutil/parseutils.h @@ -72,4 +72,38 @@ int av_parse_video_rate(AVRational *rate, const char *str); int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, void *log_ctx); +/** + * Parses timestr and returns in *time a corresponding number of + * microseconds. + * + * @param timeval puts here the number of microseconds corresponding + * to the string in timestr. If the string represents a duration, it + * is the number of microseconds contained in the time interval. If + * the string is a date, is the number of microseconds since 1st of + * January, 1970 up to the time of the parsed date. If timestr cannot + * be successfully parsed, set *time to INT64_MIN. + + * @param datestr a string representing a date or a duration. + * - If a date the syntax is: + * @code + * [{YYYY-MM-DD|YYYYMMDD}[T|t| ]]{{HH[:MM[:SS[.m...]]]}|{HH[MM[SS[.m...]]]}}[Z] + * now + * @endcode + * If the value is "now" it takes the current time. + * Time is local time unless Z is appended, in which case it is + * interpreted as UTC. + * If the year-month-day part is not specified it takes the current + * year-month-day. + * - If a duration the syntax is: + * @code + * [-]HH[:MM[:SS[.m...]]] + * [-]S+[.m...] + * @endcode + * @param duration flag which tells how to interpret timestr, if not + * zero timestr is interpreted as a duration, otherwise as a date + * @return 0 in case of success, a negative value corresponding to an + * AVERROR code otherwise + */ +int av_parse_time(int64_t *timeval, const char *timestr, int duration); + #endif /* AVUTIL_PARSEUTILS_H */ |