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 44d38ab..dff8840 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 a641541..e714129 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 020a227..de13ea4 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 d71c6a8..7906c85 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);
 }