libsemver/semver.c

255 lines
6.9 KiB
C
Raw Normal View History

2024-02-10 00:48:59 -05:00
#include "semver.h"
2024-02-10 01:50:01 -05:00
#include "epoch.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
2024-02-10 00:48:59 -05:00
u128 u128FromVersion(Version *self) {
u128 out = 0;
uint16_t pre = 0, mask = 03777;
uint64_t major, minor, patch, build;
int64_t ts;
switch (self->vk_tag) {
case Simple:
2024-02-10 23:18:06 -05:00
out |= ((u128)self->simple.major << (64 + 52));
2024-02-10 00:48:59 -05:00
break;
case Rapid:
2024-02-10 23:18:06 -05:00
major = (uint64_t)self->rapid.major << 52;
minor = (uint64_t)self->rapid.minor << 40;
2024-02-10 00:48:59 -05:00
out = (u128)(major | minor) << 64;
break;
case SemVer:
2024-02-10 23:18:06 -05:00
major = (uint64_t)self->semver.major << 52;
minor = (uint64_t)self->semver.minor << 40;
patch = (uint64_t)self->semver.patch << 28;
2024-02-10 00:48:59 -05:00
out = (u128)(major | minor | patch) << 64;
break;
case Extended:
2024-02-10 23:18:06 -05:00
major = (uint64_t)self->extended.major << 52;
minor = (uint64_t)self->extended.minor << 40;
patch = (uint64_t)self->extended.patch << 28;
build = (uint64_t)self->extended.build << 16;
2024-02-10 00:48:59 -05:00
out = (u128)(major | minor | patch | build) << 64;
break;
}
2024-02-10 23:18:06 -05:00
switch (self->pr.tag) {
2024-02-10 00:48:59 -05:00
case Alpha:
out |= ((u128)010000 << 64);
2024-02-10 23:18:06 -05:00
pre = self->pr.alpha & mask;
2024-02-10 00:48:59 -05:00
out |= ((u128)pre << 64);
break;
case Beta:
out |= ((u128)020000 << 64);
2024-02-10 23:18:06 -05:00
pre = self->pr.beta & mask;
2024-02-10 00:48:59 -05:00
out |= ((u128)pre << 64);
break;
case ReleaseCandidate:
out |= ((u128)040000 << 64);
2024-02-10 23:18:06 -05:00
pre = self->pr.rc & mask;
2024-02-10 00:48:59 -05:00
out |= ((u128)pre << 64);
break;
case GitRev:
out |= ((u128)01000 << 64);
2024-02-10 23:18:06 -05:00
ts = dateTimeGetTimestamp(&self->pr.git.dt);
2024-02-10 00:48:59 -05:00
out |= (u128)ts;
break;
case PRNone:
out |= ((u128)0100000 << 64);
break;
}
return out;
}
Comparison compareVersion(Version *self, Version *other) {
u128 a, b;
if (self->arch != other->arch)
return CompNone;
a = u128FromVersion(self);
b = u128FromVersion(other);
if (a < b)
return CompLess;
else if (a == b)
return CompEqual;
else if (a > b)
return CompGreater;
else
return CompNone;
}
const char *ArchNames[] = { "any", "arm", "aarch64", "loongson", "mips32", "mips64",
"ppc", "ppc64", "riscv64", "s390x", "sparc", "sparc64", "x86", "x86_64" };
const char *archToString(Arch self) {
return ArchNames[self];
}
2024-02-10 12:18:31 -05:00
int parseArch(char *s) {
int i;
for (i = 0; i < 14; i++) {
if (strncasecmp(s, ArchNames[i], 10) == 0)
return i;
2024-02-10 01:50:01 -05:00
}
if (strncasecmp(s, "arm64", 5) == 0)
return arm64;
else if (strncasecmp(s, "i386", 4) == 0)
return x86;
else if (strncasecmp(s, "i486", 4) == 0)
return x86;
else if (strncasecmp(s, "i586", 4) == 0)
return x86;
else if (strncasecmp(s, "i686", 4) == 0)
return x86;
else
return -1;
2024-02-10 01:50:01 -05:00
}
uint16_t parseNumNonZero(char *vp, long *out) {
long val;
char *ep;
if (vp == NULL) {
*out = 0;
}
val = strtol(vp, &ep, 10);
if (vp != ep && ep == NULL && val <= U12_MAX) {
*out = val;
} else {
return 1;
}
return 0;
}
int parseGitRev(char *vp, GitRevision *git) {
2024-02-10 23:18:06 -05:00
// todo
return 1;
}
int parsePreRelease(PreRelease *pr, char *s) {
PreReleaseTag tag;
long val = 0;
char *vp;
if (strncasecmp(s, "alpha", 5) == 0) {
tag = Alpha;
vp = s + 5;
if (parseNumNonZero(vp, &val) != 0)
return 1;
} else if (strncasecmp(s, "beta", 4) == 0) {
tag = Beta;
vp = s + 4;
if (parseNumNonZero(vp, &val) != 0)
return 1;
} else if (strncasecmp(s, "rc", 2) == 0) {
tag = ReleaseCandidate;
vp = s + 2;
if (parseNumNonZero(vp, &val) != 0)
return 1;
} else if (strncasecmp(s, "git_", 4) == 0) {
tag = GitRev;
vp = s + 4;
if (parseGitRev(vp, &pr->git) != 0)
return 1;
}
pr->tag = tag;
switch (tag) {
case Alpha:
pr->alpha = (uint16_t)val;
break;
case Beta:
pr->beta = (uint16_t)val;
break;
case ReleaseCandidate:
pr->rc = (uint16_t)val;
break;
case GitRev:
break;
default: return -1;
}
return 0;
2024-02-10 23:18:06 -05:00
}
2024-02-10 12:18:31 -05:00
int parseVersion(Version *self, const char *s) {
// todo
return -1;
}
2024-02-10 01:50:01 -05:00
char *versionToString(Version *self) {
char *buf, *temp;
2024-02-10 01:51:54 -05:00
buf = calloc(100, sizeof(char));
2024-02-10 01:50:01 -05:00
if (buf == NULL) return NULL;
temp = calloc(50, sizeof(char));
if (temp == NULL) {
free(buf);
return NULL;
}
switch (self->vk_tag) {
case Simple:
2024-02-10 23:18:06 -05:00
snprintf(buf, 6, "%d", self->simple.major);
2024-02-10 01:50:01 -05:00
break;
case Rapid:
2024-02-10 23:18:06 -05:00
snprintf(buf, 13, "%d.%d", self->rapid.major, self->rapid.minor);
2024-02-10 01:50:01 -05:00
break;
case SemVer:
snprintf(
buf, 20, "%d.%d.%d",
2024-02-10 23:18:06 -05:00
self->semver.major,
self->semver.minor,
self->semver.patch
2024-02-10 01:50:01 -05:00
);
break;
case Extended:
snprintf(
buf, 27, "%d.%d.%d.%d",
2024-02-10 23:18:06 -05:00
self->extended.major,
self->extended.minor,
self->extended.patch,
self->extended.build
2024-02-10 01:50:01 -05:00
);
break;
}
2024-02-10 23:18:06 -05:00
switch (self->pr.tag) {
2024-02-10 01:50:01 -05:00
case PRNone:
snprintf(temp, 9, "-%s", archToString(self->arch));
break;
case Alpha:
if (self->pr.alpha == 0)
snprintf(temp, 25, "_alpha-%s", archToString(self->arch));
else
snprintf(temp, 25, "_alpha%d-%s", self->pr.alpha, archToString(self->arch));
2024-02-10 01:50:01 -05:00
break;
case Beta:
if (self->pr.beta == 0)
snprintf(temp, 25, "_beta-%s", archToString(self->arch));
else
snprintf(temp, 25, "_beta%d-%s", self->pr.beta, archToString(self->arch));
2024-02-10 01:50:01 -05:00
break;
case ReleaseCandidate:
if (self->pr.rc == 0)
snprintf(temp, 25, "_rc-%s", archToString(self->arch));
else
snprintf(temp, 25, "_rc%d-%s", self->pr.rc, archToString(self->arch));
2024-02-10 01:50:01 -05:00
break;
case GitRev:
snprintf(
2024-02-10 01:51:54 -05:00
temp, 50, "_git_%c%c%c%c%c%c%c.%li-%s",
2024-02-10 23:18:06 -05:00
self->pr.git.hash[0],
self->pr.git.hash[1],
self->pr.git.hash[2],
self->pr.git.hash[3],
self->pr.git.hash[4],
self->pr.git.hash[5],
self->pr.git.hash[6],
dateTimeGetTimestamp(&self->pr.git.dt),
2024-02-10 01:50:01 -05:00
archToString(self->arch)
);
}
strncat(buf, temp, 50);
free(temp);
return buf;
}