an iCal processing library
Revision 5:69577415c16e, committed 2014-06-22
- Comitter:
- WiredHome
- Date:
- Sun Jun 22 20:52:26 2014 +0000
- Parent:
- 4:a1c25d936346
- Child:
- 6:4d1fc1cb38ad
- Commit message:
- Revise the parsing and time zone management.
Changed in this revision
iCal.cpp | Show annotated file Show diff for this revision Revisions of this file |
iCal.h | Show annotated file Show diff for this revision Revisions of this file |
--- a/iCal.cpp Sun Jun 08 01:35:37 2014 +0000 +++ b/iCal.cpp Sun Jun 22 20:52:26 2014 +0000 @@ -9,14 +9,14 @@ #include "iCal.h" #include <algorithm> -#ifdef _DEBUG +//#ifdef _DEBUG #define DEBUG "iCal" -#endif +//#endif #ifdef WIN32 #define LF "\n" -#else +#else // mbed #define LF "\r\n" -#endif +#endif // WIN32 #include <cstdio> #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) #define DBG(x, ...) std::printf("[DBG %s %3d] " x LF, DEBUG, __LINE__, ##__VA_ARGS__) @@ -80,7 +80,8 @@ } // YYYYMMDD[THHMMSS[Z]] -time_t ParseDateStamp(char * string, int32_t tzoSec) +// VALUE=DATE:YYYYMMDD +time_t ParseDateStamp(char * string, tz_sec_t tzoSec) { time_t tStamp; struct tm t; @@ -88,6 +89,9 @@ time(&tStamp); tnow = localtime(&tStamp); + if (strncmp(string, "VALUE=DATE:", 11) == 0) { + string += 11; + } //INFO("ParseDateStamp(%s,%d)\n", string, tzoSec); t.tm_year = AtoIxN(string, 4) - 1900; t.tm_mon = AtoIxN(string+4, 2) - 1; @@ -233,7 +237,7 @@ int delta = repeatFactor[repeatFreq]; if (repeatFreq == 4 && isLeapYear(curTime)) delta += 1; - INFO("freq %d, interval %d, delta %d", repeatFreq, interval, delta); + //INFO("freq %d, interval %d, delta %d", repeatFreq, interval, delta); return delta * interval * secperday; } @@ -248,9 +252,9 @@ { bool intersects = false; - INFO("RepeatFreq: %d", Event->RepeatFreq); + //INFO("RepeatFreq: %d", Event->RepeatFreq); if (Event->RepeatFreq == rptfDaily) { - INFO("rptfDaily is not handled"); + //INFO("rptfDaily is not handled"); } else if (Event->RepeatFreq == rptfWeekly) { struct tm * timeinfo; timeinfo = localtime(start1); @@ -267,7 +271,7 @@ } else if (Event->RepeatFreq == rptfYearly) { //struct tm * timeinfo; //timeinfo = localtime(start1); - INFO("rptfYearly is not handled"); + //INFO("rptfYearly is not handled well yet"); } //INFO("Mask: no handler, returning true"); return true; @@ -276,21 +280,21 @@ bool RepeatIntersects(time_t * start1, time_t * end1, time_t * start2, time_t * end2, Event_T * Event) { - INFO("** 1: (%s, %s)", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : ""); - INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : ""); + //INFO("** 1: (%s, %s)", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : ""); + //INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : ""); if (TimeIntersects(start1, end1, start2, end2)) return true; if (Event && Event->RepeatFreq) { - INFO("Summary: %s", Event->Summary); + //INFO("Summary: %s", Event->Summary); if (Event->Start < *start2 && Event->Until > *start2 ) { // Until=.... do { time_t interval = NextInterval(*start1, Event->RepeatFreq, (Event->Interval == 0) ? 1 : Event->Interval); *start1 = *start1 + interval; if (*end1) *end1 = *end1 + interval; - INFO("** 1: (%s, %s)", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : ""); - INFO("until (%24s, %s)", " ", FormatCTime(Event->Until)); - INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : ""); + //INFO("** 1: (%s, %s)", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : ""); + //INFO("until (%24s, %s)", " ", FormatCTime(Event->Until)); + //INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : ""); if (!RepeatMaskIntersects(start1, end1, start2, end2, Event)) { continue; // we're not on a repeat cycle (e.g. wrong day of the week) } @@ -305,8 +309,8 @@ *start1 = *start1 + interval; if (*end1) *end1 = *end1 + interval; - INFO("** 1: (%s, %s) - %d", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : "", count); - INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : ""); + //INFO("** 1: (%s, %s) - %d", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : "", count); + //INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : ""); if (!RepeatMaskIntersects(start1, end1, start2, end2, Event)) { continue; // we're not on a repeat cycle (e.g. wrong day of the week) } @@ -323,8 +327,8 @@ *start1 = *start1 + interval; if (*end1) *end1 = *end1 + interval; - INFO("== 1: (%s, %s)", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : ""); - INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : ""); + //INFO("== 1: (%s, %s)", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : ""); + //INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : ""); if (!RepeatMaskIntersects(start1, end1, start2, end2, Event)) { continue; // we're not on a repeat cycle (e.g. wrong day of the week) } @@ -343,8 +347,9 @@ // ... // END:VEVENT // -void ParseEvent(Event_T * Event, char * pStart, int32_t tzoSec) +void ParseEvent(Event_T * Event, char * pStart, tz_sec_t tzoSec) { + INFO("ParseEvent(...,'%s',%d)", pStart, tzoSec); if (strncmp(pStart, "DTSTART:", 8) == 0) { Event->Start = ParseDateStamp(pStart+8, tzoSec); //INFO(" Start: %d\n", mktime(&Event->eventStart)); @@ -354,7 +359,7 @@ p = strrchr(pStart, ':'); if (p) { Event->Start = ParseDateStamp(p+1, tzoSec); - //INFO(" Start: %d\n", mktime(&Event->eventStart)); + INFO(" Start: %s\n", ctime(&Event->Start)); } } else if (strncmp(pStart, "DTEND:", 6) == 0) { Event->End = ParseDateStamp(pStart+6, tzoSec); @@ -365,7 +370,7 @@ p = strrchr(pStart, ':'); if (p) { Event->End = ParseDateStamp(p+1, tzoSec); - //INFO(" End: %d\n", mktime(&Event->eventEnd)); + INFO(" End: %s\n", ctime(&Event->End)); } } else if (strncmp(pStart, "SUMMARY:", 8) == 0) { strncpy(Event->Summary, pStart+8, SUMMARY_CHARS-1); @@ -492,11 +497,12 @@ // TZID="(GMT -06:00)":20140519T063000 // TZID:(UTC-06:00) Central Time (US & Canada) // TZID:(GMT -06:00) -int32_t ParseTZID(char * string) +tz_sec_t ParseTZID(char * string) { - int32_t tzo = 0; + tz_sec_t tzo = 0; bool sign = false; + INFO("ParseTZID(%s)", string); if (*string == '"') // TZID="(GMT -06:00)":20140519T063000 string++; if ((strncmp(string, "(UTC", 4) == 0) @@ -516,13 +522,14 @@ } if (sign) tzo = -tzo; + INFO(" tzo = %d", tzo); } else { ERR("Unhandled TZID(%s)", string); } return tzo; } -int ParseICalStream(char * pStart, time_t gridStartTime, time_t gridEndTime, int32_t tzoSec, bool showEvents) +int ParseICalStream(char * pStart, time_t gridStartTime, time_t gridEndTime, tz_min_t tzoMin, bool showEvents) { Event_T Event; bool tzAdjusted = false; @@ -543,8 +550,8 @@ pEnd++; } // pStart now has a single null terminated line of text. - if (showEvents) - INFO("*** %s", pStart); + //if (showEvents) + //INFO("*** %s", pStart); switch (seeking) { case idle: if (strcmp(pStart, "BEGIN:VTIMEZONE") == 0) @@ -583,9 +590,9 @@ if (strcmp(pStart, "END:VEVENT") == 0) { // Timezone offset if (!tzAdjusted) { - Event.Start += tzoSec; + Event.Start += (60 * tzoMin); if (Event.End) - Event.End += tzoSec; + Event.End += (60 * tzoMin); } // Process it if (showEvents) @@ -598,7 +605,7 @@ } seeking = idle; } else { - ParseEvent(&Event, pStart, tzoSec); + ParseEvent(&Event, pStart, 60 * tzoMin); } // End of inEvent break;
--- a/iCal.h Sun Jun 08 01:35:37 2014 +0000 +++ b/iCal.h Sun Jun 22 20:52:26 2014 +0000 @@ -2,10 +2,12 @@ #define ICAL_H #include "mbed.h" -//#include "NTPClient.h" - // This defines the total number of events that can be handled - kind of limiting -// but maybe ok for now. +// but maybe ok for now. This is a kind of trade-off, based on having to receive +// the whole iCal file into a buffer, and that not leaving a lot left over for +// events themselves. Instead, the receive process should do more "on the fly" +// with a then smaller buffer, leaving room for many more events. Possibly too, +// the events could be quickly rejected if not matching the criteria. #define EVENT_COUNT 10 @@ -40,6 +42,9 @@ } RepeatDays_t; #endif +typedef int32_t tz_sec_t; +typedef int16_t tz_min_t; + typedef struct { time_t Start; time_t End; @@ -70,11 +75,11 @@ /// @param[in] pStart is a pointer to the start of the stream. /// @param[in] gridStartTime is a time value representing the start of the time-window of interest. /// @param[in] gridEndTime is a time value representing the end of the time-window of interest. -/// @param[in] tzoSec is the time-zone offset in seconds. +/// @param[in] tzoMin is the time-zone offset in minutes. /// @param[in] showEvents when true causes it to print the events as parsed. /// @returns number of events in range. /// -int ParseICalStream(char * pStart, time_t gridStartTime, time_t gridEndTime, int32_t tzoSec, bool showEvents = false); +int ParseICalStream(char * pStart, time_t gridStartTime, time_t gridEndTime, tz_min_t tzoMin, bool showEvents = false); /// Get the number of events that have been cached. @@ -177,7 +182,7 @@ /// @param[in] tzoSec is the time-zone offset in seconds. /// @returns time_t value. /// -time_t ParseDateStamp(char * string, int32_t tzoSec); +time_t ParseDateStamp(char * string, tz_sec_t tzoSec); /// Parse a Time Zone ID value from the front-end of a Datestamp /// @@ -189,7 +194,7 @@ /// @param[in] string to be parsed. /// @returns time zone offset in seconds. /// -int32_t ParseTZID(char * string); +tz_sec_t ParseTZID(char * string);