]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
Generalize uninternalized lookups
authorMichael Schroeder <mls@suse.de>
Fri, 21 Sep 2018 13:35:54 +0000 (15:35 +0200)
committerMichael Schroeder <mls@suse.de>
Fri, 21 Sep 2018 13:35:54 +0000 (15:35 +0200)
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.

ext/repo_appdata.c
ext/repo_rpmmd.c
ext/repo_susetags.c
src/libsolv.ver
src/repodata.c
src/repodata.h

index 62faf2d87fe7baf7af5ab3744a95b208d4b7b922..03098e2359a96f9a44c84613163799733146a87f 100644 (file)
@@ -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);
        }
     }
 }
index d639856191477a5295b3e5333b110f13f31437fa..9f49bd31572f7fb61c167d5befa2879bb0e6c924 100644 (file)
@@ -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);
     }
 }
 
index 6d03d231257e7e4cc28be7132349169bf0024d4a..561c789f8eb5b812fc1cd0feddde52f7a4024aa5 100644 (file)
@@ -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;
 }
 
index 05da2d7053f546ad252dbdb38d2e22490b13887d..d31d902cf01374117bff3dfbec37dc4aa36c04f9 100644 (file)
@@ -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;
index 7b5a064525b9e1ec3a644cdea77e4a3c8c7ea235..62ec461038b8656cb25a9130623988d3215bcc37 100644 (file)
@@ -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;
 }
 
 /************************************************************************
index e255c928d61c021b1c84810940ed1ffd89baf6b1..05d34a809627759c337ac92f9b86d0fd3267d972 100644 (file)
@@ -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);