[PATCH] Refactor parse_date for approxidate functions
From: Ramkumar Ramachandra <hidden>
Date: 2016-06-15 22:48:54
Subsystem:
the rest · Maintainer:
Linus Torvalds
approxidate_relative and approxidate_careful both use parse_date to dump the timestamp to a character buffer and parse it back into a long unsigned using strtoul(). Avoid doing this by creating a new parse_date_toffset method. Noticed-by: Jonathan Nieder [off-list ref] Signed-off-by: Ramkumar Ramachandra <redacted> --- date.c | 56 +++++++++++++++++++++++++++++++++++++------------------- 1 files changed, 37 insertions(+), 19 deletions(-)
diff --git a/date.c b/date.c
index 002aa3c..21b4096 100644
--- a/date.c
+++ b/date.c@@ -585,11 +585,17 @@ static int date_string(unsigned long date, int offset, char *buf, int len) /* Gr. strptime is crap for this; it doesn't have a way to require RFC2822 (i.e. English) day/month names, and it doesn't work correctly with %z. */ -int parse_date(const char *date, char *result, int maxlen) +int parse_date_toffset(const char *date, unsigned long *timestamp, int *offset) { struct tm tm; - int offset, tm_gmt; - time_t then; + int tm_gmt; + unsigned long dummy_timestamp; + int dummy_offset; + + if(!timestamp) + timestamp = &dummy_timestamp; + if(!offset) + offset = &dummy_offset; memset(&tm, 0, sizeof(tm)); tm.tm_year = -1;
@@ -599,7 +605,7 @@ int parse_date(const char *date, char *result, int maxlen) tm.tm_hour = -1; tm.tm_min = -1; tm.tm_sec = -1; - offset = -1; + *offset = -1; tm_gmt = 0; for (;;) {
@@ -611,11 +617,11 @@ int parse_date(const char *date, char *result, int maxlen) break; if (isalpha(c)) - match = match_alpha(date, &tm, &offset); + match = match_alpha(date, &tm, offset); else if (isdigit(c)) - match = match_digit(date, &tm, &offset, &tm_gmt); + match = match_digit(date, &tm, offset, &tm_gmt); else if ((c == '-' || c == '+') && isdigit(date[1])) - match = match_tz(date, &offset); + match = match_tz(date, offset); if (!match) { /* BAD CRAP */
@@ -626,16 +632,26 @@ int parse_date(const char *date, char *result, int maxlen) } /* mktime uses local timezone */ - then = tm_to_time_t(&tm); - if (offset == -1) - offset = (then - mktime(&tm)) / 60; + *timestamp = tm_to_time_t(&tm); + if (*offset == -1) + *offset = (*timestamp - mktime(&tm)) / 60; - if (then == -1) + if (*timestamp == -1) return -1; if (!tm_gmt) - then -= offset * 60; - return date_string(then, offset, result, maxlen); + *timestamp -= *offset * 60; + return 1; /* success */ +} + +int parse_date(const char *date, char *result, int maxlen) +{ + unsigned long timestamp; + int offset; + if(parse_date_toffset(date, ×tamp, &offset) > 0) + return date_string(timestamp, offset, result, maxlen); + else + return -1; } enum date_mode parse_date_format(const char *format)
@@ -983,11 +999,12 @@ static unsigned long approxidate_str(const char *date, unsigned long approxidate_relative(const char *date, const struct timeval *tv) { - char buffer[50]; + unsigned long timestamp; + int offset; int errors = 0; - if (parse_date(date, buffer, sizeof(buffer)) > 0) - return strtoul(buffer, NULL, 0); + if(parse_date_toffset(date, ×tamp, &offset) > 0) + return timestamp; return approxidate_str(date, tv, &errors); }
@@ -995,14 +1012,15 @@ unsigned long approxidate_relative(const char *date, const struct timeval *tv) unsigned long approxidate_careful(const char *date, int *error_ret) { struct timeval tv; - char buffer[50]; + unsigned long timestamp; + int offset; int dummy = 0; if (!error_ret) error_ret = &dummy; - if (parse_date(date, buffer, sizeof(buffer)) > 0) { + if(parse_date_toffset(date, ×tamp, &offset) > 0) { *error_ret = 0; - return strtoul(buffer, NULL, 0); + return timestamp; } gettimeofday(&tv, NULL);
--
1.7.1