X-Git-Url: https://pd.if.org/git/?p=zpackage;a=blobdiff_plain;f=lib%2Fvercmp.c;h=5d22aea798ffd25db8ecde7082a55e5f8fa4d57e;hp=cfc7edd27519e9e1f58924ecbb5ff51e9d937a45;hb=b0c5db32f5f53b5d43170756668e0c0387a88f13;hpb=e0214f50fcf9ed0fdcdca444986fc998db5d0dee diff --git a/lib/vercmp.c b/lib/vercmp.c index cfc7edd..5d22aea 100644 --- a/lib/vercmp.c +++ b/lib/vercmp.c @@ -3,12 +3,23 @@ #include #include +#include "zpm.h" + +#define TEXT 1 +#define NUMERIC 2 + struct ver { - char str[1024]; /* string rep */ - char *s; /* start component */ +#if 0 + char name[1024]; + char str[1024]; /* string rep of the version */ +#endif + const char *str; + int release; /* a trailing -\d+ value */ + const 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 len; /* current component length */ + + const char *next; /* start of potential next component */ int sep; /* number of characters in separator */ int nv; /* numeric value */ @@ -16,13 +27,53 @@ struct ver { }; static void init_ver(struct ver *v, const char *s) { +#if 0 strncpy(v->str, s, 1023); v->str[1023] = 0; - v->s = 0; + v->name[1023] = 0; +#endif + v->str = s; + v->release = 0; + v->s = v->str; v->cn = 0; v->next = v->str; - v->keep = 0; v->sep = 0; + v->len = 0; + v->type = 0; +} + +static int cmp_strlen(const char *a, size_t alen, const char *b, size_t blen) { + size_t shortest; + int base; + + if (a && !b) { + return 1; + } else if (b && !a) { + return -1; + } else if (!a && !b) { + return 0; + } + + if (alen && !blen) { + return 1; + } else if (blen && !alen) { + return -1; + } else if (!alen && !blen) { + return 0; + } + + shortest = alen < blen ? alen : blen; + + base = strncmp(a, b, shortest); + + if (base == 0) { + if (alen == blen) { + return 0; + } + return alen < blen ? -1 : 1; + } + + return base < 0 ? -1 : 1; } static int ver_cmp(struct ver *a, struct ver *b) { @@ -32,7 +83,8 @@ static int ver_cmp(struct ver *a, struct ver *b) { if (a->type != b->type) { return a->type < b->type ? -1 : 1; } - if (a->type == 1) { + + if (a->type == TEXT) { int cmp; if (a->s && ! b->s) return 1; if (b->s && ! a->s) return -1; @@ -45,7 +97,7 @@ static int ver_cmp(struct ver *a, struct ver *b) { } return cmp < 0 ? -1 : 1; } - if (a->type == 2) { + if (a->type == NUMERIC) { if (a->nv != b->nv) return a->nv < b->nv ? -1 : 1; } @@ -53,53 +105,67 @@ static int ver_cmp(struct ver *a, struct ver *b) { } static int next_comp(struct ver *v) { - char *s; + const char *s, *next; - /* restore over-written character */ - if (v->keep) { - v->next[0] = v->keep; - v->keep = 0; - } - s = v->next; + next = v->next; + v->len = 0; + v->type = 0; /* skip over anything that isn't alphanumeric */ v->sep = 0; - while (*s && !isalnum(*s)) { - v->sep++; - s++; + while (*next && !isalnum(*next)) { + next++; } - v->next = s; /* zero return if at end of string */ - if (!*s) { + if (!*next) { + v->s = next; return 0; } + + s = next; + v->s = next; + if (isdigit(*s)) { - v->type = 2; - while (isdigit(*s)) s++; - v->keep = *s; - *s = 0; - v->s = v->next; - v->nv = atoi(v->s); + v->type = NUMERIC; + v->nv = *s-'0'; + while (isdigit(*s)) { + v->nv = v->nv * 10 + *s-'0'; + v->len++; + s++; + } + v->next = s; } else if (isalpha(*s)) { - v->type = 1; - while (isalpha(*s)) s++; - v->keep = *s; - *s = 0; - v->s = v->next; + v->type = TEXT; + while (*s && (isalpha(*s) || *s == '-') ) { + v->len++; + s++; + } + v->next = s; + /* last character in a alphabetic can't be a - */ + while (*s == '-') { + v->len--; + s--; + } + } else { + /* impossible */ + return 0; } - v->next = s; - return ++v->cn; + v->cn++; + return v->cn; } /* * alphabetic less than numeric + * return -1 if vsa < vsb, 0 if equal, 1 if vsa > vsb */ int zpm_vercmp(const char *vsa, const char *vsb) { struct ver a, b; + struct zpm_version_info ainfo, binfo; int an, bn; int cmp; + char astr[256], bstr[256]; if (vsa && !vsb) { return 1; @@ -111,27 +177,56 @@ int zpm_vercmp(const char *vsa, const char *vsb) { return 0; } - init_ver(&a, vsa); - init_ver(&b, vsb); + zpm_parse_version(vsa, &ainfo); + zpm_parse_version(vsb, &binfo); + cmp = cmp_strlen(ainfo.name, ainfo.namelen, binfo.name, binfo.namelen); + + if (cmp != 0) { + return cmp; + } + + if (ainfo.verlen > 255) { + ainfo.verlen = 255; + } + if (binfo.verlen > 255) { + binfo.verlen = 255; + } + + strncpy(astr, ainfo.verstr, ainfo.verlen); + strncpy(bstr, binfo.verstr, binfo.verlen); + astr[ainfo.verlen] = 0; + bstr[binfo.verlen] = 0; + + init_ver(&a, astr); + init_ver(&b, bstr); 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; + cmp = 1; break; } else if (bn == 0 && b.type == 2 && a.sep == 0 && a.type == 1) { - return -1; + cmp = -1; break; } - return an < bn ? -1 : 1; + cmp = an < bn ? -1 : 1; break; } if (an == 0 && bn == 0) { - return 0; + break; } cmp = ver_cmp(&a, &b); if (cmp != 0) { - return cmp; + break; } } while (an && bn); - return 0; + if (cmp != 0) { + return cmp; + } + + /* compare release */ + if (ainfo.release != binfo.release) { + cmp = ainfo.release < binfo.release ? -1 : 1; + } + + return cmp; }