/* Attention! This function returns a static string. */ static const char * pil_str (vbi_pil pil) { static char buffer[32]; switch (pil) { case VBI_PIL_TIMER_CONTROL: return "TC"; case VBI_PIL_INHIBIT_TERMINATE: return "RI/T"; case VBI_PIL_INTERRUPTION: return "INT"; case VBI_PIL_CONTINUE: return "CONT"; case VBI_PIL_NSPV: return "NSPV/END"; default: snprintf (buffer, sizeof (buffer), "%02u%02uT%02u%02u", VBI_PIL_MONTH (pil), VBI_PIL_DAY (pil), VBI_PIL_HOUR (pil), VBI_PIL_MINUTE (pil)); return buffer; } }
/** * @param pil Program Identification Label. * * Determines if @a pil represents a valid date and time. * * Since PILs have no year field February 29th is considered valid. * You can find out if this date is valid in a given year with the * vbi_pil_to_time() function. * * 24:00 is not valid (an unreal hour) as defined in EN 300 231 * Annex F and EIA 608-B Section 9.5.1.1. * * @returns * @c TRUE if @a pil represents a valid date and time, @c FALSE * if @a pil contains an unreal date or time (e.g. Jan 0 27:61), * a service code or unallocated code. * * @since 0.2.34 */ vbi_bool vbi_pil_is_valid_date (vbi_pil pil) { unsigned int month; unsigned int day; month = VBI_PIL_MONTH (pil); day = VBI_PIL_DAY (pil); /* Note this also checks for zero month and day. */ return (month - 1 < 12 && day - 1 < month_days[month - 1] && VBI_PIL_HOUR (pil) < 24 && VBI_PIL_MINUTE (pil) < 60); }
/** * @internal * @param pil vbi_pil to print. * @param fp Destination stream. * * Prints a vbi_pil as service code or date and time string without * trailing newline. This is intended for debugging. */ void _vbi_pil_dump (vbi_pil pil, FILE * fp) { switch (pil) { case VBI_PIL_TIMER_CONTROL: fputs ("TC", fp); break; case VBI_PIL_INHIBIT_TERMINATE: fputs ("RI/T", fp); break; case VBI_PIL_INTERRUPTION: fputs ("INT", fp); break; case VBI_PIL_CONTINUE: fputs ("CONT", fp); break; case VBI_PIL_NSPV: /* VBI_PIL_NSPV (PDC) == VBI_PIL_END (XDS) */ fputs ("NSPV/END", fp); break; default: fprintf (fp, "%05x (%02u-%02u %02u:%02u)", pil, VBI_PIL_MONTH (pil), VBI_PIL_DAY (pil), VBI_PIL_HOUR (pil), VBI_PIL_MINUTE (pil)); break; } }
static vbi_bool tm_mon_mday_from_pil (struct tm * tm, vbi_pil pil) { unsigned int month0; month0 = VBI_PIL_MONTH (pil) - 1; if (month0 >= (unsigned int) tm->tm_mon + 6) { /* POSIX defines tm_year as int. */ if (unlikely (tm->tm_year <= INT_MIN)) return FALSE; --tm->tm_year; } else if (month0 + 6 < (unsigned int) tm->tm_mon) { if (unlikely (tm->tm_year >= INT_MAX)) return FALSE; ++tm->tm_year; } tm->tm_mon = month0; tm->tm_mday = VBI_PIL_DAY (pil); return TRUE; }
/** * @param begin The start of the validity of the PIL will be stored * here. * @param end The end of the validity of the PIL will be stored here. * @param pil Program Identification Label (PIL). * @param start The most recently announced start time of the program. * If zero the current system time will be used. * @param tz A time zone name in the same format as the TZ environment * variable. If @c NULL the current value of TZ will be used. * * This function calculates the validity time window of a PIL * according to EN 300 231. That is the time window where a network * can be expected to broadcast this PIL, usually from 00:00 on the * same day until 04:00 on the next day. * * Since PILs do not contain a year field, the year is determined from * the @a start parameter, that is the most recently announced start * time of the program or "AT-1" in EN 300 231 parlance. If @a pil * contains a month more than five months after @a start, @a pil is * assumed to refer to an earlier date than @a start. * * @a pil is assumed to be a time in the time zone specified by @a * seconds_east. @a start will be converted to a local time in the * same time zone to determine the correct year. * * Teletext packet 8/30 format 2, VPS and DVB PDC descriptors give a * PIL relative to the time zone of the intended audience of the * program. Ideally the time zone would be specified as a geographic * area like "Europe/London", such that the function can determine the * correct offset from UTC and if daylight-saving time is in effect at * any time within the validity window. See the documentation of the * localtime() function and the TZ environment variable for details. * * If @a pil is @c VBI_PIL_NSPV this function returns the same values * as vbi_pty_validity_window(). * * @returns * On error the function returns @c FALSE: * - @a pil is not @c VBI_PIL_NSPV and does not contain a * valid date or time. February 29th is a valid date only if the * estimated year is a leap year. * - @a tz is empty or contains an equal sign '='. * - @a start is zero and the current system time could not be * determined. * - The time specified by @a pil, @a start and @a tz cannot be * represented as a time_t value. * - Insufficient memory was available. * * @since 0.2.34 * * @bug * This function is not thread safe unless @a tz is @c NULL. * That is a limitation of the C library which permits the conversion * of a broken-down time in an arbitrary time zone only by setting * the TZ environment variable. The function may also fail to restore * the value of TZ if insufficient memory is available. */ vbi_bool vbi_pil_validity_window (time_t * begin, time_t * end, vbi_pil pil, time_t start, const char * tz) { unsigned int month; assert (NULL != begin); assert (NULL != end); month = VBI_PIL_MONTH (pil); if (0 == month) { /* EN 300 231 Annex F: "Unallocated". */ #if 3 == VBI_VERSION_MINOR errno = VBI_ERR_INVALID_PIL; #else errno = 0; #endif return FALSE; } else if (month <= 12) { unsigned int day; vbi_bool success; day = VBI_PIL_DAY (pil); if (day - 1 >= month_days[month - 1]) { /* Annex F: "Invalid days - indefinite time window". */ *begin = TIME_MIN; *end = TIME_MAX; return TRUE; } success = valid_pil_validity_window (begin, end, pil, start, tz); #if 2 == VBI_VERSION_MINOR errno = 0; #endif return success; } else if (month <= 14) { /* Annex F: "Indefinite time window". */ *begin = TIME_MIN; *end = TIME_MAX; return TRUE; } else { vbi_bool success; /* Annex F: "Unallocated except for the following * service codes (for which there is no restriction to * the time window of validity)". */ switch (pil) { case VBI_PIL_TIMER_CONTROL: case VBI_PIL_INHIBIT_TERMINATE: case VBI_PIL_INTERRUPTION: case VBI_PIL_CONTINUE: *begin = TIME_MIN; *end = TIME_MAX; return TRUE; /* EN 300 231 Section 9.3, Annex E.3. */ case VBI_PIL_NSPV: success = vbi_pty_validity_window (begin, end, start, tz); #if 2 == VBI_VERSION_MINOR errno = 0; #endif return success; default: #if 3 == VBI_VERSION_MINOR errno = VBI_ERR_INVALID_PIL; #else errno = 0; #endif return FALSE; } } }