Newer
Older
Import / research / ui / toolkit / experiment / idea.cpp

// 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[];
};