summaryrefslogtreecommitdiff
path: root/libavutil/parseutils.c
diff options
context:
space:
mode:
authorStefano Sabatini <stefano.sabatini-lala@poste.it>2011-02-16 08:52:36 +0000
committerMans Rullgard <mans@mansr.com>2011-02-16 23:39:56 +0000
commitf6c7375a175ac649558aefab14f3895b2cb469aa (patch)
tree759bc4cc9757e5d1d9ab5d0cb661c96862d87737 /libavutil/parseutils.c
parent610219a598095f938705f200dfe3946455ef871a (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/parseutils.c')
-rw-r--r--libavutil/parseutils.c237
1 files changed, 237 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