+
+#define CORRECT_POOL_SIZE (128*1024*1024)
+/*
+ * A forward allcator for the corrector. This corrector requires a lot
+ * of allocations. This forward allocator combats all those allocations
+ * and speeds us up a little. It also saves us space in a way since each
+ * allocation isn't wasting a little header space for when NOTRACK isn't
+ * defined.
+ */
+static unsigned char **correct_pool_data = NULL;
+static unsigned char *correct_pool_this = NULL;
+static size_t correct_pool_addr = 0;
+
+static GMQCC_INLINE void correct_pool_new(void) {
+ correct_pool_addr = 0;
+ correct_pool_this = (unsigned char *)mem_a(CORRECT_POOL_SIZE);
+
+ vec_push(correct_pool_data, correct_pool_this);
+}
+
+static GMQCC_INLINE void *correct_pool_alloc(size_t bytes) {
+ void *data;
+ if (correct_pool_addr + bytes>= CORRECT_POOL_SIZE)
+ correct_pool_new();
+
+ data = (void*)correct_pool_this;
+ correct_pool_this += bytes;
+ correct_pool_addr += bytes;
+ return data;
+}
+
+static GMQCC_INLINE void correct_pool_delete(void) {
+ size_t i;
+ for (i = 0; i < vec_size(correct_pool_data); ++i)
+ mem_d(correct_pool_data[i]);
+
+ correct_pool_data = NULL;
+ correct_pool_this = NULL;
+ correct_pool_addr = 0;
+}
+
+
+static GMQCC_INLINE char *correct_pool_claim(const char *data) {
+ char *claim = util_strdup(data);
+ correct_pool_delete();
+ return claim;
+}
+
+/*
+ * A fast space efficent trie for a dictionary of identifiers. This is
+ * faster than a hashtable for one reason. A hashtable itself may have
+ * fast constant lookup time, but the hash itself must be very fast. We
+ * have one of the fastest hash functions for strings, but if you do a
+ * lost of hashing (which we do, almost 3 million hashes per identifier)
+ * a hashtable becomes slow.
+ */
+correct_trie_t* correct_trie_new() {
+ correct_trie_t *t = (correct_trie_t*)mem_a(sizeof(correct_trie_t));
+ t->value = NULL;
+ t->entries = NULL;
+ return t;
+}
+
+void correct_trie_del_sub(correct_trie_t *t) {
+ size_t i;
+ for (i = 0; i < vec_size(t->entries); ++i)
+ correct_trie_del_sub(&t->entries[i]);
+ vec_free(t->entries);
+}
+
+void correct_trie_del(correct_trie_t *t) {
+ size_t i;
+ for (i = 0; i < vec_size(t->entries); ++i)
+ correct_trie_del_sub(&t->entries[i]);
+ vec_free(t->entries);
+ mem_d(t);
+}
+
+void* correct_trie_get(const correct_trie_t *t, const char *key) {
+ const unsigned char *data = (const unsigned char*)key;
+
+ while (*data) {
+ const correct_trie_t *entries = t->entries;
+ unsigned char ch = *data;
+ const size_t vs = vec_size(entries);
+ size_t i;
+
+ for (i = 0; i < vs; ++i) {
+ if (entries[i].ch == ch) {
+ t = &entries[i];
+ ++data;
+ break;
+ }
+ }
+ if (i == vs)
+ return NULL;
+ }
+ return t->value;