From 2e2d35cf7e3c0956389e7494dc9027f92d977d53 Mon Sep 17 00:00:00 2001 From: hummypkg Date: Fri, 3 Jun 2011 10:27:40 +0000 Subject: [PATCH] add filters --- epg.c | 58 +++++++++++++++++++++++++++++++++++++++++-- epg.h | 14 +++++++++++ lint.h | 4 ++- main.c | 77 ++++++++++++++++++++++++++++++++++++++++++---------------- 4 files changed, 129 insertions(+), 24 deletions(-) diff --git a/epg.c b/epg.c index f6abbbd..496351f 100644 --- a/epg.c +++ b/epg.c @@ -21,6 +21,7 @@ read_section(struct epg *epg) if (memcmp(h.magic, SECTION_MAGIC, sizeof(h.magic))) { printf("Section header magic mismatch.\n"); + hexdump(epg->bin + epg->offset, 64, 0); return NULL; } @@ -105,10 +106,23 @@ dump_data(struct data *d) DUMPINT(d, u1.u.descriptors_loop_length); } +static inline int +check_filter(struct epgfilter *f, enum epgfiltertype type, + unsigned int id, char *str __attribute__((unused))) +{ + if (!f) + return 1; + + for (; f; f = f->next) + if (f->type == type && f->num != id) + return 0; + return 1; +} + void parse(char *epgpath, void (*callback)(struct epg *, struct section *, struct data *, - struct descriptor **, void *), void *val) + struct descriptor **, void *), void *val, struct epgfilter *filter) { struct descriptor *dslist[3]; struct epg *epg; @@ -127,6 +141,16 @@ parse(char *epgpath, send = epg->offset - 11 + s->u1.u.length - 4; + if (!check_filter(filter, FILTER_SERVICE, s->service_id, NULL)) + { + /* Skip this service. */ + epg->offset += s->total_length - 14; + /* Skip padding bytes... */ + while (epg->bin[epg->offset] == 'U') + epg->offset++; + continue; + } + while (epg->offset < send) { struct data *d; @@ -135,9 +159,18 @@ parse(char *epgpath, if (!(d = read_data(epg))) break; + dend = epg->offset + d->u1.u.descriptors_loop_length; + + if (!check_filter(filter, FILTER_EVENT, d->event_id, + NULL)) + { + /* Skip this event. */ + epg->offset = dend; + continue; + } + dslist[0] = dslist[1] = dslist[2] = NULL; - dend = epg->offset + d->u1.u.descriptors_loop_length; while (epg->offset < dend) { struct descriptor *ds; @@ -145,6 +178,14 @@ parse(char *epgpath, if (!(ds = read_descriptor_header(epg))) continue; + if (!check_filter(filter, FILTER_DESCRIPTOR, + ds->tag, NULL)) + { + skip_descriptor(epg, ds); + free_descriptor(ds); + continue; + } + switch (ds->tag) { case DS_SHORT_EVENT: @@ -187,3 +228,16 @@ parse(char *epgpath, close_file(epg); } +void +add_epgfilter(struct epgfilter **filter, enum epgfiltertype type, + unsigned int num, char *str) +{ + struct epgfilter *f = malloc(sizeof(struct epgfilter)); + + f->type = type; + f->num = num; + f->str = str; + f->next = *filter; + *filter = f; +} + diff --git a/epg.h b/epg.h index a0233a7..dccea69 100644 --- a/epg.h +++ b/epg.h @@ -59,3 +59,17 @@ struct data { } u1; }; +enum epgfiltertype { + FILTER_SERVICE = 0, + FILTER_EVENT, + FILTER_DESCRIPTOR +}; + +struct epgfilter { + enum epgfiltertype type; + unsigned int num; + char *str; + + struct epgfilter *next; +}; + diff --git a/lint.h b/lint.h index c1eb415..c9f9ad4 100644 --- a/lint.h +++ b/lint.h @@ -20,6 +20,8 @@ void safeprintf(char *, ...); struct epg *open_file(char *); void close_file(struct epg *); +void add_epgfilter(struct epgfilter **, enum epgfiltertype, + unsigned int, char *); struct section *read_section(struct epg *); void dump_section(struct section *); @@ -29,7 +31,7 @@ void dump_data(struct data *); void parse(char *, void (*)(struct epg *, struct section *, struct data *, - struct descriptor **, void *), void *); + struct descriptor **, void *), void *, struct epgfilter *); struct descriptor *read_descriptor_header(struct epg *); void read_descriptor(struct epg *, struct descriptor *); diff --git a/main.c b/main.c index bc7d766..d2eb67b 100644 --- a/main.c +++ b/main.c @@ -25,7 +25,7 @@ syntax() { fprintf(stderr, "Humax EPG Tool v%s, by af123, 2011.\n\n", version); fprintf(stderr, - "Syntax: epg [options] ...\n"); + "Syntax: epg [options] [filters] ...\n\n"); fprintf(stderr, " Options:\n" " -b Brief output.\n" @@ -33,8 +33,15 @@ syntax() " -f Specify alternate EPG data file.\n" " -h Show help text.\n" " -p Parsable output.\n" + "\n" + ); + fprintf(stderr, + " Filters: (can be specified multiple times, all must be true)\n" + " -D Show only selected descriptor type.\n" + " -E Show only selected event.\n" + " -S Show only selected service.\n" + "\n" ); - fprintf(stderr, "\n"); fprintf(stderr, " Commands:\n" " dump Show a parsed summary of the EPG.\n" @@ -219,10 +226,29 @@ now(struct epg *epg __attribute__((unused)), dump(epg, s, d, ds, NULL); } +#define GETOPT \ + do { \ + if (*++cp == '\0' && argc < 2) \ + { \ + fprintf(stderr, \ + "No argument supplied for -%c\n", opt); \ + exit(1); \ + } \ + else if (*cp == '\0') \ + { \ + argc--, argv++; \ + cp = argv[0]; \ + } \ + while (isspace((int)*cp)) \ + cp++; \ + } while (0) + + int main(int argc, char **argv) { char *epgpath = DEFAULT_EPG_FILE; + struct epgfilter *filter = NULL; char *cp; argc--, argv++; @@ -230,7 +256,8 @@ main(int argc, char **argv) { for (cp = &argv[0][1]; *cp; cp++) { - switch (*cp) + char opt; + switch (opt = *cp) { case 'b': sysopts |= SYSOPT_BRIEF; @@ -244,18 +271,8 @@ main(int argc, char **argv) goto nextopt; case 'f': - if (*++cp == '\0') - { - fprintf(stderr, - "No argument supplied for -f\n"); - exit(1); - } - else - { - while (isspace((int)*cp)) - cp++; - epgpath = strdup(cp); - } + GETOPT; + epgpath = strdup(cp); goto nextopt; case 'h': @@ -264,24 +281,42 @@ main(int argc, char **argv) case 'p': sysopts |= SYSOPT_PARSABLE; break; + + /* Filters */ + case 'D': + GETOPT; + add_epgfilter(&filter, FILTER_DESCRIPTOR, + atoi(cp), NULL); + goto nextopt; + + case 'E': + GETOPT; + add_epgfilter(&filter, FILTER_EVENT, + atoi(cp), NULL); + goto nextopt; + + case 'S': + GETOPT; + add_epgfilter(&filter, FILTER_SERVICE, + atoi(cp), NULL); + goto nextopt; } } nextopt: argc--, argv++; } - if (argc < 1) return syntax(); if (!strcmp(argv[0], "dump")) - parse(epgpath, dump, NULL); - if (!strcmp(argv[0], "now")) - parse(epgpath, now, NULL); + parse(epgpath, dump, NULL, filter); + else if (!strcmp(argv[0], "now")) + parse(epgpath, now, NULL, filter); else if (!strcmp(argv[0], "search") && argc > 1) - parse(epgpath, search, (void *)argv[1]); + parse(epgpath, search, (void *)argv[1], filter); else if (!strcmp(argv[0], "searchall") && argc > 1) - parse(epgpath, searchall, (void *)argv[1]); + parse(epgpath, searchall, (void *)argv[1], filter); else syntax();