Implement methods to modify version object in various ways (#2)

* Initial implementation of non-mutable setting and resetting version components.

* Document new functionality in source code and update README.
This commit is contained in:
2017-01-05 21:18:51 +01:00
committed by GitHub
parent 0ca0088ee2
commit f24208aa9f
9 changed files with 683 additions and 76 deletions
+40 -3
View File
@@ -38,14 +38,51 @@ namespace version {
int compare(const Version_data&, const Version_data&) const;
};
/// Implementation of various version modification methods.
/**
All methods are non-destructive, i.e. they return a new object with modified properties;
original object is never modified.
*/
struct Semver200_modifier {
/// Set major version to specified value leaving all other components unchanged..
Version_data set_major(const Version_data&, const int) const;
/// Set minor version to specified value leaving all other components unchanged.
Version_data set_minor(const Version_data&, const int) const;
/// Set patch version to specified value leaving all other components unchanged.
Version_data set_patch(const Version_data&, const int) const;
/// Set pre-release version to specified value leaving all other components unchanged.
Version_data set_prerelease(const Version_data&, const Prerelease_identifiers&) const;
/// Set build version to specified value leaving all other components unchanged.
Version_data set_build(const Version_data&, const Build_identifiers&) const;
/// Set major version to specified value resetting all lower-priority components to zero/empty values.
Version_data reset_major(const Version_data&, const int) const;
/// Set minor version to specified value resetting all lower-priority components to zero/empty values.
Version_data reset_minor(const Version_data&, const int) const;
/// Set patch version to specified value resetting all lower-priority components to zero/empty values.
Version_data reset_patch(const Version_data&, const int) const;
/// Set pre-release version to specified value resetting all lower-priority components to zero/empty values.
Version_data reset_prerelease(const Version_data&, const Prerelease_identifiers&) const;
/// Set build version to specified value.
Version_data reset_build(const Version_data&, const Build_identifiers&) const;
};
/// Concrete version class that binds all semver 2.0.0 functionality together.
class Semver200_version : public Basic_version<Semver200_parser, Semver200_comparator> {
class Semver200_version : public Basic_version<Semver200_parser, Semver200_comparator, Semver200_modifier> {
public:
Semver200_version()
: Basic_version{ Semver200_parser(), Semver200_comparator() } {}
: Basic_version{ Semver200_parser(), Semver200_comparator(), Semver200_modifier() } {}
Semver200_version(const std::string& v)
: Basic_version{ v, Semver200_parser(), Semver200_comparator() } {}
: Basic_version{ v, Semver200_parser(), Semver200_comparator(), Semver200_modifier() } {}
};
}
+91 -29
View File
@@ -35,6 +35,11 @@ namespace version {
using std::runtime_error::runtime_error;
};
/// Any error in manipulating version data will result in Modification_error exception being thrown.
class Modification_error : public std::runtime_error {
using std::runtime_error::runtime_error;
};
/// Type of prerelease identifier: alphanumeric or numeric.
/**
Type of identifier affects comparison: alphanumeric identifiers are compared as ASCII strings, while
@@ -64,6 +69,10 @@ namespace version {
/// Description of version broken into parts, as per semantic versioning specification.
struct Version_data {
Version_data(const int M, const int m, const int p, const Prerelease_identifiers& pr, const Build_identifiers& b)
: major{ M }, minor{ m }, patch{ p }, prerelease_ids{ pr }, build_ids{ b } {}
int major; ///< Major version, change only on incompatible API modifications.
int minor; ///< Minor version, change on backwards-compatible API modifications.
int patch; ///< Patch version, change only on bugfixes.
@@ -76,59 +85,62 @@ namespace version {
};
// Forward declaration required for operators' template declarations.
template<typename Parser, typename Comparator>
template<typename Parser, typename Comparator, typename Modifier>
class Basic_version;
/// Test if left-hand version operand is of lower precedence than the right-hand version.
template<typename Parser, typename Comparator>
bool operator<(const Basic_version<Parser, Comparator>&,
const Basic_version<Parser, Comparator>&);
template<typename Parser, typename Comparator, typename Modifier>
bool operator<(const Basic_version<Parser, Comparator, Modifier>&,
const Basic_version<Parser, Comparator, Modifier>&);
/// Test if left-hand version operand if of equal precedence as the right-hand version.
template<typename Parser, typename Comparator>
bool operator==(const Basic_version<Parser, Comparator>&,
const Basic_version<Parser, Comparator>&);
template<typename Parser, typename Comparator, typename Modifier>
bool operator==(const Basic_version<Parser, Comparator, Modifier>&,
const Basic_version<Parser, Comparator, Modifier>&);
/// Output version object to stream using standard semver format (X.Y.Z-PR+B).
template<typename Parser, typename Comparator>
template<typename Parser, typename Comparator, typename Modifier>
std::ostream& operator<<(std::ostream&,
const Basic_version<Parser, Comparator>&);
const Basic_version<Parser, Comparator, Modifier>&);
/// Test if left-hand version and right-hand version are of different precedence.
template<typename Parser, typename Comparator>
bool operator!=(const Basic_version<Parser, Comparator>&,
const Basic_version<Parser, Comparator>&);
template<typename Parser, typename Comparator, typename Modifier>
bool operator!=(const Basic_version<Parser, Comparator, Modifier>&,
const Basic_version<Parser, Comparator, Modifier>&);
/// Test if left-hand version operand is of higher precedence than the right-hand version.
template<typename Parser, typename Comparator>
bool operator>(const Basic_version<Parser, Comparator>&,
const Basic_version<Parser, Comparator>&);
template<typename Parser, typename Comparator, typename Modifier>
bool operator>(const Basic_version<Parser, Comparator, Modifier>&,
const Basic_version<Parser, Comparator, Modifier>&);
/// Test if left-hand version operand is of higher or equal precedence as the right-hand version.
template<typename Parser, typename Comparator>
bool operator>=(const Basic_version<Parser, Comparator>&,
const Basic_version<Parser, Comparator>&);
template<typename Parser, typename Comparator, typename Modifier>
bool operator>=(const Basic_version<Parser, Comparator, Modifier>&,
const Basic_version<Parser, Comparator, Modifier>&);
/// Test if left-hand version operand is of lower or equal precedence as the right-hand version.
template<typename Parser, typename Comparator>
bool operator<=(const Basic_version<Parser, Comparator>&,
const Basic_version<Parser, Comparator>&);
template<typename Parser, typename Comparator, typename Modifier>
bool operator<=(const Basic_version<Parser, Comparator, Modifier>&,
const Basic_version<Parser, Comparator, Modifier>&);
/// Base class for various version parsing and precedence ordering schemes.
/// Base class for various version parsing, precedence ordering and data manipulation schemes.
/**
Basic_version class describes general version object without prescribing parsing,
validation and comparison rules. These rules are implemented by supplied Parser and
Comparator objects.
validation, comparison and modification rules. These rules are implemented by supplied Parser, Comparator
and Modifier objects.
*/
template<typename Parser, typename Comparator>
template<typename Parser, typename Comparator, typename Modifier>
class Basic_version {
public:
/// Construct Basic_version object using Parser object to parse default ("0.0.0") version string and Comparator for comparison.
Basic_version(Parser, Comparator);
/// Construct Basic_version object using Parser object to parse default ("0.0.0") version string, Comparator for comparison and Modifier for modification.
Basic_version(Parser, Comparator, Modifier);
/// Construct Basic_version object using Parser to parse supplied version string and Comparator for comparison.
Basic_version(const std::string&, Parser, Comparator);
/// Construct Basic_version object using Parser to parse supplied version string, Comparator for comparison and Modifier for modification.
Basic_version(const std::string&, Parser, Comparator, Modifier);
/// Construct Basic_version object using supplied Version_data, Parser, Comparator and Modifier objects.
Basic_version(const Version_data&, Parser, Comparator, Modifier);
/// Construct Basic_version by copying data from another one.
Basic_version(const Basic_version&);
@@ -142,6 +154,55 @@ namespace version {
const std::string prerelease() const; ///< Get prerelease version string.
const std::string build() const; ///< Get build version string.
/// Return a copy of version with major component set to specified value.
Basic_version set_major(const int) const;
/// Return a copy of version with the minor component set to specified value.
Basic_version set_minor(const int) const;
/// Return a copy of version with the patch component set to specified value.
Basic_version set_patch(const int) const;
/// Return a copy of version with the pre-release component set to specified value.
Basic_version set_prerelease(const std::string&) const;
/// Return a copy of version with the build component set to specified value.
Basic_version set_build(const std::string&) const;
/// Return a copy of version with the major component reset to specified value.
/**
Exact implementation of reset is delegated to Modifier object.
*/
Basic_version reset_major(const int) const;
/// Return a copy of version with the minor component reset to specified value.
/**
Exact implementation of reset is delegated to Modifier object.
*/
Basic_version reset_minor(const int) const;
/// Return a copy of version with the patch component reset to specified value.
/**
Exact implementation of reset is delegated to Modifier object.
*/
Basic_version reset_patch(const int) const;
/// Return a copy of version with the pre-release component reset to specified value.
/**
Exact implementation of reset is delegated to Modifier object.
*/
Basic_version reset_prerelease(const std::string&) const;
/// Return a copy of version with the build component reset to specified value.
/**
Exact implementation of reset is delegated to Modifier object.
*/
Basic_version reset_build(const std::string&) const;
Basic_version inc_major(const int = 1) const;
Basic_version inc_minor(const int = 1) const;
Basic_version inc_patch(const int = 1) const;
friend bool operator< <>(const Basic_version&, const Basic_version&);
friend bool operator== <>(const Basic_version&, const Basic_version&);
friend std::ostream& operator<< <>(std::ostream&s, const Basic_version&);
@@ -149,6 +210,7 @@ namespace version {
private:
Parser parser_;
Comparator comparator_;
Modifier modifier_;
Version_data ver_;
};
}
+115 -41
View File
@@ -45,66 +45,140 @@ namespace version {
}
}
template<typename Parser, typename Comparator>
Basic_version<Parser, Comparator>::Basic_version(Parser p, Comparator c)
: parser_(p), comparator_(c), ver_(parser_.parse("0.0.0")) {}
template<typename Parser, typename Comparator, typename Modifier>
Basic_version<Parser, Comparator, Modifier>::Basic_version(Parser p, Comparator c, Modifier m)
: parser_(p), comparator_(c), modifier_(m), ver_(parser_.parse("0.0.0")) {}
template<typename Parser, typename Comparator>
Basic_version<Parser, Comparator>::Basic_version(const std::string& v, Parser p, Comparator c)
: parser_(p), comparator_(c), ver_(parser_.parse(v)) {}
template<typename Parser, typename Comparator, typename Modifier>
Basic_version<Parser, Comparator, Modifier>::Basic_version(const std::string& v, Parser p, Comparator c, Modifier m)
: parser_(p), comparator_(c), modifier_(m), ver_(parser_.parse(v)) {}
template<typename Parser, typename Comparator>
Basic_version<Parser, Comparator>::Basic_version(const Basic_version<Parser, Comparator>&) = default;
template<typename Parser, typename Comparator, typename Modifier>
Basic_version<Parser, Comparator, Modifier>::Basic_version(const Version_data& v, Parser p, Comparator c, Modifier m)
: parser_(p), comparator_(c), modifier_(m), ver_(v) {}
template<typename Parser, typename Comparator>
Basic_version<Parser, Comparator>& Basic_version<Parser, Comparator>::operator=(
const Basic_version<Parser, Comparator>&) = default;
template<typename Parser, typename Comparator, typename Modifier>
Basic_version<Parser, Comparator, Modifier>::Basic_version(const Basic_version<Parser, Comparator, Modifier>&) = default;
template<typename Parser, typename Comparator>
int Basic_version<Parser, Comparator>::major() const {
template<typename Parser, typename Comparator, typename Modifier>
Basic_version<Parser, Comparator, Modifier>& Basic_version<Parser, Comparator, Modifier>::operator=(
const Basic_version<Parser, Comparator, Modifier>&) = default;
template<typename Parser, typename Comparator, typename Modifier>
int Basic_version<Parser, Comparator, Modifier>::major() const {
return ver_.major;
}
template<typename Parser, typename Comparator>
int Basic_version<Parser, Comparator>::minor() const {
template<typename Parser, typename Comparator, typename Modifier>
int Basic_version<Parser, Comparator, Modifier>::minor() const {
return ver_.minor;
}
template<typename Parser, typename Comparator>
int Basic_version<Parser, Comparator>::patch() const {
template<typename Parser, typename Comparator, typename Modifier>
int Basic_version<Parser, Comparator, Modifier>::patch() const {
return ver_.patch;
}
template<typename Parser, typename Comparator>
const std::string Basic_version<Parser, Comparator>::prerelease() const {
template<typename Parser, typename Comparator, typename Modifier>
const std::string Basic_version<Parser, Comparator, Modifier>::prerelease() const {
std::stringstream ss;
splice(ss, ver_.prerelease_ids, ".", [](const auto& id) { return id.first;});
return ss.str();
}
template<typename Parser, typename Comparator>
const std::string Basic_version<Parser, Comparator>::build() const {
template<typename Parser, typename Comparator, typename Modifier>
const std::string Basic_version<Parser, Comparator, Modifier>::build() const {
std::stringstream ss;
splice(ss, ver_.build_ids, ".", [](const auto& id) { return id;});
return ss.str();
}
template<typename Parser, typename Comparator, typename Modifier>
Basic_version<Parser, Comparator, Modifier> Basic_version<Parser, Comparator, Modifier>::set_major(const int m) const {
return Basic_version<Parser, Comparator, Modifier>(modifier_.set_major(ver_, m), parser_, comparator_, modifier_);
}
template<typename Parser, typename Comparator>
bool operator<(const Basic_version<Parser, Comparator>& l,
const Basic_version<Parser, Comparator>& r) {
template<typename Parser, typename Comparator, typename Modifier>
Basic_version<Parser, Comparator, Modifier> Basic_version<Parser, Comparator, Modifier>::set_minor(const int m) const {
return Basic_version<Parser, Comparator, Modifier>(modifier_.set_minor(ver_, m), parser_, comparator_, modifier_);
}
template<typename Parser, typename Comparator, typename Modifier>
Basic_version<Parser, Comparator, Modifier> Basic_version<Parser, Comparator, Modifier>::set_patch(const int p) const {
return Basic_version<Parser, Comparator, Modifier>(modifier_.set_patch(ver_, p), parser_, comparator_, modifier_);
}
template<typename Parser, typename Comparator, typename Modifier>
Basic_version<Parser, Comparator, Modifier> Basic_version<Parser, Comparator, Modifier>::set_prerelease(const std::string& pr) const {
auto vd = parser_.parse("0.0.0-" + pr);
return Basic_version<Parser, Comparator, Modifier>(modifier_.set_prerelease(ver_, vd.prerelease_ids), parser_, comparator_, modifier_);
}
template<typename Parser, typename Comparator, typename Modifier>
Basic_version<Parser, Comparator, Modifier> Basic_version<Parser, Comparator, Modifier>::set_build(const std::string& b) const {
auto vd = parser_.parse("0.0.0+" + b);
return Basic_version<Parser, Comparator, Modifier>(modifier_.set_build(ver_, vd.build_ids), parser_, comparator_, modifier_);
}
template<typename Parser, typename Comparator, typename Modifier>
Basic_version<Parser, Comparator, Modifier> Basic_version<Parser, Comparator, Modifier>::reset_major(const int m) const {
return Basic_version<Parser, Comparator, Modifier>(modifier_.reset_major(ver_, m), parser_, comparator_, modifier_);
}
template<typename Parser, typename Comparator, typename Modifier>
Basic_version<Parser, Comparator, Modifier> Basic_version<Parser, Comparator, Modifier>::reset_minor(const int m) const {
return Basic_version<Parser, Comparator, Modifier>(modifier_.reset_minor(ver_, m), parser_, comparator_, modifier_);
}
template<typename Parser, typename Comparator, typename Modifier>
Basic_version<Parser, Comparator, Modifier> Basic_version<Parser, Comparator, Modifier>::reset_patch(const int p) const {
return Basic_version<Parser, Comparator, Modifier>(modifier_.reset_patch(ver_, p), parser_, comparator_, modifier_);
}
template<typename Parser, typename Comparator, typename Modifier>
Basic_version<Parser, Comparator, Modifier> Basic_version<Parser, Comparator, Modifier>::reset_prerelease(const std::string& pr) const {
std::string ver = "0.0.0-" + pr;
auto vd = parser_.parse(ver);
return Basic_version<Parser, Comparator, Modifier>(modifier_.reset_prerelease(ver_, vd.prerelease_ids), parser_, comparator_, modifier_);
}
template<typename Parser, typename Comparator, typename Modifier>
Basic_version<Parser, Comparator, Modifier> Basic_version<Parser, Comparator, Modifier>::reset_build(const std::string& b) const {
std::string ver = "0.0.0+" + b;
auto vd = parser_.parse(ver);
return Basic_version<Parser, Comparator, Modifier>(modifier_.reset_build(ver_, vd.build_ids), parser_, comparator_, modifier_);
}
template<typename Parser, typename Comparator, typename Modifier>
Basic_version<Parser, Comparator, Modifier> Basic_version<Parser, Comparator, Modifier>::inc_major(const int i) const {
return reset_major(ver_.major + i);
}
template<typename Parser, typename Comparator, typename Modifier>
Basic_version<Parser, Comparator, Modifier> Basic_version<Parser, Comparator, Modifier>::inc_minor(const int i) const {
return reset_minor(ver_.minor + i);
}
template<typename Parser, typename Comparator, typename Modifier>
Basic_version<Parser, Comparator, Modifier> Basic_version<Parser, Comparator, Modifier>::inc_patch(const int i) const {
return reset_patch(ver_.patch + i);
}
template<typename Parser, typename Comparator, typename Modifier>
bool operator<(const Basic_version<Parser, Comparator, Modifier>& l,
const Basic_version<Parser, Comparator, Modifier>& r) {
return l.comparator_.compare(l.ver_, r.ver_) == -1;
}
template<typename Parser, typename Comparator>
bool operator==(const Basic_version<Parser, Comparator>& l,
const Basic_version<Parser, Comparator>& r) {
template<typename Parser, typename Comparator, typename Modifier>
bool operator==(const Basic_version<Parser, Comparator, Modifier>& l,
const Basic_version<Parser, Comparator, Modifier>& r) {
return l.comparator_.compare(l.ver_, r.ver_) == 0;
}
template<typename Parser, typename Comparator>
template<typename Parser, typename Comparator, typename Modifier>
std::ostream& operator<<(std::ostream& os,
const Basic_version<Parser, Comparator>& v) {
const Basic_version<Parser, Comparator, Modifier>& v) {
os << v.ver_.major << "." << v.ver_.minor << "." << v.ver_.patch;
std::string prl = v.prerelease();
if (!prl.empty()) {
@@ -117,27 +191,27 @@ namespace version {
return os;
}
template<typename Parser, typename Comparator>
inline bool operator!=(const Basic_version<Parser, Comparator>& l,
const Basic_version<Parser, Comparator>& r) {
template<typename Parser, typename Comparator, typename Modifier>
inline bool operator!=(const Basic_version<Parser, Comparator, Modifier>& l,
const Basic_version<Parser, Comparator, Modifier>& r) {
return !(l == r);
}
template<typename Parser, typename Comparator>
inline bool operator>(const Basic_version<Parser, Comparator>& l,
const Basic_version<Parser, Comparator>& r) {
template<typename Parser, typename Comparator, typename Modifier>
inline bool operator>(const Basic_version<Parser, Comparator, Modifier>& l,
const Basic_version<Parser, Comparator, Modifier>& r) {
return r < l;
}
template<typename Parser, typename Comparator>
inline bool operator>=(const Basic_version<Parser, Comparator>& l,
const Basic_version<Parser, Comparator>& r) {
template<typename Parser, typename Comparator, typename Modifier>
inline bool operator>=(const Basic_version<Parser, Comparator, Modifier>& l,
const Basic_version<Parser, Comparator, Modifier>& r) {
return !(l < r);
}
template<typename Parser, typename Comparator>
inline bool operator<=(const Basic_version<Parser, Comparator>& l,
const Basic_version<Parser, Comparator>& r) {
template<typename Parser, typename Comparator, typename Modifier>
inline bool operator<=(const Basic_version<Parser, Comparator, Modifier>& l,
const Basic_version<Parser, Comparator, Modifier>& r) {
return !(l > r);
}
}