From: Michael Schroeder Date: Fri, 21 Sep 2018 13:35:54 +0000 (+0200) Subject: Generalize uninternalized lookups X-Git-Tag: 0.7.0~30 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=00ada46c5cccef72dd1f9cbdf467f6d7d3ce7ce0;p=thirdparty%2Flibsolv.git Generalize uninternalized lookups We now have the generic repodata_lookup_kv_uninternalized and repodata_search_uninternalized to access uninternalized data. Drop the old interface, the functions were only used in some metadata parsers. So it's an API change but nobody should notice. --- diff --git a/ext/repo_appdata.c b/ext/repo_appdata.c index 62faf2d8..03098e23 100644 --- a/ext/repo_appdata.c +++ b/ext/repo_appdata.c @@ -467,13 +467,40 @@ repo_add_appdata(Repo *repo, FILE *fp, int flags) return repo_add_appdata_fn(repo, fp, flags, 0, 0); } +struct uninternalized_filelist_data { + Id did; + Queue *res; +}; + +static int +search_uninternalized_filelist_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv) +{ + struct uninternalized_filelist_data *uf = cbdata; + const char *str; + Id id; + size_t l; + if (key->type != REPOKEY_TYPE_DIRSTRARRAY || kv->id != uf->did) + return 0; + str = kv->str; + l = strlen(str); + if (l > 12 && strncmp(str + l - 12, ".appdata.xml", 12)) + id = pool_str2id(data->repo->pool, str, 1); + else if (l > 13 && strncmp(str + l - 13, ".metainfo.xml", 13)) + id = pool_str2id(data->repo->pool, str, 1); + else + return 0; + queue_push2(uf->res, s - data->repo->pool->solvables, id); + return 0; +} + static void search_uninternalized_filelist(Repo *repo, const char *dir, Queue *res) { Pool *pool = repo->pool; - Id rdid, p; - Id iter, did, idid; + Id did, rdid, p; + struct uninternalized_filelist_data uf; + uf.res = res; for (rdid = 1; rdid < repo->nrepodata; rdid++) { Repodata *data = repo_id2repodata(repo, rdid); @@ -486,31 +513,12 @@ search_uninternalized_filelist(Repo *repo, const char *dir, Queue *res) did = repodata_str2dir(data, dir, 0); if (!did) continue; + uf.did = did; for (p = data->start; p < data->end; p++) { - if (p >= pool->nsolvables) + if (p >= pool->nsolvables || pool->solvables[p].repo != repo) continue; - if (pool->solvables[p].repo != repo) - continue; - iter = 0; - for (;;) - { - const char *str; - int l; - Id id; - idid = did; - str = repodata_lookup_dirstrarray_uninternalized(data, p, SOLVABLE_FILELIST, &idid, &iter); - if (!iter) - break; - l = strlen(str); - if (l > 12 && strncmp(str + l - 12, ".appdata.xml", 12)) - id = pool_str2id(pool, str, 1); - else if (l > 13 && strncmp(str + l - 13, ".metainfo.xml", 13)) - id = pool_str2id(pool, str, 1); - else - continue; - queue_push2(res, p, id); - } + repodata_search_uninternalized(data, p, SOLVABLE_FILELIST, 0, search_uninternalized_filelist_cb, &uf); } } } diff --git a/ext/repo_rpmmd.c b/ext/repo_rpmmd.c index d6398561..9f49bd31 100644 --- a/ext/repo_rpmmd.c +++ b/ext/repo_rpmmd.c @@ -603,17 +603,18 @@ static void fill_cshash_from_new_solvables(struct parsedata *pd) { Pool *pool = pd->pool; - Id cstype = 0; - unsigned const char *cs; - int i; + int i, l; + KeyValue kv; + Repokey *key; for (i = pd->first; i < pool->nsolvables; i++) { if (pool->solvables[i].repo != pd->repo) continue; - cs = repodata_lookup_bin_checksum_uninternalized(pd->data, i, SOLVABLE_CHECKSUM, &cstype); - if (cs) - put_in_cshash(pd, cs, solv_chksum_len(cstype), i); + if ((key = repodata_lookup_kv_uninternalized(pd->data, i, SOLVABLE_CHECKSUM, &kv)) == 0) + continue; + if ((l = solv_chksum_len(key->type)) != 0) + put_in_cshash(pd, (const unsigned char *)kv.str, l, i); } } diff --git a/ext/repo_susetags.c b/ext/repo_susetags.c index 6d03d231..561c789f 100644 --- a/ext/repo_susetags.c +++ b/ext/repo_susetags.c @@ -333,7 +333,16 @@ lookup_shared_id(Repodata *data, Id p, Id keyname, Id voidid, int uninternalized return r; } if (uninternalized) - return repodata_lookup_id_uninternalized(data, p, keyname, voidid); + { + KeyValue kv; + Repokey *key = repodata_lookup_kv_uninternalized(data, p, keyname, &kv); + if (!key) + return 0; + if (key->type == REPOKEY_TYPE_VOID) + return voidid; + if (key->type == REPOKEY_TYPE_ID) + return kv.id; + } return 0; } diff --git a/src/libsolv.ver b/src/libsolv.ver index 05da2d70..d31d902c 100644 --- a/src/libsolv.ver +++ b/src/libsolv.ver @@ -202,12 +202,10 @@ SOLV_1.0 { repodata_key2id; repodata_localize_id; repodata_lookup_bin_checksum; - repodata_lookup_bin_checksum_uninternalized; repodata_lookup_binary; - repodata_lookup_dirstrarray_uninternalized; repodata_lookup_id; - repodata_lookup_id_uninternalized; repodata_lookup_idarray; + repodata_lookup_kv_uninternalized; repodata_lookup_num; repodata_lookup_str; repodata_lookup_type; @@ -220,6 +218,7 @@ SOLV_1.0 { repodata_search; repodata_search_arrayelement; repodata_search_keyskip; + repodata_search_uninternalized; repodata_set_binary; repodata_set_bin_checksum; repodata_set_checksum; diff --git a/src/repodata.c b/src/repodata.c index 7b5a0645..62ec4610 100644 --- a/src/repodata.c +++ b/src/repodata.c @@ -933,86 +933,121 @@ repodata_translate_dir_slow(Repodata *data, Repodata *fromdata, Id dir, int crea return compid; } -/* uninternalized lookups */ +/************************************************************************ + * uninternalized lookup / search + */ -Id -repodata_lookup_id_uninternalized(Repodata *data, Id solvid, Id keyname, Id voidid) +static void +data_fetch_uninternalized(Repodata *data, Repokey *key, Id value, KeyValue *kv) +{ + Id *array; + kv->eof = 1; + switch (key->type) + { + case REPOKEY_TYPE_STR: + kv->str = (const char *)data->attrdata + value; + return; + case REPOKEY_TYPE_CONSTANT: + kv->num2 = 0; + kv->num = key->size; + return; + case REPOKEY_TYPE_CONSTANTID: + kv->id = key->size; + return; + case REPOKEY_TYPE_NUM: + kv->num2 = 0; + kv->num = value; + if (value & 0x80000000) + { + kv->num = (unsigned int)data->attrnum64data[value ^ 0x80000000]; + kv->num2 = (unsigned int)(data->attrnum64data[value ^ 0x80000000] >> 32); + } + return; + case_CHKSUM_TYPES: + kv->num = 0; /* not stringified */ + kv->str = (const char *)data->attrdata + value; + return; + case REPOKEY_TYPE_IDARRAY: + array = data->attriddata + (value + kv->entry); + kv->id = array[0]; + kv->eof = array[1] ? 0 : 1; + return; + case REPOKEY_TYPE_DIRSTRARRAY: + kv->num = 0; /* not stringified */ + array = data->attriddata + (value + kv->entry * 2); + kv->id = array[0]; + kv->str = (const char *)data->attrdata + array[1]; + kv->eof = array[2] ? 0 : 1; + return; + case REPOKEY_TYPE_DIRNUMNUMARRAY: + array = data->attriddata + (value + kv->entry * 3); + kv->id = array[0]; + kv->num = array[1]; + kv->num2 = array[2]; + kv->eof = array[3] ? 0 : 1; + return; + case REPOKEY_TYPE_FIXARRAY: + case REPOKEY_TYPE_FLEXARRAY: + array = data->attriddata + (value + kv->entry); + kv->id = array[0]; /* the handle */ + kv->eof = array[1] ? 0 : 1; + return; + default: + kv->id = value; + return; + } +} + +Repokey * +repodata_lookup_kv_uninternalized(Repodata *data, Id solvid, Id keyname, KeyValue *kv) { Id *ap; - if (!data->attrs) + if (!data->attrs || solvid < data->start || solvid >= data->end) return 0; ap = data->attrs[solvid - data->start]; if (!ap) return 0; for (; *ap; ap += 2) { - if (data->keys[*ap].name != keyname) + Repokey *key = data->keys + *ap; + if (key->name != keyname) continue; - if (data->keys[*ap].type == REPOKEY_TYPE_VOID) - return voidid; - if (data->keys[*ap].type == REPOKEY_TYPE_ID) - return ap[1]; - return 0; + data_fetch_uninternalized(data, key, ap[1], kv); + return key; } return 0; } -/* returns the basename, stores the dir id in didp */ -const char * -repodata_lookup_dirstrarray_uninternalized(Repodata *data, Id solvid, Id keyname, Id *didp, Id *iterp) -{ - Id *ap, did; - Id iter = *iterp; - if (iter == 0) /* find key data */ - { - if (!data->attrs) - return 0; - ap = data->attrs[solvid - data->start]; - if (!ap) - return 0; - for (; *ap; ap += 2) - if (data->keys[*ap].name == keyname && data->keys[*ap].type == REPOKEY_TYPE_DIRSTRARRAY) - break; - if (!*ap) - return 0; - iter = ap[1]; - } - did = *didp; - for (ap = data->attriddata + iter; *ap; ap += 2) - { - if (did && ap[0] != did) - continue; - *didp = ap[0]; - *iterp = ap - data->attriddata + 2; - return (const char *)data->attrdata + ap[1]; - } - *iterp = 0; - return 0; -} - -const unsigned char * -repodata_lookup_bin_checksum_uninternalized(Repodata *data, Id solvid, Id keyname, Id *typep) +void +repodata_search_uninternalized(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata) { Id *ap; - if (!data->attrs) - return 0; + int stop; + Solvable *s; + KeyValue kv; + + if (!data->attrs || solvid < data->start || solvid >= data->end) + return; ap = data->attrs[solvid - data->start]; if (!ap) - return 0; + return; for (; *ap; ap += 2) { - if (data->keys[*ap].name != keyname) + Repokey *key = data->keys + *ap; + if (keyname && key->name != keyname) continue; - switch (data->keys[*ap].type) + s = solvid > 0 ? data->repo->pool->solvables + solvid : 0; + kv.entry = 0; + do { - case_CHKSUM_TYPES: - *typep = data->keys[*ap].type; - return (const unsigned char *)data->attrdata + ap[1]; - default: - break; + data_fetch_uninternalized(data, key, ap[1], &kv); + stop = callback(cbdata, s, data, key, &kv); + kv.entry++; } + while (!kv.eof && !stop); + if (keyname || stop > SEARCH_NEXT_KEY) + return; } - return 0; } /************************************************************************ diff --git a/src/repodata.h b/src/repodata.h index e255c928..05d34a80 100644 --- a/src/repodata.h +++ b/src/repodata.h @@ -324,10 +324,9 @@ void repodata_set_location(Repodata *data, Id solvid, int medianr, const char *d void repodata_set_deltalocation(Repodata *data, Id handle, int medianr, const char *dir, const char *file); void repodata_set_sourcepkg(Repodata *data, Id solvid, const char *sourcepkg); -/* uninternalized data lookup */ -Id repodata_lookup_id_uninternalized(Repodata *data, Id solvid, Id keyname, Id voidid); -const char *repodata_lookup_dirstrarray_uninternalized(Repodata *data, Id solvid, Id keyname, Id *didp, Id *iterp); -const unsigned char *repodata_lookup_bin_checksum_uninternalized(Repodata *data, Id solvid, Id keyname, Id *typep); +/* uninternalized data lookup / search */ +Repokey *repodata_lookup_kv_uninternalized(Repodata *data, Id solvid, Id keyname, struct _KeyValue *kv); +void repodata_search_uninternalized(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, struct _KeyValue *kv), void *cbdata); /* stats */ unsigned int repodata_memused(Repodata *data);