#include "semver.h" #include "epoch.h" #include #include #include #include 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: out |= ((u128)self->simple.major << (64 + 52)); break; case Rapid: major = (uint64_t)self->rapid.major << 52; minor = (uint64_t)self->rapid.minor << 40; out = (u128)(major | minor) << 64; break; case SemVer: major = (uint64_t)self->semver.major << 52; minor = (uint64_t)self->semver.minor << 40; patch = (uint64_t)self->semver.patch << 28; out = (u128)(major | minor | patch) << 64; break; case Extended: 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; out = (u128)(major | minor | patch | build) << 64; break; } switch (self->pr.tag) { case Alpha: out |= ((u128)010000 << 64); pre = self->pr.alpha & mask; out |= ((u128)pre << 64); break; case Beta: out |= ((u128)020000 << 64); pre = self->pr.beta & mask; out |= ((u128)pre << 64); break; case ReleaseCandidate: out |= ((u128)040000 << 64); pre = self->pr.rc & mask; out |= ((u128)pre << 64); break; case GitRev: out |= ((u128)01000 << 64); ts = dateTimeGetTimestamp(&self->pr.git.dt); 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]; } int parseArch(char *s) { int i; for (i = 0; i < 14; i++) { if (strncasecmp(s, ArchNames[i], 10) == 0) return i; } 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; } int parsePreRelease(PreRelease *pr, const char *s) { // todo return -1; } int parseVersion(Version *self, const char *s) { // todo return -1; } char *versionToString(Version *self) { char *buf, *temp; buf = calloc(100, sizeof(char)); if (buf == NULL) return NULL; temp = calloc(50, sizeof(char)); if (temp == NULL) { free(buf); return NULL; } switch (self->vk_tag) { case Simple: snprintf(buf, 6, "%d", self->simple.major); break; case Rapid: snprintf(buf, 13, "%d.%d", self->rapid.major, self->rapid.minor); break; case SemVer: snprintf( buf, 20, "%d.%d.%d", self->semver.major, self->semver.minor, self->semver.patch ); break; case Extended: snprintf( buf, 27, "%d.%d.%d.%d", self->extended.major, self->extended.minor, self->extended.patch, self->extended.build ); break; } switch (self->pr.tag) { case PRNone: snprintf(temp, 9, "-%s", archToString(self->arch)); break; case Alpha: snprintf(temp, 25, "_alpha%d-%s", self->pr.alpha, archToString(self->arch)); break; case Beta: snprintf(temp, 25, "_beta%d-%s", self->pr.beta, archToString(self->arch)); break; case ReleaseCandidate: snprintf(temp, 25, "_rc%d-%s", self->pr.rc, archToString(self->arch)); break; case GitRev: snprintf( temp, 50, "_git_%c%c%c%c%c%c%c.%li-%s", 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), archToString(self->arch) ); } strncat(buf, temp, 50); free(temp); return buf; }