A basic semantic versioning library
Revision 0:91466b3b925e, committed 2015-03-30
- Comitter:
- rosterloh84
- Date:
- Mon Mar 30 13:22:22 2015 +0000
- Commit message:
- Major, Minor and Patch implemented
Changed in this revision
SemVer.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SemVer.h Mon Mar 30 13:22:22 2015 +0000 @@ -0,0 +1,292 @@ +/** + * @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; + } + } + } + } + +};