// Marshalling / Demarshalling
// One way
// In-memory use machine native endian order
// At point of serialize/marshal, eg: send to network or send to disk, convert endian at that point
// Pro
// optimizes for access, already in correct endianess
// Con
// touches and converts even if not accessed or used
// Other way
// In-memory in network order
// Convert at point of access
// Pro
// can mmap in to memory - no cost, don't touch memory that can stay paged out
// Con
// access speed of frequently accessed values might be slower depending on code and machine
//
// Other points
// pointers
// different approaches
// one is to avoid pointers and everything is an index
// other is to convert pointers to indexes and back to pointers at serialization/deserialization
// issues with mmap of variable length arrays
// how to represent the data structures in a way that you can just mmap in everything and then
// access it with zero processing? Maybe possible.
// If just one variable length array, then just stick it at the end, but if multiple?
// Eg:
struct Everything {
struct Header {
int ver;
} header;
struct Data1 {
int len;
char charVals[];
} data1;
struct Data2 {
int len;
int intVals[];
} data2;
};
// This example has 2 different types also for the variable length part,
// making it more tricky
// Typically in a file, you layout like this:
/*
int header.ver = 1;
int data1.len = 100;
char data1.charVals[100];
int data2.len = 50;
int data2.intVals[50];
*/
// Some file formats will add offsets to the data sections like this:
/*
int header.ver = 1;
size_t header.data1Offset = 12; // offset from start of file to data1
size_t header.data2Offset = 116; // offset from start of file to data2
int data1.len = 100;
char data1.charVals[100];
int data2.len = 50;
int data2.intVals[50];
*/
// This additional information might help us
typedef uint8_t TTF_UINT8;
// Allows us to map in bytes from a file irrespective of the machine's endianess
struct TTF_UINT16
{
operator uint16_t() { return uint16_t(v1 << 8) | v2; }
private: TTF_UINT8 v1, v2;
};
struct TTF_UINT32
{
operator uint32_t() { return uint32_t(v1 << 24) | uint32_t(v2 << 16) | uint32_t(v3 << 8) | v4; }
private: TTF_UINT8 v1, v2, v3, v4;
};
/*
struct TTF_TABLE
{
};
struct TTF_Contents
{
};
*/
struct TTF_TOC_ENTRY
{
TTF_UINT32 tag, checksum, offset, length;
};
struct TTF_GENERIC_TABLE // TODO: refector where this pattern is used in the file format
{
TTF_UINT16 segCountX2; // 2 * segCount
TTF_UINT16 searchRange; // 2 * (2**FLOOR(log2(segCount)))
TTF_UINT16 entrySelector; // log2(searchRange/2)
TTF_UINT16 rangeShift; // (2 * segCount) - searchRange
};
struct TTF_HEADER // #Ref1,Table4 - The offset subtable
{
TTF_UINT32 version; // 'true' 0x74727565 | 0x00010000
TTF_UINT16 tocEntries, searchRange, entrySelector, rangeShift;
TTF_TOC_ENTRY toc[];
};