|
Libical API Documentation 4.0 UNRELEASED Go to the stable 3.0 documentation
|
Implementation of routines for dealing with recurring time. More...
Go to the source code of this file.
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.
| 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.
Definition at line 4252 of file icalrecur.c.
| void ical_set_invalid_rrule_handling_setting | ( | ical_invalid_rrule_handling | newSetting | ) |
Sets how the library should handle invalid RRULEs.
| newSetting | the ical_invalid_rrule_handling to use. |
Definition at line 4269 of file icalrecur.c.
| 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.
| rule | a pointer to a char string containing the RRULE to use |
| start | a valid starting date-time |
| count | the length of the provided icalarray |
| array | a pointer to an array of count icaltime_t values resulting from expanding the specified RRULE rule. |
rule could be converted to a string; false otherwise. Definition at line 4216 of file icalrecur.c.
| const char * icalrecur_freq_to_string | ( | icalrecurrencetype_frequency | kind | ) |
Stringifies a icalrecurrencetype_frequency.
| kind | a icalrecurrencetype_frequency to convert |
kind. If kind is invalid then NULL is returned.Definition at line 213 of file icalrecur.c.
| void icalrecur_iterator_free | ( | icalrecur_iterator * | impl | ) |
Frees the specified icalrecur_iterator.
| impl | a pointer to a valid icalrecur_iterator |
Definition at line 2408 of file icalrecur.c.
| icalrecur_iterator * icalrecur_iterator_new | ( | struct icalrecurrencetype * | rule, |
| struct icaltimetype | dtstart ) |
Creates a new recurrence rule iterator starting at DTSTART.
| rule | a pointer to a valid icalrecurrencetype |
| dtstart | a valid icaltimetype to use for the DTSART |
Definition at line 2280 of file icalrecur.c.
| struct icaltimetype icalrecur_iterator_next | ( | icalrecur_iterator * | impl | ) |
Gets the next occurrence from an icalrecur_iterator.
| impl | a pointer to a valid icalrecur_iterator |
Definition at line 3651 of file icalrecur.c.
| struct icaltimetype icalrecur_iterator_prev | ( | icalrecur_iterator * | impl | ) |
Gets the previous occurrence from an icalrecur_iterator.
| impl | a pointer to a valid icalrecur_iterator |
Definition at line 3768 of file icalrecur.c.
| bool icalrecur_iterator_set_end | ( | icalrecur_iterator * | impl, |
| struct icaltimetype | end ) |
Sets the date-time at which the iterator will stop at the latest.
| impl | is a pointer to a valid icalrecur_iterator |
| end | is the ending icaltimetype |
Values equal to or greater than end will not be returned by the iterator.
Definition at line 4087 of file icalrecur.c.
| bool icalrecur_iterator_set_range | ( | icalrecur_iterator * | impl, |
| struct icaltimetype | from, | ||
| struct icaltimetype | to ) |
Sets the date-times over which the iterator will run,
| impl | is a pointer to a valid icalrecur_iterator |
| to | is the starting icaltimetype |
| from | is 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.
Definition at line 4098 of file icalrecur.c.
| bool icalrecur_iterator_set_start | ( | icalrecur_iterator * | impl, |
| struct icaltimetype | start ) |
Sets the date-time at which the iterator will start,
| impl | is a pointer to a valid icalrecur_iterator |
| start | is the starting icaltimetype that must be between DTSTART and UNTIL. |
Definition at line 4062 of file icalrecur.c.
| 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.
| by | is a pointer to valid icalrecurrence_by_data to use |
| size | is the new size for the array |
Definition at line 306 of file icalrecur.c.
| const char * icalrecur_skip_to_string | ( | icalrecurrencetype_skip | kind | ) |
Stringifies a icalrecurrencetype_skip.
| kind | a icalrecurrencetype_skip to convert |
kind. If kind is invalid then NULL is returned.Definition at line 246 of file icalrecur.c.
| icalrecurrencetype_frequency icalrecur_string_to_freq | ( | const char * | str | ) |
Converts a char string into a icalrecurrencetype_frequency.
| str | a pointer to a char string containing the string representation of an icalrecurrencetype_frequency. |
str. If str is invalid then ICAL_NO_RECURRENCE is returned.Definition at line 201 of file icalrecur.c.
| icalrecurrencetype_skip icalrecur_string_to_skip | ( | const char * | str | ) |
Converts a char string into a icalrecurrencetype_skip.
| str | a pointer t a char string containing the string representation of an icalrecurrencetype_skip. |
str. If str is invalid then ICAL_SKIP_UNDEFINED is returned.Definition at line 234 of file icalrecur.c.
| icalrecurrencetype_weekday icalrecur_string_to_weekday | ( | const char * | str | ) |
Converts a char string into a icalrecurrencetype_weekday.
| str | a pointer to a char string containing the string representation of a icalrecurrencetype_weekday |
str. If str is invalid then :: ICAL_NO_WEEKDAY is returned.Definition at line 284 of file icalrecur.c.
| const char * icalrecur_weekday_to_string | ( | icalrecurrencetype_weekday | kind | ) |
Stringifies a icalrecurrencetype_weekday.
| kind | a icalrecurrencetype_weekday to convert |
kind. If kind is invalid then NULL is returned.Definition at line 271 of file icalrecur.c.
| char * icalrecurrencetype_as_string | ( | struct icalrecurrencetype * | recur | ) |
Represent an icalrecurrencetype as a string.
| recur | a pointer to a valid icalrecurrencetype |
recur. Returns NULL if the conversion was unsuccessful.Definition at line 1009 of file icalrecur.c.
| char * icalrecurrencetype_as_string_r | ( | struct icalrecurrencetype * | recur | ) |
Represent an icalrecurrencetype as a string.
| recur | a pointer to a valid icalrecurrencetype |
recur. Returns NULL if the conversion was unsuccessful.Definition at line 1018 of file icalrecur.c.
| 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.
| r | is a pointer to a valid icalrecurrencetype |
Definition at line 797 of file icalrecur.c.
| enum icalrecurrencetype_weekday icalrecurrencetype_day_day_of_week | ( | short | day | ) |
Decode the weekday from a "weekday:pos" form.
| day | is the "weekday:pos" to decode (as created by icalrecurrencetype_encode_day()) |
Definition at line 4178 of file icalrecur.c.
| int icalrecurrencetype_day_position | ( | short | day | ) |
Decodes a the position from a "weekday:pos" form.
| day | is the "weekday:pos" to decode (as created by icalrecurrencetype_encode_day()). |
Definition at line 4183 of file icalrecur.c.
| 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.
| weekday | is the weekday to use |
| position | is the positiog to use |
Definition at line 4194 of file icalrecur.c.
| 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.
| month | is the month to use (1-12) |
| is_leap | is a bool indicating if leap year is to be considered |
Definition at line 4211 of file icalrecur.c.
| bool icalrecurrencetype_month_is_leap | ( | short | month | ) |
Decode the is_leap from a month:leap_year form.
| month | is the month:leap_year to decode (as created by icalrecurrencetype_encode_month()) |
Definition at line 4201 of file icalrecur.c.
| int icalrecurrencetype_month_month | ( | short | month | ) |
Decode the month from a month:leap_year form.
| month | is the month:leap_year to decode (as created by icalrecurrencetype_encode_month()) |
Definition at line 4206 of file icalrecur.c.
| struct icalrecurrencetype * icalrecurrencetype_new | ( | void | ) |
Constructs a new instance of icalrecurrencetype.
The new instance is initialized with a refcount of 1.
Definition at line 708 of file icalrecur.c.
| struct icalrecurrencetype * icalrecurrencetype_new_from_string | ( | const char * | str | ) |
Create a new icalrecurrencetype from a string.
| str | a pointer to a char string containing string version of the recurrence. |
Definition at line 834 of file icalrecur.c.
| void icalrecurrencetype_ref | ( | struct icalrecurrencetype * | recur | ) |
Increases the icalrecurrencetype reference counter by 1.
| recur | is a pointer to a valid icalrecurrencetype |
Definition at line 747 of file icalrecur.c.
| icalarray * icalrecurrencetype_rscale_supported_calendars | ( | void | ) |
Return an array of RSCALE supported calendars.
Definition at line 1966 of file icalrecur.c.
| 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.
| recur | a pointer to a valid icalrecurrencetype |
Definition at line 755 of file icalrecur.c.