#pragma once // // This file is distributed under the MIT License. See LICENSE.md for details. // #include #include #include #include #include "llvm/ADT/StringRef.h" #include "revng/Pipeline/Container.h" #include "revng/Support/Assert.h" namespace pipeline { class ContainerFactoryBase { public: virtual std::unique_ptr operator()(llvm::StringRef Name) const = 0; virtual llvm::StringRef mimeType() const = 0; virtual std::vector getWrittenFiles(const revng::FilePath &Path) const = 0; virtual ~ContainerFactoryBase() = default; virtual std::unique_ptr clone() const = 0; }; template class ContainerFactoryWithArgs : public ContainerFactoryBase { private: std::tuple GlobalValue; public: ContainerFactoryWithArgs(Args &&...GlobalValue) : GlobalValue(std::make_tuple(std::forward(GlobalValue)...)) {} std::unique_ptr operator()(llvm::StringRef Name) const override { auto Creator = [Name](T &&...Values) { return std::make_unique(Name, std::forward(Values)...); }; return std::apply(Creator, GlobalValue); } llvm::StringRef mimeType() const override { return ContainerT::MIMEType; } std::vector getWrittenFiles(const revng::FilePath &Path) const override { return ContainerT::getWrittenFiles(Path); } std::unique_ptr clone() const override { return std::make_unique(*this); } ContainerFactoryWithArgs(const ContainerFactoryWithArgs &) = default; ContainerFactoryWithArgs(ContainerFactoryWithArgs &&) = default; ContainerFactoryWithArgs &operator=(ContainerFactoryWithArgs &&) = default; ContainerFactoryWithArgs & operator=(const ContainerFactoryWithArgs &) = default; ~ContainerFactoryWithArgs() override = default; }; class ContainerFactory { private: std::unique_ptr Content; ContainerFactory(std::unique_ptr Ptr) : Content(std::move(Ptr)) { revng_assert(Content != nullptr); } public: template static ContainerFactory create() { return ContainerFactory(std::make_unique>()); } template static ContainerFactory fromGlobal(G &&...Vals) { using Factory = ContainerFactoryWithArgs; return ContainerFactory(make_unique(std::forward(Vals)...)); } ContainerFactory(const ContainerFactory &Other) : Content(Other.Content->clone()) { revng_assert(Content != nullptr); } ContainerFactory(ContainerFactory &&Other) = default; ~ContainerFactory() = default; ContainerFactory &operator=(const ContainerFactory &Other) { if (this == &Other) return *this; Content = Other.Content->clone(); return *this; } ContainerFactory &operator=(ContainerFactory &&Other) = default; std::unique_ptr operator()(llvm::StringRef Name) const { return Content->operator()(Name); } llvm::StringRef mimeType() const { return Content->mimeType(); } std::vector getWrittenFiles(const revng::FilePath &Path) const { return Content->getWrittenFiles(Path); } }; } // namespace pipeline