Half implemented decompression. Need to figure out how to handle group size adjustment on decompressed data.

This commit is contained in:
2022-09-05 21:01:26 +10:00
parent 10f9c50674
commit ed613db39e
3 changed files with 76 additions and 2 deletions

View File

@@ -277,6 +277,12 @@ extern "C" {
*/
size_t espr_formid_count(char *data, size_t size);
/* Copies the data from `data` to `buf` decompressing compressed fields as
* it does so. buf_size should be the value returned from `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);
// End C++ guard
#ifdef __cplusplus
}

View File

@@ -1,6 +1,7 @@
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <intrin.h>
#include "zlib.h"
@@ -45,6 +46,7 @@ Timestamp convert_ts(uint16_t ts);
void print_callback(Node n, void *_);
void dc_size_cb(Node n, void *dc_size_ptr);
void formid_count_cb(Node n, void *count_ptr);
void decompress_cb(Node n, void *decom_ptr);
//
// === FUNCTIONS ===
@@ -135,6 +137,63 @@ void formid_count_cb(Node n, void *count_ptr) {
}
}
struct decom {
char *buf;
char *start;
size_t remaining;
};
void espr_decompress(char *data, size_t size, char *buf, size_t buf_size) {
struct decom s = { .buf = buf, .start = data, .remaining = buf_size };
espr_walk(data, size, decompress_cb, &s);
// handle final segment
size_t remaining = buf_size - (s.buf - buf);
assert(remaining == s.remaining);
memcpy(s.buf, s.start, remaining);
}
void decompress_cb(Node n, void *decom_ptr) {
struct decom *d = decom_ptr;
// only need to do anything when we find a compressed flag
if (n.type == NT_RECORD && n.header.record->flags & COMPRESSED_FLAG) {
// uncompressed segment copy
size_t size = n.data - d->start;
assert(size < d->remaining);
memcpy(d->buf, d->start, size);
// update decom struct
d->remaining -= size;
d->buf += size;
// copied header
Record *header = (Record *)(d->buf) - 1;
// decompress directly into buffer
const size_t dc_size = *((uint32_t *)n.data);
size_t to_copy = dc_size;
size_t cur_size = n.header.record->size - sizeof(uint32_t);
char *data_start = n.data + sizeof(uint32_t);
int ret = uncompress(d->buf, &to_copy, data_start, cur_size);
assert(ret == Z_OK);
assert(to_copy == dc_size);
// update decom struct
d->remaining -= dc_size;
d->buf += dc_size;
// update start to start of next record/group
d->start = n.data + n.header.record->size;
// update header data size
header->size = dc_size;
// unset compressed flag
header->flags &= ~COMPRESSED_FLAG;
}
}
/* Unknown data will be some concatenation of groups and records.
*
* `walk_concat` will call the appropriate walking function