From 8c6b4dcf08268ed2971b06df40c733ba28448582 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Thu, 9 Apr 2009 20:11:38 +0200 Subject: Make chaos calendar gem --- lib/chaos_calendar/chaos_calendar.c | 76 +++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 lib/chaos_calendar/chaos_calendar.c (limited to 'lib/chaos_calendar/chaos_calendar.c') diff --git a/lib/chaos_calendar/chaos_calendar.c b/lib/chaos_calendar/chaos_calendar.c new file mode 100644 index 00000000..e59c1ed4 --- /dev/null +++ b/lib/chaos_calendar/chaos_calendar.c @@ -0,0 +1,76 @@ +#include +#include +#include + +//#define RRULE "FREQ=MONTHLY;BYMONTH=1,2,3,4,5,6,7,8,9,10,11;BYDAY=-1WE;UNTIL=20091105T220000" +//#define RRULE "FREQ=DAILY;UNTIL=20991111T220000;VFOO" + +VALUE occurrences( VALUE dtstart, VALUE dtend, char *rrule ) { + struct icaltimetype start, end; + time_t tt; + VALUE tv_sec, occurr = rb_ary_new(); + + /* Get method ID for Time.tv_sec */ + ID time_tv_sec = rb_intern( "tv_sec" ); + ID time_to_time = rb_intern( "to_time" ); + + if( !rb_respond_to( dtstart, time_tv_sec ) ) { + if( rb_respond_to( dtstart, time_to_time ) ) + dtstart = rb_funcall( dtstart, time_to_time, 0 ); + else + rb_raise( rb_eTypeError, "Can't convert dtstart into a Time-like object." ); + } + + if( !rb_respond_to( dtend, time_tv_sec ) ) { + if( rb_respond_to( dtend, time_to_time ) ) + dtend = rb_funcall( dtend, time_to_time, 0 ); + else + rb_raise( rb_eTypeError, "Can't convert dtend into a Time-like object." ); + } + + /* Apply .tv_sec to our Time objects (if they are Times ...) */ + tv_sec = rb_funcall( dtstart, time_tv_sec, 0 ); + tt = NUM2INT( tv_sec ); + start = icaltime_from_timet( tt, 0 ); + + tv_sec = rb_funcall( dtend, time_tv_sec, 0 ); + tt = NUM2INT( tv_sec ); + end = icaltime_from_timet( tt, 0 ); + + icalerror_clear_errno(); + icalerror_set_error_state( ICAL_MALFORMEDDATA_ERROR, ICAL_ERROR_NONFATAL); + + struct icalrecurrencetype recur = icalrecurrencetype_from_string( rrule ); + if( icalerrno != ICAL_NO_ERROR ) { + rb_raise(rb_eArgError, "Malformed RRule"); + return Qnil; + } + + icalrecur_iterator* ritr = icalrecur_iterator_new( recur, start ); + + while(1) { + struct icaltimetype next = icalrecur_iterator_next(ritr); + + if( icaltime_is_null_time(next) || ( icaltime_compare( next, end ) > 0 ) ) { + icalrecur_iterator_free(ritr); + return occurr; + } + + rb_ary_push( occurr, rb_time_new( icaltime_as_timet( next ), 0 ) ); + }; + + icalrecur_iterator_free(ritr); + return occurr; +} + +VALUE duration_to_fixnum( char * duration ) { + icalerror_clear_errno(); + icalerror_set_error_state( ICAL_MALFORMEDDATA_ERROR, ICAL_ERROR_NONFATAL); + + struct icaldurationtype dur_struct = icaldurationtype_from_string( duration ); + + if( icaldurationtype_is_bad_duration( dur_struct ) ) + rb_raise(rb_eArgError, "Malformed Duration"); + + return LONG2FIX(icaldurationtype_as_int( dur_struct )); +} -- cgit v1.3