bool calendar_spec_valid(CalendarSpec *c) { assert(c); if (c->weekdays_bits > 127) return false; if (!chain_valid(c->year, 1970, 2199)) return false; if (!chain_valid(c->month, 1, 12)) return false; if (!chain_valid(c->day, 1, 31)) return false; if (!chain_valid(c->hour, 0, 23)) return false; if (!chain_valid(c->minute, 0, 59)) return false; if (!chain_valid(c->second, 0, 59)) return false; return true; }
_pure_ bool calendar_spec_valid(CalendarSpec *c) { assert(c); if (c->weekdays_bits > BITS_WEEKDAYS) return false; if (!chain_valid(c->year, MIN_YEAR, MAX_YEAR, false)) return false; if (!chain_valid(c->month, 1, 12, false)) return false; if (!chain_valid(c->day, 1, 31, c->end_of_month)) return false; if (!chain_valid(c->hour, 0, 23, false)) return false; if (!chain_valid(c->minute, 0, 59, false)) return false; if (!chain_valid(c->microsecond, 0, 60*USEC_PER_SEC-1, false)) return false; return true; }
_pure_ bool calendar_spec_valid(CalendarSpec *c) { assert(c); if (c->weekdays_bits > BITS_WEEKDAYS) return false; if (!chain_valid(c->year, 1970, 2199)) return false; if (!chain_valid(c->month, 1, 12)) return false; if (!chain_valid(c->day, 1, 31)) return false; if (!chain_valid(c->hour, 0, 23)) return false; if (!chain_valid(c->minute, 0, 59)) return false; if (!chain_valid(c->microsecond, 0, 60*USEC_PER_SEC-1)) return false; return true; }
static bool chain_valid(CalendarComponent *c, int from, int to) { if (!c) return true; if (c->value < from || c->value > to) return false; if (c->value + c->repeat > to) return false; if (c->next) return chain_valid(c->next, from, to); return true; }
_pure_ static bool chain_valid(CalendarComponent *c, int from, int to, bool end_of_month) { assert(to >= from); if (!c) return true; /* Forbid dates more than 28 days from the end of the month */ if (end_of_month) to -= 3; if (c->start < from || c->start > to) return false; /* Avoid overly large values that could cause overflow */ if (c->repeat > to - from) return false; /* * c->repeat must be short enough so at least one repetition may * occur before the end of the interval. For dates scheduled * relative to the end of the month, c->start and c->stop * correspond to the Nth last day of the month. */ if (c->stop >= 0) { if (c->stop < from || c ->stop > to) return false; if (c->start + c->repeat > c->stop) return false; } else { if (end_of_month && c->start - c->repeat < from) return false; if (!end_of_month && c->start + c->repeat > to) return false; } if (c->next) return chain_valid(c->next, from, to, end_of_month); return true; }