#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#define TT_TAG_CFF  0x43464620
#define TT_TAG_OTF  0x4f54544f

static __attribute__((always_inline)) inline uint32_t av_bswap32(uint32_t x)
{
    __asm__("bswap   %0" : "+r" (x));
    return x;
}

unsigned int ComputeTableChecksum(unsigned char *data, unsigned int length) {
  unsigned int i, checksum = 0, *data32 = (unsigned int*)data;

  for (i = 0; i < (length>>2); i++) {
    checksum += av_bswap32(data32[i]);
  }
  if (length & 3) {
    unsigned int word = 0;
    i = length & ~3;
    switch (length & 3) {
    case 3:
      word |= (data[i+2] & 0xff) <<  8;
    case 2:
      word |= (data[i+1] & 0xff) << 16;
    case 1:
      word |= (data[i  ] & 0xff) << 24;
      break;
    }
    checksum += word;
  }
  return checksum;
}

unsigned char *cff_from_otf(unsigned char *p, unsigned int *len)
{
  unsigned int pos = 0, i = 0, *h32 = (unsigned int*)p, nTables = ((p[4] << 8) || p[5]);

  if (h32[0] != TT_TAG_OTF) return NULL;

  // read the table directory
  pos += 3;
  for (i = 0; i < nTables; ++i) {
    if (av_bswap32(h32[pos+0]) == TT_TAG_CFF) {
        unsigned char *cffdata = p + av_bswap32(h32[pos+2]); // p + cff_offset
        unsigned int cfflen = av_bswap32(h32[pos+3]);
        if (ComputeTableChecksum(cffdata, cfflen) != av_bswap32(h32[pos+1]))
            write(2, "Table checksum error\n", 21);
        if (len)
            *len = cfflen;
        return cffdata;
    }
    pos += 4;
  }
  return NULL;
}

