From 97d06fb9d6514c4c8a3e68c43f825789f0448ce8 Mon Sep 17 00:00:00 2001 From: rr- Date: Thu, 3 Sep 2015 22:44:03 +0200 Subject: [PATCH] util: introduce PluginManger Managing --plugin option was similar across all the implementations (there were 3 decoders that used this option), so I extracted a class that shares common code. --- src/fmt/ivory/mbl_archive.cc | 51 ++++++++------- src/fmt/kirikiri/xp3_archive.cc | 34 ++++++++-- src/fmt/kirikiri/xp3_filter_factory.cc | 91 -------------------------- src/fmt/kirikiri/xp3_filter_factory.h | 23 ------- src/fmt/nitroplus/npa_archive.cc | 33 ++++------ src/util/plugin_mgr.hh | 72 ++++++++++++++++++++ 6 files changed, 139 insertions(+), 165 deletions(-) delete mode 100644 src/fmt/kirikiri/xp3_filter_factory.cc delete mode 100644 src/fmt/kirikiri/xp3_filter_factory.h create mode 100644 src/util/plugin_mgr.hh diff --git a/src/fmt/ivory/mbl_archive.cc b/src/fmt/ivory/mbl_archive.cc index 58a3ae494..e44181f5c 100644 --- a/src/fmt/ivory/mbl_archive.cc +++ b/src/fmt/ivory/mbl_archive.cc @@ -14,6 +14,7 @@ #include "fmt/ivory/wady_converter.h" #include "util/encoding.h" #include "util/format.h" +#include "util/plugin_mgr.hh" #include "util/range.h" #include "log.h" @@ -100,10 +101,10 @@ static std::unique_ptr read_file( struct MblArchive::Priv { + util::PluginManager plugin_mgr; PrsConverter prs_converter; WadyConverter wady_converter; PluginFunc plugin; - PluginTable all_plugins; }; MblArchive::MblArchive() : p(new Priv) @@ -111,24 +112,30 @@ MblArchive::MblArchive() : p(new Priv) add_transformer(&p->prs_converter); add_transformer(&p->wady_converter); - p->all_plugins["candy"] = [](bstr &data) + p->plugin_mgr.add("noop", "Unencrypted games", []() { - for (auto i : util::range(data.size())) - data[i] = -data[i]; - }; + return [](bstr &) { }; + }); - p->all_plugins["wanko"] = [](bstr &data) + p->plugin_mgr.add("candy", "Candy Toys", []() { - static const bstr key = - "\x82\xED\x82\xF1\x82\xB1" - "\x88\xC3\x8D\x86\x89\xBB"_b; - for (auto i : util::range(data.size())) - data[i] ^= key[i % key.size()]; - }; - - p->all_plugins["noop"] = [](bstr &) + return [](bstr &data) + { + for (auto i : util::range(data.size())) + data[i] = -data[i]; + }; + }); + + p->plugin_mgr.add("wanko", "Wanko to Kurasou", []() { - }; + return [](bstr &data) + { + static const bstr key = + "\x82\xED\x82\xF1\x82\xB1\x88\xC3\x8D\x86\x89\xBB"_b; + for (auto i : util::range(data.size())) + data[i] ^= key[i % key.size()]; + }; + }); } MblArchive::~MblArchive() @@ -137,26 +144,20 @@ MblArchive::~MblArchive() void MblArchive::register_cli_options(ArgParser &arg_parser) const { - auto sw = arg_parser.register_switch({"-p", "--plugin"}) - ->set_value_name("PLUGIN") - ->set_description("Specifies plugin for decoding dialog files."); - for (auto &it : p->all_plugins) - sw->add_possible_value(it.first); + p->plugin_mgr.register_cli_options( + arg_parser, "Specifies plugin for decoding dialog files."); Archive::register_cli_options(arg_parser); } void MblArchive::parse_cli_options(const ArgParser &arg_parser) { - if (arg_parser.has_switch("--plugin")) - set_plugin(arg_parser.get_switch("--plugin")); + p->plugin = p->plugin_mgr.get_from_cli_options(arg_parser, false); Archive::parse_cli_options(arg_parser); } void MblArchive::set_plugin(const std::string &plugin_name) { - if (p->all_plugins.find(plugin_name) == p->all_plugins.end()) - throw std::runtime_error("Unknown plugin: " + plugin_name); - p->plugin = p->all_plugins[plugin_name]; + p->plugin = p->plugin_mgr.get_from_string(plugin_name); } bool MblArchive::is_recognized_internal(File &arc_file) const diff --git a/src/fmt/kirikiri/xp3_archive.cc b/src/fmt/kirikiri/xp3_archive.cc index e8ee43542..b6d79cba3 100644 --- a/src/fmt/kirikiri/xp3_archive.cc +++ b/src/fmt/kirikiri/xp3_archive.cc @@ -17,10 +17,15 @@ #include "fmt/kirikiri/tlg_converter.h" #include "fmt/kirikiri/xp3_archive.h" -#include "fmt/kirikiri/xp3_filter_factory.h" +#include "fmt/kirikiri/xp3_filters/cxdec_comyu.h" +#include "fmt/kirikiri/xp3_filters/cxdec_fha.h" +#include "fmt/kirikiri/xp3_filters/cxdec_mahoyoru.h" +#include "fmt/kirikiri/xp3_filters/fsn.h" +#include "fmt/kirikiri/xp3_filters/noop.h" #include "io/buffered_io.h" #include "util/encoding.h" #include "util/pack/zlib.h" +#include "util/plugin_mgr.hh" using namespace au; using namespace au::fmt::kirikiri; @@ -31,6 +36,11 @@ static const bstr adlr_magic = "adlr"_b; static const bstr info_magic = "info"_b; static const bstr segm_magic = "segm"_b; +namespace +{ + using FilterPtr = std::unique_ptr; +} + static int detect_version(io::IO &arc_io) { int version = 1; @@ -163,7 +173,7 @@ static std::unique_ptr read_file( struct Xp3Archive::Priv { - Xp3FilterFactory filter_factory; + util::PluginManager plugin_mgr; TlgConverter tlg_converter; std::unique_ptr filter; @@ -175,6 +185,21 @@ struct Xp3Archive::Priv Xp3Archive::Xp3Archive() : p(new Priv) { add_transformer(&p->tlg_converter); + + p->plugin_mgr.add("noop", "Unecrypted games", + []() { return FilterPtr(new xp3_filters::Noop); }); + + p->plugin_mgr.add("comyu", "Comyu - Kuroi Ryuu to Yasashii Oukoku", + []() { return FilterPtr(new xp3_filters::CxdecComyu); }); + + p->plugin_mgr.add("fsn", "Fate/Stay Night", + []() { return FilterPtr(new xp3_filters::Fsn); }); + + p->plugin_mgr.add("fha", "Fate/Hollow Ataraxia", + []() { return FilterPtr(new xp3_filters::CxdecFha); }); + + p->plugin_mgr.add("mahoyoru", "Mahou Tsukai no Yoru", + []() { return FilterPtr(new xp3_filters::CxdecMahoYoru); }); } Xp3Archive::~Xp3Archive() @@ -183,13 +208,14 @@ Xp3Archive::~Xp3Archive() void Xp3Archive::register_cli_options(ArgParser &arg_parser) const { - p->filter_factory.register_cli_options(arg_parser); + p->plugin_mgr.register_cli_options( + arg_parser, "Selects XP3 decryption routine."); Archive::register_cli_options(arg_parser); } void Xp3Archive::parse_cli_options(const ArgParser &arg_parser) { - p->filter = p->filter_factory.get_filter_from_cli_options(arg_parser); + p->filter = p->plugin_mgr.get_from_cli_options(arg_parser, true); Archive::parse_cli_options(arg_parser); } diff --git a/src/fmt/kirikiri/xp3_filter_factory.cc b/src/fmt/kirikiri/xp3_filter_factory.cc deleted file mode 100644 index effb1167f..000000000 --- a/src/fmt/kirikiri/xp3_filter_factory.cc +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include -#include -#include "fmt/kirikiri/xp3_filter_factory.h" -#include "fmt/kirikiri/xp3_filters/cxdec_comyu.h" -#include "fmt/kirikiri/xp3_filters/cxdec_fha.h" -#include "fmt/kirikiri/xp3_filters/cxdec_mahoyoru.h" -#include "fmt/kirikiri/xp3_filters/fsn.h" -#include "fmt/kirikiri/xp3_filters/noop.h" - -using namespace au::fmt::kirikiri; - -namespace -{ - struct Definition - { - std::string name; - std::string description; - std::function creator; - }; -} - -struct Xp3FilterFactory::Priv -{ - std::vector definitions; - - void add( - const std::string &name, - const std::string &description, - std::function creator) - { - struct Definition d; - d.name = name; - d.description = description; - d.creator = creator; - definitions.push_back(d); - } -}; - -Xp3FilterFactory::Xp3FilterFactory() : p(new Priv) -{ - p->add( - "noop", - "Unecrypted games", - []() { return new xp3_filters::Noop; }); - - p->add( - "comyu", - "Comyu - Kuroi Ryuu to Yasashii Oukoku", - []() { return new xp3_filters::CxdecComyu; }); - - p->add( - "fsn", - "Fate/Stay Night", - []() { return new xp3_filters::Fsn; }); - - p->add( - "fha", - "Fate/Hollow Ataraxia", - []() { return new xp3_filters::CxdecFha; }); - - p->add( - "mahoyoru", - "Mahou Tsukai no Yoru", - []() { return new xp3_filters::CxdecMahoYoru; }); -} - -Xp3FilterFactory::~Xp3FilterFactory() -{ -} - -void Xp3FilterFactory::register_cli_options(ArgParser &arg_parser) -{ - auto sw = arg_parser.register_switch({"-p", "--plugin"}) - ->set_value_name("PLUGIN") - ->set_description("Selects XP3 decryption routine."); - for (auto &definition : p->definitions) - sw->add_possible_value(definition.name, definition.description); -} - -std::unique_ptr Xp3FilterFactory::get_filter_from_cli_options( - const ArgParser &arg_parser) -{ - if (!arg_parser.has_switch("plugin")) - throw std::runtime_error("Plugin not specified"); - const std::string plugin = arg_parser.get_switch("plugin"); - for (auto &definition : p->definitions) - if (definition.name == plugin) - return std::unique_ptr(definition.creator()); - throw std::runtime_error("Unrecognized plugin: " + plugin); -} diff --git a/src/fmt/kirikiri/xp3_filter_factory.h b/src/fmt/kirikiri/xp3_filter_factory.h deleted file mode 100644 index 5ca692fc0..000000000 --- a/src/fmt/kirikiri/xp3_filter_factory.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "fmt/kirikiri/xp3_filter.h" -#include "arg_parser.h" - -namespace au { -namespace fmt { -namespace kirikiri { - - class Xp3FilterFactory final - { - public: - Xp3FilterFactory(); - ~Xp3FilterFactory(); - void register_cli_options(ArgParser &arg_parser); - std::unique_ptr get_filter_from_cli_options( - const ArgParser &arg_parser); - private: - struct Priv; - std::unique_ptr p; - }; - -} } } diff --git a/src/fmt/nitroplus/npa_archive.cc b/src/fmt/nitroplus/npa_archive.cc index 899b92c55..a9c552389 100644 --- a/src/fmt/nitroplus/npa_archive.cc +++ b/src/fmt/nitroplus/npa_archive.cc @@ -11,6 +11,7 @@ #include "fmt/nitroplus/npa_filters/chaos_head.h" #include "util/encoding.h" #include "util/pack/zlib.h" +#include "util/plugin_mgr.hh" #include "util/range.h" using namespace au; @@ -174,11 +175,18 @@ static std::unique_ptr read_file( struct NpaArchive::Priv { + util::PluginManager> plugin_mgr; std::unique_ptr filter; }; NpaArchive::NpaArchive() : p(new Priv) { + p->plugin_mgr.add("chaos_head", "ChaoS;HEAd", []() + { + std::unique_ptr filter(new NpaFilter); + npa_filters::chaos_head_filter_init(*filter); + return filter; + }); } NpaArchive::~NpaArchive() @@ -187,33 +195,14 @@ NpaArchive::~NpaArchive() void NpaArchive::register_cli_options(ArgParser &arg_parser) const { - arg_parser.register_switch({"-p", "--plugin"}) - ->set_value_name("PLUGIN") - ->set_description("Selects NPA decryption routine.") - ->add_possible_value("chaos_head"); - + p->plugin_mgr.register_cli_options( + arg_parser, "Selects NPA decryption routine."); Archive::register_cli_options(arg_parser); } void NpaArchive::parse_cli_options(const ArgParser &arg_parser) { - const std::string plugin = arg_parser.get_switch("plugin").c_str(); - void (*initializer)(NpaFilter&) = nullptr; - if (plugin == "chaos_head") - initializer = &npa_filters::chaos_head_filter_init; - else - throw std::runtime_error("Unrecognized plugin: " + plugin); - - if (initializer != nullptr) - { - p->filter.reset(new NpaFilter); - initializer(*p->filter); - } - else - { - p->filter.reset(nullptr); - } - + p->filter = p->plugin_mgr.get_from_cli_options(arg_parser, true); Archive::parse_cli_options(arg_parser); } diff --git a/src/util/plugin_mgr.hh b/src/util/plugin_mgr.hh new file mode 100644 index 000000000..d82d28301 --- /dev/null +++ b/src/util/plugin_mgr.hh @@ -0,0 +1,72 @@ +#pragma once + +#include +#include "arg_parser.h" + +namespace au { +namespace util { + + template struct PluginDefinition + { + std::string name; + std::string description; + std::function factory; + }; + + template class PluginManager final + { + public: + PluginManager() + { + } + + ~PluginManager() + { + } + + void add( + const std::string &name, + const std::string &description, + std::function factory) + { + PluginDefinition d; + d.name = name; + d.description = description; + d.factory = factory; + definitions.push_back(d); + } + + void register_cli_options( + ArgParser &arg_parser, const std::string &description) + { + auto sw = arg_parser.register_switch({"-p", "--plugin"}) + ->set_value_name("PLUGIN") + ->set_description(description); + for (auto &def : definitions) + sw->add_possible_value(def.name, def.description); + } + + T get_from_string(const std::string &plugin) + { + for (const auto &definition : definitions) + if (definition.name == plugin) + return definition.factory(); + throw std::runtime_error("Unrecognized plugin: " + plugin); + } + + T get_from_cli_options(const ArgParser &arg_parser, bool mandatory) + { + if (!arg_parser.has_switch("plugin")) + { + if (mandatory) + throw std::runtime_error("Plugin not specified"); + return nullptr; + } + return get_from_string(arg_parser.get_switch("plugin")); + } + + private: + std::vector> definitions; + }; + +} }