an iCal processing library
iCal.h@11:fe5586155a42, 2017-02-27 (annotated)
- Committer:
- WiredHome
- Date:
- Mon Feb 27 02:17:06 2017 +0000
- Revision:
- 11:fe5586155a42
- Parent:
- 10:deeaec151283
Some incomplete work on making it less memory intensive. Far from complete.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
WiredHome | 0:49245357cd1b | 1 | #ifndef ICAL_H |
WiredHome | 0:49245357cd1b | 2 | #define ICAL_H |
WiredHome | 0:49245357cd1b | 3 | #include "mbed.h" |
WiredHome | 0:49245357cd1b | 4 | |
WiredHome | 0:49245357cd1b | 5 | // This defines the total number of events that can be handled - kind of limiting |
WiredHome | 5:69577415c16e | 6 | // but maybe ok for now. This is a kind of trade-off, based on having to receive |
WiredHome | 5:69577415c16e | 7 | // the whole iCal file into a buffer, and that not leaving a lot left over for |
WiredHome | 5:69577415c16e | 8 | // events themselves. Instead, the receive process should do more "on the fly" |
WiredHome | 5:69577415c16e | 9 | // with a then smaller buffer, leaving room for many more events. Possibly too, |
WiredHome | 5:69577415c16e | 10 | // the events could be quickly rejected if not matching the criteria. |
WiredHome | 0:49245357cd1b | 11 | #define EVENT_COUNT 10 |
WiredHome | 0:49245357cd1b | 12 | |
WiredHome | 0:49245357cd1b | 13 | |
WiredHome | 0:49245357cd1b | 14 | // Maximum storage space for each item as free-form text |
WiredHome | 4:a1c25d936346 | 15 | #ifdef WIN32 |
WiredHome | 4:a1c25d936346 | 16 | #define SUMMARY_CHARS 100 |
WiredHome | 4:a1c25d936346 | 17 | #define LOCATION_CHARS 100 |
WiredHome | 4:a1c25d936346 | 18 | #define CATEGORY_CHARS 20 |
WiredHome | 4:a1c25d936346 | 19 | #else |
WiredHome | 0:49245357cd1b | 20 | #define SUMMARY_CHARS 40 |
WiredHome | 3:fc5cdc930896 | 21 | #define LOCATION_CHARS 20 |
WiredHome | 3:fc5cdc930896 | 22 | #define CATEGORY_CHARS 20 |
WiredHome | 4:a1c25d936346 | 23 | #endif |
WiredHome | 0:49245357cd1b | 24 | |
WiredHome | 0:49245357cd1b | 25 | typedef enum { |
WiredHome | 0:49245357cd1b | 26 | rptfNone, |
WiredHome | 0:49245357cd1b | 27 | rptfDaily, |
WiredHome | 0:49245357cd1b | 28 | rptfWeekly, |
WiredHome | 0:49245357cd1b | 29 | rptfMonthly, |
WiredHome | 0:49245357cd1b | 30 | rptfYearly |
WiredHome | 0:49245357cd1b | 31 | } RepeatFreq_t; |
WiredHome | 0:49245357cd1b | 32 | |
WiredHome | 0:49245357cd1b | 33 | #if 0 |
WiredHome | 0:49245357cd1b | 34 | typedef enum { |
WiredHome | 0:49245357cd1b | 35 | Sunday = 0x01, |
WiredHome | 0:49245357cd1b | 36 | Monday = 0x02, |
WiredHome | 0:49245357cd1b | 37 | Tuesday = 0x04, |
WiredHome | 0:49245357cd1b | 38 | Wednesday = 0x08, |
WiredHome | 0:49245357cd1b | 39 | Thursday = 0x10, |
WiredHome | 0:49245357cd1b | 40 | Friday = 0x20, |
WiredHome | 0:49245357cd1b | 41 | Saturday = 0x40 |
WiredHome | 0:49245357cd1b | 42 | } RepeatDays_t; |
WiredHome | 0:49245357cd1b | 43 | #endif |
WiredHome | 0:49245357cd1b | 44 | |
WiredHome | 5:69577415c16e | 45 | typedef int32_t tz_sec_t; |
WiredHome | 5:69577415c16e | 46 | typedef int16_t tz_min_t; |
WiredHome | 5:69577415c16e | 47 | |
WiredHome | 8:87549cc99d5e | 48 | /// A single event consists of quite a number of attributes. |
WiredHome | 0:49245357cd1b | 49 | typedef struct { |
WiredHome | 0:49245357cd1b | 50 | time_t Start; |
WiredHome | 0:49245357cd1b | 51 | time_t End; |
WiredHome | 0:49245357cd1b | 52 | time_t Until; |
WiredHome | 0:49245357cd1b | 53 | uint16_t Count; |
WiredHome | 0:49245357cd1b | 54 | uint16_t Interval; |
WiredHome | 0:49245357cd1b | 55 | RepeatFreq_t RepeatFreq; |
WiredHome | 4:a1c25d936346 | 56 | uint8_t RepeatDays; // bit mapped (bit 0 = sunday, bit 1=monday, ...) |
WiredHome | 4:a1c25d936346 | 57 | uint16_t RepeatMonths; // bit mapped (bit 0 = jan, 1=feb, ...) |
WiredHome | 4:a1c25d936346 | 58 | uint32_t RepeatMonthDay; // bit mapped (bit 1 = 1st, 2=2nd, ...) |
WiredHome | 8:87549cc99d5e | 59 | uint32_t RepeatMonthDayRev; // reverse -1 = last day = bit 1, -2=bit 2, ... |
WiredHome | 0:49245357cd1b | 60 | char Summary[SUMMARY_CHARS]; |
WiredHome | 0:49245357cd1b | 61 | char Location[LOCATION_CHARS]; |
WiredHome | 8:87549cc99d5e | 62 | char Category[CATEGORY_CHARS]; // "Green", ... |
WiredHome | 8:87549cc99d5e | 63 | int Priority; // 1 == High, 5 == Normal, 9 == Low |
WiredHome | 0:49245357cd1b | 64 | } Event_T; |
WiredHome | 0:49245357cd1b | 65 | |
WiredHome | 0:49245357cd1b | 66 | extern Event_T EventList[EVENT_COUNT]; |
WiredHome | 0:49245357cd1b | 67 | |
WiredHome | 11:fe5586155a42 | 68 | /// Prepare to start processing an iCal stream |
WiredHome | 11:fe5586155a42 | 69 | /// |
WiredHome | 11:fe5586155a42 | 70 | /// This initializes the data structures for parsing. |
WiredHome | 11:fe5586155a42 | 71 | /// |
WiredHome | 11:fe5586155a42 | 72 | /// @code |
WiredHome | 11:fe5586155a42 | 73 | /// ParseICalStart(); |
WiredHome | 11:fe5586155a42 | 74 | /// while (receive(buf, ... )) |
WiredHome | 11:fe5586155a42 | 75 | /// ParseICalStream(buf, ...); |
WiredHome | 11:fe5586155a42 | 76 | /// count = ParseICalClose(); |
WiredHome | 11:fe5586155a42 | 77 | /// @endcode |
WiredHome | 11:fe5586155a42 | 78 | /// |
WiredHome | 11:fe5586155a42 | 79 | void ParseICalStart(void); |
WiredHome | 11:fe5586155a42 | 80 | |
WiredHome | 11:fe5586155a42 | 81 | |
WiredHome | 11:fe5586155a42 | 82 | /// End processing an iCal stream and return the number of events |
WiredHome | 11:fe5586155a42 | 83 | /// |
WiredHome | 11:fe5586155a42 | 84 | /// @returns number of events in range |
WiredHome | 11:fe5586155a42 | 85 | /// |
WiredHome | 11:fe5586155a42 | 86 | int ParseICalClose(void); |
WiredHome | 11:fe5586155a42 | 87 | |
WiredHome | 11:fe5586155a42 | 88 | |
WiredHome | 4:a1c25d936346 | 89 | /// Parse an iCal stream, and extract everything useful. |
WiredHome | 4:a1c25d936346 | 90 | /// |
WiredHome | 4:a1c25d936346 | 91 | /// This accepts a pointer to a [large] buffer, which is the contents |
WiredHome | 4:a1c25d936346 | 92 | /// of an iCal stream. It walked through all of the available |
WiredHome | 4:a1c25d936346 | 93 | /// information to extract the Event list. |
WiredHome | 4:a1c25d936346 | 94 | /// |
WiredHome | 4:a1c25d936346 | 95 | /// @param[in] pStart is a pointer to the start of the stream. |
WiredHome | 4:a1c25d936346 | 96 | /// @param[in] gridStartTime is a time value representing the start of the time-window of interest. |
WiredHome | 4:a1c25d936346 | 97 | /// @param[in] gridEndTime is a time value representing the end of the time-window of interest. |
WiredHome | 5:69577415c16e | 98 | /// @param[in] tzoMin is the time-zone offset in minutes. |
WiredHome | 4:a1c25d936346 | 99 | /// @param[in] showEvents when true causes it to print the events as parsed. |
WiredHome | 4:a1c25d936346 | 100 | /// @returns number of events in range. |
WiredHome | 4:a1c25d936346 | 101 | /// |
WiredHome | 10:deeaec151283 | 102 | int ParseICalStream(char * pStart, time_t gridStartTime, time_t gridEndTime, tz_min_t tzoMin, bool showEvents = true); |
WiredHome | 4:a1c25d936346 | 103 | |
WiredHome | 4:a1c25d936346 | 104 | |
WiredHome | 4:a1c25d936346 | 105 | /// Get the number of events that have been cached. |
WiredHome | 4:a1c25d936346 | 106 | /// |
WiredHome | 4:a1c25d936346 | 107 | /// @returns the number of events. |
WiredHome | 4:a1c25d936346 | 108 | /// |
WiredHome | 4:a1c25d936346 | 109 | int GetNumEvents(void); |
WiredHome | 4:a1c25d936346 | 110 | |
WiredHome | 4:a1c25d936346 | 111 | /// Compute the intersection of two time ranges, and evaluate the recurringing events. |
WiredHome | 4:a1c25d936346 | 112 | /// |
WiredHome | 4:a1c25d936346 | 113 | /// This compares a pair of time ranges, each by a start and end time. If they overlap |
WiredHome | 4:a1c25d936346 | 114 | /// it then computes the intersection of those two ranges. Additionally, for a |
WiredHome | 4:a1c25d936346 | 115 | /// specified Event, it will evaluate the recurring events that may also fall into |
WiredHome | 4:a1c25d936346 | 116 | /// the target time range. |
WiredHome | 4:a1c25d936346 | 117 | /// |
WiredHome | 4:a1c25d936346 | 118 | /// @note This is usually the only API you need, as this will first call |
WiredHome | 4:a1c25d936346 | 119 | /// the TimeIntersects function, and if that fails, then it will evaluate |
WiredHome | 4:a1c25d936346 | 120 | /// repeat information. |
WiredHome | 4:a1c25d936346 | 121 | /// |
WiredHome | 4:a1c25d936346 | 122 | /// @param[in,out] start1 is the starting time of range 1. |
WiredHome | 4:a1c25d936346 | 123 | /// @param[in,out] end1 is the ending time of range 1. |
WiredHome | 4:a1c25d936346 | 124 | /// @param[in] start2 is the starting time of range 2. |
WiredHome | 4:a1c25d936346 | 125 | /// @param[in] end2 is the ending time of range 2. |
WiredHome | 4:a1c25d936346 | 126 | /// @param[in] Event is a pointer to the event of interest that may have recurring series. |
WiredHome | 4:a1c25d936346 | 127 | /// @returns true if the ranges overlap, and then start1 and end1 are set to the |
WiredHome | 4:a1c25d936346 | 128 | /// intersection. |
WiredHome | 4:a1c25d936346 | 129 | /// |
WiredHome | 4:a1c25d936346 | 130 | bool RepeatIntersects(time_t * start1, time_t * end1, time_t * start2, time_t * end2, Event_T * Event = NULL); |
WiredHome | 4:a1c25d936346 | 131 | |
WiredHome | 4:a1c25d936346 | 132 | |
WiredHome | 4:a1c25d936346 | 133 | /// Compute the intersection of two time ranges, and returns that intersection. |
WiredHome | 4:a1c25d936346 | 134 | /// |
WiredHome | 4:a1c25d936346 | 135 | /// This compares a pair of time ranges, each by a start and end time. If they overlap |
WiredHome | 4:a1c25d936346 | 136 | /// it then computes the intersection of those two ranges. |
WiredHome | 4:a1c25d936346 | 137 | /// |
WiredHome | 4:a1c25d936346 | 138 | /// @param[in,out] start1 is the starting time of range 1. |
WiredHome | 4:a1c25d936346 | 139 | /// @param[in,out] end1 is the ending time of range 1. |
WiredHome | 4:a1c25d936346 | 140 | /// @param[in] start2 is the starting time of range 2. |
WiredHome | 4:a1c25d936346 | 141 | /// @param[in] end2 is the ending time of range 2. |
WiredHome | 4:a1c25d936346 | 142 | /// @returns true if the ranges overlap, and then start1 and end1 are set to the |
WiredHome | 4:a1c25d936346 | 143 | /// intersection. |
WiredHome | 4:a1c25d936346 | 144 | /// |
WiredHome | 4:a1c25d936346 | 145 | bool TimeIntersects(time_t * start1, time_t * end1, time_t * start2, time_t * end2); |
WiredHome | 4:a1c25d936346 | 146 | |
WiredHome | 4:a1c25d936346 | 147 | |
WiredHome | 4:a1c25d936346 | 148 | // Private Functions - no real value external to the iCal public interface |
WiredHome | 4:a1c25d936346 | 149 | // other than for test code. |
WiredHome | 4:a1c25d936346 | 150 | |
WiredHome | 4:a1c25d936346 | 151 | /// Computes the next interval for iCal events that have recurrence. |
WiredHome | 4:a1c25d936346 | 152 | /// |
WiredHome | 4:a1c25d936346 | 153 | /// @param[in] baseT is the base time value which is a factor only in leap-year. |
WiredHome | 4:a1c25d936346 | 154 | /// @param[in] repeatFreq is a value representing the frequency of recurrence - |
WiredHome | 4:a1c25d936346 | 155 | /// 0=none, 1=daily, 2=weekly, 3=monthly, 4=yearly |
WiredHome | 4:a1c25d936346 | 156 | /// @param[in] interval is the multiplier of that repeat frequency to the next |
WiredHome | 4:a1c25d936346 | 157 | /// event. |
WiredHome | 4:a1c25d936346 | 158 | /// @returns a time_t value which is the incremental interval, and would be added |
WiredHome | 4:a1c25d936346 | 159 | /// to a reference time. |
WiredHome | 4:a1c25d936346 | 160 | /// |
WiredHome | 4:a1c25d936346 | 161 | time_t NextInterval(time_t baseT, int repeatFreq, int interval); |
WiredHome | 4:a1c25d936346 | 162 | |
WiredHome | 4:a1c25d936346 | 163 | |
WiredHome | 0:49245357cd1b | 164 | /// Format a ctime value as a string, without the trailing <cr> |
WiredHome | 0:49245357cd1b | 165 | /// |
WiredHome | 0:49245357cd1b | 166 | /// This uses the normal ctime function, which appends a <cr>, but |
WiredHome | 0:49245357cd1b | 167 | /// it then removes that trailing line ending character. Additionally, |
WiredHome | 0:49245357cd1b | 168 | /// this keeps a few local static buffers to return the time string in |
WiredHome | 0:49245357cd1b | 169 | /// which permits a printf (for example) to call this api a few times |
WiredHome | 0:49245357cd1b | 170 | /// and get the proper representation of each. |
WiredHome | 0:49245357cd1b | 171 | /// |
WiredHome | 1:db274b9e40cc | 172 | /// @param[in] t is a time value; |
WiredHome | 0:49245357cd1b | 173 | /// @returns a pointer to a static buffer containing the converted time. |
WiredHome | 0:49245357cd1b | 174 | /// |
WiredHome | 0:49245357cd1b | 175 | char * FormatCTime(time_t t); |
WiredHome | 0:49245357cd1b | 176 | |
WiredHome | 0:49245357cd1b | 177 | /// Sort the Events that have been extracted from the iCal results. |
WiredHome | 0:49245357cd1b | 178 | /// |
WiredHome | 0:49245357cd1b | 179 | void SortEvents(); |
WiredHome | 0:49245357cd1b | 180 | |
WiredHome | 0:49245357cd1b | 181 | /// Show the details for a specific Event, on the specified serial stream. |
WiredHome | 0:49245357cd1b | 182 | /// |
WiredHome | 4:a1c25d936346 | 183 | /// Most useful during development, and perhaps no value after that. |
WiredHome | 0:49245357cd1b | 184 | /// |
WiredHome | 1:db274b9e40cc | 185 | /// @param[in] Event is the event of interest. |
WiredHome | 0:49245357cd1b | 186 | /// |
WiredHome | 0:49245357cd1b | 187 | void ShowEventInfo(Event_T & Event); |
WiredHome | 0:49245357cd1b | 188 | |
WiredHome | 0:49245357cd1b | 189 | /// Access the 2-letter abbreviation for the day of the week. |
WiredHome | 0:49245357cd1b | 190 | /// |
WiredHome | 1:db274b9e40cc | 191 | /// @param[in] i is the day of the week, where 0 = sunday |
WiredHome | 0:49245357cd1b | 192 | /// @returns a pointer to the 2-letter abbreviation. |
WiredHome | 0:49245357cd1b | 193 | /// |
WiredHome | 0:49245357cd1b | 194 | const char * RepeatDayAbbrev(int i); |
WiredHome | 0:49245357cd1b | 195 | |
WiredHome | 0:49245357cd1b | 196 | /// Parse a Datestamp string into a time value. |
WiredHome | 0:49245357cd1b | 197 | /// |
WiredHome | 0:49245357cd1b | 198 | /// Parses a string which can look like this: 20140505T200000 |
WiredHome | 0:49245357cd1b | 199 | /// into a time_t value. |
WiredHome | 0:49245357cd1b | 200 | /// |
WiredHome | 1:db274b9e40cc | 201 | /// @param[in] string is the string to parse. |
WiredHome | 1:db274b9e40cc | 202 | /// @param[in] tzoSec is the time-zone offset in seconds. |
WiredHome | 0:49245357cd1b | 203 | /// @returns time_t value. |
WiredHome | 0:49245357cd1b | 204 | /// |
WiredHome | 5:69577415c16e | 205 | time_t ParseDateStamp(char * string, tz_sec_t tzoSec); |
WiredHome | 0:49245357cd1b | 206 | |
WiredHome | 4:a1c25d936346 | 207 | /// Parse a Time Zone ID value from the front-end of a Datestamp |
WiredHome | 0:49245357cd1b | 208 | /// |
WiredHome | 4:a1c25d936346 | 209 | /// Parses a string which can look like one of these: |
WiredHome | 4:a1c25d936346 | 210 | /// @li TZID="(GMT -06:00)":20140519T063000 |
WiredHome | 4:a1c25d936346 | 211 | /// @li TZID:(UTC-06:00) Central Time (US & Canada) |
WiredHome | 4:a1c25d936346 | 212 | /// @li TZID:(GMT -06:00) |
WiredHome | 0:49245357cd1b | 213 | /// |
WiredHome | 4:a1c25d936346 | 214 | /// @param[in] string to be parsed. |
WiredHome | 4:a1c25d936346 | 215 | /// @returns time zone offset in seconds. |
WiredHome | 0:49245357cd1b | 216 | /// |
WiredHome | 5:69577415c16e | 217 | tz_sec_t ParseTZID(char * string); |
WiredHome | 0:49245357cd1b | 218 | |
WiredHome | 4:a1c25d936346 | 219 | |
WiredHome | 0:49245357cd1b | 220 | |
WiredHome | 0:49245357cd1b | 221 | |
WiredHome | 4:a1c25d936346 | 222 | #endif // ICAL_H |