#pragma once #include #include #include namespace vcpkg::Parse { struct ParserBase; } namespace vcpkg { /// /// /// Full specification of a package. Contains all information to reference /// a specific package. /// /// struct PackageSpec { PackageSpec() noexcept = default; PackageSpec(std::string name, Triplet triplet) : m_name(std::move(name)), m_triplet(triplet) {} static std::vector to_package_specs(const std::vector& ports, Triplet triplet); const std::string& name() const; Triplet triplet() const; std::string dir() const; std::string to_string() const; void to_string(std::string& s) const; bool operator<(const PackageSpec& other) const { if (name() < other.name()) return true; if (name() > other.name()) return false; return triplet() < other.triplet(); } private: std::string m_name; Triplet m_triplet; }; /// /// /// Full specification of a feature. Contains all information to reference /// a single feature in a specific package. /// /// struct FeatureSpec { FeatureSpec(const PackageSpec& spec, const std::string& feature) : m_spec(spec), m_feature(feature) {} const std::string& name() const { return m_spec.name(); } const std::string& feature() const { return m_feature; } Triplet triplet() const { return m_spec.triplet(); } const PackageSpec& spec() const { return m_spec; } std::string to_string() const; void to_string(std::string& out) const; bool operator<(const FeatureSpec& other) const { if (name() < other.name()) return true; if (name() > other.name()) return false; if (feature() < other.feature()) return true; if (feature() > other.feature()) return false; return triplet() < other.triplet(); } bool operator==(const FeatureSpec& other) const { return triplet() == other.triplet() && name() == other.name() && feature() == other.feature(); } bool operator!=(const FeatureSpec& other) const { return !(*this == other); } private: PackageSpec m_spec; std::string m_feature; }; /// /// /// Full specification of a package. Contains all information to reference /// a collection of features in a single package. /// /// struct FullPackageSpec { PackageSpec package_spec; std::vector features; FullPackageSpec() noexcept = default; explicit FullPackageSpec(PackageSpec spec, std::vector features = {}) : package_spec(std::move(spec)), features(std::move(features)) { } std::vector to_feature_specs(const std::vector& default_features, const std::vector& all_features) const; static ExpectedS from_string(const std::string& spec_as_string, Triplet default_triplet); }; /// /// /// Contains all information to reference a collection of features in a single package by their names. /// /// struct Features { std::string name; std::vector features; static ExpectedS from_string(const std::string& input); }; struct Dependency { Features depend; std::string qualifier; static ExpectedS from_string(const std::string& input); }; struct ParsedQualifiedSpecifier { std::string name; Optional> features; Optional triplet; Optional qualifier; }; Optional parse_feature_name(Parse::ParserBase& parser); Optional parse_package_name(Parse::ParserBase& parser); ExpectedS parse_qualified_specifier(CStringView input); Optional parse_qualified_specifier(Parse::ParserBase& parser); bool operator==(const PackageSpec& left, const PackageSpec& right); bool operator!=(const PackageSpec& left, const PackageSpec& right); } namespace std { template<> struct hash { size_t operator()(const vcpkg::PackageSpec& value) const { size_t hash = 17; hash = hash * 31 + std::hash()(value.name()); hash = hash * 31 + std::hash()(value.triplet()); return hash; } }; template<> struct equal_to { bool operator()(const vcpkg::PackageSpec& left, const vcpkg::PackageSpec& right) const { return left == right; } }; template<> struct hash { size_t operator()(const vcpkg::FeatureSpec& value) const { size_t hash = std::hash()(value.spec()); hash = hash * 31 + std::hash()(value.feature()); return hash; } }; template<> struct equal_to { bool operator()(const vcpkg::FeatureSpec& left, const vcpkg::FeatureSpec& right) const { return left == right; } }; }