Fixed a bug in espr_stats where the esp_stats structure was not being properly initialised.

Also, significantly sped up the header printing functions.
This commit is contained in:
2022-09-07 20:56:43 +10:00
parent de1a27e337
commit 4d7bdcf3cc
7 changed files with 579 additions and 483 deletions

View File

@@ -58,6 +58,9 @@ extern "C" {
// There are 10 Group Types
#define GTS_SIZE 10
#define LIT(L) (const struct str_lit) STR_LIT(L)
#define STR_LIT(L) { .lit = L , .size = sizeof( L ) - 1 }
//
// === FORWARD DEFS ===
@@ -68,6 +71,8 @@ extern "C" {
typedef struct group Group;
typedef struct record Record;
typedef struct field Field;
typedef struct meta_node MetaNode;
//
// === SIMPLE TYPES ===
@@ -83,8 +88,27 @@ extern "C" {
uint32_t uint;
};
struct str_lit {
const char *const lit;
const int size;
const char _pad[4];
};
// Inner type for Record Flag String LUT. Indexed by flag bit.
typedef const char *const rfs_inner[RFS_INNER_SIZE];
typedef const struct str_lit rfs_inner[RFS_INNER_SIZE];
struct esp_stats {
size_t decompressed_size;
uint32_t group_count;
uint32_t record_count;
};
struct str_buf {
char *buf;
int size;
char _pad[4];
};
//
// === ENUMS ===
@@ -177,6 +201,37 @@ extern "C" {
void *data;
};
/* Meta Nodes are used for constructing a more flexible tree structure
* on top of the natural structure of ESP/ESM files.
*
* Meta Nodes do not create a pure tree structure, rather they have pointers to
* their parent and first child, and children have pointers backwards and
* forward through a linked list of all of the children of the parent node.
*
* There is no root node as such, rather there is a root linked list for which
* all of the Meta Nodes have no parents.
*
* While the ESP/ESM buffer can be modified in-place, any modification that
* changes the size of the stored data cannot be directly written to the buffer
* without first shifting all of the data after the point of modification.
*
* Modifications that change data size are:
* - Adding or deleting a group or record
* - Adding or deleting a field in a record
* - Changing a variable length field with data of different length
*
* With a Meta Node you can instead allocate new, arbitrarily sized memory for
* the node data. The Meta Node tree can then be walked to reconstruct a
* contiguous view of discontiguous memory.
*/
struct meta_node {
Node n;
MetaNode *parent;
MetaNode *child;
MetaNode *prev;
MetaNode *next;
};
//
// === BINARY DATA OVERLAYS ===
//
@@ -240,7 +295,7 @@ extern "C" {
extern const enum record_type group_order[GO_SIZE];
// Printable strings for group types
extern const char *const group_type_strings[GTS_SIZE];
extern const struct str_lit group_type_strings[GTS_SIZE];
//
// === FUNCTIONS ===
@@ -267,15 +322,26 @@ 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.
/* Calculates the number of groups and records in the esp/esm file and the
* size of the esp/esm if all of the compressed records were decompressed.
*/
size_t espr_decompressed_size(char *data, size_t size);
struct esp_stats espr_stats(char *data, size_t size);
/* Counts the number of formids present in the esp/esm data. This should be
* equal to the number of records.
*/
size_t espr_formid_count(char *data, size_t size);
// Calculates the number of formid's in an esm/esp from the stats
inline uint32_t espr_formid_count(struct esp_stats stats) {
return stats.record_count;
}
// Calculates the number of nodes in the esp/esm from the stats
inline uint32_t espr_node_count(struct esp_stats stats) {
return stats.record_count + stats.group_count;
}
// Calculates the size of a MetaNode tree constructed over the esp/esm for
// which the stats were generated.
inline size_t espr_tree_size(struct esp_stats stats) {
return sizeof(MetaNode) * espr_node_count(stats);
}
/* Copies the data from `data` to `buf` decompressing compressed fields as
* it does so. buf_size should be the value returned from
@@ -283,6 +349,8 @@ extern "C" {
*/
void espr_decompress(char *data, size_t size, char *buf, size_t buf_size);
// End C++ guard
#ifdef __cplusplus
}