| 410 | } |
| 411 | |
| 412 | ObjectVersion VersionTuple(std::string_view version) |
| 413 | { |
| 414 | if (version.empty()) |
| 415 | { |
| 416 | return std::make_tuple(0, 0, 0); |
| 417 | } |
| 418 | |
| 419 | auto nums = String::split(version, "."); |
| 420 | uint16_t versions[VersionNumFields] = {}; |
| 421 | if (nums.size() > VersionNumFields) |
| 422 | { |
| 423 | LOG_WARNING("%i fields found in version string '%s', expected X.Y.Z", nums.size(), version); |
| 424 | } |
| 425 | if (nums.empty()) |
| 426 | { |
| 427 | LOG_WARNING("No fields found in version string '%s', expected X.Y.Z", version); |
| 428 | return std::make_tuple(0, 0, 0); |
| 429 | } |
| 430 | try |
| 431 | { |
| 432 | size_t highestIndex = std::min(nums.size(), VersionNumFields); |
| 433 | for (size_t i = 0; i < highestIndex; i++) |
| 434 | { |
| 435 | auto value = String::parse<int64_t>(nums.at(i)); |
| 436 | constexpr auto maxValue = std::numeric_limits<uint16_t>().max(); |
| 437 | if (value > maxValue) |
| 438 | { |
| 439 | LOG_WARNING( |
| 440 | "Version value too high in version string '%.*s', version value will be capped to %i.", |
| 441 | static_cast<int>(version.size()), version.data(), maxValue); |
| 442 | value = maxValue; |
| 443 | } |
| 444 | versions[i] = value; |
| 445 | } |
| 446 | } |
| 447 | catch (const std::exception&) |
| 448 | { |
| 449 | LOG_WARNING("Malformed version string '%.*s', expected X.Y.Z", static_cast<int>(version.size()), version.data()); |
| 450 | } |
| 451 | |
| 452 | return std::make_tuple(versions[0], versions[1], versions[2]); |
| 453 | } |
| 454 | |
| 455 | } // namespace OpenRCT2 |
| 456 | |