Imported Upstream version 0.7.13
[platform/upstream/libsolv.git] / src / repodata.c
index 71e8175..4e75b6d 100644 (file)
 #include "repopack.h"
 #include "repopage.h"
 
+#ifdef _WIN32
+  #include "strfncs.h"
+#endif
+
 #define REPODATA_BLOCK 255
 
 static unsigned char *data_skip_key(Repodata *data, unsigned char *dp, Repokey *key);
@@ -207,11 +211,13 @@ repodata_schema2id(Repodata *data, Id *schema, int create)
   cid = schematahash[h];
   if (cid)
     {
-      if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
+      if ((data->schemata[cid] + len <= data->schemadatalen) &&
+                         !memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
         return cid;
       /* cache conflict, do a slow search */
       for (cid = 1; cid < data->nschemata; cid++)
-        if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
+        if ((data->schemata[cid] + len <= data->schemadatalen) &&
+                               !memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
           return cid;
     }
   /* a new one */
@@ -791,14 +797,28 @@ repodata_lookup_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
 
   queue_empty(q);
   dp = find_key_data(data, solvid, keyname, &key);
-  if (!dp || key->type != REPOKEY_TYPE_IDARRAY)
+  if (!dp)
     return 0;
-  for (;;)
+  switch (key->type)
     {
-      dp = data_read_ideof(dp, &id, &eof);
+    case REPOKEY_TYPE_CONSTANTID:
+      queue_push(q, key->size);
+      break;
+    case REPOKEY_TYPE_ID:
+      dp = data_read_id(dp, &id);
       queue_push(q, id);
-      if (eof)
-       break;
+      break;
+    case REPOKEY_TYPE_IDARRAY:
+      for (;;)
+       {
+         dp = data_read_ideof(dp, &id, &eof);
+         queue_push(q, id);
+         if (eof)
+           break;
+       }
+      break;
+    default:
+      return 0;
     }
   return 1;
 }
@@ -821,6 +841,57 @@ repodata_lookup_binary(Repodata *data, Id solvid, Id keyname, int *lenp)
   return dp;
 }
 
+unsigned int
+repodata_lookup_count(Repodata *data, Id solvid, Id keyname)
+{
+  unsigned char *dp;
+  Repokey *key;
+  unsigned int cnt = 0;
+
+  dp = find_key_data(data, solvid, keyname, &key);
+  if (!dp)
+    return 0;
+  switch (key->type)
+    {
+    case REPOKEY_TYPE_IDARRAY:
+    case REPOKEY_TYPE_REL_IDARRAY:
+      for (cnt = 1; (*dp & 0xc0) != 0; dp++)
+       if ((*dp & 0xc0) == 0x40)
+         cnt++;
+      return cnt;
+    case REPOKEY_TYPE_FIXARRAY:
+    case REPOKEY_TYPE_FLEXARRAY:
+      data_read_id(dp, (int *)&cnt);
+      return cnt;
+    case REPOKEY_TYPE_DIRSTRARRAY:
+      for (;;)
+       {
+         cnt++;
+         while (*dp & 0x80)
+           dp++;
+         if (!(*dp++ & 0x40))
+           return cnt;
+         dp += strlen((const char *)dp) + 1;
+       }
+    case REPOKEY_TYPE_DIRNUMNUMARRAY:
+      for (;;)
+       {
+         cnt++;
+         while (*dp++ & 0x80)
+           ;
+         while (*dp++ & 0x80)
+           ;
+         while (*dp & 0x80)
+           dp++;
+         if (!(*dp++ & 0x40))
+           return cnt;
+       }
+      default:
+       break;
+    }
+  return 1;
+}
+
 /* highly specialized function to speed up fileprovides adding.
  * - repodata must be available
  * - solvid must be >= data->start and < data->end
@@ -1124,7 +1195,7 @@ repodata_search_array(Repodata *data, Id solvid, Id keyname, int flags, Repokey
 
   if (!dp || kv->entry != -1)
     return 0;
-  while (++kv->entry < kv->num)
+  while (++kv->entry < (int)kv->num)
     {
       if (kv->entry)
        dp = data_skip_schema(data, dp, schema);
@@ -2959,6 +3030,11 @@ repodata_unset_uninternalized(Repodata *data, Id solvid, Id keyname)
   ap = *app;
   if (!ap)
     return;
+  if (!keyname)
+    {
+      *app = 0;                /* delete all attributes */
+      return;
+    }
   for (; *ap; ap += 2)
     if (data->keys[*ap].name == keyname)
       break;
@@ -3024,6 +3100,8 @@ repodata_swap_attrs(Repodata *data, Id dest, Id src)
   tmpattrs = data->attrs[dest - data->start];
   data->attrs[dest - data->start] = data->attrs[src - data->start];
   data->attrs[src - data->start] = tmpattrs;
+  if (data->lasthandle == src || data->lasthandle == dest)
+    data->lasthandle = 0;
 }
 
 
@@ -3137,7 +3215,7 @@ compact_attrdata(Repodata *data, int entry, int nentry)
              break;
            case REPOKEY_TYPE_DIRSTRARRAY:
              for (v = attrs[1]; data->attriddata[v] ; v += 2)
-               if (data->attriddata[v + 1] < attrdatastart)
+               if ((unsigned int)data->attriddata[v + 1] < attrdatastart)
                  attrdatastart = data->attriddata[v + 1];
              /* FALLTHROUGH */
            case REPOKEY_TYPE_IDARRAY: