CommonLibVR
Loading...
Searching...
No Matches
Version.h
Go to the documentation of this file.
1#pragma once
2
3namespace REL
4{
5 class Version
6 {
7 public:
8 using value_type = std::uint16_t;
11
12 constexpr Version() noexcept = default;
13
14 explicit constexpr Version(std::array<value_type, 4> a_version) noexcept :
15 _impl(a_version)
16 {}
17
18 constexpr Version(value_type a_v1, value_type a_v2 = 0, value_type a_v3 = 0, value_type a_v4 = 0) noexcept :
19 _impl{ a_v1, a_v2, a_v3, a_v4 }
20 {}
21
22 explicit constexpr Version(std::string_view a_version)
23 {
24 std::array<value_type, 4> powers{ 1, 1, 1, 1 };
25 std::size_t position = 0;
26 for (std::size_t i = 0; i < a_version.size(); ++i) {
27 if (a_version[i] == '.') {
28 if (++position == powers.size()) {
29 throw std::invalid_argument("Too many parts in version number.");
30 }
31 } else {
32 powers[position] *= 10;
33 }
34 }
35 position = 0;
36 for (std::size_t i = 0; i < a_version.size(); ++i) {
37 if (a_version[i] == '.') {
38 ++position;
39 } else if (a_version[i] < '0' || a_version[i] > '9') {
40 throw std::invalid_argument("Invalid character in version number.");
41 } else {
42 powers[position] /= 10;
43 _impl[position] += static_cast<value_type>((a_version[i] - '0') * powers[position]);
44 }
45 }
46 }
47
48 [[nodiscard]] constexpr reference operator[](std::size_t a_idx) noexcept { return _impl[a_idx]; }
49 [[nodiscard]] constexpr const_reference operator[](std::size_t a_idx) const noexcept { return _impl[a_idx]; }
50
51 [[nodiscard]] constexpr decltype(auto) begin() const noexcept { return _impl.begin(); }
52 [[nodiscard]] constexpr decltype(auto) cbegin() const noexcept { return _impl.cbegin(); }
53 [[nodiscard]] constexpr decltype(auto) end() const noexcept { return _impl.end(); }
54 [[nodiscard]] constexpr decltype(auto) cend() const noexcept { return _impl.cend(); }
55
56 [[nodiscard]] std::strong_ordering constexpr compare(const Version& a_rhs) const noexcept
57 {
58 for (std::size_t i = 0; i < _impl.size(); ++i) {
59 if ((*this)[i] != a_rhs[i]) {
60 return (*this)[i] < a_rhs[i] ? std::strong_ordering::less : std::strong_ordering::greater;
61 }
62 }
63 return std::strong_ordering::equal;
64 }
65
66 [[nodiscard]] constexpr std::uint32_t pack() const noexcept
67 {
68 return static_cast<std::uint32_t>(
69 (_impl[0] & 0x0FF) << 24u |
70 (_impl[1] & 0x0FF) << 16u |
71 (_impl[2] & 0xFFF) << 4u |
72 (_impl[3] & 0x00F) << 0u);
73 }
74
75 [[nodiscard]] std::string string() const
76 {
77 std::string result;
78 for (auto&& ver : _impl) {
79 result += std::to_string(ver);
80 result += '-';
81 }
82 result.pop_back();
83 return result;
84 }
85
86 [[nodiscard]] std::wstring wstring() const
87 {
88 std::wstring result;
89 for (auto&& ver : _impl) {
90 result += std::to_wstring(ver);
91 result += L'-';
92 }
93 result.pop_back();
94 return result;
95 }
96
97 [[nodiscard]] static constexpr Version unpack(std::uint32_t a_packedVersion) noexcept
98 {
99 return REL::Version{
100 static_cast<value_type>((a_packedVersion >> 24) & 0x0FF),
101 static_cast<value_type>((a_packedVersion >> 16) & 0x0FF),
102 static_cast<value_type>((a_packedVersion >> 4) & 0xFFF),
103 static_cast<value_type>(a_packedVersion & 0x0F)
104 };
105 }
106
107 private:
108 std::array<value_type, 4> _impl{ 0, 0, 0, 0 };
109 };
110
111 [[nodiscard]] constexpr bool operator==(const Version& a_lhs, const Version& a_rhs) noexcept { return a_lhs.compare(a_rhs) == 0; }
112 [[nodiscard]] constexpr std::strong_ordering operator<=>(const Version& a_lhs, const Version& a_rhs) noexcept { return a_lhs.compare(a_rhs); }
113
114 [[nodiscard]] std::optional<Version> GetFileVersion(stl::zwstring a_filename);
115}
116
117#ifdef __cpp_lib_format
118template <class CharT>
119struct std::formatter<REL::Version, CharT> : formatter<std::string, CharT>
120{
121 template <class FormatContext>
122 constexpr auto format(const REL::Version a_version, FormatContext& a_ctx) const
123 {
124 return formatter<std::string, CharT>::format(a_version.string(), a_ctx);
125 }
126};
127#endif
128
129#ifdef FMT_VERSION
130template <class CharT>
131struct fmt::formatter<REL::Version, CharT> : formatter<std::string, CharT>
132{
133 template <class FormatContext>
134 auto format(const REL::Version a_version, FormatContext& a_ctx) const
135 {
136 return formatter<std::string, CharT>::format(a_version.string(), a_ctx);
137 }
138};
139#endif
Definition Version.h:6
constexpr decltype(auto) end() const noexcept
Definition Version.h:53
constexpr Version(value_type a_v1, value_type a_v2=0, value_type a_v3=0, value_type a_v4=0) noexcept
Definition Version.h:18
constexpr reference operator[](std::size_t a_idx) noexcept
Definition Version.h:48
std::strong_ordering constexpr compare(const Version &a_rhs) const noexcept
Definition Version.h:56
constexpr decltype(auto) cbegin() const noexcept
Definition Version.h:52
std::string string() const
Definition Version.h:75
constexpr std::uint32_t pack() const noexcept
Definition Version.h:66
constexpr Version(std::string_view a_version)
Definition Version.h:22
constexpr const_reference operator[](std::size_t a_idx) const noexcept
Definition Version.h:49
static constexpr Version unpack(std::uint32_t a_packedVersion) noexcept
Definition Version.h:97
std::uint16_t value_type
Definition Version.h:8
constexpr decltype(auto) cend() const noexcept
Definition Version.h:54
value_type & reference
Definition Version.h:9
const value_type & const_reference
Definition Version.h:10
constexpr Version() noexcept=default
constexpr decltype(auto) begin() const noexcept
Definition Version.h:51
std::wstring wstring() const
Definition Version.h:86
Definition ID.h:9
std::optional< Version > GetFileVersion(stl::zwstring a_filename)
constexpr std::strong_ordering operator<=>(const Version &a_lhs, const Version &a_rhs) noexcept
Definition Version.h:112
constexpr bool operator==(const Version &a_lhs, const Version &a_rhs) noexcept
Definition Version.h:111
basic_zstring< wchar_t > zwstring
Definition PCH.h:83
Definition EffectArchetypes.h:65
std::string to_string(RE::EffectArchetype a_archetype)
Definition EffectArchetypes.h:66