void down_heap(void *vroot, unsigned size) { struct position **root = vroot; struct position *el; unsigned j; /* Handle common case: removing the only remaining heap element */ if (size == 0) return; el = root[size]; root[size] = root[0]; j = 0; while (left(j) < size) { unsigned child = left(j); if (child + 1 < size && pos_lt(*root[child + 1], *root[child])) child++; if (pos_le(*el, *root[child])) break; root[j] = root[child]; j = child; } root[j] = el; }
void up_heap(void *vroot, unsigned size) { struct position **root = vroot; struct position *el; unsigned j; /* Handle common case: inserting element to empty heap */ if (size == 0) return; j = size; el = root[j]; if (pos_lt(*el, *root[parent(j)])) { do { root[j] = root[parent(j)]; j = parent(j); } while (j > 0 && pos_lt(*el, *root[parent(j)])); root[j] = el; } }
HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head) { // Store the head into the recursion_heads h_hashtable_put(state->recursion_heads, &k->input_pos, head); HParserCacheValue *old_cached = h_hashtable_get(state->cache, k); if (!old_cached || PC_LEFT == old_cached->value_type) h_platform_errx(1, "impossible match"); HParseResult *old_res = old_cached->right; // rewind the input state->input_stream = k->input_pos; // reset the eval_set of the head of the recursion at each beginning of growth head->eval_set = h_slist_copy(head->involved_set); HParseResult *tmp_res = perform_lowlevel_parse(state, k->parser); if (tmp_res) { if (pos_lt(old_cached->input_stream, state->input_stream)) { h_hashtable_put(state->cache, k, cached_result(state, tmp_res)); return grow(k, state, head); } else { // we're done with growing, we can remove data from the recursion head h_hashtable_del(state->recursion_heads, &k->input_pos); HParserCacheValue *cached = h_hashtable_get(state->cache, k); if (cached && PC_RIGHT == cached->value_type) { state->input_stream = cached->input_stream; return cached->right; } else { h_platform_errx(1, "impossible match"); } } } else { h_hashtable_del(state->recursion_heads, &k->input_pos); state->input_stream = old_cached->input_stream; return old_res; } }