Tree-wide cleanup of trailing whitespace
[barry.git] / src / r_recur_base.cc
blobbf13a581051951dcffed5e4e61870557b4f6fc8b
1 ///
2 /// \file r_recur_base.cc
3 /// Base class for recurring calendar event data.
4 ///
6 /*
7 Copyright (C) 2005-2009, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
22 #include "r_recur_base.h"
23 #include "protostructs.h"
24 #include "error.h"
25 #include "endian.h"
26 #include "time.h"
27 #include <string.h>
29 #define __DEBUG_MODE__
30 #include "debug.h"
32 using namespace std;
33 using namespace Barry::Protocol;
36 #define FIELDCODE_RECURRENCE_DATA 0x0c
38 namespace Barry {
41 ///////////////////////////////////////////////////////////////////////////////
42 // RecurBase class
44 RecurBase::RecurBase()
46 Clear();
49 RecurBase::~RecurBase()
53 bool RecurBase::ParseField(uint8_t type,
54 const unsigned char *data,
55 size_t size,
56 const IConverter *ic)
58 // handle special cases
59 switch( type )
61 case FIELDCODE_RECURRENCE_DATA:
62 if( size >= CALENDAR_RECURRENCE_DATA_FIELD_SIZE ) {
63 // good data
64 ParseRecurrenceData(data);
66 else {
67 // not enough data!
68 throw Error("RecurBase::ParseField: not enough data in recurrence data field");
70 return true;
73 // unknown field
74 return false;
77 // this function assumes the size has already been checked
78 void RecurBase::ParseRecurrenceData(const void *data)
80 const CalendarRecurrenceDataField *rec =
81 (const CalendarRecurrenceDataField*) data;
83 Interval = btohs(rec->interval);
84 if( Interval < 1 )
85 Interval = 1; // must always be >= 1
87 if( rec->endTime == 0xffffffff ) {
88 Perpetual = true;
90 else {
91 RecurringEndTime = min2time(rec->endTime);
92 Perpetual = false;
95 switch( rec->type )
97 case CRDF_TYPE_DAY:
98 RecurringType = Day;
99 // no extra data
100 break;
102 case CRDF_TYPE_MONTH_BY_DATE:
103 RecurringType = MonthByDate;
104 DayOfMonth = rec->u.month_by_date.monthDay;
105 break;
107 case CRDF_TYPE_MONTH_BY_DAY:
108 RecurringType = MonthByDay;
109 DayOfWeek = rec->u.month_by_day.weekDay;
110 WeekOfMonth = rec->u.month_by_day.week;
111 break;
113 case CRDF_TYPE_YEAR_BY_DATE:
114 RecurringType = YearByDate;
115 DayOfMonth = rec->u.year_by_date.monthDay;
116 MonthOfYear = rec->u.year_by_date.month;
117 break;
119 case CRDF_TYPE_YEAR_BY_DAY:
120 RecurringType = YearByDay;
121 DayOfWeek = rec->u.year_by_day.weekDay;
122 WeekOfMonth = rec->u.year_by_day.week;
123 MonthOfYear = rec->u.year_by_day.month;
124 break;
126 case CRDF_TYPE_WEEK:
127 RecurringType = Week;
129 // Note: this simple copy is only possible since
130 // the CAL_WD_* constants are the same as CRDF_WD_* constants.
131 // If this ever changes, this code will need to change.
132 WeekDays = rec->u.week.days;
133 break;
135 default:
136 eout("Unknown recurrence data type: 0x"
137 << setbase(16) << (unsigned int) rec->type);
138 throw Error("Unknown recurrence data type");
141 Recurring = true;
144 // this function assumes there is CALENDAR_RECURRENCE_DATA_FIELD_SIZE bytes
145 // available in data
146 void RecurBase::BuildRecurrenceData(time_t StartTime, void *data) const
148 if( !Recurring )
149 throw Error("RecurBase::BuildRecurrenceData: Attempting to build recurrence data on non-recurring record.");
151 CalendarRecurrenceDataField *rec = (CalendarRecurrenceDataField*) data;
153 // set all to zero
154 memset(data, 0, CALENDAR_RECURRENCE_DATA_FIELD_SIZE);
156 rec->interval = htobs(Interval);
157 rec->startTime = time2min(StartTime);
158 if( Perpetual )
159 rec->endTime = 0xffffffff;
160 else
161 rec->endTime = time2min(RecurringEndTime);
163 switch( RecurringType )
165 case Day:
166 rec->type = CRDF_TYPE_DAY;
167 // no extra data
168 break;
170 case MonthByDate:
171 rec->type = CRDF_TYPE_MONTH_BY_DATE;
172 rec->u.month_by_date.monthDay = DayOfMonth;
173 break;
175 case MonthByDay:
176 rec->type = CRDF_TYPE_MONTH_BY_DAY;
177 rec->u.month_by_day.weekDay = DayOfWeek;
178 rec->u.month_by_day.week = WeekOfMonth;
179 break;
181 case YearByDate:
182 rec->type = CRDF_TYPE_YEAR_BY_DATE;
183 rec->u.year_by_date.monthDay = DayOfMonth;
184 rec->u.year_by_date.month = MonthOfYear;
185 break;
187 case YearByDay:
188 rec->type = CRDF_TYPE_YEAR_BY_DAY;
189 rec->u.year_by_day.weekDay = DayOfWeek;
190 rec->u.year_by_day.week = WeekOfMonth;
191 rec->u.year_by_day.month = MonthOfYear;
192 break;
194 case Week:
195 rec->type = CRDF_TYPE_WEEK;
197 // Note: this simple copy is only possible since
198 // the CAL_WD_* constants are the same as CRDF_WD_* constants.
199 // If this ever changes, this code will need to change.
200 rec->u.week.days = WeekDays;
201 break;
203 default:
204 eout("RecurBase::BuildRecurrenceData: "
205 "Unknown recurrence data type: 0x"
206 << setbase(16) << (unsigned int) rec->type);
207 throw Error("RecurBase::BuildRecurrenceData: Unknown recurrence data type");
211 uint8_t RecurBase::RecurringFieldType() const
213 return FIELDCODE_RECURRENCE_DATA;
216 void RecurBase::Clear()
218 Recurring = false;
219 RecurringType = RecurBase::Week;
220 Interval = 1;
221 RecurringEndTime = 0;
222 Perpetual = false;
223 DayOfWeek = WeekOfMonth = DayOfMonth = MonthOfYear = 0;
224 WeekDays = 0;
227 void RecurBase::Dump(std::ostream &os) const
229 static const char *DayNames[] = { "Sun", "Mon", "Tue", "Wed",
230 "Thu", "Fri", "Sat" };
231 static const char *MonthNames[] = { "Jan", "Feb", "Mar", "Apr",
232 "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
234 // FIXME - need a "check all data" function that make sure that all
235 // recurrence data is within range. Then call that before using
236 // the data, such as in Build and in Dump.
238 // print recurrence data if available
239 os << " Recurring: " << (Recurring ? "yes" : "no") << "\n";
240 if( Recurring ) {
241 switch( RecurringType )
243 case Day:
244 os << " Every day.\n";
245 break;
247 case MonthByDate:
248 os << " Every month on the "
249 << DayOfMonth
250 << (DayOfMonth == 1 ? "st" : "")
251 << (DayOfMonth == 2 ? "nd" : "")
252 << (DayOfMonth == 3 ? "rd" : "")
253 << (DayOfMonth > 3 ? "th" : "")
254 << "\n";
255 break;
257 case MonthByDay:
258 os << " Every month on the "
259 << DayNames[DayOfWeek]
260 << " of week "
261 << WeekOfMonth
262 << "\n";
263 break;
265 case YearByDate:
266 os << " Every year on "
267 << MonthNames[MonthOfYear-1]
268 << " " << DayOfMonth << "\n";
269 break;
271 case YearByDay:
272 os << " Every year in " << MonthNames[MonthOfYear-1]
273 << " on "
274 << DayNames[DayOfWeek]
275 << " of week " << WeekOfMonth << "\n";
276 break;
278 case Week:
279 os << " Every week on: ";
280 if( WeekDays & CAL_WD_SUN ) os << "Sun ";
281 if( WeekDays & CAL_WD_MON ) os << "Mon ";
282 if( WeekDays & CAL_WD_TUE ) os << "Tue ";
283 if( WeekDays & CAL_WD_WED ) os << "Wed ";
284 if( WeekDays & CAL_WD_THU ) os << "Thu ";
285 if( WeekDays & CAL_WD_FRI ) os << "Fri ";
286 if( WeekDays & CAL_WD_SAT ) os << "Sat ";
287 os << "\n";
288 break;
290 default:
291 os << " Unknown recurrence type\n";
292 break;
295 os << " Interval: " << Interval << "\n";
297 if( Perpetual )
298 os << " Ends: never\n";
299 else
300 os << " Ends: " << ctime(&RecurringEndTime);
305 } // namespace Barry