Libical API Documentation 4.0 UNRELEASED Go to the stable 3.0 documentation
Loading...
Searching...
No Matches
icalrecur.c File Reference

Implementation of routines for dealing with recurring time. More...

Go to the source code of this file.

Functions

ical_invalid_rrule_handling ical_get_invalid_rrule_handling_setting (void)
void ical_set_invalid_rrule_handling_setting (ical_invalid_rrule_handling newSetting)
bool icalrecur_expand_recurrence (const char *rule, icaltime_t start, int count, icaltime_t *array)
const char * icalrecur_freq_to_string (icalrecurrencetype_frequency kind)
void icalrecur_iterator_free (icalrecur_iterator *impl)
icalrecur_iterator * icalrecur_iterator_new (struct icalrecurrencetype *rule, struct icaltimetype dtstart)
struct icaltimetype icalrecur_iterator_next (icalrecur_iterator *impl)
struct icaltimetype icalrecur_iterator_prev (icalrecur_iterator *impl)
bool icalrecur_iterator_set_end (icalrecur_iterator *impl, struct icaltimetype end)
bool icalrecur_iterator_set_range (icalrecur_iterator *impl, struct icaltimetype from, struct icaltimetype to)
bool icalrecur_iterator_set_start (icalrecur_iterator *impl, struct icaltimetype start)
bool icalrecur_resize_by (icalrecurrence_by_data *by, short size)
const char * icalrecur_skip_to_string (icalrecurrencetype_skip kind)
icalrecurrencetype_frequency icalrecur_string_to_freq (const char *str)
icalrecurrencetype_skip icalrecur_string_to_skip (const char *str)
icalrecurrencetype_weekday icalrecur_string_to_weekday (const char *str)
const char * icalrecur_weekday_to_string (icalrecurrencetype_weekday kind)
char * icalrecurrencetype_as_string (struct icalrecurrencetype *recur)
char * icalrecurrencetype_as_string_r (struct icalrecurrencetype *recur)
struct icalrecurrencetypeicalrecurrencetype_clone (struct icalrecurrencetype *recur)
enum icalrecurrencetype_weekday icalrecurrencetype_day_day_of_week (short day)
int icalrecurrencetype_day_position (short day)
short icalrecurrencetype_encode_day (enum icalrecurrencetype_weekday weekday, int position)
short icalrecurrencetype_encode_month (int month, bool is_leap)
bool icalrecurrencetype_month_is_leap (short month)
int icalrecurrencetype_month_month (short month)
struct icalrecurrencetypeicalrecurrencetype_new (void)
struct icalrecurrencetypeicalrecurrencetype_new_from_string (const char *str)
void icalrecurrencetype_ref (struct icalrecurrencetype *recur)
icalarray * icalrecurrencetype_rscale_supported_calendars (void)
void icalrecurrencetype_unref (struct icalrecurrencetype *recur)

Detailed Description

Implementation of routines for dealing with recurring time.

How this code works:

Processing starts when the caller generates a new recurrence iterator via icalrecur_iterator_new(). This routine stores a reference to the recurrence rule and extracts things like start and end dates. Then, it checks if the rule is legal, using some logic from RFC5545 and some logic that probably should be in RFC5545.

If compiled with support for Non-Gregorian Recurrence Rules (RFC7529), icalrecur_iterator_new() verifies that the given RSCALE is supported and configures ICU4C to convert occurrences to/from non-Gregorian dates.

Then, icalrecur_iterator_new() re-writes some of the BY* arrays (this happens within the iterator, the rule itself is treated immutable). This involves ( via a call to setup_defaults() ) :

1) For BY rule parts with no data ( ie BYSECOND was not specified ) set up the corresponding time part from DTSTART in the corresponding impl->bydata. So impl->bydata[ICAL_BY_SECOND].by will then have one element if it originally had none ). This only happens if the BY* rule part data would expand the number of occurrences in the occurrence set. This lets the code ignore DTSTART later on and still use it to get the time parts that were not specified in any other way.

2) For the by rule part that are not the same interval as the frequency – for HOURLY anything but BYHOUR, for instance – copy the first data element from the rule part into the first occurrence. For example, for "INTERVAL=MONTHLY and BYHOUR=10,30", initialize the first time to be returned to have an hour of 10.

Finally, for INTERVAL=YEARLY, the routine expands the rule to get all of the days specified in the rule. The code will do this for each new year, and this is the first expansion. This is a special case for the yearly interval; no other frequency gets expanded this way. The yearly interval is the most complex, so some special processing is required.

After creating a new iterator, the caller will make successive calls to icalrecur_iterator_next() to get the next time specified by the rule. The main part of this routine is a switch on the frequency of the rule. Each different frequency is handled by a different routine.

For example, next_hour handles the case of INTERVAL=HOURLY, and it is called by other routines to get the next hour. First, the routine tries to get the next minute part of a time with a call to next_minute(). If next_minute() returns 1, it has reached the end of its data, usually the last element of the BYMINUTE array. Then, if there is data in the BYHOUR array, the routine changes the hour to the next one in the array. If INTERVAL=HOURLY, the routine advances the hour by the interval.

If the routine used the last hour in the BYHOUR array, and the INTERVAL=HOURLY, then the routine calls increment_monthday() to set the next month day. The increment_* routines may call higher routine to increment the month or year also.

The code for INTERVAL=DAILY is handled by next_day(). First, the routine tries to get the next hour part of a time with a call to next_hour. If next_hour() returns 1, it has reached the end of its data, usually the last element of the BYHOUR array. This means that next_day() should increment the time to the next day. If FREQUENCY==DAILY, the routine increments the day by the interval; otherwise, it increments the day by 1.

Next_day() differs from next_hour because it does not use the BYDAY array to select an appropriate day. Instead, it returns every day ( incrementing by 1 if the frequency is not DAILY with INTERVAL!=1) Any days that are not specified in a non-empty BYDAY array are filtered out later.

Generally, the flow of these routine is for a next_* call a next_* routine of a lower interval ( next_day calls next_hour) and then to possibly call an increment_* routine of an equal or higher interval. ( next_day calls increment_monthday() )

When the call to the original next_* routine returns, icalrecur_iterator_next() will check the returned data against other BYrule parts to determine if is should be excluded by calling check_contracting_rules. Generally, a contracting rule is any with a larger time span than the interval. For instance, if INTERVAL=DAILY, BYMONTH is a contracting rule part.

check_contracting_rules() uses has_contract_restriction() to do its work. has_contract_restriction() uses expand_map[] to determine if a rule is contracting, and if it is, and if the BY rule part has some data, then the routine checks if the value of a component of the time is part of the byrule part. For instance, for "INTERVAL=DAILY; BYMONTH=6,10", ihas_contract_restriction() would check that the time value given to it has a month of either 6 or 10.

Finally, icalrecur_iterator_next() does a few other checks on the time value, and if it passes, it returns the time.

A note about the end_of_data flag. The flag indicates that the routine is at the end of its data – the last BY rule if the routine is using by rules, or the last day of the week/month/year/etc if not.

This flag is usually set early in a next_* routine and returned in the end. The way it is used allows the next_* routine to set the last time back to the first element in a BYxx rule, and then signal to the higher level routine to increment the next higher level. For instance. WITH FREQ=MONTHLY;BYDAY=TU,FR, After next_weekday_by_month runs though both TU and FR, it sets the week day back to TU and sets end_of_data to 1x. This signals next_month to increment the month.


Definition in file icalrecur.c.

Function Documentation

◆ ical_get_invalid_rrule_handling_setting()

ical_invalid_rrule_handling ical_get_invalid_rrule_handling_setting ( void )

Gets how the library should handle invalid RRULEs.

The default library setting is ICAL_RRULE_TREAT_AS_ERROR.

Returns
the library's current cal_invalid_rrule_handling setting.
See also
ical_set_invalid_rrule_handling_setting

Definition at line 4252 of file icalrecur.c.

◆ ical_set_invalid_rrule_handling_setting()

void ical_set_invalid_rrule_handling_setting ( ical_invalid_rrule_handling newSetting)

Sets how the library should handle invalid RRULEs.

Parameters
newSettingthe ical_invalid_rrule_handling to use.
See also
ical_get_invalid_rrule_handling_setting

Definition at line 4269 of file icalrecur.c.

◆ icalrecur_expand_recurrence()

bool icalrecur_expand_recurrence ( const char * rule,
icaltime_t start,
int count,
icaltime_t * array )

Fills an array with the 'count' number of occurrences generated by the rrule.

Specifically, this fills an array up with at most 'count' icaltime_t values, each representing an occurrence time in seconds past the POSIX epoch.

Note
The times are returned in UTC, but the times are calculated in local time. You will have to convert the results back into local time before using them.
Parameters
rulea pointer to a char string containing the RRULE to use
starta valid starting date-time
countthe length of the provided icalarray
arraya pointer to an array of count icaltime_t values resulting from expanding the specified RRULE rule.
Returns
true if the rule could be converted to a string; false otherwise.

Definition at line 4216 of file icalrecur.c.

◆ icalrecur_freq_to_string()

const char * icalrecur_freq_to_string ( icalrecurrencetype_frequency kind)

Stringifies a icalrecurrencetype_frequency.

Parameters
kinda icalrecurrencetype_frequency to convert
Returns
a pointer to char string version of kind. If kind is invalid then NULL is returned.
See also
icalrecur_string_to_freq

Definition at line 213 of file icalrecur.c.

◆ icalrecur_iterator_free()

void icalrecur_iterator_free ( icalrecur_iterator * impl)

Frees the specified icalrecur_iterator.

Parameters
impla pointer to a valid icalrecur_iterator

Definition at line 2408 of file icalrecur.c.

◆ icalrecur_iterator_new()

icalrecur_iterator * icalrecur_iterator_new ( struct icalrecurrencetype * rule,
struct icaltimetype dtstart )

Creates a new recurrence rule iterator starting at DTSTART.

Parameters
rulea pointer to a valid icalrecurrencetype
dtstarta valid icaltimetype to use for the DTSART
Note
The new iterator may keep a reference to the passed rule. It must not be modified as long as the iterator is in use.
Returns
a pointer to the new icalrecur_iterator.

Definition at line 2280 of file icalrecur.c.

◆ icalrecur_iterator_next()

struct icaltimetype icalrecur_iterator_next ( icalrecur_iterator * impl)

Gets the next occurrence from an icalrecur_iterator.

Parameters
impla pointer to a valid icalrecur_iterator
Returns
an icaltimetype for the next occurrence.

Definition at line 3651 of file icalrecur.c.

◆ icalrecur_iterator_prev()

struct icaltimetype icalrecur_iterator_prev ( icalrecur_iterator * impl)

Gets the previous occurrence from an icalrecur_iterator.

Parameters
impla pointer to a valid icalrecur_iterator
Returns
an icaltimetype for the previous occurrence.
Since
4.0

Definition at line 3768 of file icalrecur.c.

◆ icalrecur_iterator_set_end()

bool icalrecur_iterator_set_end ( icalrecur_iterator * impl,
struct icaltimetype end )

Sets the date-time at which the iterator will stop at the latest.

Parameters
implis a pointer to a valid icalrecur_iterator
endis the ending icaltimetype

Values equal to or greater than end will not be returned by the iterator.

Returns
if the end was successfully set; false otherwise.

Definition at line 4087 of file icalrecur.c.

◆ icalrecur_iterator_set_range()

bool icalrecur_iterator_set_range ( icalrecur_iterator * impl,
struct icaltimetype from,
struct icaltimetype to )

Sets the date-times over which the iterator will run,

Parameters
implis a pointer to a valid icalrecur_iterator
tois the starting icaltimetype
fromis the ending icaltimetype that must be between DSTART and UNTIL

If to is null time, the forward iterator will return values up to and including UNTIL (if present), otherwise up to the year 2582.

if to is non-null time and later than from, the forward iterator will return values up to and including 'to'.

If to is non-null time and earlier than from, the reverse iterator will be set to start at from and will return values down to and including to.

NOTE: CAN NOT be used with RRULEs that contain COUNT.

Returns
true if the range was successfully set; false otherwise.
Since
4.0

Definition at line 4098 of file icalrecur.c.

◆ icalrecur_iterator_set_start()

bool icalrecur_iterator_set_start ( icalrecur_iterator * impl,
struct icaltimetype start )

Sets the date-time at which the iterator will start,

Note
CAN NOT be used with RRULEs that contain COUNT.
Parameters
implis a pointer to a valid icalrecur_iterator
startis the starting icaltimetype that must be between DTSTART and UNTIL.
Returns
if the start was successfully set; false otherwise.
Since
3.0

Definition at line 4062 of file icalrecur.c.

◆ icalrecur_resize_by()

bool icalrecur_resize_by ( icalrecurrence_by_data * by,
short size )

Resizes the buffer backing the 'by' array to the specified size, if different.

Frees the buffer if the new size is 0.

Parameters
byis a pointer to valid icalrecurrence_by_data to use
sizeis the new size for the array
Returns
true on success, false on failure.

Definition at line 306 of file icalrecur.c.

◆ icalrecur_skip_to_string()

const char * icalrecur_skip_to_string ( icalrecurrencetype_skip kind)

Stringifies a icalrecurrencetype_skip.

Parameters
kinda icalrecurrencetype_skip to convert
Returns
a pointer to char string version of kind. If kind is invalid then NULL is returned.
See also
icalrecur_string_to_skip

Definition at line 246 of file icalrecur.c.

◆ icalrecur_string_to_freq()

icalrecurrencetype_frequency icalrecur_string_to_freq ( const char * str)

Converts a char string into a icalrecurrencetype_frequency.

Parameters
stra pointer to a char string containing the string representation of an icalrecurrencetype_frequency.
Returns
the icalrecurrencetype_frequency version of str. If str is invalid then ICAL_NO_RECURRENCE is returned.
See also
icalrecur_freq_to_string

Definition at line 201 of file icalrecur.c.

◆ icalrecur_string_to_skip()

icalrecurrencetype_skip icalrecur_string_to_skip ( const char * str)

Converts a char string into a icalrecurrencetype_skip.

Parameters
stra pointer t a char string containing the string representation of an icalrecurrencetype_skip.
Returns
the icalrecurrencetype_skip version of str. If str is invalid then ICAL_SKIP_UNDEFINED is returned.
See also
icalrecur_skip_to_string

Definition at line 234 of file icalrecur.c.

◆ icalrecur_string_to_weekday()

icalrecurrencetype_weekday icalrecur_string_to_weekday ( const char * str)

Converts a char string into a icalrecurrencetype_weekday.

Parameters
stra pointer to a char string containing the string representation of a icalrecurrencetype_weekday
Returns
the icalrecurrencetype_weekday version of str. If str is invalid then :: ICAL_NO_WEEKDAY is returned.
See also
icalrecur_weekday_to_string

Definition at line 284 of file icalrecur.c.

◆ icalrecur_weekday_to_string()

const char * icalrecur_weekday_to_string ( icalrecurrencetype_weekday kind)

Stringifies a icalrecurrencetype_weekday.

Parameters
kinda icalrecurrencetype_weekday to convert
Returns
a pointer to char string version of kind. If kind is invalid then NULL is returned.
See also
icalrecur_string_to_weekday

Definition at line 271 of file icalrecur.c.

◆ icalrecurrencetype_as_string()

char * icalrecurrencetype_as_string ( struct icalrecurrencetype * recur)

Represent an icalrecurrencetype as a string.

Parameters
recura pointer to a valid icalrecurrencetype
Returns
a pointer to a char string containing the string representation of recur. Returns NULL if the conversion was unsuccessful.
See also
icalrecurrencetype_as_string_r

Definition at line 1009 of file icalrecur.c.

◆ icalrecurrencetype_as_string_r()

char * icalrecurrencetype_as_string_r ( struct icalrecurrencetype * recur)

Represent an icalrecurrencetype as a string.

Parameters
recura pointer to a valid icalrecurrencetype
Returns
a pointer to a char string containing the string representation of recur. Returns NULL if the conversion was unsuccessful.
See also
icalrecurrencetype_as_string

Definition at line 1018 of file icalrecur.c.

◆ icalrecurrencetype_clone()

struct icalrecurrencetype * icalrecurrencetype_clone ( struct icalrecurrencetype * r)

Creates a deep copy of the given icalrecurrencetype.

The new instance is returned with a refcount of 1.

Parameters
ris a pointer to a valid icalrecurrencetype
Returns
a pointer to the cloned memory.

Definition at line 797 of file icalrecur.c.

◆ icalrecurrencetype_day_day_of_week()

enum icalrecurrencetype_weekday icalrecurrencetype_day_day_of_week ( short day)

Decode the weekday from a "weekday:pos" form.

Parameters
dayis the "weekday:pos" to decode (as created by icalrecurrencetype_encode_day())
Returns
The decoded day of the week from the "weekday:pos". 1 is Monday, 2 is Tuesday, etc.
See also
icalrecurrencetype_encode_day and icalrecurrencetype_day_position().

Definition at line 4178 of file icalrecur.c.

◆ icalrecurrencetype_day_position()

int icalrecurrencetype_day_position ( short day)

Decodes a the position from a "weekday:pos" form.

Parameters
dayis the "weekday:pos" to decode (as created by icalrecurrencetype_encode_day()).
Returns
The position of the day in the week, where: 0 == any of day of week. 1 == first, 2 = second, -2 == second to last, etc. 0 means 'any' or 'every'.

Definition at line 4183 of file icalrecur.c.

◆ icalrecurrencetype_encode_day()

short icalrecurrencetype_encode_day ( enum icalrecurrencetype_weekday weekday,
int position )

Encode a weekday and position into a form which can be stored into a icalrecurrencetype::by[ICAL_BY_DAY] array.

The 'day' element of icalrecurrencetype_weekday is encoded to allow representation of both the day of the week ( Monday, Tuesday), but also the Nth day of the week (First tuesday of the month, last thursday of the year) These routines decode the day values.

The day's position in the period (Nth-ness) and the numerical value of the day are encoded together as: pos*7 + dow.

A position of 0 means 'any' or 'every'.

Use icalrecurrencetype_day_day_of_week() and icalrecurrencetype_day_position() to split the encoded value back into the parts.

Parameters
weekdayis the weekday to use
positionis the positiog to use
Returns
the encoded "weekday:pos", which can later be decoded back using icalrecurrencetype_day_day_of_week() and icalrecurrencetype_day_position().
Since
4.0

Definition at line 4194 of file icalrecur.c.

◆ icalrecurrencetype_encode_month()

short icalrecurrencetype_encode_month ( int month,
bool is_leap )

Encodes a month and leap year indicator into a form which can be stored into a icalrecurrencetype::by[ICAL_BY_MONTH] array.

The month element of the by[ICAL_BY_MONTH] array is encoded to allow representation of the "L" leap suffix (RFC 7529). The "L" suffix is encoded by setting a high-order bit.

Use icalrecurrencetype_month_is_leap() and icalrecurrencetype_month_month() to split the encoded value back into the parts.

Parameters
monthis the month to use (1-12)
is_leapis a bool indicating if leap year is to be considered
Returns
the encoded "month:leap_year", which can later be decoded back using icalrecurrencetype_month_is_leap() and icalrecurrencetype_month_month().
Since
4.0

Definition at line 4211 of file icalrecur.c.

◆ icalrecurrencetype_month_is_leap()

bool icalrecurrencetype_month_is_leap ( short month)

Decode the is_leap from a month:leap_year form.

Parameters
monthis the month:leap_year to decode (as created by icalrecurrencetype_encode_month())
Returns
the is_leap portion of the month:leap_year
See also
icalrecurrencetype_encode_month, icalrecurrencetype_month_month

Definition at line 4201 of file icalrecur.c.

◆ icalrecurrencetype_month_month()

int icalrecurrencetype_month_month ( short month)

Decode the month from a month:leap_year form.

Parameters
monthis the month:leap_year to decode (as created by icalrecurrencetype_encode_month())
Returns
the month portion of the month:leap_year
See also
icalrecurrencetype_encode_month, icalrecurrencetype_month_is_leap

Definition at line 4206 of file icalrecur.c.

◆ icalrecurrencetype_new()

struct icalrecurrencetype * icalrecurrencetype_new ( void )

Constructs a new instance of icalrecurrencetype.

The new instance is initialized with a refcount of 1.

Returns
A pointer to the new instance, or NULL if memory allocation failed.

Definition at line 708 of file icalrecur.c.

◆ icalrecurrencetype_new_from_string()

struct icalrecurrencetype * icalrecurrencetype_new_from_string ( const char * str)

Create a new icalrecurrencetype from a string.

Parameters
stra pointer to a char string containing string version of the recurrence.
Returns
a pointer to the new icalrecurrencetype or NULL if the string contained an invalid representation.

Definition at line 834 of file icalrecur.c.

◆ icalrecurrencetype_ref()

void icalrecurrencetype_ref ( struct icalrecurrencetype * recur)

Increases the icalrecurrencetype reference counter by 1.

Parameters
recuris a pointer to a valid icalrecurrencetype

Definition at line 747 of file icalrecur.c.

◆ icalrecurrencetype_rscale_supported_calendars()

icalarray * icalrecurrencetype_rscale_supported_calendars ( void )

Return an array of RSCALE supported calendars.

Returns
a pointer to an icalarray of a list of RSCALE supported calendars. Currently returns list containing "GREGORIAN" only.

Definition at line 1966 of file icalrecur.c.

◆ icalrecurrencetype_unref()

void icalrecurrencetype_unref ( struct icalrecurrencetype * recur)

Decreases the icalrecurrencetype reference counter by 1.

If the counter reaches 0, the instance and all referenced memory (i.e. rscale and 'by' arrays) are deallocated.

Parameters
recura pointer to a valid icalrecurrencetype

Definition at line 755 of file icalrecur.c.