#define HMMLIB_IMPLEMENTATION #include "hmmlib.h" #include "stb_sb.h" #include #include typedef struct { char* text; int* lines; } Index; static Index* index_find(Index* base, const char* text) { for(size_t i = 0; i < sb_count(base); ++i){ if(strcmp(base[i].text, text) == 0){ return base + i; } } return NULL; } void hmml_dump(HMML_Output* hmml, bool extra) { if(!hmml){ puts("(null)"); return; } if(!hmml->well_formed){ printf("Error:%d:%d %s\n", hmml->error.line, hmml->error.col, hmml->error.message); return; } if(extra) { puts("Metadata:"); static const char* meta[] = { "member", "stream_platform", "stream_username", "project", "title", "vod_platform", "id", "output", "template", "medium" }; for(size_t i = 0; i < countof(meta); ++i) { const char* value = ((char**)&hmml->metadata)[i]; printf(" %s = %s\n", meta[i], value); } puts(" Credits:"); for(size_t i = 0; i < hmml->metadata.credit_count; ++i) { HMML_Credit* c = hmml->metadata.credits + i; printf(" %s [%s]\n", c->name, c->role); } puts(" Custom:"); for(size_t i = 0; i < hmml->metadata.custom_count; ++i) { HMML_VideoCustomMetaData* m = hmml->metadata.custom + i; printf(" %s = %s\n", m->key, m->value); } } puts("Annotations:"); for(size_t i = 0; i < hmml->annotation_count; ++i){ HMML_Annotation* a = hmml->annotations + i; char time_buf[256]; char* tp = time_buf; if(a->h) { *tp++ = (a->h%10) + '0'; sprintf(tp, ":%02d:%02d", a->m, a->s); } else { sprintf(tp, " %2d:%02d", a->m, a->s); } printf("\t%3d [%s] [%s]\n", a->line, time_buf, a->text); } Index* authors = NULL; Index* markers[HMML_MARKER_COUNT] = {}; int max_text_len = 0; for(size_t i = 0; i < hmml->annotation_count; ++i){ HMML_Annotation* a = hmml->annotations + i; if(a->author){ int len = strlen(a->author); if(len > max_text_len){ max_text_len = len; } Index* idx; if(!(idx = index_find(authors, a->author))){ Index x = { .text = a->author }; sb_push(authors, x); idx = &sb_last(authors); } sb_push(idx->lines, a->line); } } for(size_t i = 0; i < hmml->annotation_count; ++i){ HMML_Annotation* a = hmml->annotations + i; for(size_t j = 0; j < a->marker_count; ++j){ int type = a->markers[j].type; char* text = a->markers[j].marker; int len = strlen(text); if(len > max_text_len){ max_text_len = len; } Index* idx; if(!(idx = index_find(markers[type], text))){ Index x = { .text = text }; sb_push(markers[type], x); idx = &sb_last(markers[type]); } sb_push(idx->lines, a->line); } } puts("Authors:"); for(size_t i = 0; i < sb_count(authors); ++i){ printf("\t %*s: ", max_text_len, authors[i].text); for(size_t j = 0; j < sb_count(authors[i].lines); ++j){ printf("%3d ", authors[i].lines[j]); } puts(""); } static const char* m_tags[HMML_MARKER_COUNT] = { "Categories", "Members", "Projects" }; for(size_t i = 0; i < HMML_MARKER_COUNT; ++i){ printf("%s:\n", m_tags[i]); for(size_t j = 0; j < sb_count(markers[i]); ++j){ printf("\t %*s: ", max_text_len, markers[i][j].text); for(size_t k = 0; k < sb_count(markers[i][j].lines); ++k){ printf("%3d ", markers[i][j].lines[k]); } puts(""); } } static const char* r_tags[] = { "Site", "Page", "URL", "Title", "Article", "Author", "Editor", "Publisher", "ISBN" }; puts("References:"); for(size_t i = 0; i < hmml->annotation_count; ++i){ HMML_Annotation* a = hmml->annotations + i; for(size_t j = 0; j < a->reference_count; ++j){ printf("\t%3d ", a->line); HMML_Reference* r = a->references + j; for(size_t k = 0; k < countof(r_tags); ++k){ char* item = ((char**)r)[k]; if(item){ printf("[%s = %s] ", r_tags[k], item); } } puts(""); } } puts("Quotes:"); for(size_t i = 0; i < hmml->annotation_count; ++i){ HMML_Annotation* a = hmml->annotations + i; if(a->quote.present){ if(a->quote.author){ printf("\t%3d [Quote #%d, by %s]", a->line, a->quote.id, a->quote.author); } else { printf("\t%3d [Quote #%d]", a->line, a->quote.id); } puts(""); } } for(size_t i = 0; i < sb_count(authors); ++i){ sb_free(authors[i].lines); } sb_free(authors); for(size_t i = 0; i < HMML_MARKER_COUNT; ++i){ for(size_t j = 0; j < sb_count(markers[i]); ++j){ sb_free(markers[i][j].lines); } sb_free(markers[i]); } } void usage(char* argv0, FILE* out) { fprintf(out, "Usage: %s [-bx] [file]\n", argv0); } int main(int argc, char** argv) { bool dump_extra = false; bool breakpoint = false; int opt; while((opt = getopt(argc, argv, "bx")) != -1) { if(opt == 'x') { dump_extra = true; } else if(opt == 'b') { breakpoint = true; } else { usage(argv[0], stderr); return 1; } } if(optind >= argc){ usage(argv[0], stderr); return 1; } argc -= (optind-1); argv += (optind-1); FILE* f = fopen(argv[1], "r"); if(!f) { perror(argv[1]); return 1; } fseek(f, 0, SEEK_END); long size = ftell(f); rewind(f); char* mem = malloc(size+1); mem[size] = 0; fread(mem, 1, size, f); fclose(f); HMML_Output out = hmml_parse(mem); free(mem); if(breakpoint) { asm("int3"); } hmml_dump(&out, dump_extra); hmml_free(&out); }