/* * The page's view of chmdec (https://github.com/kjk/chmdec): open a CHM held * in memory, list its entries, and read one entry at a time. One archive is * open at once, which is all a worker needs. */ #include #include #include #include #include "chm.h" static chm_ctx *ctx = NULL; static uint8_t *data = NULL; static struct chm_entry **entries = NULL; static int count = 0; static uint8_t *out = NULL; static size_t out_len = 0; EMSCRIPTEN_KEEPALIVE void chmw_close(void) { if (ctx) { chm_close(ctx); chm_ctx_free(ctx); } ctx = NULL; entries = NULL; count = 0; free(data); data = NULL; free(out); out = NULL; out_len = 0; } /* A buffer for the file's bytes; the page copies the CHM in, then calls chmw_open. */ EMSCRIPTEN_KEEPALIVE uint8_t *chmw_input(size_t len) { chmw_close(); data = (uint8_t *)malloc(len ? len : 1); return data; } /* Opens the archive in the input buffer. Returns the number of entries, or -1. */ EMSCRIPTEN_KEEPALIVE int chmw_open(size_t len) { if (!data) return -1; ctx = chm_ctx_new(NULL, NULL, NULL, NULL); if (!ctx) return -1; if (!chm_open(ctx, data, len)) { chm_ctx_free(ctx); ctx = NULL; return -1; } count = chm_get_entries(ctx, &entries); return count; } EMSCRIPTEN_KEEPALIVE const char *chmw_path(int i) { return (i >= 0 && i < count && entries[i]->path) ? entries[i]->path : ""; } EMSCRIPTEN_KEEPALIVE double chmw_length(int i) { return (i >= 0 && i < count) ? (double)entries[i]->length : 0; } /* Bit 1: a file (not a directory). */ EMSCRIPTEN_KEEPALIVE int chmw_flags(int i) { if (i < 0 || i >= count) return 0; return entries[i]->is_file ? 1 : 0; } /* Reads entry i into an internal buffer; returns its address (length via chmw_length), or 0. */ EMSCRIPTEN_KEEPALIVE uint8_t *chmw_read(int i) { if (i < 0 || i >= count || !ctx) return 0; uint64_t len = entries[i]->length; if (len > 0x7fffffff) return 0; if (len + 1 > out_len) { free(out); out_len = (size_t)len + 1; out = (uint8_t *)malloc(out_len); if (!out) { out_len = 0; return 0; } } if (len == 0) return out; int64_t n = chm_read_entry(ctx, entries[i], out); return n == (int64_t)len ? out : 0; }