#define TABLE_KEY_SIZE 64 #define TABLE_NUM_LANES 32 static inline unsigned int APHash(const char* str, unsigned int length) { unsigned int hash = 0xAAAAAAAA; unsigned int i = 0; for (i = 0; i < length; ++str, ++i) { hash ^= ((i & 1) == 0) ? ( (hash << 7) ^ (*str) * (hash >> 3)) : (~((hash << 11) + ((*str) ^ (hash >> 5)))); } return hash; } static inline uint32_t fastModuloReductionDanielLemire(uint32_t v, uint32_t c) { return (((uint64_t)v) * ((uint64_t)c)) >> 32; } static inline uint32_t hash(const char* key, uint32_t keyLength, uint32_t capacity) { uint32_t value = APHash(key, keyLength); return fastModuloReductionDanielLemire(value, capacity); } typedef struct TableEntry { struct TableEntry* next; const char key[TABLE_KEY_SIZE]; ssize_t size; ssize_t align; } TableEntry; typedef struct Table { TableEntry **entries; } Table; static inline TableEntry* lookup(Table *table, const char key[TABLE_KEY_SIZE]) { TableEntry *entry = table->entries[hash(key, TABLE_KEY_SIZE, TABLE_NUM_LANES)]; for (; entry != NULL; entry = entry->next) { if (memcmp(entry->key, key, TABLE_KEY_SIZE) == 0) { return entry; } } return NULL; } static inline void insert(Table *table, const char key[TABLE_KEY_SIZE], ssize_t size, ssize_t align) { TableEntry *entry = lookup(table, key); if (!entry) { // no entry with that key exists entry = (TableEntry*) calloc(sizeof(TableEntry), 1); strWrite((char*)entry->key, key, TABLE_KEY_SIZE); entry->size = size; entry->align = align; unsigned int hashValue = hash(key, TABLE_KEY_SIZE, TABLE_NUM_LANES); entry->next = table->entries[hashValue]; table->entries[hashValue] = entry; } else { // entry already exists, replace its value entry->size = size; entry->align = align; } } static inline void insertPadZeroes(Table* table, const char* keyToPad, ssize_t size, ssize_t align) { char scratch[64] = { 0 }; for (int i = 0; i < TABLE_KEY_SIZE; i++) { if (keyToPad[i] == '\0') break; scratch[i] = keyToPad[i]; } insert(table, scratch, size, align); } static inline void traversePrint(Table *table) { for (unsigned int i = 0; i < TABLE_NUM_LANES; i++) { TableEntry *entry = table->entries[i]; while (entry != NULL) { printf("entry key: %-64s, size: %lu, align: %lu\n", entry->key, entry->size, entry->align); entry = entry->next; } } } static inline Table* initTable() { Table *table = malloc(sizeof(Table)); table->entries = (TableEntry**) calloc(sizeof(TableEntry*), TABLE_NUM_LANES); // alignof === sizeof for primitive data types, C99 doesn't have 'alignof' insertPadZeroes(table, "char", sizeof(char), sizeof(char)); insertPadZeroes(table, "signed char", sizeof(signed char), sizeof(signed char)); insertPadZeroes(table, "unsigned char", sizeof(unsigned char), sizeof(unsigned char)); insertPadZeroes(table, "short", sizeof(short), sizeof(short)); insertPadZeroes(table, "short int", sizeof(short int), sizeof(short int)); insertPadZeroes(table, "signed short", sizeof(signed short), sizeof(signed short)); insertPadZeroes(table, "signed short int", sizeof(signed short int), sizeof(signed short int)); insertPadZeroes(table, "unsigned short", sizeof(unsigned short), sizeof(unsigned short)); insertPadZeroes(table, "unsigned short int", sizeof(unsigned short int), sizeof(unsigned short int)); insertPadZeroes(table, "int", sizeof(int), sizeof(int)); insertPadZeroes(table, "signed", sizeof(signed), sizeof(signed)); insertPadZeroes(table, "signed int", sizeof(signed int), sizeof(signed int)); insertPadZeroes(table, "unsigned", sizeof(unsigned), sizeof(unsigned)); insertPadZeroes(table, "unsigned int", sizeof(unsigned int), sizeof(unsigned int)); insertPadZeroes(table, "long", sizeof(long), sizeof(long)); insertPadZeroes(table, "long int", sizeof(long int), sizeof(long int)); insertPadZeroes(table, "signed long", sizeof(signed long), sizeof(signed long)); insertPadZeroes(table, "signed long int", sizeof(signed long int), sizeof(signed long int)); insertPadZeroes(table, "unsigned long", sizeof(unsigned long), sizeof(unsigned long)); insertPadZeroes(table, "unsigned long int", sizeof(unsigned long int), sizeof(unsigned long int)); insertPadZeroes(table, "long long", sizeof(long long), sizeof(long long)); insertPadZeroes(table, "long long int", sizeof(long long int), sizeof(long long int)); insertPadZeroes(table, "signed long long", sizeof(signed long long), sizeof(signed long long)); insertPadZeroes(table, "signed long long int", sizeof(signed long long int), sizeof(signed long long int)); insertPadZeroes(table, "unsigned long long", sizeof(unsigned long long), sizeof(unsigned long long)); insertPadZeroes(table, "unsigned long long int", sizeof(unsigned long long int), sizeof(unsigned long long int)); insertPadZeroes(table, "float", sizeof(float), sizeof(float)); insertPadZeroes(table, "double", sizeof(double), sizeof(double)); insertPadZeroes(table, "long double", sizeof(long double), sizeof(long double)); insertPadZeroes(table, "size_t", sizeof(size_t), sizeof(size_t)); insertPadZeroes(table, "ssize_t", sizeof(ssize_t), sizeof(ssize_t)); insertPadZeroes(table, "bool", sizeof(bool), sizeof(bool)); insertPadZeroes(table, "_Bool", sizeof(_Bool), sizeof(_Bool)); return table; } static Table *typeTable;