A basic semantic versioning library
SemVer.h
- Committer:
- rosterloh84
- Date:
- 2015-03-30
- Revision:
- 0:91466b3b925e
File content as of revision 0:91466b3b925e:
/** * @file * @date 30 March 2015 * @author Richard Osterloh <richardo@buddi.co.uk> */ #pragma once #include <sstream> #include <string> /** * @class SemVer * @brief A basic implementation of semantic versioning */ class SemVer { public: /** * SemVer constructor * @param version string to parse as a version */ SemVer(const std::string& version) { m_version = version; m_major = 0; m_minor = 0; m_patch = 0; if (version.empty()) { m_is_valid = false; } else { m_is_valid = true; parse(); } } ~SemVer() {} /** * Get full version */ const std::string& getVersion() const { return m_version; } /** * Get the major of the version */ const int& getMajor() const { return m_major; } /** * Get the minor of the version */ const int& getMinor() const { return m_minor; } /** * Get the patch of the version */ const int& getPatch() const { return m_patch; } /** * Check if the version is valid */ const bool& isValid() const { return m_is_valid; } int compare(SemVer& rgt) { if ((*this) == rgt) { return 0; } if ((*this) > rgt) { return 1; } return -1; } SemVer& operator= (SemVer& rgt) { if ((*this) != rgt) { this->m_version = rgt.getVersion(); this->m_major = rgt.getMajor(); this->m_minor = rgt.getMinor(); this->m_patch = rgt.getPatch(); this->m_is_valid = rgt.isValid(); } return *this; } friend bool operator== (SemVer &lft, SemVer &rgt) { return lft.getVersion().compare(rgt.getVersion()) == 0; } friend bool operator!= (SemVer &lft, SemVer &rgt) { return !(lft == rgt); } friend bool operator> (SemVer &lft, SemVer &rgt) { // Major if (lft.getMajor() < 0 && rgt.getMajor() >= 0) { return false; } if (lft.getMajor() >= 0 && rgt.getMajor() < 0) { return true; } if (lft.getMajor() > rgt.getMajor()) { return true; } if (lft.getMajor() < rgt.getMajor()) { return false; } // Minor if (lft.getMinor() < 0 && rgt.getMinor() >= 0) { return false; } if (lft.getMinor() >= 0 && rgt.getMinor() < 0) { return true; } if (lft.getMinor() > rgt.getMinor()) { return true; } if (lft.getMinor() < rgt.getMinor()) { return false; } // Patch if (lft.getPatch() < 0 && rgt.getPatch() >= 0) { return false; } if (lft.getPatch() >= 0 && rgt.getPatch() < 0) { return true; } if (lft.getPatch() > rgt.getPatch()) { return true; } if (lft.getPatch() < rgt.getPatch()) { return false; } return false; } friend bool operator>= (SemVer &lft, SemVer &rgt) { return (lft > rgt) || (lft == rgt); } friend bool operator< (SemVer &lft, SemVer &rgt) { return (rgt > lft); } friend bool operator<= (SemVer &lft, SemVer &rgt) { return (lft < rgt) || (lft == rgt); } friend std::ostream& operator<< (std::ostream& out, const SemVer& value) { out << value.getVersion(); return out; } private: std::string m_version; int m_major; int m_minor; int m_patch; bool m_is_valid; enum m_type { TYPE_MAJOR, TYPE_MINOR, TYPE_PATCH, }; void parse() { int type = TYPE_MAJOR; std::string major, minor, patch; for (std::size_t i = 0; i < m_version.length(); i++) { char chr = m_version[i]; int chr_dec = chr; switch (type) { case TYPE_MAJOR: if (chr == '.') { type = TYPE_MINOR; continue; } if (chr_dec < 48 || chr_dec > 57) { m_is_valid = false; } major += chr; break; case TYPE_MINOR: if (chr == '.') { type = TYPE_PATCH; continue; } if (chr_dec < 48 || chr_dec > 57) { m_is_valid = false; } minor += chr; break; case TYPE_PATCH: if (chr_dec < 48 || chr_dec > 57) { m_is_valid = false; } patch += chr; break; } if (m_is_valid) { std::istringstream(major) >> m_major; std::istringstream(minor) >> m_minor; std::istringstream(patch) >> m_patch; if (m_major == 0 && m_minor == 0 && m_patch == 0) { m_is_valid = false; } } } } };