mirror of https://github.com/AxioDL/metaforce.git
Much refactoring
This commit is contained in:
parent
851221f861
commit
84f8c62d28
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "extern/Athena"]
|
||||||
|
path = extern/Athena
|
||||||
|
url = https://github.com/Antidote/Athena.git
|
|
@ -3,32 +3,26 @@
|
||||||
|
|
||||||
#include "HECLDatabase.hpp"
|
#include "HECLDatabase.hpp"
|
||||||
|
|
||||||
class CDUMBProject : public HECLDatabase::CProjectObject
|
class CDUMBProject : public HECLDatabase::ProjectObjectBase
|
||||||
{
|
{
|
||||||
bool _cookObject(TDataAppender dataAppender,
|
using HECLDatabase::ProjectObjectBase::ProjectObjectBase;
|
||||||
|
|
||||||
|
bool _cookObject(FDataAppender dataAppender,
|
||||||
DataEndianness endianness, DataPlatform platform)
|
DataEndianness endianness, DataPlatform platform)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _gatherDeps(TDepAdder depAdder)
|
void _gatherDeps(FDepAdder depAdder)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
CDUMBProject(const ConstructionInfo& info)
|
|
||||||
: CProjectObject(info)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~CDUMBProject()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CDUMBRuntime : public HECLDatabase::CRuntimeObject
|
class CDUMBRuntime : public HECLDatabase::RuntimeObjectBase
|
||||||
{
|
{
|
||||||
|
using HECLDatabase::RuntimeObjectBase::RuntimeObjectBase;
|
||||||
|
|
||||||
bool _objectFinishedLoading(const void* data, size_t len)
|
bool _objectFinishedLoading(const void* data, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -40,14 +34,6 @@ class CDUMBRuntime : public HECLDatabase::CRuntimeObject
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
CDUMBRuntime(const ConstructionInfo& info)
|
|
||||||
: CRuntimeObject(info)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
~CDUMBRuntime()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DUMB_HPP
|
#endif // DUMB_HPP
|
||||||
|
|
|
@ -3,32 +3,25 @@
|
||||||
|
|
||||||
#include "HECLDatabase.hpp"
|
#include "HECLDatabase.hpp"
|
||||||
|
|
||||||
class CHMDLProject : public HECLDatabase::CProjectObject
|
class CHMDLProject : public HECLDatabase::ProjectObjectBase
|
||||||
{
|
{
|
||||||
bool _cookObject(TDataAppender dataAppender,
|
using HECLDatabase::ProjectObjectBase::ProjectObjectBase;
|
||||||
|
|
||||||
|
bool _cookObject(FDataAppender dataAppender,
|
||||||
DataEndianness endianness, DataPlatform platform)
|
DataEndianness endianness, DataPlatform platform)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _gatherDeps(TDepAdder depAdder)
|
void _gatherDeps(FDepAdder depAdder)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
CHMDLProject(const ConstructionInfo& info)
|
|
||||||
: CProjectObject(info)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~CHMDLProject()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CHMDLRuntime : public HECLDatabase::CRuntimeObject
|
class CHMDLRuntime : public HECLDatabase::RuntimeObjectBase
|
||||||
{
|
{
|
||||||
|
using HECLDatabase::RuntimeObjectBase::RuntimeObjectBase;
|
||||||
|
|
||||||
bool _objectFinishedLoading(const void* data, size_t len)
|
bool _objectFinishedLoading(const void* data, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -39,15 +32,6 @@ class CHMDLRuntime : public HECLDatabase::CRuntimeObject
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
CHMDLRuntime(const ConstructionInfo& info)
|
|
||||||
: CRuntimeObject(info)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
~CHMDLRuntime()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HMDL_HPP
|
#endif // HMDL_HPP
|
||||||
|
|
|
@ -3,32 +3,25 @@
|
||||||
|
|
||||||
#include "HECLDatabase.hpp"
|
#include "HECLDatabase.hpp"
|
||||||
|
|
||||||
class CMATRProject : public HECLDatabase::CProjectObject
|
class CMATRProject : public HECLDatabase::ProjectObjectBase
|
||||||
{
|
{
|
||||||
bool _cookObject(TDataAppender dataAppender,
|
using HECLDatabase::ProjectObjectBase::ProjectObjectBase;
|
||||||
|
|
||||||
|
bool _cookObject(FDataAppender dataAppender,
|
||||||
DataEndianness endianness, DataPlatform platform)
|
DataEndianness endianness, DataPlatform platform)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _gatherDeps(TDepAdder depAdder)
|
void _gatherDeps(FDepAdder depAdder)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
CMATRProject(const ConstructionInfo& info)
|
|
||||||
: CProjectObject(info)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~CMATRProject()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CMATRRuntime : public HECLDatabase::CRuntimeObject
|
class CMATRRuntime : public HECLDatabase::RuntimeObjectBase
|
||||||
{
|
{
|
||||||
|
using HECLDatabase::RuntimeObjectBase::RuntimeObjectBase;
|
||||||
|
|
||||||
bool _objectFinishedLoading(const void* data, size_t len)
|
bool _objectFinishedLoading(const void* data, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -39,15 +32,6 @@ class CMATRRuntime : public HECLDatabase::CRuntimeObject
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
CMATRRuntime(const ConstructionInfo& info)
|
|
||||||
: CRuntimeObject(info)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
~CMATRRuntime()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MATR_HPP
|
#endif // MATR_HPP
|
||||||
|
|
|
@ -3,32 +3,25 @@
|
||||||
|
|
||||||
#include "HECLDatabase.hpp"
|
#include "HECLDatabase.hpp"
|
||||||
|
|
||||||
class CSTRGProject : public HECLDatabase::CProjectObject
|
class CSTRGProject : public HECLDatabase::ProjectObjectBase
|
||||||
{
|
{
|
||||||
bool _cookObject(TDataAppender dataAppender,
|
using HECLDatabase::ProjectObjectBase::ProjectObjectBase;
|
||||||
|
|
||||||
|
bool _cookObject(FDataAppender dataAppender,
|
||||||
DataEndianness endianness, DataPlatform platform)
|
DataEndianness endianness, DataPlatform platform)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _gatherDeps(TDepAdder depAdder)
|
void _gatherDeps(FDepAdder depAdder)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
CSTRGProject(const ConstructionInfo& info)
|
|
||||||
: CProjectObject(info)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~CSTRGProject()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CSTRGRuntime : public HECLDatabase::CRuntimeObject
|
class CSTRGRuntime : public HECLDatabase::RuntimeObjectBase
|
||||||
{
|
{
|
||||||
|
using HECLDatabase::RuntimeObjectBase::RuntimeObjectBase;
|
||||||
|
|
||||||
bool _objectFinishedLoading(const void* data, size_t len)
|
bool _objectFinishedLoading(const void* data, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -39,15 +32,6 @@ class CSTRGRuntime : public HECLDatabase::CRuntimeObject
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
CSTRGRuntime(const ConstructionInfo& info)
|
|
||||||
: CRuntimeObject(info)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
~CSTRGRuntime()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // STRG_HPP
|
#endif // STRG_HPP
|
||||||
|
|
|
@ -4,15 +4,17 @@
|
||||||
#include "HECLDatabase.hpp"
|
#include "HECLDatabase.hpp"
|
||||||
#include "helpers.hpp"
|
#include "helpers.hpp"
|
||||||
|
|
||||||
class CTXTRProject : public HECLDatabase::CProjectObject
|
class CTXTRProject : public HECLDatabase::ProjectObjectBase
|
||||||
{
|
{
|
||||||
bool _cookObject(TDataAppender dataAppender,
|
using HECLDatabase::ProjectObjectBase::ProjectObjectBase;
|
||||||
|
|
||||||
|
bool _cookObject(FDataAppender dataAppender,
|
||||||
DataEndianness endianness, DataPlatform platform)
|
DataEndianness endianness, DataPlatform platform)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _gatherDeps(TDepAdder depAdder)
|
void _gatherDeps(FDepAdder depAdder)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,19 +28,11 @@ public:
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CTXTRProject(const ConstructionInfo& info)
|
|
||||||
: CProjectObject(info)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~CTXTRProject()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CTXTRRuntime : public HECLDatabase::CRuntimeObject
|
class CTXTRRuntime : public HECLDatabase::RuntimeObjectBase
|
||||||
{
|
{
|
||||||
|
using HECLDatabase::RuntimeObjectBase::RuntimeObjectBase;
|
||||||
|
|
||||||
bool _objectFinishedLoading(const void* data, size_t len)
|
bool _objectFinishedLoading(const void* data, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -49,15 +43,6 @@ class CTXTRRuntime : public HECLDatabase::CRuntimeObject
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
CTXTRRuntime(const ConstructionInfo& info)
|
|
||||||
: CRuntimeObject(info)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
~CTXTRRuntime()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TXTR_HPP
|
#endif // TXTR_HPP
|
||||||
|
|
|
@ -58,6 +58,8 @@ public:
|
||||||
CHelpOutput::THelpFunc helpFunc = NULL;
|
CHelpOutput::THelpFunc helpFunc = NULL;
|
||||||
if (toolName == "init")
|
if (toolName == "init")
|
||||||
helpFunc = CToolInit::Help;
|
helpFunc = CToolInit::Help;
|
||||||
|
else if (toolName == "platform")
|
||||||
|
helpFunc = CToolPlatform::Help;
|
||||||
else if (toolName == "add")
|
else if (toolName == "add")
|
||||||
helpFunc = CToolAdd::Help;
|
helpFunc = CToolAdd::Help;
|
||||||
else if (toolName == "remove" || toolName == "rm")
|
else if (toolName == "remove" || toolName == "rm")
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
#ifndef CTOOL_PLATFORM
|
||||||
|
#define CTOOL_PLATFORM
|
||||||
|
|
||||||
|
#include "CToolBase.hpp"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
class CToolPlatform final : public CToolBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CToolPlatform(const SToolPassInfo& info)
|
||||||
|
: CToolBase(info)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~CToolPlatform()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Help(CHelpOutput& help)
|
||||||
|
{
|
||||||
|
help.secHead("NAME");
|
||||||
|
help.beginWrap();
|
||||||
|
help.wrap("hecl-platform - Configure platform target options\n");
|
||||||
|
help.endWrap();
|
||||||
|
|
||||||
|
help.secHead("SYNOPSIS");
|
||||||
|
help.beginWrap();
|
||||||
|
help.wrap("hecl platform [enable|disable] [<platname>...]\n");
|
||||||
|
help.endWrap();
|
||||||
|
|
||||||
|
help.secHead("DESCRIPTION");
|
||||||
|
help.beginWrap();
|
||||||
|
help.wrap("This command configures the HECL project with the user's preferred target platforms.\n\n"
|
||||||
|
"Providing enable/disable argument will bulk-set the enable status of the provided platform"
|
||||||
|
"list. If enable/disable is not provided, a list of supported platforms is printed.\n\n");
|
||||||
|
help.endWrap();
|
||||||
|
|
||||||
|
help.secHead("OPTIONS");
|
||||||
|
help.optionHead("<platname>...", "platform name(s)");
|
||||||
|
help.beginWrap();
|
||||||
|
help.wrap("Specifies platform-names to enable/disable");
|
||||||
|
help.endWrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string toolName() const {return "platform";}
|
||||||
|
|
||||||
|
int run()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CTOOL_PLATFORM
|
|
@ -31,5 +31,6 @@ HEADERS += \
|
||||||
CToolCook.hpp \
|
CToolCook.hpp \
|
||||||
CToolClean.hpp \
|
CToolClean.hpp \
|
||||||
CToolAdd.hpp \
|
CToolAdd.hpp \
|
||||||
CToolRemove.hpp
|
CToolRemove.hpp \
|
||||||
|
CToolPlatform.hpp
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include "CToolBase.hpp"
|
#include "CToolBase.hpp"
|
||||||
#include "CToolInit.hpp"
|
#include "CToolInit.hpp"
|
||||||
|
#include "CToolPlatform.hpp"
|
||||||
#include "CToolAdd.hpp"
|
#include "CToolAdd.hpp"
|
||||||
#include "CToolRemove.hpp"
|
#include "CToolRemove.hpp"
|
||||||
#include "CToolGroup.hpp"
|
#include "CToolGroup.hpp"
|
||||||
|
@ -150,6 +151,8 @@ int main(int argc, const char** argv)
|
||||||
{
|
{
|
||||||
if (toolName == "init")
|
if (toolName == "init")
|
||||||
tool = new CToolInit(info);
|
tool = new CToolInit(info);
|
||||||
|
else if (toolName == "platform")
|
||||||
|
tool = new CToolPlatform(info);
|
||||||
else if (toolName == "add")
|
else if (toolName == "add")
|
||||||
tool = new CToolAdd(info);
|
tool = new CToolAdd(info);
|
||||||
else if (toolName == "remove" || toolName == "rm")
|
else if (toolName == "remove" || toolName == "rm")
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 7785983093f77e1f967580685f8d155364a7d965
|
|
@ -3,7 +3,7 @@
|
||||||
_hecl ()
|
_hecl ()
|
||||||
{
|
{
|
||||||
local word=${COMP_WORDS[COMP_CWORD]}
|
local word=${COMP_WORDS[COMP_CWORD]}
|
||||||
local filecmds=(init add remove group cook clean package)
|
local filecmds=(init platform add remove group cook clean package)
|
||||||
|
|
||||||
if [ $COMP_CWORD == 1 ]
|
if [ $COMP_CWORD == 1 ]
|
||||||
then
|
then
|
||||||
|
@ -15,6 +15,9 @@ _hecl ()
|
||||||
init|add|remove|group|cook|clean|package)
|
init|add|remove|group|cook|clean|package)
|
||||||
COMPREPLY=($(compgen -f -- "${word}"))
|
COMPREPLY=($(compgen -f -- "${word}"))
|
||||||
;;
|
;;
|
||||||
|
platform)
|
||||||
|
COMPREPLY=($(compgen -W "enable disable" "${word}"))
|
||||||
|
;;
|
||||||
help)
|
help)
|
||||||
COMPREPLY=($(compgen -W "${filecmds[*]}" "${word}"))
|
COMPREPLY=($(compgen -W "${filecmds[*]}" "${word}"))
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
TEMPLATE = subdirs
|
TEMPLATE = subdirs
|
||||||
|
CONFIG += c++11
|
||||||
|
|
||||||
# Enable building with LLVM dependencies
|
# Enable building with LLVM dependencies
|
||||||
exists ($$PWD/llvm) {
|
exists ($$PWD/llvm) {
|
||||||
|
|
|
@ -10,25 +10,97 @@ char* win_realpath(const char* name, char* restrict resolved);
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <stdexcept>
|
|
||||||
#include "../extern/blowfish/blowfish.h"
|
#include "../extern/blowfish/blowfish.h"
|
||||||
|
|
||||||
namespace HECL
|
namespace HECL
|
||||||
{
|
{
|
||||||
|
|
||||||
#if _WIN32
|
std::string WideToUTF8(const std::wstring& src);
|
||||||
typedef std::basic_string<TCHAR> TSystemPath;
|
std::wstring UTF8ToWide(const std::string& src);
|
||||||
|
|
||||||
|
#if _WIN32 && UNICODE
|
||||||
|
typedef wchar_t SystemChar;
|
||||||
|
typedef std::wstring SystemString;
|
||||||
|
class CSystemUTF8View
|
||||||
|
{
|
||||||
|
std::string m_utf8;
|
||||||
|
public:
|
||||||
|
CSystemUTF8View(const SystemString& str)
|
||||||
|
: m_utf8(WideToUTF8(str)) {}
|
||||||
|
inline const std::string& utf8_str() {return m_utf8;}
|
||||||
|
};
|
||||||
|
class CSystemStringView
|
||||||
|
{
|
||||||
|
std::wstring m_sys;
|
||||||
|
public:
|
||||||
|
CSystemStringView(const std::string& str)
|
||||||
|
: m_sys(UTF8ToWide(str)) {}
|
||||||
|
inline const std::string& sys_str() {return m_sys;}
|
||||||
|
};
|
||||||
|
#ifndef _S
|
||||||
|
#define _S(val) L ## val
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
typedef std::string TSystemPath;
|
typedef char SystemChar;
|
||||||
|
typedef std::string SystemString;
|
||||||
|
class CSystemUTF8View
|
||||||
|
{
|
||||||
|
const std::string& m_utf8;
|
||||||
|
public:
|
||||||
|
CSystemUTF8View(const SystemString& str)
|
||||||
|
: m_utf8(str) {}
|
||||||
|
inline const std::string& utf8_str() {return m_utf8;}
|
||||||
|
};
|
||||||
|
class CSystemStringView
|
||||||
|
{
|
||||||
|
const std::string& m_sys;
|
||||||
|
public:
|
||||||
|
CSystemStringView(const std::string& str)
|
||||||
|
: m_sys(str) {}
|
||||||
|
inline const std::string& sys_str() {return m_sys;}
|
||||||
|
};
|
||||||
|
#ifndef _S
|
||||||
|
#define _S(val) val
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline void MakeDir(const SystemString& dir)
|
||||||
|
{
|
||||||
|
#if _WIN32
|
||||||
|
HRESULT err;
|
||||||
|
if (!CreateDirectory(dir.c_str(), NULL))
|
||||||
|
if ((err = GetLastError()) != ERROR_ALREADY_EXISTS)
|
||||||
|
throw std::error_code(err, std::system_category());
|
||||||
|
#else
|
||||||
|
if (mkdir(dir.c_str(), 0755))
|
||||||
|
if (errno != EEXIST)
|
||||||
|
throw std::error_code(errno, std::system_category());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline FILE* Fopen(const SystemChar* path, const SystemChar* mode)
|
||||||
|
{
|
||||||
|
#if _WIN32 && UNICODE
|
||||||
|
FILE* fp = wfopen(path, mode);
|
||||||
|
#else
|
||||||
|
FILE* fp = fopen(path, mode);
|
||||||
|
#endif
|
||||||
|
if (!fp)
|
||||||
|
throw std::error_code(errno, std::system_category());
|
||||||
|
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef std::basic_regex<SystemChar> SystemRegex;
|
||||||
|
typedef std::regex_token_iterator<SystemString::const_iterator> SystemRegexTokenIterator;
|
||||||
|
typedef std::match_results<SystemString::const_iterator> SystemRegexMatch;
|
||||||
|
|
||||||
class ProjectRootPath;
|
class ProjectRootPath;
|
||||||
static const std::regex regGLOB("\\*", std::regex::ECMAScript|std::regex::optimize);
|
|
||||||
static const std::regex regPATHCOMP("/([^/]+)", std::regex::ECMAScript|std::regex::optimize);
|
|
||||||
static const std::regex regDRIVELETTER("^([^/]*)/", std::regex::ECMAScript|std::regex::optimize);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Severity of a log event
|
* @brief Severity of a log event
|
||||||
|
@ -75,20 +147,22 @@ public:
|
||||||
* Hashes are used within HECL to avoid redundant storage of objects;
|
* Hashes are used within HECL to avoid redundant storage of objects;
|
||||||
* providing a rapid mechanism to compare for equality.
|
* providing a rapid mechanism to compare for equality.
|
||||||
*/
|
*/
|
||||||
class ObjectHash
|
class Hash
|
||||||
{
|
{
|
||||||
int64_t hash;
|
int64_t hash;
|
||||||
public:
|
public:
|
||||||
ObjectHash(const void* buf, size_t len)
|
Hash(const void* buf, size_t len)
|
||||||
: hash(Blowfish_hash(buf, len)) {}
|
: hash(Blowfish_hash(buf, len)) {}
|
||||||
ObjectHash(int64_t hashin)
|
Hash(const std::string& str)
|
||||||
|
: hash(Blowfish_hash(str.data(), str.size())) {}
|
||||||
|
Hash(int64_t hashin)
|
||||||
: hash(hashin) {}
|
: hash(hashin) {}
|
||||||
inline bool operator==(ObjectHash& other) {return hash == other.hash;}
|
inline bool operator==(Hash& other) {return hash == other.hash;}
|
||||||
inline bool operator!=(ObjectHash& other) {return hash != other.hash;}
|
inline bool operator!=(Hash& other) {return hash != other.hash;}
|
||||||
inline bool operator<(ObjectHash& other) {return hash < other.hash;}
|
inline bool operator<(Hash& other) {return hash < other.hash;}
|
||||||
inline bool operator>(ObjectHash& other) {return hash > other.hash;}
|
inline bool operator>(Hash& other) {return hash > other.hash;}
|
||||||
inline bool operator<=(ObjectHash& other) {return hash <= other.hash;}
|
inline bool operator<=(Hash& other) {return hash <= other.hash;}
|
||||||
inline bool operator>=(ObjectHash& other) {return hash >= other.hash;}
|
inline bool operator>=(Hash& other) {return hash >= other.hash;}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -107,51 +181,18 @@ public:
|
||||||
class ProjectPath
|
class ProjectPath
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
TSystemPath m_absPath;
|
SystemString m_absPath;
|
||||||
const char* m_relPath = NULL;
|
const SystemChar* m_relPath = NULL;
|
||||||
ProjectPath() {}
|
ProjectPath() {}
|
||||||
bool _canonAbsPath(const TSystemPath& path)
|
bool _canonAbsPath(const SystemString& path);
|
||||||
{
|
|
||||||
#if _WIN32
|
|
||||||
#else
|
|
||||||
char resolvedPath[PATH_MAX];
|
|
||||||
if (!realpath(path.c_str(), resolvedPath))
|
|
||||||
{
|
|
||||||
throw std::invalid_argument("Unable to resolve '" + path + "' as a canonicalized path");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_absPath = resolvedPath;
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Construct a project subpath representation
|
* @brief Construct a project subpath representation
|
||||||
* @param rootPath previously constructed ProjectRootPath held by HECLDatabase::IProject
|
* @param rootPath previously constructed ProjectRootPath held by HECLDatabase::IProject
|
||||||
* @param path valid filesystem-path (relative or absolute) to subpath
|
* @param path valid filesystem-path (relative or absolute) to subpath
|
||||||
*/
|
*/
|
||||||
ProjectPath(const ProjectRootPath& rootPath, const TSystemPath& path)
|
ProjectPath(const ProjectRootPath& rootPath, const SystemString& path);
|
||||||
{
|
|
||||||
_canonAbsPath(path);
|
|
||||||
if (m_absPath.size() < ((ProjectPath&)rootPath).m_absPath.size() ||
|
|
||||||
m_absPath.compare(0, ((ProjectPath&)rootPath).m_absPath.size(),
|
|
||||||
((ProjectPath&)rootPath).m_absPath))
|
|
||||||
{
|
|
||||||
throw std::invalid_argument("'" + m_absPath + "' is not a subpath of '" +
|
|
||||||
((ProjectPath&)rootPath).m_absPath + "'");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (m_absPath.size() == ((ProjectPath&)rootPath).m_absPath.size())
|
|
||||||
{
|
|
||||||
/* Copies of the project root are permitted */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_relPath = m_absPath.c_str() + ((ProjectPath&)rootPath).m_absPath.size();
|
|
||||||
if (m_relPath[0] == '/')
|
|
||||||
++m_relPath;
|
|
||||||
if (m_relPath[0] == '\0')
|
|
||||||
m_relPath = NULL;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* @brief Determine if ProjectPath represents project root directory
|
* @brief Determine if ProjectPath represents project root directory
|
||||||
* @return true if project root directory
|
* @return true if project root directory
|
||||||
|
@ -162,17 +203,17 @@ public:
|
||||||
* @brief Access fully-canonicalized absolute path
|
* @brief Access fully-canonicalized absolute path
|
||||||
* @return Absolute path reference
|
* @return Absolute path reference
|
||||||
*/
|
*/
|
||||||
inline const TSystemPath& getAbsolutePath() {return m_absPath;}
|
inline const SystemString& getAbsolutePath() {return m_absPath;}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Access fully-canonicalized project-relative path
|
* @brief Access fully-canonicalized project-relative path
|
||||||
* @return Relative pointer to within absolute-path or "." for project root-directory (use isRoot to detect)
|
* @return Relative pointer to within absolute-path or "." for project root-directory (use isRoot to detect)
|
||||||
*/
|
*/
|
||||||
inline const char* getRelativePath()
|
inline const SystemChar* getRelativePath()
|
||||||
{
|
{
|
||||||
if (m_relPath)
|
if (m_relPath)
|
||||||
return m_relPath;
|
return m_relPath;
|
||||||
return ".";
|
return _S(".");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -190,57 +231,13 @@ public:
|
||||||
* @brief Get type of path based on syntax and filesystem queries
|
* @brief Get type of path based on syntax and filesystem queries
|
||||||
* @return Type of path
|
* @return Type of path
|
||||||
*/
|
*/
|
||||||
PathType getPathType()
|
PathType getPathType();
|
||||||
{
|
|
||||||
if (std::regex_search(m_absPath, regGLOB))
|
|
||||||
return PT_GLOB;
|
|
||||||
#if _WIN32
|
|
||||||
#else
|
|
||||||
struct stat theStat;
|
|
||||||
if (stat(m_absPath.c_str(), &theStat))
|
|
||||||
return PT_NONE;
|
|
||||||
if (S_ISDIR(theStat.st_mode))
|
|
||||||
return PT_DIRECTORY;
|
|
||||||
if (S_ISREG(theStat.st_mode))
|
|
||||||
return PT_FILE;
|
|
||||||
return PT_NONE;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void getGlobResults(std::vector<TSystemPath>& outPaths)
|
/**
|
||||||
{
|
* @brief Insert glob matches into existing vector
|
||||||
#if _WIN32
|
* @param outPaths Vector to add matches to (will not erase existing contents)
|
||||||
std::string itStr;
|
*/
|
||||||
std::smatch letterMatch;
|
void getGlobResults(std::vector<SystemString>& outPaths);
|
||||||
if (m_absPath.compare(0, 2, "//"))
|
|
||||||
itStr = "\\\\";
|
|
||||||
else if (std::regex_search(m_absPath, letterMatch, regDRIVELETTER))
|
|
||||||
if (letterMatch[1].str().size())
|
|
||||||
itStr = letterMatch[1];
|
|
||||||
#else
|
|
||||||
std::string itStr = "/";
|
|
||||||
#endif
|
|
||||||
bool needSlash = false;
|
|
||||||
|
|
||||||
std::sregex_token_iterator pathComps(m_absPath.begin(), m_absPath.end(), regPATHCOMP);
|
|
||||||
for (; pathComps != std::sregex_token_iterator() ; ++pathComps)
|
|
||||||
{
|
|
||||||
const std::string& comp = *pathComps;
|
|
||||||
if (!std::regex_search(comp, regGLOB))
|
|
||||||
{
|
|
||||||
if (needSlash)
|
|
||||||
itStr += '/';
|
|
||||||
else
|
|
||||||
needSlash = true;
|
|
||||||
itStr += comp;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#if _WIN32
|
|
||||||
#else
|
|
||||||
DIR* dir = opendir("");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -252,7 +249,7 @@ public:
|
||||||
class ProjectRootPath : public ProjectPath
|
class ProjectRootPath : public ProjectPath
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ProjectRootPath(const TSystemPath& path)
|
ProjectRootPath(const SystemString& path)
|
||||||
{
|
{
|
||||||
_canonAbsPath(path);
|
_canonAbsPath(path);
|
||||||
}
|
}
|
||||||
|
@ -261,7 +258,8 @@ public:
|
||||||
|
|
||||||
|
|
||||||
/* Type-sensitive byte swappers */
|
/* Type-sensitive byte swappers */
|
||||||
static inline int16_t bswap(int16_t val)
|
template <typename T>
|
||||||
|
static inline T bswap16(T val)
|
||||||
{
|
{
|
||||||
#if __GNUC__
|
#if __GNUC__
|
||||||
return __builtin_bswap16(val);
|
return __builtin_bswap16(val);
|
||||||
|
@ -272,18 +270,8 @@ static inline int16_t bswap(int16_t val)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint16_t bswap(uint16_t val)
|
template <typename T>
|
||||||
{
|
static inline T bswap32(T val)
|
||||||
#if __GNUC__
|
|
||||||
return __builtin_bswap16(val);
|
|
||||||
#elif _WIN32
|
|
||||||
return _byteswap_ushort(val);
|
|
||||||
#else
|
|
||||||
return (val = (val << 8) | ((val >> 8) & 0xFF));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int32_t bswap(int32_t val)
|
|
||||||
{
|
{
|
||||||
#if __GNUC__
|
#if __GNUC__
|
||||||
return __builtin_bswap32(val);
|
return __builtin_bswap32(val);
|
||||||
|
@ -296,61 +284,54 @@ static inline int32_t bswap(int32_t val)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t bswap(uint32_t val)
|
template <typename T>
|
||||||
{
|
static inline T bswap64(T val)
|
||||||
#if __GNUC__
|
|
||||||
return __builtin_bswap32(val);
|
|
||||||
#elif _WIN32
|
|
||||||
return _byteswap_ulong(val);
|
|
||||||
#else
|
|
||||||
val = (val & 0x0000FFFF) << 16 | (val & 0xFFFF0000) >> 16;
|
|
||||||
val = (val & 0x00FF00FF) << 8 | (val & 0xFF00FF00) >> 8;
|
|
||||||
return val;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int64_t bswap(int64_t val)
|
|
||||||
{
|
{
|
||||||
#if __GNUC__
|
#if __GNUC__
|
||||||
return __builtin_bswap64(val);
|
return __builtin_bswap64(val);
|
||||||
#elif _WIN32
|
#elif _WIN32
|
||||||
return _byteswap_uint64(val);
|
return _byteswap_uint64(val);
|
||||||
#else
|
#else
|
||||||
return (val = ((atInt64)((((atInt64)(val) & 0xFF00000000000000ULL) >> 56) |
|
return ((val & 0xFF00000000000000ULL) >> 56) |
|
||||||
(((atInt64)(val) & 0x00FF000000000000ULL) >> 40) |
|
((val & 0x00FF000000000000ULL) >> 40) |
|
||||||
(((atInt64)(val) & 0x0000FF0000000000ULL) >> 24) |
|
((val & 0x0000FF0000000000ULL) >> 24) |
|
||||||
(((atInt64)(val) & 0x000000FF00000000ULL) >> 8) |
|
((val & 0x000000FF00000000ULL) >> 8) |
|
||||||
(((atInt64)(val) & 0x00000000FF000000ULL) << 8) |
|
((val & 0x00000000FF000000ULL) << 8) |
|
||||||
(((atInt64)(val) & 0x0000000000FF0000ULL) << 24) |
|
((val & 0x0000000000FF0000ULL) << 24) |
|
||||||
(((atInt64)(val) & 0x000000000000FF00ULL) << 40) |
|
((val & 0x000000000000FF00ULL) << 40) |
|
||||||
(((atInt64)(val) & 0x00000000000000FFULL) << 56))));
|
((val & 0x00000000000000FFULL) << 56);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64_t bswap(uint64_t val)
|
|
||||||
{
|
|
||||||
#if __GNUC__
|
|
||||||
return __builtin_bswap64(val);
|
|
||||||
#elif _WIN32
|
|
||||||
return _byteswap_uint64(val);
|
|
||||||
#else
|
|
||||||
return (val = ((atInt64)((((atInt64)(val) & 0xFF00000000000000ULL) >> 56) |
|
|
||||||
(((atInt64)(val) & 0x00FF000000000000ULL) >> 40) |
|
|
||||||
(((atInt64)(val) & 0x0000FF0000000000ULL) >> 24) |
|
|
||||||
(((atInt64)(val) & 0x000000FF00000000ULL) >> 8) |
|
|
||||||
(((atInt64)(val) & 0x00000000FF000000ULL) << 8) |
|
|
||||||
(((atInt64)(val) & 0x0000000000FF0000ULL) << 24) |
|
|
||||||
(((atInt64)(val) & 0x000000000000FF00ULL) << 40) |
|
|
||||||
(((atInt64)(val) & 0x00000000000000FFULL) << 56))));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
#define HECLMakeBig(val) HECL::bswap(val)
|
static inline int16_t ToBig(int16_t val) {return bswap16(val);}
|
||||||
#define HECLMakeLittle(val) (val)
|
static inline uint16_t ToBig(uint16_t val) {return bswap16(val);}
|
||||||
|
static inline int32_t ToBig(int32_t val) {return bswap32(val);}
|
||||||
|
static inline uint32_t ToBig(uint32_t val) {return bswap32(val);}
|
||||||
|
static inline int64_t ToBig(int64_t val) {return bswap64(val);}
|
||||||
|
static inline uint64_t ToBig(uint64_t val) {return bswap64(val);}
|
||||||
|
|
||||||
|
static inline int16_t ToLittle(int16_t val) {return val;}
|
||||||
|
static inline uint16_t ToLittle(uint16_t val) {return val;}
|
||||||
|
static inline int32_t ToLittle(int32_t val) {return val;}
|
||||||
|
static inline uint32_t ToLittle(uint32_t val) {return val;}
|
||||||
|
static inline int64_t ToLittle(int64_t val) {return val;}
|
||||||
|
static inline uint64_t ToLittle(uint64_t val) {return val;}
|
||||||
#else
|
#else
|
||||||
#define HECLMakeBig(val) (val)
|
static inline int16_t ToLittle(int16_t val) {return bswap16(val);}
|
||||||
#define HECLMakeLittle(val) HECL::bswap(val)
|
static inline uint16_t ToLittle(uint16_t val) {return bswap16(val);}
|
||||||
|
static inline int32_t ToLittle(int32_t val) {return bswap32(val);}
|
||||||
|
static inline uint32_t ToLittle(uint32_t val) {return bswap32(val);}
|
||||||
|
static inline int64_t ToLittle(int64_t val) {return bswap64(val);}
|
||||||
|
static inline uint64_t ToLittle(uint64_t val) {return bswap64(val);}
|
||||||
|
|
||||||
|
static inline int16_t ToBig(int16_t val) {return val;}
|
||||||
|
static inline uint16_t ToBig(uint16_t val) {return val;}
|
||||||
|
static inline int32_t ToBig(int32_t val) {return val;}
|
||||||
|
static inline uint32_t ToBig(uint32_t val) {return val;}
|
||||||
|
static inline int64_t ToBig(int64_t val) {return val;}
|
||||||
|
static inline uint64_t ToBig(uint64_t val) {return val;}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <atomic>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
@ -13,73 +16,6 @@
|
||||||
namespace HECLDatabase
|
namespace HECLDatabase
|
||||||
{
|
{
|
||||||
|
|
||||||
class IProject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Generic Database Object Class
|
|
||||||
*
|
|
||||||
* This abstract base-class is a typeless object node for entities in an
|
|
||||||
* underlying database.
|
|
||||||
*/
|
|
||||||
class IDataObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Data-key of object
|
|
||||||
* @return Primary key
|
|
||||||
*/
|
|
||||||
virtual int64_t id() const=0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief FourCC type of object
|
|
||||||
* @return FourCC type
|
|
||||||
*/
|
|
||||||
virtual const HECL::FourCC& type() const=0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Data-hash of object
|
|
||||||
* @return Object hash truncated to system's size-type
|
|
||||||
*/
|
|
||||||
virtual const HECL::ObjectHash& hash() const=0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Original path of object
|
|
||||||
* @return Name
|
|
||||||
*/
|
|
||||||
virtual const std::string& path() const=0;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief An iterable collection of objects tracked within the database
|
|
||||||
*/
|
|
||||||
class IDataDependencyGroup
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Count of objects in the group
|
|
||||||
* @return object count
|
|
||||||
*/
|
|
||||||
virtual size_t length() const=0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Alias of length()
|
|
||||||
* @return object count
|
|
||||||
*/
|
|
||||||
inline size_t size() const {return length();}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Retrieve object at specified internal index within the group
|
|
||||||
* @param idx internal index of object to fetch (range [0,length()-1])
|
|
||||||
* @return object or nullptr
|
|
||||||
*/
|
|
||||||
virtual const IDataObject* at(size_t idx) const=0;
|
|
||||||
inline const IDataObject* operator[](size_t idx) {return at(idx);}
|
|
||||||
|
|
||||||
virtual std::vector<IDataObject*>::const_iterator begin() const=0;
|
|
||||||
virtual std::vector<IDataObject*>::const_iterator end() const=0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Base object to subclass for integrating with key project operations
|
* @brief Base object to subclass for integrating with key project operations
|
||||||
*
|
*
|
||||||
|
@ -89,10 +25,11 @@ public:
|
||||||
*
|
*
|
||||||
* DO NOT CONSTRUCT THIS OR SUBCLASSES DIRECTLY!!
|
* DO NOT CONSTRUCT THIS OR SUBCLASSES DIRECTLY!!
|
||||||
*/
|
*/
|
||||||
class CProjectObject
|
class ProjectObjectBase
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
friend class CProject;
|
friend class CProject;
|
||||||
|
std::string m_path;
|
||||||
|
protected:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Byte-order of target system
|
* @brief Byte-order of target system
|
||||||
|
@ -115,7 +52,7 @@ protected:
|
||||||
DP_CAFE /**< Swizzled textures and R700 shader objects */
|
DP_CAFE /**< Swizzled textures and R700 shader objects */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::function<void(const void* data, size_t len)> TDataAppender;
|
typedef std::function<void(const void* data, size_t len)> FDataAppender;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Optional private method implemented by CProjectObject subclasses to cook objects
|
* @brief Optional private method implemented by CProjectObject subclasses to cook objects
|
||||||
|
@ -128,11 +65,11 @@ protected:
|
||||||
* Part of the cooking process may include embedding database-refs to dependencies.
|
* Part of the cooking process may include embedding database-refs to dependencies.
|
||||||
* This method should store the 64-bit value provided by IDataObject::id() when doing this.
|
* This method should store the 64-bit value provided by IDataObject::id() when doing this.
|
||||||
*/
|
*/
|
||||||
virtual bool _cookObject(TDataAppender dataAppender,
|
virtual bool _cookObject(FDataAppender dataAppender,
|
||||||
DataEndianness endianness, DataPlatform platform)
|
DataEndianness endianness, DataPlatform platform)
|
||||||
{(void)dataAppender;(void)endianness;(void)platform;return true;}
|
{(void)dataAppender;(void)endianness;(void)platform;return true;}
|
||||||
|
|
||||||
typedef std::function<void(CProjectObject*)> TDepAdder;
|
typedef std::function<void(ProjectObjectBase*)> FDepAdder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Optional private method implemented by CProjectObject subclasses to resolve dependencies
|
* @brief Optional private method implemented by CProjectObject subclasses to resolve dependencies
|
||||||
|
@ -142,24 +79,21 @@ protected:
|
||||||
* Dependencies registered via this method will eventually have this method called on themselves
|
* Dependencies registered via this method will eventually have this method called on themselves
|
||||||
* as well. This is a non-recursive operation, no need for subclasses to implement recursion-control.
|
* as well. This is a non-recursive operation, no need for subclasses to implement recursion-control.
|
||||||
*/
|
*/
|
||||||
virtual void _gatherDeps(TDepAdder depAdder)
|
virtual void _gatherDeps(FDepAdder depAdder)
|
||||||
{(void)depAdder;}
|
{(void)depAdder;}
|
||||||
|
|
||||||
protected:
|
|
||||||
std::string m_path;
|
|
||||||
IDataObject* m_mainObj;
|
|
||||||
IDataObject* m_cookedObj;
|
|
||||||
public:
|
public:
|
||||||
static bool ClaimPath(const std::string&, const std::string&) {return false;}
|
ProjectObjectBase(const std::string& path)
|
||||||
virtual ~CProjectObject();
|
: m_path(path) {}
|
||||||
struct ConstructionInfo
|
|
||||||
{
|
inline const std::string& getPath() const {return m_path;}
|
||||||
IDataObject* mainObj;
|
|
||||||
IDataObject* cookedObj;
|
/**
|
||||||
const std::string& path;
|
* @brief Overridable function to verify data at provided path
|
||||||
};
|
* @return true if ProjectObject subclass handles data at provided path/subpath
|
||||||
CProjectObject(const ConstructionInfo& info)
|
*/
|
||||||
: m_path(info.path), m_mainObj(info.mainObj), m_cookedObj(info.cookedObj) {}
|
static bool ClaimPath(const std::string& /*path*/, const std::string& /*subpath*/) {return false;}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -170,7 +104,7 @@ public:
|
||||||
* resources in their ideal editor-formats. This interface exposes all
|
* resources in their ideal editor-formats. This interface exposes all
|
||||||
* primary operations to perform on a given project.
|
* primary operations to perform on a given project.
|
||||||
*/
|
*/
|
||||||
class IProject
|
class Project
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~IProject() {}
|
virtual ~IProject() {}
|
||||||
|
@ -226,14 +160,14 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Remove a given file or file-pattern from the database
|
* @brief Remove a given file or file-pattern from the database
|
||||||
* @param path file or pattern within project
|
* @param paths file(s) or pattern(s) within project
|
||||||
* @param recursive traverse into matched subdirectories
|
* @param recursive traverse into matched subdirectories
|
||||||
* @return true on success
|
* @return true on success
|
||||||
*
|
*
|
||||||
* This method will not delete actual working files from the project
|
* This method will not delete actual working files from the project
|
||||||
* directory. It will delete associated cooked objects though.
|
* directory. It will delete associated cooked objects though.
|
||||||
*/
|
*/
|
||||||
virtual bool removePaths(const std::string& path, bool recursive=false)=0;
|
virtual bool removePaths(const std::vector<HECL::ProjectPath>& paths, bool recursive=false)=0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Register a working sub-directory as a Dependency Group
|
* @brief Register a working sub-directory as a Dependency Group
|
||||||
|
@ -249,14 +183,34 @@ public:
|
||||||
* This contiguous storage makes for optimal loading from slow block-devices
|
* This contiguous storage makes for optimal loading from slow block-devices
|
||||||
* like optical drives.
|
* like optical drives.
|
||||||
*/
|
*/
|
||||||
virtual bool addGroup(const std::string& path)=0;
|
virtual bool addGroup(const HECL::ProjectPath& path)=0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Unregister a working sub-directory as a dependency group
|
* @brief Unregister a working sub-directory as a dependency group
|
||||||
* @param path directory to unregister as Dependency Group
|
* @param path directory to unregister as Dependency Group
|
||||||
* @return true on success
|
* @return true on success
|
||||||
*/
|
*/
|
||||||
virtual bool removeGroup(const std::string& path)=0;
|
virtual bool removeGroup(const HECL::ProjectPath& path)=0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return map populated with platforms targetable by this project interface
|
||||||
|
* @return Platform map with name-string keys and enable-status values
|
||||||
|
*/
|
||||||
|
virtual const std::map<const std::string, const bool>& listPlatforms()=0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable persistent user preference for particular platform string(s)
|
||||||
|
* @param platforms String(s) representing unique platform(s) from listPlatforms
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
|
virtual bool enablePlatforms(const std::vector<std::string>& platforms)=0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disable persistent user preference for particular platform string(s)
|
||||||
|
* @param platform String(s) representing unique platform(s) from listPlatforms
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
|
virtual bool disablePlatforms(const std::vector<std::string>& platforms)=0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Begin cook process for specified directory
|
* @brief Begin cook process for specified directory
|
||||||
|
@ -269,7 +223,7 @@ public:
|
||||||
* This method blocks execution during the procedure, with periodic
|
* This method blocks execution during the procedure, with periodic
|
||||||
* feedback delivered via feedbackCb.
|
* feedback delivered via feedbackCb.
|
||||||
*/
|
*/
|
||||||
virtual bool cookPath(const std::string& path,
|
virtual bool cookPath(const HECL::SystemString& path,
|
||||||
std::function<void(std::string&, Cost, unsigned)> feedbackCb,
|
std::function<void(std::string&, Cost, unsigned)> feedbackCb,
|
||||||
bool recursive=false)=0;
|
bool recursive=false)=0;
|
||||||
|
|
||||||
|
@ -294,24 +248,39 @@ public:
|
||||||
* Developers understand how useful 'clean' is. While ideally not required,
|
* Developers understand how useful 'clean' is. While ideally not required,
|
||||||
* it's useful for verifying that a rebuild from ground-up is doable.
|
* it's useful for verifying that a rebuild from ground-up is doable.
|
||||||
*/
|
*/
|
||||||
virtual bool cleanPath(const std::string& path, bool recursive=false)=0;
|
virtual bool cleanPath(const HECL::SystemString& path, bool recursive=false)=0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Package cooked objects for directory
|
* @brief Nodegraph class for gathering dependency-resolved objects for packaging
|
||||||
* @param path directory of intermediates to package
|
|
||||||
* @param recursive traverse subdirectories to package as well
|
|
||||||
* @return true on success
|
|
||||||
*
|
|
||||||
* Once all dependent resources are cooked, this method archives specified
|
|
||||||
* intermediates into a packed database file located alongside the specified
|
|
||||||
* directory. This is a similar process to 'linking' in software development.
|
|
||||||
*
|
|
||||||
* Part of this process involves calling CProjectObject::_gatherDeps() to calculate
|
|
||||||
* object dependencies. This makes package-assembly simple, as dependencies will
|
|
||||||
* automatically be added as needed. The frontend needn't be concerned about
|
|
||||||
* gathering leaf-objects buried in corners of the working directory.
|
|
||||||
*/
|
*/
|
||||||
virtual bool packagePath(const std::string& path, bool recursive=false)=0;
|
class PackageDepsgraph
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Node
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
NODE_DATA,
|
||||||
|
NODE_GROUP
|
||||||
|
} type;
|
||||||
|
std::string path;
|
||||||
|
ProjectObjectBase* projectObj;
|
||||||
|
Node* sub;
|
||||||
|
Node* next;
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
friend class Project;
|
||||||
|
std::vector<Node> m_nodes;
|
||||||
|
public:
|
||||||
|
const Node* getRootNode() const {return &m_nodes[0];}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructs a full depsgraph of the project-subpath provided
|
||||||
|
* @param path Subpath of project to root depsgraph at
|
||||||
|
* @return Populated depsgraph ready to traverse
|
||||||
|
*/
|
||||||
|
virtual PackageDepsgraph buildPackageDepsgraph(const HECL::ProjectPath& path)=0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -324,204 +293,22 @@ public:
|
||||||
* All necessary database index files and object directories will be established
|
* All necessary database index files and object directories will be established
|
||||||
* within the specified directory path.
|
* within the specified directory path.
|
||||||
*/
|
*/
|
||||||
IProject* OpenProject(const HECL::ProjectRootPath& rootPath);
|
Project* OpenProject(const HECL::ProjectRootPath& rootPath);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Base object to subclass for integrating with key runtime operations
|
* @brief Subclassed by dataspec entries to manage per-game aspects of the data pipeline
|
||||||
*
|
*
|
||||||
* All runtime objects are provided with IDataObject pointers to their database
|
* The DataSpec class manages interfaces for unpackaging, cooking, and packaging
|
||||||
* entries. Subclasses register themselves with a type registry so instances
|
* of data for interacting with a specific system/game-engine.
|
||||||
* are automatically constructed when performing operations like runtime-integration.
|
|
||||||
*
|
|
||||||
* DO NOT CONSTRUCT THIS OR SUBCLASSES DIRECTLY!!
|
|
||||||
*/
|
*/
|
||||||
class CRuntimeObject
|
class IDataSpec
|
||||||
{
|
|
||||||
unsigned m_refCount = 0;
|
|
||||||
bool m_loaded = false;
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Optional subclass method called on background thread or in response to interrupt when data is ready
|
|
||||||
* @param data fully-loaded data buffer
|
|
||||||
* @param len length of buffer
|
|
||||||
* @return true when data is successfully integrated into the runtime
|
|
||||||
*/
|
|
||||||
virtual bool _objectFinishedLoading(const void* data, size_t len)
|
|
||||||
{(void)data;(void)len;return true;}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Optional subclass method called in response to reference-count dropping to 0
|
|
||||||
*/
|
|
||||||
virtual void _objectWillUnload() {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
IDataObject* m_obj;
|
|
||||||
public:
|
|
||||||
struct ConstructionInfo
|
|
||||||
{
|
|
||||||
IDataObject* obj;
|
|
||||||
};
|
|
||||||
CRuntimeObject(const ConstructionInfo& info)
|
|
||||||
: m_obj(info.obj) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Determine if object is fully loaded and constructed
|
|
||||||
* @return true if so
|
|
||||||
*/
|
|
||||||
inline bool isLoaded() const {return m_loaded;}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Increment object's reference count
|
|
||||||
* @return true if already loaded (ready to use) false if load is staged (poll with isLoaded())
|
|
||||||
*
|
|
||||||
* CRuntimeObject instances initially have an internal reference-count of 0.
|
|
||||||
* By calling this method from 0, an asynchronous load operation takes place.
|
|
||||||
* Synchronous loads are discouraged by HECL in order to avoid stalling game
|
|
||||||
* systems. Please poll with isLoaded() to keep things running smoothly!
|
|
||||||
*/
|
|
||||||
bool incRef();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Decrement object's reference count
|
|
||||||
*
|
|
||||||
* If the internal reference-count reaches 0, the object's unload procedure takes place
|
|
||||||
*/
|
|
||||||
void decRef();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Runtime data-management interface
|
|
||||||
*
|
|
||||||
* Interface for controlling runtime data-operations like object lookup
|
|
||||||
* and burst load-transactions. The runtime's implementation automatically
|
|
||||||
* constructs CRuntimeObject instances as needed.
|
|
||||||
*/
|
|
||||||
class IRuntime
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~IRuntime() {}
|
|
||||||
|
|
||||||
/**
|
virtual packageData();
|
||||||
* @brief Lookup singular object by database ID
|
|
||||||
* @param id database ID of object
|
|
||||||
* @return runtime object
|
|
||||||
*/
|
|
||||||
virtual CRuntimeObject* lookupObjectById(size_t id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Iterable group view providing a load interface for Dependency Groups
|
|
||||||
*
|
|
||||||
* HECL uses a background thread or other asynchronous loading mechanism to
|
|
||||||
* efficiently load and construct IRuntimeObject instances.
|
|
||||||
*
|
|
||||||
* The iterator interface may be used immediately to access contained objects.
|
|
||||||
*/
|
|
||||||
class IStagedGroup
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Poll to see if transaction complete
|
|
||||||
* @return true if complete
|
|
||||||
*/
|
|
||||||
virtual bool isDone() const=0;
|
|
||||||
|
|
||||||
virtual std::vector<CRuntimeObject*>::iterator begin() const=0;
|
|
||||||
virtual std::vector<CRuntimeObject*>::iterator end() const=0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Begin asynchronously loading a dependency group by id
|
|
||||||
* @param groupId the id of the dependency group within the database
|
|
||||||
* @return Staged group interface scheduled to load ASAP
|
|
||||||
*/
|
|
||||||
virtual IStagedGroup* loadDependencyGroup(int64_t groupId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Unload a previously-loaded dependency group or cancel a load in-progress
|
|
||||||
* @param group Staged Group obtained via loadDependencyGroup()
|
|
||||||
*/
|
|
||||||
virtual void unloadDependencyGroup(IStagedGroup* group);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Statically-constructed structure registering a FourCC with project
|
|
||||||
* and runtime factories. This is used for constructing key operational subclasses
|
|
||||||
* for cooking/packaging during development and runtime-integrating during gameplay.
|
|
||||||
*/
|
|
||||||
struct RegistryEntry
|
|
||||||
{
|
|
||||||
typedef std::function<bool(const std::string& path, const std::string& subpath)> TPathClaimer;
|
|
||||||
typedef std::function<CProjectObject*(const CProjectObject::ConstructionInfo&)> TProjectFactory;
|
|
||||||
typedef std::function<CRuntimeObject*(const CRuntimeObject::ConstructionInfo&)> TRuntimeFactory;
|
|
||||||
const HECL::FourCC& fcc;
|
|
||||||
#ifndef HECL_STRIP_PROJECT
|
|
||||||
TPathClaimer pathClaimer;
|
|
||||||
TProjectFactory projectFactory;
|
|
||||||
#endif
|
|
||||||
#ifndef HECL_STRIP_RUNTIME
|
|
||||||
TRuntimeFactory runtimeFactory;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
static RegistryEntry::TPathClaimer NULL_PATH_CLAIMER =
|
|
||||||
[](const std::string&, const std::string&) -> bool {return false;};
|
|
||||||
static RegistryEntry::TProjectFactory NULL_PROJECT_FACTORY =
|
|
||||||
[](const HECLDatabase::CProjectObject::ConstructionInfo&)
|
|
||||||
-> HECLDatabase::CProjectObject* {return nullptr;};
|
|
||||||
static RegistryEntry::TRuntimeFactory NULL_RUNTIME_FACTORY =
|
|
||||||
[](const HECLDatabase::CRuntimeObject::ConstructionInfo&)
|
|
||||||
-> HECLDatabase::CRuntimeObject* {return nullptr;};
|
|
||||||
|
|
||||||
#if !defined(HECL_STRIP_PROJECT) && !defined(HECL_STRIP_RUNTIME)
|
|
||||||
|
|
||||||
#define REGISTRY_ENTRY(fourcc, projectClass, runtimeClass) {fourcc, \
|
|
||||||
[](const std::string& path, const std::string& subpath) -> \
|
|
||||||
bool {return projectClass::ClaimPath(path, subpath);}, \
|
|
||||||
[](const HECLDatabase::CProjectObject::ConstructionInfo& info) -> \
|
|
||||||
HECLDatabase::CProjectObject* {return new projectClass(info);}, \
|
|
||||||
[](const HECLDatabase::CRuntimeObject::ConstructionInfo& info) -> \
|
|
||||||
HECLDatabase::CRuntimeObject* {return new runtimeClass(info);}}
|
|
||||||
|
|
||||||
#define REGISTRY_SENTINEL() \
|
|
||||||
{HECL::FourCC(), HECLDatabase::NULL_PATH_CLAIMER, \
|
|
||||||
HECLDatabase::NULL_PROJECT_FACTORY, HECLDatabase::NULL_RUNTIME_FACTORY}
|
|
||||||
|
|
||||||
#elif !defined(HECL_STRIP_PROJECT)
|
|
||||||
|
|
||||||
#define REGISTRY_ENTRY(fourcc, projectClass, runtimeClass) {fourcc, \
|
|
||||||
[](const std::string& path, const std::string& subpath) -> \
|
|
||||||
bool {return projectClass::ClaimPath(path, subpath);}, \
|
|
||||||
[](const HECLDatabase::CProjectObject::ConstructionInfo& info) -> \
|
|
||||||
HECLDatabase::CProjectObject* {return new projectClass(info);}}
|
|
||||||
|
|
||||||
#define REGISTRY_SENTINEL() {HECL::FourCC(), \
|
|
||||||
HECLDatabase::NULL_PATH_CLAIMER, HECLDatabase::NULL_PROJECT_FACTORY}
|
|
||||||
|
|
||||||
#elif !defined(HECL_STRIP_RUNTIME)
|
|
||||||
|
|
||||||
#define REGISTRY_ENTRY(fourcc, projectClass, runtimeClass) {fourcc, \
|
|
||||||
[](const HECLDatabase::CRuntimeObject::ConstructionInfo& info) -> \
|
|
||||||
HECLDatabase::CRuntimeObject* {return new runtimeClass(info);}}
|
|
||||||
|
|
||||||
#define REGISTRY_SENTINEL() {HECL::FourCC(), HECLDatabase::NULL_RUNTIME_FACTORY}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Statically-constructed table of registered types
|
|
||||||
*
|
|
||||||
* Table is defined in dataspec/dataspec.cpp of HECL's codebase.
|
|
||||||
* Developers are encouraged to modify/extend the default data model as
|
|
||||||
* required by their project.
|
|
||||||
*
|
|
||||||
* The REGISTRY_ENTRY macro is a helper for defining entries.
|
|
||||||
* The REGISTRY_SENTINEL must be inserted at the end of the table.
|
|
||||||
*/
|
|
||||||
extern const RegistryEntry DATASPEC_TYPE_REGISTRY[];
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // HECLDATABASE_HPP
|
#endif // HECLDATABASE_HPP
|
||||||
|
|
|
@ -1,4 +1,173 @@
|
||||||
#ifndef HECLRUNTIME_HPP
|
#ifndef HECLRUNTIME_HPP
|
||||||
#define HECLRUNTIME_HPP
|
#define HECLRUNTIME_HPP
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
#include "HECL.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace HECLRuntime
|
||||||
|
{
|
||||||
|
|
||||||
|
class RuntimeEntity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum ERuntimeEntityType
|
||||||
|
{
|
||||||
|
ENTITY_NONE,
|
||||||
|
ENTITY_OBJECT,
|
||||||
|
ENTITY_GROUP
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
ERuntimeEntityType m_type;
|
||||||
|
const std::string& m_path;
|
||||||
|
bool m_loaded = false;
|
||||||
|
|
||||||
|
friend class RuntimeGroup;
|
||||||
|
friend class RuntimeObjectBase;
|
||||||
|
RuntimeEntity(ERuntimeEntityType type, const std::string& path)
|
||||||
|
: m_type(type), m_path(path) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Get type of runtime object
|
||||||
|
* @return Type enum
|
||||||
|
*/
|
||||||
|
inline ERuntimeEntityType getType() const {return m_type;}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get database entity path
|
||||||
|
* @return Path string
|
||||||
|
*/
|
||||||
|
inline const std::string& getPath() const {return m_path;}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Determine if object is fully loaded and constructed
|
||||||
|
* @return true if so
|
||||||
|
*/
|
||||||
|
inline bool isLoaded() const {return m_loaded;}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interface representing a load-ordered group of runtime objects
|
||||||
|
*
|
||||||
|
* HLPK files perform all data retrieval using the notion of 'groups'
|
||||||
|
* Groups are a collection of data objects that have been sequentially packed
|
||||||
|
* in the package file and are constructed in the indexed order of the group.
|
||||||
|
*
|
||||||
|
* RuntimeGroup objects are internally created and weakly-referenced by CRuntime.
|
||||||
|
* RuntimeObject objects are weakly-referenced by RuntimeGroup; they're strongly
|
||||||
|
* referenced by application systems as long as they're needed.
|
||||||
|
*
|
||||||
|
* DO NOT CONSTRUCT THIS DIRECTLY!!
|
||||||
|
*/
|
||||||
|
class RuntimeGroup : public RuntimeEntity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::vector<std::weak_ptr<const class RuntimeObjectBase>> GroupObjectsVector;
|
||||||
|
private:
|
||||||
|
friend class HECLRuntime;
|
||||||
|
GroupObjectsVector m_objects;
|
||||||
|
RuntimeGroup(const std::string& path)
|
||||||
|
: RuntimeEntity(ENTITY_GROUP, path) {}
|
||||||
|
public:
|
||||||
|
inline const GroupObjectsVector& getObjects() const {return m_objects;}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Base object to subclass for integrating with key runtime operations
|
||||||
|
*
|
||||||
|
* All runtime objects are provided with IDataObject pointers to their database
|
||||||
|
* entries. Subclasses register themselves with a type registry so instances
|
||||||
|
* are automatically constructed when performing operations like runtime-integration.
|
||||||
|
*
|
||||||
|
* DO NOT CONSTRUCT THIS OR SUBCLASSES DIRECTLY!!
|
||||||
|
*/
|
||||||
|
class RuntimeObjectBase : public RuntimeEntity
|
||||||
|
{
|
||||||
|
std::shared_ptr<const RuntimeGroup> m_parent;
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Optional subclass method called on background thread or in response to interrupt when data is ready
|
||||||
|
* @param data fully-loaded data buffer
|
||||||
|
* @param len length of buffer
|
||||||
|
* @return true when data is successfully integrated into the runtime
|
||||||
|
*/
|
||||||
|
virtual bool _objectFinishedLoading(const void* data, size_t len)
|
||||||
|
{(void)data;(void)len;return true;}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Optional subclass method called in response to reference-count dropping to 0
|
||||||
|
*/
|
||||||
|
virtual void _objectWillUnload() {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
RuntimeObjectBase(const RuntimeGroup* group, const std::string& path)
|
||||||
|
: RuntimeEntity(ENTITY_OBJECT, path), m_parent(group) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get parent group of object
|
||||||
|
* @return Borrowed pointer of parent RuntimeGroup
|
||||||
|
*/
|
||||||
|
inline const RuntimeGroup* getParentGroup() {return m_parent.get();}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HLPK Runtime data-management root
|
||||||
|
*
|
||||||
|
* Interface for controlling runtime data-operations like object lookup
|
||||||
|
* and burst load-transactions using HLPK packages. The runtime's
|
||||||
|
* implementation automatically constructs RuntimeObjectBase and
|
||||||
|
* RuntimeGroup instances as needed.
|
||||||
|
*/
|
||||||
|
class HECLRuntime
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructs the HECL runtime root
|
||||||
|
* @param hlpkDirectory directory to search for .hlpk files
|
||||||
|
*/
|
||||||
|
HECLRuntime(const HECL::SystemString& hlpkDirectory);
|
||||||
|
~HECLRuntime();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Structure indicating the load status of an object group
|
||||||
|
*/
|
||||||
|
struct SGroupLoadStatus
|
||||||
|
{
|
||||||
|
std::atomic_bool done;
|
||||||
|
std::atomic_size_t completedObjects;
|
||||||
|
std::atomic_size_t totalObjects;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Begin a synchronous group-load transaction
|
||||||
|
* @param pathHash Hashed path string to perform lookup
|
||||||
|
* @return Shared reference to the loading/loaded object
|
||||||
|
*
|
||||||
|
* This method blocks until the entire containing-group is loaded.
|
||||||
|
* Paths to groups or individual objects are accepted.
|
||||||
|
*/
|
||||||
|
std::shared_ptr<RuntimeEntity> loadSync(const HECL::Hash& pathHash);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Begin an asynchronous group-load transaction
|
||||||
|
* @param pathHash Hashed path string to perform lookup
|
||||||
|
* @param statusOut Optional atomically-pollable structure updated with status fields
|
||||||
|
* @return Shared reference to the loading/loaded object
|
||||||
|
*
|
||||||
|
* This method returns once all group entity stubs are constructed.
|
||||||
|
* Paths to groups or individual objects are accepted.
|
||||||
|
*/
|
||||||
|
std::shared_ptr<RuntimeEntity> loadAsync(const HECL::Hash& pathHash,
|
||||||
|
SGroupLoadStatus* statusOut=NULL);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif // HECLRUNTIME_HPP
|
#endif // HECLRUNTIME_HPP
|
||||||
|
|
|
@ -1,9 +1 @@
|
||||||
#include "HECL.hpp"
|
#include "HECL.hpp"
|
||||||
|
|
||||||
#if _WIN32
|
|
||||||
char* win_realpath(const char* name, char* restrict resolved)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
#include "HECL.hpp"
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
char* win_realpath(const char* name, char* restrict resolved)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace HECL
|
||||||
|
{
|
||||||
|
|
||||||
|
static const SystemRegex regGLOB(_S("\\*"), SystemRegex::ECMAScript|SystemRegex::optimize);
|
||||||
|
static const SystemRegex regPATHCOMP(_S("/([^/]+)"), SystemRegex::ECMAScript|SystemRegex::optimize);
|
||||||
|
static const SystemRegex regDRIVELETTER(_S("^([^/]*)/"), SystemRegex::ECMAScript|SystemRegex::optimize);
|
||||||
|
|
||||||
|
bool ProjectPath::_canonAbsPath(const SystemString& path)
|
||||||
|
{
|
||||||
|
#if _WIN32
|
||||||
|
#else
|
||||||
|
SystemChar resolvedPath[PATH_MAX];
|
||||||
|
if (!realpath(path.c_str(), resolvedPath))
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("Unable to resolve '" + CSystemUTF8View(path).utf8_str() +
|
||||||
|
"' as a canonicalized path");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_absPath = resolvedPath;
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectPath::ProjectPath(const ProjectRootPath& rootPath, const SystemString& path)
|
||||||
|
{
|
||||||
|
_canonAbsPath(path);
|
||||||
|
if (m_absPath.size() < ((ProjectPath&)rootPath).m_absPath.size() ||
|
||||||
|
m_absPath.compare(0, ((ProjectPath&)rootPath).m_absPath.size(),
|
||||||
|
((ProjectPath&)rootPath).m_absPath))
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("'" + CSystemUTF8View(m_absPath).utf8_str() + "' is not a subpath of '" +
|
||||||
|
CSystemUTF8View(((ProjectPath&)rootPath).m_absPath).utf8_str() + "'");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_absPath.size() == ((ProjectPath&)rootPath).m_absPath.size())
|
||||||
|
{
|
||||||
|
/* Copies of the project root are permitted */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_relPath = m_absPath.c_str() + ((ProjectPath&)rootPath).m_absPath.size();
|
||||||
|
if (m_relPath[0] == _S('/'))
|
||||||
|
++m_relPath;
|
||||||
|
if (m_relPath[0] == _S('\0'))
|
||||||
|
m_relPath = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectPath::PathType ProjectPath::getPathType()
|
||||||
|
{
|
||||||
|
if (std::regex_search(m_absPath, regGLOB))
|
||||||
|
return PT_GLOB;
|
||||||
|
#if _WIN32
|
||||||
|
#else
|
||||||
|
struct stat theStat;
|
||||||
|
if (stat(m_absPath.c_str(), &theStat))
|
||||||
|
return PT_NONE;
|
||||||
|
if (S_ISDIR(theStat.st_mode))
|
||||||
|
return PT_DIRECTORY;
|
||||||
|
if (S_ISREG(theStat.st_mode))
|
||||||
|
return PT_FILE;
|
||||||
|
return PT_NONE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _recursiveGlob(std::vector<SystemString>& outPaths,
|
||||||
|
size_t level,
|
||||||
|
const SystemRegexMatch& pathCompMatches,
|
||||||
|
const SystemString& itStr,
|
||||||
|
bool needSlash)
|
||||||
|
{
|
||||||
|
if (level >= pathCompMatches.size())
|
||||||
|
return;
|
||||||
|
|
||||||
|
SystemString comp = pathCompMatches.str(level);
|
||||||
|
if (!std::regex_search(comp, regGLOB))
|
||||||
|
{
|
||||||
|
SystemString nextItStr = itStr;
|
||||||
|
if (needSlash)
|
||||||
|
nextItStr += _S('/');
|
||||||
|
nextItStr += comp;
|
||||||
|
_recursiveGlob(outPaths, level+1, pathCompMatches, nextItStr, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compile component into regex */
|
||||||
|
SystemRegex regComp(comp, SystemRegex::ECMAScript);
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
#else
|
||||||
|
DIR* dir = opendir(itStr.c_str());
|
||||||
|
if (!dir)
|
||||||
|
throw std::runtime_error("unable to open directory for traversal at '" + itStr + "'");
|
||||||
|
|
||||||
|
struct dirent* de;
|
||||||
|
while ((de = readdir(dir)))
|
||||||
|
{
|
||||||
|
if (std::regex_search(de->d_name, regComp))
|
||||||
|
{
|
||||||
|
SystemString nextItStr = itStr;
|
||||||
|
if (needSlash)
|
||||||
|
nextItStr += '/';
|
||||||
|
nextItStr += de->d_name;
|
||||||
|
|
||||||
|
struct stat theStat;
|
||||||
|
if (stat(nextItStr.c_str(), &theStat))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (S_ISDIR(theStat.st_mode))
|
||||||
|
_recursiveGlob(outPaths, level+1, pathCompMatches, nextItStr, true);
|
||||||
|
else if (S_ISREG(theStat.st_mode))
|
||||||
|
outPaths.push_back(nextItStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProjectPath::getGlobResults(std::vector<SystemString>& outPaths)
|
||||||
|
{
|
||||||
|
#if _WIN32
|
||||||
|
TSystemPath itStr;
|
||||||
|
SystemRegexMatch letterMatch;
|
||||||
|
if (m_absPath.compare(0, 2, _S("//")))
|
||||||
|
itStr = _S("\\\\");
|
||||||
|
else if (std::regex_search(m_absPath, letterMatch, regDRIVELETTER))
|
||||||
|
if (letterMatch[1].str().size())
|
||||||
|
itStr = letterMatch[1];
|
||||||
|
#else
|
||||||
|
SystemString itStr = _S("/");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SystemRegexMatch pathCompMatches;
|
||||||
|
if (std::regex_search(m_absPath, pathCompMatches, regPATHCOMP))
|
||||||
|
_recursiveGlob(outPaths, 1, pathCompMatches, itStr, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
#include "HECL.hpp"
|
||||||
|
#include <locale>
|
||||||
|
#include <codecvt>
|
||||||
|
|
||||||
|
namespace HECL
|
||||||
|
{
|
||||||
|
|
||||||
|
std::string WideToUTF8(const std::wstring& src)
|
||||||
|
{
|
||||||
|
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||||
|
return conv.to_bytes(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring UTF8ToWide(const std::string& src)
|
||||||
|
{
|
||||||
|
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||||
|
return conv.from_bytes(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,18 +1,125 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
|
||||||
#include "HECLDatabase.hpp"
|
#include "HECLDatabase.hpp"
|
||||||
#include "CSQLiteMain.hpp"
|
|
||||||
|
|
||||||
namespace HECLDatabase
|
namespace HECLDatabase
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static inline bool CheckNewLineAdvance(std::string::const_iterator& it)
|
||||||
|
{
|
||||||
|
if (*it == '\n' || *it == '\0')
|
||||||
|
{
|
||||||
|
it += 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (*it == '\r')
|
||||||
|
{
|
||||||
|
if (*(it+1) == '\n')
|
||||||
|
{
|
||||||
|
it += 2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
class CProject : public IProject
|
class CProject : public IProject
|
||||||
{
|
{
|
||||||
std::string m_rootPath;
|
HECL::SystemString m_rootPath;
|
||||||
CSQLiteMain* m_db;
|
|
||||||
|
class ConfigFile
|
||||||
|
{
|
||||||
|
const CProject& m_project;
|
||||||
|
const HECL::SystemString& m_name;
|
||||||
|
HECL::SystemString m_filepath;
|
||||||
|
public:
|
||||||
|
ConfigFile(const CProject& project, const HECL::SystemString& name)
|
||||||
|
: m_project(project), m_name(name)
|
||||||
|
{
|
||||||
|
m_filepath = project.m_rootPath + _S("/.hecl/config/") + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> readLines()
|
||||||
|
{
|
||||||
|
FILE* fp = HECL::Fopen(m_filepath.c_str(), _S("r"));
|
||||||
|
|
||||||
|
std::string mainString;
|
||||||
|
char readBuf[1024];
|
||||||
|
size_t readSz;
|
||||||
|
while ((readSz = fread(readBuf, 1, 1024, fp)))
|
||||||
|
mainString += std::string(readBuf, readSz);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
std::string::const_iterator begin = mainString.begin();
|
||||||
|
std::string::const_iterator end = mainString.begin();
|
||||||
|
|
||||||
|
std::vector<std::string> retval;
|
||||||
|
while (end != mainString.end())
|
||||||
|
{
|
||||||
|
std::string::const_iterator origEnd = end;
|
||||||
|
if (CheckNewLineAdvance(end))
|
||||||
|
{
|
||||||
|
if (begin != origEnd)
|
||||||
|
retval.push_back(std::string(begin, origEnd));
|
||||||
|
begin = end;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++end;
|
||||||
|
}
|
||||||
|
if (begin != end)
|
||||||
|
retval.push_back(std::string(begin, end));
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addLine(const std::string& line)
|
||||||
|
{
|
||||||
|
std::vector<std::string> curLines = readLines();
|
||||||
|
|
||||||
|
FILE* fp = HECL::Fopen(m_filepath.c_str(), _S("w"));
|
||||||
|
for (std::string& line : curLines)
|
||||||
|
{
|
||||||
|
fwrite(line.data(), 1, line.length(), fp);
|
||||||
|
fwrite("\n", 1, 1, fp);
|
||||||
|
}
|
||||||
|
fwrite(line.data(), 1, line.length(), fp);
|
||||||
|
fwrite("\n", 1, 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeLine(const std::string& refLine)
|
||||||
|
{
|
||||||
|
std::vector<std::string> curLines = readLines();
|
||||||
|
|
||||||
|
FILE* fp = HECL::Fopen(m_filepath.c_str(), _S("w"));
|
||||||
|
for (std::string& line : curLines)
|
||||||
|
{
|
||||||
|
if (line.compare(refLine))
|
||||||
|
{
|
||||||
|
fwrite(line.data(), 1, line.length(), fp);
|
||||||
|
fwrite("\n", 1, 1, fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkForLine(const std::string& refLine)
|
||||||
|
{
|
||||||
|
std::vector<std::string> curLines = readLines();
|
||||||
|
for (std::string& line : curLines)
|
||||||
|
{
|
||||||
|
if (!line.compare(refLine))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CProject(const std::string& rootPath)
|
CProject(const std::string& rootPath)
|
||||||
: m_rootPath(rootPath)
|
: m_rootPath(rootPath)
|
||||||
|
@ -25,20 +132,16 @@ public:
|
||||||
if (!S_ISDIR(myStat.st_mode))
|
if (!S_ISDIR(myStat.st_mode))
|
||||||
throw std::invalid_argument("provided path must be a directory; '" + m_rootPath + "' isn't");
|
throw std::invalid_argument("provided path must be a directory; '" + m_rootPath + "' isn't");
|
||||||
|
|
||||||
/* Create project directory */
|
/* Create project directory structure */
|
||||||
if (mkdir((m_rootPath + "/.hecl").c_str(), 0755))
|
HECL::MakeDir(m_rootPath + "/.hecl");
|
||||||
{
|
HECL::MakeDir(m_rootPath + "/.hecl/cooked");
|
||||||
if (errno != EEXIST)
|
HECL::MakeDir(m_rootPath + "/.hecl/config");
|
||||||
throw std::error_code(errno, std::system_category());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create or open databases */
|
/* Create or open databases */
|
||||||
m_db = new CSQLiteMain(m_rootPath + "/.hecl/main.db");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~CProject()
|
~CProject()
|
||||||
{
|
{
|
||||||
delete m_db;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerLogger(HECL::TLogger logger)
|
void registerLogger(HECL::TLogger logger)
|
||||||
|
@ -49,11 +152,11 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool addPath(const std::string& path)
|
bool addPaths(const std::vector<HECL::ProjectPath>& paths)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool removePath(const std::string& path, bool recursive)
|
bool removePaths(const std::vector<HECL::ProjectPath>& paths, bool recursive)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +168,18 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::map<const std::string, const bool>& listPlatforms()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool enablePlatforms(const std::vector<std::string>& platforms)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool disablePlatforms(const std::vector<std::string>& platforms)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool cookPath(const std::string& path,
|
bool cookPath(const std::string& path,
|
||||||
std::function<void(std::string&, Cost, unsigned)> feedbackCb,
|
std::function<void(std::string&, Cost, unsigned)> feedbackCb,
|
||||||
bool recursive)
|
bool recursive)
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
|
|
||||||
#include "HECLDatabase.hpp"
|
|
||||||
#include "CSQLiteMain.hpp"
|
|
||||||
|
|
||||||
namespace HECLDatabase
|
|
||||||
{
|
|
||||||
|
|
||||||
class CRuntime : public IRuntime
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,82 +0,0 @@
|
||||||
#ifndef CSQLITECOOKED_HPP
|
|
||||||
#define CSQLITECOOKED_HPP
|
|
||||||
|
|
||||||
#include <sqlite3.h>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include "HECLDatabase.hpp"
|
|
||||||
#include "sqlite_hecl_vfs.h"
|
|
||||||
|
|
||||||
namespace HECLDatabase
|
|
||||||
{
|
|
||||||
|
|
||||||
static const char* skCOOKEDDBINIT =
|
|
||||||
"PRAGMA foreign_keys = ON;\n"
|
|
||||||
"CREATE TABLE IF NOT EXISTS cgrps("
|
|
||||||
"grpid INTEGER PRIMARY KEY," /* Unique group identifier (from main DB) */
|
|
||||||
"offset UNSIGNED INTEGER," /* Group-blob offset within package */
|
|
||||||
"compLen UNSIGNED INTEGER," /* Compressed blob-length */
|
|
||||||
"decompLen UNSIGNED INTEGER);\n" /* Decompressed blob-length */
|
|
||||||
"CREATE TABLE IF NOT EXISTS cobjs("
|
|
||||||
"objid INTEGER PRIMARY KEY," /* Unique object identifier (from main DB) */
|
|
||||||
"type4cc UNSIGNED INTEGER," /* Type FourCC as claimed by first project class in dataspec */
|
|
||||||
"loosegrp REFERENCES cgrps(grpid) ON DELETE SET NULL DEFAULT NULL);\n" /* single-object group of ungrouped object */
|
|
||||||
"CREATE TABLE IF NOT EXISTS cgrplinks("
|
|
||||||
"grpid REFERENCES cgrps(grpid) ON DELETE CASCADE," /* Group ref */
|
|
||||||
"objid REFERENCES cobjs(objid) ON DELETE CASCADE," /* Object ref */
|
|
||||||
"offset UNSIGNED INTEGER," /* Offset within decompressed group-blob */
|
|
||||||
"decompLen UNSIGNED INTEGER," /* Decompressed object length */
|
|
||||||
"UNIQUE (grpid, objid) ON CONFLICT IGNORE);\n"
|
|
||||||
"CREATE INDEX IF NOT EXISTS grpidx ON cgrplinks(grpid);\n";
|
|
||||||
|
|
||||||
#define PREPSTMT(stmtSrc, outVar)\
|
|
||||||
if (sqlite3_prepare_v2(m_db, stmtSrc, 0, &outVar, NULL) != SQLITE_OK)\
|
|
||||||
{\
|
|
||||||
throw std::runtime_error(sqlite3_errmsg(m_db));\
|
|
||||||
sqlite3_close(m_db);\
|
|
||||||
return;\
|
|
||||||
}
|
|
||||||
|
|
||||||
class CSQLiteCooked
|
|
||||||
{
|
|
||||||
sqlite3* m_db;
|
|
||||||
|
|
||||||
public:
|
|
||||||
CSQLiteCooked(const char* path, bool readonly)
|
|
||||||
{
|
|
||||||
/* Open database connection */
|
|
||||||
int errCode = 0;
|
|
||||||
if ((errCode = sqlite3_open_v2(path, &m_db, SQLITE_OPEN_READONLY,
|
|
||||||
"hecl_memlba")) != SQLITE_OK)
|
|
||||||
{
|
|
||||||
throw std::runtime_error(sqlite3_errstr(errCode));
|
|
||||||
sqlite3_close(m_db);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Execute bootstrap statements */
|
|
||||||
char* errMsg = NULL;
|
|
||||||
sqlite3_exec(m_db, skCOOKEDDBINIT, NULL, NULL, &errMsg);
|
|
||||||
if (errMsg)
|
|
||||||
{
|
|
||||||
throw std::runtime_error(errMsg);
|
|
||||||
sqlite3_free(errMsg);
|
|
||||||
sqlite3_close(m_db);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Precompile statements */
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
~CSQLiteCooked()
|
|
||||||
{
|
|
||||||
sqlite3_close(m_db);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // CSQLITE_HPP
|
|
|
@ -1,134 +0,0 @@
|
||||||
#ifndef CSQLITEMAIN_HPP
|
|
||||||
#define CSQLITEMAIN_HPP
|
|
||||||
|
|
||||||
#include <sqlite3.h>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include "HECLDatabase.hpp"
|
|
||||||
#include "sqlite_hecl_vfs.h"
|
|
||||||
|
|
||||||
namespace HECLDatabase
|
|
||||||
{
|
|
||||||
|
|
||||||
static const char* skMAINDBINIT =
|
|
||||||
"PRAGMA foreign_keys = ON;\n"
|
|
||||||
"CREATE TABLE IF NOT EXISTS grps("
|
|
||||||
"grpid INTEGER PRIMARY KEY," /* Unique group identifier (used as in-game ref) */
|
|
||||||
"path);\n" /* Directory path collecting working files for group */
|
|
||||||
"CREATE TABLE IF NOT EXISTS objs("
|
|
||||||
"objid INTEGER PRIMARY KEY," /* Unique object identifier (used as in-game ref) */
|
|
||||||
"path," /* Path of working file */
|
|
||||||
"subpath DEFAULT NULL," /* String name of sub-object within working file (i.e. blender object) */
|
|
||||||
"cookedHash64 INTEGER DEFAULT NULL," /* Hash of last cooking pass */
|
|
||||||
"cookedTime64 INTEGER DEFAULT NULL);\n"; /* UTC unix-time of last cooking pass */
|
|
||||||
|
|
||||||
#define PREPSTMT(stmtSrc, outVar)\
|
|
||||||
if (sqlite3_prepare_v2(m_db, stmtSrc, 0, &outVar, NULL) != SQLITE_OK)\
|
|
||||||
{\
|
|
||||||
throw std::runtime_error(sqlite3_errmsg(m_db));\
|
|
||||||
sqlite3_close(m_db);\
|
|
||||||
return;\
|
|
||||||
}
|
|
||||||
|
|
||||||
class CSQLiteMain
|
|
||||||
{
|
|
||||||
sqlite3* m_db;
|
|
||||||
|
|
||||||
struct SCloseBuf
|
|
||||||
{
|
|
||||||
void* buf = NULL;
|
|
||||||
size_t sz = 0;
|
|
||||||
};
|
|
||||||
static void _vfsClose(void* buf, size_t bufSz, SCloseBuf* ctx)
|
|
||||||
{
|
|
||||||
ctx->buf = buf;
|
|
||||||
ctx->sz = bufSz;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
CSQLiteMain(const std::string& path)
|
|
||||||
{
|
|
||||||
/* Open database connection */
|
|
||||||
int errCode = 0;
|
|
||||||
if ((errCode = sqlite3_open(path.c_str(), &m_db) != SQLITE_OK))
|
|
||||||
{
|
|
||||||
throw std::runtime_error(sqlite3_errstr(errCode));
|
|
||||||
sqlite3_close(m_db);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Execute bootstrap statements */
|
|
||||||
char* errMsg = NULL;
|
|
||||||
sqlite3_exec(m_db, skMAINDBINIT, NULL, NULL, &errMsg);
|
|
||||||
if (errMsg)
|
|
||||||
{
|
|
||||||
throw std::runtime_error(errMsg);
|
|
||||||
sqlite3_free(errMsg);
|
|
||||||
sqlite3_close(m_db);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Precompile statements */
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
~CSQLiteMain()
|
|
||||||
{
|
|
||||||
sqlite3_close(m_db);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void* fillDBBuffer(size_t& bufSzOut) const
|
|
||||||
{
|
|
||||||
/* Instructs vfs that a close operation is premature and buffer should be freed */
|
|
||||||
sqlite_hecl_mem_vfs_register(NULL, NULL);
|
|
||||||
|
|
||||||
/* Open pure-memory DB */
|
|
||||||
sqlite3* memDb;
|
|
||||||
int errCode;
|
|
||||||
if ((errCode = sqlite3_open_v2("", &memDb, SQLITE_OPEN_READWRITE, "hecl_mem")) != SQLITE_OK)
|
|
||||||
{
|
|
||||||
throw std::runtime_error(sqlite3_errstr(errCode));
|
|
||||||
sqlite3_close(memDb);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Perform backup (row copy) */
|
|
||||||
sqlite3_backup* backup = sqlite3_backup_init(memDb, "main", m_db, "main");
|
|
||||||
if (!backup)
|
|
||||||
{
|
|
||||||
throw std::runtime_error(sqlite3_errmsg(memDb));
|
|
||||||
sqlite3_close(memDb);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
sqlite3_backup_step(backup, -1);
|
|
||||||
sqlite3_backup_finish(backup);
|
|
||||||
|
|
||||||
/* Now a close operation is useful; register close callback */
|
|
||||||
SCloseBuf closeBuf;
|
|
||||||
sqlite_hecl_mem_vfs_register((TCloseCallback)_vfsClose, &closeBuf);
|
|
||||||
sqlite3_close(memDb);
|
|
||||||
|
|
||||||
/* This should be set by close callback */
|
|
||||||
if (!closeBuf.buf)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("close operation did not write buffer");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* All good! */
|
|
||||||
bufSzOut = closeBuf.sz;
|
|
||||||
return closeBuf.buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void freeDBBuffer(void* buf)
|
|
||||||
{
|
|
||||||
sqlite3_free(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // CSQLITEMAIN_HPP
|
|
|
@ -1,11 +1,4 @@
|
||||||
HEADERS += \
|
HEADERS +=
|
||||||
$$PWD/sqlite_hecl_vfs.h \
|
|
||||||
$$PWD/CSQLiteMain.hpp \
|
|
||||||
$$PWD/CSQLiteCooked.hpp
|
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/CRuntime.cpp \
|
$$PWD/CProject.cpp
|
||||||
$$PWD/CProject.cpp \
|
|
||||||
$$PWD/sqlite_hecl_mem_vfs.c \
|
|
||||||
$$PWD/sqlite_hecl_memlba_vfs.c \
|
|
||||||
$$PWD/sqlite_hecl_memlba_make.c
|
|
||||||
|
|
|
@ -1,386 +0,0 @@
|
||||||
#include "sqlite_hecl_vfs.h"
|
|
||||||
|
|
||||||
#include "sqlite3.h"
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Modified test_onefile.c VFS for sqlite3
|
|
||||||
*
|
|
||||||
* This VFS gets registered with sqlite to access an in-memory,
|
|
||||||
* block-compressed LBA. It's designed for read-only access of
|
|
||||||
* a packed object-database.
|
|
||||||
*
|
|
||||||
* Journal and temp read/write is unsupported and will call abort
|
|
||||||
* if attempted.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* App-supplied callback called when file is closed (ready to access)
|
|
||||||
*/
|
|
||||||
static TCloseCallback CLOSE_CALLBACK = NULL;
|
|
||||||
static void* CLOSE_CTX = NULL;
|
|
||||||
|
|
||||||
typedef struct mem_file mem_file;
|
|
||||||
struct mem_file
|
|
||||||
{
|
|
||||||
sqlite3_file base;
|
|
||||||
int nSize;
|
|
||||||
int nAlloc;
|
|
||||||
char* zAlloc;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Method declarations for mem_file.
|
|
||||||
*/
|
|
||||||
static int memClose(sqlite3_file*);
|
|
||||||
static int memRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
|
|
||||||
static int memWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
|
|
||||||
static int memTruncate(sqlite3_file*, sqlite3_int64 size);
|
|
||||||
static int memSync(sqlite3_file*, int flags);
|
|
||||||
static int memFileSize(sqlite3_file*, sqlite3_int64* pSize);
|
|
||||||
static int memLock(sqlite3_file*, int);
|
|
||||||
static int memUnlock(sqlite3_file*, int);
|
|
||||||
static int memCheckReservedLock(sqlite3_file*, int* pResOut);
|
|
||||||
static int memFileControl(sqlite3_file*, int op, void* pArg);
|
|
||||||
static int memSectorSize(sqlite3_file*);
|
|
||||||
static int memDeviceCharacteristics(sqlite3_file*);
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Method declarations for fs_vfs.
|
|
||||||
*/
|
|
||||||
static int memOpen(sqlite3_vfs*, const char*, sqlite3_file*, int , int*);
|
|
||||||
static int memDelete(sqlite3_vfs*, const char* zName, int syncDir);
|
|
||||||
static int memAccess(sqlite3_vfs*, const char* zName, int flags, int*);
|
|
||||||
static int memFullPathname(sqlite3_vfs*, const char* zName, int nOut, char* zOut);
|
|
||||||
static void* memDlOpen(sqlite3_vfs*, const char* zFilename);
|
|
||||||
static void memDlError(sqlite3_vfs*, int nByte, char* zErrMsg);
|
|
||||||
static void (*memDlSym(sqlite3_vfs*, void*, const char* zSymbol))(void);
|
|
||||||
static void memDlClose(sqlite3_vfs*, void*);
|
|
||||||
static int memRandomness(sqlite3_vfs*, int nByte, char* zOut);
|
|
||||||
static int memSleep(sqlite3_vfs*, int microseconds);
|
|
||||||
static int memCurrentTime(sqlite3_vfs*, double*);
|
|
||||||
|
|
||||||
static sqlite3_vfs mem_vfs =
|
|
||||||
{
|
|
||||||
1, /* iVersion */
|
|
||||||
0, /* szOsFile */
|
|
||||||
0, /* mxPathname */
|
|
||||||
0, /* pNext */
|
|
||||||
"hecl_mem", /* zName */
|
|
||||||
0, /* pAppData */
|
|
||||||
memOpen, /* xOpen */
|
|
||||||
memDelete, /* xDelete */
|
|
||||||
memAccess, /* xAccess */
|
|
||||||
memFullPathname, /* xFullPathname */
|
|
||||||
memDlOpen, /* xDlOpen */
|
|
||||||
memDlError, /* xDlError */
|
|
||||||
memDlSym, /* xDlSym */
|
|
||||||
memDlClose, /* xDlClose */
|
|
||||||
memRandomness, /* xRandomness */
|
|
||||||
memSleep, /* xSleep */
|
|
||||||
memCurrentTime, /* xCurrentTime */
|
|
||||||
0 /* xCurrentTimeInt64 */
|
|
||||||
};
|
|
||||||
|
|
||||||
static sqlite3_io_methods mem_io_methods =
|
|
||||||
{
|
|
||||||
1, /* iVersion */
|
|
||||||
memClose, /* xClose */
|
|
||||||
memRead, /* xRead */
|
|
||||||
memWrite, /* xWrite */
|
|
||||||
memTruncate, /* xTruncate */
|
|
||||||
memSync, /* xSync */
|
|
||||||
memFileSize, /* xFileSize */
|
|
||||||
memLock, /* xLock */
|
|
||||||
memUnlock, /* xUnlock */
|
|
||||||
memCheckReservedLock, /* xCheckReservedLock */
|
|
||||||
memFileControl, /* xFileControl */
|
|
||||||
memSectorSize, /* xSectorSize */
|
|
||||||
memDeviceCharacteristics, /* xDeviceCharacteristics */
|
|
||||||
0, /* xShmMap */
|
|
||||||
0, /* xShmLock */
|
|
||||||
0, /* xShmBarrier */
|
|
||||||
0, /* xShmUnmap */
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Useful macros used in several places */
|
|
||||||
#define MIN(x,y) ((x)<(y)?(x):(y))
|
|
||||||
#define MAX(x,y) ((x)>(y)?(x):(y))
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Close a mem-file.
|
|
||||||
*/
|
|
||||||
static int memClose(sqlite3_file* pFile)
|
|
||||||
{
|
|
||||||
mem_file* pTmp = (mem_file*)pFile;
|
|
||||||
if(CLOSE_CALLBACK)
|
|
||||||
CLOSE_CALLBACK(pTmp->zAlloc, pTmp->nSize, CLOSE_CTX);
|
|
||||||
else
|
|
||||||
sqlite3_free(pTmp->zAlloc);
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Read data from a mem-file.
|
|
||||||
*/
|
|
||||||
static int memRead(
|
|
||||||
sqlite3_file* pFile,
|
|
||||||
void* zBuf,
|
|
||||||
int iAmt,
|
|
||||||
sqlite_int64 iOfst
|
|
||||||
)
|
|
||||||
{
|
|
||||||
mem_file* pTmp = (mem_file*)pFile;
|
|
||||||
if((iAmt + iOfst) > pTmp->nSize)
|
|
||||||
return SQLITE_IOERR_SHORT_READ;
|
|
||||||
memcpy(zBuf, &pTmp->zAlloc[iOfst], iAmt);
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Write data to a mem-file.
|
|
||||||
*/
|
|
||||||
static int memWrite(
|
|
||||||
sqlite3_file* pFile,
|
|
||||||
const void* zBuf,
|
|
||||||
int iAmt,
|
|
||||||
sqlite_int64 iOfst
|
|
||||||
)
|
|
||||||
{
|
|
||||||
mem_file* pTmp = (mem_file*)pFile;
|
|
||||||
if((iAmt + iOfst) > pTmp->nAlloc)
|
|
||||||
{
|
|
||||||
int nNew = (int)(2 * (iAmt + iOfst + pTmp->nAlloc));
|
|
||||||
char* zNew = sqlite3_realloc(pTmp->zAlloc, nNew);
|
|
||||||
if(!zNew)
|
|
||||||
return SQLITE_NOMEM;
|
|
||||||
pTmp->zAlloc = zNew;
|
|
||||||
pTmp->nAlloc = nNew;
|
|
||||||
}
|
|
||||||
memcpy(&pTmp->zAlloc[iOfst], zBuf, iAmt);
|
|
||||||
pTmp->nSize = (int)MAX(pTmp->nSize, iOfst + iAmt);
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Truncate a mem-file.
|
|
||||||
*/
|
|
||||||
static int memTruncate(sqlite3_file* pFile, sqlite_int64 size)
|
|
||||||
{
|
|
||||||
mem_file* pTmp = (mem_file*)pFile;
|
|
||||||
pTmp->nSize = (int)MIN(pTmp->nSize, size);
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Sync a mem-file.
|
|
||||||
*/
|
|
||||||
static int memSync(sqlite3_file* pFile, int flags)
|
|
||||||
{
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Return the current file-size of a mem-file.
|
|
||||||
*/
|
|
||||||
static int memFileSize(sqlite3_file* pFile, sqlite_int64* pSize)
|
|
||||||
{
|
|
||||||
mem_file* pTmp = (mem_file*)pFile;
|
|
||||||
*pSize = pTmp->nSize;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Lock a mem-file.
|
|
||||||
*/
|
|
||||||
static int memLock(sqlite3_file* pFile, int eLock)
|
|
||||||
{
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Unlock a mem-file.
|
|
||||||
*/
|
|
||||||
static int memUnlock(sqlite3_file* pFile, int eLock)
|
|
||||||
{
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Check if another file-handle holds a RESERVED lock on a mem-file.
|
|
||||||
*/
|
|
||||||
static int memCheckReservedLock(sqlite3_file* pFile, int* pResOut)
|
|
||||||
{
|
|
||||||
*pResOut = 0;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** File control method. For custom operations on a mem-file.
|
|
||||||
*/
|
|
||||||
static int memFileControl(sqlite3_file* pFile, int op, void* pArg)
|
|
||||||
{
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Return the sector-size in bytes for a mem-file.
|
|
||||||
*/
|
|
||||||
static int memSectorSize(sqlite3_file* pFile)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Return the device characteristic flags supported by a mem-file.
|
|
||||||
*/
|
|
||||||
static int memDeviceCharacteristics(sqlite3_file* pFile)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Open an mem file handle.
|
|
||||||
*/
|
|
||||||
static int memOpen(
|
|
||||||
sqlite3_vfs* pVfs,
|
|
||||||
const char* zName,
|
|
||||||
sqlite3_file* pFile,
|
|
||||||
int flags,
|
|
||||||
int* pOutFlags
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if ((flags & SQLITE_OPEN_MAIN_DB) != SQLITE_OPEN_MAIN_DB)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "the sqlite hecl mem VFS only supports main-db reading/writing\n");
|
|
||||||
return SQLITE_CANTOPEN;
|
|
||||||
}
|
|
||||||
mem_file* p2 = (mem_file*)pFile;
|
|
||||||
memset(p2, 0, sizeof(*p2));
|
|
||||||
p2->base.pMethods = &mem_io_methods;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Delete the file located at zPath. If the dirSync argument is true,
|
|
||||||
** ensure the file-system modifications are synced to disk before
|
|
||||||
** returning.
|
|
||||||
*/
|
|
||||||
static int memDelete(sqlite3_vfs* pVfs, const char* zPath, int dirSync)
|
|
||||||
{
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Test for access permissions. Return true if the requested permission
|
|
||||||
** is available, or false otherwise.
|
|
||||||
*/
|
|
||||||
static int memAccess(
|
|
||||||
sqlite3_vfs* pVfs,
|
|
||||||
const char* zPath,
|
|
||||||
int flags,
|
|
||||||
int* pResOut
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if(flags & SQLITE_ACCESS_READ | SQLITE_ACCESS_READWRITE)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Populate buffer zOut with the full canonical pathname corresponding
|
|
||||||
** to the pathname in zPath. zOut is guaranteed to point to a buffer
|
|
||||||
** of at least (FS_MAX_PATHNAME+1) bytes.
|
|
||||||
*/
|
|
||||||
static int memFullPathname(
|
|
||||||
sqlite3_vfs* pVfs, /* Pointer to vfs object */
|
|
||||||
const char* zPath, /* Possibly relative input path */
|
|
||||||
int nOut, /* Size of output buffer in bytes */
|
|
||||||
char* zOut) /* Output buffer */
|
|
||||||
{
|
|
||||||
strncpy(zOut, zPath, nOut);
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Open the dynamic library located at zPath and return a handle.
|
|
||||||
*/
|
|
||||||
static void* memDlOpen(sqlite3_vfs* pVfs, const char* zPath)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Populate the buffer zErrMsg (size nByte bytes) with a human readable
|
|
||||||
** utf-8 string describing the most recent error encountered associated
|
|
||||||
** with dynamic libraries.
|
|
||||||
*/
|
|
||||||
static void memDlError(sqlite3_vfs* pVfs, int nByte, char* zErrMsg)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
|
|
||||||
*/
|
|
||||||
static void (*memDlSym(sqlite3_vfs* pVfs, void* pH, const char* zSym))(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Close the dynamic library handle pHandle.
|
|
||||||
*/
|
|
||||||
static void memDlClose(sqlite3_vfs* pVfs, void* pHandle)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Populate the buffer pointed to by zBufOut with nByte bytes of
|
|
||||||
** random data.
|
|
||||||
*/
|
|
||||||
static int memRandomness(sqlite3_vfs* pVfs, int nByte, char* zBufOut)
|
|
||||||
{
|
|
||||||
for(int i = 0 ; i < nByte ; ++i)
|
|
||||||
zBufOut[i] = rand();
|
|
||||||
return nByte;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Sleep for nMicro microseconds. Return the number of microseconds
|
|
||||||
** actually slept.
|
|
||||||
*/
|
|
||||||
static int memSleep(sqlite3_vfs* pVfs, int nMicro)
|
|
||||||
{
|
|
||||||
int seconds = (nMicro + 999999) / 1000000;
|
|
||||||
sleep(seconds);
|
|
||||||
return seconds * 1000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Return the current time as a Julian Day number in *pTimeOut.
|
|
||||||
*/
|
|
||||||
static int memCurrentTime(sqlite3_vfs* pVfs, double* pTimeOut)
|
|
||||||
{
|
|
||||||
*pTimeOut = 0.0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This procedure registers the mem vfs with SQLite. If the argument is
|
|
||||||
** true, the mem vfs becomes the new default vfs. It is the only publicly
|
|
||||||
** available function in this file.
|
|
||||||
*/
|
|
||||||
int sqlite_hecl_mem_vfs_register(TCloseCallback closeCb, void* ctx)
|
|
||||||
{
|
|
||||||
CLOSE_CALLBACK = closeCb;
|
|
||||||
CLOSE_CTX = ctx;
|
|
||||||
if(mem_vfs.szOsFile) return SQLITE_OK;
|
|
||||||
mem_vfs.szOsFile = sizeof(mem_file);
|
|
||||||
return sqlite3_vfs_register(&mem_vfs, 0);
|
|
||||||
}
|
|
|
@ -1,108 +0,0 @@
|
||||||
#include "sqlite_hecl_vfs.h"
|
|
||||||
#include <zlib/zlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Block-compression LBA generator used for storing packed sqlite3 database
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define BLOCK_SIZE 0x4000
|
|
||||||
#define ROUND_UP_BLOCK(val) (((val) + (BLOCK_SIZE-1)) & ~(BLOCK_SIZE-1))
|
|
||||||
|
|
||||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
|
||||||
static inline uint32_t makeu32(uint32_t val, bool bigEndian)
|
|
||||||
{
|
|
||||||
if (!bigEndian)
|
|
||||||
return val;
|
|
||||||
#if __GNUC__
|
|
||||||
return __builtin_bswap32(val);
|
|
||||||
#elif _WIN32
|
|
||||||
return _byteswap_ulong(val);
|
|
||||||
#else
|
|
||||||
val = (val & 0x0000FFFF) << 16 | (val & 0xFFFF0000) >> 16;
|
|
||||||
val = (val & 0x00FF00FF) << 8 | (val & 0xFF00FF00) >> 8;
|
|
||||||
return val;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static inline uint32_t makeu32(uint32_t val, bool bigEndian)
|
|
||||||
{
|
|
||||||
if (bigEndian)
|
|
||||||
return val;
|
|
||||||
#if __GNUC__
|
|
||||||
return __builtin_bswap32(val);
|
|
||||||
#elif _WIN32
|
|
||||||
return _byteswap_ulong(val);
|
|
||||||
#else
|
|
||||||
val = (val & 0x0000FFFF) << 16 | (val & 0xFFFF0000) >> 16;
|
|
||||||
val = (val & 0x00FF00FF) << 8 | (val & 0xFF00FF00) >> 8;
|
|
||||||
return val;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Useful macros used in several places */
|
|
||||||
#define MIN(x,y) ((x)<(y)?(x):(y))
|
|
||||||
#define MAX(x,y) ((x)>(y)?(x):(y))
|
|
||||||
|
|
||||||
void sqlite_hecl_memlba_make(FILE* fout, void* bufin, size_t bufinLen, bool bigEndian)
|
|
||||||
{
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
/* Magic */
|
|
||||||
fwrite("HLPK", 1, 4, fout);
|
|
||||||
|
|
||||||
/* Block size */
|
|
||||||
uint32_t blockSize_s = makeu32(BLOCK_SIZE, bigEndian);
|
|
||||||
fwrite(&blockSize_s, 1, 4, fout);
|
|
||||||
|
|
||||||
/* Block count */
|
|
||||||
size_t blockCount = ROUND_UP_BLOCK(bufinLen) / BLOCK_SIZE;
|
|
||||||
uint32_t blockCount_s = makeu32(blockCount, bigEndian);
|
|
||||||
fwrite(&blockCount_s, 1, 4, fout);
|
|
||||||
|
|
||||||
/* Header+TOC+DB Size */
|
|
||||||
fwrite("\0\0\0\0", 1, 4, fout);
|
|
||||||
|
|
||||||
/* Block TOC buffer and file-space */
|
|
||||||
uint32_t* blockTOC = calloc(blockCount+1, 4);
|
|
||||||
for (i=0 ; i<blockCount+1 ; ++i)
|
|
||||||
fwrite("\0\0\0\0", 1, 4, fout);
|
|
||||||
|
|
||||||
/* Block-compression context */
|
|
||||||
z_stream zstrm = {};
|
|
||||||
deflateInit(&zstrm, 7);
|
|
||||||
zstrm.next_in = bufin;
|
|
||||||
|
|
||||||
/* Compress! */
|
|
||||||
size_t curOff = 16 + (blockCount+1) * 4;
|
|
||||||
size_t remSz = bufinLen;
|
|
||||||
for (i=0 ; i<blockCount ; ++i)
|
|
||||||
{
|
|
||||||
unsigned char compBuf[BLOCK_SIZE*2];
|
|
||||||
zstrm.avail_in = MIN(remSz, BLOCK_SIZE);
|
|
||||||
zstrm.avail_out = BLOCK_SIZE*2;
|
|
||||||
zstrm.next_out = compBuf;
|
|
||||||
deflate(&zstrm, Z_FINISH);
|
|
||||||
fwrite(compBuf, 1, zstrm.total_out, fout);
|
|
||||||
blockTOC[i] = makeu32(curOff, bigEndian);
|
|
||||||
curOff += zstrm.total_out;
|
|
||||||
remSz -= zstrm.total_in;
|
|
||||||
deflateReset(&zstrm);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write Header+TOC+DB Size */
|
|
||||||
fseek(fout, 12, SEEK_SET);
|
|
||||||
uint32_t headSz_s = makeu32(curOff, bigEndian);
|
|
||||||
fwrite(&headSz_s, 1, 4, fout);
|
|
||||||
|
|
||||||
/* Write TOC */
|
|
||||||
blockTOC[blockCount] = headSz_s;
|
|
||||||
fwrite(blockTOC, 4, blockCount+1, fout);
|
|
||||||
|
|
||||||
/* Cleanup */
|
|
||||||
deflateEnd(&zstrm);
|
|
||||||
free(blockTOC);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,493 +0,0 @@
|
||||||
#include "sqlite_hecl_vfs.h"
|
|
||||||
|
|
||||||
#include "sqlite3.h"
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <zlib/zlib.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Modified test_onefile.c VFS for sqlite3
|
|
||||||
*
|
|
||||||
* This VFS gets registered with sqlite to access an in-memory,
|
|
||||||
* block-compressed LBA. It's designed for read-only access of
|
|
||||||
* a packed object-database.
|
|
||||||
*
|
|
||||||
* Journal and temp read/write is unsupported and will call abort
|
|
||||||
* if attempted.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* App-supplied pointer to head buffer (Header+TOC+DB)
|
|
||||||
*/
|
|
||||||
static void* HEAD_BUF = NULL;
|
|
||||||
|
|
||||||
#define BLOCK_SLOTS 4
|
|
||||||
|
|
||||||
typedef struct memlba_file memlba_file;
|
|
||||||
struct memlba_file
|
|
||||||
{
|
|
||||||
sqlite3_file base;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
char magic[4];
|
|
||||||
uint32_t blockSize;
|
|
||||||
uint32_t blockCount;
|
|
||||||
uint32_t headSz;
|
|
||||||
uint32_t blockTOC[];
|
|
||||||
}* headBuf;
|
|
||||||
void* cachedBlockBufs[BLOCK_SLOTS];
|
|
||||||
/* All initialized to -1 */
|
|
||||||
int cachedBlockIndices[BLOCK_SLOTS];
|
|
||||||
/* Ages start at 0, newly inserted block is 1.
|
|
||||||
* Non-0 blocks incremented on every insertion.
|
|
||||||
* If any slot is BLOCK_SLOTS upon insertion, surrounding blocks
|
|
||||||
* are incremented and that slot is reset to 1 (oldest-block caching)
|
|
||||||
*/
|
|
||||||
int cachedBlockAges[BLOCK_SLOTS];
|
|
||||||
z_stream zstrm;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int newBlockSlot(memlba_file* file)
|
|
||||||
{
|
|
||||||
unsigned i;
|
|
||||||
for (i=0 ; i<BLOCK_SLOTS ; ++i)
|
|
||||||
if (file->cachedBlockAges[i] != 0)
|
|
||||||
++file->cachedBlockAges[i];
|
|
||||||
for (i=0 ; i<BLOCK_SLOTS ; ++i)
|
|
||||||
if (file->cachedBlockAges[i] == 0)
|
|
||||||
{
|
|
||||||
file->cachedBlockAges[i] = 1;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
for (i=0 ; i<BLOCK_SLOTS ; ++i)
|
|
||||||
if (file->cachedBlockAges[i] == BLOCK_SLOTS+1)
|
|
||||||
{
|
|
||||||
file->cachedBlockAges[i] = 1;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
/* Shouldn't happen (fallback) */
|
|
||||||
for (i=1 ; i<BLOCK_SLOTS ; ++i)
|
|
||||||
{
|
|
||||||
file->cachedBlockAges[i] = 0;
|
|
||||||
file->cachedBlockIndices[i] = -1;
|
|
||||||
}
|
|
||||||
file->cachedBlockAges[0] = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void decompressBlock(memlba_file* file, unsigned blockIdx, int targetSlot)
|
|
||||||
{
|
|
||||||
if (blockIdx >= file->headBuf->blockCount)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "exceeded memlba block range");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
void* dbBlock = ((void*)file->headBuf) + file->headBuf->blockTOC[blockIdx];
|
|
||||||
file->zstrm.next_in = dbBlock;
|
|
||||||
file->zstrm.avail_in = file->headBuf->blockTOC[blockIdx+1] - file->headBuf->blockTOC[blockIdx];
|
|
||||||
file->zstrm.next_out = file->cachedBlockBufs[targetSlot];
|
|
||||||
file->zstrm.avail_out = file->headBuf->blockSize;
|
|
||||||
inflate(&file->zstrm, Z_FINISH);
|
|
||||||
inflateReset(&file->zstrm);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int getBlockSlot(memlba_file* file, int blockIdx)
|
|
||||||
{
|
|
||||||
unsigned i;
|
|
||||||
for (i=0 ; i<BLOCK_SLOTS ; ++i)
|
|
||||||
if (file->cachedBlockIndices[i] != blockIdx)
|
|
||||||
return i;
|
|
||||||
int newSlot = newBlockSlot(file);
|
|
||||||
file->cachedBlockIndices[newSlot] = blockIdx;
|
|
||||||
decompressBlock(file, blockIdx, newSlot);
|
|
||||||
return newSlot;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Method declarations for memlba_file.
|
|
||||||
*/
|
|
||||||
static int memlbaClose(sqlite3_file*);
|
|
||||||
static int memlbaRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
|
|
||||||
static int memlbaWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
|
|
||||||
static int memlbaTruncate(sqlite3_file*, sqlite3_int64 size);
|
|
||||||
static int memlbaSync(sqlite3_file*, int flags);
|
|
||||||
static int memlbaFileSize(sqlite3_file*, sqlite3_int64* pSize);
|
|
||||||
static int memlbaLock(sqlite3_file*, int);
|
|
||||||
static int memlbaUnlock(sqlite3_file*, int);
|
|
||||||
static int memlbaCheckReservedLock(sqlite3_file*, int* pResOut);
|
|
||||||
static int memlbaFileControl(sqlite3_file*, int op, void* pArg);
|
|
||||||
static int memlbaSectorSize(sqlite3_file*);
|
|
||||||
static int memlbaDeviceCharacteristics(sqlite3_file*);
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Method declarations for fs_vfs.
|
|
||||||
*/
|
|
||||||
static int memlbaOpen(sqlite3_vfs*, const char*, sqlite3_file*, int , int*);
|
|
||||||
static int memlbaDelete(sqlite3_vfs*, const char* zName, int syncDir);
|
|
||||||
static int memlbaAccess(sqlite3_vfs*, const char* zName, int flags, int*);
|
|
||||||
static int memlbaFullPathname(sqlite3_vfs*, const char* zName, int nOut, char* zOut);
|
|
||||||
static void* memlbaDlOpen(sqlite3_vfs*, const char* zFilename);
|
|
||||||
static void memlbaDlError(sqlite3_vfs*, int nByte, char* zErrMsg);
|
|
||||||
static void (*memlbaDlSym(sqlite3_vfs*, void*, const char* zSymbol))(void);
|
|
||||||
static void memlbaDlClose(sqlite3_vfs*, void*);
|
|
||||||
static int memlbaRandomness(sqlite3_vfs*, int nByte, char* zOut);
|
|
||||||
static int memlbaSleep(sqlite3_vfs*, int microseconds);
|
|
||||||
static int memlbaCurrentTime(sqlite3_vfs*, double*);
|
|
||||||
|
|
||||||
static sqlite3_vfs memlba_vfs =
|
|
||||||
{
|
|
||||||
1, /* iVersion */
|
|
||||||
0, /* szOsFile */
|
|
||||||
0, /* mxPathname */
|
|
||||||
0, /* pNext */
|
|
||||||
"hecl_memlba", /* zName */
|
|
||||||
0, /* pAppData */
|
|
||||||
memlbaOpen, /* xOpen */
|
|
||||||
memlbaDelete, /* xDelete */
|
|
||||||
memlbaAccess, /* xAccess */
|
|
||||||
memlbaFullPathname, /* xFullPathname */
|
|
||||||
memlbaDlOpen, /* xDlOpen */
|
|
||||||
memlbaDlError, /* xDlError */
|
|
||||||
memlbaDlSym, /* xDlSym */
|
|
||||||
memlbaDlClose, /* xDlClose */
|
|
||||||
memlbaRandomness, /* xRandomness */
|
|
||||||
memlbaSleep, /* xSleep */
|
|
||||||
memlbaCurrentTime, /* xCurrentTime */
|
|
||||||
0, 0, 0, 0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
static sqlite3_io_methods memlba_io_methods =
|
|
||||||
{
|
|
||||||
1, /* iVersion */
|
|
||||||
memlbaClose, /* xClose */
|
|
||||||
memlbaRead, /* xRead */
|
|
||||||
memlbaWrite, /* xWrite */
|
|
||||||
memlbaTruncate, /* xTruncate */
|
|
||||||
memlbaSync, /* xSync */
|
|
||||||
memlbaFileSize, /* xFileSize */
|
|
||||||
memlbaLock, /* xLock */
|
|
||||||
memlbaUnlock, /* xUnlock */
|
|
||||||
memlbaCheckReservedLock, /* xCheckReservedLock */
|
|
||||||
memlbaFileControl, /* xFileControl */
|
|
||||||
memlbaSectorSize, /* xSectorSize */
|
|
||||||
memlbaDeviceCharacteristics, /* xDeviceCharacteristics */
|
|
||||||
0, /* xShmMap */
|
|
||||||
0, /* xShmLock */
|
|
||||||
0, /* xShmBarrier */
|
|
||||||
0, /* xShmUnmap */
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Useful macros used in several places */
|
|
||||||
#define MIN(x,y) ((x)<(y)?(x):(y))
|
|
||||||
#define MAX(x,y) ((x)>(y)?(x):(y))
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Close a memlba-file.
|
|
||||||
*/
|
|
||||||
static int memlbaClose(sqlite3_file* pFile)
|
|
||||||
{
|
|
||||||
memlba_file* pTmp = (memlba_file*)pFile;
|
|
||||||
free(pTmp->headBuf);
|
|
||||||
free(pTmp->cachedBlockBufs[0]);
|
|
||||||
inflateEnd(&pTmp->zstrm);
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Read data from a memlba-file.
|
|
||||||
*/
|
|
||||||
static int memlbaRead(
|
|
||||||
sqlite3_file* pFile,
|
|
||||||
void* zBuf,
|
|
||||||
int iAmt,
|
|
||||||
sqlite_int64 iOfst
|
|
||||||
)
|
|
||||||
{
|
|
||||||
memlba_file* pTmp = (memlba_file*)pFile;
|
|
||||||
|
|
||||||
unsigned blockIdx = iOfst / pTmp->headBuf->blockSize;
|
|
||||||
unsigned firstOff = iOfst % pTmp->headBuf->blockSize;
|
|
||||||
unsigned firstRemBytes = pTmp->headBuf->blockSize - firstOff;
|
|
||||||
|
|
||||||
int slot = getBlockSlot(pTmp, blockIdx);
|
|
||||||
unsigned toRead = MIN((unsigned)iAmt, firstRemBytes);
|
|
||||||
memcpy(zBuf, pTmp->cachedBlockBufs[slot] + firstOff, toRead);
|
|
||||||
iAmt -= toRead;
|
|
||||||
zBuf += toRead;
|
|
||||||
|
|
||||||
while (iAmt > 0)
|
|
||||||
{
|
|
||||||
slot = getBlockSlot(pTmp, ++blockIdx);
|
|
||||||
toRead = MIN((unsigned)iAmt, pTmp->headBuf->blockSize);
|
|
||||||
memcpy(zBuf, pTmp->cachedBlockBufs[slot], toRead);
|
|
||||||
iAmt -= toRead;
|
|
||||||
zBuf += toRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Write data to a memlba-file.
|
|
||||||
*/
|
|
||||||
static int memlbaWrite(
|
|
||||||
sqlite3_file* pFile,
|
|
||||||
const void* zBuf,
|
|
||||||
int iAmt,
|
|
||||||
sqlite_int64 iOfst
|
|
||||||
)
|
|
||||||
{
|
|
||||||
(void)pFile; (void)zBuf; (void)iAmt; (void)iOfst;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Truncate a memlba-file.
|
|
||||||
*/
|
|
||||||
static int memlbaTruncate(sqlite3_file* pFile, sqlite_int64 size)
|
|
||||||
{
|
|
||||||
(void)pFile; (void)size;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Sync a memlba-file.
|
|
||||||
*/
|
|
||||||
static int memlbaSync(sqlite3_file* pFile, int flags)
|
|
||||||
{
|
|
||||||
(void)pFile; (void)flags;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Return the current file-size of a memlba-file.
|
|
||||||
*/
|
|
||||||
static int memlbaFileSize(sqlite3_file* pFile, sqlite_int64* pSize)
|
|
||||||
{
|
|
||||||
memlba_file* pTmp = (memlba_file*)pFile;
|
|
||||||
*pSize = pTmp->headBuf->headSz - pTmp->headBuf->blockTOC[0];
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Lock a memlba-file.
|
|
||||||
*/
|
|
||||||
static int memlbaLock(sqlite3_file* pFile, int eLock)
|
|
||||||
{
|
|
||||||
(void)pFile; (void)eLock;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Unlock a memlba-file.
|
|
||||||
*/
|
|
||||||
static int memlbaUnlock(sqlite3_file* pFile, int eLock)
|
|
||||||
{
|
|
||||||
(void)pFile; (void)eLock;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Check if another file-handle holds a RESERVED lock on a memlba-file.
|
|
||||||
*/
|
|
||||||
static int memlbaCheckReservedLock(sqlite3_file* pFile, int* pResOut)
|
|
||||||
{
|
|
||||||
(void)pFile;
|
|
||||||
*pResOut = 0;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** File control method. For custom operations on a memlba-file.
|
|
||||||
*/
|
|
||||||
static int memlbaFileControl(sqlite3_file* pFile, int op, void* pArg)
|
|
||||||
{
|
|
||||||
(void)pFile; (void)op; (void)pArg;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Return the sector-size in bytes for a memlba-file.
|
|
||||||
*/
|
|
||||||
static int memlbaSectorSize(sqlite3_file* pFile)
|
|
||||||
{
|
|
||||||
(void)pFile;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Return the device characteristic flags supported by a memlba-file.
|
|
||||||
*/
|
|
||||||
static int memlbaDeviceCharacteristics(sqlite3_file* pFile)
|
|
||||||
{
|
|
||||||
(void)pFile;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Open an memlba file handle.
|
|
||||||
*/
|
|
||||||
static int memlbaOpen(
|
|
||||||
sqlite3_vfs* pVfs,
|
|
||||||
const char* zName,
|
|
||||||
sqlite3_file* pFile,
|
|
||||||
int flags,
|
|
||||||
int* pOutFlags
|
|
||||||
)
|
|
||||||
{
|
|
||||||
(void)pVfs; (void)zName; (void)pOutFlags;
|
|
||||||
if ((flags & SQLITE_OPEN_MAIN_DB) != SQLITE_OPEN_MAIN_DB ||
|
|
||||||
(flags & SQLITE_OPEN_READONLY) != SQLITE_OPEN_READONLY)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "the sqlite hecl memlba VFS only supports main-db reading\n");
|
|
||||||
return SQLITE_CANTOPEN;
|
|
||||||
}
|
|
||||||
memlba_file* p2 = (memlba_file*)pFile;
|
|
||||||
memset(p2, 0, sizeof(*p2));
|
|
||||||
p2->base.pMethods = &memlba_io_methods;
|
|
||||||
inflateInit(&p2->zstrm);
|
|
||||||
p2->headBuf = HEAD_BUF;
|
|
||||||
unsigned i;
|
|
||||||
void* blockBufs = calloc(BLOCK_SLOTS, p2->headBuf->blockSize);
|
|
||||||
for (i=0 ; i<BLOCK_SLOTS ; ++i)
|
|
||||||
{
|
|
||||||
p2->cachedBlockBufs[i] = blockBufs + p2->headBuf->blockSize * i;
|
|
||||||
p2->cachedBlockIndices[i] = -1;
|
|
||||||
}
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Delete the file located at zPath. If the dirSync argument is true,
|
|
||||||
** ensure the file-system modifications are synced to disk before
|
|
||||||
** returning.
|
|
||||||
*/
|
|
||||||
static int memlbaDelete(sqlite3_vfs* pVfs, const char* zPath, int dirSync)
|
|
||||||
{
|
|
||||||
(void)pVfs; (void)zPath; (void)dirSync;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Test for access permissions. Return true if the requested permission
|
|
||||||
** is available, or false otherwise.
|
|
||||||
*/
|
|
||||||
static int memlbaAccess(
|
|
||||||
sqlite3_vfs* pVfs,
|
|
||||||
const char* zPath,
|
|
||||||
int flags,
|
|
||||||
int* pResOut
|
|
||||||
)
|
|
||||||
{
|
|
||||||
(void)pVfs; (void)zPath; (void)pResOut;
|
|
||||||
if (flags & (SQLITE_ACCESS_READ | SQLITE_ACCESS_READWRITE))
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Populate buffer zOut with the full canonical pathname corresponding
|
|
||||||
** to the pathname in zPath. zOut is guaranteed to point to a buffer
|
|
||||||
** of at least (FS_MAX_PATHNAME+1) bytes.
|
|
||||||
*/
|
|
||||||
static int memlbaFullPathname(
|
|
||||||
sqlite3_vfs* pVfs, /* Pointer to vfs object */
|
|
||||||
const char* zPath, /* Possibly relative input path */
|
|
||||||
int nOut, /* Size of output buffer in bytes */
|
|
||||||
char* zOut) /* Output buffer */
|
|
||||||
{
|
|
||||||
(void)pVfs;
|
|
||||||
strncpy(zOut, zPath, nOut);
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Open the dynamic library located at zPath and return a handle.
|
|
||||||
*/
|
|
||||||
static void* memlbaDlOpen(sqlite3_vfs* pVfs, const char* zPath)
|
|
||||||
{
|
|
||||||
(void)pVfs; (void)zPath;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Populate the buffer zErrMsg (size nByte bytes) with a human readable
|
|
||||||
** utf-8 string describing the most recent error encountered associated
|
|
||||||
** with dynamic libraries.
|
|
||||||
*/
|
|
||||||
static void memlbaDlError(sqlite3_vfs* pVfs, int nByte, char* zErrMsg)
|
|
||||||
{
|
|
||||||
(void)pVfs; (void)nByte; (void)zErrMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
|
|
||||||
*/
|
|
||||||
static void (*memlbaDlSym(sqlite3_vfs* pVfs, void* pH, const char* zSym))(void)
|
|
||||||
{
|
|
||||||
(void)pVfs; (void)pH; (void)zSym;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Close the dynamic library handle pHandle.
|
|
||||||
*/
|
|
||||||
static void memlbaDlClose(sqlite3_vfs* pVfs, void* pHandle)
|
|
||||||
{
|
|
||||||
(void)pVfs; (void)pHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Populate the buffer pointed to by zBufOut with nByte bytes of
|
|
||||||
** random data.
|
|
||||||
*/
|
|
||||||
static int memlbaRandomness(sqlite3_vfs* pVfs, int nByte, char* zBufOut)
|
|
||||||
{
|
|
||||||
(void)pVfs;
|
|
||||||
for(int i = 0 ; i < nByte ; ++i)
|
|
||||||
zBufOut[i] = rand();
|
|
||||||
return nByte;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Sleep for nMicro microseconds. Return the number of microseconds
|
|
||||||
** actually slept.
|
|
||||||
*/
|
|
||||||
static int memlbaSleep(sqlite3_vfs* pVfs, int nMicro)
|
|
||||||
{
|
|
||||||
(void)pVfs;
|
|
||||||
int seconds = (nMicro + 999999) / 1000000;
|
|
||||||
sleep(seconds);
|
|
||||||
return seconds * 1000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Return the current time as a Julian Day number in *pTimeOut.
|
|
||||||
*/
|
|
||||||
static int memlbaCurrentTime(sqlite3_vfs* pVfs, double* pTimeOut)
|
|
||||||
{
|
|
||||||
(void)pVfs;
|
|
||||||
*pTimeOut = 0.0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This procedure registers the memlba vfs with SQLite. If the argument is
|
|
||||||
** true, the memlba vfs becomes the new default vfs. It is the only publicly
|
|
||||||
** available function in this file.
|
|
||||||
*/
|
|
||||||
int sqlite_hecl_memlba_vfs_register(void* headBuf)
|
|
||||||
{
|
|
||||||
HEAD_BUF = headBuf;
|
|
||||||
if(memlba_vfs.szOsFile) return SQLITE_OK;
|
|
||||||
memlba_vfs.szOsFile = sizeof(memlba_file);
|
|
||||||
return sqlite3_vfs_register(&memlba_vfs, 0);
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
#ifndef SQLITE_HECL_VFS
|
|
||||||
#define SQLITE_HECL_VFS
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
typedef void(*TCloseCallback)(void* buf, size_t bufLen, void* ctx);
|
|
||||||
int sqlite_hecl_mem_vfs_register(TCloseCallback closeCb, void* ctx);
|
|
||||||
int sqlite_hecl_memlba_vfs_register(void* headBuf);
|
|
||||||
void sqlite_hecl_memlba_make(FILE* fout, void* bufin, size_t bufinLen, bool bigEndian);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // SQLITE_HECL_VFS
|
|
|
@ -1,5 +1,5 @@
|
||||||
TEMPLATE = lib
|
TEMPLATE = lib
|
||||||
CONFIG += staticlib
|
CONFIG += staticlib c++11
|
||||||
TARGET = hecl
|
TARGET = hecl
|
||||||
CONFIG -= Qt
|
CONFIG -= Qt
|
||||||
QT =
|
QT =
|
||||||
|
@ -17,4 +17,6 @@ include (database/database.pri)
|
||||||
include (runtime/runtime.pri)
|
include (runtime/runtime.pri)
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
HECL.cpp
|
HECL.cpp \
|
||||||
|
ProjectPath.cpp \
|
||||||
|
WideStringConvert.cpp
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include "HECLRuntime.hpp"
|
||||||
|
|
||||||
|
namespace HECLRuntime
|
||||||
|
{
|
||||||
|
|
||||||
|
HECLRuntime::HECLRuntime(const HECL::SystemString& hlpkDirectory)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HECLRuntime::~HECLRuntime()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<RuntimeEntity> HECLRuntime::loadSync(const HECL::Hash& pathHash)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<RuntimeEntity> HECLRuntime::loadAsync(const HECL::Hash& pathHash,
|
||||||
|
SGroupLoadStatus* statusOut)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue