#include <cstddef>
#include <cstdint>
#include <stdexcept>
#include <string>
#include <string_view>
#include "semver.hpp"
#include "utils.hpp"
namespace ddwaf {
semantic_version::semantic_version(std::string_view version) : str_(version)
{
std::size_t start = 0;
auto end = version.find('.');
if (end == std::string_view::npos) {
throw std::invalid_argument("invalid version syntax");
}
auto major_str = version.substr(start, end - start);
if (major_str.empty() || major_str.size() > 3 || !parse_number(major_str, major_)) {
throw std::invalid_argument("invalid major version: " + std::string{major_str});
}
start = end + 1;
end = version.find('.', start);
if (end == std::string_view::npos) {
throw std::invalid_argument("invalid version syntax");
}
auto minor_str = version.substr(start, end - start);
if (minor_str.empty() || minor_str.size() > 3 || !parse_number(minor_str, minor_)) {
throw std::invalid_argument("invalid minor version: " + std::string{minor_str});
}
start = end + 1;
end = version.find('-', start);
auto patch_str = version.substr(start, end - start);
if (patch_str.empty() || patch_str.size() > 3 || !parse_number(patch_str, patch_)) {
throw std::invalid_argument("invalid patch version: " + std::string{patch_str});
}
number_ = major_ * 1000000 + minor_ * 1000 + patch_;
}
bool semantic_version::parse_number(std::string_view str, uint16_t &output)
{
if (auto [res, value] = from_string<uint16_t>(str); res) {
output = value;
return true;
}
return false;
}
}