#include "domain/SpineVersion.hpp" #include namespace dts { namespace { std::optional parseNumber(std::string_view text) { int value = 0; const auto result = std::from_chars(text.data(), text.data() + text.size(), value); if (result.ec != std::errc{} || result.ptr != text.data() + text.size()) { return std::nullopt; } return value; } } // namespace std::optional SpineVersion::parse(std::string_view text) { const auto firstDot = text.find('.'); if (firstDot == std::string_view::npos) { return std::nullopt; } const auto secondDot = text.find('.', firstDot + 1); const auto majorValue = parseNumber(text.substr(0, firstDot)); const auto minorEnd = secondDot == std::string_view::npos ? text.size() : secondDot; const auto minorValue = parseNumber(text.substr(firstDot + 1, minorEnd - firstDot - 1)); if (!majorValue || !minorValue) { return std::nullopt; } SpineVersion version{*majorValue, *minorValue, 0, false}; if (secondDot != std::string_view::npos) { auto patchText = text.substr(secondDot + 1); const auto suffix = patchText.find_first_not_of("0123456789"); const auto numericPatch = patchText.substr(0, suffix); if (numericPatch.empty() || (suffix != std::string_view::npos && patchText[suffix] != '-')) { return std::nullopt; } const auto patchValue = parseNumber(numericPatch); if (!patchValue) { return std::nullopt; } version.patch = *patchValue; version.hasPatch = true; } return version; } std::string SpineVersion::line() const { return std::to_string(major) + "." + std::to_string(minor); } std::string SpineVersion::toString() const { auto value = line(); if (hasPatch) { value += "." + std::to_string(patch); } return value; } bool SpineVersion::isSupported() const { if (major == 3 && minor == 8) { return !hasPatch || patch >= 20; } return major == 4 && minor >= 0 && minor <= 3; } } // namespace dts