added extract tool

This commit is contained in:
Jack Andersen 2015-06-11 23:08:49 -10:00
parent 8de863fcba
commit 4b13e9da9d
10 changed files with 123 additions and 22 deletions

View File

@ -0,0 +1,50 @@
#ifndef CTOOL_EXTRACT
#define CTOOL_EXTRACT
#include "ToolBase.hpp"
#include <stdio.h>
class ToolExtract final : public ToolBase
{
public:
ToolExtract(const ToolPassInfo& info)
: ToolBase(info)
{
}
static void Help(HelpOutput& help)
{
help.secHead(_S("NAME"));
help.beginWrap();
help.wrap(_S("hecl-extract - Extract objects from supported package/image formats\n"));
help.endWrap();
help.secHead(_S("SYNOPSIS"));
help.beginWrap();
help.wrap(_S("hecl extract <packagefile>[/<subnode>...]\n"));
help.endWrap();
help.secHead(_S("DESCRIPTION"));
help.beginWrap();
help.wrap(_S("This command recursively extracts all or part of a dataspec-supported "
"package format.\n\n"));
help.endWrap();
help.secHead(_S("OPTIONS"));
help.optionHead(_S("<packagefile>[/<subnode>...]"), _S("input file"));
help.beginWrap();
help.wrap(_S("Specifies the package file or disc image to source data from. "
"An optional subnode specifies a named hierarchical-node specific "
"to the game architecture (levels/areas)."));
help.endWrap();
}
HECL::SystemString toolName() const {return _S("extract");}
int run()
{
return 0;
}
};
#endif // CTOOL_EXTRACT

View File

@ -60,6 +60,8 @@ public:
helpFunc = ToolInit::Help;
else if (toolName == _S("spec"))
helpFunc = ToolSpec::Help;
else if (toolName == _S("extract"))
helpFunc = ToolExtract::Help;
else if (toolName == _S("add"))
helpFunc = ToolAdd::Help;
else if (toolName == _S("remove") || toolName == _S("rm"))

View File

@ -45,7 +45,8 @@ public:
return -1;
try
{
HECL::Database::Project(HECL::ProjectRootPath(*m_dir));
HECL::Database::Project proj((HECL::ProjectRootPath(*m_dir)));
proj.enableDataSpecs({_S("hecl-little")});
}
catch (HECL::Exception& e)
{

View File

@ -23,6 +23,7 @@ SOURCES += \
HEADERS += \
ToolBase.hpp \
ToolPackage.hpp \
ToolExtract.hpp \
ToolInit.hpp \
ToolHelp.hpp \
ToolGroup.hpp \

View File

@ -10,6 +10,7 @@
#include "ToolBase.hpp"
#include "ToolInit.hpp"
#include "ToolSpec.hpp"
#include "ToolExtract.hpp"
#include "ToolAdd.hpp"
#include "ToolRemove.hpp"
#include "ToolGroup.hpp"
@ -180,6 +181,8 @@ int main(int argc, const char** argv)
tool.reset(new ToolInit(info));
else if (toolName == _S("spec"))
tool.reset(new ToolSpec(info));
else if (toolName == _S("extract"))
tool.reset(new ToolExtract(info));
else if (toolName == _S("add"))
tool.reset(new ToolAdd(info));
else if (toolName == _S("remove") || toolName == _S("rm"))

View File

@ -3,7 +3,7 @@
_hecl ()
{
local word=${COMP_WORDS[COMP_CWORD]}
local filecmds=(init spec add remove group cook clean package)
local filecmds=(init spec extract add remove group cook clean package)
if [ $COMP_CWORD == 1 ]
then
@ -12,7 +12,7 @@ _hecl ()
elif [ $COMP_CWORD == 2 ]
then
case ${COMP_WORDS[1]} in
init|add|remove|group|cook|clean|package)
init|extract|add|remove|group|cook|clean|package)
COMPREPLY=($(compgen -f -- "${word}"))
;;
spec)

View File

@ -262,6 +262,7 @@ public:
Hash(int64_t hashin)
: hash(hashin) {}
Hash(const Hash& other) {hash = other.hash;}
inline size_t val() const {return hash;}
inline Hash& operator=(const Hash& other) {hash = other.hash; return *this;}
inline bool operator==(const Hash& other) const {return hash == other.hash;}
inline bool operator!=(const Hash& other) const {return hash != other.hash;}
@ -309,7 +310,7 @@ class ProjectPath
protected:
SystemString m_absPath;
SystemString m_relPath;
size_t m_hash = 0;
Hash m_hash = 0;
#if HECL_UCS2
std::string m_utf8AbsPath;
const char* m_utf8RelPath;
@ -404,10 +405,10 @@ public:
void getGlobResults(std::vector<SystemString>& outPaths) const;
/**
* @brief C++11 compatible runtime hash (NOT USED IN PACKAGES!!)
* @return System-specific hash value
* @brief HECL-specific blowfish hash
* @return unique hash value
*/
inline size_t hash() const {return m_hash;}
inline size_t hash() const {return m_hash.val();}
inline bool operator==(const ProjectPath& other) const {return m_hash == other.m_hash;}
inline bool operator!=(const ProjectPath& other) const {return m_hash != other.m_hash;}
@ -517,7 +518,7 @@ namespace std
{
template <> struct hash<HECL::ProjectPath>
{
size_t operator()(const HECL::ProjectPath& val) const noexcept
inline size_t operator()(const HECL::ProjectPath& val) const noexcept
{return val.hash();}
};
}

View File

@ -8,6 +8,7 @@
#include <map>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <memory>
#include <atomic>
#include <stdexcept>
@ -21,6 +22,7 @@ namespace HECL
{
namespace Database
{
class Project;
/**
* @brief Nodegraph class for gathering dependency-resolved objects for packaging
@ -35,7 +37,8 @@ public:
NODE_DATA,
NODE_GROUP
} type;
SystemString path;
ProjectPath path;
ProjectPath cookedPath;
class ObjectBase* projectObj;
Node* sub;
Node* next;
@ -56,21 +59,62 @@ public:
class IDataSpec
{
public:
/**
* @brief Extract Pass Info
*
* An extract pass iterates through a source package or image and
* reverses the cooking process by emitting editable resources
*/
struct ExtractPassInfo
{
SystemString srcpath;
ProjectPath subpath;
bool cookedonly;
};
virtual bool canExtract(const ExtractPassInfo& info) {(void)info;return false;}
virtual void doExtract(const ExtractPassInfo& info) {(void)info;}
virtual bool canExtract(const Project& project, const ExtractPassInfo& info,
SystemString& reasonNo)
{(void)project;(void)info;reasonNo=_S("not implemented");return false;}
virtual void doExtract(const Project& project, const ExtractPassInfo& info)
{(void)project;(void)info;}
/**
* @brief Cook Task Info
*
* A cook task takes a single tracked path and generates the
* corresponding cooked version
*/
struct CookTaskInfo
{
ProjectPath path;
ProjectPath cookedPath;
};
virtual bool canCook(const Project& project, const CookTaskInfo& info,
SystemString& reasonNo)
{(void)project;(void)info;reasonNo=_S("not implemented");return false;}
virtual void doCook(const Project& project, const CookTaskInfo& info)
{(void)project;(void)info;}
/**
* @brief Package Pass Info
*
* A package pass performs last-minute queries of source resources,
* gathers dependencies and packages cooked data together in the
* most efficient form for the dataspec
*/
struct PackagePassInfo
{
PackageDepsgraph& depsgraph;
const PackageDepsgraph& depsgraph;
ProjectPath subpath;
ProjectPath outpath;
};
virtual bool canPackage(const PackagePassInfo& info) {(void)info;return false;}
virtual void doPackage(const PackagePassInfo& info) {(void)info;}
virtual bool canPackage(const Project& project, const PackagePassInfo& info,
SystemString& reasonNo)
{(void)project;(void)info;reasonNo=_S("not implemented");return false;}
virtual void gatherDependencies(const Project& project, const PackagePassInfo& info,
std::unordered_set<ProjectPath>& implicitsOut)
{(void)project;(void)info;(void)implicitsOut;}
virtual void doPackage(const Project& project, const PackagePassInfo& info)
{(void)project;(void)info;}
};
/**
@ -189,7 +233,8 @@ public:
std::list<std::string> m_lines;
FILE* m_lockedFile = NULL;
public:
ConfigFile(const Project& project, const SystemString& name);
ConfigFile(const Project& project, const SystemString& name,
const SystemString& subdir=_S("/.hecl/"));
std::list<std::string>& lockAndRead();
void addLine(const std::string& line);
void removeLine(const std::string& refLine);

View File

@ -51,9 +51,7 @@ ProjectPath::ProjectPath(const ProjectRootPath& rootPath, const SystemString& pa
if (*beginit == _S('/'))
++beginit;
m_relPath = SystemString(beginit, m_absPath.end());
std::hash<std::string> hash_fn;
m_hash = hash_fn(std::string(m_relPath));
m_hash = Hash(m_relPath);
#if HECL_UCS2
m_utf8AbsPath = WideToUTF8(m_absPath);
@ -205,7 +203,7 @@ std::unique_ptr<ProjectRootPath> SearchForProject(const SystemString& path)
while (begin != end)
{
SystemString testPath(begin, end);
SystemString testIndexPath = testPath + _S("/.hecl/index");
SystemString testIndexPath = testPath + _S("/.hecl/beacon");
struct stat theStat;
if (!HECL::Stat(testIndexPath.c_str(), &theStat))
{

View File

@ -40,9 +40,10 @@ static inline bool CheckNewLineAdvance(std::string::const_iterator& it)
return false;
}
Project::ConfigFile::ConfigFile(const Project& project, const SystemString& name)
Project::ConfigFile::ConfigFile(const Project& project, const SystemString& name,
const SystemString& subdir)
{
m_filepath = project.m_rootPath.getAbsolutePath() + _S("/.hecl/config/") + name;
m_filepath = project.m_rootPath.getAbsolutePath() + subdir + name;
}
std::list<std::string>& Project::ConfigFile::lockAndRead()
@ -184,7 +185,6 @@ Project::Project(const ProjectRootPath& rootPath)
/* Create project directory structure */
HECL::MakeDir(m_rootPath.getAbsolutePath() + _S("/.hecl"));
HECL::MakeDir(m_rootPath.getAbsolutePath() + _S("/.hecl/cooked"));
HECL::MakeDir(m_rootPath.getAbsolutePath() + _S("/.hecl/config"));
/* Ensure beacon is valid or created */
FILE* bf = HECL::Fopen((m_rootPath.getAbsolutePath() + _S("/.hecl/beacon")).c_str(), _S("a+b"));