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;
}
}
}
}
};
Richard Osterloh