Minor merge adjustments

Comments inserted.

Slightly different implementations of parse_time() and parse_datetime().

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
This commit is contained in:
Lars Henriksen 2018-06-02 21:53:39 +02:00 committed by Lukas Fleischer
parent 0543df5f31
commit 7f448ee8cd

View File

@ -938,6 +938,13 @@ parse_date_interactive(const char *datestr, int *year, int *month, int *day)
* Convert a date duration string into a number of days. * Convert a date duration string into a number of days.
* If start is non-zero, the final end time is validated. * If start is non-zero, the final end time is validated.
* *
* Allowed formats in lenient BNF:
* <duration> ::= <days> | <period>
* <period> ::= [ <weeks>w ][ <days>d ]
* Notes:
* <days> and <weeks> are any integer >= 0.
* <period> must have at least one non-terminal.
*
* Returns 1 on success and 0 on failure. * Returns 1 on success and 0 on failure.
*/ */
int parse_date_duration(const char *string, unsigned *days, time_t start) int parse_date_duration(const char *string, unsigned *days, time_t start)
@ -996,10 +1003,8 @@ int parse_date_duration(const char *string, unsigned *days, time_t start)
denom = 1; denom = 1;
} }
} }
if (state == STATE_DONE && in > 0) if (state == STATE_DONE && in > 0)
return 0; return 0;
dur += in; dur += in;
if (start) { if (start) {
/* wanted: start = start + dur * DAYINSEC */ /* wanted: start = start + dur * DAYINSEC */
@ -1013,7 +1018,6 @@ int parse_date_duration(const char *string, unsigned *days, time_t start)
return 0; return 0;
} }
*days = dur; *days = dur;
return 1; return 1;
} }
@ -1027,7 +1031,9 @@ int check_time(unsigned hours, unsigned minutes)
/* /*
* Converts a time string into hours and minutes. Short forms like "23:" * Converts a time string into hours and minutes. Short forms like "23:"
* (23:00) or ":45" (0:45) are allowed. * (23:00) or ":45" (0:45) are allowed as well as "2345". Note: the latter
* clashes with date formats 0001 .. 0031 and must be picked up before
* dates when parsing in parse_datetime.
* *
* Returns 1 on success and 0 on failure. * Returns 1 on success and 0 on failure.
*/ */
@ -1044,14 +1050,18 @@ int parse_time(const char *string, unsigned *hour, unsigned *minute)
if (*p == ':') { if (*p == ':') {
if ((++n) > 1) if ((++n) > 1)
return 0; return 0;
} else if ((*p >= '0') && (*p <= '9')) { } else if (isdigit(*p)) {
if ((n == 0) && (p == (string + 2)) && *(p + 1)) in[n] = in[n] * 10 + *p - '0';
n++;
in[n] = in[n] * 10 + (int)(*p - '0');
} else { } else {
return 0; return 0;
} }
} }
/* 24-hour format without ':' (hhmm)? */
if (n == 0 && strlen(string) == 4) {
in[1] = in[0] % 100;
in[0] = in[0] / 100;
n = 1;
}
if (n != 1 || !check_time(in[0], in[1])) if (n != 1 || !check_time(in[0], in[1]))
return 0; return 0;
@ -1065,13 +1075,15 @@ int parse_time(const char *string, unsigned *hour, unsigned *minute)
* Converts a duration string into minutes. * Converts a duration string into minutes.
* If start time is non-zero, the final end time is validated. * If start time is non-zero, the final end time is validated.
* *
* Allowed formats (noted as regular expressions): * Allowed formats in lenient BNF:
* * <duration> ::= <minutes> | <time> | <period>
* - \d*:\d* * <time> ::= <hours>:<min>
* - (\d*m|\d*h(|\d*m)|\d*d(|\d*m|\d*h(|\d*m))) * <period> ::= [ <days>d ][ <hours>h ][ <minutes>m ]
* - \d+ * <min> ::= integer in the range 0-59
* * Notes:
* "\d" is used as a placeholder for "(0|1|2|3|4|5|6|7|8|9)". * <days>, <hours> and <minutes> are any sequence of
* the characters 1,2,..,9,0.
* <period> must have at least one non-terminal.
* *
* Returns 1 on success and 0 on failure. * Returns 1 on success and 0 on failure.
*/ */
@ -1144,7 +1156,6 @@ int parse_duration(const char *string, unsigned *duration, time_t start)
break; break;
case STATE_HHMM_MM: case STATE_HHMM_MM:
return 0; return 0;
break;
default: default:
break; break;
} }
@ -1154,8 +1165,7 @@ int parse_duration(const char *string, unsigned *duration, time_t start)
} }
} }
if ((state == STATE_HHMM_MM && in >= HOURINMIN) || if ((state == STATE_HHMM_MM && in >= HOURINMIN) ||
((state == STATE_DDHHMM_HH || state == STATE_DDHHMM_MM) ((state == STATE_DDHHMM_HH || state == STATE_DDHHMM_MM) && in > 0))
&& in > 0))
return 0; return 0;
dur += in; dur += in;
if (start) { if (start) {
@ -1171,7 +1181,6 @@ int parse_duration(const char *string, unsigned *duration, time_t start)
return 0; return 0;
} }
*duration = dur; *duration = dur;
return 1; return 1;
} }
@ -1192,37 +1201,35 @@ int parse_duration(const char *string, unsigned *duration, time_t start)
*/ */
int parse_datetime(const char *string, time_t *ts, time_t dur) int parse_datetime(const char *string, time_t *ts, time_t dur)
{ {
char *t = mem_strdup(string); unsigned hour, minute;
char *p = strchr(t, ' ');
unsigned int hour, minute;
int year, month, day; int year, month, day;
struct date new_date;
int ret = 0; int ret = 0;
if (p) { char *d = mem_strdup(string);
*p = '\0'; /* Split into date and time, if possible. */
if (parse_date_interactive(t, &year, &month, &day) && char *t = strchr(d, ' ');
parse_time(p + 1, &hour, &minute)) { if (t)
*t++ = '\0';
if (t) {
if (parse_date_interactive(d, &year, &month, &day) &&
parse_time(t, &hour, &minute)) {
ret |= PARSE_DATETIME_HAS_DATE | ret |= PARSE_DATETIME_HAS_DATE |
PARSE_DATETIME_HAS_TIME; PARSE_DATETIME_HAS_TIME;
} }
} else if (parse_time(t, &hour, &minute)) { /* Time before date, see comments in parse_time(). */
} else if (parse_time(d, &hour, &minute)) {
ret |= PARSE_DATETIME_HAS_TIME; ret |= PARSE_DATETIME_HAS_TIME;
} else if (parse_date_interactive(t, &year, &month, &day)) { } else if (parse_date_interactive(d, &year, &month, &day)) {
ret |= PARSE_DATETIME_HAS_DATE; ret |= PARSE_DATETIME_HAS_DATE;
} }
if (ret & PARSE_DATETIME_HAS_DATE) { if (ret & PARSE_DATETIME_HAS_DATE) {
new_date.dd = day; struct date date = { day , month, year };
new_date.mm = month; *ts = date2sec(date, 0, 0) + get_item_time(*ts);
new_date.yyyy = year;
*ts = date2sec(new_date, 0, 0) + get_item_time(*ts);
} }
if (ret & PARSE_DATETIME_HAS_TIME) if (ret & PARSE_DATETIME_HAS_TIME)
*ts = update_time_in_date(*ts, hour, minute); *ts = update_time_in_date(*ts, hour, minute);
mem_free(d);
mem_free(t);
/* Is the resulting time a valid (start or end) time? */ /* Is the resulting time a valid (start or end) time? */
if (!check_sec(ts)) if (!check_sec(ts))
return 0; return 0;