#ifndef LLVM_SUPPORT_VERSIONTUPLE_H
#define LLVM_SUPPORT_VERSIONTUPLE_H
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Endian.h"
#include <string>
#include <tuple>
namespace llvm {
template <typename HasherT, support::endianness Endianness>
class HashBuilderImpl;
class raw_ostream;
class StringRef;
class VersionTuple {
unsigned Major : 32;
unsigned Minor : 31;
unsigned HasMinor : 1;
unsigned Subminor : 31;
unsigned HasSubminor : 1;
unsigned Build : 31;
unsigned HasBuild : 1;
public:
VersionTuple()
: Major(0), Minor(0), HasMinor(false), Subminor(0), HasSubminor(false),
Build(0), HasBuild(false) {}
explicit VersionTuple(unsigned Major)
: Major(Major), Minor(0), HasMinor(false), Subminor(0),
HasSubminor(false), Build(0), HasBuild(false) {}
explicit VersionTuple(unsigned Major, unsigned Minor)
: Major(Major), Minor(Minor), HasMinor(true), Subminor(0),
HasSubminor(false), Build(0), HasBuild(false) {}
explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor)
: Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor),
HasSubminor(true), Build(0), HasBuild(false) {}
explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor,
unsigned Build)
: Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor),
HasSubminor(true), Build(Build), HasBuild(true) {}
bool empty() const {
return Major == 0 && Minor == 0 && Subminor == 0 && Build == 0;
}
unsigned getMajor() const { return Major; }
Optional<unsigned> getMinor() const {
if (!HasMinor)
return None;
return Minor;
}
Optional<unsigned> getSubminor() const {
if (!HasSubminor)
return None;
return Subminor;
}
Optional<unsigned> getBuild() const {
if (!HasBuild)
return None;
return Build;
}
VersionTuple withoutBuild() const {
if (HasBuild)
return VersionTuple(Major, Minor, Subminor);
return *this;
}
VersionTuple withMajorReplaced(unsigned NewMajor) const {
return VersionTuple(NewMajor, Minor, Subminor, Build);
}
VersionTuple normalize() const {
VersionTuple Result = *this;
if (Result.Build == 0) {
Result.HasBuild = false;
if (Result.Subminor == 0) {
Result.HasSubminor = false;
if (Result.Minor == 0)
Result.HasMinor = false;
}
}
return Result;
}
friend bool operator==(const VersionTuple &X, const VersionTuple &Y) {
return X.Major == Y.Major && X.Minor == Y.Minor &&
X.Subminor == Y.Subminor && X.Build == Y.Build;
}
friend bool operator!=(const VersionTuple &X, const VersionTuple &Y) {
return !(X == Y);
}
friend bool operator<(const VersionTuple &X, const VersionTuple &Y) {
return std::tie(X.Major, X.Minor, X.Subminor, X.Build) <
std::tie(Y.Major, Y.Minor, Y.Subminor, Y.Build);
}
friend bool operator>(const VersionTuple &X, const VersionTuple &Y) {
return Y < X;
}
friend bool operator<=(const VersionTuple &X, const VersionTuple &Y) {
return !(Y < X);
}
friend bool operator>=(const VersionTuple &X, const VersionTuple &Y) {
return !(X < Y);
}
friend hash_code hash_value(const VersionTuple &VT) {
return hash_combine(VT.Major, VT.Minor, VT.Subminor, VT.Build);
}
template <typename HasherT, llvm::support::endianness Endianness>
friend void addHash(HashBuilderImpl<HasherT, Endianness> &HBuilder,
const VersionTuple &VT) {
HBuilder.add(VT.Major, VT.Minor, VT.Subminor, VT.Build);
}
std::string getAsString() const;
bool tryParse(StringRef string);
};
raw_ostream &operator<<(raw_ostream &Out, const VersionTuple &V);
template <> struct DenseMapInfo<VersionTuple> {
static inline VersionTuple getEmptyKey() { return VersionTuple(0x7FFFFFFF); }
static inline VersionTuple getTombstoneKey() {
return VersionTuple(0x7FFFFFFE);
}
static unsigned getHashValue(const VersionTuple &Value) {
unsigned Result = Value.getMajor();
if (auto Minor = Value.getMinor())
Result = detail::combineHashValue(Result, *Minor);
if (auto Subminor = Value.getSubminor())
Result = detail::combineHashValue(Result, *Subminor);
if (auto Build = Value.getBuild())
Result = detail::combineHashValue(Result, *Build);
return Result;
}
static bool isEqual(const VersionTuple &LHS, const VersionTuple &RHS) {
return LHS == RHS;
}
};
} #endif