[Base] Move Factory class to xenia-base
This commit is contained in:
parent
4689d26967
commit
72ae10dc2b
|
@ -0,0 +1,98 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_BASE_FACTORY_H_
|
||||||
|
#define XENIA_BASE_FACTORY_H_
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
class Factory {
|
||||||
|
private:
|
||||||
|
struct Creator {
|
||||||
|
std::string name;
|
||||||
|
std::function<bool()> is_available;
|
||||||
|
std::function<std::unique_ptr<T>(Args...)> instantiate;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<Creator> creators_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Add(const std::string_view name, std::function<bool()> is_available,
|
||||||
|
std::function<std::unique_ptr<T>(Args...)> instantiate) {
|
||||||
|
creators_.push_back({std::string(name), is_available, instantiate});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Add(const std::string_view name,
|
||||||
|
std::function<std::unique_ptr<T>(Args...)> instantiate) {
|
||||||
|
auto always_available = []() { return true; };
|
||||||
|
Add(name, always_available, instantiate);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename DT>
|
||||||
|
void Add(const std::string_view name) {
|
||||||
|
Add(name, DT::IsAvailable, [](Args... args) {
|
||||||
|
return std::make_unique<DT>(std::forward<Args>(args)...);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<T> Create(const std::string_view name, Args... args) {
|
||||||
|
if (!name.empty() && name != "any") {
|
||||||
|
auto it = std::find_if(
|
||||||
|
creators_.cbegin(), creators_.cend(),
|
||||||
|
[&name](const auto& f) { return name.compare(f.name) == 0; });
|
||||||
|
if (it != creators_.cend() && (*it).is_available()) {
|
||||||
|
return (*it).instantiate(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
} else {
|
||||||
|
for (const auto& creator : creators_) {
|
||||||
|
if (!creator.is_available()) continue;
|
||||||
|
auto instance = creator.instantiate(std::forward<Args>(args)...);
|
||||||
|
if (!instance) continue;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<T>> CreateAll(const std::string_view name,
|
||||||
|
Args... args) {
|
||||||
|
std::vector<std::unique_ptr<T>> instances;
|
||||||
|
if (!name.empty() && name != "any") {
|
||||||
|
auto it = std::find_if(
|
||||||
|
creators_.cbegin(), creators_.cend(),
|
||||||
|
[&name](const auto& f) { return name.compare(f.name) == 0; });
|
||||||
|
if (it != creators_.cend() && (*it).is_available()) {
|
||||||
|
auto instance = (*it).instantiate(std::forward<Args>(args)...);
|
||||||
|
if (instance) {
|
||||||
|
instances.emplace_back(std::move(instance));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const auto& creator : creators_) {
|
||||||
|
if (!creator.is_available()) continue;
|
||||||
|
auto instance = creator.instantiate(std::forward<Args>(args)...);
|
||||||
|
if (instance) {
|
||||||
|
instances.emplace_back(std::move(instance));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instances;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue