David Smart / iCal
Committer:
WiredHome
Date:
Sat May 17 19:54:51 2014 +0000
Revision:
2:1f5dbc624b95
Parent:
1:db274b9e40cc
Child:
4:a1c25d936346
Working to improve the recurring event parsing

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 2:1f5dbc624b95 1 //
WiredHome 2:1f5dbc624b95 2 // TODO
WiredHome 2:1f5dbc624b95 3 // Repeat parsing is quite weak right now. It handles repeating days w/in a week
WiredHome 2:1f5dbc624b95 4 // (e.g. repeat weekly, on Mon, Tue, Thu)
WiredHome 2:1f5dbc624b95 5 //
WiredHome 0:49245357cd1b 6
WiredHome 0:49245357cd1b 7 #include "iCal.h"
WiredHome 0:49245357cd1b 8 #include <algorithm>
WiredHome 0:49245357cd1b 9
WiredHome 2:1f5dbc624b95 10 #define DEBUG "iCal"
WiredHome 0:49245357cd1b 11 #include <cstdio>
WiredHome 0:49245357cd1b 12 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
WiredHome 0:49245357cd1b 13 #define DBG(x, ...) std::printf("[DBG %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 0:49245357cd1b 14 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 0:49245357cd1b 15 #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 0:49245357cd1b 16 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 0:49245357cd1b 17 #else
WiredHome 0:49245357cd1b 18 #define DBG(x, ...)
WiredHome 0:49245357cd1b 19 #define WARN(x, ...)
WiredHome 0:49245357cd1b 20 #define ERR(x, ...)
WiredHome 0:49245357cd1b 21 #define INFO(x, ...)
WiredHome 0:49245357cd1b 22 #endif
WiredHome 0:49245357cd1b 23
WiredHome 0:49245357cd1b 24 Event_T EventList[EVENT_COUNT];
WiredHome 0:49245357cd1b 25 int EventCount = 0;
WiredHome 0:49245357cd1b 26
WiredHome 0:49245357cd1b 27
WiredHome 0:49245357cd1b 28 const char * RPT_DAYS[] = { "SU", "MO", "TU", "WE", "TH", "FR", "SA", "" };
WiredHome 0:49245357cd1b 29
WiredHome 0:49245357cd1b 30 int GetNumEvents(void)
WiredHome 0:49245357cd1b 31 {
WiredHome 0:49245357cd1b 32 return EventCount;
WiredHome 0:49245357cd1b 33 }
WiredHome 0:49245357cd1b 34
WiredHome 0:49245357cd1b 35 const char * RepeatDayAbbrev(int i)
WiredHome 0:49245357cd1b 36 {
WiredHome 0:49245357cd1b 37 if (i < 7)
WiredHome 0:49245357cd1b 38 return RPT_DAYS[i];
WiredHome 0:49245357cd1b 39 else
WiredHome 0:49245357cd1b 40 return RPT_DAYS[7];
WiredHome 0:49245357cd1b 41 }
WiredHome 0:49245357cd1b 42
WiredHome 0:49245357cd1b 43 void SortEvents()
WiredHome 0:49245357cd1b 44 {
WiredHome 0:49245357cd1b 45 bool swapped;
WiredHome 0:49245357cd1b 46 int e;
WiredHome 0:49245357cd1b 47 Event_T Event;
WiredHome 0:49245357cd1b 48
WiredHome 0:49245357cd1b 49 do {
WiredHome 0:49245357cd1b 50 swapped = false;
WiredHome 0:49245357cd1b 51 for (e=0; e<EventCount-1; e++) {
WiredHome 0:49245357cd1b 52 if (EventList[e].Start > EventList[e+1].Start) {
WiredHome 0:49245357cd1b 53 Event = EventList[e];
WiredHome 0:49245357cd1b 54 EventList[e] = EventList[e+1];
WiredHome 0:49245357cd1b 55 EventList[e+1] = Event;
WiredHome 0:49245357cd1b 56 swapped = true;
WiredHome 0:49245357cd1b 57 }
WiredHome 0:49245357cd1b 58 }
WiredHome 0:49245357cd1b 59 } while (swapped);
WiredHome 0:49245357cd1b 60 }
WiredHome 0:49245357cd1b 61
WiredHome 0:49245357cd1b 62 uint16_t AtoIxN(char * p, int n)
WiredHome 0:49245357cd1b 63 {
WiredHome 0:49245357cd1b 64 uint16_t res = 0;
WiredHome 0:49245357cd1b 65
WiredHome 0:49245357cd1b 66 while (n--) {
WiredHome 0:49245357cd1b 67 res = (res * 10) + (*p - '0');
WiredHome 0:49245357cd1b 68 p++;
WiredHome 0:49245357cd1b 69 }
WiredHome 0:49245357cd1b 70 return res;
WiredHome 0:49245357cd1b 71 }
WiredHome 0:49245357cd1b 72
WiredHome 1:db274b9e40cc 73 time_t ParseDateStamp(char * string, int32_t tzoSec)
WiredHome 0:49245357cd1b 74 {
WiredHome 0:49245357cd1b 75 time_t tStamp;
WiredHome 0:49245357cd1b 76 struct tm t;
WiredHome 2:1f5dbc624b95 77 INFO("ParseDateStamp(%s,%d)\r\n", string, tzoSec);
WiredHome 0:49245357cd1b 78 t.tm_year = AtoIxN(string, 4) - 1900;
WiredHome 0:49245357cd1b 79 t.tm_mon = AtoIxN(string+4, 2) - 1;
WiredHome 0:49245357cd1b 80 t.tm_mday = AtoIxN(string+6, 2);
WiredHome 0:49245357cd1b 81 t.tm_hour = AtoIxN(string+9, 2);
WiredHome 0:49245357cd1b 82 t.tm_min = AtoIxN(string+11, 2);
WiredHome 0:49245357cd1b 83 t.tm_sec = AtoIxN(string+13, 2);
WiredHome 0:49245357cd1b 84 tStamp = mktime(&t);
WiredHome 2:1f5dbc624b95 85 if (string[strlen(string)-1] == 'Z') {
WiredHome 2:1f5dbc624b95 86 INFO("Applying tzoSec %d", tzoSec);
WiredHome 1:db274b9e40cc 87 tStamp = tStamp + tzoSec;
WiredHome 2:1f5dbc624b95 88 }
WiredHome 0:49245357cd1b 89 return tStamp;
WiredHome 0:49245357cd1b 90 //int tm_sec //seconds after the minute – [0, 60][@1] (public member object)
WiredHome 0:49245357cd1b 91 //int tm_min //minutes after the hour – [0, 59] (public member object)
WiredHome 0:49245357cd1b 92 //int tm_hour //hours since midnight – [0, 23] (public member object)
WiredHome 0:49245357cd1b 93 //int tm_mday //day of the month – [1, 31] (public member object)
WiredHome 0:49245357cd1b 94 //int tm_mon //months since January – [0, 11] (public member object)
WiredHome 0:49245357cd1b 95 //int tm_year //years since 1900 (public member object)
WiredHome 0:49245357cd1b 96 //int tm_wday //days since Sunday – [0, 6] (public member object)
WiredHome 0:49245357cd1b 97 //int tm_yday //days since January 1 – [0, 365]
WiredHome 0:49245357cd1b 98 //int tm_isdst
WiredHome 0:49245357cd1b 99 }
WiredHome 0:49245357cd1b 100
WiredHome 0:49245357cd1b 101 char * FormatCTime(time_t t)
WiredHome 0:49245357cd1b 102 {
WiredHome 0:49245357cd1b 103 static char temp[4][80];
WiredHome 0:49245357cd1b 104 static int i = 0;
WiredHome 2:1f5dbc624b95 105
WiredHome 0:49245357cd1b 106 i &= 3;
WiredHome 0:49245357cd1b 107 strcpy(temp[i], ctime(&t));
WiredHome 0:49245357cd1b 108 temp[i][strlen(temp[i])-1] = '\0';
WiredHome 0:49245357cd1b 109 return temp[i++];
WiredHome 0:49245357cd1b 110 }
WiredHome 0:49245357cd1b 111
WiredHome 0:49245357cd1b 112
WiredHome 0:49245357cd1b 113 void ShowEventInfo(Event_T & Event)
WiredHome 0:49245357cd1b 114 {
WiredHome 0:49245357cd1b 115 char temp[80];
WiredHome 2:1f5dbc624b95 116
WiredHome 0:49245357cd1b 117 INFO("*** Summary: %s", Event.Summary);
WiredHome 0:49245357cd1b 118 strcpy(temp, ctime(&Event.Start));
WiredHome 0:49245357cd1b 119 temp[strlen(temp)-1] = '\0';
WiredHome 0:49245357cd1b 120 INFO(" Start: %d %s", Event.Start, temp);
WiredHome 0:49245357cd1b 121 strcpy(temp, ctime(&Event.End));
WiredHome 0:49245357cd1b 122 temp[strlen(temp)-1] = '\0';
WiredHome 0:49245357cd1b 123 INFO(" End: %d %s", Event.End, temp );
WiredHome 0:49245357cd1b 124 INFO(" Count: %d", Event.Count);
WiredHome 0:49245357cd1b 125 INFO(" RepeatFrq: %d", Event.RepeatFreq);
WiredHome 0:49245357cd1b 126 INFO(" RepeatDay: %02X", Event.RepeatDays);
WiredHome 0:49245357cd1b 127 strcpy(temp, ctime(&Event.Until));
WiredHome 0:49245357cd1b 128 temp[strlen(temp)-1] = '\0';
WiredHome 0:49245357cd1b 129 INFO(" Until: %d %s", Event.Until, temp);
WiredHome 0:49245357cd1b 130 INFO(" Location: %s", Event.Location);
WiredHome 0:49245357cd1b 131 INFO(" Category: %s", Event.Category);
WiredHome 0:49245357cd1b 132 INFO(" Priority: %d", Event.Priority);
WiredHome 0:49245357cd1b 133 }
WiredHome 0:49245357cd1b 134
WiredHome 0:49245357cd1b 135
WiredHome 0:49245357cd1b 136 /// Computes the intersection of time1 and time2 ranges, and modifies time1
WiredHome 0:49245357cd1b 137 /// range to represent the intersection.
WiredHome 0:49245357cd1b 138 ///
WiredHome 0:49245357cd1b 139 /// @param start1 is input as the start of the time1 range, and is written
WiredHome 0:49245357cd1b 140 /// to represent the intersection of the two ranges.
WiredHome 0:49245357cd1b 141 /// @param end1 is input as the end of the time1 range and is written to
WiredHome 0:49245357cd1b 142 /// represent the intersection of the two ranges.
WiredHome 0:49245357cd1b 143 /// @param start2 is the start of the time2 range.
WiredHome 0:49245357cd1b 144 /// @param end2 is the end of the time2 range.
WiredHome 0:49245357cd1b 145 /// @returns true if the ranges have an intersection, and the time1 range
WiredHome 0:49245357cd1b 146 /// values have been modified.
WiredHome 0:49245357cd1b 147 ///
WiredHome 0:49245357cd1b 148 bool TimeIntersects(time_t * start1, time_t * end1, time_t * start2, time_t * end2)
WiredHome 0:49245357cd1b 149 {
WiredHome 0:49245357cd1b 150 // |----Time1----|
WiredHome 0:49245357cd1b 151 // |--Time2--| false
WiredHome 0:49245357cd1b 152 //
WiredHome 0:49245357cd1b 153 // |----Time1----|
WiredHome 0:49245357cd1b 154 // |--Time2--| false
WiredHome 0:49245357cd1b 155 //
WiredHome 0:49245357cd1b 156 // |----Time1----|
WiredHome 0:49245357cd1b 157 // |----Time2----|
WiredHome 0:49245357cd1b 158 // |-Time1-| true
WiredHome 0:49245357cd1b 159 //
WiredHome 0:49245357cd1b 160 // |----Time1----|
WiredHome 0:49245357cd1b 161 // |----Time2----|
WiredHome 0:49245357cd1b 162 // |-Time1-| true
WiredHome 0:49245357cd1b 163 //
WiredHome 0:49245357cd1b 164 // |----Time1-------|
WiredHome 0:49245357cd1b 165 // |-Time2-|
WiredHome 0:49245357cd1b 166 // |-Time1-| true
WiredHome 0:49245357cd1b 167 //
WiredHome 0:49245357cd1b 168 if (*end1 < *start2 || *end2 < *start1)
WiredHome 0:49245357cd1b 169 return false;
WiredHome 0:49245357cd1b 170 if (max(*start1,*start2) < min(*end1,*end2)) {
WiredHome 0:49245357cd1b 171 *start1 = max(*start1,*start2);
WiredHome 0:49245357cd1b 172 *end1 = min(*end1,*end2);
WiredHome 0:49245357cd1b 173 return true;
WiredHome 0:49245357cd1b 174 } else {
WiredHome 0:49245357cd1b 175 return false;
WiredHome 0:49245357cd1b 176 }
WiredHome 0:49245357cd1b 177 }
WiredHome 0:49245357cd1b 178
WiredHome 0:49245357cd1b 179 time_t NextInterval(int repeatFreq, int interval)
WiredHome 0:49245357cd1b 180 {
WiredHome 2:1f5dbc624b95 181 const time_t secperday = 60*60*24;
WiredHome 2:1f5dbc624b95 182 const int repeatFactor[] = {0, 1, 7, 30, 365};
WiredHome 0:49245357cd1b 183 INFO("freq %d, interval %d", repeatFreq, interval);
WiredHome 0:49245357cd1b 184 return repeatFactor[repeatFreq-1] * interval * secperday;
WiredHome 0:49245357cd1b 185 }
WiredHome 0:49245357cd1b 186
WiredHome 2:1f5dbc624b95 187
WiredHome 2:1f5dbc624b95 188 // start1,end1 is the time range representing the visible grid
WiredHome 2:1f5dbc624b95 189 // start2,end2 is the time range of the event being tested
WiredHome 2:1f5dbc624b95 190 // Event is also the event being tested and permits testing the repeat information.
WiredHome 2:1f5dbc624b95 191 //
WiredHome 2:1f5dbc624b95 192 // If the event repeat pattern intersects with the display pattern, indicate this as "true"
WiredHome 2:1f5dbc624b95 193 //
WiredHome 2:1f5dbc624b95 194 bool RepeatMaskIntersects(time_t * start1, time_t * end1, time_t * start2, time_t * end2, Event_T & Event)
WiredHome 2:1f5dbc624b95 195 {
WiredHome 2:1f5dbc624b95 196 bool intersects = false;
WiredHome 2:1f5dbc624b95 197
WiredHome 2:1f5dbc624b95 198 if (Event.RepeatFreq == rptfWeekly) {
WiredHome 2:1f5dbc624b95 199 struct tm * timeinfo;
WiredHome 2:1f5dbc624b95 200 timeinfo = localtime(start1);
WiredHome 2:1f5dbc624b95 201 uint8_t daymask = Event.RepeatDays;
WiredHome 2:1f5dbc624b95 202 // now, check the tm_wday (0=Sunday, 1=Monday, ...) and see if we intersect with the event time
WiredHome 2:1f5dbc624b95 203 uint8_t testmask = 1 << timeinfo->tm_wday;
WiredHome 2:1f5dbc624b95 204 //INFO("Mask: Event mask: %02X, test mask: %02X", daymask, testmask);
WiredHome 2:1f5dbc624b95 205 if (daymask & testmask)
WiredHome 2:1f5dbc624b95 206 intersects = true;
WiredHome 2:1f5dbc624b95 207 else
WiredHome 2:1f5dbc624b95 208 intersects = false;
WiredHome 2:1f5dbc624b95 209 //INFO(" intersects: %02X", daymask & testmask);
WiredHome 2:1f5dbc624b95 210 return intersects;
WiredHome 2:1f5dbc624b95 211 }
WiredHome 2:1f5dbc624b95 212 //INFO("Mask: no handler, returning true");
WiredHome 2:1f5dbc624b95 213 return true;
WiredHome 2:1f5dbc624b95 214 }
WiredHome 2:1f5dbc624b95 215
WiredHome 0:49245357cd1b 216 bool RepeatIntersects(time_t * start1, time_t * end1, time_t * start2, time_t * end2, Event_T & Event)
WiredHome 0:49245357cd1b 217 {
WiredHome 0:49245357cd1b 218 if (Event.RepeatFreq) {
WiredHome 2:1f5dbc624b95 219 INFO("Summary: %s", Event.Summary);
WiredHome 0:49245357cd1b 220 INFO("** 1: (%s, %s)", FormatCTime(*start1), FormatCTime(*end1));
WiredHome 0:49245357cd1b 221 INFO(" 2: (%s, %s)", FormatCTime(*start2), FormatCTime(*end2));
WiredHome 0:49245357cd1b 222 if (TimeIntersects(start1, end1, start2, end2)) {
WiredHome 0:49245357cd1b 223 return true;
WiredHome 0:49245357cd1b 224 } else if (Event.Start < *start2 && Event.Until > *start2 ) { // Until=....
WiredHome 0:49245357cd1b 225 do {
WiredHome 0:49245357cd1b 226 time_t interval = NextInterval(Event.RepeatFreq, (Event.Interval == 0) ? 1 : Event.Interval);
WiredHome 0:49245357cd1b 227 *start1 = *start1 + interval;
WiredHome 0:49245357cd1b 228 *end1 = *end1 + interval;
WiredHome 0:49245357cd1b 229 INFO("** 1: (%s, %s)", FormatCTime(*start1), FormatCTime(*end1));
WiredHome 0:49245357cd1b 230 INFO("until (%24s, %s)", " ", FormatCTime(Event.Until));
WiredHome 0:49245357cd1b 231 INFO(" 2: (%s, %s)", FormatCTime(*start2), FormatCTime(*end2));
WiredHome 2:1f5dbc624b95 232 if (!RepeatMaskIntersects(start1, end1, start2, end2, Event)) {
WiredHome 2:1f5dbc624b95 233 continue; // we're not on a repeat cycle (e.g. wrong day of the week)
WiredHome 2:1f5dbc624b95 234 }
WiredHome 0:49245357cd1b 235 if (TimeIntersects(start1, end1, start2, end2)) {
WiredHome 0:49245357cd1b 236 return true;
WiredHome 0:49245357cd1b 237 }
WiredHome 2:1f5dbc624b95 238 } while (*start1 < *end2 && *start1 < Event.Until);
WiredHome 0:49245357cd1b 239 } else if (Event.Start < *start2 && Event.Count) { // Count=
WiredHome 0:49245357cd1b 240 int count = Event.Count - 1;
WiredHome 0:49245357cd1b 241 do {
WiredHome 0:49245357cd1b 242 time_t interval = NextInterval(Event.RepeatFreq, (Event.Interval == 0) ? 1 : Event.Interval);
WiredHome 0:49245357cd1b 243 *start1 = *start1 + interval;
WiredHome 0:49245357cd1b 244 *end1 = *end1 + interval;
WiredHome 0:49245357cd1b 245 INFO("** 1: (%s, %s) - %d", FormatCTime(*start1), FormatCTime(*end1), count);
WiredHome 0:49245357cd1b 246 INFO(" 2: (%s, %s)", FormatCTime(*start2), FormatCTime(*end2));
WiredHome 2:1f5dbc624b95 247 if (!RepeatMaskIntersects(start1, end1, start2, end2, Event)) {
WiredHome 2:1f5dbc624b95 248 continue; // we're not on a repeat cycle (e.g. wrong day of the week)
WiredHome 2:1f5dbc624b95 249 }
WiredHome 0:49245357cd1b 250 if (TimeIntersects(start1, end1, start2, end2)) {
WiredHome 0:49245357cd1b 251 return true;
WiredHome 0:49245357cd1b 252 }
WiredHome 2:1f5dbc624b95 253 } while (--count);
WiredHome 0:49245357cd1b 254 } else if (Event.Start < *start2) { // no Count= and no Until=
WiredHome 0:49245357cd1b 255 do {
WiredHome 0:49245357cd1b 256 time_t interval = NextInterval(Event.RepeatFreq, (Event.Interval == 0) ? 1 : Event.Interval);
WiredHome 0:49245357cd1b 257 *start1 = *start1 + interval;
WiredHome 0:49245357cd1b 258 *end1 = *end1 + interval;
WiredHome 0:49245357cd1b 259 INFO("== 1: (%s, %s)", FormatCTime(*start1), FormatCTime(*end1));
WiredHome 0:49245357cd1b 260 INFO(" 2: (%s, %s)", FormatCTime(*start2), FormatCTime(*end2));
WiredHome 2:1f5dbc624b95 261 if (!RepeatMaskIntersects(start1, end1, start2, end2, Event)) {
WiredHome 2:1f5dbc624b95 262 continue; // we're not on a repeat cycle (e.g. wrong day of the week)
WiredHome 2:1f5dbc624b95 263 }
WiredHome 0:49245357cd1b 264 if (TimeIntersects(start1, end1, start2, end2)) {
WiredHome 0:49245357cd1b 265 return true;
WiredHome 0:49245357cd1b 266 }
WiredHome 0:49245357cd1b 267 } while (*start1 < *end2);
WiredHome 0:49245357cd1b 268 }
WiredHome 0:49245357cd1b 269 }
WiredHome 2:1f5dbc624b95 270 //INFO(" no intersection");
WiredHome 0:49245357cd1b 271 return false;
WiredHome 0:49245357cd1b 272 }
WiredHome 0:49245357cd1b 273
WiredHome 2:1f5dbc624b95 274 // All the stuff between
WiredHome 2:1f5dbc624b95 275 // BEGIN:VEVENT
WiredHome 2:1f5dbc624b95 276 // ...
WiredHome 2:1f5dbc624b95 277 // END:VEVENT
WiredHome 2:1f5dbc624b95 278 //
WiredHome 2:1f5dbc624b95 279 void ParseEvent(Event_T * Event, char * pStart, int32_t tzoSec)
WiredHome 2:1f5dbc624b95 280 {
WiredHome 2:1f5dbc624b95 281 if (strncmp(pStart, "DTSTART:", 8) == 0) {
WiredHome 2:1f5dbc624b95 282 Event->Start = ParseDateStamp(pStart+8, tzoSec);
WiredHome 2:1f5dbc624b95 283 //INFO(" Start: %d\r\n", mktime(&Event->eventStart));
WiredHome 2:1f5dbc624b95 284 } else if (strncmp(pStart, "DTSTART;", 8) == 0) {
WiredHome 2:1f5dbc624b95 285 char * p = strrchr(pStart, ':');
WiredHome 2:1f5dbc624b95 286 if (p) {
WiredHome 2:1f5dbc624b95 287 Event->Start = ParseDateStamp(p+1, tzoSec);
WiredHome 2:1f5dbc624b95 288 //INFO(" Start: %d\r\n", mktime(&Event->eventStart));
WiredHome 2:1f5dbc624b95 289 }
WiredHome 2:1f5dbc624b95 290 } else if (strncmp(pStart, "DTEND:", 6) == 0) {
WiredHome 2:1f5dbc624b95 291 Event->End = ParseDateStamp(pStart+6, tzoSec);
WiredHome 2:1f5dbc624b95 292 //INFO(" End: %d\r\n", mktime(&Event->eventEnd));
WiredHome 2:1f5dbc624b95 293 } else if (strncmp(pStart, "DTEND;", 6) == 0) {
WiredHome 2:1f5dbc624b95 294 char * p = strrchr(pStart, ':');
WiredHome 2:1f5dbc624b95 295 if (p) {
WiredHome 2:1f5dbc624b95 296 Event->End = ParseDateStamp(p+1, tzoSec);
WiredHome 2:1f5dbc624b95 297 //INFO(" End: %d\r\n", mktime(&Event->eventEnd));
WiredHome 2:1f5dbc624b95 298 }
WiredHome 2:1f5dbc624b95 299 } else if (strncmp(pStart, "SUMMARY:", 8) == 0) {
WiredHome 2:1f5dbc624b95 300 strncpy(Event->Summary, pStart+8, SUMMARY_CHARS-1);
WiredHome 2:1f5dbc624b95 301 Event->Summary[SUMMARY_CHARS-1] = '\0';
WiredHome 2:1f5dbc624b95 302 //INFO(" Summary: %s\r\n", Event->Summary);
WiredHome 2:1f5dbc624b95 303 } else if (strncmp(pStart, "LOCATION:", 9) == 0) {
WiredHome 2:1f5dbc624b95 304 strncpy(Event->Location, pStart+9, LOCATION_CHARS-1);
WiredHome 2:1f5dbc624b95 305 Event->Location[LOCATION_CHARS-1] = '\0';
WiredHome 2:1f5dbc624b95 306 //INFO(" Location: %s\r\n", Event->Location);
WiredHome 2:1f5dbc624b95 307 } else if (strncmp(pStart, "PRIORITY:", 9) == 0) {
WiredHome 2:1f5dbc624b95 308 Event->Priority = *(pStart+9) - '0';
WiredHome 2:1f5dbc624b95 309 //INFO(" Priority: %d\r\n", Event->Priority);
WiredHome 2:1f5dbc624b95 310 } else if (strncmp(pStart, "CATEGORIES:", 11) == 0) {
WiredHome 2:1f5dbc624b95 311 strncpy(Event->Category, pStart+11, CATEGORY_CHARS-1);
WiredHome 2:1f5dbc624b95 312 Event->Category[CATEGORY_CHARS-1] = '\0';
WiredHome 2:1f5dbc624b95 313 //INFO(" Category: %s\r\n", Event->Category);
WiredHome 2:1f5dbc624b95 314 } else if (strncmp(pStart, "RRULE:", 6) == 0) {
WiredHome 2:1f5dbc624b95 315 //RRULE:FREQ=WEEKLY;UNTIL=20140502T180000;BYDAY=MO,TU,WE,TH,FR
WiredHome 2:1f5dbc624b95 316 char * p1, *p2;
WiredHome 2:1f5dbc624b95 317 //INFO("%s", pStart);
WiredHome 2:1f5dbc624b95 318 p1 = pStart + 6; // p1 = FREQ=WEEKLY;UNTIL=20140502T180000;BYDAY=MO,TU,WE,TH,FR
WiredHome 2:1f5dbc624b95 319 p2 = strchr(p1, ';');
WiredHome 2:1f5dbc624b95 320 if (p2)
WiredHome 2:1f5dbc624b95 321 *p2++ = '\0';
WiredHome 2:1f5dbc624b95 322 while (*p1) {
WiredHome 2:1f5dbc624b95 323 //INFO("%s", p1);
WiredHome 2:1f5dbc624b95 324 if (strncmp(p1, "FREQ=", 5) == 0) {
WiredHome 2:1f5dbc624b95 325 //INFO("%s", p1);
WiredHome 2:1f5dbc624b95 326 p1 += 5; // p1 = WEEKLY;UNTIL=20140502T180000;BYDAY=MO,TU,WE,TH,FR
WiredHome 2:1f5dbc624b95 327 if (strncmp(p1, "WEEKLY", 6) == 0) {
WiredHome 2:1f5dbc624b95 328 //INFO(" %s", p1);
WiredHome 2:1f5dbc624b95 329 Event->RepeatFreq = rptfWeekly;
WiredHome 2:1f5dbc624b95 330 p1 += 6;
WiredHome 2:1f5dbc624b95 331 } else if (strncmp(p1, "DAILY", 5) == 0) {
WiredHome 2:1f5dbc624b95 332 //INFO(" %s", p1);
WiredHome 2:1f5dbc624b95 333 Event->RepeatFreq = rptfDaily;
WiredHome 2:1f5dbc624b95 334 p1 += 5;
WiredHome 2:1f5dbc624b95 335 } else if (strncmp(p1, "MONTHLY", 7) == 0) {
WiredHome 2:1f5dbc624b95 336 //INFO(" %s", p1);
WiredHome 2:1f5dbc624b95 337 Event->RepeatFreq = rptfMonthly;
WiredHome 2:1f5dbc624b95 338 p1 += 7;
WiredHome 2:1f5dbc624b95 339 } else if (strncmp(p1, "YEARLY", 6) == 0) {
WiredHome 2:1f5dbc624b95 340 //INFO(" %s", p1);
WiredHome 2:1f5dbc624b95 341 Event->RepeatFreq = rptfYearly;
WiredHome 2:1f5dbc624b95 342 p1 += 7;
WiredHome 2:1f5dbc624b95 343 }
WiredHome 2:1f5dbc624b95 344 } else if (strncmp(p1, "INTERVAL=", 9) == 0) { // INTERVAL=2
WiredHome 2:1f5dbc624b95 345 //INFO("%s", p1);
WiredHome 2:1f5dbc624b95 346 p1 += 9;
WiredHome 2:1f5dbc624b95 347 Event->Interval = atoi(p1);
WiredHome 2:1f5dbc624b95 348 } else if (strncmp(p1, "COUNT=", 6) == 0) { // COUNT=12;
WiredHome 2:1f5dbc624b95 349 //INFO("%s", p1);
WiredHome 2:1f5dbc624b95 350 p1 += 6; // p1 =
WiredHome 2:1f5dbc624b95 351 Event->Count = atoi(p1);
WiredHome 2:1f5dbc624b95 352 } else if (strncmp(p1, "UNTIL=", 6) == 0) {
WiredHome 2:1f5dbc624b95 353 //INFO("%s", p1);
WiredHome 2:1f5dbc624b95 354 p1 += 6; // p1 = 20140502T180000;BYDAY=MO,TU,WE,TH,FR
WiredHome 2:1f5dbc624b95 355 Event->Until = ParseDateStamp(p1, tzoSec);
WiredHome 2:1f5dbc624b95 356 } else if (strncmp(p1, "BYDAY=", 6) == 0) {
WiredHome 2:1f5dbc624b95 357 //INFO("%s", p1);
WiredHome 2:1f5dbc624b95 358 p1 += 6; // p1 = MO,TU,WE,TH,FR
WiredHome 2:1f5dbc624b95 359 while (*p1 >= ' ') {
WiredHome 2:1f5dbc624b95 360 //INFO(" %s", p1);
WiredHome 2:1f5dbc624b95 361 for (int d=0; d<7; d++) {
WiredHome 2:1f5dbc624b95 362 if (strncmp(p1,RepeatDayAbbrev(d),2) == 0) {
WiredHome 2:1f5dbc624b95 363 Event->RepeatDays |= (1 << d);
WiredHome 2:1f5dbc624b95 364 //INFO(" %s %02X", RepeatDayAbbrev(d), Event->RepeatDays);
WiredHome 2:1f5dbc624b95 365 break;
WiredHome 2:1f5dbc624b95 366 }
WiredHome 2:1f5dbc624b95 367 }
WiredHome 2:1f5dbc624b95 368 p1 += 3;
WiredHome 2:1f5dbc624b95 369 }
WiredHome 2:1f5dbc624b95 370 //INFO(" RepeatDay: %02X", Event->RepeatDays);
WiredHome 2:1f5dbc624b95 371 }
WiredHome 2:1f5dbc624b95 372 if (!p2)
WiredHome 2:1f5dbc624b95 373 break;
WiredHome 2:1f5dbc624b95 374 p1 = p2;
WiredHome 2:1f5dbc624b95 375 p2 = strchr(p1, ';');
WiredHome 2:1f5dbc624b95 376 if (p2)
WiredHome 2:1f5dbc624b95 377 *p2++ = '\0';
WiredHome 2:1f5dbc624b95 378 }
WiredHome 2:1f5dbc624b95 379 }
WiredHome 2:1f5dbc624b95 380 }
WiredHome 0:49245357cd1b 381
WiredHome 1:db274b9e40cc 382 void ParseICalStream(char * pStart, time_t gridStartTime, time_t gridEndTime, int32_t tzoSec)
WiredHome 0:49245357cd1b 383 {
WiredHome 0:49245357cd1b 384 Event_T Event;
WiredHome 0:49245357cd1b 385 bool tzAdjusted = false;
WiredHome 0:49245357cd1b 386 char * pEnd;
WiredHome 0:49245357cd1b 387 typedef enum { idle, inTimeZone, inEvent } seekstate_t;
WiredHome 0:49245357cd1b 388 seekstate_t seeking = idle;
WiredHome 0:49245357cd1b 389 EventCount = 0;
WiredHome 2:1f5dbc624b95 390
WiredHome 0:49245357cd1b 391 while (pStart && EventCount < EVENT_COUNT) {
WiredHome 0:49245357cd1b 392 pEnd = strchr(pStart, '\n');
WiredHome 0:49245357cd1b 393 if (pEnd) {
WiredHome 0:49245357cd1b 394 if (*(pEnd-1) == '\r')
WiredHome 0:49245357cd1b 395 pEnd--;
WiredHome 0:49245357cd1b 396 *pEnd++ = '\0';
WiredHome 0:49245357cd1b 397 while (*pEnd && *pEnd < ' ') {
WiredHome 0:49245357cd1b 398 pEnd++;
WiredHome 0:49245357cd1b 399 }
WiredHome 0:49245357cd1b 400 // pStart now has a single null terminated line of text.
WiredHome 0:49245357cd1b 401 //INFO("*** %s", pStart);
WiredHome 0:49245357cd1b 402 switch (seeking) {
WiredHome 0:49245357cd1b 403 case idle:
WiredHome 0:49245357cd1b 404 if (strcmp(pStart, "BEGIN:VTIMEZONE") == 0)
WiredHome 0:49245357cd1b 405 seeking = inTimeZone;
WiredHome 0:49245357cd1b 406 else if (strcmp(pStart, "BEGIN:VEVENT") == 0) {
WiredHome 0:49245357cd1b 407 seeking = inEvent;
WiredHome 0:49245357cd1b 408 Event.Start = 0;
WiredHome 0:49245357cd1b 409 Event.End = 0;
WiredHome 0:49245357cd1b 410 Event.Until = 0;
WiredHome 0:49245357cd1b 411 Event.Summary[0] = '\0';
WiredHome 0:49245357cd1b 412 Event.Location[0] = '\0';
WiredHome 0:49245357cd1b 413 Event.Category[0] = '\0';
WiredHome 0:49245357cd1b 414 Event.Count = 0;
WiredHome 0:49245357cd1b 415 Event.Interval = 0;
WiredHome 0:49245357cd1b 416 Event.RepeatFreq = rptfNone;
WiredHome 0:49245357cd1b 417 Event.RepeatDays = 0;
WiredHome 0:49245357cd1b 418 Event.Priority = 5; // 5 is Normal
WiredHome 0:49245357cd1b 419 //ShowEventInfo(Event, pc);
WiredHome 0:49245357cd1b 420 }
WiredHome 0:49245357cd1b 421 break;
WiredHome 0:49245357cd1b 422 case inTimeZone:
WiredHome 0:49245357cd1b 423 // Can also pick up daylight savings time
WiredHome 0:49245357cd1b 424 if (strcmp(pStart, "END:VTIMEZONE") == 0)
WiredHome 0:49245357cd1b 425 seeking = idle;
WiredHome 0:49245357cd1b 426 else if (strncmp(pStart, "TZID", 4) == 0)
WiredHome 0:49245357cd1b 427 tzAdjusted = true;
WiredHome 0:49245357cd1b 428 break;
WiredHome 0:49245357cd1b 429 case inEvent:
WiredHome 0:49245357cd1b 430 // inEvent
WiredHome 0:49245357cd1b 431 if (strcmp(pStart, "END:VEVENT") == 0) {
WiredHome 0:49245357cd1b 432 // Timezone offset
WiredHome 0:49245357cd1b 433 if (!tzAdjusted) {
WiredHome 1:db274b9e40cc 434 Event.Start += tzoSec;
WiredHome 1:db274b9e40cc 435 Event.End += tzoSec;
WiredHome 0:49245357cd1b 436 }
WiredHome 0:49245357cd1b 437 // Process it
WiredHome 0:49245357cd1b 438 ShowEventInfo(Event);
WiredHome 0:49245357cd1b 439 if (1 || Event.Start >= gridStartTime && Event.Start < gridEndTime
WiredHome 0:49245357cd1b 440 || Event.End >= gridStartTime && Event.End < gridEndTime) {
WiredHome 0:49245357cd1b 441 EventList[EventCount++] = Event;
WiredHome 2:1f5dbc624b95 442 INFO(" ++++++++++++ Added Event %d: %s", EventCount, Event.Summary);
WiredHome 0:49245357cd1b 443 }
WiredHome 0:49245357cd1b 444 seeking = idle;
WiredHome 2:1f5dbc624b95 445 } else {
WiredHome 2:1f5dbc624b95 446 ParseEvent(&Event, pStart, tzoSec);
WiredHome 2:1f5dbc624b95 447 }
WiredHome 0:49245357cd1b 448 // End of inEvent
WiredHome 0:49245357cd1b 449 break;
WiredHome 0:49245357cd1b 450 default:
WiredHome 0:49245357cd1b 451 seeking = idle;
WiredHome 0:49245357cd1b 452 break;
WiredHome 0:49245357cd1b 453 }
WiredHome 0:49245357cd1b 454 pStart = pEnd;
WiredHome 0:49245357cd1b 455 } else {
WiredHome 0:49245357cd1b 456 pStart = NULL;
WiredHome 0:49245357cd1b 457 }
WiredHome 0:49245357cd1b 458 } // while
WiredHome 0:49245357cd1b 459 }