diff options
author | Ken Murchison <murch@fastmail.com> | 2021-03-23 10:36:57 -0400 |
---|---|---|
committer | Ken Murchison <murch@fastmail.com> | 2021-03-23 10:36:57 -0400 |
commit | e976e4bcca85d37ade3279428476e0b7d1f28fa2 (patch) | |
tree | 7797dc27ce16676cf6edb1c7d41d4e483a417d30 | |
parent | 98761e2709de98d16f229dbeed05f119c61f0a6e (diff) | |
download | libical-git-e976e4bcca85d37ade3279428476e0b7d1f28fa2.tar.gz |
icalrecur.c: order BY* parts per the processing order in Section 3.3.10 or RFC 5545; also iterate through the BY* parts in a more sane and extensible manner
-rw-r--r-- | src/libical/icalrecur.c | 104 |
1 files changed, 53 insertions, 51 deletions
diff --git a/src/libical/icalrecur.c b/src/libical/icalrecur.c index 43edfad3..c1311020 100644 --- a/src/libical/icalrecur.c +++ b/src/libical/icalrecur.c @@ -333,23 +333,25 @@ struct icalrecur_parser enum byrule { NO_CONTRACTION = -1, - BY_SECOND = 0, - BY_MINUTE = 1, - BY_HOUR = 2, - BY_DAY = 3, - BY_MONTH_DAY = 4, - BY_YEAR_DAY = 5, - BY_WEEK_NO = 6, - BY_MONTH = 7, - BY_SET_POS + BY_MONTH = 0, + BY_WEEK_NO = 1, + BY_YEAR_DAY = 2, + BY_MONTH_DAY = 3, + BY_DAY = 4, + BY_HOUR = 5, + BY_MINUTE = 6, + BY_SECOND = 7, + BY_SET_POS = 8 }; +#define NUM_BY_PARTS 9 + enum expand_table { - UNKNOWN = 0, + UNKNOWN = 0, CONTRACT = 1, - EXPAND = 2, - ILLEGAL = 3 + EXPAND = 2, + ILLEGAL = 3 }; struct expand_split_map_struct @@ -359,7 +361,7 @@ struct expand_split_map_struct /* Elements of the 'map' array correspond to the BYxxx rules: Second,Minute,Hour,Day,Month Day,Year Day,Week No,Month,SetPos */ - short map[BY_SET_POS+1]; + short map[NUM_BY_PARTS]; }; /** @@ -370,13 +372,13 @@ struct expand_split_map_struct */ static const struct expand_split_map_struct expand_map[] = { - /* s m h D MD YD W M P */ - {ICAL_SECONDLY_RECURRENCE, { 1, 1, 1, 1, 1, 1, 3, 1, 1 }}, - {ICAL_MINUTELY_RECURRENCE, { 2, 1, 1, 1, 1, 1, 3, 1, 1 }}, - {ICAL_HOURLY_RECURRENCE, { 2, 2, 1, 1, 1, 1, 3, 1, 1 }}, - {ICAL_DAILY_RECURRENCE, { 2, 2, 2, 1, 1, 3, 3, 1, 1 }}, - {ICAL_WEEKLY_RECURRENCE, { 2, 2, 2, 2, 3, 3, 3, 1, 1 }}, - {ICAL_MONTHLY_RECURRENCE, { 2, 2, 2, 2, 2, 3, 3, 1, 1 }}, + /* M W YD MD D h m s P */ + {ICAL_SECONDLY_RECURRENCE, { 1, 3, 1, 1, 1, 1, 1, 1, 1 }}, + {ICAL_MINUTELY_RECURRENCE, { 1, 3, 1, 1, 1, 1, 1, 2, 1 }}, + {ICAL_HOURLY_RECURRENCE, { 1, 3, 1, 1, 1, 1, 2, 2, 1 }}, + {ICAL_DAILY_RECURRENCE, { 1, 3, 3, 1, 1, 2, 2, 2, 1 }}, + {ICAL_WEEKLY_RECURRENCE, { 1, 3, 3, 3, 2, 2, 2, 2, 1 }}, + {ICAL_MONTHLY_RECURRENCE, { 1, 3, 3, 2, 2, 2, 2, 2, 1 }}, {ICAL_YEARLY_RECURRENCE, { 2, 2, 2, 2, 2, 2, 2, 2, 1 }}, {ICAL_NO_RECURRENCE, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }} //krazy:exclude=style }; @@ -388,22 +390,22 @@ static struct recur_map int size; int min; } recur_map[] = { - { "BYSECOND", offsetof(struct icalrecurrencetype, by_second), - ICAL_BY_SECOND_SIZE, 0 }, - { "BYMINUTE", offsetof(struct icalrecurrencetype, by_minute), - ICAL_BY_MINUTE_SIZE, 0 }, - { "BYHOUR", offsetof(struct icalrecurrencetype, by_hour), - ICAL_BY_HOUR_SIZE, 0 }, - { "BYDAY", offsetof(struct icalrecurrencetype, by_day), - ICAL_BY_DAY_SIZE, 0 }, - { "BYMONTHDAY", offsetof(struct icalrecurrencetype, by_month_day), - ICAL_BY_MONTHDAY_SIZE, -1 }, - { "BYYEARDAY", offsetof(struct icalrecurrencetype, by_year_day), - ICAL_BY_YEARDAY_SIZE, -1 }, - { "BYWEEKNO", offsetof(struct icalrecurrencetype, by_week_no), - ICAL_BY_WEEKNO_SIZE, -1 }, { "BYMONTH", offsetof(struct icalrecurrencetype, by_month), ICAL_BY_MONTH_SIZE, 1 }, + { "BYWEEKNO", offsetof(struct icalrecurrencetype, by_week_no), + ICAL_BY_WEEKNO_SIZE, -1 }, + { "BYYEARDAY", offsetof(struct icalrecurrencetype, by_year_day), + ICAL_BY_YEARDAY_SIZE, -1 }, + { "BYMONTHDAY", offsetof(struct icalrecurrencetype, by_month_day), + ICAL_BY_MONTHDAY_SIZE, -1 }, + { "BYDAY", offsetof(struct icalrecurrencetype, by_day), + ICAL_BY_DAY_SIZE, 0 }, + { "BYHOUR", offsetof(struct icalrecurrencetype, by_hour), + ICAL_BY_HOUR_SIZE, 0 }, + { "BYMINUTE", offsetof(struct icalrecurrencetype, by_minute), + ICAL_BY_MINUTE_SIZE, 0 }, + { "BYSECOND", offsetof(struct icalrecurrencetype, by_second), + ICAL_BY_SECOND_SIZE, 0 }, { "BYSETPOS", offsetof(struct icalrecurrencetype, by_set_pos), ICAL_BY_SETPOS_SIZE, -1 }, }; @@ -745,7 +747,7 @@ struct icalrecurrencetype icalrecurrencetype_from_string(const char *str) } else if (strncasecmp(name, "BY", 2) == 0) { r = -1; - for (byrule = BY_SECOND; byrule <= BY_SET_POS; byrule++) { + for (byrule = 0; byrule < NUM_BY_PARTS; byrule++) { if (strcasecmp(name+2, recur_map[byrule].str+2) == 0) { if (byrule == BY_DAY) { r = icalrecur_add_bydayrules(&parser, value); @@ -778,7 +780,7 @@ struct icalrecurrencetype icalrecurrencetype_from_string(const char *str) } } - for (byrule = BY_SECOND; byrule <= BY_SET_POS; byrule++) { + for (byrule = 0; byrule < NUM_BY_PARTS; byrule++) { short *array = (short *)(recur_map[byrule].offset + (size_t) &parser.rt); if (array[0] != ICAL_RECURRENCE_ARRAY_MAX && @@ -832,6 +834,7 @@ char *icalrecurrencetype_as_string_r(struct icalrecurrencetype *recur) icalmemory_append_string(&str, &str_p, &buf_sz, "RSCALE="); icalmemory_append_string(&str, &str_p, &buf_sz, recur->rscale); + /* Omit is the default, so no need to write that out */ if (recur->skip != ICAL_SKIP_OMIT) { const char *skipstr = icalrecur_skip_to_string(recur->skip); icalmemory_append_string(&str, &str_p, &buf_sz, ";SKIP="); @@ -844,6 +847,13 @@ char *icalrecurrencetype_as_string_r(struct icalrecurrencetype *recur) icalmemory_append_string(&str, &str_p, &buf_sz, icalrecur_freq_to_string(recur->freq)); + /* 1 is the default, so no need to write that out */ + if (recur->interval != 1) { + snprintf(temp, sizeof(temp), "%d", recur->interval); + icalmemory_append_string(&str, &str_p, &buf_sz, ";INTERVAL="); + icalmemory_append_string(&str, &str_p, &buf_sz, temp); + } + /* Monday is the default, so no need to write that out */ if (recur->week_start != ICAL_MONDAY_WEEKDAY && recur->week_start != ICAL_NO_WEEKDAY) { @@ -853,7 +863,7 @@ char *icalrecurrencetype_as_string_r(struct icalrecurrencetype *recur) icalmemory_append_string(&str, &str_p, &buf_sz, daystr); } - for (j = BY_SET_POS; j >= BY_SECOND; j--) { + for (j = 0; j < NUM_BY_PARTS; j++) { short *array = (short *)(recur_map[j].offset + (size_t) recur); int limit = recur_map[j].size - 1; @@ -864,8 +874,7 @@ char *icalrecurrencetype_as_string_r(struct icalrecurrencetype *recur) icalmemory_append_string(&str, &str_p, &buf_sz, recur_map[j].str); icalmemory_append_char(&str, &str_p, &buf_sz, '='); - for (i = 0; - i < limit && array[i] != ICAL_RECURRENCE_ARRAY_MAX; i++) { + for (i = 0; i < limit && array[i] != ICAL_RECURRENCE_ARRAY_MAX; i++) { if (j == BY_DAY) { int pos = icalrecurrencetype_day_position(array[i]); int dow = icalrecurrencetype_day_day_of_week(array[i]); @@ -896,14 +905,7 @@ char *icalrecurrencetype_as_string_r(struct icalrecurrencetype *recur) } } - if (recur->interval != 1) { - snprintf(temp, sizeof(temp), "%d", recur->interval); - icalmemory_append_string(&str, &str_p, &buf_sz, ";INTERVAL="); - icalmemory_append_string(&str, &str_p, &buf_sz, temp); - } - if (recur->until.year != 0) { - temp[0] = 0; if (recur->until.is_date) { print_date_to_string(temp, &(recur->until)); @@ -969,10 +971,10 @@ struct icalrecur_iterator_impl short days_index; enum byrule byrule; - short by_indices[9]; - short orig_data[9]; /**< 1 if there was data in the byrule */ + short by_indices[NUM_BY_PARTS]; + short orig_data[NUM_BY_PARTS]; /**< 1 if there was data in the byrule */ - short *by_ptrs[9]; /**< Pointers into the by_* array elements of the rule */ + short *by_ptrs[NUM_BY_PARTS]; /**< Pointers into the by_* array elements of the rule */ }; @@ -1953,7 +1955,7 @@ icalrecur_iterator *icalrecur_iterator_new(struct icalrecurrencetype rule, impl->by_ptrs[BY_SECOND] = impl->rule.by_second; impl->by_ptrs[BY_SET_POS] = impl->rule.by_set_pos; - memset(impl->orig_data, 0, 9 * sizeof(short)); + memset(impl->orig_data, 0, NUM_BY_PARTS * sizeof(short)); /* Note which by rules had data in them when the iterator was created. We can't use the actual by_x arrays, because the @@ -1981,7 +1983,7 @@ icalrecur_iterator *icalrecur_iterator_new(struct icalrecurrencetype rule, /* Check if the recurrence rule is legal */ - for (byrule = BY_SECOND; byrule <= BY_SET_POS; byrule++) { + for (byrule = 0; byrule < NUM_BY_PARTS; byrule++) { if (expand_map[freq].map[byrule] == ILLEGAL && has_by_data(impl, byrule)) { ical_invalid_rrule_handling rruleHandlingSetting = |