HCountedArray *h_carray_new_sized(HArena * arena, size_t size) { HCountedArray *ret = h_arena_malloc(arena, sizeof(HCountedArray)); if (size == 0) size = 1; ret->used = 0; ret->capacity = size; ret->arena = arena; ret->elements = h_arena_malloc(arena, sizeof(void*) * size); return ret; }
void h_hashtable_put(HHashTable* ht, void* key, void* value) { // # Start with a rebalancing //h_hashtable_ensure_capacity(ht, ht->used + 1); HHashValue hashval = ht->hashFunc(key); #ifdef CONSISTENCY_CHECK assert((ht->capacity & (ht->capacity - 1)) == 0); // capacity is a power of 2 #endif HHashTableEntry *hte = &ht->contents[hashval & (ht->capacity - 1)]; if (hte->key != NULL) { do { if (hte->hashval == hashval && ht->equalFunc(key, hte->key)) goto insert_here; if (hte->next != NULL) hte = hte->next; } while (hte->next != NULL); // Add a new link... assert (hte->next == NULL); hte->next = h_arena_malloc(ht->arena, sizeof(HHashTableEntry)); hte = hte->next; hte->next = NULL; ht->used++; } else ht->used++; insert_here: hte->key = key; hte->value = value; hte->hashval = hashval; }
HParsedToken *h_make_bytes(HArena *arena, size_t len) { HParsedToken *ret = h_make_(arena, TT_BYTES); ret->bytes.len = len; ret->bytes.token = h_arena_malloc(arena, len); return ret; }
HLRAction *h_shift_action(HArena *arena, size_t nextstate) { HLRAction *action = h_arena_malloc(arena, sizeof(HLRAction)); action->type = HLR_SHIFT; action->nextstate = nextstate; return action; }
void h_slist_push(HSlist *slist, void* item) { HSlistNode *hnode = h_arena_malloc(slist->arena, sizeof(HSlistNode)); hnode->elem = item; hnode->next = slist->head; // write memory barrier here. slist->head = hnode; }
void h_hashtable_put_raw(HHashTable* ht, HHashTableEntry *new_entry) { #ifdef CONSISTENCY_CHECK assert((ht->capacity & (ht->capacity - 1)) == 0); // capacity is a power of 2 #endif HHashTableEntry *hte = &ht->contents[new_entry->hashval & (ht->capacity - 1)]; if (hte->key != NULL) { for(;;) { // check each link, stay on last if not found if (hte->hashval == new_entry->hashval && ht->equalFunc(new_entry->key, hte->key)) goto insert_here; if (hte->next == NULL) break; hte = hte->next; } // Add a new link... assert (hte->next == NULL); hte->next = h_arena_malloc(ht->arena, sizeof(HHashTableEntry)); hte = hte->next; hte->next = NULL; ht->used++; } else ht->used++; insert_here: hte->key = new_entry->key; hte->value = new_entry->value; hte->hashval = new_entry->hashval; }
HHashTable* h_hashtable_new(HArena *arena, HEqualFunc equalFunc, HHashFunc hashFunc) { HHashTable *ht = h_arena_malloc(arena, sizeof(HHashTable)); ht->hashFunc = hashFunc; ht->equalFunc = equalFunc; ht->capacity = 64; // to start; should be tuned later... ht->used = 0; ht->arena = arena; ht->contents = h_arena_malloc(arena, sizeof(HHashTableEntry) * ht->capacity); for (size_t i = 0; i < ht->capacity; i++) { ht->contents[i].key = NULL; ht->contents[i].value = NULL; ht->contents[i].next = NULL; ht->contents[i].hashval = 0; } //memset(ht->contents, 0, sizeof(HHashTableEntry) * ht->capacity); return ht; }
const HParsedToken *act_txt(const HParseResult *p) { dns_rr_txt_t *txt = H_ALLOC(dns_rr_txt_t); const HCountedArray *arr = H_CAST_SEQ(p->ast); uint8_t **ret = h_arena_malloc(arr->arena, sizeof(uint8_t*)*arr->used); for (size_t i=0; i<arr->used; ++i) { size_t len = h_seq_len(arr->elements[i]); uint8_t *tmp = h_arena_malloc(arr->arena, sizeof(uint8_t)*len); for (size_t j=0; j<len; ++j) tmp[j] = H_INDEX_UINT(arr->elements[i], j); ret[i] = tmp; } txt->count = arr->used; txt->txt_data = ret; return H_MAKE(dns_rr_txt_t, txt); }
static inline HLRTransition *transition(HArena *arena, size_t x, const HCFChoice *A, size_t y) { HLRTransition *t = h_arena_malloc(arena, sizeof(HLRTransition)); t->from = x; t->symbol = A; t->to = y; return t; }
const HParsedToken *act_null(const HParseResult *p) { dns_rr_null_t *null = H_ALLOC(dns_rr_null_t); size_t len = h_seq_len(p->ast); uint8_t *buf = h_arena_malloc(p->arena, sizeof(uint8_t)*len); for (size_t i=0; i<len; ++i) buf[i] = H_FIELD_UINT(i); return H_MAKE(dns_rr_null_t, null); }
HLRAction *h_reduce_action(HArena *arena, const HLRItem *item) { HLRAction *action = h_arena_malloc(arena, sizeof(HLRAction)); action->type = HLR_REDUCE; action->production.lhs = item->lhs; action->production.length = item->len; #ifndef NDEBUG action->production.rhs = item->rhs; #endif return action; }
void h_carray_append(HCountedArray *array, void* item) { if (array->used >= array->capacity) { HParsedToken **elements = h_arena_malloc(array->arena, (array->capacity *= 2) * sizeof(HCountedArray*)); for (size_t i = 0; i < array->used; i++) elements[i] = array->elements[i]; for (size_t i = array->used; i < array->capacity; i++) elements[i] = 0; array->elements = elements; } array->elements[array->used++] = item; }
const HParsedToken* act_wks(const HParseResult *p) { dns_rr_wks_t *wks = H_ALLOC(dns_rr_wks_t); wks->address = H_FIELD_UINT(0); wks->protocol = H_FIELD_UINT(1); wks->len = H_FIELD_SEQ(2)->used; wks->bit_map = h_arena_malloc(p->arena, sizeof(uint8_t)*wks->len); for (size_t i=0; i<wks->len; ++i) wks->bit_map[i] = H_INDEX_UINT(p->ast, 2, i); return H_MAKE(dns_rr_wks_t, wks); }
const HParsedToken* act_cstr(const HParseResult *p) { dns_cstr_t *cs = H_ALLOC(dns_cstr_t); const HCountedArray *arr = H_CAST_SEQ(p->ast); uint8_t *ret = h_arena_malloc(arr->arena, sizeof(uint8_t)*arr->used); for (size_t i=0; i<arr->used; ++i) ret[i] = H_CAST_UINT(arr->elements[i]); assert(ret[arr->used-1] == '\0'); // XXX Is this right?! If so, shouldn't it be a validation? *cs = ret; return H_MAKE(dns_cstr_t, cs); }
HLRTable *h_lrtable_new(HAllocator *mm__, size_t nrows) { HArena *arena = h_new_arena(mm__, 0); // default blocksize assert(arena != NULL); HLRTable *ret = h_new(HLRTable, 1); ret->nrows = nrows; ret->ntmap = h_arena_malloc(arena, nrows * sizeof(HHashTable *)); ret->tmap = h_arena_malloc(arena, nrows * sizeof(HStringMap *)); ret->forall = h_arena_malloc(arena, nrows * sizeof(HLRAction *)); ret->inadeq = h_slist_new(arena); ret->arena = arena; ret->mm__ = mm__; for(size_t i=0; i<nrows; i++) { ret->ntmap[i] = h_hashtable_new(arena, h_eq_symbol, h_hash_symbol); ret->tmap[i] = h_stringmap_new(arena); ret->forall[i] = NULL; } return ret; }
static HParsedToken* reshape_optional(const HParseResult *p, void* user_data) { assert(p->ast); assert(p->ast->token_type == TT_SEQUENCE); if (p->ast->seq->used > 0) { HParsedToken *res = p->ast->seq->elements[0]; if(res) return res; } HParsedToken *ret = h_arena_malloc(p->arena, sizeof(HParsedToken)); ret->token_type = TT_NONE; return ret; }
HLRItem *h_lritem_new(HArena *a, HCFChoice *lhs, HCFChoice **rhs, size_t mark) { HLRItem *ret = h_arena_malloc(a, sizeof(HLRItem)); size_t len = 0; for(HCFChoice **p=rhs; *p; p++) len++; assert(mark <= len); ret->lhs = lhs; ret->rhs = rhs; ret->len = len; ret->mark = mark; return ret; }
static HParsedToken *act_bytes(const HParseResult *p, void *user) { DNP3_Object *o = H_ALLOC(DNP3_Object); HCountedArray *a = H_CAST_SEQ(p->ast); size_t n = a->used; o->applid.len = n; o->applid.str = h_arena_malloc(p->arena, n+1); // null-terminate for(size_t i=0; i<n; i++) o->applid.str[i] = H_CAST_UINT(a->elements[i]); o->applid.str[n] = '\0'; return H_MAKE(DNP3_Object, o); }
// no-op on terminal symbols static void transform_productions(const HLRTable *table, HLREnhGrammar *eg, size_t x, HCFChoice *xAy) { if (xAy->type != HCF_CHOICE) { return; } // XXX CHARSET? HArena *arena = eg->arena; HCFSequence **seq = h_arena_malloc(arena, seqsize(xAy->seq) * sizeof(HCFSequence *)); HCFSequence **p, **q; for(p=xAy->seq, q=seq; *p; p++, q++) { // trace rhs starting in state x and following the transitions // xAy -> ... iBj ... size_t i = x; HCFChoice **B = (*p)->items; HCFChoice **items = h_arena_malloc(arena, seqsize(B) * sizeof(HCFChoice *)); HCFChoice **iBj = items; for(; *B; B++, iBj++) { size_t j = follow_transition(table, i, *B); HLRTransition *i_B_j = transition(arena, i, *B, j); *iBj = h_hashtable_get(eg->tmap, i_B_j); assert(*iBj != NULL); i = j; } *iBj = NULL; *q = h_arena_malloc(arena, sizeof(HCFSequence)); (*q)->items = items; } *q = NULL; xAy->seq = seq; }
static HCFChoice *new_enhanced_symbol(HLREnhGrammar *eg, const HCFChoice *sym) { HArena *arena = eg->arena; HCFChoice *esym = h_arena_malloc(arena, sizeof(HCFChoice)); *esym = *sym; HHashSet *cs = h_hashtable_get(eg->corr, sym); if (!cs) { cs = h_hashset_new(arena, h_eq_symbol, h_hash_symbol); h_hashtable_put(eg->corr, sym, cs); } h_hashset_put(cs, esym); return esym; }
static HParsedToken *act_segment(const HParseResult *p, void *user) { DNP3_Segment *s = H_ALLOC(DNP3_Segment); s->fin = H_FIELD_UINT(0, 0); s->fir = H_FIELD_UINT(0, 1); s->seq = H_FIELD_UINT(0, 2); HCountedArray *a = H_FIELD_SEQ(1); s->len = a->used; s->payload = h_arena_malloc(p->arena, s->len); assert(s->payload != NULL); for(size_t i=0; i<s->len; i++) { s->payload[i] = H_CAST_UINT(a->elements[i]); } return H_MAKE(DNP3_Segment, s); }
HSlist* h_slist_copy(HSlist *slist) { HSlist *ret = h_slist_new(slist->arena); HSlistNode *head = slist->head; HSlistNode *tail; if (head != NULL) { h_slist_push(ret, head->elem); tail = ret->head; head = head->next; while (head != NULL) { // append head item to tail in a new node HSlistNode *node = h_arena_malloc(slist->arena, sizeof(HSlistNode)); node->elem = head->elem; node->next = NULL; tail = tail->next = node; head = head->next; } } return ret; }
void h_hashtable_ensure_capacity(HHashTable* ht, size_t n) { bool do_resize = false; size_t old_capacity = ht->capacity; while (n * 1.3 > ht->capacity) { ht->capacity *= 2; do_resize = true; } if (!do_resize) return; HHashTableEntry *old_contents = ht->contents; HHashTableEntry *new_contents = h_arena_malloc(ht->arena, sizeof(HHashTableEntry) * ht->capacity); ht->contents = new_contents; ht->used = 0; memset(new_contents, 0, sizeof(HHashTableEntry) * ht->capacity); for (size_t i = 0; i < old_capacity; ++i) for (HHashTableEntry *entry = &old_contents[i]; entry; entry = entry->next) if (entry->key) h_hashtable_put_raw(ht, entry); //h_arena_free(ht->arena, old_contents); }
HParsedToken* act_domain(const HParseResult *p, void* user_data) { HParsedToken *ret = NULL; char *arr = NULL; switch(p->ast->token_type) { case TT_UINT: arr = " "; break; case TT_SEQUENCE: // Sequence of subdomains separated by "." // Each subdomain is a label, which can be no more than 63 chars. arr = h_arena_malloc(p->arena, 64*p->ast->seq->used); size_t count = 0; for (size_t i=0; i<p->ast->seq->used; ++i) { HParsedToken *tmp = p->ast->seq->elements[i]; for (size_t j=0; j<tmp->seq->used; ++j) { arr[count] = tmp->seq->elements[i]->uint; ++count; } arr[count] = '.'; ++count; } arr[count-1] = '\x00'; break; default: arr = NULL; ret = NULL; } if(arr) { dns_domain_t *val = H_ALLOC(dns_domain_t); // dns_domain_t is char* *val = arr; ret = H_MAKE(dns_domain_t, val); } return ret; }
static HLREnhGrammar *enhance_grammar(const HCFGrammar *g, const HLRDFA *dfa, const HLRTable *table) { HAllocator *mm__ = g->mm__; HArena *arena = g->arena; HLREnhGrammar *eg = h_arena_malloc(arena, sizeof(HLREnhGrammar)); eg->tmap = h_hashtable_new(arena, h_eq_transition, h_hash_transition); eg->smap = h_hashtable_new(arena, h_eq_ptr, h_hash_ptr); eg->corr = h_hashtable_new(arena, h_eq_symbol, h_hash_symbol); // XXX must use h_eq/hash_ptr for symbols! so enhanced CHARs are different eg->arena = arena; // establish mapping between transitions and symbols for(HSlistNode *x=dfa->transitions->head; x; x=x->next) { HLRTransition *t = x->elem; assert(!h_hashtable_present(eg->tmap, t)); HCFChoice *sym = new_enhanced_symbol(eg, t->symbol); h_hashtable_put(eg->tmap, t, sym); h_hashtable_put(eg->smap, sym, t); } // transform the productions H_FOREACH(eg->tmap, HLRTransition *t, HCFChoice *sym) transform_productions(table, eg, t->from, sym); H_END_FOREACH // add the start symbol HCFChoice *start = new_enhanced_symbol(eg, g->start); transform_productions(table, eg, 0, start); eg->grammar = h_cfgrammar_(mm__, start); return eg; }
action->production.lhs = item->lhs; action->production.length = item->len; #ifndef NDEBUG action->production.rhs = item->rhs; #endif return action; } // adds 'new' to the branches of 'action' // returns a 'action' if it is already of type HLR_CONFLICT // allocates a new HLRAction otherwise HLRAction *h_lr_conflict(HArena *arena, HLRAction *action, HLRAction *new) { if(action->type != HLR_CONFLICT) { HLRAction *old = action; action = h_arena_malloc(arena, sizeof(HLRAction)); action->type = HLR_CONFLICT; action->branches = h_slist_new(arena); h_slist_push(action->branches, old); h_slist_push(action->branches, new); } else { // check if 'new' is already among branches HSlistNode *x; for(x=action->branches->head; x; x=x->next) { if(x->elem == new) break; } // add 'new' if it is not already in list if(x == NULL) h_slist_push(action->branches, new); }
// Low-level helper for the h_make family. HParsedToken *h_make_(HArena *arena, HTokenType type) { HParsedToken *ret = h_arena_malloc(arena, sizeof(HParsedToken)); ret->token_type = type; return ret; }
// HSlist HSlist* h_slist_new(HArena *arena) { HSlist *ret = h_arena_malloc(arena, sizeof(HSlist)); ret->head = NULL; ret->arena = arena; return ret; }