#include #include #include #include #include #include #include #define EXEC(xx) if (sqlite3_exec(db, xx, NULL, NULL, &error) != SQLITE_OK) \ do { \ printf("Failed: %s - %s (%s)\n", xx, error, sqlite3_errmsg(db)); \ sqlite3_free(error); \ exit(0); \ } while (0) struct episode { unsigned long id; char *name; char *overview; unsigned long series; unsigned long episode; }; #define HANDLE(str, c, n) \ do { \ if (!strncmp(p, str, (n + 1))) \ { \ *p = c; \ memmove(p + 1, p + (n + 1), l - (p - txt) - (n + 1)); \ l -= n; \ txt[l] = '\0'; \ } \ } while (0) void unescape(char *txt) { char *p = txt; int l = strlen(txt); //printf("PRE: [%s]\n", txt); while ((p = strchr(p, '&'))) { HANDLE(""", '"', 5); HANDLE("&", '&', 4); p++; } if ((p = strpbrk(txt, "\n\r"))) *p = '\0'; //printf("PST: [%s]\n", txt); //printf("\n"); } int main(int argc, char **argv) { char buf[0x400], *p, *q; struct episode e; char *error; sqlite3_stmt *stmt; sqlite3 *db; FILE *fp; if (argc != 3) { printf("Syntax: %s \n", argv[0]); return 0; } if (!(fp = fopen(argv[1], "r"))) { perror("open"); return 0; } sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); if (sqlite3_open_v2(argv[2], &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_PRIVATECACHE, NULL) != SQLITE_OK) { printf("Failed to open database: %s\n", sqlite3_errmsg(db)); return 0; } EXEC("pragma journal_mode = off"); EXEC("pragma synchronous = off"); EXEC( "create table if not exists episode(" "[episode_id] integer primary key, " "[series] integer, " "[episode] integer, " "[name] text, " "[overview] text" ")" ); if (sqlite3_prepare_v2(db, "insert or replace into episode " "values(?,?,?,?,?)", -1, &stmt, NULL) != SQLITE_OK) { fprintf(stderr, "Problem preparing statement %s", sqlite3_errmsg(db)); exit(1); } while (fgets(buf, sizeof(buf), fp)) { p = buf; while ((*p++) != '<') ; if (!strncmp(p, "Episode>", 8)) { /* New episode */ memset(&e, '\0', sizeof(e)); } if (!strncmp(p, "id>", 3)) e.id = strtoul(p + 3, (char **)NULL, 10); if (!strncmp(p, "Combined_episodenumber>", 23)) e.episode = strtoul(p + 23, (char **)NULL, 10); if (!strncmp(p, "Combined_season>", 16)) e.series = strtoul(p + 16, (char **)NULL, 10); if (!strncmp(p, "EpisodeName>", 12)) { e.name = strdup(p + 12); if ((q = strstr(e.name, ""))) *q = '\0'; unescape(e.name); } if (!strncmp(p, "Overview>", 9)) { e.overview = strdup(p + 9); if ((q = strstr(e.overview, ""))) *q = '\0'; unescape(e.overview); } if (!strncmp(p, "/Episode>", 8)) { /* End of episode */ if (e.id) { sqlite3_bind_int(stmt, 1, e.id); sqlite3_bind_int(stmt, 2, e.series); sqlite3_bind_int(stmt, 3, e.episode); sqlite3_bind_text(stmt, 4, e.name, -1, NULL); sqlite3_bind_text(stmt, 5, e.overview, -1, NULL); sqlite3_step(stmt); sqlite3_reset(stmt); sqlite3_clear_bindings(stmt); } if (e.name) free(e.name); if (e.overview) free(e.overview); } } fclose(fp); sqlite3_finalize(stmt); sqlite3_close(db); return 0; }