Skip to content

Commit

Permalink
convert version from string to real number for comparison
Browse files Browse the repository at this point in the history
Allow 2.3.10 to be > than 2.3.9
allow 1.1.1.1 and not only 1.1.1
#2301
  • Loading branch information
supermerill committed Feb 3, 2022
1 parent 56b2f2b commit 3a3627a
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 100 deletions.
2 changes: 1 addition & 1 deletion src/libslic3r/AppConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ std::string AppConfig::load()
// Make 1.40.0 alphas compare well
ini_ver->set_metadata(boost::none);
ini_ver->set_prerelease(boost::none);
m_legacy_datadir = ini_ver < Semver(1, 40, 0);
m_legacy_datadir = ini_ver < Semver(1, 40, 0, 0);
}

// Legacy conversion
Expand Down
71 changes: 45 additions & 26 deletions src/libslic3r/Semver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,30 @@ class Semver
public:
struct Major { const int i; Major(int i) : i(i) {} };
struct Minor { const int i; Minor(int i) : i(i) {} };
struct Counter { const int i; Counter(int i) : i(i) {} }; //for SuSi
struct Patch { const int i; Patch(int i) : i(i) {} };

Semver() : ver(semver_zero()) {}

Semver(int major, int minor, int patch,
Semver(int major, int minor, int counter, int patch,
boost::optional<const std::string&> metadata = boost::none,
boost::optional<const std::string&> prerelease = boost::none)
: ver(semver_zero())
{
ver.major = major;
ver.minor = minor;
ver.patch = patch;
semver_free(&ver);
ver.counter_size = 4;
ver.counters = new int[4];
ver.counters[0] = major;
ver.counters[1] = minor;
ver.counters[2] = counter;
ver.counters[3] = patch;
set_metadata(metadata);
set_prerelease(prerelease);
}

Semver(const std::string &str) : ver(semver_zero())
{

auto parsed = parse(str);
if (! parsed) {
throw Slic3r::RuntimeError(std::string("Could not parse version string: ") + str);
Expand All @@ -60,13 +66,16 @@ class Semver

static const Semver inf()
{
static semver_t ver = { std::numeric_limits<int>::max(), std::numeric_limits<int>::max(), std::numeric_limits<int>::max(), nullptr, nullptr };
semver_t ver = { new int[4], 4, nullptr, nullptr };
for (int i = 0; i < ver.counter_size; i++)
ver.counters[i] = std::numeric_limits<int>::max();
return Semver(ver);
}

static const Semver invalid()
{
static semver_t ver = { -1, 0, 0, nullptr, nullptr };
semver_t ver = { new int[1], 1, nullptr, nullptr };
ver.counters[0] = -1;
return Semver(ver);
}

Expand All @@ -91,16 +100,18 @@ class Semver
~Semver() { ::semver_free(&ver); }

// const accessors
int maj() const { return ver.major; }
int min() const { return ver.minor; }
int patch() const { return ver.patch; }
//int maj() const { return ver.counter_size > 0 ? ver.counters[0] : 0; }
//int min() const { return ver.counter_size > 1 ? ver.counters[1] : 0; }
//int counter() const { return ver.counter_size > 2 ? ver.counters[2] : 0; }
//int patch() const { return ver.counter_size > 3 ? ver.counters[3] : 0; }
const char* prerelease() const { return ver.prerelease; }
const char* metadata() const { return ver.metadata; }

// Setters
void set_maj(int maj) { ver.major = maj; }
void set_min(int min) { ver.minor = min; }
void set_patch(int patch) { ver.patch = patch; }
//void set_maj(int maj) { if(ver.counter_size > 0) ver.counters[0] = maj; }
//void set_min(int min) { if (ver.counter_size > 1) ver.counters[1] = min; }
//void set_counter(int count) { if (ver.counter_size > 2) ver.counters[2] = count; }
//void set_patch(int patch) { if (ver.counter_size > 3) ver.counters[3] = patch; }
void set_metadata(boost::optional<const std::string&> meta) { ver.metadata = meta ? strdup(*meta) : nullptr; }
void set_prerelease(boost::optional<const std::string&> pre) { ver.prerelease = pre ? strdup(*pre) : nullptr; }

Expand All @@ -120,25 +131,32 @@ class Semver

// Conversion
std::string to_string() const {
auto res = (boost::format("%1%.%2%.%3%") % ver.major % ver.minor % ver.patch).str();
std::string res;
for (int i = 0; i < ver.counter_size; i++) {
res += ( (i==0 ? boost::format("%1%") : boost::format(".%1%")) % ver.counters[i]).str();
}
if (ver.prerelease != nullptr) { res += '-'; res += ver.prerelease; }
if (ver.metadata != nullptr) { res += '+'; res += ver.metadata; }
return res;
}

// Arithmetics
Semver& operator+=(const Major &b) { ver.major += b.i; return *this; }
Semver& operator+=(const Minor &b) { ver.minor += b.i; return *this; }
Semver& operator+=(const Patch &b) { ver.patch += b.i; return *this; }
Semver& operator-=(const Major &b) { ver.major -= b.i; return *this; }
Semver& operator-=(const Minor &b) { ver.minor -= b.i; return *this; }
Semver& operator-=(const Patch &b) { ver.patch -= b.i; return *this; }
Semver operator+(const Major &b) const { Semver res(*this); return res += b; }
Semver operator+(const Minor &b) const { Semver res(*this); return res += b; }
Semver operator+(const Patch &b) const { Semver res(*this); return res += b; }
Semver operator-(const Major &b) const { Semver res(*this); return res -= b; }
Semver operator-(const Minor &b) const { Semver res(*this); return res -= b; }
Semver operator-(const Patch &b) const { Semver res(*this); return res -= b; }
//Semver& operator+=(const Major &b) { set_maj(maj()+b.i); return *this; }
//Semver& operator+=(const Minor &b) { set_min(min() + b.i); return *this; }
//Semver& operator+=(const Counter& b) { set_counter(counter() + b.i); return *this; }
//Semver& operator+=(const Patch &b) { set_patch(patch() + b.i); return *this; }
//Semver& operator-=(const Major& b) { set_maj(maj() - b.i); return *this; }
//Semver& operator-=(const Minor& b) { set_min(min() - b.i); return *this; }
//Semver& operator-=(const Counter& b) { set_counter(counter() - b.i); return *this; }
//Semver& operator-=(const Patch& b) { set_patch(patch() - b.i); return *this; }
//Semver operator+(const Major &b) const { Semver res(*this); return res += b; }
//Semver operator+(const Minor &b) const { Semver res(*this); return res += b; }
//Semver operator+(const Counter& b) const { Semver res(*this); return res += b; }
//Semver operator+(const Patch& b) const { Semver res(*this); return res += b; }
//Semver operator-(const Major &b) const { Semver res(*this); return res -= b; }
//Semver operator-(const Minor &b) const { Semver res(*this); return res -= b; }
//Semver operator-(const Counter& b) const { Semver res(*this); return res -= b; }
//Semver operator-(const Patch& b) const { Semver res(*this); return res -= b; }

// Stream output
friend std::ostream& operator<<(std::ostream& os, const Semver &self) {
Expand All @@ -148,9 +166,10 @@ class Semver
private:
semver_t ver;


Semver(semver_t ver) : ver(ver) {}

static semver_t semver_zero() { return { 0, 0, 0, nullptr, nullptr }; }
static semver_t semver_zero() { return { nullptr, 0, nullptr, nullptr }; }
static char * strdup(const std::string &str) { return ::semver_strdup(str.data()); }
};

Expand Down
162 changes: 106 additions & 56 deletions src/semver/semver.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,40 @@ semver_parse (const char *str, semver_t *ver) {
return res;
}

/**
* count he numbezr of int
*/
int
semver_count_version(const char* str) {
size_t len;
int index, value;
char* slice, * next, * endptr;
slice = (char*)str;
index = 0;

while (slice != NULL && index++ < 4) {
next = strchr(slice, DELIMITER[0]);
if (next == NULL)
len = strlen(slice);
else
len = next - slice;
if (len > SLICE_SIZE) return -1;

/* Cast to integer and store */
value = strtol(slice, &endptr, 10);
if (endptr != next && *endptr != '\0') return -1;

/* Continue with the next slice */
if (next == NULL)
slice = NULL;
else
slice = next + 1;
}

// Major and minor versions are mandatory, patch version is not mandatory.
return index;
}

/**
* Parses a given string as semver expression.
*
Expand All @@ -178,37 +212,37 @@ semver_parse_version (const char *str, semver_t *ver) {
char *slice, *next, *endptr;
slice = (char *) str;
index = 0;

// non mandatory
ver->patch = 0;

while (slice != NULL && index++ < 4) {
next = strchr(slice, DELIMITER[0]);
if (next == NULL)
len = strlen(slice);
else
len = next - slice;
if (len > SLICE_SIZE) return -1;

/* Cast to integer and store */
value = strtol(slice, &endptr, 10);
if (endptr != next && *endptr != '\0') return -1;

switch (index) {
case 1: ver->major = value; break;
case 2: ver->minor = value; break;
case 3: ver->patch = value; break;
}

/* Continue with the next slice */
if (next == NULL)
slice = NULL;
else
slice = next + 1;
if (ver->counters) {
free(ver->counters);
ver->counters = NULL;
}
ver->counter_size = semver_count_version(str);
if (ver->counter_size != 0) {
ver->counters = malloc(ver->counter_size * sizeof(int));

while (slice != NULL && index++ < 4) {
next = strchr(slice, DELIMITER[0]);
if (next == NULL)
len = strlen(slice);
else
len = next - slice;
if (len > SLICE_SIZE) return -1;

/* Cast to integer and store */
value = strtol(slice, &endptr, 10);
if (endptr != next && *endptr != '\0') return -1;

ver->counters[index - 1] = value;

/* Continue with the next slice */
if (next == NULL)
slice = NULL;
else
slice = next + 1;
}
}

// Major and minor versions are mandatory, patch version is not mandatory.
return (index == 2 || index == 3) ? 0 : -1;
return (index >= 2) ? 0 : -1;
}

static int
Expand Down Expand Up @@ -280,12 +314,11 @@ semver_compare_prerelease (semver_t x, semver_t y) {

int
semver_compare_version (semver_t x, semver_t y) {
int res;
int res = binary_comparison(x.counter_size, y.counter_size);

if ((res = binary_comparison(x.major, y.major)) == 0) {
if ((res = binary_comparison(x.minor, y.minor)) == 0) {
return binary_comparison(x.patch, y.patch);
}
for (int i = 0; i < x.counter_size && i < y.counter_size; i++) {
if ((res = binary_comparison(x.counters[i], y.counters[i])) != 0)
return res;
}

return res;
Expand Down Expand Up @@ -379,9 +412,9 @@ semver_lte (semver_t x, semver_t y) {

int
semver_satisfies_caret (semver_t x, semver_t y) {
if (x.major == y.major) {
if (x.major == 0) {
return x.minor >= y.minor;
if (x.counter_size > 0 && y.counter_size > 0 && x.counters[0] == y.counters[0]) {
if (x.counters[0] == 0) {
return x.counter_size > 1 && y.counter_size > 1 && x.counters[1] >= y.counters[1];
}
return 1;
}
Expand All @@ -402,8 +435,8 @@ semver_satisfies_caret (semver_t x, semver_t y) {

int
semver_satisfies_patch (semver_t x, semver_t y) {
return x.major == y.major
&& x.minor == y.minor;
return x.counter_size > 1 && y.counter_size > 1 && x.counters[0] == y.counters[0]
&& x.counters[1] == y.counters[1];
}

/**
Expand Down Expand Up @@ -480,6 +513,11 @@ semver_free (semver_t *x) {
free(x->prerelease);
x->prerelease = NULL;
}
if (x->counters) {
x->counter_size = 0;
free(x->counters);
x->counters = NULL;
}
}

/**
Expand Down Expand Up @@ -507,9 +545,9 @@ concat_char (char * str, char * x, char * sep) {

void
semver_render (semver_t *x, char *dest) {
if (x->major) concat_num(dest, x->major, NULL);
if (x->minor) concat_num(dest, x->minor, DELIMITER);
if (x->patch) concat_num(dest, x->patch, DELIMITER);
for (int i = 0; i < x->counter_size; ++i) {
concat_num(dest, x->counters[i], i==0 ? NULL : DELIMITER);
}
if (x->prerelease) concat_char(dest, x->prerelease, PR_DELIMITER);
if (x->metadata) concat_char(dest, x->metadata, MT_DELIMITER);
}
Expand All @@ -519,18 +557,21 @@ semver_render (semver_t *x, char *dest) {
*/

void
semver_bump (semver_t *x) {
x->major++;
semver_bump_major (semver_t *x) {
if(x->counter_size > 0)
x->counters[0]++;
}

void
semver_bump_minor (semver_t *x) {
x->minor++;
if (x->counter_size > 1)
x->counters[1]++;
}

void
semver_bump_patch (semver_t *x) {
x->patch++;
semver_bump (semver_t *x, int idx) {
if (x->counter_size > idx)
x->counters[idx]++;
}

/**
Expand Down Expand Up @@ -612,9 +653,9 @@ semver_numeric (semver_t *x) {
char buf[SLICE_SIZE * 3];
memset(&buf, 0, SLICE_SIZE * 3);

if (x->major) concat_num(buf, x->major, NULL);
if (x->minor) concat_num(buf, x->minor, NULL);
if (x->patch) concat_num(buf, x->patch, NULL);
for (int i = 0; i < x->counter_size; ++i) {
concat_num(buf, x->counters[i], NULL);
}

num = parse_int(buf);
if(num == -1) return -1;
Expand All @@ -625,11 +666,17 @@ semver_numeric (semver_t *x) {
return num;
}

char *semver_strdup(const char *src) {
if (src == NULL) return NULL;
size_t len = strlen(src) + 1;
char *res = malloc(len);
return res != NULL ? (char *) memcpy(res, src, len) : NULL;
char* semver_strdup(const char* src) {
if (src == NULL) return NULL;
size_t len = strlen(src) + 1;
char* res = malloc(len);
return res != NULL ? (char*)memcpy(res, src, len) : NULL;
}

int* semver_intdup(const int* src, int len) {
if (src == NULL) return NULL;
int* res = malloc(len * sizeof(int));
return res != NULL ? (int*)memcpy(res, src, len * sizeof(int)) : NULL;
}

semver_t
Expand All @@ -639,7 +686,10 @@ semver_copy(const semver_t *ver) {
res.metadata = strdup(ver->metadata);
}
if (ver->prerelease != NULL) {
res.prerelease = strdup(ver->prerelease);
res.prerelease = strdup(ver->prerelease);
}
if (ver->counters) {
res.counters = semver_intdup(ver->counters, ver->counter_size);
}
return res;
}
Loading

0 comments on commit 3a3627a

Please sign in to comment.