File indexing completed on 2025-01-05 04:01:22
0001 /* 0002 * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best> 0003 * 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include "base.hpp" 0010 #include "mime/mime_serializer.hpp" 0011 0012 namespace glaxnimate::io { 0013 0014 namespace detail { 0015 0016 inline bool compare_ie_ptr(const ImportExport* ptr_a, const ImportExport* ptr_b) noexcept 0017 { 0018 return ptr_a->priority() > ptr_b->priority(); 0019 } 0020 0021 inline bool compare_ie_unique_ptr(const std::unique_ptr<ImportExport>& ptr_a, const std::unique_ptr<ImportExport>& ptr_b) noexcept 0022 { 0023 return compare_ie_ptr(ptr_a.get(), ptr_b.get()); 0024 } 0025 0026 } // namespace detail 0027 0028 class IoRegistry 0029 { 0030 public: 0031 static IoRegistry& instance() 0032 { 0033 static IoRegistry factory; 0034 return factory; 0035 } 0036 0037 ImportExport* register_object(std::unique_ptr<ImportExport> ie) 0038 { 0039 using namespace detail; 0040 auto iter = std::upper_bound(object_list.begin(), object_list.end(), ie, &compare_ie_unique_ptr); 0041 ImportExport* format = ie.get(); 0042 object_list.insert(iter, std::move(ie)); 0043 if ( format->can_save() ) 0044 exporters_.insert(std::upper_bound(exporters_.begin(), exporters_.end(), format, &compare_ie_ptr), format); 0045 if ( format->can_open() ) 0046 importers_.insert(std::upper_bound(importers_.begin(), importers_.end(), format, &compare_ie_ptr), format); 0047 return format; 0048 } 0049 0050 void unregister(ImportExport* object) 0051 { 0052 for ( auto it = object_list.begin(); it != object_list.end(); ++it ) 0053 { 0054 if ( it->get() == object ) 0055 { 0056 object_list.erase(it); 0057 break; 0058 } 0059 } 0060 importers_.erase(std::remove(importers_.begin(), importers_.end(), object), importers_.end()); 0061 exporters_.erase(std::remove(exporters_.begin(), exporters_.end(), object), exporters_.end()); 0062 } 0063 0064 mime::MimeSerializer* register_object(std::unique_ptr<mime::MimeSerializer> ie) 0065 { 0066 mime_list.push_back(std::move(ie)); 0067 mime::MimeSerializer* format = mime_list.back().get(); 0068 mime_pointers.push_back(format); 0069 return format; 0070 } 0071 0072 const std::vector<ImportExport*>& importers() const { return importers_; } 0073 const std::vector<ImportExport*>& exporters() const { return exporters_; } 0074 const std::vector<mime::MimeSerializer*>& serializers() const { return mime_pointers; } 0075 0076 const std::vector<std::unique_ptr<ImportExport>>& registered() const 0077 { 0078 return object_list; 0079 } 0080 0081 ImportExport* from_extension(const QString& extension, ImportExport::Direction direction) const 0082 { 0083 int top_priority = std::numeric_limits<int>::min(); 0084 ImportExport* best = nullptr; 0085 for ( const auto& p : object_list ) 0086 { 0087 if ( p->can_handle_extension(extension, direction) && p->priority() > top_priority ) 0088 { 0089 best = p.get(); 0090 top_priority = p->priority(); 0091 } 0092 } 0093 0094 return best; 0095 } 0096 0097 ImportExport* from_filename(const QString& filename, ImportExport::Direction direction) const 0098 { 0099 int top_priority = std::numeric_limits<int>::min(); 0100 ImportExport* best = nullptr; 0101 0102 for ( const auto& p : object_list ) 0103 { 0104 if ( p->can_handle_filename(filename, direction) && p->priority() > top_priority ) 0105 { 0106 best = p.get(); 0107 top_priority = p->priority(); 0108 } 0109 } 0110 0111 return best; 0112 } 0113 0114 ImportExport* from_slug(const QString& slug) const 0115 { 0116 for ( const auto& p : object_list ) 0117 if ( p->slug() == slug ) 0118 return p.get(); 0119 0120 return nullptr; 0121 } 0122 0123 mime::MimeSerializer* serializer_from_slug(const QString& slug) const 0124 { 0125 for ( const auto& serializer : mime_list ) 0126 { 0127 if ( serializer->slug() == slug ) 0128 return serializer.get(); 0129 } 0130 0131 return nullptr; 0132 } 0133 0134 private: 0135 std::vector<std::unique_ptr<ImportExport>> object_list; 0136 std::vector<ImportExport*> importers_; 0137 std::vector<ImportExport*> exporters_; 0138 std::vector<std::unique_ptr<mime::MimeSerializer>> mime_list; 0139 std::vector<mime::MimeSerializer*> mime_pointers; 0140 0141 IoRegistry() = default; 0142 ~IoRegistry() = default; 0143 }; 0144 0145 0146 template<class Derived> 0147 class Autoreg 0148 { 0149 public: 0150 template<class... Args> 0151 Autoreg(Args&&... args) 0152 : registered { static_cast<Derived*>( 0153 IoRegistry::instance().register_object(std::make_unique<Derived>(std::forward<Args>(args)...)) 0154 ) } {} 0155 0156 Derived* const registered; 0157 }; 0158 0159 } // namespace glaxnimate::io