mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 08:05:45 +00:00
add linker basis
This commit is contained in:
parent
39a1485be6
commit
e6a91c0305
@ -38,9 +38,15 @@ function Linker:project()
|
|||||||
|
|
||||||
self:include(includes)
|
self:include(includes)
|
||||||
Utils:include(includes)
|
Utils:include(includes)
|
||||||
|
ZoneLoading:include(includes)
|
||||||
|
ObjLoading:include(includes)
|
||||||
|
ObjWriting:include(includes)
|
||||||
ZoneWriting:include(includes)
|
ZoneWriting:include(includes)
|
||||||
|
|
||||||
links:linkto(Utils)
|
links:linkto(Utils)
|
||||||
--links:linkto(ZoneWriting)
|
links:linkto(ZoneLoading)
|
||||||
|
links:linkto(ZoneWriting)
|
||||||
|
links:linkto(ObjLoading)
|
||||||
|
links:linkto(ObjWriting)
|
||||||
links:linkall()
|
links:linkall()
|
||||||
end
|
end
|
||||||
|
224
src/Linker/Linker.cpp
Normal file
224
src/Linker/Linker.cpp
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
#include "Linker.h"
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <regex>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "Utils/ClassUtils.h"
|
||||||
|
#include "Utils/Arguments/ArgumentParser.h"
|
||||||
|
#include "ZoneLoading.h"
|
||||||
|
#include "ObjWriting.h"
|
||||||
|
#include "ObjLoading.h"
|
||||||
|
#include "SearchPath/SearchPaths.h"
|
||||||
|
#include "SearchPath/SearchPathFilesystem.h"
|
||||||
|
#include "ObjContainer/IWD/IWD.h"
|
||||||
|
#include "LinkerArgs.h"
|
||||||
|
|
||||||
|
#include "Utils/ObjFileStream.h"
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
class Linker::Impl
|
||||||
|
{
|
||||||
|
LinkerArgs m_args;
|
||||||
|
SearchPaths m_search_paths;
|
||||||
|
SearchPathFilesystem* m_last_zone_search_path;
|
||||||
|
std::set<std::string> m_absolute_search_paths;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Loads a search path.
|
||||||
|
* \param searchPath The search path to load.
|
||||||
|
*/
|
||||||
|
void LoadSearchPath(ISearchPath* searchPath) const
|
||||||
|
{
|
||||||
|
if (m_args.m_verbose)
|
||||||
|
{
|
||||||
|
printf("Loading search path: \"%s\"\n", searchPath->GetPath().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjLoading::LoadIWDsInSearchPath(searchPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Unloads a search path.
|
||||||
|
* \param searchPath The search path to unload.
|
||||||
|
*/
|
||||||
|
void UnloadSearchPath(ISearchPath* searchPath) const
|
||||||
|
{
|
||||||
|
if (m_args.m_verbose)
|
||||||
|
{
|
||||||
|
printf("Unloading search path: \"%s\"\n", searchPath->GetPath().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjLoading::UnloadIWDsInSearchPath(searchPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Loads all search paths that are valid for the specified zone and returns them.
|
||||||
|
* \param zonePath The path to the zone file that should be prepared for.
|
||||||
|
* \return A \c SearchPaths object that contains all search paths that should be considered when loading the specified zone.
|
||||||
|
*/
|
||||||
|
SearchPaths GetSearchPathsForZone(const std::string& zonePath)
|
||||||
|
{
|
||||||
|
SearchPaths searchPathsForZone;
|
||||||
|
const auto absoluteZoneDirectory = fs::absolute(std::filesystem::path(zonePath).remove_filename()).string();
|
||||||
|
|
||||||
|
if (m_last_zone_search_path != nullptr && m_last_zone_search_path->GetPath() == absoluteZoneDirectory)
|
||||||
|
{
|
||||||
|
searchPathsForZone.IncludeSearchPath(m_last_zone_search_path);
|
||||||
|
}
|
||||||
|
else if (m_absolute_search_paths.find(absoluteZoneDirectory) == m_absolute_search_paths.end())
|
||||||
|
{
|
||||||
|
if (m_last_zone_search_path != nullptr)
|
||||||
|
{
|
||||||
|
UnloadSearchPath(m_last_zone_search_path);
|
||||||
|
delete m_last_zone_search_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_last_zone_search_path = new SearchPathFilesystem(absoluteZoneDirectory);
|
||||||
|
searchPathsForZone.IncludeSearchPath(m_last_zone_search_path);
|
||||||
|
LoadSearchPath(m_last_zone_search_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto* iwd : IWD::Repository)
|
||||||
|
{
|
||||||
|
searchPathsForZone.IncludeSearchPath(iwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return searchPathsForZone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initializes the Linker object's search paths based on the user's input.
|
||||||
|
* \return \c true if building the search paths was successful, otherwise \c false.
|
||||||
|
*/
|
||||||
|
bool BuildSearchPaths()
|
||||||
|
{
|
||||||
|
for (const auto& path : m_args.m_user_search_paths)
|
||||||
|
{
|
||||||
|
auto absolutePath = fs::absolute(path);
|
||||||
|
|
||||||
|
if (!fs::is_directory(absolutePath))
|
||||||
|
{
|
||||||
|
printf("Could not find directory of search path: \"%s\"\n", path.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto searchPath = std::make_unique<SearchPathFilesystem>(absolutePath.string());
|
||||||
|
LoadSearchPath(searchPath.get());
|
||||||
|
m_search_paths.CommitSearchPath(std::move(searchPath));
|
||||||
|
|
||||||
|
m_absolute_search_paths.insert(absolutePath.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_args.m_verbose)
|
||||||
|
{
|
||||||
|
printf("%u SearchPaths%s\n", m_absolute_search_paths.size(), !m_absolute_search_paths.empty() ? ":" : "");
|
||||||
|
for (const auto& absoluteSearchPath : m_absolute_search_paths)
|
||||||
|
{
|
||||||
|
printf(" \"%s\"\n", absoluteSearchPath.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_absolute_search_paths.empty())
|
||||||
|
{
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Performs the tasks specified by the command line arguments on the specified zone.
|
||||||
|
* \param zone The zone to handle.
|
||||||
|
* \return \c true if handling the zone was successful, otherwise \c false.
|
||||||
|
*/
|
||||||
|
bool BuildZone(const std::string& zoneName) const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Impl()
|
||||||
|
{
|
||||||
|
m_last_zone_search_path = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \copydoc Linker::Start
|
||||||
|
*/
|
||||||
|
bool Start(const int argc, const char** argv)
|
||||||
|
{
|
||||||
|
if (!m_args.ParseArgs(argc, argv))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!BuildSearchPaths())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<Zone>> zones;
|
||||||
|
|
||||||
|
for (const auto& zonePath : m_args.m_zones_to_load)
|
||||||
|
{
|
||||||
|
if (!fs::is_regular_file(zonePath))
|
||||||
|
{
|
||||||
|
printf("Could not find file \"%s\".\n", zonePath.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto absoluteZoneDirectory = absolute(std::filesystem::path(zonePath).remove_filename()).string();
|
||||||
|
|
||||||
|
auto searchPathsForZone = GetSearchPathsForZone(absoluteZoneDirectory);
|
||||||
|
searchPathsForZone.IncludeSearchPath(&m_search_paths);
|
||||||
|
|
||||||
|
auto zone = std::unique_ptr<Zone>(ZoneLoading::LoadZone(zonePath));
|
||||||
|
if (zone == nullptr)
|
||||||
|
{
|
||||||
|
printf("Failed to load zone \"%s\".\n", zonePath.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_args.m_verbose)
|
||||||
|
{
|
||||||
|
printf("Loaded zone \"%s\"\n", zone->m_name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjLoading::LoadReferencedContainersForZone(&searchPathsForZone, zone.get());
|
||||||
|
ObjLoading::LoadObjDataForZone(&searchPathsForZone, zone.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = true;
|
||||||
|
for(const auto& zone : m_args.m_zones_to_build)
|
||||||
|
{
|
||||||
|
if (!BuildZone(zone))
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const auto& zone : zones)
|
||||||
|
{
|
||||||
|
ObjLoading::UnloadContainersOfZone(zone.get());
|
||||||
|
}
|
||||||
|
zones.clear();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Linker::Linker()
|
||||||
|
{
|
||||||
|
m_impl = new Impl();
|
||||||
|
}
|
||||||
|
|
||||||
|
Linker::~Linker()
|
||||||
|
{
|
||||||
|
delete m_impl;
|
||||||
|
m_impl = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Linker::Start(const int argc, const char** argv) const
|
||||||
|
{
|
||||||
|
return m_impl->Start(argc, argv);
|
||||||
|
}
|
24
src/Linker/Linker.h
Normal file
24
src/Linker/Linker.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class Linker
|
||||||
|
{
|
||||||
|
class Impl;
|
||||||
|
Impl* m_impl;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Linker();
|
||||||
|
~Linker();
|
||||||
|
|
||||||
|
Linker(const Linker& other) = delete;
|
||||||
|
Linker(Linker&& other) noexcept = delete;
|
||||||
|
Linker& operator=(const Linker& other) = delete;
|
||||||
|
Linker& operator=(Linker&& other) noexcept = delete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Starts the Linker application logic.
|
||||||
|
* \param argc The amount of command line arguments specified.
|
||||||
|
* \param argv The command line arguments.
|
||||||
|
* \return \c true if the application was successful or \c false if an error occurred.
|
||||||
|
*/
|
||||||
|
bool Start(int argc, const char** argv) const;
|
||||||
|
};
|
133
src/Linker/LinkerArgs.cpp
Normal file
133
src/Linker/LinkerArgs.cpp
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
#include "LinkerArgs.h"
|
||||||
|
|
||||||
|
#include <regex>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "Utils/Arguments/UsageInformation.h"
|
||||||
|
#include "ObjLoading.h"
|
||||||
|
#include "ObjWriting.h"
|
||||||
|
#include "Utils/FileUtils.h"
|
||||||
|
|
||||||
|
const CommandLineOption* const OPTION_HELP =
|
||||||
|
CommandLineOption::Builder::Create()
|
||||||
|
.WithShortName("?")
|
||||||
|
.WithLongName("help")
|
||||||
|
.WithDescription("Displays usage information.")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
const CommandLineOption* const OPTION_VERBOSE =
|
||||||
|
CommandLineOption::Builder::Create()
|
||||||
|
.WithShortName("v")
|
||||||
|
.WithLongName("verbose")
|
||||||
|
.WithDescription("Outputs a lot more and more detailed messages.")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
const CommandLineOption* const OPTION_OUTPUT_FOLDER =
|
||||||
|
CommandLineOption::Builder::Create()
|
||||||
|
.WithShortName("o")
|
||||||
|
.WithLongName("output-folder")
|
||||||
|
.WithDescription("Specifies the output folder containing the contents of the unlinked zones. Defaults to ./%zoneName%")
|
||||||
|
.WithParameter("outputFolderPath")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
const CommandLineOption* const OPTION_SEARCH_PATH =
|
||||||
|
CommandLineOption::Builder::Create()
|
||||||
|
.WithLongName("search-path")
|
||||||
|
.WithDescription("Specifies a semi-colon separated list of paths to search for additional game files.")
|
||||||
|
.WithParameter("searchPathString")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
const CommandLineOption* const OPTION_LOAD =
|
||||||
|
CommandLineOption::Builder::Create()
|
||||||
|
.WithShortName("l")
|
||||||
|
.WithLongName("load")
|
||||||
|
.WithDescription("Loads an existing zone to be able to use its assets when building.")
|
||||||
|
.WithParameter("zonePath")
|
||||||
|
.Reusable()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
const CommandLineOption* const COMMAND_LINE_OPTIONS[]
|
||||||
|
{
|
||||||
|
OPTION_HELP,
|
||||||
|
OPTION_VERBOSE,
|
||||||
|
OPTION_OUTPUT_FOLDER,
|
||||||
|
OPTION_SEARCH_PATH,
|
||||||
|
OPTION_LOAD
|
||||||
|
};
|
||||||
|
|
||||||
|
LinkerArgs::LinkerArgs()
|
||||||
|
: m_argument_parser(COMMAND_LINE_OPTIONS, std::extent<decltype(COMMAND_LINE_OPTIONS)>::value),
|
||||||
|
m_output_folder("zone_out/%zoneName%"),
|
||||||
|
m_verbose(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinkerArgs::PrintUsage()
|
||||||
|
{
|
||||||
|
UsageInformation usage("Linker.exe");
|
||||||
|
|
||||||
|
for (const auto* commandLineOption : COMMAND_LINE_OPTIONS)
|
||||||
|
{
|
||||||
|
usage.AddCommandLineOption(commandLineOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
usage.AddArgument("zoneName");
|
||||||
|
usage.SetVariableArguments(true);
|
||||||
|
|
||||||
|
usage.Print();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinkerArgs::SetVerbose(const bool isVerbose)
|
||||||
|
{
|
||||||
|
m_verbose = isVerbose;
|
||||||
|
ObjLoading::Configuration.Verbose = isVerbose;
|
||||||
|
ObjWriting::Configuration.Verbose = isVerbose;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LinkerArgs::ParseArgs(const int argc, const char** argv)
|
||||||
|
{
|
||||||
|
if (!m_argument_parser.ParseArguments(argc - 1, &argv[1]))
|
||||||
|
{
|
||||||
|
PrintUsage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the user requested help
|
||||||
|
if (m_argument_parser.IsOptionSpecified(OPTION_HELP))
|
||||||
|
{
|
||||||
|
PrintUsage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_zones_to_build = m_argument_parser.GetArguments();
|
||||||
|
if (m_zones_to_build.empty())
|
||||||
|
{
|
||||||
|
// No zones to build specified...
|
||||||
|
PrintUsage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -v; --verbose
|
||||||
|
SetVerbose(m_argument_parser.IsOptionSpecified(OPTION_VERBOSE));
|
||||||
|
|
||||||
|
// -o; --output-folder
|
||||||
|
if (m_argument_parser.IsOptionSpecified(OPTION_OUTPUT_FOLDER))
|
||||||
|
m_output_folder = m_argument_parser.GetValueForOption(OPTION_OUTPUT_FOLDER);
|
||||||
|
|
||||||
|
// --search-path
|
||||||
|
if (m_argument_parser.IsOptionSpecified(OPTION_SEARCH_PATH))
|
||||||
|
{
|
||||||
|
if (!FileUtils::ParsePathsString(m_argument_parser.GetValueForOption(OPTION_SEARCH_PATH), m_user_search_paths))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_argument_parser.IsOptionSpecified(OPTION_LOAD))
|
||||||
|
m_zones_to_load = m_argument_parser.GetParametersForOption(OPTION_LOAD);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LinkerArgs::GetOutputFolderPathForZone(const std::string& zoneName) const
|
||||||
|
{
|
||||||
|
return std::regex_replace(m_output_folder, std::regex("%zoneName%"), zoneName);
|
||||||
|
}
|
38
src/Linker/LinkerArgs.h
Normal file
38
src/Linker/LinkerArgs.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include "Utils/ClassUtils.h"
|
||||||
|
#include "Utils/Arguments/ArgumentParser.h"
|
||||||
|
#include "Zone/Zone.h"
|
||||||
|
|
||||||
|
class LinkerArgs
|
||||||
|
{
|
||||||
|
ArgumentParser m_argument_parser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Prints a command line usage help text for the Linker tool to stdout.
|
||||||
|
*/
|
||||||
|
static void PrintUsage();
|
||||||
|
|
||||||
|
void SetVerbose(bool isVerbose);
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::vector<std::string> m_zones_to_load;
|
||||||
|
std::vector<std::string> m_zones_to_build;
|
||||||
|
std::set<std::string> m_user_search_paths;
|
||||||
|
|
||||||
|
std::string m_output_folder;
|
||||||
|
|
||||||
|
bool m_verbose;
|
||||||
|
|
||||||
|
LinkerArgs();
|
||||||
|
bool ParseArgs(int argc, const char** argv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Converts the output path specified by command line arguments to a path applies for the specified zone.
|
||||||
|
* \param zoneName The name of the zone to resolve the path input for.
|
||||||
|
* \return An output path for the zone based on the user input.
|
||||||
|
*/
|
||||||
|
_NODISCARD std::string GetOutputFolderPathForZone(const std::string& zoneName) const;
|
||||||
|
};
|
@ -1,4 +1,8 @@
|
|||||||
int main(int argc, const char** argv)
|
#include "Linker.h"
|
||||||
|
|
||||||
|
int main(const int argc, const char** argv)
|
||||||
{
|
{
|
||||||
return 0;
|
Linker linker;
|
||||||
|
|
||||||
|
return linker.Start(argc, argv) ? 0 : 1;
|
||||||
}
|
}
|
@ -3,10 +3,10 @@
|
|||||||
|
|
||||||
#include "Utils/FileUtils.h"
|
#include "Utils/FileUtils.h"
|
||||||
|
|
||||||
constexpr uint32_t WAV_WAVE_ID = MakeMagic32('W', 'A', 'V', 'E');
|
constexpr uint32_t WAV_WAVE_ID = FileUtils::MakeMagic32('W', 'A', 'V', 'E');
|
||||||
constexpr uint32_t WAV_CHUNK_ID_RIFF = MakeMagic32('R', 'I', 'F', 'F');
|
constexpr uint32_t WAV_CHUNK_ID_RIFF = FileUtils::MakeMagic32('R', 'I', 'F', 'F');
|
||||||
constexpr uint32_t WAV_CHUNK_ID_FMT = MakeMagic32('f', 'm', 't', ' ');
|
constexpr uint32_t WAV_CHUNK_ID_FMT = FileUtils::MakeMagic32('f', 'm', 't', ' ');
|
||||||
constexpr uint32_t WAV_CHUNK_ID_DATA = MakeMagic32('d', 'a', 't', 'a');
|
constexpr uint32_t WAV_CHUNK_ID_DATA = FileUtils::MakeMagic32('d', 'a', 't', 'a');
|
||||||
|
|
||||||
struct WavChunkHeader
|
struct WavChunkHeader
|
||||||
{
|
{
|
||||||
|
@ -18,7 +18,7 @@ ObjContainerRepository<IPak, Zone> IPak::Repository;
|
|||||||
|
|
||||||
class IPak::Impl : public ObjContainerReferenceable
|
class IPak::Impl : public ObjContainerReferenceable
|
||||||
{
|
{
|
||||||
static const uint32_t MAGIC = MakeMagic32('K', 'A', 'P', 'I');
|
static const uint32_t MAGIC = FileUtils::MakeMagic32('K', 'A', 'P', 'I');
|
||||||
static const uint32_t VERSION = 0x50000;
|
static const uint32_t VERSION = 0x50000;
|
||||||
|
|
||||||
std::string m_path;
|
std::string m_path;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "Utils/Arguments/UsageInformation.h"
|
#include "Utils/Arguments/UsageInformation.h"
|
||||||
#include "ObjLoading.h"
|
#include "ObjLoading.h"
|
||||||
#include "ObjWriting.h"
|
#include "ObjWriting.h"
|
||||||
|
#include "Utils/FileUtils.h"
|
||||||
|
|
||||||
const CommandLineOption* const OPTION_HELP =
|
const CommandLineOption* const OPTION_HELP =
|
||||||
CommandLineOption::Builder::Create()
|
CommandLineOption::Builder::Create()
|
||||||
@ -84,66 +85,6 @@ UnlinkerArgs::UnlinkerArgs()
|
|||||||
m_verbose = false;
|
m_verbose = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UnlinkerArgs::ParsePathsString(const std::string& pathsString, std::set<std::string>& output)
|
|
||||||
{
|
|
||||||
std::ostringstream currentPath;
|
|
||||||
bool pathStart = true;
|
|
||||||
int quotationPos = 0; // 0 = before quotations, 1 = in quotations, 2 = after quotations
|
|
||||||
|
|
||||||
for (auto character : pathsString)
|
|
||||||
{
|
|
||||||
switch (character)
|
|
||||||
{
|
|
||||||
case '"':
|
|
||||||
if (quotationPos == 0 && pathStart)
|
|
||||||
{
|
|
||||||
quotationPos = 1;
|
|
||||||
}
|
|
||||||
else if (quotationPos == 1)
|
|
||||||
{
|
|
||||||
quotationPos = 2;
|
|
||||||
pathStart = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ';':
|
|
||||||
if (quotationPos != 1)
|
|
||||||
{
|
|
||||||
std::string path = currentPath.str();
|
|
||||||
if (!path.empty())
|
|
||||||
{
|
|
||||||
output.insert(path);
|
|
||||||
currentPath = std::ostringstream();
|
|
||||||
}
|
|
||||||
|
|
||||||
pathStart = true;
|
|
||||||
quotationPos = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
currentPath << character;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
currentPath << character;
|
|
||||||
pathStart = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentPath.tellp() > 0)
|
|
||||||
{
|
|
||||||
output.insert(currentPath.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnlinkerArgs::PrintUsage()
|
void UnlinkerArgs::PrintUsage()
|
||||||
{
|
{
|
||||||
UsageInformation usage("unlinker.exe");
|
UsageInformation usage("unlinker.exe");
|
||||||
@ -231,7 +172,7 @@ bool UnlinkerArgs::ParseArgs(const int argc, const char** argv)
|
|||||||
// --search-path
|
// --search-path
|
||||||
if (m_argument_parser.IsOptionSpecified(OPTION_SEARCH_PATH))
|
if (m_argument_parser.IsOptionSpecified(OPTION_SEARCH_PATH))
|
||||||
{
|
{
|
||||||
if (!ParsePathsString(m_argument_parser.GetValueForOption(OPTION_SEARCH_PATH), m_user_search_paths))
|
if (!FileUtils::ParsePathsString(m_argument_parser.GetValueForOption(OPTION_SEARCH_PATH), m_user_search_paths))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,6 @@ class UnlinkerArgs
|
|||||||
*/
|
*/
|
||||||
static void PrintUsage();
|
static void PrintUsage();
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Splits a path string as user input into a list of paths.
|
|
||||||
* \param pathsString The path string that was taken as user input.
|
|
||||||
* \param output A set for strings to save the output to.
|
|
||||||
* \return \c true if the user input was valid and could be processed successfully, otherwise \c false.
|
|
||||||
*/
|
|
||||||
static bool ParsePathsString(const std::string& pathsString, std::set<std::string>& output);
|
|
||||||
|
|
||||||
void SetVerbose(bool isVerbose);
|
void SetVerbose(bool isVerbose);
|
||||||
bool SetImageDumpingMode();
|
bool SetImageDumpingMode();
|
||||||
|
|
||||||
|
63
src/Utils/Utils/FileUtils.cpp
Normal file
63
src/Utils/Utils/FileUtils.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#include "FileUtils.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
bool FileUtils::ParsePathsString(const std::string& pathsString, std::set<std::string>& output)
|
||||||
|
{
|
||||||
|
std::ostringstream currentPath;
|
||||||
|
auto pathStart = true;
|
||||||
|
auto quotationPos = 0; // 0 = before quotations, 1 = in quotations, 2 = after quotations
|
||||||
|
|
||||||
|
for (auto character : pathsString)
|
||||||
|
{
|
||||||
|
switch (character)
|
||||||
|
{
|
||||||
|
case '"':
|
||||||
|
if (quotationPos == 0 && pathStart)
|
||||||
|
{
|
||||||
|
quotationPos = 1;
|
||||||
|
}
|
||||||
|
else if (quotationPos == 1)
|
||||||
|
{
|
||||||
|
quotationPos = 2;
|
||||||
|
pathStart = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ';':
|
||||||
|
if (quotationPos != 1)
|
||||||
|
{
|
||||||
|
auto path = currentPath.str();
|
||||||
|
if (!path.empty())
|
||||||
|
{
|
||||||
|
output.insert(path);
|
||||||
|
currentPath = std::ostringstream();
|
||||||
|
}
|
||||||
|
|
||||||
|
pathStart = true;
|
||||||
|
quotationPos = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentPath << character;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
currentPath << character;
|
||||||
|
pathStart = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPath.tellp() > 0)
|
||||||
|
{
|
||||||
|
output.insert(currentPath.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
@ -1,10 +1,24 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
constexpr uint32_t MakeMagic32(const char ch0, const char ch1, const char ch2, const char ch3)
|
class FileUtils
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
static constexpr uint32_t MakeMagic32(const char ch0, const char ch1, const char ch2, const char ch3)
|
||||||
|
{
|
||||||
return static_cast<uint32_t>(ch0)
|
return static_cast<uint32_t>(ch0)
|
||||||
| static_cast<uint32_t>(ch1) << 8
|
| static_cast<uint32_t>(ch1) << 8
|
||||||
| static_cast<uint32_t>(ch2) << 16
|
| static_cast<uint32_t>(ch2) << 16
|
||||||
| static_cast<uint32_t>(ch3) << 24;
|
| static_cast<uint32_t>(ch3) << 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Splits a path string as user input into a list of paths.
|
||||||
|
* \param pathsString The path string that was taken as user input.
|
||||||
|
* \param output A set for strings to save the output to.
|
||||||
|
* \return \c true if the user input was valid and could be processed successfully, otherwise \c false.
|
||||||
|
*/
|
||||||
|
static bool ParsePathsString(const std::string& pathsString, std::set<std::string>& output);
|
||||||
|
};
|
||||||
|
6
src/ZoneWriting/ZoneWriting.cpp
Normal file
6
src/ZoneWriting/ZoneWriting.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "ZoneWriting.h"
|
||||||
|
|
||||||
|
bool ZoneWriting::WriteZone(Zone* zone)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
9
src/ZoneWriting/ZoneWriting.h
Normal file
9
src/ZoneWriting/ZoneWriting.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include "Zone/Zone.h"
|
||||||
|
|
||||||
|
class ZoneWriting
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static bool WriteZone(Zone* zone);
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user