VersionTuple.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- VersionTuple.h - Version Number Handling -----------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. ///
  14. /// \file
  15. /// Defines the llvm::VersionTuple class, which represents a version in
  16. /// the form major[.minor[.subminor]].
  17. ///
  18. //===----------------------------------------------------------------------===//
  19. #ifndef LLVM_SUPPORT_VERSIONTUPLE_H
  20. #define LLVM_SUPPORT_VERSIONTUPLE_H
  21. #include "llvm/ADT/DenseMapInfo.h"
  22. #include "llvm/ADT/Hashing.h"
  23. #include "llvm/Support/Endian.h"
  24. #include <optional>
  25. #include <string>
  26. #include <tuple>
  27. namespace llvm {
  28. template <typename HasherT, support::endianness Endianness>
  29. class HashBuilderImpl;
  30. class raw_ostream;
  31. class StringRef;
  32. /// Represents a version number in the form major[.minor[.subminor[.build]]].
  33. class VersionTuple {
  34. unsigned Major : 32;
  35. unsigned Minor : 31;
  36. unsigned HasMinor : 1;
  37. unsigned Subminor : 31;
  38. unsigned HasSubminor : 1;
  39. unsigned Build : 31;
  40. unsigned HasBuild : 1;
  41. public:
  42. constexpr VersionTuple()
  43. : Major(0), Minor(0), HasMinor(false), Subminor(0), HasSubminor(false),
  44. Build(0), HasBuild(false) {}
  45. explicit constexpr VersionTuple(unsigned Major)
  46. : Major(Major), Minor(0), HasMinor(false), Subminor(0),
  47. HasSubminor(false), Build(0), HasBuild(false) {}
  48. explicit constexpr VersionTuple(unsigned Major, unsigned Minor)
  49. : Major(Major), Minor(Minor), HasMinor(true), Subminor(0),
  50. HasSubminor(false), Build(0), HasBuild(false) {}
  51. explicit constexpr VersionTuple(unsigned Major, unsigned Minor,
  52. unsigned Subminor)
  53. : Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor),
  54. HasSubminor(true), Build(0), HasBuild(false) {}
  55. explicit constexpr VersionTuple(unsigned Major, unsigned Minor,
  56. unsigned Subminor, unsigned Build)
  57. : Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor),
  58. HasSubminor(true), Build(Build), HasBuild(true) {}
  59. /// Determine whether this version information is empty
  60. /// (e.g., all version components are zero).
  61. bool empty() const {
  62. return Major == 0 && Minor == 0 && Subminor == 0 && Build == 0;
  63. }
  64. /// Retrieve the major version number.
  65. unsigned getMajor() const { return Major; }
  66. /// Retrieve the minor version number, if provided.
  67. std::optional<unsigned> getMinor() const {
  68. if (!HasMinor)
  69. return std::nullopt;
  70. return Minor;
  71. }
  72. /// Retrieve the subminor version number, if provided.
  73. std::optional<unsigned> getSubminor() const {
  74. if (!HasSubminor)
  75. return std::nullopt;
  76. return Subminor;
  77. }
  78. /// Retrieve the build version number, if provided.
  79. std::optional<unsigned> getBuild() const {
  80. if (!HasBuild)
  81. return std::nullopt;
  82. return Build;
  83. }
  84. /// Return a version tuple that contains only the first 3 version components.
  85. VersionTuple withoutBuild() const {
  86. if (HasBuild)
  87. return VersionTuple(Major, Minor, Subminor);
  88. return *this;
  89. }
  90. /// Return a version tuple that contains a different major version but
  91. /// everything else is the same.
  92. VersionTuple withMajorReplaced(unsigned NewMajor) const {
  93. return VersionTuple(NewMajor, Minor, Subminor, Build);
  94. }
  95. /// Return a version tuple that contains only components that are non-zero.
  96. VersionTuple normalize() const {
  97. VersionTuple Result = *this;
  98. if (Result.Build == 0) {
  99. Result.HasBuild = false;
  100. if (Result.Subminor == 0) {
  101. Result.HasSubminor = false;
  102. if (Result.Minor == 0)
  103. Result.HasMinor = false;
  104. }
  105. }
  106. return Result;
  107. }
  108. /// Determine if two version numbers are equivalent. If not
  109. /// provided, minor and subminor version numbers are considered to be zero.
  110. friend bool operator==(const VersionTuple &X, const VersionTuple &Y) {
  111. return X.Major == Y.Major && X.Minor == Y.Minor &&
  112. X.Subminor == Y.Subminor && X.Build == Y.Build;
  113. }
  114. /// Determine if two version numbers are not equivalent.
  115. ///
  116. /// If not provided, minor and subminor version numbers are considered to be
  117. /// zero.
  118. friend bool operator!=(const VersionTuple &X, const VersionTuple &Y) {
  119. return !(X == Y);
  120. }
  121. /// Determine whether one version number precedes another.
  122. ///
  123. /// If not provided, minor and subminor version numbers are considered to be
  124. /// zero.
  125. friend bool operator<(const VersionTuple &X, const VersionTuple &Y) {
  126. return std::tie(X.Major, X.Minor, X.Subminor, X.Build) <
  127. std::tie(Y.Major, Y.Minor, Y.Subminor, Y.Build);
  128. }
  129. /// Determine whether one version number follows another.
  130. ///
  131. /// If not provided, minor and subminor version numbers are considered to be
  132. /// zero.
  133. friend bool operator>(const VersionTuple &X, const VersionTuple &Y) {
  134. return Y < X;
  135. }
  136. /// Determine whether one version number precedes or is
  137. /// equivalent to another.
  138. ///
  139. /// If not provided, minor and subminor version numbers are considered to be
  140. /// zero.
  141. friend bool operator<=(const VersionTuple &X, const VersionTuple &Y) {
  142. return !(Y < X);
  143. }
  144. /// Determine whether one version number follows or is
  145. /// equivalent to another.
  146. ///
  147. /// If not provided, minor and subminor version numbers are considered to be
  148. /// zero.
  149. friend bool operator>=(const VersionTuple &X, const VersionTuple &Y) {
  150. return !(X < Y);
  151. }
  152. friend hash_code hash_value(const VersionTuple &VT) {
  153. return hash_combine(VT.Major, VT.Minor, VT.Subminor, VT.Build);
  154. }
  155. template <typename HasherT, llvm::support::endianness Endianness>
  156. friend void addHash(HashBuilderImpl<HasherT, Endianness> &HBuilder,
  157. const VersionTuple &VT) {
  158. HBuilder.add(VT.Major, VT.Minor, VT.Subminor, VT.Build);
  159. }
  160. /// Retrieve a string representation of the version number.
  161. std::string getAsString() const;
  162. /// Try to parse the given string as a version number.
  163. /// \returns \c true if the string does not match the regular expression
  164. /// [0-9]+(\.[0-9]+){0,3}
  165. bool tryParse(StringRef string);
  166. };
  167. /// Print a version number.
  168. raw_ostream &operator<<(raw_ostream &Out, const VersionTuple &V);
  169. // Provide DenseMapInfo for version tuples.
  170. template <> struct DenseMapInfo<VersionTuple> {
  171. static inline VersionTuple getEmptyKey() { return VersionTuple(0x7FFFFFFF); }
  172. static inline VersionTuple getTombstoneKey() {
  173. return VersionTuple(0x7FFFFFFE);
  174. }
  175. static unsigned getHashValue(const VersionTuple &Value) {
  176. unsigned Result = Value.getMajor();
  177. if (auto Minor = Value.getMinor())
  178. Result = detail::combineHashValue(Result, *Minor);
  179. if (auto Subminor = Value.getSubminor())
  180. Result = detail::combineHashValue(Result, *Subminor);
  181. if (auto Build = Value.getBuild())
  182. Result = detail::combineHashValue(Result, *Build);
  183. return Result;
  184. }
  185. static bool isEqual(const VersionTuple &LHS, const VersionTuple &RHS) {
  186. return LHS == RHS;
  187. }
  188. };
  189. } // end namespace llvm
  190. #endif // LLVM_SUPPORT_VERSIONTUPLE_H
  191. #ifdef __GNUC__
  192. #pragma GCC diagnostic pop
  193. #endif