bool hs_isect_arr (struct hs *res, const struct hs *hs, const array_t *a) { const struct hs_vec *v = &hs->list; array_t tmp[ARRAY_BYTES (hs->len) / sizeof (array_t)]; int pos = -1; for (int i = 0; i < v->used; i++) { if (!array_isect (v->elems[i], a, hs->len, tmp)) continue; pos = i; break; } if (pos == -1) return false; memset (res, 0, sizeof *res); res->len = hs->len; struct hs_vec *resv = &res->list; for (int i = pos; i < v->used; i++) { if (i == pos) vec_append (resv, xmemdup (tmp, sizeof tmp), false); else { array_t *isect = array_isect_a (v->elems[i], a, res->len); if (!isect) continue; vec_append (resv, isect, false); } struct hs_vec *diff = &v->diff[i], *resd = &resv->diff[resv->used - 1]; for (int j = 0; j < diff->used; j++) { array_t *isect = array_isect_a (diff->elems[j], a, res->len); if (!isect) continue; vec_append (resd, isect, true); } } return true; }
static uint32_t arr_find (const array_t *a, const array_t *arrs, int n) { if (!a) return 0; int len = ARRAY_BYTES (arr_len); array_t *b = bsearch (a, arrs, n, len, arr_cmp); assert (b); return VALID_OFS + ((uint8_t *)b - (uint8_t *)arrs); }
static array_t * gen_arrs (const struct parse_ntf *ntf, uint32_t *n) { char *buf, *buf2; size_t bufsz, buf2sz; FILE *f = open_memstream (&buf, &bufsz); uint32_t len = ARRAY_BYTES (arr_len); int count = 0; for (int i = 0; i < ntf->ntfs; i++) { const struct parse_tf *tf = ntf->tfs[i]; for (struct parse_rule *r = tf->rules.head; r; r = r->next) { assert (r->match); fwrite (r->match, len, 1, f); count++; if (r->mask) { fwrite (r->mask, len, 1, f); fwrite (r->rewrite, len, 1, f); count += 2; } for (struct parse_dep *dep = r->deps.head; dep; dep = dep->next) { fwrite (dep->match, len, 1, f); count++; } } } fclose (f); printf ("Arrays: %d (%zu)", count, bufsz); fflush (stdout); assert (count * len == bufsz); qsort (buf, count, len, arr_cmp); array_t *arrs = (array_t *) buf; int count2 = 0, last = -1; f = open_memstream (&buf2, &buf2sz); for (int i = 0; i < count * (len / sizeof (array_t)); i += len / sizeof (array_t)) { if (last != -1 && array_is_eq (&arrs[i], &arrs[last], arr_len)) continue; fwrite (&arrs[i], len, 1, f); last = i; count2++; } fclose (f); free (buf); printf (" -> %d (%zu)\n", count2, buf2sz); assert (count2 * len == buf2sz); *n = count2; return (array_t *) buf2; }
void data_gen (const char *name, const struct parse_ntf *ntf, const struct parse_tf *ttf) { FILE *out = fopen (name, "w"); if (!out) err (1, "Can't open output file %s", name); int ntfs = ntf->ntfs + 1; char *buf_strs; size_t sz_strs; FILE *f_strs = open_memstream (&buf_strs, &sz_strs); uint32_t narrs; arr_len = ntf->tfs[0]->len; array_t *arrs = gen_arrs (ntf, &narrs); int hdr_size = offsetof (struct file, tf_ofs[ntfs]); struct file *hdr = xmalloc (hdr_size); memset (hdr, 0, hdr_size); hdr->ntfs = ntfs; hdr->stages = ntf->stages; fwrite (hdr, hdr_size, 1, out); for (int i = 0; i < ntfs; i++) { hdr->tf_ofs[i] = ftell (out); printf ("%" PRIu32 "\n", hdr->tf_ofs[i]); if (!i) gen_tf (ttf, out, f_strs, arrs, narrs); else gen_tf (ntf->tfs[i - 1], out, f_strs, arrs, narrs); } fclose (f_strs); int len = ARRAY_BYTES (arr_len); hdr->arrs_ofs = ftell (out); fwrite (&arr_len, sizeof arr_len, 1, out); fwrite (&narrs, sizeof narrs, 1, out); fwrite (arrs, len, narrs, out); free (arrs); hdr->strs_ofs = ftell (out); fwrite (buf_strs, 1, sz_strs, out); free (buf_strs); int end = ftell (out); rewind (out); fwrite (hdr, hdr_size, 1, out); free (hdr); printf ("Total: %d bytes\n", end); fclose (out); }
static int arr_cmp (const void *a, const void *b) { return memcmp (a, b, ARRAY_BYTES (arr_len)); }