#include #include #include namespace hex { SemanticVersion::SemanticVersion(u32 major, u32 minor, u32 patch) : SemanticVersion(fmt::format("{}.{}.{}", major, minor, patch)) { } SemanticVersion::SemanticVersion(const char *version) : SemanticVersion(std::string(version)) { } SemanticVersion::SemanticVersion(std::string_view version) : SemanticVersion(std::string(version.begin(), version.end())) { } SemanticVersion::SemanticVersion(std::string version) { if (version.empty()) return; if (version.starts_with("v")) version = version.substr(1); m_parts = wolv::util::splitString(version, "."); if (m_parts.size() != 3 && m_parts.size() != 4) { m_parts.clear(); return; } if (m_parts.back().contains("-")) { auto buildTypeParts = wolv::util::splitString(m_parts.back(), "-"); if (buildTypeParts.size() != 2) { m_parts.clear(); return; } m_parts.back() = buildTypeParts[0]; m_buildType = buildTypeParts[1]; } } u32 SemanticVersion::major() const { if (!isValid()) return 0; try { return std::stoul(m_parts[0]); } catch (...) { return 0; } } u32 SemanticVersion::minor() const { if (!isValid()) return 0; try { return std::stoul(m_parts[1]); } catch (...) { return 0; } } u32 SemanticVersion::patch() const { if (!isValid()) return 0; try { return std::stoul(m_parts[2]); } catch (...) { return 0; } } bool SemanticVersion::nightly() const { if (!isValid()) return false; return m_parts.size() == 4 && m_parts[3] == "WIP"; } const std::string& SemanticVersion::buildType() const { return m_buildType; } bool SemanticVersion::isValid() const { return !m_parts.empty(); } bool SemanticVersion::operator==(const SemanticVersion& other) const { return this->m_parts == other.m_parts; } std::strong_ordering SemanticVersion::operator<=>(const SemanticVersion &other) const { if (const auto result = major() <=> other.major(); result != std::strong_ordering::equal) return result; if (auto result = minor() <=> other.minor(); result != std::strong_ordering::equal) return result; if (auto result = patch() <=> other.patch(); result != std::strong_ordering::equal) return result; // nightly builds are considered "greater" than release builds if (nightly() != other.nightly()) return nightly() ? std::strong_ordering::greater : std::strong_ordering::less; return std::strong_ordering::equal; } std::string SemanticVersion::get(bool withBuildType) const { if (!isValid()) return ""; auto result = wolv::util::combineStrings(m_parts, "."); if (withBuildType && !m_buildType.empty()) result += fmt::format("-{}", m_buildType); return result; } }