diff --git a/include/semver.h b/include/semver.h index 18a9d3c..4e573e5 100644 --- a/include/semver.h +++ b/include/semver.h @@ -1,7 +1,8 @@ #include "epoch.h" #include -#define u128 __uint128_t +#define u128 __uint128_t +#define U12_MAX 4096 typedef enum { Simple, diff --git a/semver.c b/semver.c index ac3ee98..3b07e97 100644 --- a/semver.c +++ b/semver.c @@ -106,9 +106,69 @@ int parseArch(char *s) { return -1; } -int parsePreRelease(PreRelease *pr, const char *s) { +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) { // todo - return -1; + 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; } int parseVersion(Version *self, const char *s) { @@ -156,13 +216,22 @@ char *versionToString(Version *self) { snprintf(temp, 9, "-%s", archToString(self->arch)); break; case Alpha: - snprintf(temp, 25, "_alpha%d-%s", self->pr.alpha, archToString(self->arch)); + 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)); break; case Beta: - snprintf(temp, 25, "_beta%d-%s", self->pr.beta, archToString(self->arch)); + 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)); break; case ReleaseCandidate: - snprintf(temp, 25, "_rc%d-%s", self->pr.rc, archToString(self->arch)); + 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)); break; case GitRev: snprintf(