A basic semantic versioning library

Dependents:   BLE_Display

Revision:
0:91466b3b925e
--- /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;
+                }
+            }
+        }
+    }
+
+};