]> pd.if.org Git - zpackage/blob - lib/vercmp.c
cfc7edd27519e9e1f58924ecbb5ff51e9d937a45
[zpackage] / lib / vercmp.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <ctype.h>
5
6 struct ver {
7         char str[1024]; /* string rep */
8         char *s; /* start component */
9         int cn; /* current component number */
10         char *next; /* start of potential next component */
11         char keep; /* character over-written with null byte */
12         int sep; /* number of characters in separator */
13         
14         int nv; /* numeric value */
15         int type; /* 0 null, 1 text, 2 numeric */
16 };
17
18 static void init_ver(struct ver *v, const char *s) {
19         strncpy(v->str, s, 1023);
20         v->str[1023] = 0;
21         v->s = 0;
22         v->cn = 0;
23         v->next = v->str;
24         v->keep = 0;
25         v->sep = 0;
26 }
27
28 static int ver_cmp(struct ver *a, struct ver *b) {
29         if (a->type == 0 && b->type == 0) {
30                 return 0;
31         }
32         if (a->type != b->type) {
33                 return a->type < b->type ? -1 : 1;
34         }
35         if (a->type == 1) {
36                 int cmp;
37                 if (a->s && ! b->s) return 1;
38                 if (b->s && ! a->s) return -1;
39                 if (!b->s && ! a->s) {
40                         return 0;
41                 }
42                 cmp = strcmp(a->s, b->s);
43                 if (cmp == 0) {
44                         return 0;
45                 }
46                 return cmp < 0 ? -1 : 1;
47         }
48         if (a->type == 2) {
49                 if (a->nv != b->nv)
50                 return a->nv < b->nv ? -1 : 1;
51         }
52         return 0;
53 }
54
55 static int next_comp(struct ver *v) {
56         char *s;
57
58         /* restore over-written character */
59         if (v->keep) {
60                 v->next[0] = v->keep;
61                 v->keep = 0;
62         }
63         s = v->next;
64
65         /* skip over anything that isn't alphanumeric */
66         v->sep = 0;
67         while (*s && !isalnum(*s)) {
68                 v->sep++;
69                 s++;
70         }
71         v->next = s;
72
73         /* zero return if at end of string */
74         if (!*s) {
75                 return 0;
76         }
77         if (isdigit(*s)) {
78                 v->type = 2;
79                 while (isdigit(*s)) s++;
80                 v->keep = *s;
81                 *s = 0;
82                 v->s = v->next;
83                 v->nv = atoi(v->s);
84         } else if (isalpha(*s)) {
85                 v->type = 1;
86                 while (isalpha(*s)) s++;
87                 v->keep = *s;
88                 *s = 0;
89                 v->s = v->next;
90         }
91         v->next = s;
92
93         return ++v->cn;
94 }
95
96 /*
97  * alphabetic less than numeric
98  */
99 int zpm_vercmp(const char *vsa, const char *vsb) {
100         struct ver a, b;
101         int an, bn;
102         int cmp;
103
104         if (vsa && !vsb) {
105                 return 1;
106         }
107         if (vsb && !vsa) {
108                 return -1;
109         }
110         if (!vsa && !vsb) {
111                 return 0;
112         }
113
114         init_ver(&a, vsa);
115         init_ver(&b, vsb);
116         do {
117                 an = next_comp(&a);
118                 bn = next_comp(&b);
119                 if (an != bn) {
120                         if (an == 0 && a.type == 2 && b.sep == 0 && b.type == 1) {
121                                 return 1;
122                         } else if (bn == 0 && b.type == 2 && a.sep == 0 && a.type == 1) {
123                                 return -1;
124                         }
125                         return an < bn ? -1 : 1;
126                 }
127                 if (an == 0 && bn == 0) {
128                         return 0;
129                 }
130                 cmp = ver_cmp(&a, &b);
131                 if (cmp != 0) {
132                         return cmp;
133                 }
134         } while (an && bn);
135
136         return 0;
137 }