]> pd.if.org Git - zpackage/blobdiff - lib/vercmp.c
move vercmp into zpm library
[zpackage] / lib / vercmp.c
diff --git a/lib/vercmp.c b/lib/vercmp.c
new file mode 100644 (file)
index 0000000..8cbad73
--- /dev/null
@@ -0,0 +1,142 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+struct ver {
+       char str[1024]; /* string rep */
+       char *s; /* start component */
+       int cn; /* current component number */
+       char *next; /* start of potential next component */
+       char keep; /* character over-written with null byte */
+       int sep; /* number of characters in separator */
+       
+       int nv; /* numeric value */
+       int type; /* 0 null, 1 text, 2 numeric */
+       int release;
+       char *relstr;
+};
+
+static void init_ver(struct ver *v, char *s) {
+       strncpy(v->str, s, 1023);
+       v->str[1023] = 0;
+       v->s = 0;
+       v->cn = 0;
+       v->next = v->str;
+       v->relstr = 0;
+       v->keep = 0;
+       v->sep = 0;
+
+       /* scan for trailing release */
+       int n;
+       n = strlen(v->str) - 1;
+       if (n > 0 && isdigit(v->str[n])) {
+               while (isdigit(v->str[n])) {
+                       n--;
+               }
+               if (s[n] == '-') {
+                       v->relstr = v->str + n;
+                       v->release = atoi(v->str + n + 1);
+                       v->str[n] = 0;
+               }
+       }
+
+}
+
+static int ver_cmp(struct ver *a, struct ver *b) {
+       if (a->type == 0 && b->type == 0) {
+               return 0;
+       }
+       if (a->type != b->type) {
+               return a->type < b->type ? -1 : 1;
+       }
+       if (a->type == 1) {
+               int cmp;
+               cmp = strcmp(a->s, b->s);
+               if (cmp == 0) {
+                       return 0;
+               }
+               return cmp < 0 ? -1 : 1;
+       }
+       if (a->type == 2) {
+               if (a->nv != b->nv)
+               return a->nv < b->nv ? -1 : 1;
+       }
+       return 0;
+}
+
+static int next_comp(struct ver *v) {
+       char *s;
+
+       /* restore over-written character */
+       if (v->keep) {
+               v->next[0] = v->keep;
+               v->keep = 0;
+       }
+       s = v->next;
+
+       /* skip over anything that isn't alphanumeric */
+       v->sep = 0;
+       while (*s && !isalnum(*s)) {
+               v->sep++;
+               s++;
+       }
+       v->next = s;
+
+       /* zero return if at end of string */
+       if (!*s) {
+               return 0;
+       }
+       if (isdigit(*s)) {
+               v->type = 2;
+               while (isdigit(*s)) s++;
+               v->keep = *s;
+               *s = 0;
+               v->s = v->next;
+               v->nv = atoi(v->s);
+       } else if (isalpha(*s)) {
+               v->type = 1;
+               while (isalpha(*s)) s++;
+               v->keep = *s;
+               *s = 0;
+               v->s = v->next;
+       }
+       v->next = s;
+
+       return ++v->cn;
+}
+
+/*
+ * alphabetic less than numeric
+ */
+int zpm_vercmp(char *vsa, char *vsb) {
+       struct ver a, b;
+       int an, bn;
+       int cmp;
+
+       init_ver(&a, vsa);
+       init_ver(&b, vsb);
+       do {
+               an = next_comp(&a);
+               bn = next_comp(&b);
+               if (an != bn) {
+                       if (an == 0 && a.type == 2 && b.sep == 0 && b.type == 1) {
+                               return 1;
+                       } else if (bn == 0 && b.type == 2 && a.sep == 0 && a.type == 1) {
+                               return -1;
+                       }
+                       return an < bn ? -1 : 1;
+               }
+               cmp = ver_cmp(&a, &b);
+               if (cmp != 0) {
+                       return cmp;
+               }
+       } while (an && bn);
+
+       /* if we've gotten here, and both have releases, check those */
+       if (a.relstr && b.relstr && a.release != b.release) {
+               return a.release < b.release ? -1 : 1;
+       }
+       
+       return 0;
+}