VersionTuple.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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/ADT/Optional.h"
  24. #include "llvm/Support/HashBuilder.h"
  25. #include <string>
  26. #include <tuple>
  27. namespace llvm {
  28. class raw_ostream;
  29. class StringRef;
  30. /// Represents a version number in the form major[.minor[.subminor[.build]]].
  31. class VersionTuple {
  32. unsigned Major : 32;
  33. unsigned Minor : 31;
  34. unsigned HasMinor : 1;
  35. unsigned Subminor : 31;
  36. unsigned HasSubminor : 1;
  37. unsigned Build : 31;
  38. unsigned HasBuild : 1;
  39. public:
  40. VersionTuple()
  41. : Major(0), Minor(0), HasMinor(false), Subminor(0), HasSubminor(false),
  42. Build(0), HasBuild(false) {}
  43. explicit VersionTuple(unsigned Major)
  44. : Major(Major), Minor(0), HasMinor(false), Subminor(0),
  45. HasSubminor(false), Build(0), HasBuild(false) {}
  46. explicit VersionTuple(unsigned Major, unsigned Minor)
  47. : Major(Major), Minor(Minor), HasMinor(true), Subminor(0),
  48. HasSubminor(false), Build(0), HasBuild(false) {}
  49. explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor)
  50. : Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor),
  51. HasSubminor(true), Build(0), HasBuild(false) {}
  52. explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor,
  53. unsigned Build)
  54. : Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor),
  55. HasSubminor(true), Build(Build), HasBuild(true) {}
  56. /// Determine whether this version information is empty
  57. /// (e.g., all version components are zero).
  58. bool empty() const {
  59. return Major == 0 && Minor == 0 && Subminor == 0 && Build == 0;
  60. }
  61. /// Retrieve the major version number.
  62. unsigned getMajor() const { return Major; }
  63. /// Retrieve the minor version number, if provided.
  64. Optional<unsigned> getMinor() const {
  65. if (!HasMinor)
  66. return None;
  67. return Minor;
  68. }
  69. /// Retrieve the subminor version number, if provided.
  70. Optional<unsigned> getSubminor() const {
  71. if (!HasSubminor)
  72. return None;
  73. return Subminor;
  74. }
  75. /// Retrieve the build version number, if provided.
  76. Optional<unsigned> getBuild() const {
  77. if (!HasBuild)
  78. return None;
  79. return Build;
  80. }
  81. /// Return a version tuple that contains only the first 3 version components.
  82. VersionTuple withoutBuild() const {
  83. if (HasBuild)
  84. return VersionTuple(Major, Minor, Subminor);
  85. return *this;
  86. }
  87. /// Return a version tuple that contains only components that are non-zero.
  88. VersionTuple normalize() const {
  89. VersionTuple Result = *this;
  90. if (Result.Build == 0) {
  91. Result.HasBuild = false;
  92. if (Result.Subminor == 0) {
  93. Result.HasSubminor = false;
  94. if (Result.Minor == 0)
  95. Result.HasMinor = false;
  96. }
  97. }
  98. return Result;
  99. }
  100. /// Determine if two version numbers are equivalent. If not
  101. /// provided, minor and subminor version numbers are considered to be zero.
  102. friend bool operator==(const VersionTuple &X, const VersionTuple &Y) {
  103. return X.Major == Y.Major && X.Minor == Y.Minor &&
  104. X.Subminor == Y.Subminor && X.Build == Y.Build;
  105. }
  106. /// Determine if two version numbers are not equivalent.
  107. ///
  108. /// If not provided, minor and subminor version numbers are considered to be
  109. /// zero.
  110. friend bool operator!=(const VersionTuple &X, const VersionTuple &Y) {
  111. return !(X == Y);
  112. }
  113. /// Determine whether one version number precedes another.
  114. ///
  115. /// If not provided, minor and subminor version numbers are considered to be
  116. /// zero.
  117. friend bool operator<(const VersionTuple &X, const VersionTuple &Y) {
  118. return std::tie(X.Major, X.Minor, X.Subminor, X.Build) <
  119. std::tie(Y.Major, Y.Minor, Y.Subminor, Y.Build);
  120. }
  121. /// Determine whether one version number follows 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 Y < X;
  127. }
  128. /// Determine whether one version number precedes or is
  129. /// equivalent to 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 follows 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 !(X < Y);
  143. }
  144. friend llvm::hash_code hash_value(const VersionTuple &VT) {
  145. return llvm::hash_combine(VT.Major, VT.Minor, VT.Subminor, VT.Build);
  146. }
  147. template <typename HasherT, llvm::support::endianness Endianness>
  148. friend void addHash(HashBuilderImpl<HasherT, Endianness> &HBuilder,
  149. const VersionTuple &VT) {
  150. HBuilder.add(VT.Major, VT.Minor, VT.Subminor, VT.Build);
  151. }
  152. /// Retrieve a string representation of the version number.
  153. std::string getAsString() const;
  154. /// Try to parse the given string as a version number.
  155. /// \returns \c true if the string does not match the regular expression
  156. /// [0-9]+(\.[0-9]+){0,3}
  157. bool tryParse(StringRef string);
  158. };
  159. /// Print a version number.
  160. raw_ostream &operator<<(raw_ostream &Out, const VersionTuple &V);
  161. // Provide DenseMapInfo for version tuples.
  162. template <> struct DenseMapInfo<VersionTuple> {
  163. static inline VersionTuple getEmptyKey() { return VersionTuple(0x7FFFFFFF); }
  164. static inline VersionTuple getTombstoneKey() {
  165. return VersionTuple(0x7FFFFFFE);
  166. }
  167. static unsigned getHashValue(const VersionTuple &Value) {
  168. unsigned Result = Value.getMajor();
  169. if (auto Minor = Value.getMinor())
  170. Result = detail::combineHashValue(Result, *Minor);
  171. if (auto Subminor = Value.getSubminor())
  172. Result = detail::combineHashValue(Result, *Subminor);
  173. if (auto Build = Value.getBuild())
  174. Result = detail::combineHashValue(Result, *Build);
  175. return Result;
  176. }
  177. static bool isEqual(const VersionTuple &LHS, const VersionTuple &RHS) {
  178. return LHS == RHS;
  179. }
  180. };
  181. } // end namespace llvm
  182. #endif // LLVM_SUPPORT_VERSIONTUPLE_H
  183. #ifdef __GNUC__
  184. #pragma GCC diagnostic pop
  185. #endif