]> pd.if.org Git - zpackage/commitdiff
add zpm-vercmp
authorNathan Wagner <nw@hydaspes.if.org>
Thu, 17 Nov 2016 09:10:05 +0000 (09:10 +0000)
committerNathan Wagner <nw@hydaspes.if.org>
Thu, 17 Nov 2016 09:10:05 +0000 (09:10 +0000)
t/vercmp.t [new file with mode: 0755]
vercmp.c [new file with mode: 0644]

diff --git a/t/vercmp.t b/t/vercmp.t
new file mode 100755 (executable)
index 0000000..2799a53
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+# test addfile
+
+. tap.sh
+
+vtest() {
+       res=$(zpm-vercmp "$1" "$2")
+       okstreq "$res" -1 "$1 < $2"
+       res=$(zpm-vercmp "$2" "$1")
+       okstreq "$res" 1 "$2 > $1"
+       res=$(zpm-vercmp "$1" "$1")
+       okstreq "$res" 0 "$1 == $1"
+}
+
+plan 45
+
+# alpha
+vtest 1.0a 1.0b
+vtest 1.0b 1.0beta
+vtest 1.0beta 1.0p
+vtest 1.0p 1.0pre
+vtest 1.0pre 1.0rc
+vtest 1.0rc 1.0
+vtest 1.0 1.0.a
+vtest 1.0.a 1.0.1
+
+vtest 1 1.0
+vtest 1.0 1.1
+vtest 1.1 1.1.1
+vtest 1.2 2.0
+vtest 2.0 3.0.0
+
+# release
+vtest 1.0-1 1.0-2
+vtest 1.0-2 2.0-1
+
+finish
diff --git a/vercmp.c b/vercmp.c
new file mode 100644 (file)
index 0000000..58053d9
--- /dev/null
+++ b/vercmp.c
@@ -0,0 +1,149 @@
+#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;
+};
+
+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;
+               }
+       }
+
+}
+
+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;
+}
+
+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 main(int ac, char *av[]) {
+       struct ver a, b;
+       int an, bn;
+       int cmp;
+
+       if (ac < 2) return 1;
+
+       init_ver(&a, av[1]);
+       init_ver(&b, av[2]);
+       do {
+               an = next_comp(&a);
+               bn = next_comp(&b);
+               if (an != bn) {
+                       if (an == 0 && a.type == 2 && b.sep == 0 && b.type == 1) {
+                               printf("1\n");
+                       } else if (bn == 0 && b.type == 2 && a.sep == 0 && a.type == 1) {
+                               printf("-1\n");
+                       } else {
+                               printf("%s\n", an < bn ? "-1" : "1");
+                       }
+                       exit(0);
+               }
+               cmp = ver_cmp(&a, &b);
+               if (cmp != 0) {
+                       printf("%d\n", cmp);
+                       exit(0);
+               }
+       } while (an && bn);
+
+       /* if we've gotten here, and both have releases, check those */
+       if (a.relstr && b.relstr && a.release != b.release) {
+               printf("%s\n", a.release < b.release ? "-1" : "1");
+               exit(0);
+       }
+       
+       printf("0\n");
+       return 0;
+}