release 0.1.15
[liba.git] / src / version.c
blob28a8d8262a6adf828e507d96558dd07844dc8217
1 #include "a/version.h"
3 unsigned int const a_version_major = A_VERSION_MAJOR;
4 unsigned int const a_version_minor = A_VERSION_MINOR;
5 unsigned int const a_version_patch = A_VERSION_PATCH;
6 a_u32 const a_version_tweak = A_VERSION_TWEAK;
8 int a_version_check(unsigned int major, unsigned int minor, unsigned int patch)
10 a_version inner, outer;
11 inner.major = a_version_major;
12 inner.minor = a_version_minor;
13 inner.third = a_version_patch;
14 outer.major = major;
15 outer.minor = minor;
16 outer.third = patch;
17 return a_version_cmp(&inner, &outer);
20 int a_version_cmp(a_version const *lhs, a_version const *rhs)
22 if (lhs->major < rhs->major) { return -3; }
23 if (lhs->major > rhs->major) { return +3; }
24 if (lhs->minor < rhs->minor) { return -2; }
25 if (lhs->minor > rhs->minor) { return +2; }
26 if (lhs->third < rhs->third) { return -1; }
27 if (lhs->third > rhs->third) { return +1; }
28 return 0;
31 a_bool a_version_lt(a_version const *lhs, a_version const *rhs)
33 if (lhs->major < rhs->major) { return A_TRUE; }
34 if (lhs->major > rhs->major) { return A_FALSE; }
35 if (lhs->minor < rhs->minor) { return A_TRUE; }
36 if (lhs->minor > rhs->minor) { return A_FALSE; }
37 if (lhs->third < rhs->third) { return A_TRUE; }
38 if (lhs->third > rhs->third) { return A_FALSE; }
39 return A_FALSE;
42 a_bool a_version_gt(a_version const *lhs, a_version const *rhs)
44 if (lhs->major > rhs->major) { return A_TRUE; }
45 if (lhs->major < rhs->major) { return A_FALSE; }
46 if (lhs->minor > rhs->minor) { return A_TRUE; }
47 if (lhs->minor < rhs->minor) { return A_FALSE; }
48 if (lhs->third > rhs->third) { return A_TRUE; }
49 if (lhs->third < rhs->third) { return A_FALSE; }
50 return A_FALSE;
53 a_bool a_version_le(a_version const *lhs, a_version const *rhs)
55 if (lhs->major < rhs->major) { return A_TRUE; }
56 if (lhs->major > rhs->major) { return A_FALSE; }
57 if (lhs->minor < rhs->minor) { return A_TRUE; }
58 if (lhs->minor > rhs->minor) { return A_FALSE; }
59 if (lhs->third < rhs->third) { return A_TRUE; }
60 if (lhs->third > rhs->third) { return A_FALSE; }
61 return A_TRUE;
64 a_bool a_version_ge(a_version const *lhs, a_version const *rhs)
66 if (lhs->major > rhs->major) { return A_TRUE; }
67 if (lhs->major < rhs->major) { return A_FALSE; }
68 if (lhs->minor > rhs->minor) { return A_TRUE; }
69 if (lhs->minor < rhs->minor) { return A_FALSE; }
70 if (lhs->third > rhs->third) { return A_TRUE; }
71 if (lhs->third < rhs->third) { return A_FALSE; }
72 return A_TRUE;
75 a_bool a_version_eq(a_version const *lhs, a_version const *rhs)
77 return (lhs->major == rhs->major) && (lhs->minor == rhs->minor) && (lhs->third == rhs->third);
80 a_bool a_version_ne(a_version const *lhs, a_version const *rhs)
82 return (lhs->major != rhs->major) || (lhs->minor != rhs->minor) || (lhs->third != rhs->third);
85 #include <ctype.h>
86 #if __has_warning("-Wdisabled-macro-expansion")
87 #pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
88 #endif /* -Wdisabled-macro-expansion */
90 static A_INLINE char const *a_version_set_alpha_(a_version *ctx, char const *alpha)
92 unsigned int c = 1;
93 ctx->alpha_[0] = *alpha;
94 for (++alpha; isalpha((a_byte)*alpha); ++alpha)
96 if (c < sizeof(ctx->alpha_)) { ctx->alpha_[c++] = *alpha; }
98 if (*alpha == '.')
100 if (c < sizeof(ctx->alpha_)) { ctx->alpha_[c++] = *alpha; }
101 else { ctx->alpha_[c - 1] = *alpha; }
102 ++alpha;
104 while (c < sizeof(ctx->alpha_)) { ctx->alpha_[c++] = 0; }
105 return alpha;
108 void a_version_set_alpha(a_version *ctx, char const *alpha)
110 if ((*alpha == '.' || *alpha == '-' || *alpha == '+' || isalpha((a_byte)*alpha)) &&
111 (isalpha((a_byte)alpha[1]) || !alpha[1])) { a_version_set_alpha_(ctx, alpha); }
114 #include <stdlib.h>
116 unsigned int a_version_parse(a_version *ctx, char const *ver)
118 union
120 char const *s;
121 char *p;
122 } u;
123 u.s = ver;
124 if (!ver) { return 0; }
125 ctx->major = (unsigned int)strtoul(u.s, &u.p, 10);
126 if (u.s[0] == '.' && u.s[1] >= '0' && u.s[1] <= '9') { ++u.s; }
127 else { goto major; }
128 ctx->minor = (unsigned int)strtoul(u.s, &u.p, 10);
129 if (u.s[0] == '.' && u.s[1] >= '0' && u.s[1] <= '9') { ++u.s; }
130 else { goto minor; }
131 ctx->third = (unsigned int)strtoul(u.s, &u.p, 10);
132 if ((u.s[0] == '.' || u.s[0] == '-' || u.s[0] == '+' || isalpha((a_byte)u.s[0])) &&
133 (isalnum((a_byte)u.s[1]) || !u.s[1])) { u.s = a_version_set_alpha_(ctx, u.s); }
134 else { goto third; }
135 ctx->extra = (unsigned int)strtoul(u.s, &u.p, 10);
136 goto extra;
137 major:
138 ctx->minor = 0;
139 minor:
140 ctx->third = 0;
141 third:
142 ctx->extra = 0;
143 extra:
144 return (unsigned int)(u.s - ver);
147 #include <stdio.h>
148 #if defined(_MSC_VER) && (_MSC_VER < 1900)
149 #define snprintf sprintf_s
150 #endif /* _MSC_VER */
152 void a_version_alpha(a_version const *ctx, char alpha[5])
154 unsigned int c;
155 for (c = 0; c < sizeof(ctx->alpha_) && ctx->alpha_[c]; ++c)
157 alpha[c] = ctx->alpha_[c];
159 alpha[c] = 0;
162 unsigned int a_version_tostr(a_version const *ctx, void *pdata, a_size nbyte)
164 int n;
165 char *p = (char *)pdata;
166 char alpha[sizeof(ctx->alpha_) + 1];
167 if (ctx->extra || isalpha((a_byte)ctx->alpha_[0]) || isalpha((a_byte)ctx->alpha_[1]))
169 a_version_alpha(ctx, alpha);
170 n = snprintf(p, nbyte, "%u.%u.%u%s%u",
171 ctx->major, ctx->minor, ctx->third, alpha, ctx->extra);
173 else
175 n = snprintf(p, nbyte, "%u.%u.%u",
176 ctx->major, ctx->minor, ctx->third);
178 return n > 0 ? (unsigned int)n : 0;