tools/eupak: Refactor InfoTask to ITask pattern

This commit is contained in:
Lily Tsuru 2025-01-15 19:25:31 -05:00
parent 7fee38be55
commit e30913b018
5 changed files with 78 additions and 30 deletions

View file

@ -25,16 +25,6 @@ int main(int argc, char** argv) {
argparse::ArgumentParser parser("eupak", EUPAK_VERSION_STR); argparse::ArgumentParser parser("eupak", EUPAK_VERSION_STR);
parser.add_description("Eupak (Europa Package Multi-Tool) v" EUPAK_VERSION_STR); parser.add_description("Eupak (Europa Package Multi-Tool) v" EUPAK_VERSION_STR);
argparse::ArgumentParser infoParser("info", EUPAK_VERSION_STR, argparse::default_arguments::help);
infoParser.add_description("Print information about a package file.");
infoParser.add_argument("input")
.help("Input archive")
.metavar("ARCHIVE");
infoParser.add_argument("--verbose")
.help("Increase information output verbosity (print a list of files).")
.default_value(false)
.implicit_value(true);
argparse::ArgumentParser extractParser("extract", EUPAK_VERSION_STR, argparse::default_arguments::help); argparse::ArgumentParser extractParser("extract", EUPAK_VERSION_STR, argparse::default_arguments::help);
extractParser.add_description("Extract a package file."); extractParser.add_description("Extract a package file.");
@ -51,11 +41,11 @@ int main(int argc, char** argv) {
.default_value(false) .default_value(false)
.implicit_value(true); .implicit_value(true);
parser.add_subparser(infoParser);
parser.add_subparser(extractParser); parser.add_subparser(extractParser);
auto tasks = std::vector { auto tasks = std::vector {
eupak::tasks::TaskFactory::CreateNamed("create", parser) eupak::tasks::TaskFactory::CreateNamed("create", parser),
eupak::tasks::TaskFactory::CreateNamed("info", parser)
}; };
try { try {
@ -115,8 +105,6 @@ int main(int argc, char** argv) {
eupak::tasks::InfoTask task; eupak::tasks::InfoTask task;
eupak::tasks::InfoTask::Arguments args; eupak::tasks::InfoTask::Arguments args;
args.verbose = infoParser.get<bool>("--verbose");
args.inputPath = eupak::fs::path(infoParser.get("input"));
return task.Run(std::move(args)); return task.Run(std::move(args));
} }

View file

@ -6,19 +6,63 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
#include <EupakConfig.hpp>
#include <europa/io/PakReader.hpp> #include <europa/io/PakReader.hpp>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <tasks/InfoTask.hpp> #include <tasks/InfoTask.hpp>
#include <Utils.hpp> #include <Utils.hpp>
#include "argparse/argparse.hpp"
#include "europa/structs/Pak.hpp" #include "europa/structs/Pak.hpp"
namespace eupak::tasks { namespace eupak::tasks {
constexpr static auto DATE_FORMAT = "%m/%d/%Y %r"; constexpr static auto DATE_FORMAT = "%m/%d/%Y %r";
int InfoTask::Run(Arguments&& args) { InfoTask::InfoTask()
: parser("info", EUPAK_VERSION_STR, argparse::default_arguments::help) {
// clang-format off
parser
.add_description("Print information about a package file.");
parser
.add_argument("input")
.help("Input archive")
.metavar("ARCHIVE");
// FIXME: Probably just print this always, in a thinner format, but use
// the existing thicker format for verbosity.
parser
.add_argument("--verbose")
.help("Increase information output verbosity (print a list of files).")
.default_value(false)
.implicit_value(true);
// clang-format on
}
void InfoTask::Init(argparse::ArgumentParser& parentParser) {
parentParser.add_subparser(parser);
}
int InfoTask::Parse() {
auto& args = currentArgs;
try {
args.verbose = parser.get<bool>("--verbose");
args.inputPath = eupak::fs::path(parser.get("input"));
} catch(...) {
return 1;
}
return 0;
}
bool InfoTask::ShouldRun(argparse::ArgumentParser& parentParser) const {
return parentParser.is_subcommand_used("info");
}
int InfoTask::Run() {
const auto& args = currentArgs;
std::ifstream ifs(args.inputPath.string(), std::ifstream::binary); std::ifstream ifs(args.inputPath.string(), std::ifstream::binary);
if(!ifs) { if(!ifs) {
@ -72,4 +116,6 @@ namespace eupak::tasks {
return 0; return 0;
} }
EUPAK_REGISTER_TASK("info", InfoTask);
} // namespace eupak::tasks } // namespace eupak::tasks

View file

@ -11,20 +11,31 @@
#include <CommonDefs.hpp> #include <CommonDefs.hpp>
#include "tasks/Task.hpp"
namespace eupak::tasks { namespace eupak::tasks {
struct InfoTask { struct InfoTask : ITask {
struct Arguments { struct Arguments {
fs::path inputPath; fs::path inputPath;
bool verbose; bool verbose;
}; };
InfoTask();
void Init(argparse::ArgumentParser& parentParser) override;
int Run(Arguments&& args); bool ShouldRun(argparse::ArgumentParser& parentParser) const override;
int Parse() override;
int Run() override;
private:
argparse::ArgumentParser parser;
Arguments currentArgs;
}; };
} } // namespace eupak::tasks
#endif // EUROPA_EUPAK_TASKS_INFOTASK_HPP #endif // EUROPA_EUPAK_TASKS_INFOTASK_HPP

View file

@ -1,5 +1,5 @@
#pragma once
#include "Task.hpp" #include "Task.hpp"
#include <stdexcept> #include <stdexcept>
namespace eupak::tasks { namespace eupak::tasks {

View file

@ -32,7 +32,7 @@ namespace eupak::tasks {
virtual int Run() = 0; virtual int Run() = 0;
}; };
/// Creates tasks. /// Creates ITask instances for clients.
struct TaskFactory { struct TaskFactory {
using FactoryMethod = std::shared_ptr<ITask> (*)(); using FactoryMethod = std::shared_ptr<ITask> (*)();
@ -49,6 +49,7 @@ namespace eupak::tasks {
} }
}; };
/// Helper template to register into the [TaskFactory].
template <class T> template <class T>
struct TaskFactoryRegister { struct TaskFactoryRegister {
TaskFactoryRegister(const std::string& name) { TaskFactoryRegister(const std::string& name) {
@ -60,6 +61,8 @@ namespace eupak::tasks {
} }
}; };
/// Registers a task. Should be put in the .cpp implementation source file of the
/// task object itself.
#define EUPAK_REGISTER_TASK(Name, TTask) \ #define EUPAK_REGISTER_TASK(Name, TTask) \
static ::eupak::tasks::TaskFactoryRegister<TTask> __register__##TTask(Name) static ::eupak::tasks::TaskFactoryRegister<TTask> __register__##TTask(Name)