@@ -1771,15 +1771,19 @@ static void ical_next_rrule_base_itime(ical_rrule *pirrule)
17711771 }
17721772}
17731773
1774- /* ptz_component can be NULL, represents UTC */
1775- bool ical_parse_rrule (const ical_component *ptz_component,
1774+ /*
1775+ * @ptz_component: if NULL, represents UTC
1776+ *
1777+ * On success, returns %nullptr. On error, the error indicator string is returned.
1778+ */
1779+ const char *ical_parse_rrule (const ical_component *ptz_component,
17761780 time_t start_time, const std::vector<ical_value> *pvalue_list,
17771781 ical_rrule *pirrule)
17781782{
17791783 *pirrule = {};
17801784 auto pvalue = ical_get_first_subvalue_by_name_internal (pvalue_list, " FREQ" );
17811785 if (pvalue == nullptr )
1782- return false ;
1786+ return " E-2824: RRULE has no FREQ " ;
17831787 if (strcasecmp (pvalue, " SECONDLY" ) == 0 )
17841788 pirrule->frequency = ical_frequency::second;
17851789 else if (strcasecmp (pvalue, " MINUTELY" ) == 0 )
@@ -1795,33 +1799,33 @@ bool ical_parse_rrule(const ical_component *ptz_component,
17951799 else if (strcasecmp (pvalue, " YEARLY" ) == 0 )
17961800 pirrule->frequency = ical_frequency::year;
17971801 else
1798- return false ;
1802+ return " E-2825: RRULE has invalid FREQ " ;
17991803 pirrule->real_frequency = pirrule->frequency ;
18001804 pvalue = ical_get_first_subvalue_by_name_internal (pvalue_list, " INTERVAL" );
18011805 if (NULL == pvalue) {
18021806 pirrule->interval = 1 ;
18031807 } else {
18041808 pirrule->interval = strtol (pvalue, nullptr , 0 );
18051809 if (pirrule->interval <= 0 )
1806- return false ;
1810+ return " E-2826: RRULE has invalid INTERVAL " ;
18071811 }
18081812 pvalue = ical_get_first_subvalue_by_name_internal (pvalue_list, " COUNT" );
18091813 if (NULL == pvalue) {
18101814 pirrule->total_count = 0 ;
18111815 } else {
18121816 pirrule->total_count = strtol (pvalue, nullptr , 0 );
18131817 if (pirrule->total_count <= 0 )
1814- return false ;
1818+ return " E-2827: RRULE has invalid COUNT " ;
18151819 }
18161820 pvalue = ical_get_first_subvalue_by_name_internal (pvalue_list, " UNTIL" );
18171821 if (NULL != pvalue) {
18181822 if (pirrule->total_count != 0 )
1819- return false ;
1823+ return " E-2828: Cannot combine COUNT with UNTIL in RRULE " ;
18201824 time_t until_time;
18211825 if (!ical_parse_until (ptz_component, pvalue, &until_time))
1822- return false ;
1826+ return " E-2829: RRULE has invalid UNTIL " ;
18231827 if (until_time < start_time)
1824- return false ;
1828+ return " E-2830: RRULE has UNTIL < DTSTART " ;
18251829 /* until==start can happen with a recurrent series with one occurrence */
18261830 pirrule->b_until = true ;
18271831 ical_utc_to_datetime (ptz_component,
@@ -1910,14 +1914,14 @@ bool ical_parse_rrule(const ical_component *ptz_component,
19101914 if (pirrule->frequency != ical_frequency::week &&
19111915 pirrule->frequency != ical_frequency::month &&
19121916 pirrule->frequency != ical_frequency::year)
1913- return false ;
1917+ return " E-2841: RRULE has BYDAY but is not of frequency WEEK/MONTH/YEAR " ;
19141918 for (const auto &pnv2 : *pbywday_list) {
19151919 int dayofweek = -1 , weekorder = -1 ;
19161920 if (!ical_parse_byday (pnv2.c_str (), &dayofweek, &weekorder))
19171921 continue ;
19181922 if (ical_frequency::month == pirrule->frequency ) {
19191923 if (weekorder > 5 || weekorder < -5 )
1920- return false ;
1924+ return " E-2844: RRULE.FREQ=MONTHLY with invalid weekorder " ;
19211925 else if (weekorder > 0 )
19221926 ical_set_bitmap (pirrule->wday_bitmap ,
19231927 7 *(weekorder - 1 ) + dayofweek);
@@ -1939,7 +1943,7 @@ bool ical_parse_rrule(const ical_component *ptz_component,
19391943 ical_set_bitmap (pirrule->wday_bitmap , 7 *i + dayofweek);
19401944 } else {
19411945 if (weekorder != 0 )
1942- return false ;
1946+ return " E-2845: RRULE with invalid weekorder " ;
19431947 ical_set_bitmap (pirrule->wday_bitmap , dayofweek);
19441948 }
19451949 }
@@ -1982,57 +1986,57 @@ bool ical_parse_rrule(const ical_component *ptz_component,
19821986 if (NULL != psetpos_list) {
19831987 switch (pirrule->frequency ) {
19841988 case ical_frequency::second:
1985- return false ;
1989+ return " E-2850: RRULE has both BYSECOND and BYSETPOS " ;
19861990 case ical_frequency::minute:
19871991 if (pirrule->real_frequency != ical_frequency::second)
1988- return false ;
1992+ return " E-2851 " ;
19891993 if (60 * pirrule->interval > 366 )
1990- return false ;
1994+ return " E-2852 " ;
19911995 break ;
19921996 case ical_frequency::hour:
19931997 if (pirrule->real_frequency != ical_frequency::minute)
1994- return false ;
1998+ return " E-2853 " ;
19951999 if (60 * pirrule->interval > 366 )
1996- return false ;
2000+ return " E-2854 " ;
19972001 break ;
19982002 case ical_frequency::day:
19992003 if (pirrule->real_frequency != ical_frequency::hour)
2000- return false ;
2004+ return " E-2855 " ;
20012005 if (24 * pirrule->interval > 366 )
2002- return false ;
2006+ return " E-2856 " ;
20032007 break ;
20042008 case ical_frequency::week:
20052009 if (pirrule->real_frequency == ical_frequency::day) {
20062010 break ;
20072011 } else if (pirrule->real_frequency == ical_frequency::hour) {
20082012 if (7 * 24 * pirrule->interval > 366 )
2009- return false ;
2013+ return " E-2857 " ;
20102014 break ;
20112015 }
2012- return false ;
2016+ return " E-2858 " ;
20132017 case ical_frequency::month:
20142018 if (pirrule->real_frequency == ical_frequency::day) {
20152019 if (31 * pirrule->interval > 366 )
2016- return false ;
2020+ return " E-2859 " ;
20172021 } else if (pirrule->real_frequency == ical_frequency::week) {
20182022 if (5 * pirrule->interval > 366 )
2019- return false ;
2023+ return " E-2860 " ;
20202024 } else {
2021- return false ;
2025+ return " E-2861 " ;
20222026 }
20232027 break ;
20242028 case ical_frequency::year:
20252029 if (pirrule->real_frequency == ical_frequency::day) {
20262030 if (pirrule->interval > 1 )
2027- return false ;
2031+ return " E-2862 " ;
20282032 } else if (pirrule->real_frequency == ical_frequency::week) {
20292033 if (pirrule->interval > 8 )
2030- return false ;
2034+ return " E-2863 " ;
20312035 } else if (pirrule->real_frequency == ical_frequency::month) {
20322036 if (pirrule->interval > 30 )
2033- return false ;
2037+ return " E-2864 " ;
20342038 } else {
2035- return false ;
2039+ return " E-2865 " ;
20362040 }
20372041 break ;
20382042 }
@@ -2053,7 +2057,7 @@ bool ical_parse_rrule(const ical_component *ptz_component,
20532057 if (NULL != pvalue) {
20542058 auto dow = weekday_to_int (pvalue);
20552059 if (dow < 0 )
2056- return false ;
2060+ return " E-2868 " ;
20572061 pirrule->weekstart = dow;
20582062 } else {
20592063 pirrule->weekstart = pbywnum_list != nullptr ;
@@ -2129,7 +2133,7 @@ bool ical_parse_rrule(const ical_component *ptz_component,
21292133 itime < pirrule->next_base_itime ;
21302134 itime = ical_next_rrule_itime (pirrule, hint_result, itime)) {
21312135 if (pirrule->b_until && itime > pirrule->until_itime )
2132- return false ;
2136+ return " E-2869 " ;
21332137 hint_result = ical_test_rrule (pirrule, itime);
21342138 if (hint_result != rrule_by::setpos)
21352139 continue ;
@@ -2146,10 +2150,10 @@ bool ical_parse_rrule(const ical_component *ptz_component,
21462150 pirrule->real_start_itime = itime;
21472151 pirrule->current_instance = 1 ;
21482152 pirrule->next_base_itime = pirrule->base_itime ;
2149- return true ;
2153+ return nullptr ;
21502154 }
21512155 pirrule->current_instance = 1 ;
2152- return true ;
2156+ return nullptr ;
21532157 }
21542158 auto base_itime = pirrule->base_itime ;
21552159 itime = pirrule->instance_itime ;
@@ -2166,7 +2170,7 @@ bool ical_parse_rrule(const ical_component *ptz_component,
21662170 }
21672171 pirrule->current_instance = 1 ;
21682172 pirrule->b_start_exceptional = true ;
2169- return true ;
2173+ return nullptr ;
21702174}
21712175
21722176bool ical_rrule::iterate ()
0 commit comments