Comments improvements; minor header files cleanup.

This commit is contained in:
Marko Zivanovic
2015-10-13 21:05:24 +02:00
parent 522e8b484b
commit 398ca786c4
5 changed files with 249 additions and 235 deletions
+50 -43
View File
@@ -30,7 +30,7 @@ SOFTWARE.
namespace version { namespace version {
/// Parse_error is thrown on all parsing and validation errors. /// Any error in parsing or validation of version string will result in Parse_error exception being thrown.
class Parse_error : public std::runtime_error { class Parse_error : public std::runtime_error {
using std::runtime_error::runtime_error; using std::runtime_error::runtime_error;
}; };
@@ -40,7 +40,7 @@ namespace version {
Type of identifier affects comparison: alphanumeric identifiers are compared as ASCII strings, while Type of identifier affects comparison: alphanumeric identifiers are compared as ASCII strings, while
numeric identifiers are compared as numbers. numeric identifiers are compared as numbers.
*/ */
enum class Identifier_type { enum class Id_type {
alnum, ///< Identifier is alphanumerical alnum, ///< Identifier is alphanumerical
num ///< Identifier is numeric num ///< Identifier is numeric
}; };
@@ -51,22 +51,22 @@ namespace version {
These identifiers can be either numerical or alphanumerical. These identifiers can be either numerical or alphanumerical.
This structure describes one such identifier. This structure describes one such identifier.
*/ */
using Prerelease_identifier = std::pair<std::string, Identifier_type>; using Prerelease_identifier = std::pair<std::string, Id_type>;
/// Container for all prerelease identifiers for a given version string. /// Container for all prerelease identifiers for a given version string.
using Prerelease_identifiers = std::vector<Prerelease_identifier>; using Prerelease_identifiers = std::vector<Prerelease_identifier>;
/// Build identifier is just a string and has no meaning for the purpose of version precedence. /// Build identifier is arbitrary string with no special meaning with regards to version precedence.
using Build_identifier = std::string; using Build_identifier = std::string;
/// Container for all build identifiers for a given version string. /// Container for all build identifiers of a given version string.
using Build_identifiers = std::vector<Build_identifier>; using Build_identifiers = std::vector<Build_identifier>;
/// Description of version broken into parts, as per semantic versioning specification. /// Description of version broken into parts, as per semantic versioning specification.
struct Version_data { struct Version_data {
int major; ///< Major version, change only on incompatible API modifications int major; ///< Major version, change only on incompatible API modifications.
int minor; ///< Minor version, change on compatible API modifications int minor; ///< Minor version, change on backwards-compatible API modifications.
int patch; ///< Patch version, change only on bugfixes int patch; ///< Patch version, change only on bugfixes.
/// Optional series of prerelease identifiers. /// Optional series of prerelease identifiers.
Prerelease_identifiers prerelease_ids; Prerelease_identifiers prerelease_ids;
@@ -75,40 +75,47 @@ namespace version {
Build_identifiers build_ids; Build_identifiers build_ids;
}; };
/// Forward declaration required for operators' template declarations. // Forward declaration required for operators' template declarations.
template<typename P, typename C> template<typename Parser, typename Comparator>
class Basic_version; class Basic_version;
/// Compare if left version object is less than the right. /// Test if left-hand version operand is of lower precedence than the right-hand version.
template<typename P, typename C> template<typename Parser, typename Comparator>
bool operator<(const Basic_version<P, C>&, const Basic_version<P, C>&); bool operator<(const Basic_version<Parser, Comparator>&,
const Basic_version<Parser, Comparator>&);
/// Compare if two version objects are equal. /// Test if left-hand version operand if of equal precedence as the right-hand version.
template<typename P, typename C> template<typename Parser, typename Comparator>
bool operator==(const Basic_version<P, C>& l, const Basic_version<P, C>& r); bool operator==(const Basic_version<Parser, Comparator>&,
const Basic_version<Parser, Comparator>&);
/// Output version object to stream using standard semver format (X.Y.Z-PR+B). /// Output version object to stream using standard semver format (X.Y.Z-PR+B).
template<typename P, typename C> template<typename Parser, typename Comparator>
std::ostream& operator<<(std::ostream& os, const Basic_version<P, C>& v); std::ostream& operator<<(std::ostream&,
const Basic_version<Parser, Comparator>&);
/// Compare if two version objects are different. /// Test if left-hand version and right-hand version are of different precedence.
template<typename P, typename C> template<typename Parser, typename Comparator>
bool operator!=(const version::Basic_version<P, C>& l, const version::Basic_version<P, C>& r); bool operator!=(const Basic_version<Parser, Comparator>&,
const Basic_version<Parser, Comparator>&);
/// Compare if left version object is greater than the right. /// Test if left-hand version operand is of higher precedence than the right-hand version.
template<typename P, typename C> template<typename Parser, typename Comparator>
bool operator>(const version::Basic_version<P, C>& l, const version::Basic_version<P, C>& r); bool operator>(const Basic_version<Parser, Comparator>&,
const Basic_version<Parser, Comparator>&);
/// Compare if left version object is greater than or equal the right. /// Test if left-hand version operand is of higher or equal precedence as the right-hand version.
template<typename P, typename C> template<typename Parser, typename Comparator>
bool operator>=(const version::Basic_version<P, C>& l, const version::Basic_version<P, C>& r); bool operator>=(const Basic_version<Parser, Comparator>&,
const Basic_version<Parser, Comparator>&);
/// Compare if left version object is less than or equal the right. /// Test if left-hand version operand is of lower or equal precedence as the right-hand version.
template<typename P, typename C> template<typename Parser, typename Comparator>
bool operator<=(const version::Basic_version<P, C>& l, const version::Basic_version<P, C>& r); bool operator<=(const Basic_version<Parser, Comparator>&,
const Basic_version<Parser, Comparator>&);
/// Generic version description and comparison class. /// Base class for various version parsing and precedence ordering schemes.
/** /**
Basic_version class describes general version object without prescribing parsing, Basic_version class describes general version object without prescribing parsing,
validation and comparison rules. These rules are implemented by supplied Parser and validation and comparison rules. These rules are implemented by supplied Parser and
@@ -117,11 +124,11 @@ namespace version {
template<typename Parser, typename Comparator> template<typename Parser, typename Comparator>
class Basic_version { class Basic_version {
public: public:
/// Construct Basic_version object using P to parse default ("0.0.0") version string and C for comparison. /// Construct Basic_version object using Parser object to parse default ("0.0.0") version string and Comparator for comparison.
Basic_version(Parser p, Comparator c); Basic_version(Parser, Comparator);
/// Construct Basic_version object using P to parse version string and C for comparison. /// Construct Basic_version object using Parser to parse supplied version string and Comparator for comparison.
Basic_version(const std::string& v, Parser p, Comparator c); Basic_version(const std::string&, Parser, Comparator);
/// Construct Basic_version by copying data from another one. /// Construct Basic_version by copying data from another one.
Basic_version(const Basic_version&); Basic_version(const Basic_version&);
@@ -129,15 +136,15 @@ namespace version {
/// Copy version data from another Basic_version to this one. /// Copy version data from another Basic_version to this one.
Basic_version& operator=(const Basic_version&); Basic_version& operator=(const Basic_version&);
const int major() const; const int major() const; ///< Get major version.
const int minor() const; const int minor() const; ///< Get minor version.
const int patch() const; const int patch() const; ///< Get patch version.
const std::string prerelease() const; const std::string prerelease() const; ///< Get prerelease version string.
const std::string build() const; const std::string build() const; ///< Get build version string.
friend bool operator< <>(const Basic_version& l, const Basic_version& r); friend bool operator< <>(const Basic_version&, const Basic_version&);
friend bool operator== <>(const Basic_version& l, const Basic_version& r); friend bool operator== <>(const Basic_version&, const Basic_version&);
friend std::ostream& operator<< <>(std::ostream& os, const Basic_version& v); friend std::ostream& operator<< <>(std::ostream&s, const Basic_version&);
private: private:
Parser parser_; Parser parser_;
+44 -40
View File
@@ -33,73 +33,77 @@ namespace version {
/// Utility function to splice all vector elements to output stream, using designated separator /// Utility function to splice all vector elements to output stream, using designated separator
/// between elements and function object for getting values from vector elements. /// between elements and function object for getting values from vector elements.
template<typename T, typename F> template<typename T, typename F>
std::ostream& splice(std::ostream& os, const std::vector<T>& v, const std::string& sep, F read) { std::ostream& splice(std::ostream& os, const std::vector<T>& vec, const std::string& sep, F read) {
if (!v.empty()) { if (!vec.empty()) {
for (auto it = v.cbegin(); it < v.cend() - 1; ++it) { for (auto it = vec.cbegin(); it < vec.cend() - 1; ++it) {
os << read(*it) << sep; os << read(*it) << sep;
} }
os << read(*v.crbegin()); os << read(*vec.crbegin());
} }
return os; return os;
} }
} }
template<typename P, typename C> template<typename Parser, typename Comparator>
Basic_version<P, C>::Basic_version(P p, C c) Basic_version<Parser, Comparator>::Basic_version(Parser p, Comparator c)
: parser_(p), comparator_(c), ver_(parser_.parse("0.0.0")) {}; : parser_(p), comparator_(c), ver_(parser_.parse("0.0.0")) {};
template<typename P, typename C> template<typename Parser, typename Comparator>
Basic_version<P, C>::Basic_version(const std::string& v, P p, C c) Basic_version<Parser, Comparator>::Basic_version(const std::string& v, Parser p, Comparator c)
: parser_(p), comparator_(c), ver_(parser_.parse(v)) {}; : parser_(p), comparator_(c), ver_(parser_.parse(v)) {};
template<typename P, typename C> template<typename Parser, typename Comparator>
Basic_version<P, C>::Basic_version(const Basic_version<P, C>&) = default; Basic_version<Parser, Comparator>::Basic_version(const Basic_version<Parser, Comparator>&) = default;
template<typename P, typename C> template<typename Parser, typename Comparator>
Basic_version<P, C>& Basic_version<P, C>::operator=(const Basic_version<P, C>&) = default; Basic_version<Parser, Comparator>& Basic_version<Parser, Comparator>::operator=(
const Basic_version<Parser, Comparator>&) = default;
template<typename P, typename C> template<typename Parser, typename Comparator>
const int Basic_version<P, C>::major() const { const int Basic_version<Parser, Comparator>::major() const {
return ver_.major; return ver_.major;
} }
template<typename P, typename C> template<typename Parser, typename Comparator>
const int Basic_version<P, C>::minor() const { const int Basic_version<Parser, Comparator>::minor() const {
return ver_.minor; return ver_.minor;
} }
template<typename P, typename C> template<typename Parser, typename Comparator>
const int Basic_version<P, C>::patch() const { const int Basic_version<Parser, Comparator>::patch() const {
return ver_.patch; return ver_.patch;
} }
template<typename P, typename C> template<typename Parser, typename Comparator>
const std::string Basic_version<P, C>::prerelease() const { const std::string Basic_version<Parser, Comparator>::prerelease() const {
std::stringstream ss; std::stringstream ss;
splice(ss, ver_.prerelease_ids, ".", [](const auto& id) { return id.first;}); splice(ss, ver_.prerelease_ids, ".", [](const auto& id) { return id.first;});
return ss.str(); return ss.str();
} }
template<typename P, typename C> template<typename Parser, typename Comparator>
const std::string Basic_version<P, C>::build() const { const std::string Basic_version<Parser, Comparator>::build() const {
std::stringstream ss; std::stringstream ss;
splice(ss, ver_.build_ids, ".", [](const auto& id) { return id;}); splice(ss, ver_.build_ids, ".", [](const auto& id) { return id;});
return ss.str(); return ss.str();
} }
template<typename P, typename C> template<typename Parser, typename Comparator>
bool operator<(const Basic_version<P, C>& l, const Basic_version<P, C>& r) { bool operator<(const Basic_version<Parser, Comparator>& l,
const Basic_version<Parser, Comparator>& r) {
return l.comparator_.compare(l.ver_, r.ver_) == -1; return l.comparator_.compare(l.ver_, r.ver_) == -1;
} }
template<typename P, typename C> template<typename Parser, typename Comparator>
bool operator==(const version::Basic_version<P, C>& l, const version::Basic_version<P, C>& r) { bool operator==(const Basic_version<Parser, Comparator>& l,
const Basic_version<Parser, Comparator>& r) {
return l.comparator_.compare(l.ver_, r.ver_) == 0; return l.comparator_.compare(l.ver_, r.ver_) == 0;
} }
template<typename P, typename C> template<typename Parser, typename Comparator>
std::ostream& operator<<(std::ostream& os, const version::Basic_version<P, C>& v) { std::ostream& operator<<(std::ostream& os,
const Basic_version<Parser, Comparator>& v) {
os << v.ver_.major << "." << v.ver_.minor << "." << v.ver_.patch; os << v.ver_.major << "." << v.ver_.minor << "." << v.ver_.patch;
std::string prl = v.prerelease(); std::string prl = v.prerelease();
if (!prl.empty()) { if (!prl.empty()) {
@@ -112,27 +116,27 @@ namespace version {
return os; return os;
} }
/// Compare if two version objects are different. template<typename Parser, typename Comparator>
template<typename P, typename C> inline bool operator!=(const Basic_version<Parser, Comparator>& l,
inline bool operator!=(const version::Basic_version<P, C>& l, const version::Basic_version<P, C>& r) { const Basic_version<Parser, Comparator>& r) {
return !(l == r); return !(l == r);
} }
/// Compare if left version object is greater than the right. template<typename Parser, typename Comparator>
template<typename P, typename C> inline bool operator>(const Basic_version<Parser, Comparator>& l,
inline bool operator>(const version::Basic_version<P, C>& l, const version::Basic_version<P, C>& r) { const Basic_version<Parser, Comparator>& r) {
return r < l; return r < l;
} }
/// Compare if left version object is greater than or equal the right. template<typename Parser, typename Comparator>
template<typename P, typename C> inline bool operator>=(const Basic_version<Parser, Comparator>& l,
inline bool operator>=(const version::Basic_version<P, C>& l, const version::Basic_version<P, C>& r) { const Basic_version<Parser, Comparator>& r) {
return !(l < r); return !(l < r);
} }
/// Compare if left version object is less than or equal the right. template<typename Parser, typename Comparator>
template<typename P, typename C> inline bool operator<=(const Basic_version<Parser, Comparator>& l,
inline bool operator<=(const version::Basic_version<P, C>& l, const version::Basic_version<P, C>& r) { const Basic_version<Parser, Comparator>& r) {
return !(l > r); return !(l > r);
} }
} }
+11 -13
View File
@@ -25,13 +25,13 @@ SOFTWARE.
#include <algorithm> #include <algorithm>
#include <functional> #include <functional>
#include <map> #include <map>
#include "common/semver200.h" #include "semver200.h"
using namespace std; using namespace std;
namespace { namespace version {
using namespace version; namespace {
// Compare normal version identifiers. // Compare normal version identifiers.
int compare_normal(const Version_data& l, const Version_data& r) { int compare_normal(const Version_data& l, const Version_data& r) {
@@ -62,13 +62,13 @@ namespace {
return li > ri ? 1 : -1; return li > ri ? 1 : -1;
} }
using Prerel_types = pair<Identifier_type, Identifier_type>; using Prerel_type_pair = pair<Id_type, Id_type>;
using Prerel_id_comparator = function<int(const string&, const string&)>; using Prerel_id_comparator = function<int(const string&, const string&)>;
const map<Prerel_types, Prerel_id_comparator> comparators = { const map<Prerel_type_pair, Prerel_id_comparator> comparators = {
{ { Identifier_type::alnum, Identifier_type::alnum }, cmp_alnum_prerel_ids }, { { Id_type::alnum, Id_type::alnum }, cmp_alnum_prerel_ids },
{ { Identifier_type::alnum, Identifier_type::num }, [](const string&, const string&) {return 1;} }, { { Id_type::alnum, Id_type::num }, [](const string&, const string&) {return 1;} },
{ { Identifier_type::num, Identifier_type::alnum }, [](const string&, const string&) {return -1;} }, { { Id_type::num, Id_type::alnum }, [](const string&, const string&) {return -1;} },
{ { Identifier_type::num, Identifier_type::num }, cmp_num_prerel_ids } { { Id_type::num, Id_type::num }, cmp_num_prerel_ids }
}; };
// Compare prerelease identifiers based on their types. // Compare prerelease identifiers based on their types.
@@ -82,16 +82,14 @@ namespace {
if (r.empty() && !l.empty()) return -1; if (r.empty() && !l.empty()) return -1;
return 0; return 0;
} }
} }
namespace version {
int Semver200_comparator::compare(const Version_data& l, const Version_data& r) const { int Semver200_comparator::compare(const Version_data& l, const Version_data& r) const {
// Compare normal version components. // Compare normal version components.
int cmp = compare_normal(l, r); int cmp = compare_normal(l, r);
if (cmp != 0) return cmp; if (cmp != 0) return cmp;
// Compare if one version is release and the other prerelease; release is always higher than prerelease. // Compare if one version is release and the other prerelease - release is always higher.
cmp = cmp_rel_prerel(l.prerelease_ids, r.prerelease_ids); cmp = cmp_rel_prerel(l.prerelease_ids, r.prerelease_ids);
if (cmp != 0) return cmp; if (cmp != 0) return cmp;
+19 -14
View File
@@ -24,11 +24,18 @@ SOFTWARE.
#include <functional> #include <functional>
#include <map> #include <map>
#include "common/semver200.h" #include "semver200.h"
#ifdef _MSC_VER
// disable symbol name too long warning
#pragma warning(disable:4503)
#endif
using namespace std; using namespace std;
namespace { namespace version {
namespace {
enum class Parser_state { enum class Parser_state {
major, minor, patch, prerelease, build major, minor, patch, prerelease, build
}; };
@@ -75,8 +82,8 @@ namespace {
/// Validate normal (major, minor, patch) version components. /// Validate normal (major, minor, patch) version components.
inline void normal_version_validator(const string& tgt, const char c) { inline void normal_version_validator(const string& tgt, const char c) {
if (c < '0' || c > '9') throw version::Parse_error("invalid character encountered: " + string(1, c)); if (c < '0' || c > '9') throw Parse_error("invalid character encountered: " + string(1, c));
if (tgt.compare(0, 1, "0") == 0) throw version::Parse_error("leading 0 not allowed"); if (tgt.compare(0, 1, "0") == 0) throw Parse_error("leading 0 not allowed");
} }
/// Validate that prerelease and build version identifiers are comprised of allowed chars only. /// Validate that prerelease and build version identifiers are comprised of allowed chars only.
@@ -86,7 +93,7 @@ namespace {
res |= (c >= r.first && c <= r.second); res |= (c >= r.first && c <= r.second);
} }
if (!res) if (!res)
throw version::Parse_error("invalid character encountered: " + string(1, c)); throw Parse_error("invalid character encountered: " + string(1, c));
} }
inline bool is_identifier_numeric(const string& id) { inline bool is_identifier_numeric(const string& id) {
@@ -98,12 +105,12 @@ namespace {
} }
/// Validate every individual prerelease identifier, determine it's type and add it to collection. /// Validate every individual prerelease identifier, determine it's type and add it to collection.
void prerelease_hook_impl(string& id, version::Prerelease_identifiers& prerelease) { void prerelease_hook_impl(string& id, Prerelease_identifiers& prerelease) {
using namespace version; using namespace version;
if (id.empty()) throw Parse_error("version identifier cannot be empty"); if (id.empty()) throw Parse_error("version identifier cannot be empty");
Identifier_type t = Identifier_type::alnum; Id_type t = Id_type::alnum;
if (is_identifier_numeric(id)) { if (is_identifier_numeric(id)) {
t = Identifier_type::num; t = Id_type::num;
if (check_for_leading_0(id)) { if (check_for_leading_0(id)) {
throw Parse_error("numeric identifiers cannot have leading 0"); throw Parse_error("numeric identifiers cannot have leading 0");
} }
@@ -113,18 +120,16 @@ namespace {
} }
/// Validate every individual build identifier and add it to collection. /// Validate every individual build identifier and add it to collection.
void build_hook_impl(string& id, Parser_state& pstate, version::Build_identifiers& build, void build_hook_impl(string& id, Parser_state& pstate, Build_identifiers& build,
std::string& prerelease_id, version::Prerelease_identifiers& prerelease) { std::string& prerelease_id, Prerelease_identifiers& prerelease) {
// process last token left from parsing prerelease data // process last token left from parsing prerelease data
if (pstate == Parser_state::prerelease) prerelease_hook_impl(prerelease_id, prerelease); if (pstate == Parser_state::prerelease) prerelease_hook_impl(prerelease_id, prerelease);
if (id.empty()) throw version::Parse_error("version identifier cannot be empty"); if (id.empty()) throw Parse_error("version identifier cannot be empty");
build.push_back(id); build.push_back(id);
id.clear(); id.clear();
} }
} }
namespace version {
/// Parse semver 2.0.0-compatible string to Version_data structure. /// Parse semver 2.0.0-compatible string to Version_data structure.
/** /**
+2 -2
View File
@@ -32,8 +32,8 @@ version::Semver200_parser p;
const version::Prerelease_identifiers no_rel_ids; const version::Prerelease_identifiers no_rel_ids;
const version::Build_identifiers no_build_ids; const version::Build_identifiers no_build_ids;
#define N Identifier_type::num #define N Id_type::num
#define A Identifier_type::alnum #define A Id_type::alnum
#define BOOST_PATCH BOOST_VERSION % 100 #define BOOST_PATCH BOOST_VERSION % 100
#define BOOST_MINOR BOOST_VERSION / 100 % 1000 #define BOOST_MINOR BOOST_VERSION / 100 % 1000