From 148a9999536a7faa7403d7a79f8822f3085c19b7 Mon Sep 17 00:00:00 2001 From: William Miles Date: Mon, 5 Sep 2022 20:04:54 +1000 Subject: [PATCH] Implemented walker overlay that calculates decompressed size. --- NavmeshList/main.c | 3 ++- espReader/ESPReader.h | 5 +++++ espReader/Reader.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/NavmeshList/main.c b/NavmeshList/main.c index 3a955c7..d754482 100644 --- a/NavmeshList/main.c +++ b/NavmeshList/main.c @@ -23,7 +23,8 @@ int main(void) { size_t read = fread(buffer, sizeof(char), size, fp); assert(read == size); - espr_print(buffer, size); + size_t decompressed = espr_decompressed_size(buffer, size); + printf("%llu -> %llu\n", size, decompressed); return 0; } diff --git a/espReader/ESPReader.h b/espReader/ESPReader.h index 2188fa6..df4b336 100644 --- a/espReader/ESPReader.h +++ b/espReader/ESPReader.h @@ -267,6 +267,11 @@ extern "C" { */ void espr_print(char *data, size_t size); + /* Calculates the size of the esp data if all of the compressed records are + * decompressed. + */ + size_t espr_decompressed_size(char *data, size_t size); + // End C++ guard #ifdef __cplusplus } diff --git a/espReader/Reader.c b/espReader/Reader.c index 4439cbc..182c93f 100644 --- a/espReader/Reader.c +++ b/espReader/Reader.c @@ -43,6 +43,7 @@ void print_type4(Type4 val); // Utilities Timestamp convert_ts(uint16_t ts); void print_callback(Node n, void *_); +void dc_size_cb(Node n, void *dc_size_ptr); // // === FUNCTIONS === @@ -88,6 +89,33 @@ void print_callback(Node n, void *pt) { } } +size_t espr_decompressed_size(char *data, size_t size) { + size_t dc_size = 0; + espr_walk(data, size, dc_size_cb, &dc_size); + return dc_size; +} + +void dc_size_cb(Node n, void *dc_size_ptr) { + size_t *dcsp = dc_size_ptr; + switch (n.type) { + case NT_GROUP: + // Only add header size for groups, internals will be walked + *dcsp += sizeof(Group); + break; + case NT_RECORD: + // Add the whole record and header, records are leaf-ish + *dcsp += sizeof(Record); + if (n.header.record->flags & COMPRESSED_FLAG) { + // Read decompressed size + *dcsp += *((uint32_t *)n.data); + } else + *dcsp += n.header.record->size; + break; + default: + assert(false); // invalid node type + } +} + /* Unknown data will be some concatenation of groups and records. * * `walk_concat` will call the appropriate walking function