CommonLibVR
Version.h
Go to the documentation of this file.
1 #pragma once
2 
3 namespace REL
4 {
5  class Version
6  {
7  public:
8  using value_type = std::uint16_t;
9  using reference = value_type&;
10  using const_reference = const value_type&;
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
118 template <class CharT>
119 struct 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
130 template <class CharT>
131 struct 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
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 std::strong_ordering compare(const Version &a_rhs) const noexcept
Definition: Version.h:56
constexpr decltype(auto) begin() const noexcept
Definition: Version.h:51
std::wstring wstring() const
Definition: Version.h:86
Definition: ID.h:9
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
std::optional< Version > GetFileVersion(stl::zwstring a_filename)
string(const CharT(&)[N]) -> string< CharT, N - 1 >
basic_zstring< wchar_t > zwstring
Definition: PCH.h:80
Definition: EffectArchetypes.h:65
std::string to_string(RE::EffectArchetype a_archetype)
Definition: EffectArchetypes.h:66