Tree builder not crashing, need to check functional correctness.

This commit is contained in:
2022-09-08 12:54:37 +10:00
parent 2d5c85f0e8
commit abc9cf6a61
3 changed files with 70 additions and 16 deletions

View File

@@ -28,8 +28,11 @@ int main(void) {
size_t read = fread(buffer, sizeof(char), size, fp); size_t read = fread(buffer, sizeof(char), size, fp);
assert(read == size); assert(read == size);
struct sized_buf esp = { .data = buffer, .size = size };
struct esp_stats stats = espr_stats(buffer, size); struct esp_stats stats = espr_stats(buffer, size);
/*
char *decompressed = malloc(stats.decompressed_size); char *decompressed = malloc(stats.decompressed_size);
if (!decompressed) if (!decompressed)
return errno; return errno;
@@ -37,12 +40,21 @@ int main(void) {
// espr_print(buffer, size); // espr_print(buffer, size);
espr_decompress(buffer, size, decompressed, stats.decompressed_size); espr_decompress(buffer, size, decompressed, stats.decompressed_size);
*/
size_t tree_size = espr_tree_size(stats);
char *tree_data = malloc(tree_size);
struct sized_buf tree = { .data = tree_data, .size = tree_size };
MetaNode *root = espr_create_tree(esp, tree);
free(buffer); free(buffer);
/*
espr_print(decompressed, stats.decompressed_size); espr_print(decompressed, stats.decompressed_size);
free(decompressed); free(decompressed);
*/
return 0; return 0;
} }

View File

@@ -24,6 +24,9 @@
*/ */
#include <stdint.h> #include <stdint.h>
#undef NDEBUG
#include <assert.h>
#define NDEBUG
#include "msh.h" #include "msh.h"
// Guards for C++ usage // Guards for C++ usage
@@ -320,6 +323,13 @@ extern "C" {
return rth2rt[uint32_t_msh(type, RT_HASH_BITS, RT_HASH_SEED)]; return rth2rt[uint32_t_msh(type, RT_HASH_BITS, RT_HASH_SEED)];
} }
// Updates a sized_buf after using `size` bytes
inline void sized_buf_update(struct sized_buf *sb, size_t size) {
assert(sb->size >= size);
sb->data += size;
sb->size -= size;
}
/* `espr_walk` walks through the tree structure of the esp/esm binary /* `espr_walk` walks through the tree structure of the esp/esm binary
* data starting at `data` of `size` bytes. * data starting at `data` of `size` bytes.
* *
@@ -329,7 +339,12 @@ extern "C" {
* Data is walked sequentially. Nodes passed to `cb` will be strictly * Data is walked sequentially. Nodes passed to `cb` will be strictly
* increasing in terms of memory location within the buffer. * increasing in terms of memory location within the buffer.
*/ */
void espr_walk(char *data, size_t size, struct walker_callbacks cb); void espr_walk(
char *data,
size_t size,
struct walker_callbacks cb,
void *from_parent
);
/* `espr_print` prints the header of every group and record in the given /* `espr_print` prints the header of every group and record in the given
* esp/esm binary data. * esp/esm binary data.
@@ -355,15 +370,26 @@ extern "C" {
// Calculates the size of a MetaNode tree constructed over the esp/esm // Calculates the size of a MetaNode tree constructed over the esp/esm
// for which the stats were generated. // for which the stats were generated.
inline size_t espr_tree_size(struct esp_stats stats) { inline size_t espr_tree_size(struct esp_stats stats) {
return sizeof(MetaNode) * espr_node_count(stats); return sizeof(MetaNode) * ((size_t)espr_node_count(stats) + 1);
} }
/* Copies the data from `data` to `buf` decompressing compressed fields /* Copies the data from `data` to `buf` decompressing compressed fields
* as it does so. buf_size should be the value returned from * as it does so. buf_size should be the value returned from
* `espr_decompressed_size`, and `buf` should be at least of that size. * `espr_decompressed_size`, and `buf` should be at least of that size.
*/ */
void espr_decompress(char *data, size_t size, char *buf, size_t buf_size); void espr_decompress(
char *data,
size_t size,
char *buf,
size_t buf_size
);
/* Constructs a MetaNode tree in `tree` over the esp/esm data in `in`.
*
* MetaNode trees allows for easier programatic traversal of the esp/esm
* data, and also allow for modifications that add, remove, or change
* the size of groups/records/fields.
*/
MetaNode *espr_create_tree(struct sized_buf in, struct sized_buf tree); MetaNode *espr_create_tree(struct sized_buf in, struct sized_buf tree);
// End C++ guard // End C++ guard

View File

@@ -117,8 +117,12 @@ void asserts(void)
assert(sizeof(Bytef) == sizeof(char)); assert(sizeof(Bytef) == sizeof(char));
} }
void espr_walk(char *data, size_t size, struct walker_callbacks cb) void espr_walk(
{ char *data,
size_t size,
struct walker_callbacks cb,
void *from_parent
) {
// check assertions that cannot be checked at compile time // check assertions that cannot be checked at compile time
asserts(); asserts();
@@ -128,7 +132,7 @@ void espr_walk(char *data, size_t size, struct walker_callbacks cb)
const Type4 type = *(const Type4 *)data; const Type4 type = *(const Type4 *)data;
assert(type.uint == rt[TES4]); assert(type.uint == rt[TES4]);
data = walk_concat(data, size, cb, NULL); data = walk_concat(data, size, cb, from_parent);
assert(data == data_start + size); assert(data == data_start + size);
} }
@@ -236,7 +240,7 @@ char *walk_record(char *data, struct walker_callbacks cb, void *from_parent)
void espr_print(char *data, size_t size) void espr_print(char *data, size_t size)
{ {
struct walker_callbacks cb = { .pre = print_cb }; struct walker_callbacks cb = { .pre = print_cb };
espr_walk(data, size, cb); espr_walk(data, size, cb, NULL);
} }
void print_cb( void print_cb(
@@ -266,7 +270,7 @@ struct esp_stats espr_stats(char *data, size_t size)
{ {
struct esp_stats stats = { 0 }; struct esp_stats stats = { 0 };
struct walker_callbacks cb = { .pre = stats_cb, .data = &stats }; struct walker_callbacks cb = { .pre = stats_cb, .data = &stats };
espr_walk(data, size, cb); espr_walk(data, size, cb, NULL);
return stats; return stats;
} }
@@ -320,7 +324,7 @@ void espr_decompress(char *data, size_t size, char *buf, size_t buf_size)
.post = decompress_post, .post = decompress_post,
.data = &s .data = &s
}; };
espr_walk(data, size, cb); espr_walk(data, size, cb, NULL);
} }
/* Handles the copying of groups and records, and the decompression of /* Handles the copying of groups and records, and the decompression of
@@ -639,10 +643,18 @@ Timestamp convert_ts(uint16_t ts)
MetaNode *espr_create_tree(struct sized_buf in, struct sized_buf tree) MetaNode *espr_create_tree(struct sized_buf in, struct sized_buf tree)
{ {
const struct sized_buf tree_pre = tree; // create root node
MetaNode *root = (MetaNode *)tree.data;
*root = (MetaNode){ 0 };
// update tree
sized_buf_update(&tree, sizeof(MetaNode));
// walk
struct walker_callbacks cb = { .pre = create_tree_cb, .data = &tree }; struct walker_callbacks cb = { .pre = create_tree_cb, .data = &tree };
espr_walk(in.data, in.size, cb); espr_walk(in.data, in.size, cb, root);
return (MetaNode *)tree_pre.data;
return root;
} }
void create_tree_cb( void create_tree_cb(
@@ -656,18 +668,22 @@ void create_tree_cb(
// add new metanode to tree // add new metanode to tree
struct sized_buf *tree = data; struct sized_buf *tree = data;
assert(tree->size >= sizeof(MetaNode));
MetaNode *m = (MetaNode *)tree->data; MetaNode *m = (MetaNode *)tree->data;
tree->data += sizeof(MetaNode); sized_buf_update(tree, sizeof(MetaNode));
tree->size -= sizeof(MetaNode);
// parent passes their MetaNode to children
MetaNode *p = from_parent; MetaNode *p = from_parent;
// construct new node // construct new node
*m = (MetaNode){ 0 }; // zero/null unused
m->n = n; m->n = n;
m->parent = p; m->parent = p;
m->prev = p->last_child; m->prev = p->last_child;
// the linked list of children may not already exist
if (p->last_child)
p->last_child->next = m; p->last_child->next = m;
else
p->first_child = m;
p->last_child = m; p->last_child = m;
// send self to children // send self to children