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
+1
View File
@@ -38,3 +38,4 @@ enable_testing()
add_test(NAME semver200_parser_tests COMMAND semver200_parser_tests)
add_test(NAME semver200_comparator_tests COMMAND semver200_comparator_tests)
add_test(NAME semver200_version_tests COMMAND semver200_version_tests)
add_test(NAME semver200_modifier_tests COMMAND semver200_modifier_tests)
+40 -2
View File
@@ -1,5 +1,5 @@
# About
This project is MIT-licensed, C++14 implementation of [semantic versioning](http://semver.org) parser and comparator. Semantic versioning 2.0.0 specification is supported out-of-the-box and the code should be flexible-enough to support future revisions or other similar versioning schemes.
This project is MIT-licensed, C++14 implementation of [semantic versioning](http://semver.org) parser and comparator with support for modifying parsed version strings. Semantic versioning 2.0.0 specification is supported out-of-the-box and the code should be flexible-enough to support future revisions or other similar versioning schemes.
# Usage
Parsing and comparing two version strings:
@@ -42,8 +42,46 @@ Pre-release: alpha.1
Build: build.no.123
```
Parsed version object supports a few modification methods. All modification methods are non-destructive i.e. they return new objects with modified properties and original objects are never changed. You can:
- set major, minor, patch, pre-release or build version to desired value while keeping other fields unchanged;
- reset major, minor, patch, pre-release or build version to desired value by resetting lower-priority fields to zero/empty values (Priority is major > minor > patch > pre-release > build);
- increase/decrease major, minor or patch version by desired increment (can be negative); this is reset-type operation which will zero/empty lower priority fields.
A few examples of version modifications:
```c++
#include "semver200.h"
void main(int, char**) {
version::Semver200_version v("1.2.3-alpha.1+build.no.123");
std::cout << "Next major version: " << v.inc_major() << std::endl;
std::cout << "Next but one major: " << v.inc_major(2) << std::endl;
std::cout << "Next minor version: " << v.inc_minor() << std::endl;
std::cout << "Previous minor version: " << v.inc_minor(-1) << std::endl;
std::cout << "Next patch version: " << v.inc_patch() << std::endl;
std::cout << "Change pre-release: " << v.set_prerelease("beta.3") << std::endl;
std::cout << "Change build: " << v.set_build("170105") << std::endl;
std::cout << "Set major to 3, minor to 1: " << v.set_major(3).set_minor(1) << std::endl;
std::cout << "Reset major to 3, minor to 1: " << v.reset_major(3).reset_minor(1) << std::endl;
}
```
should generate following output:
```
Next major version: 2.0.0
Next but one major: 3.0.0
Next minor version: 1.3.0
Previous minor version: 1.1.0
Next patch version: 1.2.4
Change pre-release: 1.2.3-beta.3+build.no.123
Change build: 1.2.3-alpha.1+170105
Set major to 3, minor to 1: 3.1.3-alpha.1+build.no.123
Reset major to 3, minor to 1: 3.1.0
```
# Build
The code is written in C++14, so, fairly recent compiler is required to build it. Following compiler were tested:
The code is written in C++14, so, fairly recent compiler is required to build it. Following compilers were tested:
- Microsoft Visual Studio 2015
- GCC 5.1.1
- Clang 3.7.0
+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);
}
}
+1 -1
View File
@@ -3,5 +3,5 @@ include_directories(
)
add_library(semver
Semver200_comparator.cpp Semver200_parser.cpp
Semver200_comparator.cpp Semver200_parser.cpp Semver200_modifier.cpp
)
+75
View File
@@ -0,0 +1,75 @@
/*
The MIT License (MIT)
Copyright (c) 2015 Marko Zivanovic
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <climits>
#include "semver200.h"
namespace version {
Version_data Semver200_modifier::set_major(const Version_data& s, const int m) const {
if (m < 0) throw Modification_error("major version cannot be less than 0");
return Version_data{ m, s.minor, s.patch, s.prerelease_ids, s.build_ids };
}
Version_data Semver200_modifier::set_minor(const Version_data& s, const int m) const {
if (m < 0) throw Modification_error("minor version cannot be less than 0");
return Version_data{ s.major, m, s.patch, s.prerelease_ids, s.build_ids };
}
Version_data Semver200_modifier::set_patch(const Version_data& s, const int p) const {
if (p < 0) throw Modification_error("patch version cannot be less than 0");
return Version_data{ s.major, s.minor, p, s.prerelease_ids, s.build_ids };
}
Version_data Semver200_modifier::set_prerelease(const Version_data& s, const Prerelease_identifiers& pr) const {
return Version_data{ s.major, s.minor, s.patch, pr, s.build_ids };
}
Version_data Semver200_modifier::set_build(const Version_data& s, const Build_identifiers& b) const {
return Version_data{ s.major, s.minor, s.patch, s.prerelease_ids, b };
}
Version_data Semver200_modifier::reset_major(const Version_data& s, const int m) const {
if (m < 0) throw Modification_error("major version cannot be less than 0");
return Version_data{ m, 0, 0, Prerelease_identifiers{}, Build_identifiers{} };
}
Version_data Semver200_modifier::reset_minor(const Version_data& s, const int m) const {
if (m < 0) throw Modification_error("minor version cannot be less than 0");
return Version_data{ s.major, m, 0, Prerelease_identifiers{}, Build_identifiers{} };
}
Version_data Semver200_modifier::reset_patch(const Version_data& s, const int p) const {
if (p < 0) throw Modification_error("patch version cannot be less than 0");
return Version_data{ s.major, s.minor, p, Prerelease_identifiers{}, Build_identifiers{} };
}
Version_data Semver200_modifier::reset_prerelease(const Version_data& s, const Prerelease_identifiers& pr) const {
return Version_data{ s.major, s.minor, s.patch, pr, Build_identifiers{} };
}
Version_data Semver200_modifier::reset_build(const Version_data& s, const Build_identifiers& b) const {
return Version_data{ s.major, s.minor, s.patch, s.prerelease_ids, b };
}
}
+6
View File
@@ -26,3 +26,9 @@ target_link_libraries(semver200_version_tests
${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
semver
)
add_executable(semver200_modifier_tests semver200_modifier_tests.cpp clang_fixes.cpp)
target_link_libraries(semver200_modifier_tests
${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
semver
)
+314
View File
@@ -0,0 +1,314 @@
/*
The MIT License (MIT)
Copyright (c) 2017 Marko Zivanovic
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#define BOOST_TEST_MODULE semver200_modifier_tests
#include <climits>
#include <boost/test/unit_test.hpp>
#include "semver200.h"
using namespace version;
Semver200_comparator c;
Semver200_parser p;
Semver200_modifier m;
#define CHECK_SRC { \
BOOST_CHECK(v.major() == 1); \
BOOST_CHECK(v.minor() == 2); \
BOOST_CHECK(v.patch() == 3); \
BOOST_CHECK(v.prerelease() == "pre.rel.0"); \
BOOST_CHECK(v.build() == "build.no.321"); \
}
BOOST_AUTO_TEST_CASE(set_major) {
Semver200_version v("1.2.3-pre.rel.0+build.no.321");
auto v2 = v.set_major(2);
// Check if setter works as expected
BOOST_CHECK(v2.major() == 2);
BOOST_CHECK(v2.minor() == 2);
BOOST_CHECK(v2.patch() == 3);
BOOST_CHECK(v2.prerelease() == "pre.rel.0");
BOOST_CHECK(v2.build() == "build.no.321");
// Check invalid values
BOOST_CHECK_THROW(v.set_major(-1), version::Modification_error);
// Check source version is unaffected
CHECK_SRC
}
BOOST_AUTO_TEST_CASE(set_minor) {
Semver200_version v("1.2.3-pre.rel.0+build.no.321");
auto v2 = v.set_minor(3);
// Check if setter works as expected
BOOST_CHECK(v2.major() == 1);
BOOST_CHECK(v2.minor() == 3);
BOOST_CHECK(v2.patch() == 3);
BOOST_CHECK(v2.prerelease() == "pre.rel.0");
BOOST_CHECK(v2.build() == "build.no.321");
// Check invalid values
BOOST_CHECK_THROW(v.set_minor(-1), version::Modification_error);
// Check source version is unaffected
CHECK_SRC
}
BOOST_AUTO_TEST_CASE(set_patch) {
Semver200_version v("1.2.3-pre.rel.0+build.no.321");
auto v2 = v.set_patch(4);
// Check if setter works as expected
BOOST_CHECK(v2.major() == 1);
BOOST_CHECK(v2.minor() == 2);
BOOST_CHECK(v2.patch() == 4);
BOOST_CHECK(v2.prerelease() == "pre.rel.0");
BOOST_CHECK(v2.build() == "build.no.321");
// Check invalid values
BOOST_CHECK_THROW(v.set_patch(-1), version::Modification_error);
// Check source version is unaffected
CHECK_SRC
}
BOOST_AUTO_TEST_CASE(set_prerelease) {
Semver200_version v("1.2.3-pre.rel.0+build.no.321");
auto v2 = v.set_prerelease("alpha.1");
// Check if setter works as expected
BOOST_CHECK(v2.major() == 1);
BOOST_CHECK(v2.minor() == 2);
BOOST_CHECK(v2.patch() == 3);
BOOST_CHECK(v2.prerelease() == "alpha.1");
BOOST_CHECK(v2.build() == "build.no.321");
// Check source version is unaffected
CHECK_SRC
}
BOOST_AUTO_TEST_CASE(set_build) {
Semver200_version v("1.2.3-pre.rel.0+build.no.321");
auto v2 = v.set_build("b123");
// Check if setter works as expected
BOOST_CHECK(v2.major() == 1);
BOOST_CHECK(v2.minor() == 2);
BOOST_CHECK(v2.patch() == 3);
BOOST_CHECK(v2.prerelease() == "pre.rel.0");
BOOST_CHECK(v2.build() == "b123");
// Check source version is unaffected
CHECK_SRC
}
BOOST_AUTO_TEST_CASE(reset_major) {
Semver200_version v("1.2.3-pre.rel.0+build.no.321");
auto v2 = v.reset_major(2);
// Check if setter works as expected
BOOST_CHECK(v2.major() == 2);
BOOST_CHECK(v2.minor() == 0);
BOOST_CHECK(v2.patch() == 0);
BOOST_CHECK(v2.prerelease() == "");
BOOST_CHECK(v2.build() == "");
// Check invalid values
BOOST_CHECK_THROW(v.reset_major(-1), version::Modification_error);
// Check source version is unaffected
CHECK_SRC
}
BOOST_AUTO_TEST_CASE(reset_minor) {
Semver200_version v("1.2.3-pre.rel.0+build.no.321");
auto v2 = v.reset_minor(3);
// Check if setter works as expected
BOOST_CHECK(v2.major() == 1);
BOOST_CHECK(v2.minor() == 3);
BOOST_CHECK(v2.patch() == 0);
BOOST_CHECK(v2.prerelease() == "");
BOOST_CHECK(v2.build() == "");
// Check invalid values
BOOST_CHECK_THROW(v.reset_minor(-1), version::Modification_error);
// Check source version is unaffected
CHECK_SRC
}
BOOST_AUTO_TEST_CASE(reset_patch) {
Semver200_version v("1.2.3-pre.rel.0+build.no.321");
auto v2 = v.reset_patch(4);
// Check if setter works as expected
BOOST_CHECK(v2.major() == 1);
BOOST_CHECK(v2.minor() == 2);
BOOST_CHECK(v2.patch() == 4);
BOOST_CHECK(v2.prerelease() == "");
BOOST_CHECK(v2.build() == "");
// Check invalid values
BOOST_CHECK_THROW(v.reset_patch(-1), version::Modification_error);
// Check source version is unaffected
CHECK_SRC
}
BOOST_AUTO_TEST_CASE(reset_prerelease) {
Semver200_version v("1.2.3-pre.rel.0+build.no.321");
auto v2 = v.reset_prerelease("alpha.1");
// Check if setter works as expected
BOOST_CHECK(v2.major() == 1);
BOOST_CHECK(v2.minor() == 2);
BOOST_CHECK(v2.patch() == 3);
BOOST_CHECK(v2.prerelease() == "alpha.1");
BOOST_CHECK(v2.build() == "");
// Check source version is unaffected
CHECK_SRC
}
BOOST_AUTO_TEST_CASE(reset_build) {
Semver200_version v("1.2.3-pre.rel.0+build.no.321");
auto v2 = v.reset_build("b123");
// Check if setter works as expected
BOOST_CHECK(v2.major() == 1);
BOOST_CHECK(v2.minor() == 2);
BOOST_CHECK(v2.patch() == 3);
BOOST_CHECK(v2.prerelease() == "pre.rel.0");
BOOST_CHECK(v2.build() == "b123");
// Check source version is unaffected
CHECK_SRC
}
BOOST_AUTO_TEST_CASE(inc_major) {
Semver200_version v("1.2.3-pre.rel.0+build.no.321");
// Check default increment
auto v2 = v.inc_major();
BOOST_CHECK(v2.major() == 2);
BOOST_CHECK(v2.minor() == 0);
BOOST_CHECK(v2.patch() == 0);
BOOST_CHECK(v2.prerelease() == "");
BOOST_CHECK(v2.build() == "");
// Check non-default increment
auto v2 = v.inc_major(3);
BOOST_CHECK(v2.major() == 4);
BOOST_CHECK(v2.minor() == 0);
BOOST_CHECK(v2.patch() == 0);
BOOST_CHECK(v2.prerelease() == "");
BOOST_CHECK(v2.build() == "");
// Check negative increment
v2 = v.inc_major(-1);
BOOST_CHECK(v2.major() == 0);
BOOST_CHECK(v2.minor() == 0);
BOOST_CHECK(v2.patch() == 0);
BOOST_CHECK(v2.prerelease() == "");
BOOST_CHECK(v2.build() == "");
// Check too negative increment
BOOST_CHECK_THROW(v.inc_major(-2), version::Modification_error);
// Check source version is unaffected
CHECK_SRC
}
BOOST_AUTO_TEST_CASE(inc_minor) {
Semver200_version v("1.2.3-pre.rel.0+build.no.321");
// Check default increment
auto v2 = v.inc_minor();
BOOST_CHECK(v2.major() == 1);
BOOST_CHECK(v2.minor() == 3);
BOOST_CHECK(v2.patch() == 0);
BOOST_CHECK(v2.prerelease() == "");
BOOST_CHECK(v2.build() == "");
// Check non-default increment
auto v2 = v.inc_minor(3);
BOOST_CHECK(v2.major() == 1);
BOOST_CHECK(v2.minor() == 5);
BOOST_CHECK(v2.patch() == 0);
BOOST_CHECK(v2.prerelease() == "");
BOOST_CHECK(v2.build() == "");
// Check negative increment
v2 = v.inc_minor(-1);
BOOST_CHECK(v2.major() == 1);
BOOST_CHECK(v2.minor() == 1);
BOOST_CHECK(v2.patch() == 0);
BOOST_CHECK(v2.prerelease() == "");
BOOST_CHECK(v2.build() == "");
// Check too negative increment
BOOST_CHECK_THROW(v.inc_minor(-3), version::Modification_error);
// Check source version is unaffected
CHECK_SRC
}
BOOST_AUTO_TEST_CASE(inc_patch) {
Semver200_version v("1.2.3-pre.rel.0+build.no.321");
// Check default increment
auto v2 = v.inc_patch();
BOOST_CHECK(v2.major() == 1);
BOOST_CHECK(v2.minor() == 2);
BOOST_CHECK(v2.patch() == 4);
BOOST_CHECK(v2.prerelease() == "");
BOOST_CHECK(v2.build() == "");
// Check default increment
auto v2 = v.inc_patch(3);
BOOST_CHECK(v2.major() == 1);
BOOST_CHECK(v2.minor() == 2);
BOOST_CHECK(v2.patch() == 6);
BOOST_CHECK(v2.prerelease() == "");
BOOST_CHECK(v2.build() == "");
// Check negative increment
v2 = v.inc_patch(-1);
BOOST_CHECK(v2.major() == 1);
BOOST_CHECK(v2.minor() == 2);
BOOST_CHECK(v2.patch() == 2);
BOOST_CHECK(v2.prerelease() == "");
BOOST_CHECK(v2.build() == "");
// Check too negative increment
BOOST_CHECK_THROW(v.inc_patch(-4), version::Modification_error);
// Check source version is unaffected
CHECK_SRC
}