2018-04-05 12:22:11 +00:00
|
|
|
#ifndef slic3r_Semver_hpp_
|
|
|
|
#define slic3r_Semver_hpp_
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <cstring>
|
2018-04-11 11:12:08 +00:00
|
|
|
#include <ostream>
|
2018-04-05 12:22:11 +00:00
|
|
|
#include <boost/optional.hpp>
|
|
|
|
#include <boost/format.hpp>
|
|
|
|
|
|
|
|
#include "semver/semver.h"
|
|
|
|
|
|
|
|
namespace Slic3r {
|
|
|
|
|
|
|
|
|
|
|
|
class Semver
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
struct Major { const int i; Major(int i) : i(i) {} };
|
|
|
|
struct Minor { const int i; Minor(int i) : i(i) {} };
|
|
|
|
struct Patch { const int i; Patch(int i) : i(i) {} };
|
|
|
|
|
2018-04-12 18:04:48 +00:00
|
|
|
Semver() : ver(semver_zero()) {}
|
|
|
|
|
2018-04-11 11:12:08 +00:00
|
|
|
Semver(int major, int minor, int patch,
|
|
|
|
boost::optional<std::string> metadata = boost::none,
|
|
|
|
boost::optional<std::string> prerelease = boost::none)
|
|
|
|
{
|
|
|
|
ver.major = major;
|
|
|
|
ver.minor = minor;
|
|
|
|
ver.patch = patch;
|
|
|
|
ver.metadata = metadata ? std::strcpy(ver.metadata, metadata->c_str()) : nullptr;
|
|
|
|
ver.prerelease = prerelease ? std::strcpy(ver.prerelease, prerelease->c_str()) : nullptr;
|
|
|
|
}
|
|
|
|
|
2018-04-05 12:22:11 +00:00
|
|
|
static boost::optional<Semver> parse(const std::string &str)
|
|
|
|
{
|
2018-04-11 11:12:08 +00:00
|
|
|
semver_t ver = semver_zero();
|
2018-04-05 12:22:11 +00:00
|
|
|
if (::semver_parse(str.c_str(), &ver) == 0) {
|
|
|
|
return Semver(ver);
|
|
|
|
} else {
|
|
|
|
return boost::none;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-11 15:07:27 +00:00
|
|
|
static const Semver zero() { return Semver(semver_zero()); }
|
2018-04-06 14:49:33 +00:00
|
|
|
|
|
|
|
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 };
|
|
|
|
return Semver(ver);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const Semver invalid()
|
|
|
|
{
|
|
|
|
static semver_t ver = { -1, 0, 0, nullptr, nullptr };
|
|
|
|
return Semver(ver);
|
|
|
|
}
|
|
|
|
|
2018-04-11 15:07:27 +00:00
|
|
|
Semver(Semver &&other) : ver(other.ver) { other.ver = semver_zero(); }
|
|
|
|
Semver(const Semver &other) : ver(::semver_copy(&other.ver)) {}
|
2018-04-05 12:22:11 +00:00
|
|
|
|
|
|
|
Semver &operator=(Semver &&other)
|
|
|
|
{
|
2018-04-10 14:27:42 +00:00
|
|
|
::semver_free(&ver);
|
2018-04-05 12:22:11 +00:00
|
|
|
ver = other.ver;
|
2018-04-11 15:07:27 +00:00
|
|
|
other.ver = semver_zero();
|
2018-04-06 14:49:33 +00:00
|
|
|
return *this;
|
2018-04-05 12:22:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Semver &operator=(const Semver &other)
|
|
|
|
{
|
2018-04-06 14:49:33 +00:00
|
|
|
::semver_free(&ver);
|
2018-04-11 15:07:27 +00:00
|
|
|
ver = ::semver_copy(&other.ver);
|
2018-04-06 14:49:33 +00:00
|
|
|
return *this;
|
2018-04-05 12:22:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
~Semver() { ::semver_free(&ver); }
|
|
|
|
|
2018-04-13 14:15:30 +00:00
|
|
|
// const accessors
|
|
|
|
int major() const { return ver.major; }
|
|
|
|
int minor() const { return ver.minor; }
|
|
|
|
int patch() const { return ver.patch; }
|
|
|
|
const char* prerelease() const { return ver.prerelease; }
|
|
|
|
const char* metadata() const { return ver.metadata; }
|
|
|
|
|
2018-04-05 12:22:11 +00:00
|
|
|
// Comparison
|
|
|
|
bool operator<(const Semver &b) const { return ::semver_compare(ver, b.ver) == -1; }
|
|
|
|
bool operator<=(const Semver &b) const { return ::semver_compare(ver, b.ver) <= 0; }
|
|
|
|
bool operator==(const Semver &b) const { return ::semver_compare(ver, b.ver) == 0; }
|
|
|
|
bool operator!=(const Semver &b) const { return ::semver_compare(ver, b.ver) != 0; }
|
|
|
|
bool operator>=(const Semver &b) const { return ::semver_compare(ver, b.ver) >= 0; }
|
|
|
|
bool operator>(const Semver &b) const { return ::semver_compare(ver, b.ver) == 1; }
|
|
|
|
// We're using '&' instead of the '~' operator here as '~' is unary-only:
|
2018-04-06 14:49:33 +00:00
|
|
|
// Satisfies patch if Major and minor are equal.
|
2018-04-05 12:22:11 +00:00
|
|
|
bool operator&(const Semver &b) const { return ::semver_satisfies_patch(ver, b.ver); }
|
|
|
|
bool operator^(const Semver &b) const { return ::semver_satisfies_caret(ver, b.ver); }
|
2018-04-06 14:49:33 +00:00
|
|
|
bool in_range(const Semver &low, const Semver &high) const { return low <= *this && *this <= high; }
|
2018-04-05 12:22:11 +00:00
|
|
|
|
|
|
|
// Conversion
|
|
|
|
std::string to_string() const {
|
|
|
|
auto res = (boost::format("%1%.%2%.%3%") % ver.major % ver.minor % ver.patch).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; }
|
2018-04-06 14:49:33 +00:00
|
|
|
|
2018-04-05 12:22:11 +00:00
|
|
|
private:
|
|
|
|
semver_t ver;
|
|
|
|
|
|
|
|
Semver(semver_t ver) : ver(ver) {}
|
2018-04-11 11:12:08 +00:00
|
|
|
|
|
|
|
static semver_t semver_zero() { return { 0, 0, 0, nullptr, nullptr }; }
|
2018-04-05 12:22:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif
|