+static int
+cmp_ids (const void *pa, const void *pb)
+{
+ Id a = *(Id *)pa;
+ Id b = *(Id *)pb;
+ return a - b;
+}
+
+static void
+write_idarray_sort(FILE *fp, Pool *pool, NeedId *needid, Id *ids)
+{
+ int len, i;
+ if (!ids)
+ return;
+ if (!*ids)
+ {
+ write_u8 (fp, 0);
+ return;
+ }
+ /* If we ever share idarrays we can't do this in-place. */
+ for (len = 0; ids[len]; len++)
+ {
+ Id id = ids[len];
+ if (needid)
+ ids[len] = needid[ISRELDEP(id) ? RELOFF(id) : id].need;
+ }
+
+ /* That bloody solvable:prereqmarker needs to stay in position :-( */
+ Id prereq = SOLVABLE_PREREQMARKER;
+ if (needid)
+ prereq = needid[prereq].need;
+ for (i = 0; i < len; i++)
+ if (ids[i] == prereq)
+ break;
+ if (i > 1)
+ qsort (ids, i, sizeof (Id), cmp_ids);
+ if ((len - i) > 2)
+ qsort (ids + i + 1, len - i - 1, sizeof (Id), cmp_ids);
+
+ Id old = 0;
+ for (i = 0; i < len; i++)
+ /* Ugly PREREQ handling. A "difference" of 1 is the prereq marker,
+ hence all real differences are offsetted by 1. Otherwise we would
+ have to handle negative differences, which would cost code space for
+ the encoding of the sign. We loose the exact mapping of prereq here,
+ but we know the result, so we can recover from that in the reader. */
+ if (ids[i] == prereq)
+ old = ids[i] = 1;
+ else
+ {
+ ids[i] -= old;
+ old = ids[i] + old;
+ /* difference is zero --> we have multiple equal elements in the list */
+ assert (ids[i] > 0);
+ ids[i]++;
+ }
+
+ /* The differencing above produces many runs of ones and twos. I tried
+ fairly elaborate schemes to RLE those, but they give only very mediocre
+ improvements in compression, as coding the escapes costs quite some
+ space. Even if they are coded only as bits in IDs. The best improvement
+ was about 2.7% for the whole .solv file. It's probably better to
+ invest some complexity into sharing idarrays, than RLEing. */
+ for (;;)
+ {
+ Id id = *ids++;
+ if (id >= 64)
+ id = (id & 63) | ((id & ~63) << 1);
+ if (!*ids)
+ {
+ write_id(fp, id);
+ return;
+ }
+ write_id(fp, id | 64);
+ }
+}