11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
22PROMEKI_NAMESPACE_BEGIN
51template <
typename Product>
class FileFormatFactory {
63 IODevice *device =
nullptr;
71 static int registerFactory(FileFormatFactory *factory) {
72 if (factory ==
nullptr)
return -1;
73 auto &list = factoryList();
74 int ret = list.size();
75 promekiLog(Logger::LogLevel::Debug,
"Registered FileFormatFactory %s", factory->name().cstr());
79 list.pushToBack(UniquePtr<FileFormatFactory>::takeOwnership(factory));
91 static const FileFormatFactory *lookup(
const Context &ctx) {
92 auto &list = factoryList();
93 for (
const auto &f : list) {
94 if (f->canDoOperation(ctx))
return f.get();
100 FileFormatFactory() =
default;
103 virtual ~FileFormatFactory() {}
109 String name()
const {
return _name; }
115 const StringList &extensions()
const {
return _exts; }
122 bool isExtensionSupported(
const String &filename)
const {
123 size_t dot = filename.rfind(
'.');
124 if (dot == String::npos || dot + 1 >= filename.size())
return false;
125 String ext = filename.mid(dot + 1).toLower();
126 for (
const auto &item : _exts) {
127 if (ext == item)
return true;
137 bool isHintSupported(
const String &hint)
const {
138 String lower = hint.toLower();
139 for (
const auto &item : _exts) {
140 if (lower == item)
return true;
153 virtual bool canDoOperation(
const Context &ctx)
const {
return false; }
162 virtual Result<Product> createForOperation(
const Context &ctx)
const {
163 return makeError<Product>(Error::NotImplemented);
171 static List<UniquePtr<FileFormatFactory>> &factoryList() {
172 static List<UniquePtr<FileFormatFactory>> list;
182#define PROMEKI_REGISTER_FILE_FORMAT_FACTORY(product, name) \
183 [[maybe_unused]] static int PROMEKI_CONCAT(__promeki_fff_, PROMEKI_UNIQUE_ID) = \
184 FileFormatFactory<product>::registerFactory(new name);