]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
An iterator interface to attributes. Supports the same things as the
authorMichael Matz <matz@suse.de>
Sat, 23 Feb 2008 01:50:41 +0000 (01:50 +0000)
committerMichael Matz <matz@suse.de>
Sat, 23 Feb 2008 01:50:41 +0000 (01:50 +0000)
callback interface (one or all solvables, one or all attributes, with or
without matching), except the solvable data (to be implemented).
Also some inactive (but working) code in dumpsolv testing the iterator.

src/repo.c
src/repo.h
src/repodata.c
tools/dumpsolv.c

index 44d38abd1bbc6334c35ea2d5aef58957a1f9981b..dff8840e82a390bf66f90af56aa7263ea6cd9b5f 100644 (file)
@@ -728,7 +728,7 @@ repo_search_md(Repo *repo, Id p, Id keyname, struct matchdata *md)
 }
 
 void
-repo_search(Repo *repo, Id p, Id key, const char *match, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
+repo_search(Repo *repo, Id p, Id keyname, const char *match, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
 {
   struct matchdata md;
 
@@ -738,7 +738,7 @@ repo_search(Repo *repo, Id p, Id key, const char *match, int flags, int (*callba
   md.flags = flags;
   md.callback = callback;
   md.callback_data = cbdata;
-  repo_search_md(repo, p, key, &md);
+  repo_search_md(repo, p, keyname, &md);
 }
 
 const char *
@@ -954,3 +954,6 @@ repo_add_attrstore (Repo *repo, Attrstore *s, const char *location)
 #endif
 
 // EOF
+/*
+vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4:
+*/
index a64154158f4b6dd85a6d9e045dac6cb1630bfa7e..e714129ae6b71442f8f33a8399e1cd473eed4d6c 100644 (file)
@@ -160,6 +160,9 @@ typedef struct _KeyValue {
 #define        SEARCH_NOCASE                   (1<<8)
 #define        SEARCH_NO_STORAGE_SOLVABLE      (1<<9)
 
+/* Internal */
+#define __SEARCH_ONESOLVABLE           (1 << 31)
+
 Repodata *repo_add_repodata(Repo *repo);
 void repo_search(Repo *repo, Id p, Id key, const char *match, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata);
 
@@ -170,6 +173,29 @@ int repo_lookup_num(Solvable *s, Id key);
 /* generic attribute lookup */
 int repo_lookup(Solvable *s, Id key, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata);
 
+typedef struct _Dataiterator
+{
+  Repodata *data;
+  Id *keyp;
+  unsigned char *nextkeydp;
+  unsigned char *dp;
+  Repokey *key;
+  Repo *repo;
+  const char *match;
+  Id solvid;
+  Id keyname;
+  unsigned flags;
+  KeyValue kv;
+} Dataiterator;
+
+/* Use these like:
+     Dataiterator di;
+     dataiterator_init(&di, repo, 0, 0, "bla", SEARCH_SUBSTRING);
+     while (dataiterator_step(&di))
+       dosomething(di.solvid, di.key, di.kv);  */
+void dataiterator_init(Dataiterator *di, Repo *repo, Id p, Id keyname,
+                      const char *match, int flags);
+int dataiterator_step(Dataiterator *di);
 
 void repo_set_id(Repo *repo, Id p, Id keyname, Id id);
 void repo_set_num(Repo *repo, Id p, Id keyname, Id num);
index 020a227dd964663177c69e098108fa4ad0cc4397..de13ea44ef7795a5347ec9ca813efcd1ee8f64d9 100644 (file)
@@ -14,6 +14,7 @@
 
 #define _GNU_SOURCE
 #include <string.h>
+#include <fnmatch.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -572,6 +573,207 @@ repodata_search(Repodata *data, Id entry, Id keyname, int (*callback)(void *cbda
     }
 }
 
+static void
+dataiterator_newdata(Dataiterator *di)
+{
+  Id keyname = di->keyname;
+  Repodata *data = di->data;
+  di->nextkeydp = 0;
+
+  if (data->state == REPODATA_STUB)
+    {
+      if (keyname)
+       {
+         int j;
+         for (j = 1; j < data->nkeys; j++)
+           if (keyname == data->keys[j].name)
+             break;
+         if (j == data->nkeys)
+           return;
+       }
+      /* load it */
+      if (data->loadcallback)
+       data->loadcallback(data);
+      else
+       data->state = REPODATA_ERROR;
+    }
+  if (data->state == REPODATA_ERROR)
+    return;
+
+  Id schema;
+  unsigned char *dp = data->incoredata + data->incoreoffset[di->solvid - data->start];
+  dp = data_read_id(dp, &schema);
+  Id *keyp = data->schemadata + data->schemata[schema];
+  if (keyname)
+    {
+      Id k, *kp;
+      /* search in a specific key */
+      for (kp = keyp; (k = *kp++) != 0; )
+       if (data->keys[k].name == keyname)
+         break;
+      if (k == 0)
+       return;
+      dp = forward_to_key(data, k, schema, dp);
+      if (!dp)
+       return;
+      keyp = kp - 1;
+    }
+  Id keyid = *keyp++;
+  if (!keyid)
+    return;
+
+  di->data = data;
+  di->key = di->data->keys + keyid;
+  di->keyp = keyp;
+  di->dp = 0;
+
+  di->nextkeydp = dp;
+  di->dp = get_data(di->data, di->key, &di->nextkeydp);
+  di->kv.eof = 0;
+}
+
+void
+dataiterator_init(Dataiterator *di, Repo *repo, Id p, Id keyname,
+                 const char *match, int flags)
+{
+  di->flags = flags;
+  if (p)
+    {
+      di->solvid = p;
+      di->flags |= __SEARCH_ONESOLVABLE;
+      di->data = repo->repodata - 1;
+    }
+  else
+    {
+      di->solvid = repo->start - 1;
+      di->data = repo->repodata + repo->nrepodata - 1;
+    }
+  di->match = match;
+  di->keyname = keyname;
+  static Id zeroid = 0;
+  di->keyp = &zeroid;
+  di->kv.eof = 1;
+  di->repo = repo;
+}
+
+/* FIXME factor and merge with repo_matchvalue */
+static int
+dataiterator_match(Dataiterator *di, KeyValue *kv)
+{
+  int flags = di->flags;
+
+  if ((flags & SEARCH_STRINGMASK) != 0)
+    {
+      switch (di->key->type)
+       {
+       case TYPE_ID:
+       case TYPE_IDARRAY:
+         if (di->data && di->data->localpool)
+           kv->str = stringpool_id2str(&di->data->spool, kv->id);
+         else
+           kv->str = id2str(di->repo->pool, kv->id);
+         break;
+       case TYPE_STR:
+         break;
+       default:
+         return 0;
+       }
+      switch ((flags & SEARCH_STRINGMASK))
+       {
+         case SEARCH_SUBSTRING:
+           if (flags & SEARCH_NOCASE)
+             {
+               if (!strcasestr(kv->str, di->match))
+                 return 0;
+             }
+           else
+             {
+               if (!strstr(kv->str, di->match))
+                 return 0;
+             }
+           break;
+         case SEARCH_STRING:
+           if (flags & SEARCH_NOCASE)
+             {
+               if (strcasecmp(di->match, kv->str))
+                 return 0;
+             }
+           else
+             {
+               if (strcmp(di->match, kv->str))
+                 return 0;
+             }
+           break;
+         case SEARCH_GLOB:
+           if (fnmatch(di->match, kv->str, (flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
+             return 0;
+           break;
+#if 0
+         case SEARCH_REGEX:
+           if (regexec(&di->regexp, kv->str, 0, NULL, 0))
+             return 0;
+#endif
+         default:
+           return 0;
+       }
+    }
+  return 1;
+}
+
+int
+dataiterator_step(Dataiterator *di)
+{
+  /* FIXME add solvable data */
+  while (1)
+    {
+      if (di->kv.eof)
+       di->dp = 0;
+      else
+       di->dp = data_fetch(di->dp, &di->kv, di->key);
+
+      while (!di->dp)
+       {
+         Id keyid;
+         if (di->keyname || !(keyid = *di->keyp++))
+           {
+             while (1)
+               {
+                 Repo *repo = di->repo;
+                 Repodata *data = ++di->data;
+                 if (data >= repo->repodata + repo->nrepodata)
+                   {
+                     if (di->flags & __SEARCH_ONESOLVABLE)
+                       return 0;
+                     while (++di->solvid < repo->end)
+                       if (repo->pool->solvables[di->solvid].repo == repo)
+                         break;
+                     if (di->solvid >= repo->end)
+                       return 0;
+                     di->data = repo->repodata - 1;
+                     continue;
+                   }
+                 if (di->solvid >= data->start && di->solvid < data->end)
+                   {
+                     dataiterator_newdata(di);
+                     if (di->nextkeydp)
+                       break;
+                   }
+               }
+           }
+         else
+           {
+             di->key = di->data->keys + keyid;
+             di->dp = get_data(di->data, di->key, &di->nextkeydp);
+           }
+         di->dp = data_fetch(di->dp, &di->kv, di->key);
+       }
+      if (!di->match
+         || dataiterator_match(di, &di->kv))
+       break;
+    }
+  return 1;
+}
+
 void
 repodata_init(Repodata *data, Repo *repo, int localpool)
 {
@@ -1367,3 +1569,6 @@ repodata_read_or_setup_pages(Repodata *data, unsigned int pagesz, unsigned int b
        }
     }
 }
+/*
+vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4:
+*/
index d71c6a82f805498da5f0e32ad132e672e9dfeac7..7906c85c449e9ff68583a6c7aba0e891cbf085bc 100644 (file)
@@ -14,81 +14,6 @@ static int with_attr = 0;
 
 #include "pool.h"
 #include "repo_solv.h"
-#if 0
-#include "attr_store.h"
-#include "attr_store_p.h"
-
-static void
-dump_attrs_1 (Attrstore *s, unsigned int entry)
-{
-  attr_iterator ai;
-  FOR_ATTRS (s, entry, &ai)
-    {
-      fprintf (stdout, "%s:", id2str (s->pool, ai.name));
-      switch (ai.type)
-       {
-       case TYPE_ATTR_INT:
-         fprintf (stdout, "int  %u\n", ai.as_int);
-         break;
-       case TYPE_ATTR_CHUNK:
-         {
-           const char *str = attr_retrieve_blob (s, ai.as_chunk[0], ai.as_chunk[1]);
-           if (str)
-             fprintf (stdout, "blob %s\n", str);
-           else
-             fprintf (stdout, "blob %u+%u\n", ai.as_chunk[0], ai.as_chunk[1]);
-         }
-         break;
-       case TYPE_ATTR_STRING:
-         fprintf (stdout, "str  %s\n", ai.as_string);
-         break;
-       case TYPE_ATTR_INTLIST:
-         {
-           fprintf (stdout, "lint\n ");
-           while (1)
-             {
-               int val;
-               get_num (ai.as_numlist, val);
-               fprintf (stdout, " %d", (val & 63) | ((val >> 1) & ~63));
-               if (!(val & 64))
-                 break;
-             }
-           fprintf (stdout, "\n");
-           break;
-         }
-       case TYPE_ATTR_LOCALIDS:
-         {
-           fprintf (stdout, "lids");
-           while (1)
-             {
-               Id val;
-               get_num (ai.as_numlist, val);
-               if (!val)
-                 break;
-               fprintf (stdout, "\n  %s(%d)", localid2str (s, val), val);
-             }
-           fprintf (stdout, "\n");
-           break;
-         }
-       default:
-         fprintf (stdout, "\n");
-         break;
-       }
-    }
-}
-
-static void
-dump_attrs (Repo *repo, unsigned int entry)
-{
-  unsigned i;
-  for (i = 0; i < repo->nrepodata; i++)
-    {
-      Attrstore *s = repo->repodata[i].s;
-      if (s && entry < s->entries)
-        dump_attrs_1 (s, entry);
-    }
-}
-#endif
 
 static void
 dump_repodata (Repo *repo)
@@ -188,9 +113,18 @@ dump_repoattrs_cb(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyV
 void
 dump_repoattrs(Repo *repo, Id p)
 {
+#if 1
   repo_search(repo, p, 0, 0, SEARCH_NO_STORAGE_SOLVABLE, dump_repoattrs_cb, 0);
+#else
+  Dataiterator di;
+  dataiterator_init(&di, repo, p, 0, 0, SEARCH_NO_STORAGE_SOLVABLE);
+  while (dataiterator_step(&di))
+    dump_repoattrs_cb(0, repo->pool->solvables + di.solvid, di.data, di.key,
+                     &di.kv);
+#endif
 }
 
+#if 0
 void
 dump_some_attrs(Repo *repo, Solvable *s)
 {
@@ -209,6 +143,7 @@ dump_some_attrs(Repo *repo, Solvable *s)
 
   printf ("  XXX %d %d %u %s\n", medianr, downloadsize, time, summary);
 }
+#endif
 
 
 static FILE *
@@ -238,6 +173,37 @@ usage( const char *err )
   exit(0);
 }
 
+#if 0
+static void
+tryme (Repo *repo, Id p, Id keyname, const char *match, int flags)
+{
+  Dataiterator di;
+  dataiterator_init(&di, repo, p, keyname, match, flags);
+  while (dataiterator_step(&di))
+    {
+      switch (di.key->type)
+       {
+         case TYPE_ID:
+         case TYPE_IDARRAY:
+             if (di.data && di.data->localpool)
+               di.kv.str = stringpool_id2str(&di.data->spool, di.kv.id);
+             else
+               di.kv.str = id2str(repo->pool, di.kv.id);
+             break;
+         case TYPE_STR:
+         case TYPE_DIRSTRARRAY:
+             break;
+         default:
+             di.kv.str = 0;
+       }
+      fprintf (stdout, "found: %d:%s %d %s %d %d %d\n",
+              di.solvid,
+              id2str(repo->pool, di.key->name),
+              di.kv.id,
+              di.kv.str, di.kv.num, di.kv.num2, di.kv.eof);
+    }
+}
+#endif
 
 int main(int argc, char **argv)
 {
@@ -306,11 +272,18 @@ int main(int argc, char **argv)
       dump_attrs (repo, n - 1);
 #endif
       dump_repoattrs(repo, i);
-#if 1
+#if 0
       dump_some_attrs(repo, s);
 #endif
       n++;
     }
+#if 0
+  tryme(repo, 0, str2id (repo->pool, "medianr", 0), 0, 0);
+  printf("\n");
+  tryme(repo, 0, 0, 0, 0);
+  printf("\n");
+  tryme(repo, 0, 0, "*y*e*", SEARCH_GLOB);
+#endif
   pool_free(pool);
   exit(0);
 }