A little more formatting.
This commit is contained in:
@@ -11,38 +11,38 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
errno_t ret = fopen_s(&fp, "Skyrim.esm", "rb");
|
errno_t ret = fopen_s(&fp, "Skyrim.esm", "rb");
|
||||||
|
|
||||||
if (ret || !fp)
|
if (ret || !fp)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
fseek(fp, 0L, SEEK_END);
|
fseek(fp, 0L, SEEK_END);
|
||||||
size_t size = ftell(fp);
|
size_t size = ftell(fp);
|
||||||
rewind(fp);
|
rewind(fp);
|
||||||
|
|
||||||
char *buffer = malloc(size);
|
char *buffer = malloc(size);
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return errno;
|
return errno;
|
||||||
|
|
||||||
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 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;
|
||||||
|
|
||||||
// espr_print(buffer, size);
|
// espr_print(buffer, size);
|
||||||
|
|
||||||
espr_decompress(buffer, size, decompressed, stats.decompressed_size);
|
espr_decompress(buffer, size, decompressed, stats.decompressed_size);
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
espr_print(decompressed, stats.decompressed_size);
|
espr_print(decompressed, stats.decompressed_size);
|
||||||
|
|
||||||
free(decompressed);
|
free(decompressed);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,13 +37,13 @@ extern "C" {
|
|||||||
// There are 127 record types + a NONE type used for sanity checks
|
// There are 127 record types + a NONE type used for sanity checks
|
||||||
#define RT_SIZE 128
|
#define RT_SIZE 128
|
||||||
|
|
||||||
/* RT hash seed was externally calculated s.t. the fourcc codes perfectly hash
|
/* RT hash seed was externally calculated s.t. the fourcc codes perfectly hash
|
||||||
* into indices between 0 and 511. That is, there are no hashing collisions.
|
* into indices between 0 and 511. That is, there are no hashing collisions.
|
||||||
* This allows for hard coded lookup tables for the fourcc codes in a relatively
|
* This allows for hard coded lookup tables for the fourcc codes in a relatively
|
||||||
* small space.
|
* small space.
|
||||||
*
|
*
|
||||||
* A minimal perfect hash is also possible with an intermediate seed table,
|
* A minimal perfect hash is also possible with an intermediate seed table,
|
||||||
* though I'm not sure which is faster, if it's worth trying to speed this up,
|
* though I'm not sure which is faster, if it's worth trying to speed this up,
|
||||||
* etc.
|
* etc.
|
||||||
*/
|
*/
|
||||||
#define RT_HASH_SIZE 512
|
#define RT_HASH_SIZE 512
|
||||||
@@ -62,220 +62,229 @@ extern "C" {
|
|||||||
#define STR_LIT(L) { .lit = L , .size = sizeof( L ) - 1 }
|
#define STR_LIT(L) { .lit = L , .size = sizeof( L ) - 1 }
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// === FORWARD DEFS ===
|
// === FORWARD DEFS ===
|
||||||
//
|
//
|
||||||
|
|
||||||
typedef union type4 Type4;
|
typedef union type4 Type4;
|
||||||
typedef struct timestamp Timestamp;
|
typedef struct timestamp Timestamp;
|
||||||
typedef struct group Group;
|
typedef struct group Group;
|
||||||
typedef struct record Record;
|
typedef struct record Record;
|
||||||
typedef struct field Field;
|
typedef struct field Field;
|
||||||
typedef struct meta_node MetaNode;
|
typedef struct meta_node MetaNode;
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// === SIMPLE TYPES ===
|
// === SIMPLE TYPES ===
|
||||||
//
|
//
|
||||||
|
|
||||||
// 3 byte ID, upper byte is determined at run time and is used to reference
|
// 3 byte ID, upper byte is determined at run time and is used to
|
||||||
// across esp/esm files
|
// reference across esp/esm files
|
||||||
typedef uint32_t formid;
|
typedef uint32_t formid;
|
||||||
|
|
||||||
// char[4] with uint32_t access, used to access fourcc values
|
// char[4] with uint32_t access, used to access fourcc values
|
||||||
union type4 {
|
union type4 {
|
||||||
char bytes[4];
|
char bytes[4];
|
||||||
uint32_t uint;
|
uint32_t uint;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct str_lit {
|
struct str_lit {
|
||||||
const char *const lit;
|
const char *const lit;
|
||||||
const int size;
|
const int size;
|
||||||
const char _pad[4];
|
const char _pad[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Inner type for Record Flag String LUT. Indexed by flag bit.
|
// Inner type for Record Flag String LUT. Indexed by flag bit.
|
||||||
typedef const struct str_lit rfs_inner[RFS_INNER_SIZE];
|
typedef const struct str_lit rfs_inner[RFS_INNER_SIZE];
|
||||||
|
|
||||||
struct esp_stats {
|
struct esp_stats {
|
||||||
size_t decompressed_size;
|
size_t decompressed_size;
|
||||||
uint32_t group_count;
|
uint32_t group_count;
|
||||||
uint32_t record_count;
|
uint32_t record_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct str_buf {
|
struct str_buf {
|
||||||
char *buf;
|
char *buf;
|
||||||
int size;
|
int size;
|
||||||
char _pad[4];
|
char _pad[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sized_buf {
|
struct sized_buf {
|
||||||
char *data;
|
char *data;
|
||||||
size_t size;
|
size_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// === ENUMS ===
|
// === ENUMS ===
|
||||||
//
|
//
|
||||||
|
|
||||||
// Tag for generic node tagged union
|
// Tag for generic node tagged union
|
||||||
enum node_type {
|
enum node_type {
|
||||||
NT_GROUP,
|
NT_GROUP,
|
||||||
NT_RECORD,
|
NT_RECORD,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Record type enum
|
// Record type enum
|
||||||
enum record_type {
|
enum record_type {
|
||||||
NONE,
|
NONE,
|
||||||
AACT, ACHR, ACTI, ADDN, ALCH, AMMO,
|
AACT, ACHR, ACTI, ADDN, ALCH, AMMO,
|
||||||
ANIO, APPA, ARMA, ARMO, ARTO, ASPC,
|
ANIO, APPA, ARMA, ARMO, ARTO, ASPC,
|
||||||
ASTP, AVIF, BOOK, BPTD, CAMS, CELL,
|
ASTP, AVIF, BOOK, BPTD, CAMS, CELL,
|
||||||
CLAS, CLDC, CLFM, CLMT, COBJ, COLL,
|
CLAS, CLDC, CLFM, CLMT, COBJ, COLL,
|
||||||
CONT, CPTH, CSTY, DEBR, DIAL, DLBR,
|
CONT, CPTH, CSTY, DEBR, DIAL, DLBR,
|
||||||
DLVW, DOBJ, DOOR, DUAL, ECZN, EFSH,
|
DLVW, DOBJ, DOOR, DUAL, ECZN, EFSH,
|
||||||
ENCH, EQUP, EXPL, EYES, FACT, FLOR,
|
ENCH, EQUP, EXPL, EYES, FACT, FLOR,
|
||||||
FLST, FSTP, FSTS, FURN, GLOB, GMST,
|
FLST, FSTP, FSTS, FURN, GLOB, GMST,
|
||||||
GRAS, GRUP, HAIR, HAZD, HDPT, IDLE,
|
GRAS, GRUP, HAIR, HAZD, HDPT, IDLE,
|
||||||
IDLM, IMAD, IMGS, INFO, INGR, IPCT,
|
IDLM, IMAD, IMGS, INFO, INGR, IPCT,
|
||||||
IPDS, KEYM, KYWD, LAND, LCRT, LCTN,
|
IPDS, KEYM, KYWD, LAND, LCRT, LCTN,
|
||||||
LGTM, LIGH, LSCR, LTEX, LVLI, LVLN,
|
LGTM, LIGH, LSCR, LTEX, LVLI, LVLN,
|
||||||
LVSP, MATO, MATT, MESG, MGEF, MISC,
|
LVSP, MATO, MATT, MESG, MGEF, MISC,
|
||||||
MOVT, MSTT, MUSC, MUST, NAVI, NAVM,
|
MOVT, MSTT, MUSC, MUST, NAVI, NAVM,
|
||||||
NOTE, NPC_, OTFT, PACK, PERK, PGRE,
|
NOTE, NPC_, OTFT, PACK, PERK, PGRE,
|
||||||
PHZD, PROJ, PWAT, QUST, RACE, REFR,
|
PHZD, PROJ, PWAT, QUST, RACE, REFR,
|
||||||
REGN, RELA, REVB, RFCT, RGDL, SCEN,
|
REGN, RELA, REVB, RFCT, RGDL, SCEN,
|
||||||
SCOL, SCPT, SCRL, SHOU, SLGM, SMBN,
|
SCOL, SCPT, SCRL, SHOU, SLGM, SMBN,
|
||||||
SMEN, SMQN, SNCT, SNDR, SOPM, SOUN,
|
SMEN, SMQN, SNCT, SNDR, SOPM, SOUN,
|
||||||
SPEL, SPGD, STAT, TACT, TES4, TREE,
|
SPEL, SPGD, STAT, TACT, TES4, TREE,
|
||||||
TXST, VTYP, WATR, WEAP, WOOP, WRLD,
|
TXST, VTYP, WATR, WEAP, WOOP, WRLD,
|
||||||
WTHR,
|
WTHR,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Group type enum
|
// Group type enum
|
||||||
enum group_type {
|
enum group_type {
|
||||||
GT_TOP = 0,
|
GT_TOP = 0,
|
||||||
GT_WORLD_CHILDREN = 1,
|
GT_WORLD_CHILDREN = 1,
|
||||||
GT_INTERIOR_CELL_BLOCK = 2,
|
GT_INTERIOR_CELL_BLOCK = 2,
|
||||||
GT_INTERIOR_CELL_SUBBLOCK = 3,
|
GT_INTERIOR_CELL_SUBBLOCK = 3,
|
||||||
GT_EXTERIOR_CELL_BLOCK = 4,
|
GT_EXTERIOR_CELL_BLOCK = 4,
|
||||||
GT_EXTERIOR_CELL_SUBBLOCK = 5,
|
GT_EXTERIOR_CELL_SUBBLOCK = 5,
|
||||||
GT_CELL_CHILDREN = 6,
|
GT_CELL_CHILDREN = 6,
|
||||||
GT_TOPIC_CHILDREN = 7,
|
GT_TOPIC_CHILDREN = 7,
|
||||||
GT_CELL_PERSISTENT_CHILDREN = 8,
|
GT_CELL_PERSISTENT_CHILDREN = 8,
|
||||||
GT_CELL_TEMPORARY_CHILDREN = 9,
|
GT_CELL_TEMPORARY_CHILDREN = 9,
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// === COMPOSITE TYPES ===
|
// === COMPOSITE TYPES ===
|
||||||
//
|
//
|
||||||
|
|
||||||
// Generic node in the esp/esm tree
|
// Generic node in the esp/esm tree
|
||||||
typedef struct node Node;
|
typedef struct node Node;
|
||||||
struct node {
|
struct node {
|
||||||
union {
|
union {
|
||||||
Group *group;
|
Group *group;
|
||||||
Record *record;
|
Record *record;
|
||||||
} header;
|
} header;
|
||||||
char *data;
|
char *data;
|
||||||
enum node_type type;
|
enum node_type type;
|
||||||
uint32_t _pad;
|
uint32_t _pad;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Used for passing around parsed timestamps
|
// Used for passing around parsed timestamps
|
||||||
struct timestamp {
|
struct timestamp {
|
||||||
uint16_t year;
|
uint16_t year;
|
||||||
uint8_t month;
|
uint8_t month;
|
||||||
uint8_t day;
|
uint8_t day;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Given to espr_walk.
|
/* Given to espr_walk.
|
||||||
*
|
*
|
||||||
* pre is called before the children of the current node have been walked
|
* pre is called before the children of the current node have been
|
||||||
* post is called after the children of the current node have been walked
|
* walked post is called after the children of the current node have
|
||||||
*
|
* been walked
|
||||||
* carry_out and carry_in is a pointer to a void * on the stack that can be
|
*
|
||||||
* used for passing data between pre and post for a node.
|
* carry_out and carry_in is a pointer to a void * on the stack that can
|
||||||
*
|
* be used for passing data between pre and post for a node.
|
||||||
* data is a pointer that the user can supply when calling espr_walk that
|
*
|
||||||
* will be passed to pre and post when they are called.
|
* data is a pointer that the user can supply when calling espr_walk
|
||||||
*/
|
* that will be passed to pre and post when they are called.
|
||||||
struct walker_callbacks {
|
*/
|
||||||
void (*pre)(Node n, void *data, void **carry_out, void *from_parent, void **to_children);
|
struct walker_callbacks {
|
||||||
void (*post)(Node n, void *data, void *carry_in);
|
void (*pre)(
|
||||||
void *data;
|
Node n,
|
||||||
};
|
void *data,
|
||||||
|
void **carry_out,
|
||||||
|
void *from_parent,
|
||||||
|
void **to_children
|
||||||
|
);
|
||||||
|
void (*post)(Node n, void *data, void *carry_in);
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
/* Meta Nodes are used for constructing a more flexible tree structure
|
/* Meta Nodes are used for constructing a more flexible tree structure
|
||||||
* on top of the natural structure of ESP/ESM files.
|
* on top of the natural structure of ESP/ESM files.
|
||||||
*
|
*
|
||||||
* Meta Nodes do not create a pure tree structure, rather they have pointers to
|
* Meta Nodes do not create a pure tree structure, rather they have
|
||||||
* their parent and first child, and children have pointers backwards and
|
* pointers to their parent and first child, and children have pointers
|
||||||
* forward through a linked list of all of the children of the parent node.
|
* 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.
|
* 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
|
* While the ESP/ESM buffer can be modified in-place, any modification
|
||||||
* without first shifting all of the data after the point of 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
|
||||||
* Modifications that change data size are:
|
* of modification.
|
||||||
* - Adding or deleting a group or record
|
*
|
||||||
* - Adding or deleting a field in a record
|
* Modifications that change data size are:
|
||||||
* - Changing a variable length field with data of different length
|
* - Adding or deleting a group or record
|
||||||
*
|
* - Adding or deleting a field in a record
|
||||||
* With a Meta Node you can instead allocate new, arbitrarily sized memory for
|
* - Changing a variable length field with data of different length
|
||||||
* the node data. The Meta Node tree can then be walked to reconstruct a
|
*
|
||||||
* contiguous view of discontiguous memory.
|
* 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
|
||||||
struct meta_node {
|
* reconstruct a contiguous view of discontiguous memory.
|
||||||
Node n;
|
*/
|
||||||
MetaNode *parent;
|
struct meta_node {
|
||||||
MetaNode *first_child;
|
Node n;
|
||||||
MetaNode *last_child;
|
MetaNode *parent;
|
||||||
MetaNode *prev;
|
MetaNode *first_child;
|
||||||
MetaNode *next;
|
MetaNode *last_child;
|
||||||
};
|
MetaNode *prev;
|
||||||
|
MetaNode *next;
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// === BINARY DATA OVERLAYS ===
|
// === BINARY DATA OVERLAYS ===
|
||||||
//
|
//
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
// Group header overlay
|
// Group header overlay
|
||||||
struct group {
|
struct group {
|
||||||
Type4 grup; // always RT_GRUP
|
Type4 grup; // always RT_GRUP
|
||||||
uint32_t size; // uncludes the 24 byte group header
|
uint32_t size; // uncludes the 24 byte group header
|
||||||
union {
|
union {
|
||||||
Type4 type; // this may be mangled and should not be relied on
|
Type4 type; // this may be mangled, do not rely on
|
||||||
formid formid;
|
formid formid;
|
||||||
int32_t number;
|
int32_t number;
|
||||||
int16_t coord[2];
|
int16_t coord[2];
|
||||||
} label; // access determined by the `type` below
|
} label; // access determined by the `type` below
|
||||||
int32_t type; // group_type enum
|
int32_t type; // group_type enum
|
||||||
uint16_t timestamp;
|
uint16_t timestamp;
|
||||||
uint16_t vcinfo;
|
uint16_t vcinfo;
|
||||||
uint32_t unknown;
|
uint32_t unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Record header overlay
|
// Record header overlay
|
||||||
struct record {
|
struct record {
|
||||||
Type4 type;
|
Type4 type;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint32_t formid;
|
uint32_t formid;
|
||||||
uint16_t timestamp;
|
uint16_t timestamp;
|
||||||
uint16_t vcinfo;
|
uint16_t vcinfo;
|
||||||
uint16_t version;
|
uint16_t version;
|
||||||
uint16_t unknown;
|
uint16_t unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Field header overlay
|
// Field header overlay
|
||||||
struct field {
|
struct field {
|
||||||
Type4 type;
|
Type4 type;
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
@@ -284,77 +293,78 @@ extern "C" {
|
|||||||
//
|
//
|
||||||
|
|
||||||
// record type enum to fourcc value
|
// record type enum to fourcc value
|
||||||
extern const uint32_t rt[RT_SIZE];
|
extern const uint32_t rt[RT_SIZE];
|
||||||
|
|
||||||
// for converting between record_type and record_type_hash enums
|
// for converting between record_type and record_type_hash enums
|
||||||
extern const uint16_t rt2rth[RT_SIZE];
|
extern const uint16_t rt2rth[RT_SIZE];
|
||||||
extern const uint8_t rth2rt[RT_HASH_SIZE];
|
extern const uint8_t rth2rt[RT_HASH_SIZE];
|
||||||
|
|
||||||
// type -> flag mappings
|
// type -> flag mappings
|
||||||
// NULL table pointers indicate no flags
|
// NULL table pointers indicate no flags
|
||||||
// NULL string pointers indicate invalid flag
|
// NULL string pointers indicate invalid flag
|
||||||
extern rfs_inner *const rfs[RT_SIZE];
|
extern rfs_inner *const rfs[RT_SIZE];
|
||||||
extern rfs_inner *const rfs_refr[RT_SIZE];
|
extern rfs_inner *const rfs_refr[RT_SIZE];
|
||||||
|
|
||||||
// Expected (probably) order of top level groups in an esp/esm
|
// Expected (probably) order of top level groups in an esp/esm
|
||||||
extern const enum record_type group_order[GO_SIZE];
|
extern const enum record_type group_order[GO_SIZE];
|
||||||
|
|
||||||
// Printable strings for group types
|
// Printable strings for group types
|
||||||
extern const struct str_lit group_type_strings[GTS_SIZE];
|
extern const struct str_lit group_type_strings[GTS_SIZE];
|
||||||
|
|
||||||
//
|
//
|
||||||
// === FUNCTIONS ===
|
// === FUNCTIONS ===
|
||||||
//
|
//
|
||||||
|
|
||||||
// hashes type value into a record type enum value
|
// hashes type value into a record type enum value
|
||||||
inline uint32_t rt_hash(uint32_t type) {
|
inline uint32_t rt_hash(uint32_t type) {
|
||||||
return rth2rt[uint32_t_msh(type, RT_HASH_BITS, RT_HASH_SEED)];
|
return rth2rt[uint32_t_msh(type, RT_HASH_BITS, RT_HASH_SEED)];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* `espr_walk` walks through the tree structure of the esp/esm binary data
|
/* `espr_walk` walks through the tree structure of the esp/esm binary
|
||||||
* starting at `data` of `size` bytes.
|
* data starting at `data` of `size` bytes.
|
||||||
*
|
*
|
||||||
* `cb` is a callback that takes a `Node` to process. `pt` is a pointer to
|
* `cb` is a callback that takes a `Node` to process. `pt` is a pointer
|
||||||
* arbitrary data that is passed on to `cb` whenever it is called.
|
* to arbitrary data that is passed on to `cb` whenever it is called.
|
||||||
*
|
*
|
||||||
* 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);
|
||||||
|
|
||||||
/* `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.
|
||||||
*/
|
*/
|
||||||
void espr_print(char *data, size_t size);
|
void espr_print(char *data, size_t size);
|
||||||
|
|
||||||
/* Calculates the number of groups and records in the esp/esm file and the
|
/* Calculates the number of groups and records in the esp/esm file and
|
||||||
* size of the esp/esm if all of the compressed records were decompressed.
|
* the size of the esp/esm if all of the compressed records were
|
||||||
*/
|
* decompressed.
|
||||||
struct esp_stats espr_stats(char *data, size_t size);
|
*/
|
||||||
|
struct esp_stats espr_stats(char *data, size_t size);
|
||||||
|
|
||||||
// Calculates the number of formid's in an esm/esp from the stats
|
// Calculates the number of formid's in an esm/esp from the stats
|
||||||
inline uint32_t espr_formid_count(struct esp_stats stats) {
|
inline uint32_t espr_formid_count(struct esp_stats stats) {
|
||||||
return stats.record_count;
|
return stats.record_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculates the number of nodes in the esp/esm from the stats
|
// Calculates the number of nodes in the esp/esm from the stats
|
||||||
inline uint32_t espr_node_count(struct esp_stats stats) {
|
inline uint32_t espr_node_count(struct esp_stats stats) {
|
||||||
return stats.record_count + stats.group_count;
|
return stats.record_count + stats.group_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculates the size of a MetaNode tree constructed over the esp/esm for
|
// Calculates the size of a MetaNode tree constructed over the esp/esm
|
||||||
// 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) * espr_node_count(stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copies the data from `data` to `buf` decompressing compressed fields as
|
/* Copies the data from `data` to `buf` decompressing compressed fields
|
||||||
* 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);
|
||||||
|
|
||||||
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
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
938
espReader/LUT.c
938
espReader/LUT.c
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user