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