summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Murchison <murch@fastmail.com>2021-03-23 10:36:57 -0400
committerKen Murchison <murch@fastmail.com>2021-03-23 10:36:57 -0400
commite976e4bcca85d37ade3279428476e0b7d1f28fa2 (patch)
tree7797dc27ce16676cf6edb1c7d41d4e483a417d30
parent98761e2709de98d16f229dbeed05f119c61f0a6e (diff)
downloadlibical-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.c104
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 =