an iCal processing library

Committer:
WiredHome
Date:
Sun Jun 08 01:35:37 2014 +0000
Revision:
4:a1c25d936346
Parent:
2:1f5dbc624b95
Child:
5:69577415c16e
Cleaned up debugging interface.

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 4:a1c25d936346 6 //#include "stdafx.h"
WiredHome 4:a1c25d936346 7 //#pragma warning (disable: 4996)
WiredHome 0:49245357cd1b 8
WiredHome 0:49245357cd1b 9 #include "iCal.h"
WiredHome 0:49245357cd1b 10 #include <algorithm>
WiredHome 0:49245357cd1b 11
WiredHome 4:a1c25d936346 12 #ifdef _DEBUG
WiredHome 2:1f5dbc624b95 13 #define DEBUG "iCal"
WiredHome 4:a1c25d936346 14 #endif
WiredHome 4:a1c25d936346 15 #ifdef WIN32
WiredHome 4:a1c25d936346 16 #define LF "\n"
WiredHome 4:a1c25d936346 17 #else
WiredHome 4:a1c25d936346 18 #define LF "\r\n"
WiredHome 4:a1c25d936346 19 #endif
WiredHome 0:49245357cd1b 20 #include <cstdio>
WiredHome 0:49245357cd1b 21 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
WiredHome 4:a1c25d936346 22 #define DBG(x, ...) std::printf("[DBG %s %3d] " x LF, DEBUG, __LINE__, ##__VA_ARGS__)
WiredHome 4:a1c25d936346 23 #define WARN(x, ...) std::printf("[WRN %s %3d] " x LF, DEBUG, __LINE__, ##__VA_ARGS__)
WiredHome 4:a1c25d936346 24 #define ERR(x, ...) std::printf("[ERR %s %3d] " x LF, DEBUG, __LINE__, ##__VA_ARGS__)
WiredHome 4:a1c25d936346 25 #define INFO(x, ...) std::printf("[INF %s %3d] " x LF, DEBUG, __LINE__, ##__VA_ARGS__)
WiredHome 0:49245357cd1b 26 #else
WiredHome 0:49245357cd1b 27 #define DBG(x, ...)
WiredHome 0:49245357cd1b 28 #define WARN(x, ...)
WiredHome 0:49245357cd1b 29 #define ERR(x, ...)
WiredHome 0:49245357cd1b 30 #define INFO(x, ...)
WiredHome 0:49245357cd1b 31 #endif
WiredHome 0:49245357cd1b 32
WiredHome 0:49245357cd1b 33 Event_T EventList[EVENT_COUNT];
WiredHome 0:49245357cd1b 34 int EventCount = 0;
WiredHome 4:a1c25d936346 35 int32_t tzoTZIDSec = 0;
WiredHome 0:49245357cd1b 36
WiredHome 0:49245357cd1b 37 const char * RPT_DAYS[] = { "SU", "MO", "TU", "WE", "TH", "FR", "SA", "" };
WiredHome 0:49245357cd1b 38
WiredHome 0:49245357cd1b 39 int GetNumEvents(void)
WiredHome 0:49245357cd1b 40 {
WiredHome 0:49245357cd1b 41 return EventCount;
WiredHome 0:49245357cd1b 42 }
WiredHome 0:49245357cd1b 43
WiredHome 0:49245357cd1b 44 const char * RepeatDayAbbrev(int i)
WiredHome 0:49245357cd1b 45 {
WiredHome 0:49245357cd1b 46 if (i < 7)
WiredHome 0:49245357cd1b 47 return RPT_DAYS[i];
WiredHome 0:49245357cd1b 48 else
WiredHome 0:49245357cd1b 49 return RPT_DAYS[7];
WiredHome 0:49245357cd1b 50 }
WiredHome 0:49245357cd1b 51
WiredHome 0:49245357cd1b 52 void SortEvents()
WiredHome 0:49245357cd1b 53 {
WiredHome 0:49245357cd1b 54 bool swapped;
WiredHome 0:49245357cd1b 55 int e;
WiredHome 0:49245357cd1b 56 Event_T Event;
WiredHome 0:49245357cd1b 57
WiredHome 0:49245357cd1b 58 do {
WiredHome 0:49245357cd1b 59 swapped = false;
WiredHome 0:49245357cd1b 60 for (e=0; e<EventCount-1; e++) {
WiredHome 0:49245357cd1b 61 if (EventList[e].Start > EventList[e+1].Start) {
WiredHome 0:49245357cd1b 62 Event = EventList[e];
WiredHome 0:49245357cd1b 63 EventList[e] = EventList[e+1];
WiredHome 0:49245357cd1b 64 EventList[e+1] = Event;
WiredHome 0:49245357cd1b 65 swapped = true;
WiredHome 0:49245357cd1b 66 }
WiredHome 0:49245357cd1b 67 }
WiredHome 0:49245357cd1b 68 } while (swapped);
WiredHome 0:49245357cd1b 69 }
WiredHome 0:49245357cd1b 70
WiredHome 0:49245357cd1b 71 uint16_t AtoIxN(char * p, int n)
WiredHome 0:49245357cd1b 72 {
WiredHome 0:49245357cd1b 73 uint16_t res = 0;
WiredHome 0:49245357cd1b 74
WiredHome 0:49245357cd1b 75 while (n--) {
WiredHome 0:49245357cd1b 76 res = (res * 10) + (*p - '0');
WiredHome 0:49245357cd1b 77 p++;
WiredHome 0:49245357cd1b 78 }
WiredHome 0:49245357cd1b 79 return res;
WiredHome 0:49245357cd1b 80 }
WiredHome 0:49245357cd1b 81
WiredHome 4:a1c25d936346 82 // YYYYMMDD[THHMMSS[Z]]
WiredHome 1:db274b9e40cc 83 time_t ParseDateStamp(char * string, int32_t tzoSec)
WiredHome 0:49245357cd1b 84 {
WiredHome 0:49245357cd1b 85 time_t tStamp;
WiredHome 0:49245357cd1b 86 struct tm t;
WiredHome 4:a1c25d936346 87 struct tm * tnow;
WiredHome 4:a1c25d936346 88
WiredHome 4:a1c25d936346 89 time(&tStamp);
WiredHome 4:a1c25d936346 90 tnow = localtime(&tStamp);
WiredHome 4:a1c25d936346 91 //INFO("ParseDateStamp(%s,%d)\n", string, tzoSec);
WiredHome 0:49245357cd1b 92 t.tm_year = AtoIxN(string, 4) - 1900;
WiredHome 0:49245357cd1b 93 t.tm_mon = AtoIxN(string+4, 2) - 1;
WiredHome 0:49245357cd1b 94 t.tm_mday = AtoIxN(string+6, 2);
WiredHome 4:a1c25d936346 95 if (strlen(string) > 8) {
WiredHome 4:a1c25d936346 96 t.tm_hour = AtoIxN(string+9, 2);
WiredHome 4:a1c25d936346 97 t.tm_min = AtoIxN(string+11, 2);
WiredHome 4:a1c25d936346 98 t.tm_sec = AtoIxN(string+13, 2);
WiredHome 4:a1c25d936346 99 t.tm_isdst = tnow->tm_isdst;
WiredHome 4:a1c25d936346 100 } else {
WiredHome 4:a1c25d936346 101 t.tm_hour = 0;
WiredHome 4:a1c25d936346 102 t.tm_min = 0;
WiredHome 4:a1c25d936346 103 t.tm_sec = 0;
WiredHome 4:a1c25d936346 104 t.tm_isdst = tnow->tm_isdst;
WiredHome 4:a1c25d936346 105 }
WiredHome 0:49245357cd1b 106 tStamp = mktime(&t);
WiredHome 2:1f5dbc624b95 107 if (string[strlen(string)-1] == 'Z') {
WiredHome 4:a1c25d936346 108 //INFO("Applying tzoSec %d", tzoSec);
WiredHome 4:a1c25d936346 109 tStamp = tStamp + tzoTZIDSec;
WiredHome 4:a1c25d936346 110 } else {
WiredHome 1:db274b9e40cc 111 tStamp = tStamp + tzoSec;
WiredHome 2:1f5dbc624b95 112 }
WiredHome 0:49245357cd1b 113 return tStamp;
WiredHome 0:49245357cd1b 114 //int tm_sec //seconds after the minute – [0, 60][@1] (public member object)
WiredHome 0:49245357cd1b 115 //int tm_min //minutes after the hour – [0, 59] (public member object)
WiredHome 0:49245357cd1b 116 //int tm_hour //hours since midnight – [0, 23] (public member object)
WiredHome 0:49245357cd1b 117 //int tm_mday //day of the month – [1, 31] (public member object)
WiredHome 0:49245357cd1b 118 //int tm_mon //months since January – [0, 11] (public member object)
WiredHome 0:49245357cd1b 119 //int tm_year //years since 1900 (public member object)
WiredHome 0:49245357cd1b 120 //int tm_wday //days since Sunday – [0, 6] (public member object)
WiredHome 0:49245357cd1b 121 //int tm_yday //days since January 1 – [0, 365]
WiredHome 0:49245357cd1b 122 //int tm_isdst
WiredHome 0:49245357cd1b 123 }
WiredHome 0:49245357cd1b 124
WiredHome 0:49245357cd1b 125 char * FormatCTime(time_t t)
WiredHome 0:49245357cd1b 126 {
WiredHome 0:49245357cd1b 127 static char temp[4][80];
WiredHome 0:49245357cd1b 128 static int i = 0;
WiredHome 2:1f5dbc624b95 129
WiredHome 0:49245357cd1b 130 i &= 3;
WiredHome 0:49245357cd1b 131 strcpy(temp[i], ctime(&t));
WiredHome 0:49245357cd1b 132 temp[i][strlen(temp[i])-1] = '\0';
WiredHome 0:49245357cd1b 133 return temp[i++];
WiredHome 0:49245357cd1b 134 }
WiredHome 0:49245357cd1b 135
WiredHome 0:49245357cd1b 136
WiredHome 0:49245357cd1b 137 void ShowEventInfo(Event_T & Event)
WiredHome 0:49245357cd1b 138 {
WiredHome 4:a1c25d936346 139 char scratch[80];
WiredHome 2:1f5dbc624b95 140
WiredHome 4:a1c25d936346 141 printf("******* Summary: %s" LF, Event.Summary);
WiredHome 4:a1c25d936346 142 printf(" Location: %s" LF, Event.Location);
WiredHome 4:a1c25d936346 143 printf(" Category: %s" LF, Event.Category);
WiredHome 4:a1c25d936346 144 printf(" Priority: %d" LF, Event.Priority);
WiredHome 4:a1c25d936346 145 sprintf(scratch, "%d ", Event.Start);
WiredHome 4:a1c25d936346 146 sprintf(scratch + strlen(scratch), "%s", (Event.Start == 0) ? "" : ctime(&Event.Start));
WiredHome 4:a1c25d936346 147 scratch[strlen(scratch)-1] = '\0';
WiredHome 4:a1c25d936346 148 printf(" Start: %s" LF, scratch);
WiredHome 4:a1c25d936346 149 sprintf(scratch, "%d ", Event.End);
WiredHome 4:a1c25d936346 150 sprintf(scratch + strlen(scratch), "%s", (Event.End == 0) ? "" : ctime(&Event.End));
WiredHome 4:a1c25d936346 151 scratch[strlen(scratch)-1] = '\0';
WiredHome 4:a1c25d936346 152 printf(" End: %s" LF, scratch);
WiredHome 4:a1c25d936346 153 printf(" Count: %d" LF, Event.Count);
WiredHome 4:a1c25d936346 154 printf(" Interval: %d" LF, Event.Interval);
WiredHome 4:a1c25d936346 155 printf(" RepeatFrq: %d" LF, Event.RepeatFreq);
WiredHome 4:a1c25d936346 156 printf(" RepeatDay: %02X" LF, Event.RepeatDays);
WiredHome 4:a1c25d936346 157 printf(" RepeatMonthDay: %08X" LF, Event.RepeatMonthDay);
WiredHome 4:a1c25d936346 158 printf(" RepeatMonthDayRev: %08X" LF, Event.RepeatMonthDayRev);
WiredHome 4:a1c25d936346 159 printf(" RepeatMonth: %04X" LF, Event.RepeatMonths);
WiredHome 4:a1c25d936346 160 sprintf(scratch, "%d ", Event.Until);
WiredHome 4:a1c25d936346 161 sprintf(scratch + strlen(scratch), "%s", (Event.Until == 0) ? "" : ctime(&Event.Until));
WiredHome 4:a1c25d936346 162 scratch[strlen(scratch)-1] = '\0';
WiredHome 4:a1c25d936346 163 printf(" Until: %s" LF, scratch);
WiredHome 4:a1c25d936346 164 printf("" LF);
WiredHome 0:49245357cd1b 165 }
WiredHome 0:49245357cd1b 166
WiredHome 0:49245357cd1b 167
WiredHome 0:49245357cd1b 168 /// Computes the intersection of time1 and time2 ranges, and modifies time1
WiredHome 0:49245357cd1b 169 /// range to represent the intersection.
WiredHome 0:49245357cd1b 170 ///
WiredHome 0:49245357cd1b 171 /// @param start1 is input as the start of the time1 range, and is written
WiredHome 0:49245357cd1b 172 /// to represent the intersection of the two ranges.
WiredHome 0:49245357cd1b 173 /// @param end1 is input as the end of the time1 range and is written to
WiredHome 0:49245357cd1b 174 /// represent the intersection of the two ranges.
WiredHome 0:49245357cd1b 175 /// @param start2 is the start of the time2 range.
WiredHome 0:49245357cd1b 176 /// @param end2 is the end of the time2 range.
WiredHome 0:49245357cd1b 177 /// @returns true if the ranges have an intersection, and the time1 range
WiredHome 0:49245357cd1b 178 /// values have been modified.
WiredHome 0:49245357cd1b 179 ///
WiredHome 0:49245357cd1b 180 bool TimeIntersects(time_t * start1, time_t * end1, time_t * start2, time_t * end2)
WiredHome 0:49245357cd1b 181 {
WiredHome 0:49245357cd1b 182 // |----Time1----|
WiredHome 0:49245357cd1b 183 // |--Time2--| false
WiredHome 0:49245357cd1b 184 //
WiredHome 0:49245357cd1b 185 // |----Time1----|
WiredHome 0:49245357cd1b 186 // |--Time2--| false
WiredHome 0:49245357cd1b 187 //
WiredHome 0:49245357cd1b 188 // |----Time1----|
WiredHome 0:49245357cd1b 189 // |----Time2----|
WiredHome 0:49245357cd1b 190 // |-Time1-| true
WiredHome 0:49245357cd1b 191 //
WiredHome 0:49245357cd1b 192 // |----Time1----|
WiredHome 0:49245357cd1b 193 // |----Time2----|
WiredHome 0:49245357cd1b 194 // |-Time1-| true
WiredHome 0:49245357cd1b 195 //
WiredHome 0:49245357cd1b 196 // |----Time1-------|
WiredHome 0:49245357cd1b 197 // |-Time2-|
WiredHome 0:49245357cd1b 198 // |-Time1-| true
WiredHome 0:49245357cd1b 199 //
WiredHome 4:a1c25d936346 200 // | Time1 (end1 == 0)
WiredHome 4:a1c25d936346 201 // | Time2 (end2 == 0) true
WiredHome 4:a1c25d936346 202 //
WiredHome 4:a1c25d936346 203 if (*start1 == *start2 && *end1 == 0 && *end2 == 0)
WiredHome 4:a1c25d936346 204 return true;
WiredHome 0:49245357cd1b 205 if (*end1 < *start2 || *end2 < *start1)
WiredHome 0:49245357cd1b 206 return false;
WiredHome 0:49245357cd1b 207 if (max(*start1,*start2) < min(*end1,*end2)) {
WiredHome 0:49245357cd1b 208 *start1 = max(*start1,*start2);
WiredHome 0:49245357cd1b 209 *end1 = min(*end1,*end2);
WiredHome 0:49245357cd1b 210 return true;
WiredHome 0:49245357cd1b 211 } else {
WiredHome 0:49245357cd1b 212 return false;
WiredHome 0:49245357cd1b 213 }
WiredHome 0:49245357cd1b 214 }
WiredHome 0:49245357cd1b 215
WiredHome 4:a1c25d936346 216 bool isLeapYear(time_t t)
WiredHome 4:a1c25d936346 217 {
WiredHome 4:a1c25d936346 218 int year;
WiredHome 4:a1c25d936346 219 struct tm * ts;
WiredHome 4:a1c25d936346 220 ts = localtime(&t);
WiredHome 4:a1c25d936346 221
WiredHome 4:a1c25d936346 222 year = 1900 + ts->tm_year + 1;
WiredHome 4:a1c25d936346 223 if ((((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0))
WiredHome 4:a1c25d936346 224 return true;
WiredHome 4:a1c25d936346 225 else
WiredHome 4:a1c25d936346 226 return false;
WiredHome 4:a1c25d936346 227 }
WiredHome 4:a1c25d936346 228
WiredHome 4:a1c25d936346 229 time_t NextInterval(time_t curTime, int repeatFreq, int interval)
WiredHome 0:49245357cd1b 230 {
WiredHome 2:1f5dbc624b95 231 const time_t secperday = 60*60*24;
WiredHome 2:1f5dbc624b95 232 const int repeatFactor[] = {0, 1, 7, 30, 365};
WiredHome 4:a1c25d936346 233 int delta = repeatFactor[repeatFreq];
WiredHome 4:a1c25d936346 234 if (repeatFreq == 4 && isLeapYear(curTime))
WiredHome 4:a1c25d936346 235 delta += 1;
WiredHome 4:a1c25d936346 236 INFO("freq %d, interval %d, delta %d", repeatFreq, interval, delta);
WiredHome 4:a1c25d936346 237 return delta * interval * secperday;
WiredHome 0:49245357cd1b 238 }
WiredHome 0:49245357cd1b 239
WiredHome 2:1f5dbc624b95 240
WiredHome 2:1f5dbc624b95 241 // start1,end1 is the time range representing the visible grid
WiredHome 2:1f5dbc624b95 242 // start2,end2 is the time range of the event being tested
WiredHome 2:1f5dbc624b95 243 // Event is also the event being tested and permits testing the repeat information.
WiredHome 2:1f5dbc624b95 244 //
WiredHome 2:1f5dbc624b95 245 // If the event repeat pattern intersects with the display pattern, indicate this as "true"
WiredHome 2:1f5dbc624b95 246 //
WiredHome 4:a1c25d936346 247 bool RepeatMaskIntersects(time_t * start1, time_t * end1, time_t * start2, time_t * end2, Event_T * Event)
WiredHome 2:1f5dbc624b95 248 {
WiredHome 2:1f5dbc624b95 249 bool intersects = false;
WiredHome 2:1f5dbc624b95 250
WiredHome 4:a1c25d936346 251 INFO("RepeatFreq: %d", Event->RepeatFreq);
WiredHome 4:a1c25d936346 252 if (Event->RepeatFreq == rptfDaily) {
WiredHome 4:a1c25d936346 253 INFO("rptfDaily is not handled");
WiredHome 4:a1c25d936346 254 } else if (Event->RepeatFreq == rptfWeekly) {
WiredHome 2:1f5dbc624b95 255 struct tm * timeinfo;
WiredHome 2:1f5dbc624b95 256 timeinfo = localtime(start1);
WiredHome 4:a1c25d936346 257 uint8_t daymask = Event->RepeatDays;
WiredHome 2:1f5dbc624b95 258 // now, check the tm_wday (0=Sunday, 1=Monday, ...) and see if we intersect with the event time
WiredHome 2:1f5dbc624b95 259 uint8_t testmask = 1 << timeinfo->tm_wday;
WiredHome 2:1f5dbc624b95 260 //INFO("Mask: Event mask: %02X, test mask: %02X", daymask, testmask);
WiredHome 2:1f5dbc624b95 261 if (daymask & testmask)
WiredHome 2:1f5dbc624b95 262 intersects = true;
WiredHome 2:1f5dbc624b95 263 else
WiredHome 2:1f5dbc624b95 264 intersects = false;
WiredHome 2:1f5dbc624b95 265 //INFO(" intersects: %02X", daymask & testmask);
WiredHome 2:1f5dbc624b95 266 return intersects;
WiredHome 4:a1c25d936346 267 } else if (Event->RepeatFreq == rptfYearly) {
WiredHome 4:a1c25d936346 268 //struct tm * timeinfo;
WiredHome 4:a1c25d936346 269 //timeinfo = localtime(start1);
WiredHome 4:a1c25d936346 270 INFO("rptfYearly is not handled");
WiredHome 2:1f5dbc624b95 271 }
WiredHome 2:1f5dbc624b95 272 //INFO("Mask: no handler, returning true");
WiredHome 2:1f5dbc624b95 273 return true;
WiredHome 2:1f5dbc624b95 274 }
WiredHome 2:1f5dbc624b95 275
WiredHome 4:a1c25d936346 276 bool RepeatIntersects(time_t * start1, time_t * end1, time_t * start2, time_t * end2, Event_T * Event)
WiredHome 0:49245357cd1b 277 {
WiredHome 4:a1c25d936346 278
WiredHome 4:a1c25d936346 279 INFO("** 1: (%s, %s)", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : "");
WiredHome 4:a1c25d936346 280 INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : "");
WiredHome 4:a1c25d936346 281 if (TimeIntersects(start1, end1, start2, end2))
WiredHome 4:a1c25d936346 282 return true;
WiredHome 4:a1c25d936346 283 if (Event && Event->RepeatFreq) {
WiredHome 4:a1c25d936346 284 INFO("Summary: %s", Event->Summary);
WiredHome 4:a1c25d936346 285 if (Event->Start < *start2 && Event->Until > *start2 ) { // Until=....
WiredHome 0:49245357cd1b 286 do {
WiredHome 4:a1c25d936346 287 time_t interval = NextInterval(*start1, Event->RepeatFreq, (Event->Interval == 0) ? 1 : Event->Interval);
WiredHome 0:49245357cd1b 288 *start1 = *start1 + interval;
WiredHome 4:a1c25d936346 289 if (*end1)
WiredHome 4:a1c25d936346 290 *end1 = *end1 + interval;
WiredHome 4:a1c25d936346 291 INFO("** 1: (%s, %s)", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : "");
WiredHome 4:a1c25d936346 292 INFO("until (%24s, %s)", " ", FormatCTime(Event->Until));
WiredHome 4:a1c25d936346 293 INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : "");
WiredHome 2:1f5dbc624b95 294 if (!RepeatMaskIntersects(start1, end1, start2, end2, Event)) {
WiredHome 2:1f5dbc624b95 295 continue; // we're not on a repeat cycle (e.g. wrong day of the week)
WiredHome 2:1f5dbc624b95 296 }
WiredHome 0:49245357cd1b 297 if (TimeIntersects(start1, end1, start2, end2)) {
WiredHome 0:49245357cd1b 298 return true;
WiredHome 0:49245357cd1b 299 }
WiredHome 4:a1c25d936346 300 } while ((*end2 == 0 || *start1 < *end2) && *start1 < Event->Until);
WiredHome 4:a1c25d936346 301 } else if (Event->Start < *start2 && Event->Count) { // Count=
WiredHome 4:a1c25d936346 302 int count = Event->Count - 1;
WiredHome 0:49245357cd1b 303 do {
WiredHome 4:a1c25d936346 304 time_t interval = NextInterval(*start1, Event->RepeatFreq, (Event->Interval == 0) ? 1 : Event->Interval);
WiredHome 0:49245357cd1b 305 *start1 = *start1 + interval;
WiredHome 4:a1c25d936346 306 if (*end1)
WiredHome 4:a1c25d936346 307 *end1 = *end1 + interval;
WiredHome 4:a1c25d936346 308 INFO("** 1: (%s, %s) - %d", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : "", count);
WiredHome 4:a1c25d936346 309 INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : "");
WiredHome 2:1f5dbc624b95 310 if (!RepeatMaskIntersects(start1, end1, start2, end2, Event)) {
WiredHome 2:1f5dbc624b95 311 continue; // we're not on a repeat cycle (e.g. wrong day of the week)
WiredHome 2:1f5dbc624b95 312 }
WiredHome 0:49245357cd1b 313 if (TimeIntersects(start1, end1, start2, end2)) {
WiredHome 0:49245357cd1b 314 return true;
WiredHome 0:49245357cd1b 315 }
WiredHome 2:1f5dbc624b95 316 } while (--count);
WiredHome 4:a1c25d936346 317 } else if (Event->Start < *start2) { // no Count= and no Until=
WiredHome 0:49245357cd1b 318 do {
WiredHome 4:a1c25d936346 319 int rptFreq = Event->RepeatFreq;
WiredHome 4:a1c25d936346 320 if (Event->RepeatFreq == 2 && Event->RepeatDays != 0)
WiredHome 4:a1c25d936346 321 rptFreq--;
WiredHome 4:a1c25d936346 322 time_t interval = NextInterval(*start1, rptFreq, (Event->Interval == 0) ? 1 : Event->Interval);
WiredHome 0:49245357cd1b 323 *start1 = *start1 + interval;
WiredHome 4:a1c25d936346 324 if (*end1)
WiredHome 4:a1c25d936346 325 *end1 = *end1 + interval;
WiredHome 4:a1c25d936346 326 INFO("== 1: (%s, %s)", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : "");
WiredHome 4:a1c25d936346 327 INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : "");
WiredHome 2:1f5dbc624b95 328 if (!RepeatMaskIntersects(start1, end1, start2, end2, Event)) {
WiredHome 2:1f5dbc624b95 329 continue; // we're not on a repeat cycle (e.g. wrong day of the week)
WiredHome 2:1f5dbc624b95 330 }
WiredHome 0:49245357cd1b 331 if (TimeIntersects(start1, end1, start2, end2)) {
WiredHome 0:49245357cd1b 332 return true;
WiredHome 0:49245357cd1b 333 }
WiredHome 4:a1c25d936346 334 } while (*start1 < *end2 || (*end2 == 0 && *start1 < *start2));
WiredHome 0:49245357cd1b 335 }
WiredHome 0:49245357cd1b 336 }
WiredHome 2:1f5dbc624b95 337 //INFO(" no intersection");
WiredHome 0:49245357cd1b 338 return false;
WiredHome 0:49245357cd1b 339 }
WiredHome 0:49245357cd1b 340
WiredHome 2:1f5dbc624b95 341 // All the stuff between
WiredHome 2:1f5dbc624b95 342 // BEGIN:VEVENT
WiredHome 2:1f5dbc624b95 343 // ...
WiredHome 2:1f5dbc624b95 344 // END:VEVENT
WiredHome 2:1f5dbc624b95 345 //
WiredHome 2:1f5dbc624b95 346 void ParseEvent(Event_T * Event, char * pStart, int32_t tzoSec)
WiredHome 2:1f5dbc624b95 347 {
WiredHome 2:1f5dbc624b95 348 if (strncmp(pStart, "DTSTART:", 8) == 0) {
WiredHome 2:1f5dbc624b95 349 Event->Start = ParseDateStamp(pStart+8, tzoSec);
WiredHome 4:a1c25d936346 350 //INFO(" Start: %d\n", mktime(&Event->eventStart));
WiredHome 2:1f5dbc624b95 351 } else if (strncmp(pStart, "DTSTART;", 8) == 0) {
WiredHome 4:a1c25d936346 352 char * p = pStart + 8;
WiredHome 4:a1c25d936346 353 tzoSec = ParseTZID(p);
WiredHome 4:a1c25d936346 354 p = strrchr(pStart, ':');
WiredHome 2:1f5dbc624b95 355 if (p) {
WiredHome 2:1f5dbc624b95 356 Event->Start = ParseDateStamp(p+1, tzoSec);
WiredHome 4:a1c25d936346 357 //INFO(" Start: %d\n", mktime(&Event->eventStart));
WiredHome 2:1f5dbc624b95 358 }
WiredHome 2:1f5dbc624b95 359 } else if (strncmp(pStart, "DTEND:", 6) == 0) {
WiredHome 2:1f5dbc624b95 360 Event->End = ParseDateStamp(pStart+6, tzoSec);
WiredHome 4:a1c25d936346 361 //INFO(" End: %d\n", mktime(&Event->eventEnd));
WiredHome 2:1f5dbc624b95 362 } else if (strncmp(pStart, "DTEND;", 6) == 0) {
WiredHome 4:a1c25d936346 363 char * p = pStart + 8;
WiredHome 4:a1c25d936346 364 tzoSec = ParseTZID(p);
WiredHome 4:a1c25d936346 365 p = strrchr(pStart, ':');
WiredHome 2:1f5dbc624b95 366 if (p) {
WiredHome 2:1f5dbc624b95 367 Event->End = ParseDateStamp(p+1, tzoSec);
WiredHome 4:a1c25d936346 368 //INFO(" End: %d\n", mktime(&Event->eventEnd));
WiredHome 2:1f5dbc624b95 369 }
WiredHome 2:1f5dbc624b95 370 } else if (strncmp(pStart, "SUMMARY:", 8) == 0) {
WiredHome 2:1f5dbc624b95 371 strncpy(Event->Summary, pStart+8, SUMMARY_CHARS-1);
WiredHome 2:1f5dbc624b95 372 Event->Summary[SUMMARY_CHARS-1] = '\0';
WiredHome 4:a1c25d936346 373 //INFO(" Summary: %s\n", Event->Summary);
WiredHome 2:1f5dbc624b95 374 } else if (strncmp(pStart, "LOCATION:", 9) == 0) {
WiredHome 2:1f5dbc624b95 375 strncpy(Event->Location, pStart+9, LOCATION_CHARS-1);
WiredHome 2:1f5dbc624b95 376 Event->Location[LOCATION_CHARS-1] = '\0';
WiredHome 4:a1c25d936346 377 //INFO(" Location: %s\n", Event->Location);
WiredHome 2:1f5dbc624b95 378 } else if (strncmp(pStart, "PRIORITY:", 9) == 0) {
WiredHome 2:1f5dbc624b95 379 Event->Priority = *(pStart+9) - '0';
WiredHome 4:a1c25d936346 380 //INFO(" Priority: %d\n", Event->Priority);
WiredHome 2:1f5dbc624b95 381 } else if (strncmp(pStart, "CATEGORIES:", 11) == 0) {
WiredHome 2:1f5dbc624b95 382 strncpy(Event->Category, pStart+11, CATEGORY_CHARS-1);
WiredHome 2:1f5dbc624b95 383 Event->Category[CATEGORY_CHARS-1] = '\0';
WiredHome 4:a1c25d936346 384 //INFO(" Category: %s\n", Event->Category);
WiredHome 2:1f5dbc624b95 385 } else if (strncmp(pStart, "RRULE:", 6) == 0) {
WiredHome 2:1f5dbc624b95 386 //RRULE:FREQ=WEEKLY;UNTIL=20140502T180000;BYDAY=MO,TU,WE,TH,FR
WiredHome 2:1f5dbc624b95 387 char * p1, *p2;
WiredHome 2:1f5dbc624b95 388 //INFO("%s", pStart);
WiredHome 2:1f5dbc624b95 389 p1 = pStart + 6; // p1 = FREQ=WEEKLY;UNTIL=20140502T180000;BYDAY=MO,TU,WE,TH,FR
WiredHome 2:1f5dbc624b95 390 p2 = strchr(p1, ';');
WiredHome 2:1f5dbc624b95 391 if (p2)
WiredHome 2:1f5dbc624b95 392 *p2++ = '\0';
WiredHome 2:1f5dbc624b95 393 while (*p1) {
WiredHome 2:1f5dbc624b95 394 //INFO("%s", p1);
WiredHome 2:1f5dbc624b95 395 if (strncmp(p1, "FREQ=", 5) == 0) {
WiredHome 2:1f5dbc624b95 396 //INFO("%s", p1);
WiredHome 2:1f5dbc624b95 397 p1 += 5; // p1 = WEEKLY;UNTIL=20140502T180000;BYDAY=MO,TU,WE,TH,FR
WiredHome 2:1f5dbc624b95 398 if (strncmp(p1, "WEEKLY", 6) == 0) {
WiredHome 2:1f5dbc624b95 399 //INFO(" %s", p1);
WiredHome 2:1f5dbc624b95 400 Event->RepeatFreq = rptfWeekly;
WiredHome 2:1f5dbc624b95 401 p1 += 6;
WiredHome 2:1f5dbc624b95 402 } else if (strncmp(p1, "DAILY", 5) == 0) {
WiredHome 2:1f5dbc624b95 403 //INFO(" %s", p1);
WiredHome 2:1f5dbc624b95 404 Event->RepeatFreq = rptfDaily;
WiredHome 2:1f5dbc624b95 405 p1 += 5;
WiredHome 2:1f5dbc624b95 406 } else if (strncmp(p1, "MONTHLY", 7) == 0) {
WiredHome 2:1f5dbc624b95 407 //INFO(" %s", p1);
WiredHome 2:1f5dbc624b95 408 Event->RepeatFreq = rptfMonthly;
WiredHome 2:1f5dbc624b95 409 p1 += 7;
WiredHome 2:1f5dbc624b95 410 } else if (strncmp(p1, "YEARLY", 6) == 0) {
WiredHome 2:1f5dbc624b95 411 //INFO(" %s", p1);
WiredHome 2:1f5dbc624b95 412 Event->RepeatFreq = rptfYearly;
WiredHome 4:a1c25d936346 413 p1 += 6;
WiredHome 2:1f5dbc624b95 414 }
WiredHome 2:1f5dbc624b95 415 } else if (strncmp(p1, "INTERVAL=", 9) == 0) { // INTERVAL=2
WiredHome 2:1f5dbc624b95 416 //INFO("%s", p1);
WiredHome 2:1f5dbc624b95 417 p1 += 9;
WiredHome 2:1f5dbc624b95 418 Event->Interval = atoi(p1);
WiredHome 2:1f5dbc624b95 419 } else if (strncmp(p1, "COUNT=", 6) == 0) { // COUNT=12;
WiredHome 2:1f5dbc624b95 420 //INFO("%s", p1);
WiredHome 2:1f5dbc624b95 421 p1 += 6; // p1 =
WiredHome 2:1f5dbc624b95 422 Event->Count = atoi(p1);
WiredHome 2:1f5dbc624b95 423 } else if (strncmp(p1, "UNTIL=", 6) == 0) {
WiredHome 2:1f5dbc624b95 424 //INFO("%s", p1);
WiredHome 2:1f5dbc624b95 425 p1 += 6; // p1 = 20140502T180000;BYDAY=MO,TU,WE,TH,FR
WiredHome 4:a1c25d936346 426 //printf("UNTIL= {%s}\n", p1);
WiredHome 2:1f5dbc624b95 427 Event->Until = ParseDateStamp(p1, tzoSec);
WiredHome 4:a1c25d936346 428 //printf("UNTIL:: %d: %d\n", Event->Until, tzoSec);
WiredHome 2:1f5dbc624b95 429 } else if (strncmp(p1, "BYDAY=", 6) == 0) {
WiredHome 2:1f5dbc624b95 430 //INFO("%s", p1);
WiredHome 2:1f5dbc624b95 431 p1 += 6; // p1 = MO,TU,WE,TH,FR
WiredHome 2:1f5dbc624b95 432 while (*p1 >= ' ') {
WiredHome 2:1f5dbc624b95 433 //INFO(" %s", p1);
WiredHome 2:1f5dbc624b95 434 for (int d=0; d<7; d++) {
WiredHome 2:1f5dbc624b95 435 if (strncmp(p1,RepeatDayAbbrev(d),2) == 0) {
WiredHome 2:1f5dbc624b95 436 Event->RepeatDays |= (1 << d);
WiredHome 2:1f5dbc624b95 437 //INFO(" %s %02X", RepeatDayAbbrev(d), Event->RepeatDays);
WiredHome 2:1f5dbc624b95 438 break;
WiredHome 2:1f5dbc624b95 439 }
WiredHome 2:1f5dbc624b95 440 }
WiredHome 2:1f5dbc624b95 441 p1 += 3;
WiredHome 2:1f5dbc624b95 442 }
WiredHome 2:1f5dbc624b95 443 //INFO(" RepeatDay: %02X", Event->RepeatDays);
WiredHome 4:a1c25d936346 444 } else if (strncmp(p1, "BYMONTHDAY=", 11) == 0) {
WiredHome 4:a1c25d936346 445 // RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15
WiredHome 4:a1c25d936346 446 p1 += 11;
WiredHome 4:a1c25d936346 447 while (*p1 >= ' ') {
WiredHome 4:a1c25d936346 448 char * px = p1;
WiredHome 4:a1c25d936346 449 while (*px >= ' ' && *px != ',') { // find , or ; or <nul>
WiredHome 4:a1c25d936346 450 px++;
WiredHome 4:a1c25d936346 451 }
WiredHome 4:a1c25d936346 452 if (*px)
WiredHome 4:a1c25d936346 453 *px++ = '\0';
WiredHome 4:a1c25d936346 454 int num = atoi(p1);
WiredHome 4:a1c25d936346 455 if (num >= 0)
WiredHome 4:a1c25d936346 456 Event->RepeatMonthDay |= (1 << num);
WiredHome 4:a1c25d936346 457 else
WiredHome 4:a1c25d936346 458 Event->RepeatMonthDayRev |= (1 << -num);
WiredHome 4:a1c25d936346 459 p1 = px;
WiredHome 4:a1c25d936346 460 }
WiredHome 4:a1c25d936346 461 INFO(" RepeatMonthDay: %08X", Event->RepeatMonthDay);
WiredHome 4:a1c25d936346 462 } else if (strncmp(p1, "BYMONTH=", 8) == 0) {
WiredHome 4:a1c25d936346 463 // RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3
WiredHome 4:a1c25d936346 464 p1 += 8;
WiredHome 4:a1c25d936346 465 while (*p1 >= ' ') {
WiredHome 4:a1c25d936346 466 char * px = p1;
WiredHome 4:a1c25d936346 467 while (*px >= ' ' && *px != ',') { // find , or ; or <nul>
WiredHome 4:a1c25d936346 468 px++;
WiredHome 4:a1c25d936346 469 }
WiredHome 4:a1c25d936346 470 if (*px)
WiredHome 4:a1c25d936346 471 *px++ = '\0';
WiredHome 4:a1c25d936346 472 int num = atoi(p1);
WiredHome 4:a1c25d936346 473 if (num >= 0)
WiredHome 4:a1c25d936346 474 Event->RepeatMonths |= (1 << num);
WiredHome 4:a1c25d936346 475 else
WiredHome 4:a1c25d936346 476 ; // Event->RepeatMonthsRev |= (1 << -num);
WiredHome 4:a1c25d936346 477 p1 = px;
WiredHome 4:a1c25d936346 478 }
WiredHome 4:a1c25d936346 479 INFO(" RepeatMonths: %04X", Event->RepeatMonths);
WiredHome 2:1f5dbc624b95 480 }
WiredHome 2:1f5dbc624b95 481 if (!p2)
WiredHome 2:1f5dbc624b95 482 break;
WiredHome 2:1f5dbc624b95 483 p1 = p2;
WiredHome 2:1f5dbc624b95 484 p2 = strchr(p1, ';');
WiredHome 2:1f5dbc624b95 485 if (p2)
WiredHome 2:1f5dbc624b95 486 *p2++ = '\0';
WiredHome 2:1f5dbc624b95 487 }
WiredHome 2:1f5dbc624b95 488 }
WiredHome 2:1f5dbc624b95 489 }
WiredHome 0:49245357cd1b 490
WiredHome 4:a1c25d936346 491
WiredHome 4:a1c25d936346 492 // TZID="(GMT -06:00)":20140519T063000
WiredHome 4:a1c25d936346 493 // TZID:(UTC-06:00) Central Time (US & Canada)
WiredHome 4:a1c25d936346 494 // TZID:(GMT -06:00)
WiredHome 4:a1c25d936346 495 int32_t ParseTZID(char * string)
WiredHome 4:a1c25d936346 496 {
WiredHome 4:a1c25d936346 497 int32_t tzo = 0;
WiredHome 4:a1c25d936346 498 bool sign = false;
WiredHome 4:a1c25d936346 499
WiredHome 4:a1c25d936346 500 if (*string == '"') // TZID="(GMT -06:00)":20140519T063000
WiredHome 4:a1c25d936346 501 string++;
WiredHome 4:a1c25d936346 502 if ((strncmp(string, "(UTC", 4) == 0)
WiredHome 4:a1c25d936346 503 || (strncmp(string, "(GMT", 4) == 0) ){
WiredHome 4:a1c25d936346 504 string += 4;
WiredHome 4:a1c25d936346 505 if (*string == ' ')
WiredHome 4:a1c25d936346 506 string++;
WiredHome 4:a1c25d936346 507 if (*string == '-') {
WiredHome 4:a1c25d936346 508 sign = true;
WiredHome 4:a1c25d936346 509 string++;
WiredHome 4:a1c25d936346 510 }
WiredHome 4:a1c25d936346 511 tzo = atoi(string) * 3600;
WiredHome 4:a1c25d936346 512 string = strchr(string, ':');
WiredHome 4:a1c25d936346 513 if (string) {
WiredHome 4:a1c25d936346 514 string++;
WiredHome 4:a1c25d936346 515 tzo += atoi(string) * 60;
WiredHome 4:a1c25d936346 516 }
WiredHome 4:a1c25d936346 517 if (sign)
WiredHome 4:a1c25d936346 518 tzo = -tzo;
WiredHome 4:a1c25d936346 519 } else {
WiredHome 4:a1c25d936346 520 ERR("Unhandled TZID(%s)", string);
WiredHome 4:a1c25d936346 521 }
WiredHome 4:a1c25d936346 522 return tzo;
WiredHome 4:a1c25d936346 523 }
WiredHome 4:a1c25d936346 524
WiredHome 4:a1c25d936346 525 int ParseICalStream(char * pStart, time_t gridStartTime, time_t gridEndTime, int32_t tzoSec, bool showEvents)
WiredHome 0:49245357cd1b 526 {
WiredHome 0:49245357cd1b 527 Event_T Event;
WiredHome 0:49245357cd1b 528 bool tzAdjusted = false;
WiredHome 0:49245357cd1b 529 char * pEnd;
WiredHome 0:49245357cd1b 530 typedef enum { idle, inTimeZone, inEvent } seekstate_t;
WiredHome 0:49245357cd1b 531 seekstate_t seeking = idle;
WiredHome 4:a1c25d936346 532
WiredHome 0:49245357cd1b 533 EventCount = 0;
WiredHome 4:a1c25d936346 534 if (gridEndTime == gridStartTime)
WiredHome 4:a1c25d936346 535 gridEndTime++; // advance so they are not equal
WiredHome 0:49245357cd1b 536 while (pStart && EventCount < EVENT_COUNT) {
WiredHome 0:49245357cd1b 537 pEnd = strchr(pStart, '\n');
WiredHome 0:49245357cd1b 538 if (pEnd) {
WiredHome 0:49245357cd1b 539 if (*(pEnd-1) == '\r')
WiredHome 0:49245357cd1b 540 pEnd--;
WiredHome 0:49245357cd1b 541 *pEnd++ = '\0';
WiredHome 0:49245357cd1b 542 while (*pEnd && *pEnd < ' ') {
WiredHome 0:49245357cd1b 543 pEnd++;
WiredHome 0:49245357cd1b 544 }
WiredHome 0:49245357cd1b 545 // pStart now has a single null terminated line of text.
WiredHome 4:a1c25d936346 546 if (showEvents)
WiredHome 4:a1c25d936346 547 INFO("*** %s", pStart);
WiredHome 0:49245357cd1b 548 switch (seeking) {
WiredHome 0:49245357cd1b 549 case idle:
WiredHome 0:49245357cd1b 550 if (strcmp(pStart, "BEGIN:VTIMEZONE") == 0)
WiredHome 0:49245357cd1b 551 seeking = inTimeZone;
WiredHome 0:49245357cd1b 552 else if (strcmp(pStart, "BEGIN:VEVENT") == 0) {
WiredHome 0:49245357cd1b 553 seeking = inEvent;
WiredHome 0:49245357cd1b 554 Event.Start = 0;
WiredHome 0:49245357cd1b 555 Event.End = 0;
WiredHome 0:49245357cd1b 556 Event.Until = 0;
WiredHome 0:49245357cd1b 557 Event.Summary[0] = '\0';
WiredHome 0:49245357cd1b 558 Event.Location[0] = '\0';
WiredHome 0:49245357cd1b 559 Event.Category[0] = '\0';
WiredHome 0:49245357cd1b 560 Event.Count = 0;
WiredHome 0:49245357cd1b 561 Event.Interval = 0;
WiredHome 0:49245357cd1b 562 Event.RepeatFreq = rptfNone;
WiredHome 0:49245357cd1b 563 Event.RepeatDays = 0;
WiredHome 4:a1c25d936346 564 Event.RepeatMonthDay = 0;
WiredHome 4:a1c25d936346 565 Event.RepeatMonthDayRev = 0;
WiredHome 4:a1c25d936346 566 Event.RepeatMonths = 0;
WiredHome 0:49245357cd1b 567 Event.Priority = 5; // 5 is Normal
WiredHome 4:a1c25d936346 568 //ShowEventInfo(Event);
WiredHome 0:49245357cd1b 569 }
WiredHome 0:49245357cd1b 570 break;
WiredHome 0:49245357cd1b 571 case inTimeZone:
WiredHome 0:49245357cd1b 572 // Can also pick up daylight savings time
WiredHome 0:49245357cd1b 573 if (strcmp(pStart, "END:VTIMEZONE") == 0)
WiredHome 0:49245357cd1b 574 seeking = idle;
WiredHome 4:a1c25d936346 575 else if ((strncmp(pStart, "TZID:", 5) == 0)
WiredHome 4:a1c25d936346 576 || (strncmp(pStart, "TZID=", 5) == 0) ) {
WiredHome 4:a1c25d936346 577 tzoTZIDSec = ParseTZID(pStart + 5);
WiredHome 0:49245357cd1b 578 tzAdjusted = true;
WiredHome 4:a1c25d936346 579 }
WiredHome 0:49245357cd1b 580 break;
WiredHome 0:49245357cd1b 581 case inEvent:
WiredHome 0:49245357cd1b 582 // inEvent
WiredHome 0:49245357cd1b 583 if (strcmp(pStart, "END:VEVENT") == 0) {
WiredHome 0:49245357cd1b 584 // Timezone offset
WiredHome 0:49245357cd1b 585 if (!tzAdjusted) {
WiredHome 1:db274b9e40cc 586 Event.Start += tzoSec;
WiredHome 4:a1c25d936346 587 if (Event.End)
WiredHome 4:a1c25d936346 588 Event.End += tzoSec;
WiredHome 0:49245357cd1b 589 }
WiredHome 0:49245357cd1b 590 // Process it
WiredHome 4:a1c25d936346 591 if (showEvents)
WiredHome 4:a1c25d936346 592 ShowEventInfo(Event);
WiredHome 0:49245357cd1b 593 if (1 || Event.Start >= gridStartTime && Event.Start < gridEndTime
WiredHome 0:49245357cd1b 594 || Event.End >= gridStartTime && Event.End < gridEndTime) {
WiredHome 0:49245357cd1b 595 EventList[EventCount++] = Event;
WiredHome 4:a1c25d936346 596 if (showEvents)
WiredHome 4:a1c25d936346 597 INFO(" +++++ Added Event %d: %s", EventCount, Event.Summary);
WiredHome 0:49245357cd1b 598 }
WiredHome 0:49245357cd1b 599 seeking = idle;
WiredHome 2:1f5dbc624b95 600 } else {
WiredHome 2:1f5dbc624b95 601 ParseEvent(&Event, pStart, tzoSec);
WiredHome 2:1f5dbc624b95 602 }
WiredHome 0:49245357cd1b 603 // End of inEvent
WiredHome 0:49245357cd1b 604 break;
WiredHome 0:49245357cd1b 605 default:
WiredHome 0:49245357cd1b 606 seeking = idle;
WiredHome 0:49245357cd1b 607 break;
WiredHome 0:49245357cd1b 608 }
WiredHome 0:49245357cd1b 609 pStart = pEnd;
WiredHome 0:49245357cd1b 610 } else {
WiredHome 0:49245357cd1b 611 pStart = NULL;
WiredHome 0:49245357cd1b 612 }
WiredHome 0:49245357cd1b 613 } // while
WiredHome 4:a1c25d936346 614 if (EventCount > 0)
WiredHome 4:a1c25d936346 615 SortEvents();
WiredHome 4:a1c25d936346 616 return GetNumEvents();
WiredHome 4:a1c25d936346 617 }