123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551 |
- #ifndef VERSION_H
- #define VERSION_H
- /**
- * Semver - The Semantic Versioning, https://github.com/euskadi31/semver-cpp
- *
- * Copyright (c) 2013 Axel Etcheverry, 2021 enhancements & fixes Lord-Grey
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is furnished
- * to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
- #include <cstdlib>
- #include <iostream>
- #include <sstream>
- #include <string>
- namespace semver {
- enum PRE_RELEASE {
- PRE_RELEASE_ALPHA,
- PRE_RELEASE_BETA,
- PRE_RELEASE_RC,
- PRE_RELEASE_NONE
- };
- typedef enum PRE_RELEASE pre_release_t;
- class version
- {
- private:
- std::string m_version;
- int m_major;
- int m_minor;
- int m_patch;
- pre_release_t m_pre_release_type;
- std::string m_pre_release_id;
- std::string m_pre_release;
- std::string m_build;
- bool m_is_valid;
- bool m_is_stable;
- enum m_type {
- TYPE_MAJOR,
- TYPE_MINOR,
- TYPE_PATCH,
- TYPE_PRE_RELEASE,
- TYPE_PRE_RELEASE_ID,
- TYPE_BUILD
- };
- 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
- 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 == '-')
- {
- type = TYPE_PRE_RELEASE;
- continue;
- }
- if (chr == '+')
- {
- type = TYPE_BUILD;
- continue;
- }
- if (chr_dec < 48 || chr_dec > 57)
- {
- m_is_valid = false;
- }
- patch += chr;
- break;
- case TYPE_PRE_RELEASE:
- if (chr == '.')
- {
- type = TYPE_PRE_RELEASE_ID;
- m_pre_release += chr;
- continue;
- }
- if (chr == '+')
- {
- type = TYPE_BUILD;
- continue;
- }
- if (
- (chr_dec < 48 || chr_dec > 57) && // 0-9
- (chr_dec < 65 || chr_dec > 90) && // A-Z
- (chr_dec < 97 || chr_dec > 122) && // a-z
- (chr_dec != 45) && // -
- (chr_dec != 46) // .
- )
- {
- m_is_valid = false;
- }
- m_pre_release += chr;
- break;
- case TYPE_PRE_RELEASE_ID:
- if (chr == '+')
- {
- type = TYPE_BUILD;
- continue;
- }
- if (
- (chr_dec < 48 || chr_dec > 57) && // 0-9
- (chr_dec < 65 || chr_dec > 90) && // A-Z
- (chr_dec < 97 || chr_dec > 122) && // a-z
- (chr_dec != 45) // -
- )
- {
- m_is_valid = false;
- }
- m_pre_release += chr;
- m_pre_release_id += chr;
- break;
- case TYPE_BUILD:
- if (
- (chr_dec < 48 || chr_dec > 57) && // 0-9
- (chr_dec < 65 || chr_dec > 90) && // A-Z
- (chr_dec < 97 || chr_dec > 122) && // a-z
- (chr_dec != 45) // -
- )
- {
- m_is_valid = false;
- }
- m_build += chr;
- break;
- }
- }
- if (m_is_valid)
- {
- std::istringstream(major) >> m_major;
- std::istringstream(minor) >> m_minor;
- std::istringstream(patch) >> m_patch;
- if (m_pre_release.empty())
- {
- m_pre_release_type = PRE_RELEASE_NONE;
- }
- else if (m_pre_release.find("alpha") != std::string::npos)
- {
- m_pre_release_type = PRE_RELEASE_ALPHA;
- }
- else if (m_pre_release.find("beta") != std::string::npos)
- {
- m_pre_release_type = PRE_RELEASE_BETA;
- }
- else if (m_pre_release.find("rc") != std::string::npos)
- {
- m_pre_release_type = PRE_RELEASE_RC;
- }
- if (m_major == 0 && m_minor == 0 && m_patch == 0)
- {
- m_is_valid = false;
- }
- if (!m_pre_release_id.empty() && m_pre_release_id[0] == '0')
- {
- m_is_valid = false;
- }
- if (m_major == 0)
- {
- m_is_stable = false;
- }
- if (m_pre_release_type != PRE_RELEASE_NONE)
- {
- m_is_stable = false;
- }
- }
- }
- public:
- /**
- * Parse the version string
- */
- version(const std::string& version)
- {
- setVersion(version);
- }
- version(const version&) = default;
- ~version() = default;
- /**
- * Set version
- */
- bool setVersion(const std::string& version)
- {
- m_version = version;
- m_major = 0;
- m_minor = 0;
- m_patch = 0;
- m_build = "";
- m_pre_release = "";
- m_pre_release_id = "";
- m_is_stable = true;
- if (version.empty())
- {
- m_is_valid = false;
- }
- else
- {
- m_is_valid = true;
- parse();
- }
- return m_is_valid;
- }
- /**
- * 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;
- }
- /**
- * Get the build of the version
- */
- const std::string& getBuild() const
- {
- return m_build;
- }
- /**
- * Get the release type of the version
- */
- const pre_release_t& getPreReleaseType() const
- {
- return m_pre_release_type;
- }
- /**
- * Get the release identifier of the version
- */
- const std::string& getPreReleaseId() const
- {
- return m_pre_release_id;
- }
- /**
- * Get the release of the version
- */
- const std::string& getPreRelease() const
- {
- return m_pre_release;
- }
- /**
- * Check if the version is stable
- */
- const bool& isStable() const
- {
- return m_is_stable;
- }
- /**
- * Check if the version is valid
- */
- const bool& isValid() const
- {
- return m_is_valid;
- }
- int compare(version& rgt)
- {
- if ((*this) == rgt)
- {
- return 0;
- }
- if ((*this) > rgt)
- {
- return 1;
- }
- return -1;
- }
- version& operator= (version& 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_pre_release_type = rgt.getPreReleaseType();
- this->m_pre_release_id = rgt.getPreReleaseId();
- this->m_pre_release = rgt.getPreRelease();
- this->m_build = rgt.getBuild();
- this->m_is_valid = rgt.isValid();
- this->m_is_stable = rgt.isStable();
- }
- return *this;
- }
- friend bool operator== (version &lft, version &rgt)
- {
- return !(lft != rgt);
- }
- friend bool operator!= (version &lft, version &rgt)
- {
- return (lft > rgt) || (lft < rgt);
- }
- friend bool operator> (version &lft, version &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;
- }
-
- // Pre release
- if (
- (lft.getPreReleaseType() == rgt.getPreReleaseType()) &&
- (lft.getPreReleaseId() == rgt.getPreReleaseId())
- )
- {
- return false;
- }
- if (
- (lft.getPreReleaseType() == rgt.getPreReleaseType()) &&
- (lft.getPreReleaseId().find_first_not_of("0123456789") == std::string::npos) &&
- (rgt.getPreReleaseId().find_first_not_of("0123456789") == std::string::npos)
- )
- {
- if (atoi(lft.getPreReleaseId().c_str()) > atoi(rgt.getPreReleaseId().c_str()))
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- if (
- (lft.getPreReleaseType() == rgt.getPreReleaseType()) &&
- (lft.getPreReleaseId().compare(rgt.getPreReleaseId()) > 0)
- )
- {
- return true;
- }
- if (lft.getPreReleaseType() > rgt.getPreReleaseType())
- {
- return true;
- }
- return false;
- }
- friend bool operator>= (version &lft, version &rgt)
- {
- return (lft > rgt) || (lft == rgt);
- }
- friend bool operator< (version &lft, version &rgt)
- {
- return (rgt > lft);
- }
- friend bool operator<= (version &lft, version &rgt)
- {
- return (lft < rgt) || (lft == rgt);
- }
- friend std::ostream& operator<< (std::ostream& out, const version& value)
- {
- out << value.getVersion();
- return out;
- }
- };
- } // end semver namespace
- #endif // VERSION_H
|