diff --git a/hecl/driver/ToolBase.hpp b/hecl/driver/ToolBase.hpp index 6a28a7251..d5f9502cd 100644 --- a/hecl/driver/ToolBase.hpp +++ b/hecl/driver/ToolBase.hpp @@ -88,7 +88,7 @@ protected: } public: - ToolBase(const ToolPassInfo& info) : m_info(info) { + explicit ToolBase(const ToolPassInfo& info) : m_info(info) { hecl::VerbosityLevel = info.verbosityLevel; hecl::GuiMode = info.gui; } @@ -96,15 +96,15 @@ public: virtual hecl::SystemString toolName() const = 0; virtual int run() = 0; virtual void cancel() {} - inline operator bool() const { return m_good; } + explicit operator bool() const { return m_good; } }; class HelpOutput { public: - typedef void (*HelpFunc)(HelpOutput&); + using HelpFunc = void (*)(HelpOutput&); private: - FILE* m_sout; + FILE* m_sout = nullptr; HelpFunc m_helpFunc; int m_lineWidth; hecl::SystemString m_wrapBuffer; @@ -156,8 +156,8 @@ private: } public: - HelpOutput(HelpFunc helpFunc) - : m_sout(NULL), m_helpFunc(helpFunc), m_lineWidth(hecl::GuiMode ? 120 : hecl::ConsoleWidth()) {} + explicit HelpOutput(HelpFunc helpFunc) + : m_helpFunc(helpFunc), m_lineWidth(hecl::GuiMode ? 120 : hecl::ConsoleWidth()) {} void go() { #if _WIN32 diff --git a/hecl/driver/ToolCook.hpp b/hecl/driver/ToolCook.hpp index 928bd50f3..1f3e83702 100644 --- a/hecl/driver/ToolCook.hpp +++ b/hecl/driver/ToolCook.hpp @@ -13,7 +13,7 @@ class ToolCook final : public ToolBase { bool m_fast = false; public: - ToolCook(const ToolPassInfo& info) : ToolBase(info), m_useProj(info.project) { + explicit ToolCook(const ToolPassInfo& info) : ToolBase(info), m_useProj(info.project) { /* Check for recursive flag */ for (hecl::SystemChar arg : info.flags) if (arg == _SYS_STR('r')) @@ -145,9 +145,9 @@ public: } } - hecl::SystemString toolName() const { return _SYS_STR("cook"); } + hecl::SystemString toolName() const override { return _SYS_STR("cook"); } - int run() { + int run() override { hecl::MultiProgressPrinter printer(true); hecl::ClientProcess cp(&printer); for (const hecl::ProjectPath& path : m_selectedItems) @@ -156,5 +156,5 @@ public: return 0; } - void cancel() { m_useProj->interruptCook(); } + void cancel() override { m_useProj->interruptCook(); } }; diff --git a/hecl/driver/ToolExtract.hpp b/hecl/driver/ToolExtract.hpp index eb3206e81..b1c1f617d 100644 --- a/hecl/driver/ToolExtract.hpp +++ b/hecl/driver/ToolExtract.hpp @@ -27,7 +27,7 @@ class ToolExtract final : public ToolBase { hecl::Database::Project* m_useProj = nullptr; public: - ToolExtract(const ToolPassInfo& info) : ToolBase(info) { + explicit ToolExtract(const ToolPassInfo& info) : ToolBase(info) { if (!m_info.args.size()) LogModule.report(logvisor::Fatal, fmt("hecl extract needs a source path as its first argument")); @@ -112,7 +112,7 @@ public: help.endWrap(); } - hecl::SystemString toolName() const { return _SYS_STR("extract"); } + hecl::SystemString toolName() const override { return _SYS_STR("extract"); } static void _recursivePrint(int level, hecl::Database::IDataSpec::ExtractReport& rep) { for (int l = 0; l < level; ++l) @@ -129,7 +129,7 @@ public: _recursivePrint(level + 1, child); } - int run() { + int run() override { if (m_specPasses.empty()) { if (XTERM_COLOR) fmt::print(fmt(_SYS_STR("" RED BOLD "NOTHING TO EXTRACT" NORMAL "\n"))); diff --git a/hecl/driver/ToolHelp.hpp b/hecl/driver/ToolHelp.hpp index 590cbf1ef..b698f5747 100644 --- a/hecl/driver/ToolHelp.hpp +++ b/hecl/driver/ToolHelp.hpp @@ -7,7 +7,7 @@ class ToolHelp final : public ToolBase { public: - ToolHelp(const ToolPassInfo& info) : ToolBase(info) { + explicit ToolHelp(const ToolPassInfo& info) : ToolBase(info) { if (m_info.args.empty()) { LogModule.report(logvisor::Error, fmt("help requires a tool name argument")); return; @@ -15,7 +15,7 @@ public: m_good = true; } - ~ToolHelp() {} + ~ToolHelp() override = default; static void Help(HelpOutput& help) { help.printBold( @@ -50,7 +50,7 @@ public: static void ShowHelp(const hecl::SystemString& toolName) { /* Select tool's help-text streamer */ - HelpOutput::HelpFunc helpFunc = NULL; + HelpOutput::HelpFunc helpFunc = nullptr; if (toolName == _SYS_STR("init")) helpFunc = ToolInit::Help; else if (toolName == _SYS_STR("spec")) @@ -72,9 +72,9 @@ public: ho.go(); } - hecl::SystemString toolName() const { return _SYS_STR("help"); } + hecl::SystemString toolName() const override { return _SYS_STR("help"); } - int run() { + int run() override { ShowHelp(m_info.args.front()); return 0; } diff --git a/hecl/driver/ToolImage.hpp b/hecl/driver/ToolImage.hpp index 6644313b3..fcab3405a 100644 --- a/hecl/driver/ToolImage.hpp +++ b/hecl/driver/ToolImage.hpp @@ -15,7 +15,7 @@ class ToolImage final : public ToolBase { hecl::Database::Project* m_useProj; public: - ToolImage(const ToolPassInfo& info) : ToolBase(info), m_useProj(info.project) { + explicit ToolImage(const ToolPassInfo& info) : ToolBase(info), m_useProj(info.project) { if (!info.project) LogModule.report(logvisor::Fatal, fmt("hecl image must be ran within a project directory")); @@ -44,7 +44,7 @@ public: "provided a path within a project")); } - ~ToolImage() {} + ~ToolImage() override = default; static void Help(HelpOutput& help) { help.secHead(_SYS_STR("NAME")); @@ -71,9 +71,9 @@ public: help.endWrap(); } - hecl::SystemString toolName() const { return _SYS_STR("image"); } + hecl::SystemString toolName() const override { return _SYS_STR("image"); } - int run() { + int run() override { if (XTERM_COLOR) fmt::print(fmt(_SYS_STR("" GREEN BOLD "ABOUT TO IMAGE:" NORMAL "\n"))); else diff --git a/hecl/driver/ToolInit.hpp b/hecl/driver/ToolInit.hpp index 27adc5ad8..e799a2f76 100644 --- a/hecl/driver/ToolInit.hpp +++ b/hecl/driver/ToolInit.hpp @@ -4,10 +4,10 @@ #include class ToolInit final : public ToolBase { - const hecl::SystemString* m_dir = NULL; + const hecl::SystemString* m_dir = nullptr; public: - ToolInit(const ToolPassInfo& info) : ToolBase(info) { + explicit ToolInit(const ToolPassInfo& info) : ToolBase(info) { hecl::Sstat theStat; const hecl::SystemString* dir; if (info.args.size()) @@ -36,7 +36,7 @@ public: m_dir = dir; } - int run() { + int run() override { if (!m_dir) return 1; size_t ErrorRef = logvisor::ErrorCount; @@ -73,5 +73,5 @@ public: help.endWrap(); } - hecl::SystemString toolName() const { return _SYS_STR("init"); } + hecl::SystemString toolName() const override { return _SYS_STR("init"); } }; diff --git a/hecl/driver/ToolPackage.hpp b/hecl/driver/ToolPackage.hpp index d5c42329d..ebbb20f2d 100644 --- a/hecl/driver/ToolPackage.hpp +++ b/hecl/driver/ToolPackage.hpp @@ -59,7 +59,7 @@ class ToolPackage final : public ToolBase { } public: - ToolPackage(const ToolPassInfo& info) : ToolBase(info), m_useProj(info.project) { + explicit ToolPackage(const ToolPassInfo& info) : ToolBase(info), m_useProj(info.project) { if (!info.project) LogModule.report(logvisor::Fatal, fmt("hecl package must be ran within a project directory")); @@ -156,9 +156,9 @@ public: help.endWrap(); } - hecl::SystemString toolName() const { return _SYS_STR("package"); } + hecl::SystemString toolName() const override { return _SYS_STR("package"); } - int run() { + int run() override { if (XTERM_COLOR) fmt::print(fmt(_SYS_STR("" GREEN BOLD "ABOUT TO PACKAGE:" NORMAL "\n"))); else @@ -181,5 +181,5 @@ public: return 0; } - void cancel() { m_useProj->interruptCook(); } + void cancel() override { m_useProj->interruptCook(); } }; diff --git a/hecl/driver/ToolSpec.hpp b/hecl/driver/ToolSpec.hpp index 09515bfde..ec96a4f25 100644 --- a/hecl/driver/ToolSpec.hpp +++ b/hecl/driver/ToolSpec.hpp @@ -8,7 +8,7 @@ class ToolSpec final : public ToolBase { enum Mode { MLIST = 0, MENABLE, MDISABLE } mode = MLIST; public: - ToolSpec(const ToolPassInfo& info) : ToolBase(info) { + explicit ToolSpec(const ToolPassInfo& info) : ToolBase(info) { if (info.args.empty()) return; @@ -71,9 +71,9 @@ public: help.endWrap(); } - hecl::SystemString toolName() const { return _SYS_STR("spec"); } + hecl::SystemString toolName() const override { return _SYS_STR("spec"); } - int run() { + int run() override { if (!m_info.project) { for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY) { if (XTERM_COLOR) diff --git a/hecl/driver/main.cpp b/hecl/driver/main.cpp index b53509e55..9c4c3363a 100644 --- a/hecl/driver/main.cpp +++ b/hecl/driver/main.cpp @@ -77,14 +77,196 @@ static void SIGINTHandler(int sig) { } static logvisor::Module AthenaLog("Athena"); -static void AthenaExc(athena::error::Level level, const char* file, const char*, int line, - fmt::string_view fmt, fmt::format_args args) { +static void AthenaExc(athena::error::Level level, const char* file, const char*, int line, fmt::string_view fmt, + fmt::format_args args) { AthenaLog.vreport(logvisor::Level(level), fmt, args); } -static hecl::SystemChar cwdbuf[1024]; hecl::SystemString ExeDir; +#if _WIN32 +static ToolPassInfo CreateInfo(int argc, const wchar_t** argv) { +#else +static ToolPassInfo CreateInfo(int argc, const char** argv) { +#endif + hecl::SystemChar cwdbuf[1024]; + + ToolPassInfo info; + info.pname = argv[0]; + + if (hecl::Getcwd(cwdbuf, static_cast(std::size(cwdbuf)))) { + info.cwd = cwdbuf; + if (info.cwd.size() && info.cwd.back() != _SYS_STR('/') && info.cwd.back() != _SYS_STR('\\')) { +#if _WIN32 + info.cwd += _SYS_STR('\\'); +#else + info.cwd += _SYS_STR('/'); +#endif + } + + if (hecl::PathRelative(argv[0])) { + ExeDir = hecl::SystemString(cwdbuf) + _SYS_STR('/'); + } + hecl::SystemString Argv0(argv[0]); + hecl::SystemString::size_type lastIdx = Argv0.find_last_of(_SYS_STR("/\\")); + if (lastIdx != hecl::SystemString::npos) { + ExeDir.insert(ExeDir.end(), Argv0.begin(), Argv0.begin() + lastIdx); + } + } + + /* Concatenate args */ + std::vector args; + args.reserve(argc - 2); + for (int i = 2; i < argc; ++i) { + args.emplace_back(argv[i]); + } + + if (!args.empty()) { + /* Extract output argument */ + for (auto it = args.cbegin(); it != args.cend();) { + const hecl::SystemString& arg = *it; + hecl::SystemRegexMatch oMatch; + + if (std::regex_search(arg, oMatch, regOPEN)) { + const hecl::SystemString& token = oMatch[1].str(); + + if (token.size()) { + if (info.output.empty()) { + info.output = oMatch[1].str(); + } + + it = args.erase(it); + } else { + it = args.erase(it); + + if (it == args.end()) { + break; + } + + if (info.output.empty()) { + info.output = *it; + } + + it = args.erase(it); + } + + continue; + } + + ++it; + } + + /* Iterate flags */ + bool threadArg = false; + for (auto it = args.cbegin(); it != args.cend();) { + const hecl::SystemString& arg = *it; + if (threadArg) { + threadArg = false; + hecl::CpuCountOverride = int(hecl::StrToUl(arg.c_str(), nullptr, 0)); + it = args.erase(it); + continue; + } + if (arg.size() < 2 || arg[0] != _SYS_STR('-') || arg[1] == _SYS_STR('-')) { + ++it; + continue; + } + + for (auto chit = arg.cbegin() + 1; chit != arg.cend(); ++chit) { + if (*chit == _SYS_STR('v')) + ++info.verbosityLevel; + else if (*chit == _SYS_STR('f')) + info.force = true; + else if (*chit == _SYS_STR('y')) + info.yes = true; + else if (*chit == _SYS_STR('g')) + info.gui = true; + else if (*chit == _SYS_STR('j')) { + ++chit; + if (*chit) + hecl::CpuCountOverride = int(hecl::StrToUl(&*chit, nullptr, 0)); + else + threadArg = true; + break; + } else + info.flags.push_back(*chit); + } + + it = args.erase(it); + } + + /* Gather remaining args */ + info.args.reserve(args.size()); + for (const hecl::SystemString& arg : args) + info.args.push_back(arg); + } + + return info; +} + +static std::unique_ptr FindProject(hecl::SystemStringView cwd) { + const hecl::ProjectRootPath rootPath = hecl::SearchForProject(cwd); + if (!rootPath) { + return nullptr; + } + + const size_t ErrorRef = logvisor::ErrorCount; + auto newProj = std::make_unique(rootPath); + if (logvisor::ErrorCount > ErrorRef) { +#if WIN_PAUSE + system("PAUSE"); +#endif + return nullptr; + } + + return newProj; +} + +static std::unique_ptr MakeSelectedTool(hecl::SystemString toolName, ToolPassInfo& info) { + hecl::SystemString toolNameLower = toolName; + hecl::ToLower(toolNameLower); + + if (toolNameLower == _SYS_STR("init")) { + return std::make_unique(info); + } + + if (toolNameLower == _SYS_STR("spec")) { + return std::make_unique(info); + } + + if (toolNameLower == _SYS_STR("extract")) { + return std::make_unique(info); + } + + if (toolNameLower == _SYS_STR("cook")) { + return std::make_unique(info); + } + + if (toolNameLower == _SYS_STR("package") || toolNameLower == _SYS_STR("pack")) { + return std::make_unique(info); + } + +#if HECL_HAS_NOD + if (toolNameLower == _SYS_STR("image")) { + return std::make_unique(info); + } +#endif + + if (toolNameLower == _SYS_STR("help")) { + return std::make_unique(info); + } + + auto fp = hecl::FopenUnique(toolName.c_str(), _SYS_STR("rb")); + if (fp == nullptr) { + LogModule.report(logvisor::Error, fmt(_SYS_STR("unrecognized tool '{}'")), toolNameLower); + return nullptr; + } + fp.reset(); + + /* Shortcut-case: implicit extract */ + info.args.insert(info.args.begin(), std::move(toolName)); + return std::make_unique(info); +} + #if _WIN32 int wmain(int argc, const wchar_t** argv) #else @@ -140,167 +322,34 @@ int main(int argc, const char** argv) HECLRegisterDataSpecs(); /* Assemble common tool pass info */ - ToolPassInfo info; - info.pname = argv[0]; - if (hecl::Getcwd(cwdbuf, 1024)) { - info.cwd = cwdbuf; - if (info.cwd.size() && info.cwd.back() != _SYS_STR('/') && info.cwd.back() != _SYS_STR('\\')) -#if _WIN32 - info.cwd += _SYS_STR('\\'); -#else - info.cwd += _SYS_STR('/'); -#endif - - if (hecl::PathRelative(argv[0])) - ExeDir = hecl::SystemString(cwdbuf) + _SYS_STR('/'); - hecl::SystemString Argv0(argv[0]); - hecl::SystemString::size_type lastIdx = Argv0.find_last_of(_SYS_STR("/\\")); - if (lastIdx != hecl::SystemString::npos) - ExeDir.insert(ExeDir.end(), Argv0.begin(), Argv0.begin() + lastIdx); - } - - /* Concatenate args */ - std::vector args; - args.reserve(argc - 2); - for (int i = 2; i < argc; ++i) - args.push_back(hecl::SystemString(argv[i])); - - if (!args.empty()) { - /* Extract output argument */ - for (auto it = args.cbegin(); it != args.cend();) { - const hecl::SystemString& arg = *it; - hecl::SystemRegexMatch oMatch; - if (std::regex_search(arg, oMatch, regOPEN)) { - const hecl::SystemString& token = oMatch[1].str(); - if (token.size()) { - if (info.output.empty()) - info.output = oMatch[1].str(); - it = args.erase(it); - } else { - it = args.erase(it); - if (it == args.end()) - break; - if (info.output.empty()) - info.output = *it; - it = args.erase(it); - } - continue; - } - ++it; - } - - /* Iterate flags */ - bool threadArg = false; - for (auto it = args.cbegin(); it != args.cend();) { - const hecl::SystemString& arg = *it; - if (threadArg) { - threadArg = false; - hecl::CpuCountOverride = int(hecl::StrToUl(arg.c_str(), nullptr, 0)); - it = args.erase(it); - continue; - } - if (arg.size() < 2 || arg[0] != _SYS_STR('-') || arg[1] == _SYS_STR('-')) { - ++it; - continue; - } - - for (auto chit = arg.cbegin() + 1; chit != arg.cend(); ++chit) { - if (*chit == _SYS_STR('v')) - ++info.verbosityLevel; - else if (*chit == _SYS_STR('f')) - info.force = true; - else if (*chit == _SYS_STR('y')) - info.yes = true; - else if (*chit == _SYS_STR('g')) - info.gui = true; - else if (*chit == _SYS_STR('j')) { - ++chit; - if (*chit) - hecl::CpuCountOverride = int(hecl::StrToUl(&*chit, nullptr, 0)); - else - threadArg = true; - break; - } - else - info.flags.push_back(*chit); - } - - it = args.erase(it); - } - - /* Gather remaining args */ - info.args.reserve(args.size()); - for (const hecl::SystemString& arg : args) - info.args.push_back(arg); - } + ToolPassInfo info = CreateInfo(argc, argv); /* Attempt to find hecl project */ - hecl::ProjectRootPath rootPath = hecl::SearchForProject(info.cwd); - std::unique_ptr project; - if (rootPath) { - size_t ErrorRef = logvisor::ErrorCount; - hecl::Database::Project* newProj = new hecl::Database::Project(rootPath); - if (logvisor::ErrorCount > ErrorRef) { -#if WIN_PAUSE - system("PAUSE"); -#endif - delete newProj; - return 1; - } - project.reset(newProj); - info.project = newProj; + auto project = FindProject(info.cwd); + if (project != nullptr) { + info.project = project.get(); } /* Construct selected tool */ - hecl::SystemString toolName(argv[1]); - hecl::ToLower(toolName); - std::unique_ptr tool; - - size_t ErrorRef = logvisor::ErrorCount; - if (toolName == _SYS_STR("init")) - tool.reset(new ToolInit(info)); - else if (toolName == _SYS_STR("spec")) - tool.reset(new ToolSpec(info)); - else if (toolName == _SYS_STR("extract")) - tool.reset(new ToolExtract(info)); - else if (toolName == _SYS_STR("cook")) - tool.reset(new ToolCook(info)); - else if (toolName == _SYS_STR("package") || toolName == _SYS_STR("pack")) - tool.reset(new ToolPackage(info)); -#if HECL_HAS_NOD - else if (toolName == _SYS_STR("image")) - tool.reset(new ToolImage(info)); -#endif - else if (toolName == _SYS_STR("help")) - tool.reset(new ToolHelp(info)); - else { - FILE* fp = hecl::Fopen(argv[1], _SYS_STR("rb")); - if (!fp) - LogModule.report(logvisor::Error, fmt(_SYS_STR("unrecognized tool '{}'")), toolName); - else { - /* Shortcut-case: implicit extract */ - fclose(fp); - info.args.insert(info.args.begin(), argv[1]); - tool.reset(new ToolExtract(info)); - } - } - - if (logvisor::ErrorCount > ErrorRef) { + const size_t MakeToolErrorRef = logvisor::ErrorCount; + auto tool = MakeSelectedTool(argv[1], info); + if (logvisor::ErrorCount > MakeToolErrorRef) { #if WIN_PAUSE system("PAUSE"); #endif return 1; } - - if (info.verbosityLevel) - LogModule.report(logvisor::Info, fmt(_SYS_STR("Constructed tool '{}' {}\n")), tool->toolName(), info.verbosityLevel); + if (info.verbosityLevel) { + LogModule.report(logvisor::Info, fmt(_SYS_STR("Constructed tool '{}' {}\n")), tool->toolName(), + info.verbosityLevel); + } /* Run tool */ - ErrorRef = logvisor::ErrorCount; + const size_t RunToolErrorRef = logvisor::ErrorCount; ToolPtr = tool.get(); - int retval = tool->run(); + const int retval = tool->run(); ToolPtr = nullptr; - if (logvisor::ErrorCount > ErrorRef) { + if (logvisor::ErrorCount > RunToolErrorRef) { hecl::blender::Connection::Shutdown(); #if WIN_PAUSE system("PAUSE"); diff --git a/hecl/include/hecl/BitVector.hpp b/hecl/include/hecl/BitVector.hpp index acd1916fc..3944b6512 100644 --- a/hecl/include/hecl/BitVector.hpp +++ b/hecl/include/hecl/BitVector.hpp @@ -67,7 +67,7 @@ public: return *this; } - operator bool() const { return ((*WordRef) & (BitWord(1) << BitPos)) != 0; } + explicit operator bool() const { return ((*WordRef) & (BitWord(1) << BitPos)) != 0; } }; /// BitVector default ctor - Creates an empty bitvector. diff --git a/hecl/include/hecl/Blender/Connection.hpp b/hecl/include/hecl/Blender/Connection.hpp index 147508177..82f66d3b7 100644 --- a/hecl/include/hecl/Blender/Connection.hpp +++ b/hecl/include/hecl/Blender/Connection.hpp @@ -12,32 +12,37 @@ #include #endif +#include +#include +#include #include #include -#include -#include #include -#include +#include +#include +#include +#include #include -#include +#include #include +#include #include "hecl/hecl.hpp" +#include "hecl/Backend.hpp" #include "hecl/HMDLMeta.hpp" #include "hecl/TypedVariant.hpp" -#include "hecl/Backend.hpp" -#include "athena/Types.hpp" -#include "athena/MemoryWriter.hpp" -#include -#include "Token.hpp" + +#include #include +#include namespace hecl::blender { using namespace std::literals; -extern logvisor::Module BlenderLog; -class HMDLBuffers; class Connection; +class HMDLBuffers; + +extern logvisor::Module BlenderLog; struct PoolSkinIndex { size_t m_poolSz = 0; @@ -76,7 +81,7 @@ class PyOutStream : public std::ostream { StreamBuf(PyOutStream& parent, bool deleteOnError) : m_parent(parent), m_deleteOnError(deleteOnError) {} StreamBuf(const StreamBuf& other) = delete; StreamBuf(StreamBuf&& other) = default; - int_type overflow(int_type ch); + int_type overflow(int_type ch) override; } m_sbuf; PyOutStream(Connection* parent, bool deleteOnError); @@ -85,7 +90,7 @@ public: PyOutStream(PyOutStream&& other) : std::ostream(&m_sbuf), m_parent(other.m_parent), m_sbuf(std::move(other.m_sbuf)) { other.m_parent = nullptr; } - ~PyOutStream() { close(); } + ~PyOutStream() override { close(); } void close(); template > void format(const S& format, Args&&... args); @@ -136,15 +141,15 @@ struct Vector4f { } }; struct Matrix3f { - atVec3f m[3]; - inline atVec3f& operator[](size_t idx) { return m[idx]; } - inline const atVec3f& operator[](size_t idx) const { return m[idx]; } + std::array m; + atVec3f& operator[](size_t idx) { return m[idx]; } + const atVec3f& operator[](size_t idx) const { return m[idx]; } }; struct Matrix4f { - atVec4f val[4]; + std::array val; Matrix4f() = default; - void read(Connection& conn); Matrix4f(Connection& conn) { read(conn); } + void read(Connection& conn); const atVec4f& operator[](size_t idx) const { return val[idx]; } }; struct Index { @@ -343,8 +348,8 @@ struct Mesh { struct Vert { uint32_t iPos = 0xffffffff; uint32_t iNorm = 0xffffffff; - uint32_t iColor[4] = {0xffffffff}; - uint32_t iUv[8] = {0xffffffff}; + std::array iColor = {0xffffffff}; + std::array iUv = {0xffffffff}; uint32_t iSkin = 0xffffffff; uint32_t iBankSkin = 0xffffffff; @@ -433,14 +438,14 @@ struct ColMesh { std::vector verts; struct Edge { - uint32_t verts[2]; + std::array verts; bool seam; Edge(Connection& conn); }; std::vector edges; struct Triangle { - uint32_t edges[3]; + std::array edges; uint32_t matIdx; bool flip; Triangle(Connection& conn); @@ -454,10 +459,10 @@ struct ColMesh { struct World { struct Area { ProjectPath path; - Vector3f aabb[2]; + std::array aabb; Matrix4f transform; struct Dock { - Vector3f verts[4]; + std::array verts; Index targetArea; Index targetDock; Dock(Connection& conn); @@ -666,30 +671,30 @@ public: }; class Connection { + friend class ANIMOutStream; friend class DataStream; friend class PyOutStream; - friend class ANIMOutStream; - friend struct PyOutStream::StreamBuf; - friend struct Mesh; - friend struct Material; + friend struct Action; + friend struct Actor; + friend struct Armature; + friend struct Bone; + friend struct Boolean; friend struct ColMesh; - friend struct World; + friend struct Float; + friend struct Index; friend struct Light; friend struct MapArea; friend struct MapUniverse; - friend struct Actor; - friend struct Armature; - friend struct Action; - friend struct Bone; + friend struct Material; + friend struct Matrix3f; + friend struct Matrix4f; + friend struct Mesh; friend struct PathMesh; + friend struct PyOutStream::StreamBuf; friend struct Vector2f; friend struct Vector3f; friend struct Vector4f; - friend struct Matrix3f; - friend struct Matrix4f; - friend struct Index; - friend struct Float; - friend struct Boolean; + friend struct World; std::atomic_bool m_lock = {false}; bool m_pyStreamActive = false; @@ -701,8 +706,8 @@ class Connection { #else pid_t m_blenderProc = 0; #endif - int m_readpipe[2]; - int m_writepipe[2]; + std::array m_readpipe{}; + std::array m_writepipe{}; BlendType m_loadedType = BlendType::None; bool m_loadedRigged = false; ProjectPath m_loadedBlend; @@ -710,8 +715,7 @@ class Connection { uint32_t _readStr(char* buf, uint32_t bufSz); uint32_t _writeStr(const char* str, uint32_t len, int wpipe); uint32_t _writeStr(const char* str, uint32_t len) { return _writeStr(str, len, m_writepipe[1]); } - uint32_t _writeStr(const char* str) { return _writeStr(str, strlen(str)); } - uint32_t _writeStr(const std::string& str) { return _writeStr(str.c_str(), str.size()); } + uint32_t _writeStr(std::string_view view) { return _writeStr(view.data(), view.size()); } size_t _readBuf(void* buf, size_t len); size_t _writeBuf(const void* buf, size_t len); void _closePipe(); diff --git a/hecl/include/hecl/Blender/SDNARead.hpp b/hecl/include/hecl/Blender/SDNARead.hpp index 9a8e2b823..55334223c 100644 --- a/hecl/include/hecl/Blender/SDNARead.hpp +++ b/hecl/include/hecl/Blender/SDNARead.hpp @@ -57,7 +57,7 @@ class SDNARead { public: explicit SDNARead(SystemStringView path); - operator bool() const { return !m_data.empty(); } + explicit operator bool() const { return !m_data.empty(); } const SDNABlock& sdnaBlock() const { return m_sdnaBlock; } void enumerate(const std::function& func) const; }; diff --git a/hecl/include/hecl/CVar.hpp b/hecl/include/hecl/CVar.hpp index 65d30a7f5..29095b4fd 100644 --- a/hecl/include/hecl/CVar.hpp +++ b/hecl/include/hecl/CVar.hpp @@ -70,8 +70,8 @@ public: float toFloat(bool* isValid = nullptr) const; bool toBoolean(bool* isValid = nullptr) const; int toInteger(bool* isValid = nullptr) const; - const std::wstring toWideLiteral(bool* isValid = nullptr) const; - const std::string toLiteral(bool* isValid = nullptr) const; + std::wstring toWideLiteral(bool* isValid = nullptr) const; + std::string toLiteral(bool* isValid = nullptr) const; bool fromVec4f(const atVec4f& val); bool fromFloat(float val); @@ -117,7 +117,7 @@ public: */ void lock(); - void addListener(ListenerFunc func) { m_listeners.push_back(func); } + void addListener(ListenerFunc func) { m_listeners.push_back(std::move(func)); } private: void dispatch(); diff --git a/hecl/include/hecl/ClientProcess.hpp b/hecl/include/hecl/ClientProcess.hpp index 4287871e7..6ff691129 100644 --- a/hecl/include/hecl/ClientProcess.hpp +++ b/hecl/include/hecl/ClientProcess.hpp @@ -36,7 +36,7 @@ public: void* m_targetBuf; size_t m_maxLen; size_t m_offset; - void run(blender::Token& btok); + void run(blender::Token& btok) override; BufferTransaction(ClientProcess& parent, const ProjectPath& path, void* target, size_t maxLen, size_t offset) : Transaction(parent, Type::Buffer), m_path(path), m_targetBuf(target), m_maxLen(maxLen), m_offset(offset) {} }; @@ -46,13 +46,13 @@ public: bool m_returnResult = false; bool m_force; bool m_fast; - void run(blender::Token& btok); + void run(blender::Token& btok) override; CookTransaction(ClientProcess& parent, const ProjectPath& path, bool force, bool fast, Database::IDataSpec* spec) : Transaction(parent, Type::Cook), m_path(path), m_dataSpec(spec), m_force(force), m_fast(fast) {} }; struct LambdaTransaction final : Transaction { std::function m_func; - void run(blender::Token& btok); + void run(blender::Token& btok) override; LambdaTransaction(ClientProcess& parent, std::function&& func) : Transaction(parent, Type::Lambda), m_func(std::move(func)) {} }; diff --git a/hecl/include/hecl/Compilers.hpp b/hecl/include/hecl/Compilers.hpp index 6c214559e..7c714eb75 100644 --- a/hecl/include/hecl/Compilers.hpp +++ b/hecl/include/hecl/Compilers.hpp @@ -12,35 +12,35 @@ using PlatformEnum = boo::IGraphicsDataFactory::Platform; struct Null {}; struct OpenGL { static constexpr PlatformEnum Enum = PlatformEnum::OpenGL; - static const char* Name; + static constexpr char Name[] = "OpenGL"; #if BOO_HAS_GL using Context = boo::GLDataFactory::Context; #endif }; struct D3D11 { static constexpr PlatformEnum Enum = PlatformEnum::D3D11; - static const char* Name; + static constexpr char Name[] = "D3D11"; #if _WIN32 using Context = boo::D3D11DataFactory::Context; #endif }; struct Metal { static constexpr PlatformEnum Enum = PlatformEnum::Metal; - static const char* Name; + static constexpr char Name[] = "Metal"; #if BOO_HAS_METAL using Context = boo::MetalDataFactory::Context; #endif }; struct Vulkan { static constexpr PlatformEnum Enum = PlatformEnum::Vulkan; - static const char* Name; + static constexpr char Name[] = "Vulkan"; #if BOO_HAS_VULKAN using Context = boo::VulkanDataFactory::Context; #endif }; struct NX { static constexpr PlatformEnum Enum = PlatformEnum::NX; - static const char* Name; + static constexpr char Name[] = "NX"; #if BOO_HAS_NX using Context = boo::NXDataFactory::Context; #endif @@ -51,27 +51,27 @@ namespace PipelineStage { using StageEnum = boo::PipelineStage; struct Null { static constexpr StageEnum Enum = StageEnum::Null; - static const char* Name; + static constexpr char Name[] = "Null"; }; struct Vertex { static constexpr StageEnum Enum = StageEnum::Vertex; - static const char* Name; + static constexpr char Name[] = "Vertex"; }; struct Fragment { static constexpr StageEnum Enum = StageEnum::Fragment; - static const char* Name; + static constexpr char Name[] = "Fragment"; }; struct Geometry { static constexpr StageEnum Enum = StageEnum::Geometry; - static const char* Name; + static constexpr char Name[] = "Geometry"; }; struct Control { static constexpr StageEnum Enum = StageEnum::Control; - static const char* Name; + static constexpr char Name[] = "Control"; }; struct Evaluation { static constexpr StageEnum Enum = StageEnum::Evaluation; - static const char* Name; + static constexpr char Name[] = "Evaluation"; }; } // namespace PipelineStage diff --git a/hecl/include/hecl/Console.hpp b/hecl/include/hecl/Console.hpp index bc54547f3..ab2e95b12 100644 --- a/hecl/include/hecl/Console.hpp +++ b/hecl/include/hecl/Console.hpp @@ -26,13 +26,14 @@ class Console { Console* m_con; LogVisorAdapter(Console* con) : m_con(con) {} - ~LogVisorAdapter() = default; - void report(const char* modName, logvisor::Level severity, fmt::string_view format, fmt::format_args args); - void report(const char* modName, logvisor::Level severity, fmt::wstring_view format, fmt::wformat_args args); + ~LogVisorAdapter() override = default; + void report(const char* modName, logvisor::Level severity, fmt::string_view format, fmt::format_args args) override; + void report(const char* modName, logvisor::Level severity, fmt::wstring_view format, + fmt::wformat_args args) override; void reportSource(const char* modName, logvisor::Level severity, const char* file, unsigned linenum, - fmt::string_view format, fmt::format_args args); + fmt::string_view format, fmt::format_args args) override; void reportSource(const char* modName, logvisor::Level severity, const char* file, unsigned linenum, - fmt::wstring_view format, fmt::wformat_args args); + fmt::wstring_view format, fmt::wformat_args args) override; }; public: diff --git a/hecl/include/hecl/Database.hpp b/hecl/include/hecl/Database.hpp index f4de2c5e1..5f7dee115 100644 --- a/hecl/include/hecl/Database.hpp +++ b/hecl/include/hecl/Database.hpp @@ -1,21 +1,17 @@ #pragma once -#include -#include +#include +#include +#include +#include #include -#include -#include -#include +#include +#include #include #include -#include -#include -#include -#include -#include +#include -#include "athena/IStreamReader.hpp" -#include "logvisor/logvisor.hpp" +#include #include "hecl.hpp" @@ -62,7 +58,7 @@ class IDataSpec { public: IDataSpec(const DataSpecEntry* specEntry) : m_specEntry(specEntry) {} - virtual ~IDataSpec() {} + virtual ~IDataSpec() = default; using FCookProgress = std::function; /** @@ -91,43 +87,33 @@ public: virtual void setThreadProject() {} - virtual bool canExtract(const ExtractPassInfo& info, std::vector& reps) { - (void)info; - (void)reps; + virtual bool canExtract([[maybe_unused]] const ExtractPassInfo& info, + [[maybe_unused]] std::vector& reps) { LogModule.report(logvisor::Error, fmt("not implemented")); return false; } - virtual void doExtract(const ExtractPassInfo& info, const MultiProgressPrinter& progress) { - (void)info; - (void)progress; - } + virtual void doExtract([[maybe_unused]] const ExtractPassInfo& info, + [[maybe_unused]] const MultiProgressPrinter& progress) {} - virtual bool canCook(const ProjectPath& path, blender::Token& btok) { - (void)path; + virtual bool canCook([[maybe_unused]] const ProjectPath& path, [[maybe_unused]] blender::Token& btok) { LogModule.report(logvisor::Error, fmt("not implemented")); return false; } - virtual const DataSpecEntry* overrideDataSpec(const ProjectPath& path, - const Database::DataSpecEntry* oldEntry) const { - (void)path; + virtual const DataSpecEntry* overrideDataSpec([[maybe_unused]] const ProjectPath& path, + const DataSpecEntry* oldEntry) const { return oldEntry; } - virtual void doCook(const ProjectPath& path, const ProjectPath& cookedPath, bool fast, blender::Token& btok, - FCookProgress progress) { - (void)path; - (void)cookedPath; - (void)fast; - (void)progress; - } + virtual void doCook([[maybe_unused]] const ProjectPath& path, [[maybe_unused]] const ProjectPath& cookedPath, + [[maybe_unused]] bool fast, [[maybe_unused]] blender::Token& btok, + [[maybe_unused]] FCookProgress progress) {} - virtual bool canPackage(const ProjectPath& path) { - (void)path; + virtual bool canPackage([[maybe_unused]] const ProjectPath& path) { return false; } - virtual void doPackage(const ProjectPath& path, const Database::DataSpecEntry* entry, bool fast, blender::Token& btok, - const MultiProgressPrinter& progress, ClientProcess* cp = nullptr) { - (void)path; - } + virtual void doPackage([[maybe_unused]] const ProjectPath& path, [[maybe_unused]] const DataSpecEntry* entry, + [[maybe_unused]] bool fast, [[maybe_unused]] blender::Token& btok, + [[maybe_unused]] const MultiProgressPrinter& progress, + [[maybe_unused]] ClientProcess* cp = nullptr) {} virtual void interruptCook() {} @@ -190,7 +176,7 @@ protected: Cafe /**< Swizzled textures and R700 shader objects */ }; - typedef std::function FDataAppender; + using FDataAppender = std::function; /** * @brief Optional private method implemented by subclasses to cook objects @@ -203,14 +189,12 @@ protected: * 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. */ - virtual bool cookObject(FDataAppender dataAppender, DataEndianness endianness, DataPlatform platform) { - (void)dataAppender; - (void)endianness; - (void)platform; + virtual bool cookObject([[maybe_unused]] FDataAppender dataAppender, [[maybe_unused]] DataEndianness endianness, + [[maybe_unused]] DataPlatform platform) { return true; } - typedef std::function FDepAdder; + using FDepAdder = std::function; /** * @brief Optional private method implemented by CProjectObject subclasses to resolve dependencies @@ -220,7 +204,7 @@ protected: * 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. */ - virtual void gatherDeps(FDepAdder depAdder) { (void)depAdder; } + virtual void gatherDeps([[maybe_unused]] FDepAdder depAdder) {} /** * @brief Get a packagable FourCC representation of the object's type @@ -262,7 +246,7 @@ private: public: Project(const ProjectRootPath& rootPath); - operator bool() const { return m_valid; } + explicit operator bool() const { return m_valid; } /** * @brief Configuration file handle @@ -273,7 +257,7 @@ public: class ConfigFile { SystemString m_filepath; std::vector m_lines; - FILE* m_lockedFile = NULL; + UniqueFilePtr m_lockedFile; public: ConfigFile(const Project& project, SystemStringView name, SystemStringView subdir = _SYS_STR("/.hecl/")); @@ -311,7 +295,7 @@ public: /** * @brief Get the path of project's cooked directory for a specific DataSpec - * @param DataSpec to retrieve path for + * @param spec DataSpec to retrieve path for * @return project cooked path * * The cooked path matches the directory layout of the working directory @@ -320,7 +304,7 @@ public: /** * @brief Add given file(s) to the database - * @param path file or pattern within project + * @param paths files or patterns within project * @return true on success * * This method blocks while object hashing takes place diff --git a/hecl/include/hecl/FourCC.hpp b/hecl/include/hecl/FourCC.hpp index 63cf98439..26ba12ad6 100644 --- a/hecl/include/hecl/FourCC.hpp +++ b/hecl/include/hecl/FourCC.hpp @@ -18,28 +18,36 @@ class FourCC { protected: union { char fcc[4]; - uint32_t num; + uint32_t num = 0; }; public: - constexpr FourCC() /* Sentinel FourCC */ - : num(0) {} - constexpr FourCC(const FourCC& other) : num(other.num) {} - constexpr FourCC(const char* name) : num(*(uint32_t*)name) {} - constexpr FourCC(uint32_t n) : num(n) {} - bool operator==(const FourCC& other) const { return num == other.num; } - bool operator!=(const FourCC& other) const { return num != other.num; } - bool operator==(const char* other) const { return num == *(uint32_t*)other; } - bool operator!=(const char* other) const { return num != *(uint32_t*)other; } - bool operator==(int32_t other) const { return num == uint32_t(other); } - bool operator!=(int32_t other) const { return num != uint32_t(other); } - bool operator==(uint32_t other) const { return num == other; } - bool operator!=(uint32_t other) const { return num != other; } - std::string toString() const { return std::string(fcc, 4); } - uint32_t toUint32() const { return num; } - const char* getChars() const { return fcc; } - char* getChars() { return fcc; } - bool IsValid() const { return num != 0; } + // Sentinel FourCC + constexpr FourCC() noexcept = default; + constexpr FourCC(const FourCC& other) noexcept = default; + constexpr FourCC(FourCC&& other) noexcept = default; + constexpr FourCC(const char* name) noexcept : fcc{name[0], name[1], name[2], name[3]} {} + constexpr FourCC(uint32_t n) noexcept : num(n) {} + + constexpr FourCC& operator=(const FourCC&) noexcept = default; + constexpr FourCC& operator=(FourCC&&) noexcept = default; + + constexpr bool operator==(const FourCC& other) const { return num == other.num; } + constexpr bool operator!=(const FourCC& other) const { return !operator==(other); } + constexpr bool operator==(const char* other) const { + return other[0] == fcc[0] && other[1] == fcc[1] && other[2] == fcc[2] && other[3] == fcc[3]; + } + constexpr bool operator!=(const char* other) const { return !operator==(other); } + constexpr bool operator==(int32_t other) const { return num == uint32_t(other); } + constexpr bool operator!=(int32_t other) const { return !operator==(other); } + constexpr bool operator==(uint32_t other) const { return num == other; } + constexpr bool operator!=(uint32_t other) const { return !operator==(other); } + + std::string toString() const { return std::string(std::begin(fcc), std::end(fcc)); } + constexpr uint32_t toUint32() const { return num; } + constexpr const char* getChars() const { return fcc; } + constexpr char* getChars() { return fcc; } + constexpr bool IsValid() const { return num != 0; } }; #define FOURCC(chars) FourCC(SBIG(chars)) @@ -55,25 +63,25 @@ public: AT_DECL_EXPLICIT_DNA_YAML }; template <> -inline void DNAFourCC::Enumerate(typename Read::StreamT& r) { - r.readUBytesToBuf(fcc, 4); +inline void DNAFourCC::Enumerate(Read::StreamT& r) { + r.readUBytesToBuf(fcc, std::size(fcc)); } template <> -inline void DNAFourCC::Enumerate(typename Write::StreamT& w) { - w.writeUBytes((atUint8*)fcc, 4); +inline void DNAFourCC::Enumerate(Write::StreamT& w) { + w.writeBytes(fcc, std::size(fcc)); } template <> -inline void DNAFourCC::Enumerate(typename ReadYaml::StreamT& r) { - std::string rs = r.readString(nullptr); - strncpy(fcc, rs.c_str(), 4); +inline void DNAFourCC::Enumerate(ReadYaml::StreamT& r) { + const std::string rs = r.readString(nullptr); + rs.copy(fcc, std::size(fcc)); } template <> -inline void DNAFourCC::Enumerate(typename WriteYaml::StreamT& w) { - w.writeString(nullptr, std::string(fcc, 4)); +inline void DNAFourCC::Enumerate(WriteYaml::StreamT& w) { + w.writeString(nullptr, std::string_view{fcc, std::size(fcc)}); } template <> -inline void DNAFourCC::Enumerate(typename BinarySize::StreamT& s) { - s += 4; +inline void DNAFourCC::Enumerate(BinarySize::StreamT& s) { + s += std::size(fcc); } } // namespace hecl @@ -85,7 +93,7 @@ struct hash { }; } // namespace std -FMT_CUSTOM_FORMATTER(hecl::FourCC, "{:c}{:c}{:c}{:c}", - obj.getChars()[0], obj.getChars()[1], obj.getChars()[2], obj.getChars()[3]) -FMT_CUSTOM_FORMATTER(hecl::DNAFourCC, "{:c}{:c}{:c}{:c}", - obj.getChars()[0], obj.getChars()[1], obj.getChars()[2], obj.getChars()[3]) +FMT_CUSTOM_FORMATTER(hecl::FourCC, "{:c}{:c}{:c}{:c}", obj.getChars()[0], obj.getChars()[1], obj.getChars()[2], + obj.getChars()[3]) +FMT_CUSTOM_FORMATTER(hecl::DNAFourCC, "{:c}{:c}{:c}{:c}", obj.getChars()[0], obj.getChars()[1], obj.getChars()[2], + obj.getChars()[3]) diff --git a/hecl/include/hecl/PipelineBase.hpp b/hecl/include/hecl/PipelineBase.hpp index d15fdf612..235f1723f 100644 --- a/hecl/include/hecl/PipelineBase.hpp +++ b/hecl/include/hecl/PipelineBase.hpp @@ -1,6 +1,6 @@ #pragma once #include "Compilers.hpp" -extern "C" unsigned long long XXH64(const void* input, size_t length, unsigned long long seed); +#include "../extern/boo/xxhash/xxhash.h" #define HECL_RUNTIME 1 diff --git a/hecl/include/hecl/SystemChar.hpp b/hecl/include/hecl/SystemChar.hpp index 373ae0c76..124c28332 100644 --- a/hecl/include/hecl/SystemChar.hpp +++ b/hecl/include/hecl/SystemChar.hpp @@ -26,7 +26,6 @@ namespace hecl { #if HECL_UCS2 typedef wchar_t SystemChar; -static inline size_t StrLen(const SystemChar* str) { return wcslen(str); } typedef std::wstring SystemString; typedef std::wstring_view SystemStringView; static inline void ToLower(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), towlower); } @@ -37,15 +36,22 @@ static inline void ToUpper(SystemString& str) { std::transform(str.begin(), str. typedef struct _stat Sstat; #else typedef char SystemChar; -static inline size_t StrLen(const SystemChar* str) { return strlen(str); } typedef std::string SystemString; typedef std::string_view SystemStringView; -static inline void ToLower(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), tolower); } -static inline void ToUpper(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), toupper); } +static inline void ToLower(SystemString& str) { + std::transform(str.begin(), str.end(), str.begin(), + [](SystemChar c) { return std::tolower(static_cast(c)); }); +} +static inline void ToUpper(SystemString& str) { + std::transform(str.begin(), str.end(), str.begin(), + [](SystemChar c) { return std::toupper(static_cast(c)); }); +} #ifndef _SYS_STR #define _SYS_STR(val) val #endif typedef struct stat Sstat; #endif +constexpr size_t StrLen(const SystemChar* str) { return std::char_traits::length(str); } + } // namespace hecl diff --git a/hecl/include/hecl/TypedVariant.hpp b/hecl/include/hecl/TypedVariant.hpp index 1ed924a94..5eae4b1a8 100644 --- a/hecl/include/hecl/TypedVariant.hpp +++ b/hecl/include/hecl/TypedVariant.hpp @@ -173,7 +173,7 @@ public: }, static_cast(*this)); } - constexpr operator bool() const noexcept { + constexpr explicit operator bool() const noexcept { return !std::holds_alternative>>(*this); } }; @@ -204,7 +204,7 @@ template <> \ template <> \ inline void hecl::TypedVariantBigDNA<__VA_ARGS__>::Enumerate::Read>(typename Read::StreamT & r) { \ EnumType variant_type = {}; \ - Do::Read>({"variant_type"}, variant_type, r); \ + Do::Read>(athena::io::PropId("variant_type"), variant_type, r); \ static_cast&>(*this) = Build(variant_type); \ visit([&](auto& var) { var.read(r); }); \ } \ @@ -215,7 +215,7 @@ inline void hecl::TypedVariantBigDNA<__VA_ARGS__>::Enumerate; \ EnumType variant_type = T::variant_type(); \ - Do::Write>({"variant_type"}, variant_type, w); \ + Do::Write>(athena::io::PropId("variant_type"), variant_type, w); \ var.write(w); \ }); \ } \ @@ -226,7 +226,7 @@ inline void hecl::TypedVariantBigDNA<__VA_ARGS__>::Enumerate; \ EnumType variant_type = T::variant_type(); \ - Do::BinarySize>({"variant_type"}, variant_type, sz); \ + Do::BinarySize>(athena::io::PropId("variant_type"), variant_type, sz); \ var.binarySize(sz); \ }); \ } \ @@ -241,7 +241,7 @@ template <> \ template <> \ inline void hecl::TypedVariantBigDNA<__VA_ARGS__>::Enumerate::ReadYaml>(typename ReadYaml::StreamT & r) { \ EnumType variant_type = {}; \ - Do::ReadYaml>({"variant_type"}, variant_type, r); \ + Do::ReadYaml>(athena::io::PropId("variant_type"), variant_type, r); \ static_cast&>(*this) = Build(variant_type); \ visit([&](auto& var) { var.read(r); }); \ } \ @@ -252,7 +252,7 @@ inline void hecl::TypedVariantBigDNA<__VA_ARGS__>::Enumerate; \ EnumType variant_type = T::variant_type(); \ - Do::WriteYaml>({"variant_type"}, variant_type, w); \ + Do::WriteYaml>(athena::io::PropId("variant_type"), variant_type, w); \ var.write(w); \ }); \ } diff --git a/hecl/include/hecl/UniformBufferPool.hpp b/hecl/include/hecl/UniformBufferPool.hpp index b9ceb115d..61c6dea09 100644 --- a/hecl/include/hecl/UniformBufferPool.hpp +++ b/hecl/include/hecl/UniformBufferPool.hpp @@ -153,7 +153,7 @@ public: return {bucket.buffer, m_div.rem * m_pool->m_stride}; } - operator bool() const { return m_pool != nullptr && m_index != -1; } + explicit operator bool() const { return m_pool != nullptr && m_index != -1; } }; UniformBufferPool() = default; diff --git a/hecl/include/hecl/VertexBufferPool.hpp b/hecl/include/hecl/VertexBufferPool.hpp index 4468e5ef2..feb8e6ec0 100644 --- a/hecl/include/hecl/VertexBufferPool.hpp +++ b/hecl/include/hecl/VertexBufferPool.hpp @@ -158,7 +158,7 @@ public: return {bucket.buffer, m_div.rem}; } - operator bool() const { return m_pool != nullptr && m_index != -1; } + explicit operator bool() const { return m_pool != nullptr && m_index != -1; } }; VertexBufferPool() = default; diff --git a/hecl/include/hecl/hecl.hpp b/hecl/include/hecl/hecl.hpp index 57d51c93a..28a0ba3c8 100644 --- a/hecl/include/hecl/hecl.hpp +++ b/hecl/include/hecl/hecl.hpp @@ -22,20 +22,22 @@ extern "C" int rep_closefrom(int lower); #endif #include #include +#include #include #include "winsupport.hpp" #endif +#include #include -#include #include #include +#include #include -#include -#include -#include #include #include +#include +#include + #include "logvisor/logvisor.hpp" #include "athena/Global.hpp" #include "../extern/boo/xxhash/xxhash.h" @@ -109,46 +111,66 @@ class SystemUTF8Conv { public: explicit SystemUTF8Conv(SystemStringView str) : m_utf8(WideToUTF8(str)) {} + std::string_view str() const { return m_utf8; } const char* c_str() const { return m_utf8.c_str(); } - std::string operator+(std::string_view other) const { return m_utf8 + other.data(); } + + friend std::string operator+(const SystemUTF8Conv& lhs, std::string_view rhs) { return lhs.m_utf8 + rhs.data(); } + friend std::string operator+(std::string_view lhs, const SystemUTF8Conv& rhs) { + return std::string(lhs).append(rhs.m_utf8); + } }; -inline std::string operator+(std::string_view lhs, const SystemUTF8Conv& rhs) { return std::string(lhs) + rhs.c_str(); } + class SystemStringConv { std::wstring m_sys; public: explicit SystemStringConv(std::string_view str) : m_sys(UTF8ToWide(str)) {} + SystemStringView sys_str() const { return m_sys; } const SystemChar* c_str() const { return m_sys.c_str(); } - std::wstring operator+(const std::wstring_view other) const { return m_sys + other.data(); } + + friend std::wstring operator+(const SystemStringConv& lhs, const std::wstring_view rhs) { + return lhs.m_sys + rhs.data(); + } + friend std::wstring operator+(std::wstring_view lhs, const SystemStringConv& rhs) { + return std::wstring(lhs).append(rhs.m_sys); + } }; -inline std::wstring operator+(std::wstring_view lhs, const SystemStringConv& rhs) { - return std::wstring(lhs) + rhs.c_str(); -} #else class SystemUTF8Conv { std::string_view m_utf8; public: explicit SystemUTF8Conv(SystemStringView str) : m_utf8(str) {} + std::string_view str() const { return m_utf8; } const char* c_str() const { return m_utf8.data(); } - std::string operator+(std::string_view other) const { return std::string(m_utf8) + other.data(); } + + friend std::string operator+(const SystemUTF8Conv& lhs, std::string_view rhs) { + return std::string(lhs.m_utf8).append(rhs); + } + friend std::string operator+(std::string_view lhs, const SystemUTF8Conv& rhs) { + return std::string(lhs).append(rhs.m_utf8); + } }; -inline std::string operator+(std::string_view lhs, const SystemUTF8Conv& rhs) { return std::string(lhs) + rhs.c_str(); } + class SystemStringConv { std::string_view m_sys; public: explicit SystemStringConv(std::string_view str) : m_sys(str) {} + SystemStringView sys_str() const { return m_sys; } const SystemChar* c_str() const { return m_sys.data(); } - std::string operator+(std::string_view other) const { return std::string(m_sys) + other.data(); } + + friend std::string operator+(const SystemStringConv& lhs, std::string_view rhs) { + return std::string(lhs.m_sys).append(rhs); + } + friend std::string operator+(std::string_view lhs, const SystemStringConv& rhs) { + return std::string(lhs).append(rhs.m_sys); + } }; -inline std::string operator+(std::string_view lhs, const SystemStringConv& rhs) { - return std::string(lhs) + rhs.c_str(); -} #endif void SanitizePath(std::string& path); @@ -167,7 +189,7 @@ inline void MakeDir(const char* dir) { HRESULT err; if (!CreateDirectoryA(dir, NULL)) if ((err = GetLastError()) != ERROR_ALREADY_EXISTS) - LogModule.report(logvisor::Fatal, fmt("MakeDir(%s)"), dir); + LogModule.report(logvisor::Fatal, fmt("MakeDir({})"), dir); #else if (mkdir(dir, 0755)) if (errno != EEXIST) @@ -180,7 +202,7 @@ inline void MakeDir(const wchar_t* dir) { HRESULT err; if (!CreateDirectoryW(dir, NULL)) if ((err = GetLastError()) != ERROR_ALREADY_EXISTS) - LogModule.report(logvisor::Fatal, fmt(_SYS_STR("MakeDir(%s)")), dir); + LogModule.report(logvisor::Fatal, fmt(_SYS_STR("MakeDir({})")), dir); } #endif @@ -253,6 +275,16 @@ inline FILE* Fopen(const SystemChar* path, const SystemChar* mode, FileLockType return fp; } +struct UniqueFileDeleter { + void operator()(FILE* file) const noexcept { std::fclose(file); } +}; +using UniqueFilePtr = std::unique_ptr; + +inline UniqueFilePtr FopenUnique(const SystemChar* path, const SystemChar* mode, + FileLockType lock = FileLockType::None) { + return UniqueFilePtr{Fopen(path, mode, lock)}; +} + inline int FSeek(FILE* fp, int64_t offset, int whence) { #if _WIN32 return _fseeki64(fp, offset, whence); @@ -309,11 +341,8 @@ inline int StrCmp(const SystemChar* str1, const SystemChar* str2) { inline int StrNCmp(const SystemChar* str1, const SystemChar* str2, size_t count) { if (!str1 || !str2) return str1 != str2; -#if HECL_UCS2 - return wcsncmp(str1, str2, count); -#else - return strncmp(str1, str2, count); -#endif + + return std::char_traits::compare(str1, str2, count); } inline int StrCaseCmp(const SystemChar* str1, const SystemChar* str2) { @@ -341,11 +370,11 @@ inline bool CheckFreeSpace(const SystemChar* path, size_t reqSz) { wchar_t* end; DWORD ret = GetFullPathNameW(path, 1024, buf, &end); if (!ret || ret > 1024) - LogModule.report(logvisor::Fatal, fmt(_SYS_STR("GetFullPathNameW %s")), path); + LogModule.report(logvisor::Fatal, fmt(_SYS_STR("GetFullPathNameW {}")), path); if (end) end[0] = L'\0'; if (!GetDiskFreeSpaceExW(buf, &freeBytes, nullptr, nullptr)) - LogModule.report(logvisor::Fatal, fmt(_SYS_STR("GetDiskFreeSpaceExW %s: %d")), path, GetLastError()); + LogModule.report(logvisor::Fatal, fmt(_SYS_STR("GetDiskFreeSpaceExW {}: {}")), path, GetLastError()); return reqSz < freeBytes.QuadPart; #else struct statvfs svfs; @@ -391,13 +420,12 @@ inline int ConsoleWidth(bool* ok = nullptr) { } class MultiProgressPrinter; - -typedef std::basic_regex SystemRegex; -typedef std::regex_token_iterator SystemRegexTokenIterator; -typedef std::match_results SystemRegexMatch; - class ProjectRootPath; +using SystemRegex = std::basic_regex; +using SystemRegexMatch = std::match_results; +using SystemRegexTokenIterator = std::regex_token_iterator; + /** * @brief Hash representation used for all storable and comparable objects * @@ -409,35 +437,36 @@ protected: uint64_t hash = 0; public: - Hash() = default; - operator bool() const { return hash != 0; } - Hash(const void* buf, size_t len) : hash(XXH64((uint8_t*)buf, len, 0)) {} - Hash(std::string_view str) : hash(XXH64((uint8_t*)str.data(), str.size(), 0)) {} - Hash(std::wstring_view str) : hash(XXH64((uint8_t*)str.data(), str.size() * 2, 0)) {} - Hash(uint64_t hashin) : hash(hashin) {} - Hash(const Hash& other) { hash = other.hash; } - uint32_t val32() const { return uint32_t(hash) ^ uint32_t(hash >> 32); } - uint64_t val64() const { return uint64_t(hash); } - size_t valSizeT() const { return size_t(hash); } + constexpr Hash() noexcept = default; + constexpr Hash(const Hash&) noexcept = default; + constexpr Hash(Hash&&) noexcept = default; + constexpr Hash(uint64_t hashin) noexcept : hash(hashin) {} + explicit Hash(const void* buf, size_t len) noexcept : hash(XXH64(buf, len, 0)) {} + explicit Hash(std::string_view str) noexcept : hash(XXH64(str.data(), str.size(), 0)) {} + explicit Hash(std::wstring_view str) noexcept : hash(XXH64(str.data(), str.size() * 2, 0)) {} + + constexpr uint32_t val32() const noexcept { return uint32_t(hash) ^ uint32_t(hash >> 32); } + constexpr uint64_t val64() const noexcept { return uint64_t(hash); } + constexpr size_t valSizeT() const noexcept { return size_t(hash); } template - T valT() const; - Hash& operator=(const Hash& other) { - hash = other.hash; - return *this; - } - bool operator==(const Hash& other) const { return hash == other.hash; } - bool operator!=(const Hash& other) const { return hash != other.hash; } - bool operator<(const Hash& other) const { return hash < other.hash; } - bool operator>(const Hash& other) const { return hash > other.hash; } - bool operator<=(const Hash& other) const { return hash <= other.hash; } - bool operator>=(const Hash& other) const { return hash >= other.hash; } + constexpr T valT() const noexcept; + + constexpr Hash& operator=(const Hash& other) noexcept = default; + constexpr Hash& operator=(Hash&& other) noexcept = default; + constexpr bool operator==(const Hash& other) const noexcept { return hash == other.hash; } + constexpr bool operator!=(const Hash& other) const noexcept { return !operator==(other); } + constexpr bool operator<(const Hash& other) const noexcept { return hash < other.hash; } + constexpr bool operator>(const Hash& other) const noexcept { return hash > other.hash; } + constexpr bool operator<=(const Hash& other) const noexcept { return hash <= other.hash; } + constexpr bool operator>=(const Hash& other) const noexcept { return hash >= other.hash; } + constexpr explicit operator bool() const noexcept { return hash != 0; } }; template <> -inline uint32_t Hash::valT() const { +constexpr uint32_t Hash::valT() const noexcept { return val32(); } template <> -inline uint64_t Hash::valT() const { +constexpr uint64_t Hash::valT() const noexcept { return val64(); } @@ -469,22 +498,16 @@ public: */ struct CaseInsensitiveCompare { bool operator()(std::string_view lhs, std::string_view rhs) const { -#if _WIN32 - if (_stricmp(lhs.data(), rhs.data()) < 0) -#else - if (strcasecmp(lhs.data(), rhs.data()) < 0) -#endif - return true; - return false; + return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), [](char lhs, char rhs) { + return std::tolower(static_cast(lhs)) < std::tolower(static_cast(rhs)); + }); } -#if _WIN32 bool operator()(std::wstring_view lhs, std::wstring_view rhs) const { - if (_wcsicmp(lhs.data(), rhs.data()) < 0) - return true; - return false; + return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), [](wchar_t lhs, wchar_t rhs) { + return std::towlower(lhs) < std::towlower(rhs); + }); } -#endif }; /** @@ -499,8 +522,8 @@ public: size_t m_fileSz; bool m_isDir; - Entry(const hecl::SystemString& path, const hecl::SystemChar* name, size_t sz, bool isDir) - : m_path(path), m_name(name), m_fileSz(sz), m_isDir(isDir) {} + Entry(hecl::SystemString path, const hecl::SystemChar* name, size_t sz, bool isDir) + : m_path(std::move(path)), m_name(name), m_fileSz(sz), m_isDir(isDir) {} }; private: @@ -510,7 +533,7 @@ public: DirectoryEnumerator(SystemStringView path, Mode mode = Mode::DirsThenFilesSorted, bool sizeSort = false, bool reverse = false, bool noHidden = false); - operator bool() const { return m_entries.size() != 0; } + explicit operator bool() const { return m_entries.size() != 0; } size_t size() const { return m_entries.size(); } std::vector::const_iterator begin() const { return m_entries.cbegin(); } std::vector::const_iterator end() const { return m_entries.cend(); } @@ -542,7 +565,7 @@ public: /** * @brief Tests for non-empty project root path */ - operator bool() const { return m_projRoot.size() != 0; } + explicit operator bool() const { return m_projRoot.size() != 0; } /** * @brief Construct a representation of a project root path @@ -577,7 +600,8 @@ public: return SystemString(beginIt, absPathForward.cend()); } } - LogModule.report(logvisor::Fatal, fmt(_SYS_STR("unable to resolve '{}' as project relative '{}'")), absPath, m_projRoot); + LogModule.report(logvisor::Fatal, fmt(_SYS_STR("unable to resolve '{}' as project relative '{}'")), absPath, + m_projRoot); return SystemString(); } @@ -593,9 +617,9 @@ public: * @brief HECL-specific xxhash * @return unique hash value */ - Hash hash() const { return m_hash; } - bool operator==(const ProjectRootPath& other) const { return m_hash == other.m_hash; } - bool operator!=(const ProjectRootPath& other) const { return m_hash != other.m_hash; } + Hash hash() const noexcept { return m_hash; } + bool operator==(const ProjectRootPath& other) const noexcept { return m_hash == other.m_hash; } + bool operator!=(const ProjectRootPath& other) const noexcept { return !operator==(other); } /** * @brief Obtain c-string of final path component @@ -661,7 +685,7 @@ public: /** * @brief Tests for non-empty project path */ - operator bool() const { return m_absPath.size() != 0; } + explicit operator bool() const { return m_absPath.size() != 0; } /** * @brief Clears path @@ -1026,9 +1050,9 @@ public: * @brief HECL-specific xxhash * @return unique hash value */ - Hash hash() const { return m_hash; } - bool operator==(const ProjectPath& other) const { return m_hash == other.m_hash; } - bool operator!=(const ProjectPath& other) const { return m_hash != other.m_hash; } + Hash hash() const noexcept { return m_hash; } + bool operator==(const ProjectPath& other) const noexcept { return m_hash == other.m_hash; } + bool operator!=(const ProjectPath& other) const noexcept { return !operator==(other); } }; /** @@ -1039,21 +1063,21 @@ public: static bool BeginsWith(SystemStringView str, SystemStringView test) { if (test.size() > str.size()) return false; - return !StrNCmp(str.data(), test.data(), test.size()); + return str.compare(0, test.size(), test) == 0; } static bool EndsWith(SystemStringView str, SystemStringView test) { if (test.size() > str.size()) return false; - return !StrNCmp(&*(str.end() - test.size()), test.data(), test.size()); + return str.compare(str.size() - test.size(), SystemStringView::npos, test) == 0; } static std::string TrimWhitespace(std::string_view str) { auto bit = str.begin(); - while (bit != str.cend() && isspace(*bit)) + while (bit != str.cend() && std::isspace(static_cast(*bit))) ++bit; auto eit = str.end(); - while (eit != str.cbegin() && isspace(*(eit - 1))) + while (eit != str.cbegin() && std::isspace(static_cast(*(eit - 1)))) --eit; return {bit, eit}; } @@ -1062,21 +1086,21 @@ public: static bool BeginsWith(std::string_view str, std::string_view test) { if (test.size() > str.size()) return false; - return !strncmp(str.data(), test.data(), test.size()); + return str.compare(0, test.size(), test) == 0; } static bool EndsWith(std::string_view str, std::string_view test) { if (test.size() > str.size()) return false; - return !strncmp(&*(str.end() - test.size()), test.data(), test.size()); + return str.compare(str.size() - test.size(), std::string_view::npos, test) == 0; } static SystemString TrimWhitespace(SystemStringView str) { auto bit = str.begin(); - while (bit != str.cend() && iswspace(*bit)) + while (bit != str.cend() && std::iswspace(*bit)) ++bit; auto eit = str.end(); - while (eit != str.cbegin() && iswspace(*(eit - 1))) + while (eit != str.cbegin() && std::iswspace(*(eit - 1))) --eit; return {bit, eit}; } @@ -1095,9 +1119,9 @@ class ResourceLock { bool good; public: - operator bool() const { return good; } + explicit operator bool() const { return good; } static bool InProgress(const ProjectPath& path); - ResourceLock(const ProjectPath& path) { good = SetThreadRes(path); } + explicit ResourceLock(const ProjectPath& path) : good{SetThreadRes(path)} {} ~ResourceLock() { if (good) ClearThreadRes(); @@ -1150,7 +1174,7 @@ bool IsPathYAML(const hecl::ProjectPath& path); /* Type-sensitive byte swappers */ template -constexpr T bswap16(T val) { +constexpr T bswap16(T val) noexcept { #if __GNUC__ return __builtin_bswap16(val); #elif _WIN32 @@ -1161,7 +1185,7 @@ constexpr T bswap16(T val) { } template -constexpr T bswap32(T val) { +constexpr T bswap32(T val) noexcept { #if __GNUC__ return __builtin_bswap32(val); #elif _WIN32 @@ -1174,7 +1198,7 @@ constexpr T bswap32(T val) { } template -constexpr T bswap64(T val) { +constexpr T bswap64(T val) noexcept { #if __GNUC__ return __builtin_bswap64(val); #elif _WIN32 @@ -1188,49 +1212,61 @@ constexpr T bswap64(T val) { } #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -constexpr int16_t SBig(int16_t val) { return bswap16(val); } -constexpr uint16_t SBig(uint16_t val) { return bswap16(val); } -constexpr int32_t SBig(int32_t val) { return bswap32(val); } -constexpr uint32_t SBig(uint32_t val) { return bswap32(val); } -constexpr int64_t SBig(int64_t val) { return bswap64(val); } -constexpr uint64_t SBig(uint64_t val) { return bswap64(val); } -constexpr float SBig(float val) { - union { float f; atInt32 i; } uval1 = {val}; - union { atInt32 i; float f; } uval2 = {bswap32(uval1.i)}; +constexpr int16_t SBig(int16_t val) noexcept { return bswap16(val); } +constexpr uint16_t SBig(uint16_t val) noexcept { return bswap16(val); } +constexpr int32_t SBig(int32_t val) noexcept { return bswap32(val); } +constexpr uint32_t SBig(uint32_t val) noexcept { return bswap32(val); } +constexpr int64_t SBig(int64_t val) noexcept { return bswap64(val); } +constexpr uint64_t SBig(uint64_t val) noexcept { return bswap64(val); } +constexpr float SBig(float val) noexcept { + union { + float f; + atInt32 i; + } uval1 = {val}; + union { + atInt32 i; + float f; + } uval2 = {bswap32(uval1.i)}; return uval2.f; } -constexpr double SBig(double val) { - union { double f; atInt64 i; } uval1 = {val}; - union { atInt64 i; double f; } uval2 = {bswap64(uval1.i)}; +constexpr double SBig(double val) noexcept { + union { + double f; + atInt64 i; + } uval1 = {val}; + union { + atInt64 i; + double f; + } uval2 = {bswap64(uval1.i)}; return uval2.f; } #ifndef SBIG #define SBIG(q) (((q)&0x000000FF) << 24 | ((q)&0x0000FF00) << 8 | ((q)&0x00FF0000) >> 8 | ((q)&0xFF000000) >> 24) #endif -constexpr int16_t SLittle(int16_t val) { return val; } -constexpr uint16_t SLittle(uint16_t val) { return val; } -constexpr int32_t SLittle(int32_t val) { return val; } -constexpr uint32_t SLittle(uint32_t val) { return val; } -constexpr int64_t SLittle(int64_t val) { return val; } -constexpr uint64_t SLittle(uint64_t val) { return val; } -constexpr float SLittle(float val) { return val; } -constexpr double SLittle(double val) { return val; } +constexpr int16_t SLittle(int16_t val) noexcept { return val; } +constexpr uint16_t SLittle(uint16_t val) noexcept { return val; } +constexpr int32_t SLittle(int32_t val) noexcept { return val; } +constexpr uint32_t SLittle(uint32_t val) noexcept { return val; } +constexpr int64_t SLittle(int64_t val) noexcept { return val; } +constexpr uint64_t SLittle(uint64_t val) noexcept { return val; } +constexpr float SLittle(float val) noexcept { return val; } +constexpr double SLittle(double val) noexcept { return val; } #ifndef SLITTLE #define SLITTLE(q) (q) #endif #else -constexpr int16_t SLittle(int16_t val) { return bswap16(val); } -constexpr uint16_t SLittle(uint16_t val) { return bswap16(val); } -constexpr int32_t SLittle(int32_t val) { return bswap32(val); } -constexpr uint32_t SLittle(uint32_t val) { return bswap32(val); } -constexpr int64_t SLittle(int64_t val) { return bswap64(val); } -constexpr uint64_t SLittle(uint64_t val) { return bswap64(val); } -constexpr float SLittle(float val) { +constexpr int16_t SLittle(int16_t val) noexcept { return bswap16(val); } +constexpr uint16_t SLittle(uint16_t val) noexcept { return bswap16(val); } +constexpr int32_t SLittle(int32_t val) noexcept { return bswap32(val); } +constexpr uint32_t SLittle(uint32_t val) noexcept { return bswap32(val); } +constexpr int64_t SLittle(int64_t val) noexcept { return bswap64(val); } +constexpr uint64_t SLittle(uint64_t val) noexcept { return bswap64(val); } +constexpr float SLittle(float val) noexcept { int32_t ival = bswap32(*((int32_t*)(&val))); return *((float*)(&ival)); } -constexpr double SLittle(double val) { +constexpr double SLittle(double val) noexcept { int64_t ival = bswap64(*((int64_t*)(&val))); return *((double*)(&ival)); } @@ -1238,22 +1274,22 @@ constexpr double SLittle(double val) { #define SLITTLE(q) (((q)&0x000000FF) << 24 | ((q)&0x0000FF00) << 8 | ((q)&0x00FF0000) >> 8 | ((q)&0xFF000000) >> 24) #endif -constexpr int16_t SBig(int16_t val) { return val; } -constexpr uint16_t SBig(uint16_t val) { return val; } -constexpr int32_t SBig(int32_t val) { return val; } -constexpr uint32_t SBig(uint32_t val) { return val; } -constexpr int64_t SBig(int64_t val) { return val; } -constexpr uint64_t SBig(uint64_t val) { return val; } -constexpr float SBig(float val) { return val; } -constexpr double SBig(double val) { return val; } +constexpr int16_t SBig(int16_t val) noexcept { return val; } +constexpr uint16_t SBig(uint16_t val) noexcept { return val; } +constexpr int32_t SBig(int32_t val) noexcept { return val; } +constexpr uint32_t SBig(uint32_t val) noexcept { return val; } +constexpr int64_t SBig(int64_t val) noexcept { return val; } +constexpr uint64_t SBig(uint64_t val) noexcept { return val; } +constexpr float SBig(float val) noexcept { return val; } +constexpr double SBig(double val) noexcept { return val; } #ifndef SBIG #define SBIG(q) (q) #endif #endif template -constexpr void hash_combine_impl(SizeT& seed, SizeT value) { - seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2); +constexpr void hash_combine_impl(SizeT& seed, SizeT value) noexcept { + seed ^= value + 0x9e3779b9 + (seed << 6) + (seed >> 2); } } // namespace hecl diff --git a/hecl/lib/Blender/Connection.cpp b/hecl/lib/Blender/Connection.cpp index b4ad59278..9e63544d9 100644 --- a/hecl/lib/Blender/Connection.cpp +++ b/hecl/lib/Blender/Connection.cpp @@ -1,23 +1,28 @@ +#include #include +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include #include #include -#include "logvisor/logvisor.hpp" #include "hecl/Blender/Connection.hpp" +#include "hecl/Blender/Token.hpp" #include "hecl/SteamFinder.hpp" #include "MeshOptimizer.hpp" +#include +#include + #if _WIN32 #include #include @@ -60,19 +65,23 @@ extern "C" uint8_t HECL_STARTUP[]; extern "C" size_t HECL_STARTUP_SZ; static void InstallBlendershell(const SystemChar* path) { - FILE* fp = hecl::Fopen(path, _SYS_STR("w")); - if (!fp) + auto fp = hecl::FopenUnique(path, _SYS_STR("w")); + + if (fp == nullptr) { BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("unable to open {} for writing")), path); - fwrite(HECL_BLENDERSHELL, 1, HECL_BLENDERSHELL_SZ, fp); - fclose(fp); + } + + std::fwrite(HECL_BLENDERSHELL, 1, HECL_BLENDERSHELL_SZ, fp.get()); } static void InstallAddon(const SystemChar* path) { - FILE* fp = hecl::Fopen(path, _SYS_STR("wb")); - if (!fp) + auto fp = hecl::FopenUnique(path, _SYS_STR("wb")); + + if (fp == nullptr) { BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("Unable to install blender addon at '{}'")), path); - fwrite(HECL_ADDON, 1, HECL_ADDON_SZ, fp); - fclose(fp); + } + + std::fwrite(HECL_ADDON, 1, HECL_ADDON_SZ, fp.get()); } static int Read(int fd, void* buf, size_t size) { @@ -107,7 +116,7 @@ static int Write(int fd, const void* buf, size_t size) { uint32_t Connection::_readStr(char* buf, uint32_t bufSz) { uint32_t readLen; - int ret = Read(m_readpipe[0], &readLen, 4); + int ret = Read(m_readpipe[0], &readLen, sizeof(readLen)); if (ret < 4) { BlenderLog.report(logvisor::Error, fmt("Pipe error {} {}"), ret, strerror(errno)); _blenderDied(); @@ -124,8 +133,11 @@ uint32_t Connection::_readStr(char* buf, uint32_t bufSz) { if (ret < 0) { BlenderLog.report(logvisor::Fatal, fmt("{}"), strerror(errno)); return 0; - } else if (readLen >= 9) { - if (!memcmp(buf, "EXCEPTION", std::min(readLen, uint32_t(9)))) { + } + + constexpr std::string_view exception_str{"EXCEPTION"}; + if (readLen >= exception_str.size()) { + if (exception_str.compare(0, exception_str.size(), buf) == 0) { _blenderDied(); return 0; } @@ -136,54 +148,75 @@ uint32_t Connection::_readStr(char* buf, uint32_t bufSz) { } uint32_t Connection::_writeStr(const char* buf, uint32_t len, int wpipe) { - int ret, nlerr; - nlerr = Write(wpipe, &len, 4); - if (nlerr < 4) - goto err; - ret = Write(wpipe, buf, len); - if (ret < 0) - goto err; - return (uint32_t)ret; -err: - _blenderDied(); - return 0; + const auto error = [this] { + _blenderDied(); + return 0U; + }; + + const int nlerr = Write(wpipe, &len, 4); + if (nlerr < 4) { + return error(); + } + + const int ret = Write(wpipe, buf, len); + if (ret < 0) { + return error(); + } + + return static_cast(ret); } size_t Connection::_readBuf(void* buf, size_t len) { - uint8_t* cBuf = reinterpret_cast(buf); + const auto error = [this] { + _blenderDied(); + return 0U; + }; + + auto* cBuf = static_cast(buf); size_t readLen = 0; + do { - int ret = Read(m_readpipe[0], cBuf, len); - if (ret < 0) - goto err; - if (len >= 9) - if (!memcmp((char*)cBuf, "EXCEPTION", std::min(len, size_t(9)))) + const int ret = Read(m_readpipe[0], cBuf, len); + if (ret < 0) { + return error(); + } + + constexpr std::string_view exception_str{"EXCEPTION"}; + if (len >= exception_str.size()) { + if (exception_str.compare(0, exception_str.size(), static_cast(buf)) == 0) { _blenderDied(); + } + } + readLen += ret; cBuf += ret; len -= ret; - } while (len); + } while (len != 0); + return readLen; -err: - _blenderDied(); - return 0; } size_t Connection::_writeBuf(const void* buf, size_t len) { - const uint8_t* cBuf = reinterpret_cast(buf); + const auto error = [this] { + _blenderDied(); + return 0U; + }; + + const auto* cBuf = static_cast(buf); size_t writeLen = 0; + do { - int ret = Write(m_writepipe[1], cBuf, len); - if (ret < 0) - goto err; + const int ret = Write(m_writepipe[1], cBuf, len); + if (ret < 0) { + return error(); + } + writeLen += ret; cBuf += ret; len -= ret; - } while (len); + } while (len != 0); + return writeLen; -err: - _blenderDied(); - return 0; } void Connection::_closePipe() { @@ -200,18 +233,20 @@ void Connection::_closePipe() { void Connection::_blenderDied() { std::this_thread::sleep_for(std::chrono::milliseconds(100)); - FILE* errFp = hecl::Fopen(m_errPath.c_str(), _SYS_STR("r")); - if (errFp) { - fseek(errFp, 0, SEEK_END); - int64_t len = hecl::FTell(errFp); - if (len) { - fseek(errFp, 0, SEEK_SET); - std::unique_ptr buf(new char[len + 1]); - memset(buf.get(), 0, len + 1); - fread(buf.get(), 1, len, errFp); + auto errFp = hecl::FopenUnique(m_errPath.c_str(), _SYS_STR("r")); + + if (errFp != nullptr) { + std::fseek(errFp.get(), 0, SEEK_END); + const int64_t len = hecl::FTell(errFp.get()); + + if (len != 0) { + std::fseek(errFp.get(), 0, SEEK_SET); + const auto buf = std::make_unique(len + 1); + std::fread(buf.get(), 1, len, errFp.get()); BlenderLog.report(logvisor::Fatal, fmt("\n{:.{}s}"), buf.get(), len); } } + BlenderLog.report(logvisor::Fatal, fmt("Blender Exception")); } @@ -253,14 +288,14 @@ Connection::Connection(int verbosityLevel) { while (true) { /* Construct communication pipes */ #if _WIN32 - _pipe(m_readpipe, 2048, _O_BINARY); - _pipe(m_writepipe, 2048, _O_BINARY); + _pipe(m_readpipe.data(), 2048, _O_BINARY); + _pipe(m_writepipe.data(), 2048, _O_BINARY); HANDLE writehandle = HANDLE(_get_osfhandle(m_writepipe[0])); SetHandleInformation(writehandle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); HANDLE readhandle = HANDLE(_get_osfhandle(m_readpipe[1])); SetHandleInformation(readhandle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); - SECURITY_ATTRIBUTES sattrs = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; + SECURITY_ATTRIBUTES sattrs = {sizeof(SECURITY_ATTRIBUTES), nullptr, TRUE}; HANDLE consoleOutReadTmp, consoleOutWrite, consoleErrWrite, consoleOutRead; if (!CreatePipe(&consoleOutReadTmp, &consoleOutWrite, &sattrs, 1024)) BlenderLog.report(logvisor::Fatal, fmt("Error with CreatePipe")); @@ -278,8 +313,8 @@ Connection::Connection(int verbosityLevel) { if (!CloseHandle(consoleOutReadTmp)) BlenderLog.report(logvisor::Fatal, fmt("Error with CloseHandle")); #else - pipe(m_readpipe); - pipe(m_writepipe); + pipe(m_readpipe.data()); + pipe(m_writepipe.data()); #endif /* User-specified blender path */ @@ -315,12 +350,12 @@ Connection::Connection(int verbosityLevel) { } } - std::wstring cmdLine = fmt::format(fmt(L" --background -P \"{}\" -- {} {} {} \"{}\""), - blenderShellPath, uintptr_t(writehandle), uintptr_t(readhandle), verbosityLevel, blenderAddonPath); + std::wstring cmdLine = fmt::format(fmt(L" --background -P \"{}\" -- {} {} {} \"{}\""), blenderShellPath, + uintptr_t(writehandle), uintptr_t(readhandle), verbosityLevel, blenderAddonPath); STARTUPINFO sinfo = {sizeof(STARTUPINFO)}; HANDLE nulHandle = CreateFileW(L"nul", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sattrs, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); + FILE_ATTRIBUTE_NORMAL, nullptr); sinfo.dwFlags = STARTF_USESTDHANDLES; sinfo.hStdInput = nulHandle; if (verbosityLevel == 0) { @@ -331,11 +366,12 @@ Connection::Connection(int verbosityLevel) { sinfo.hStdOutput = consoleOutWrite; } - if (!CreateProcessW(blenderBin, const_cast(cmdLine.c_str()), NULL, NULL, TRUE, - NORMAL_PRIORITY_CLASS, NULL, NULL, &sinfo, &m_pinfo)) { + if (!CreateProcessW(blenderBin, cmdLine.data(), nullptr, nullptr, TRUE, NORMAL_PRIORITY_CLASS, nullptr, nullptr, + &sinfo, &m_pinfo)) { LPWSTR messageBuffer = nullptr; - FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, - GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, NULL); + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, + nullptr); BlenderLog.report(logvisor::Fatal, fmt(L"unable to launch blender from {}: {}"), blenderBin, messageBuffer); } @@ -353,7 +389,7 @@ Connection::Connection(int verbosityLevel) { DWORD nCharsWritten; while (m_consoleThreadRunning) { - if (!ReadFile(consoleOutRead, lpBuffer, sizeof(lpBuffer), &nBytesRead, NULL) || !nBytesRead) { + if (!ReadFile(consoleOutRead, lpBuffer, sizeof(lpBuffer), &nBytesRead, nullptr) || !nBytesRead) { DWORD err = GetLastError(); if (err == ERROR_BROKEN_PIPE) break; // pipe done - normal exit path. @@ -363,7 +399,7 @@ Connection::Connection(int verbosityLevel) { // Display the character read on the screen. auto lk = logvisor::LockLog(); - if (!WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), lpBuffer, nBytesRead, &nCharsWritten, NULL)) { + if (!WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), lpBuffer, nBytesRead, &nCharsWritten, nullptr)) { // BlenderLog.report(logvisor::Error, fmt("Error with WriteConsole: %08X"), GetLastError()); } } @@ -396,8 +432,8 @@ Connection::Connection(int verbosityLevel) { /* Try user-specified blender first */ if (blenderBin) { - execlp(blenderBin, blenderBin, "--background", "-P", blenderShellPath.c_str(), "--", - readfds.c_str(), writefds.c_str(), vLevel.c_str(), blenderAddonPath.c_str(), NULL); + execlp(blenderBin, blenderBin, "--background", "-P", blenderShellPath.c_str(), "--", readfds.c_str(), + writefds.c_str(), vLevel.c_str(), blenderAddonPath.c_str(), nullptr); if (errno != ENOENT) { errbuf = fmt::format(fmt("NOLAUNCH {}"), strerror(errno)); _writeStr(errbuf.c_str(), errbuf.size(), m_readpipe[1]); @@ -414,8 +450,8 @@ Connection::Connection(int verbosityLevel) { steamBlender += "/blender"; #endif blenderBin = steamBlender.c_str(); - execlp(blenderBin, blenderBin, "--background", "-P", blenderShellPath.c_str(), "--", - readfds.c_str(), writefds.c_str(), vLevel.c_str(), blenderAddonPath.c_str(), NULL); + execlp(blenderBin, blenderBin, "--background", "-P", blenderShellPath.c_str(), "--", readfds.c_str(), + writefds.c_str(), vLevel.c_str(), blenderAddonPath.c_str(), nullptr); if (errno != ENOENT) { errbuf = fmt::format(fmt("NOLAUNCH {}"), strerror(errno)); _writeStr(errbuf.c_str(), errbuf.size(), m_readpipe[1]); @@ -425,7 +461,7 @@ Connection::Connection(int verbosityLevel) { /* Otherwise default blender */ execlp(DEFAULT_BLENDER_BIN, DEFAULT_BLENDER_BIN, "--background", "-P", blenderShellPath.c_str(), "--", - readfds.c_str(), writefds.c_str(), vLevel.c_str(), blenderAddonPath.c_str(), NULL); + readfds.c_str(), writefds.c_str(), vLevel.c_str(), blenderAddonPath.c_str(), nullptr); if (errno != ENOENT) { errbuf = fmt::format(fmt("NOLAUNCH {}"), strerror(errno)); _writeStr(errbuf.c_str(), errbuf.size(), m_readpipe[1]); @@ -446,8 +482,8 @@ Connection::Connection(int verbosityLevel) { m_errPath = hecl::SystemString(TMPDIR) + fmt::format(fmt(_SYS_STR("/hecl_{:016X}.derp")), (unsigned long long)m_pinfo.dwProcessId); #else - m_errPath = - hecl::SystemString(TMPDIR) + fmt::format(fmt(_SYS_STR("/hecl_{:016X}.derp")), (unsigned long long)m_blenderProc); + m_errPath = hecl::SystemString(TMPDIR) + + fmt::format(fmt(_SYS_STR("/hecl_{:016X}.derp")), (unsigned long long)m_blenderProc); #endif hecl::Unlink(m_errPath.c_str()); @@ -528,8 +564,9 @@ std::streambuf::int_type PyOutStream::StreamBuf::overflow(int_type ch) { return ch; } -static const char* BlendTypeStrs[] = {"NONE", "MESH", "CMESH", "ACTOR", "AREA", "WORLD", - "MAPAREA", "MAPUNIVERSE", "FRAME", "PATH", nullptr}; +constexpr std::array BlendTypeStrs{ + "NONE", "MESH", "CMESH", "ACTOR", "AREA", "WORLD", "MAPAREA", "MAPUNIVERSE", "FRAME", "PATH", nullptr, +}; bool Connection::createBlend(const ProjectPath& path, BlendType type) { if (m_lock) { @@ -628,87 +665,83 @@ void PyOutStream::close() { } void PyOutStream::linkBlend(const char* target, const char* objName, bool link) { - format(fmt( - "if '{}' not in bpy.data.scenes:\n" - " with bpy.data.libraries.load('''{}''', link={}, relative=True) as (data_from, data_to):\n" - " data_to.scenes = data_from.scenes\n" - " obj_scene = None\n" - " for scene in data_to.scenes:\n" - " if scene.name == '{}':\n" - " obj_scene = scene\n" - " break\n" - " if not obj_scene:\n" - " raise RuntimeError('''unable to find {} in {}. try deleting it and restart the extract.''')\n" - " obj = None\n" - " for object in obj_scene.objects:\n" - " if object.name == obj_scene.name:\n" - " obj = object\n" - "else:\n" - " obj = bpy.data.objects['{}']\n" - "\n"), - objName, target, link ? "True" : "False", objName, objName, target, objName); + format(fmt("if '{}' not in bpy.data.scenes:\n" + " with bpy.data.libraries.load('''{}''', link={}, relative=True) as (data_from, data_to):\n" + " data_to.scenes = data_from.scenes\n" + " obj_scene = None\n" + " for scene in data_to.scenes:\n" + " if scene.name == '{}':\n" + " obj_scene = scene\n" + " break\n" + " if not obj_scene:\n" + " raise RuntimeError('''unable to find {} in {}. try deleting it and restart the extract.''')\n" + " obj = None\n" + " for object in obj_scene.objects:\n" + " if object.name == obj_scene.name:\n" + " obj = object\n" + "else:\n" + " obj = bpy.data.objects['{}']\n" + "\n"), + objName, target, link ? "True" : "False", objName, objName, target, objName); } void PyOutStream::linkBackground(const char* target, const char* sceneName) { if (!sceneName) { - format(fmt( - "with bpy.data.libraries.load('''{}''', link=True, relative=True) as (data_from, data_to):\n" - " data_to.scenes = data_from.scenes\n" - "obj_scene = None\n" - "for scene in data_to.scenes:\n" - " obj_scene = scene\n" - " break\n" - "if not obj_scene:\n" - " raise RuntimeError('''unable to find {}. try deleting it and restart the extract.''')\n" - "\n" - "bpy.context.scene.background_set = obj_scene\n"), - target, target); + format(fmt("with bpy.data.libraries.load('''{}''', link=True, relative=True) as (data_from, data_to):\n" + " data_to.scenes = data_from.scenes\n" + "obj_scene = None\n" + "for scene in data_to.scenes:\n" + " obj_scene = scene\n" + " break\n" + "if not obj_scene:\n" + " raise RuntimeError('''unable to find {}. try deleting it and restart the extract.''')\n" + "\n" + "bpy.context.scene.background_set = obj_scene\n"), + target, target); } else { - format(fmt( - "if '{}' not in bpy.data.scenes:\n" - " with bpy.data.libraries.load('''{}''', link=True, relative=True) as (data_from, data_to):\n" - " data_to.scenes = data_from.scenes\n" - " obj_scene = None\n" - " for scene in data_to.scenes:\n" - " if scene.name == '{}':\n" - " obj_scene = scene\n" - " break\n" - " if not obj_scene:\n" - " raise RuntimeError('''unable to find {} in {}. try deleting it and restart the extract.''')\n" - "\n" - "bpy.context.scene.background_set = bpy.data.scenes['{}']\n"), - sceneName, target, sceneName, sceneName, target, sceneName); + format(fmt("if '{}' not in bpy.data.scenes:\n" + " with bpy.data.libraries.load('''{}''', link=True, relative=True) as (data_from, data_to):\n" + " data_to.scenes = data_from.scenes\n" + " obj_scene = None\n" + " for scene in data_to.scenes:\n" + " if scene.name == '{}':\n" + " obj_scene = scene\n" + " break\n" + " if not obj_scene:\n" + " raise RuntimeError('''unable to find {} in {}. try deleting it and restart the extract.''')\n" + "\n" + "bpy.context.scene.background_set = bpy.data.scenes['{}']\n"), + sceneName, target, sceneName, sceneName, target, sceneName); } } void PyOutStream::AABBToBMesh(const atVec3f& min, const atVec3f& max) { athena::simd_floats minf(min.simd); athena::simd_floats maxf(max.simd); - format(fmt( - "bm = bmesh.new()\n" - "bm.verts.new(({},{},{}))\n" - "bm.verts.new(({},{},{}))\n" - "bm.verts.new(({},{},{}))\n" - "bm.verts.new(({},{},{}))\n" - "bm.verts.new(({},{},{}))\n" - "bm.verts.new(({},{},{}))\n" - "bm.verts.new(({},{},{}))\n" - "bm.verts.new(({},{},{}))\n" - "bm.verts.ensure_lookup_table()\n" - "bm.edges.new((bm.verts[0], bm.verts[1]))\n" - "bm.edges.new((bm.verts[0], bm.verts[2]))\n" - "bm.edges.new((bm.verts[0], bm.verts[4]))\n" - "bm.edges.new((bm.verts[3], bm.verts[1]))\n" - "bm.edges.new((bm.verts[3], bm.verts[2]))\n" - "bm.edges.new((bm.verts[3], bm.verts[7]))\n" - "bm.edges.new((bm.verts[5], bm.verts[1]))\n" - "bm.edges.new((bm.verts[5], bm.verts[4]))\n" - "bm.edges.new((bm.verts[5], bm.verts[7]))\n" - "bm.edges.new((bm.verts[6], bm.verts[2]))\n" - "bm.edges.new((bm.verts[6], bm.verts[4]))\n" - "bm.edges.new((bm.verts[6], bm.verts[7]))\n"), - minf[0], minf[1], minf[2], maxf[0], minf[1], minf[2], minf[0], maxf[1], minf[2], maxf[0], maxf[1], minf[2], - minf[0], minf[1], maxf[2], maxf[0], minf[1], maxf[2], minf[0], maxf[1], maxf[2], maxf[0], maxf[1], maxf[2]); + format(fmt("bm = bmesh.new()\n" + "bm.verts.new(({},{},{}))\n" + "bm.verts.new(({},{},{}))\n" + "bm.verts.new(({},{},{}))\n" + "bm.verts.new(({},{},{}))\n" + "bm.verts.new(({},{},{}))\n" + "bm.verts.new(({},{},{}))\n" + "bm.verts.new(({},{},{}))\n" + "bm.verts.new(({},{},{}))\n" + "bm.verts.ensure_lookup_table()\n" + "bm.edges.new((bm.verts[0], bm.verts[1]))\n" + "bm.edges.new((bm.verts[0], bm.verts[2]))\n" + "bm.edges.new((bm.verts[0], bm.verts[4]))\n" + "bm.edges.new((bm.verts[3], bm.verts[1]))\n" + "bm.edges.new((bm.verts[3], bm.verts[2]))\n" + "bm.edges.new((bm.verts[3], bm.verts[7]))\n" + "bm.edges.new((bm.verts[5], bm.verts[1]))\n" + "bm.edges.new((bm.verts[5], bm.verts[4]))\n" + "bm.edges.new((bm.verts[5], bm.verts[7]))\n" + "bm.edges.new((bm.verts[6], bm.verts[2]))\n" + "bm.edges.new((bm.verts[6], bm.verts[4]))\n" + "bm.edges.new((bm.verts[6], bm.verts[7]))\n"), + minf[0], minf[1], minf[2], maxf[0], minf[1], minf[2], minf[0], maxf[1], minf[2], maxf[0], maxf[1], minf[2], + minf[0], minf[1], maxf[2], maxf[0], minf[1], maxf[2], minf[0], maxf[1], maxf[2], maxf[0], maxf[1], maxf[2]); } void PyOutStream::centerView() { @@ -805,8 +838,7 @@ Mesh::Mesh(Connection& conn, HMDLTopology topologyIn, int skinSlotCount, bool us Index matSetCount(conn); materialSets.reserve(matSetCount.val); for (uint32_t i = 0; i < matSetCount.val; ++i) { - materialSets.emplace_back(); - std::vector& materials = materialSets.back(); + std::vector& materials = materialSets.emplace_back(); Index matCount(conn); materials.reserve(matCount.val); for (uint32_t j = 0; j < matCount.val; ++j) @@ -914,7 +946,7 @@ Material::PASS::PASS(Connection& conn) { SystemStringConv absolute(readStr); SystemString relative = - conn.getBlendPath().getProject().getProjectRootPath().getProjectRelativeFromAbsolute(absolute.sys_str()); + conn.getBlendPath().getProject().getProjectRootPath().getProjectRelativeFromAbsolute(absolute.sys_str()); tex.assign(conn.getBlendPath().getProject().getProjectWorkingPath(), relative); conn._readBuf(&source, 1); @@ -969,26 +1001,12 @@ Material::Material(Connection& conn) { } bool Mesh::Surface::Vert::operator==(const Vert& other) const { - if (iPos != other.iPos) - return false; - if (iNorm != other.iNorm) - return false; - for (int i = 0; i < 4; ++i) - if (iColor[i] != other.iColor[i]) - return false; - for (int i = 0; i < 8; ++i) - if (iUv[i] != other.iUv[i]) - return false; - if (iSkin != other.iSkin) - return false; - return true; + return std::tie(iPos, iNorm, iColor, iUv, iSkin) == + std::tie(other.iPos, other.iNorm, other.iColor, other.iUv, other.iSkin); } static bool VertInBank(const std::vector& bank, uint32_t sIdx) { - for (uint32_t idx : bank) - if (sIdx == idx) - return true; - return false; + return std::any_of(bank.cbegin(), bank.cend(), [sIdx](auto index) { return index == sIdx; }); } void Mesh::SkinBanks::Bank::addSkins(const Mesh& parent, const std::vector& skinIdxs) { @@ -1153,8 +1171,7 @@ MapArea::Surface::Surface(Connection& conn) { conn._readBuf(&borderCount, 4); borders.reserve(borderCount); for (uint32_t i = 0; i < borderCount; ++i) { - borders.emplace_back(); - std::pair& idx = borders.back(); + std::pair& idx = borders.emplace_back(); conn._readBuf(&idx, 8); } } @@ -1344,14 +1361,13 @@ Actor::Subtype::Subtype(Connection& conn) { name.assign(bufSz, ' '); conn._readBuf(&name[0], bufSz); - std::string meshPath; conn._readBuf(&bufSz, 4); - if (bufSz) { - meshPath.assign(bufSz, ' '); - conn._readBuf(&meshPath[0], bufSz); - SystemStringConv meshPathAbs(meshPath); + if (bufSz != 0) { + std::string meshPath(bufSz, ' '); + conn._readBuf(meshPath.data(), meshPath.size()); + const SystemStringConv meshPathAbs(meshPath); - SystemString meshPathRel = + const SystemString meshPathRel = conn.getBlendPath().getProject().getProjectRootPath().getProjectRelativeFromAbsolute(meshPathAbs.sys_str()); mesh.assign(conn.getBlendPath().getProject().getProjectWorkingPath(), meshPathRel); } @@ -1367,14 +1383,13 @@ Actor::Subtype::Subtype(Connection& conn) { overlayName.assign(bufSz, ' '); conn._readBuf(&overlayName[0], bufSz); - std::string meshPath; conn._readBuf(&bufSz, 4); - if (bufSz) { - meshPath.assign(bufSz, ' '); - conn._readBuf(&meshPath[0], bufSz); - SystemStringConv meshPathAbs(meshPath); + if (bufSz != 0) { + std::string meshPath(bufSz, ' '); + conn._readBuf(meshPath.data(), meshPath.size()); + const SystemStringConv meshPathAbs(meshPath); - SystemString meshPathRel = + const SystemString meshPathRel = conn.getBlendPath().getProject().getProjectRootPath().getProjectRelativeFromAbsolute(meshPathAbs.sys_str()); overlayMeshes.emplace_back(std::move(overlayName), ProjectPath(conn.getBlendPath().getProject().getProjectWorkingPath(), meshPathRel)); @@ -1431,12 +1446,11 @@ Action::Action(Connection& conn) { conn._readBuf(&aabbCount, 4); subtypeAABBs.reserve(aabbCount); for (uint32_t i = 0; i < aabbCount; ++i) { - subtypeAABBs.emplace_back(); - subtypeAABBs.back().first.read(conn); - subtypeAABBs.back().second.read(conn); - //printf("AABB %s %d (%f %f %f) (%f %f %f)\n", name.c_str(), i, - // float(subtypeAABBs.back().first.val.simd[0]), float(subtypeAABBs.back().first.val.simd[1]), float(subtypeAABBs.back().first.val.simd[2]), - // float(subtypeAABBs.back().second.val.simd[0]), float(subtypeAABBs.back().second.val.simd[1]), float(subtypeAABBs.back().second.val.simd[2])); + subtypeAABBs.emplace_back(conn, conn); + // printf("AABB %s %d (%f %f %f) (%f %f %f)\n", name.c_str(), i, + // float(subtypeAABBs.back().first.val.simd[0]), float(subtypeAABBs.back().first.val.simd[1]), + // float(subtypeAABBs.back().first.val.simd[2]), float(subtypeAABBs.back().second.val.simd[0]), + // float(subtypeAABBs.back().second.val.simd[1]), float(subtypeAABBs.back().second.val.simd[2])); } } @@ -1532,7 +1546,7 @@ std::pair DataStream::getMeshAABB() { } const char* DataStream::MeshOutputModeString(HMDLTopology topology) { - static const char* STRS[] = {"TRIANGLES", "TRISTRIPS"}; + static constexpr std::array STRS{"TRIANGLES", "TRISTRIPS"}; return STRS[int(topology)]; } @@ -1787,12 +1801,11 @@ std::vector DataStream::getArmatureNames() { m_parent->_readBuf(&armCount, 4); ret.reserve(armCount); for (uint32_t i = 0; i < armCount; ++i) { - ret.emplace_back(); - std::string& name = ret.back(); + std::string& name = ret.emplace_back(); uint32_t bufSz; m_parent->_readBuf(&bufSz, 4); name.assign(bufSz, ' '); - m_parent->_readBuf(&name[0], bufSz); + m_parent->_readBuf(name.data(), name.size()); } return ret; @@ -1816,12 +1829,11 @@ std::vector DataStream::getSubtypeNames() { m_parent->_readBuf(&subCount, 4); ret.reserve(subCount); for (uint32_t i = 0; i < subCount; ++i) { - ret.emplace_back(); - std::string& name = ret.back(); + std::string& name = ret.emplace_back(); uint32_t bufSz; m_parent->_readBuf(&bufSz, 4); name.assign(bufSz, ' '); - m_parent->_readBuf(&name[0], bufSz); + m_parent->_readBuf(name.data(), name.size()); } return ret; @@ -1845,12 +1857,11 @@ std::vector DataStream::getActionNames() { m_parent->_readBuf(&actCount, 4); ret.reserve(actCount); for (uint32_t i = 0; i < actCount; ++i) { - ret.emplace_back(); - std::string& name = ret.back(); + std::string& name = ret.emplace_back(); uint32_t bufSz; m_parent->_readBuf(&bufSz, 4); name.assign(bufSz, ' '); - m_parent->_readBuf(&name[0], bufSz); + m_parent->_readBuf(name.data(), name.size()); } return ret; @@ -1874,12 +1885,11 @@ std::vector DataStream::getSubtypeOverlayNames(std::string_view nam m_parent->_readBuf(&subCount, 4); ret.reserve(subCount); for (uint32_t i = 0; i < subCount; ++i) { - ret.emplace_back(); - std::string& name = ret.back(); + std::string& subtypeName = ret.emplace_back(); uint32_t bufSz; m_parent->_readBuf(&bufSz, 4); - name.assign(bufSz, ' '); - m_parent->_readBuf(&name[0], bufSz); + subtypeName.assign(bufSz, ' '); + m_parent->_readBuf(subtypeName.data(), subtypeName.size()); } return ret; @@ -1903,12 +1913,11 @@ std::vector DataStream::getAttachmentNames() { m_parent->_readBuf(&attCount, 4); ret.reserve(attCount); for (uint32_t i = 0; i < attCount; ++i) { - ret.emplace_back(); - std::string& name = ret.back(); + std::string& name = ret.emplace_back(); uint32_t bufSz; m_parent->_readBuf(&bufSz, 4); name.assign(bufSz, ' '); - m_parent->_readBuf(&name[0], bufSz); + m_parent->_readBuf(name.data(), name.size()); } return ret; @@ -1935,23 +1944,22 @@ std::unordered_map DataStream::getBoneMatrices(std::strin m_parent->_readBuf(&boneCount, 4); ret.reserve(boneCount); for (uint32_t i = 0; i < boneCount; ++i) { - std::string name; uint32_t bufSz; m_parent->_readBuf(&bufSz, 4); - name.assign(bufSz, ' '); - m_parent->_readBuf(&name[0], bufSz); + std::string mat_name(bufSz, ' '); + m_parent->_readBuf(mat_name.data(), bufSz); Matrix3f matOut; - for (int i = 0; i < 3; ++i) { - for (int j = 0; j < 3; ++j) { + for (int mat_i = 0; mat_i < 3; ++mat_i) { + for (int mat_j = 0; mat_j < 3; ++mat_j) { float val; m_parent->_readBuf(&val, 4); - matOut[i].simd[j] = val; + matOut[mat_i].simd[mat_j] = val; } - reinterpret_cast(matOut[i]).simd[3] = 0.f; + reinterpret_cast(matOut[mat_i]).simd[3] = 0.f; } - ret.emplace(std::make_pair(std::move(name), std::move(matOut))); + ret.emplace(std::move(mat_name), std::move(matOut)); } return ret; diff --git a/hecl/lib/Blender/HMDL.cpp b/hecl/lib/Blender/HMDL.cpp index 9d17cad9f..430cc3b7b 100644 --- a/hecl/lib/Blender/HMDL.cpp +++ b/hecl/lib/Blender/HMDL.cpp @@ -1,6 +1,9 @@ #include "hecl/Blender/Connection.hpp" -#include + #include +#include + +#include #undef min #undef max diff --git a/hecl/lib/Blender/MeshOptimizer.cpp b/hecl/lib/Blender/MeshOptimizer.cpp index 2ddca9ad8..f14068735 100644 --- a/hecl/lib/Blender/MeshOptimizer.cpp +++ b/hecl/lib/Blender/MeshOptimizer.cpp @@ -1,5 +1,6 @@ #include "MeshOptimizer.hpp" #include +#include #include namespace hecl::blender { diff --git a/hecl/lib/CVar.cpp b/hecl/lib/CVar.cpp index ae1d25d6e..9d2bfc81c 100644 --- a/hecl/lib/CVar.cpp +++ b/hecl/lib/CVar.cpp @@ -191,23 +191,25 @@ int CVar::toInteger(bool* isValid) const { return strtol(m_value.c_str(), nullptr, 0); } -const std::string CVar::toLiteral(bool* isValid) const { +std::string CVar::toLiteral(bool* isValid) const { if (m_type != EType::Literal && (com_developer && com_developer->toBoolean())) { if (isValid != nullptr) *isValid = false; - } else if (isValid != nullptr) + } else if (isValid != nullptr) { *isValid = true; + } // Even if it's not a literal, it's still safe to return return m_value; } -const std::wstring CVar::toWideLiteral(bool* isValid) const { +std::wstring CVar::toWideLiteral(bool* isValid) const { if (m_type != EType::Literal && (com_developer && com_developer->toBoolean())) { if (isValid != nullptr) *isValid = false; - } else if (isValid != nullptr) + } else if (isValid != nullptr) { *isValid = true; + } // Even if it's not a literal, it's still safe to return return hecl::UTF8ToWide(m_value); diff --git a/hecl/lib/CVarManager.cpp b/hecl/lib/CVarManager.cpp index a7d6005eb..94fc0379f 100644 --- a/hecl/lib/CVarManager.cpp +++ b/hecl/lib/CVarManager.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -24,12 +25,11 @@ CVarManager::CVarManager(hecl::Runtime::FileStoreManager& store, bool useBinary) com_configfile = newCVar("config", "File to store configuration", std::string("config"), CVar::EFlags::System); com_developer = newCVar("developer", "Enables developer mode", false, (CVar::EFlags::System | CVar::EFlags::ReadOnly | CVar::EFlags::InternalArchivable)); - com_enableCheats = - newCVar("cheats", "Enable cheats", false, - (CVar::EFlags::System | CVar::EFlags::ReadOnly | CVar::EFlags::Hidden | CVar::EFlags::InternalArchivable)); - com_cubemaps = - newCVar("cubemaps", "Enable cubemaps", false, - (CVar::EFlags::Game | CVar::EFlags::ReadOnly | CVar::EFlags::InternalArchivable)); + com_enableCheats = newCVar( + "cheats", "Enable cheats", false, + (CVar::EFlags::System | CVar::EFlags::ReadOnly | CVar::EFlags::Hidden | CVar::EFlags::InternalArchivable)); + com_cubemaps = newCVar("cubemaps", "Enable cubemaps", false, + (CVar::EFlags::Game | CVar::EFlags::ReadOnly | CVar::EFlags::InternalArchivable)); } CVarManager::~CVarManager() {} @@ -37,11 +37,13 @@ CVarManager::~CVarManager() {} CVar* CVarManager::registerCVar(std::unique_ptr&& cvar) { std::string tmp(cvar->name()); athena::utility::tolower(tmp); - if (m_cvars.find(tmp) != m_cvars.end()) + + if (m_cvars.find(tmp) != m_cvars.end()) { return nullptr; + } CVar* ret = cvar.get(); - m_cvars[tmp] = std::move(cvar); + m_cvars.insert_or_assign(std::move(tmp), std::move(cvar)); return ret; } @@ -80,8 +82,8 @@ void CVarManager::deserialize(CVar* cvar) { /* First let's check for a deferred value */ std::string lowName = cvar->name().data(); athena::utility::tolower(lowName); - if (m_deferedCVars.find(lowName) != m_deferedCVars.end()) { - std::string val = m_deferedCVars[lowName]; + if (const auto iter = m_deferedCVars.find(lowName); iter != m_deferedCVars.end()) { + std::string val = std::move(iter->second); m_deferedCVars.erase(lowName); if (cvar->fromLiteralToType(val)) return; @@ -162,10 +164,13 @@ void CVarManager::serialize() { if (m_useBinary) { CVarContainer container; - for (const auto& pair : m_cvars) - if (pair.second->isArchive() || - (pair.second->isInternalArchivable() && pair.second->wasDeserialized() && !pair.second->hasDefaultValue())) - container.cvars.push_back(*pair.second); + for (const auto& pair : m_cvars) { + const auto& cvar = pair.second; + + if (cvar->isArchive() || (cvar->isInternalArchivable() && cvar->wasDeserialized() && !cvar->hasDefaultValue())) { + container.cvars.push_back(*cvar); + } + } container.cvarCount = atUint32(container.cvars.size()); filename += _SYS_STR(".bin"); @@ -180,10 +185,13 @@ void CVarManager::serialize() { r.close(); docWriter.setStyle(athena::io::YAMLNodeStyle::Block); - for (const auto& pair : m_cvars) - if (pair.second->isArchive() || - (pair.second->isInternalArchivable() && pair.second->wasDeserialized() && !pair.second->hasDefaultValue())) - docWriter.writeString(pair.second->name().data(), pair.second->toLiteral()); + for (const auto& pair : m_cvars) { + const auto& cvar = pair.second; + + if (cvar->isArchive() || (cvar->isInternalArchivable() && cvar->wasDeserialized() && !cvar->hasDefaultValue())) { + docWriter.writeString(cvar->name().data(), cvar->toLiteral()); + } + } athena::io::FileWriter w(filename); if (w.isOpen()) @@ -208,12 +216,13 @@ void CVarManager::setCVar(Console* con, const std::vector& args) { std::string cvName = args[0]; athena::utility::tolower(cvName); - if (m_cvars.find(cvName) == m_cvars.end()) { + const auto iter = m_cvars.find(cvName); + if (iter == m_cvars.end()) { con->report(Console::Level::Error, fmt("CVar '{}' does not exist"), args[0]); return; } - const auto& cv = m_cvars[cvName]; + const auto& cv = iter->second; std::string oldVal = cv->value(); std::string value = args[1]; auto it = args.begin() + 2; @@ -238,12 +247,13 @@ void CVarManager::getCVar(Console* con, const std::vector& args) { std::string cvName = args[0]; athena::utility::tolower(cvName); - if (m_cvars.find(cvName) == m_cvars.end()) { + const auto iter = m_cvars.find(cvName); + if (iter == m_cvars.end()) { con->report(Console::Level::Error, fmt("CVar '{}' does not exist"), args[0]); return; } - const auto& cv = m_cvars[cvName]; + const auto& cv = iter->second; con->report(Console::Level::Info, fmt("'{}' = '{}'"), cv->name(), cv->value()); } @@ -266,38 +276,38 @@ void CVarManager::setCheatsEnabled(bool v, bool setDeserialized) { } bool CVarManager::restartRequired() const { - for (const auto& cv : m_cvars) { - if (cv.second->isModified() && cv.second->modificationRequiresRestart()) - return true; - } - - return false; + return std::any_of(m_cvars.cbegin(), m_cvars.cend(), [](const auto& entry) { + return entry.second->isModified() && entry.second->modificationRequiresRestart(); + }); } void CVarManager::parseCommandLine(const std::vector& args) { bool oldDeveloper = suppressDeveloper(); - std::string developerName = com_developer->name().data(); + std::string developerName(com_developer->name()); athena::utility::tolower(developerName); for (const SystemString& arg : args) { - if (arg[0] == _SYS_STR('+')) { - std::string tmp = SystemUTF8Conv(arg).c_str(); + if (arg[0] != _SYS_STR('+')) { + continue; + } - std::smatch matches; - if (std::regex_match(tmp, matches, cmdLineRegex)) { - std::string cvarName = matches[1].str(); - std::string cvarValue = matches[2].str(); - if (CVar* cv = findCVar(cvarName)) { - cv->fromLiteralToType(cvarValue); - athena::utility::tolower(cvarName); - if (developerName == cvarName) - /* Make sure we're not overriding developer mode when we restore */ - oldDeveloper = com_developer->toBoolean(); - } else { - /* Unable to find an existing CVar, let's defer for the time being 8 */ - athena::utility::tolower(cvarName); - m_deferedCVars[cvarName] = cvarValue; - } - } + const std::string tmp(SystemUTF8Conv(arg).str()); + std::smatch matches; + if (!std::regex_match(tmp, matches, cmdLineRegex)) { + continue; + } + + std::string cvarName = matches[1].str(); + std::string cvarValue = matches[2].str(); + if (CVar* cv = findCVar(cvarName)) { + cv->fromLiteralToType(cvarValue); + athena::utility::tolower(cvarName); + if (developerName == cvarName) + /* Make sure we're not overriding developer mode when we restore */ + oldDeveloper = com_developer->toBoolean(); + } else { + /* Unable to find an existing CVar, let's defer for the time being 8 */ + athena::utility::tolower(cvarName); + m_deferedCVars.insert_or_assign(std::move(cvarName), std::move(cvarValue)); } } diff --git a/hecl/lib/ClientProcess.cpp b/hecl/lib/ClientProcess.cpp index bdf539375..ccda39f3b 100644 --- a/hecl/lib/ClientProcess.cpp +++ b/hecl/lib/ClientProcess.cpp @@ -71,7 +71,7 @@ void ClientProcess::BufferTransaction::run(blender::Token& btok) { void ClientProcess::CookTransaction::run(blender::Token& btok) { m_dataSpec->setThreadProject(); m_returnResult = m_parent.syncCook(m_path, m_dataSpec, btok, m_force, m_fast); - std::unique_lock lk(m_parent.m_mutex); + std::unique_lock lk{m_parent.m_mutex}; ++m_parent.m_completedCooks; m_parent.m_progPrinter->setMainFactor(m_parent.m_completedCooks / float(m_parent.m_addedCooks)); m_complete = true; @@ -92,7 +92,7 @@ void ClientProcess::Worker::proc() { std::string thrName = fmt::format(fmt("HECL Worker {}"), m_idx); logvisor::RegisterThreadName(thrName.c_str()); - std::unique_lock lk(m_proc.m_mutex); + std::unique_lock lk{m_proc.m_mutex}; while (m_proc.m_running) { if (!m_didInit) { m_proc.m_initCv.notify_one(); @@ -125,7 +125,7 @@ ClientProcess::ClientProcess(const MultiProgressPrinter* progPrinter) : m_progPr #endif m_workers.reserve(cpuCount); for (int i = 0; i < cpuCount; ++i) { - std::unique_lock lk(m_mutex); + std::unique_lock lk{m_mutex}; m_workers.emplace_back(*this, m_workers.size()); m_initCv.wait(lk); } @@ -134,7 +134,7 @@ ClientProcess::ClientProcess(const MultiProgressPrinter* progPrinter) : m_progPr std::shared_ptr ClientProcess::addBufferTransaction(const ProjectPath& path, void* target, size_t maxLen, size_t offset) { - std::unique_lock lk(m_mutex); + std::unique_lock lk{m_mutex}; auto ret = std::make_shared(*this, path, target, maxLen, offset); m_pendingQueue.emplace_back(ret); m_cv.notify_one(); @@ -144,7 +144,7 @@ std::shared_ptr ClientProcess::addBuffer std::shared_ptr ClientProcess::addCookTransaction(const hecl::ProjectPath& path, bool force, bool fast, Database::IDataSpec* spec) { - std::unique_lock lk(m_mutex); + std::unique_lock lk{m_mutex}; auto ret = std::make_shared(*this, path, force, fast, spec); m_pendingQueue.emplace_back(ret); m_cv.notify_one(); @@ -155,7 +155,7 @@ std::shared_ptr ClientProcess::addCookTran std::shared_ptr ClientProcess::addLambdaTransaction(std::function&& func) { - std::unique_lock lk(m_mutex); + std::unique_lock lk{m_mutex}; auto ret = std::make_shared(*this, std::move(func)); m_pendingQueue.emplace_back(ret); m_cv.notify_one(); @@ -204,12 +204,12 @@ bool ClientProcess::syncCook(const hecl::ProjectPath& path, Database::IDataSpec* } void ClientProcess::swapCompletedQueue(std::list>& queue) { - std::unique_lock lk(m_mutex); + std::unique_lock lk{m_mutex}; queue.swap(m_completedQueue); } void ClientProcess::waitUntilComplete() { - std::unique_lock lk(m_mutex); + std::unique_lock lk{m_mutex}; while (isBusy()) m_waitCv.wait(lk); } @@ -217,7 +217,7 @@ void ClientProcess::waitUntilComplete() { void ClientProcess::shutdown() { if (!m_running) return; - std::unique_lock lk(m_mutex); + std::unique_lock lk{m_mutex}; m_pendingQueue.clear(); m_running = false; m_cv.notify_all(); diff --git a/hecl/lib/Compilers.cpp b/hecl/lib/Compilers.cpp index a3ef74f31..549537bc1 100644 --- a/hecl/lib/Compilers.cpp +++ b/hecl/lib/Compilers.cpp @@ -1,14 +1,17 @@ #include "hecl/Compilers.hpp" -#include "boo/graphicsdev/GLSLMacros.hpp" -#include "logvisor/logvisor.hpp" +#include +#include + #include #include #include #include + #if _WIN32 #include extern pD3DCompile D3DCompilePROC; #endif + #if __APPLE__ #include #include @@ -17,23 +20,6 @@ extern pD3DCompile D3DCompilePROC; namespace hecl { logvisor::Module Log("hecl::Compilers"); -namespace PlatformType { -const char* OpenGL::Name = "OpenGL"; -const char* Vulkan::Name = "Vulkan"; -const char* D3D11::Name = "D3D11"; -const char* Metal::Name = "Metal"; -const char* NX::Name = "NX"; -} // namespace PlatformType - -namespace PipelineStage { -const char* Null::Name = "Null"; -const char* Vertex::Name = "Vertex"; -const char* Fragment::Name = "Fragment"; -const char* Geometry::Name = "Geometry"; -const char* Control::Name = "Control"; -const char* Evaluation::Name = "Evaluation"; -} // namespace PipelineStage - template struct ShaderCompiler {}; @@ -99,7 +85,7 @@ struct ShaderCompiler { ComPtr blobOut; if (FAILED(D3DCompilePROC(text.data(), text.size(), "Boo HLSL Source", nullptr, nullptr, "main", D3DShaderTypes[int(S::Enum)], BOO_D3DCOMPILE_FLAG, 0, &blobOut, &errBlob))) { - printf("%s\n", text.data()); + fmt::print(fmt("{}\n"), text); Log.report(logvisor::Fatal, fmt("error compiling shader: {}"), (char*)errBlob->GetBufferPointer()); return {}; } @@ -124,7 +110,7 @@ struct ShaderCompiler { pid_t pid = fork(); if (!pid) { - execlp("xcrun", "xcrun", "-sdk", "macosx", "metal", "--version", NULL); + execlp("xcrun", "xcrun", "-sdk", "macosx", "metal", "--version", nullptr); /* xcrun returns 72 if metal command not found; * emulate that if xcrun not found */ exit(72); @@ -180,8 +166,8 @@ struct ShaderCompiler { #ifndef NDEBUG "-gline-tables-only", "-MO", #endif - "-", NULL); - fprintf(stderr, "execlp fail %s\n", strerror(errno)); + "-", nullptr); + fmt::print(stderr, fmt("execlp fail {}\n"), strerror(errno)); exit(1); } close(compilerIn[0]); @@ -196,8 +182,8 @@ struct ShaderCompiler { close(compilerIn[1]); /* metallib doesn't like outputting to a pipe, so temp file will have to do */ - execlp("xcrun", "xcrun", "-sdk", "macosx", "metallib", "-", "-o", libFile.c_str(), NULL); - fprintf(stderr, "execlp fail %s\n", strerror(errno)); + execlp("xcrun", "xcrun", "-sdk", "macosx", "metallib", "-", "-o", libFile.c_str(), nullptr); + fmt::print(stderr, fmt("execlp fail {}\n"), strerror(errno)); exit(1); } close(compilerOut[0]); @@ -208,7 +194,7 @@ struct ShaderCompiler { while (inRem) { ssize_t writeRes = write(compilerIn[1], inPtr, inRem); if (writeRes < 0) { - fprintf(stderr, "write fail %s\n", strerror(errno)); + fmt::print(stderr, fmt("write fail {}\n"), strerror(errno)); break; } inPtr += writeRes; @@ -221,7 +207,7 @@ struct ShaderCompiler { while (waitpid(compilerPid, &compilerStat, 0) < 0) { if (errno == EINTR) continue; - Log.report(logvisor::Fatal, fmt("waitpid fail %s"), strerror(errno)); + Log.report(logvisor::Fatal, fmt("waitpid fail {}"), strerror(errno)); return {}; } @@ -233,7 +219,7 @@ struct ShaderCompiler { while (waitpid(linkerPid, &linkerStat, 0) < 0) { if (errno == EINTR) continue; - Log.report(logvisor::Fatal, fmt("waitpid fail %s"), strerror(errno)); + Log.report(logvisor::Fatal, fmt("waitpid fail {}"), strerror(errno)); return {}; } diff --git a/hecl/lib/Console.cpp b/hecl/lib/Console.cpp index 82d704cfa..75947efc2 100644 --- a/hecl/lib/Console.cpp +++ b/hecl/lib/Console.cpp @@ -368,8 +368,8 @@ void Console::LogVisorAdapter::report(const char* modName, logvisor::Level sever auto tmp = fmt::internal::vformat(format, args); std::vector lines = athena::utility::split(tmp, '\n'); for (const std::string& line : lines) { - auto v = fmt::format(fmt("[%s] %s"), modName, line.c_str()); - m_con->m_log.emplace_back(v, Console::Level(severity)); + auto v = fmt::format(fmt("[{}] {}"), modName, line); + m_con->m_log.emplace_back(std::move(v), Console::Level(severity)); } } @@ -378,16 +378,16 @@ void Console::LogVisorAdapter::report(const char* modName, logvisor::Level sever auto tmp = fmt::internal::vformat(format, args); std::vector lines = athena::utility::split(athena::utility::wideToUtf8(tmp), '\n'); for (const std::string& line : lines) { - auto v = fmt::format(fmt("[%s] %s"), modName, line.c_str()); - m_con->m_log.emplace_back(v, Console::Level(severity)); + auto v = fmt::format(fmt("[{}] {}"), modName, line); + m_con->m_log.emplace_back(std::move(v), Console::Level(severity)); } } void Console::LogVisorAdapter::reportSource(const char* modName, logvisor::Level severity, const char* file, unsigned linenum, fmt::string_view format, fmt::format_args args) { auto tmp = fmt::internal::vformat(format, args); - auto v = fmt::format(fmt("[%s] %s %s:%i"), modName, tmp, file, linenum); - m_con->m_log.emplace_back(v, Console::Level(severity)); + auto v = fmt::format(fmt("[{}] {} {}:{}"), modName, tmp, file, linenum); + m_con->m_log.emplace_back(std::move(v), Console::Level(severity)); } void Console::LogVisorAdapter::reportSource(const char* modName, logvisor::Level severity, const char* file, @@ -395,8 +395,8 @@ void Console::LogVisorAdapter::reportSource(const char* modName, logvisor::Level auto tmp = fmt::internal::vformat(format, args); std::vector lines = athena::utility::split(athena::utility::wideToUtf8(tmp), '\n'); for (const std::string& line : lines) { - auto v = fmt::format(fmt("[%s] %s %s:%i"), modName, line.c_str(), file, linenum); - m_con->m_log.emplace_back(v, Console::Level(severity)); + auto v = fmt::format(fmt("[{}] {} {}:{}"), modName, line, file, linenum); + m_con->m_log.emplace_back(std::move(v), Console::Level(severity)); } } diff --git a/hecl/lib/MultiProgressPrinter.cpp b/hecl/lib/MultiProgressPrinter.cpp index 94208dd1e..90a149e1b 100644 --- a/hecl/lib/MultiProgressPrinter.cpp +++ b/hecl/lib/MultiProgressPrinter.cpp @@ -242,9 +242,12 @@ void MultiProgressPrinter::DoPrint() { void MultiProgressPrinter::LogProc() { while (m_running) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); - if (!m_dirty && !m_mainIndeterminate) + + if (!m_dirty && !m_mainIndeterminate) { continue; - std::lock_guard lk(m_logLock); + } + + std::lock_guard lk{m_logLock}; DoPrint(); } } @@ -280,22 +283,30 @@ MultiProgressPrinter::~MultiProgressPrinter() { void MultiProgressPrinter::print(const hecl::SystemChar* message, const hecl::SystemChar* submessage, float factor, int threadIdx) const { - if (!m_running) + if (!m_running) { return; - std::lock_guard lk(m_logLock); - if (threadIdx < 0) + } + + std::lock_guard lk{m_logLock}; + if (threadIdx < 0) { threadIdx = 0; - if (threadIdx >= m_threadStats.size()) + } + if (threadIdx >= m_threadStats.size()) { m_threadStats.resize(threadIdx + 1); + } + ThreadStat& stat = m_threadStats[threadIdx]; - if (message) + if (message) { stat.m_message = message; - else + } else { stat.m_message.clear(); - if (submessage) + } + if (submessage) { stat.m_submessage = submessage; - else + } else { stat.m_submessage.clear(); + } + stat.m_factor = factor; stat.m_active = true; m_latestThread = threadIdx; @@ -303,18 +314,23 @@ void MultiProgressPrinter::print(const hecl::SystemChar* message, const hecl::Sy } void MultiProgressPrinter::setMainFactor(float factor) const { - if (!m_running) + if (!m_running) { return; - std::lock_guard lk(m_logLock); - if (!m_mainIndeterminate) + } + + std::lock_guard lk{m_logLock}; + if (!m_mainIndeterminate) { m_dirty = true; + } m_mainFactor = factor; } void MultiProgressPrinter::setMainIndeterminate(bool indeterminate) const { - if (!m_running) + if (!m_running) { return; - std::lock_guard lk(m_logLock); + } + + std::lock_guard lk{m_logLock}; if (m_mainIndeterminate != indeterminate) { m_mainIndeterminate = indeterminate; m_dirty = true; @@ -322,9 +338,11 @@ void MultiProgressPrinter::setMainIndeterminate(bool indeterminate) const { } void MultiProgressPrinter::startNewLine() const { - if (!m_running) + if (!m_running) { return; - std::lock_guard lk(m_logLock); + } + + std::lock_guard lk{m_logLock}; const_cast(*this).DoPrint(); m_threadStats.clear(); m_latestThread = -1; @@ -335,7 +353,7 @@ void MultiProgressPrinter::startNewLine() const { } void MultiProgressPrinter::flush() const { - std::lock_guard lk(m_logLock); + std::lock_guard lk{m_logLock}; const_cast(*this).DoPrint(); } diff --git a/hecl/lib/Pipeline.cpp b/hecl/lib/Pipeline.cpp index 68918cde6..7f2aed739 100644 --- a/hecl/lib/Pipeline.cpp +++ b/hecl/lib/Pipeline.cpp @@ -24,9 +24,9 @@ public: m_zstrm.avail_in = 0; inflateInit(&m_zstrm); } - ~ShaderCacheZipStream() { inflateEnd(&m_zstrm); } - operator bool() const { return m_compBuf.operator bool(); } - atUint64 readUBytesToBuf(void* buf, atUint64 len) { + ~ShaderCacheZipStream() override { inflateEnd(&m_zstrm); } + explicit operator bool() const { return m_compBuf.operator bool(); } + atUint64 readUBytesToBuf(void* buf, atUint64 len) override { m_zstrm.next_out = (Bytef*)buf; m_zstrm.avail_out = len; m_zstrm.total_out = 0; @@ -42,9 +42,9 @@ public: } return m_zstrm.total_out; } - void seek(atInt64, athena::SeekOrigin) {} - atUint64 position() const { return 0; } - atUint64 length() const { return 0; } + void seek(atInt64, athena::SeekOrigin) override {} + atUint64 position() const override { return 0; } + atUint64 length() const override { return 0; } }; template diff --git a/hecl/lib/Project.cpp b/hecl/lib/Project.cpp index 9243c805e..57b167399 100644 --- a/hecl/lib/Project.cpp +++ b/hecl/lib/Project.cpp @@ -17,7 +17,7 @@ namespace hecl::Database { logvisor::Module LogModule("hecl::Database"); -static const hecl::FourCC HECLfcc("HECL"); +constexpr hecl::FourCC HECLfcc("HECL"); /********************************************** * Project::ConfigFile @@ -43,17 +43,19 @@ Project::ConfigFile::ConfigFile(const Project& project, SystemStringView name, S } std::vector& Project::ConfigFile::lockAndRead() { - if (m_lockedFile) + if (m_lockedFile != nullptr) { return m_lines; + } - m_lockedFile = hecl::Fopen(m_filepath.c_str(), _SYS_STR("a+"), FileLockType::Write); - hecl::FSeek(m_lockedFile, 0, SEEK_SET); + m_lockedFile = hecl::FopenUnique(m_filepath.c_str(), _SYS_STR("a+"), FileLockType::Write); + hecl::FSeek(m_lockedFile.get(), 0, SEEK_SET); std::string mainString; char readBuf[1024]; size_t readSz; - while ((readSz = fread(readBuf, 1, 1024, m_lockedFile))) + while ((readSz = std::fread(readBuf, 1, sizeof(readBuf), m_lockedFile.get()))) { mainString += std::string(readBuf, readSz); + } std::string::const_iterator begin = mainString.begin(); std::string::const_iterator end = mainString.begin(); @@ -110,14 +112,13 @@ bool Project::ConfigFile::checkForLine(std::string_view refLine) { } void Project::ConfigFile::unlockAndDiscard() { - if (!m_lockedFile) { + if (m_lockedFile == nullptr) { LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__, fmt("Project::ConfigFile::lockAndRead not yet called")); return; } m_lines.clear(); - fclose(m_lockedFile); - m_lockedFile = NULL; + m_lockedFile.reset(); } bool Project::ConfigFile::unlockAndCommit() { @@ -126,23 +127,22 @@ bool Project::ConfigFile::unlockAndCommit() { return false; } - SystemString newPath = m_filepath + _SYS_STR(".part"); - FILE* newFile = hecl::Fopen(newPath.c_str(), _SYS_STR("w"), FileLockType::Write); + const SystemString newPath = m_filepath + _SYS_STR(".part"); + auto newFile = hecl::FopenUnique(newPath.c_str(), _SYS_STR("w"), FileLockType::Write); bool fail = false; for (const std::string& line : m_lines) { - if (fwrite(line.c_str(), 1, line.size(), newFile) != line.size()) { + if (std::fwrite(line.c_str(), 1, line.size(), newFile.get()) != line.size()) { fail = true; break; } - if (fwrite("\n", 1, 1, newFile) != 1) { + if (std::fputc('\n', newFile.get()) == EOF) { fail = true; break; } } m_lines.clear(); - fclose(newFile); - fclose(m_lockedFile); - m_lockedFile = NULL; + newFile.reset(); + m_lockedFile.reset(); if (fail) { #if HECL_UCS2 _wunlink(newPath.c_str()); @@ -191,20 +191,21 @@ Project::Project(const ProjectRootPath& rootPath) m_cookedRoot.makeDir(); /* Ensure beacon is valid or created */ - ProjectPath beaconPath(m_dotPath, _SYS_STR("beacon")); - FILE* bf = hecl::Fopen(beaconPath.getAbsolutePath().data(), _SYS_STR("a+b")); + const ProjectPath beaconPath(m_dotPath, _SYS_STR("beacon")); + auto bf = hecl::FopenUnique(beaconPath.getAbsolutePath().data(), _SYS_STR("a+b")); struct BeaconStruct { hecl::FourCC magic; uint32_t version; } beacon; -#define DATA_VERSION 1 - if (fread(&beacon, 1, sizeof(beacon), bf) != sizeof(beacon)) { - fseek(bf, 0, SEEK_SET); + constexpr uint32_t DATA_VERSION = 1; + if (std::fread(&beacon, 1, sizeof(beacon), bf.get()) != sizeof(beacon)) { + std::fseek(bf.get(), 0, SEEK_SET); beacon.magic = HECLfcc; beacon.version = SBig(DATA_VERSION); - fwrite(&beacon, 1, sizeof(beacon), bf); + std::fwrite(&beacon, 1, sizeof(beacon), bf.get()); } - fclose(bf); + bf.reset(); + if (beacon.magic != HECLfcc || SBig(beacon.version) != DATA_VERSION) { LogModule.report(logvisor::Fatal, fmt("incompatible project version")); return; @@ -413,9 +414,11 @@ bool Project::cookPath(const ProjectPath& path, const hecl::MultiProgressPrinter } } else if (m_cookSpecs.empty()) { m_cookSpecs.reserve(m_compiledSpecs.size()); - for (const ProjectDataSpec& spec : m_compiledSpecs) - if (spec.active && spec.spec.m_factory) - m_cookSpecs.push_back(spec.spec.m_factory(*this, DataSpecTool::Cook)); + for (const ProjectDataSpec& projectSpec : m_compiledSpecs) { + if (projectSpec.active && projectSpec.spec.m_factory) { + m_cookSpecs.push_back(projectSpec.spec.m_factory(*this, DataSpecTool::Cook)); + } + } } /* Iterate complete directory/file/glob list */ @@ -443,17 +446,18 @@ bool Project::packagePath(const ProjectPath& path, const hecl::MultiProgressPrin /* Construct DataSpec instance for packaging */ const DataSpecEntry* specEntry = nullptr; if (spec) { - if (spec->m_factory) + if (spec->m_factory) { specEntry = spec; + } } else { bool foundPC = false; - for (const ProjectDataSpec& spec : m_compiledSpecs) { - if (spec.active && spec.spec.m_factory) { - if (hecl::StringUtils::EndsWith(spec.spec.m_name, _SYS_STR("-PC"))) { + for (const ProjectDataSpec& projectSpec : m_compiledSpecs) { + if (projectSpec.active && projectSpec.spec.m_factory) { + if (hecl::StringUtils::EndsWith(projectSpec.spec.m_name, _SYS_STR("-PC"))) { foundPC = true; - specEntry = &spec.spec; + specEntry = &projectSpec.spec; } else if (!foundPC) { - specEntry = &spec.spec; + specEntry = &projectSpec.spec; } } } diff --git a/hecl/lib/ProjectPath.cpp b/hecl/lib/ProjectPath.cpp index 802946ed6..0eca7f826 100644 --- a/hecl/lib/ProjectPath.cpp +++ b/hecl/lib/ProjectPath.cpp @@ -256,17 +256,22 @@ ProjectRootPath SearchForProject(SystemStringView path) { Sstat theStat; if (!hecl::Stat(testIndexPath.c_str(), &theStat)) { if (S_ISREG(theStat.st_mode)) { - FILE* fp = hecl::Fopen(testIndexPath.c_str(), _SYS_STR("rb")); - if (!fp) + const auto fp = hecl::FopenUnique(testIndexPath.c_str(), _SYS_STR("rb")); + if (fp == nullptr) { continue; + } + char magic[4]; - size_t readSize = fread(magic, 1, 4, fp); - fclose(fp); - if (readSize != 4) + const size_t readSize = std::fread(magic, 1, sizeof(magic), fp.get()); + if (readSize != sizeof(magic)) { continue; - static const hecl::FourCC hecl("HECL"); - if (hecl::FourCC(magic) != hecl) + } + + static constexpr hecl::FourCC hecl("HECL"); + if (hecl::FourCC(magic) != hecl) { continue; + } + return ProjectRootPath(testPath); } } @@ -280,40 +285,51 @@ ProjectRootPath SearchForProject(SystemStringView path) { } ProjectRootPath SearchForProject(SystemStringView path, SystemString& subpathOut) { - ProjectRootPath testRoot(path); + const ProjectRootPath testRoot(path); auto begin = testRoot.getAbsolutePath().begin(); auto end = testRoot.getAbsolutePath().end(); + while (begin != end) { SystemString testPath(begin, end); SystemString testIndexPath = testPath + _SYS_STR("/.hecl/beacon"); Sstat theStat; + if (!hecl::Stat(testIndexPath.c_str(), &theStat)) { if (S_ISREG(theStat.st_mode)) { - FILE* fp = hecl::Fopen(testIndexPath.c_str(), _SYS_STR("rb")); - if (!fp) + const auto fp = hecl::FopenUnique(testIndexPath.c_str(), _SYS_STR("rb")); + if (fp == nullptr) { continue; + } + char magic[4]; - size_t readSize = fread(magic, 1, 4, fp); - fclose(fp); - if (readSize != 4) + const size_t readSize = std::fread(magic, 1, sizeof(magic), fp.get()); + if (readSize != sizeof(magic)) { continue; - if (hecl::FourCC(magic) != FOURCC('HECL')) + } + if (hecl::FourCC(magic) != FOURCC('HECL')) { continue; - ProjectRootPath newRootPath = ProjectRootPath(testPath); - auto origEnd = testRoot.getAbsolutePath().end(); - while (end != origEnd && *end != _SYS_STR('/') && *end != _SYS_STR('\\')) + } + + const ProjectRootPath newRootPath = ProjectRootPath(testPath); + const auto origEnd = testRoot.getAbsolutePath().end(); + while (end != origEnd && *end != _SYS_STR('/') && *end != _SYS_STR('\\')) { ++end; - if (end != origEnd && (*end == _SYS_STR('/') || *end == _SYS_STR('\\'))) + } + if (end != origEnd && (*end == _SYS_STR('/') || *end == _SYS_STR('\\'))) { ++end; + } + subpathOut.assign(end, origEnd); return newRootPath; } } - while (begin != end && *(end - 1) != _SYS_STR('/') && *(end - 1) != _SYS_STR('\\')) + while (begin != end && *(end - 1) != _SYS_STR('/') && *(end - 1) != _SYS_STR('\\')) { --end; - if (begin != end) + } + if (begin != end) { --end; + } } return ProjectRootPath(); } diff --git a/hecl/lib/SteamFinder.cpp b/hecl/lib/SteamFinder.cpp index e9dccea47..a930e5d5f 100644 --- a/hecl/lib/SteamFinder.cpp +++ b/hecl/lib/SteamFinder.cpp @@ -57,44 +57,45 @@ hecl::SystemString FindCommonSteamApp(const hecl::SystemChar* name) { #endif - hecl::SystemString appPath = hecl::SystemString(_SYS_STR("common")) + PATH_SEP + name; + const hecl::SystemString appPath = hecl::SystemString(_SYS_STR("common")) + PATH_SEP + name; /* Try main steam install directory first */ - hecl::SystemString steamAppsMain = steamInstallDir + PATH_SEP + _SYS_STR("steamapps"); - hecl::SystemString mainAppPath = steamAppsMain + PATH_SEP + appPath; - if (!hecl::Stat(mainAppPath.c_str(), &theStat) && S_ISDIR(theStat.st_mode)) + const hecl::SystemString steamAppsMain = steamInstallDir + PATH_SEP + _SYS_STR("steamapps"); + const hecl::SystemString mainAppPath = steamAppsMain + PATH_SEP + appPath; + if (!hecl::Stat(mainAppPath.c_str(), &theStat) && S_ISDIR(theStat.st_mode)) { return mainAppPath; + } /* Iterate alternate steam install dirs */ - hecl::SystemString libraryFoldersVdfPath = steamAppsMain + PATH_SEP + _SYS_STR("libraryfolders.vdf"); - FILE* fp = hecl::Fopen(libraryFoldersVdfPath.c_str(), _SYS_STR("r")); - if (!fp) + const hecl::SystemString libraryFoldersVdfPath = steamAppsMain + PATH_SEP + _SYS_STR("libraryfolders.vdf"); + auto fp = hecl::FopenUnique(libraryFoldersVdfPath.c_str(), _SYS_STR("r")); + if (fp == nullptr) { return {}; - hecl::FSeek(fp, 0, SEEK_END); - int64_t fileLen = hecl::FTell(fp); + } + hecl::FSeek(fp.get(), 0, SEEK_END); + const int64_t fileLen = hecl::FTell(fp.get()); if (fileLen <= 0) { - fclose(fp); return {}; } - hecl::FSeek(fp, 0, SEEK_SET); - std::string fileBuf; - fileBuf.resize(fileLen); - if (fread(&fileBuf[0], 1, fileLen, fp) != fileLen) { - fclose(fp); + hecl::FSeek(fp.get(), 0, SEEK_SET); + std::string fileBuf(fileLen, '\0'); + if (std::fread(fileBuf.data(), 1, fileLen, fp.get()) != fileLen) { return {}; } - fclose(fp); std::smatch dirMatch; auto begin = fileBuf.cbegin(); - auto end = fileBuf.cend(); + const auto end = fileBuf.cend(); while (std::regex_search(begin, end, dirMatch, regSteamPath)) { - std::string match = dirMatch[1].str(); - hecl::SystemStringConv otherInstallDir(match); - hecl::SystemString otherAppPath = + const std::string match = dirMatch[1].str(); + const hecl::SystemStringConv otherInstallDir(match); + const auto otherAppPath = hecl::SystemString(otherInstallDir.sys_str()) + PATH_SEP + _SYS_STR("steamapps") + PATH_SEP + appPath; - if (!hecl::Stat(otherAppPath.c_str(), &theStat) && S_ISDIR(theStat.st_mode)) + + if (!hecl::Stat(otherAppPath.c_str(), &theStat) && S_ISDIR(theStat.st_mode)) { return otherAppPath; + } + begin = dirMatch.suffix().first; } diff --git a/hecl/lib/hecl.cpp b/hecl/lib/hecl.cpp index 5122f53a0..27e491986 100644 --- a/hecl/lib/hecl.cpp +++ b/hecl/lib/hecl.cpp @@ -1,6 +1,14 @@ #include "hecl/hecl.hpp" -#include + +#include +#include +#include +#include +#include #include +#include +#include +#include #include #ifdef WIN32 @@ -20,11 +28,13 @@ #include #endif +#include + namespace hecl { unsigned VerbosityLevel = 0; bool GuiMode = false; logvisor::Module LogModule("hecl"); -static const std::string Illegals{"<>?\""}; +constexpr std::string_view Illegals{"<>?\""}; void SanitizePath(std::string& path) { if (path.empty()) @@ -54,7 +64,7 @@ void SanitizePath(std::string& path) { path.pop_back(); } -static const std::wstring WIllegals{L"<>?\""}; +constexpr std::wstring_view WIllegals{L"<>?\""}; void SanitizePath(std::wstring& path) { if (path.empty()) @@ -90,8 +100,9 @@ SystemString GetcwdStr() { // const int MaxChunks=10240; // 2550 KiBs of current path are more than enough SystemChar stackBuffer[255]; // Stack buffer for the "normal" case - if (Getcwd(stackBuffer, 255) != nullptr) + if (Getcwd(stackBuffer, int(std::size(stackBuffer))) != nullptr) { return SystemString(stackBuffer); + } if (errno != ERANGE) { // It's not ERANGE, so we don't know how to handle it LogModule.report(logvisor::Fatal, fmt("Cannot determine the current path.")); @@ -101,9 +112,11 @@ SystemString GetcwdStr() { for (int chunks = 2; chunks < 10240; chunks++) { // With boost use scoped_ptr; in C++0x, use unique_ptr // If you want to be less C++ but more efficient you may want to use realloc - std::unique_ptr cwd(new SystemChar[255 * chunks]); - if (Getcwd(cwd.get(), 255 * chunks) != nullptr) + const int bufSize = 255 * chunks; + std::unique_ptr cwd(new SystemChar[bufSize]); + if (Getcwd(cwd.get(), bufSize) != nullptr) { return SystemString(cwd.get()); + } if (errno != ERANGE) { // It's not ERANGE, so we don't know how to handle it LogModule.report(logvisor::Fatal, fmt("Cannot determine the current path.")); @@ -118,64 +131,65 @@ static std::mutex PathsMutex; static std::unordered_map PathsInProgress; bool ResourceLock::InProgress(const ProjectPath& path) { - std::unique_lock lk(PathsMutex); - for (const auto& p : PathsInProgress) - if (p.second == path) - return true; - return false; + std::unique_lock lk{PathsMutex}; + return std::any_of(PathsInProgress.cbegin(), PathsInProgress.cend(), + [&path](const auto& entry) { return entry.second == path; }); } bool ResourceLock::SetThreadRes(const ProjectPath& path) { - std::unique_lock lk(PathsMutex); - if (PathsInProgress.find(std::this_thread::get_id()) != PathsInProgress.cend()) + std::unique_lock lk{PathsMutex}; + if (PathsInProgress.find(std::this_thread::get_id()) != PathsInProgress.cend()) { LogModule.report(logvisor::Fatal, fmt("multiple resource locks on thread")); + } - for (const auto& p : PathsInProgress) - if (p.second == path) - return false; + const bool isInProgress = std::any_of(PathsInProgress.cbegin(), PathsInProgress.cend(), + [&path](const auto& entry) { return entry.second == path; }); + if (isInProgress) { + return false; + } - PathsInProgress[std::this_thread::get_id()] = path; + PathsInProgress.insert_or_assign(std::this_thread::get_id(), path); return true; } void ResourceLock::ClearThreadRes() { - std::unique_lock lk(PathsMutex); + std::unique_lock lk{PathsMutex}; PathsInProgress.erase(std::this_thread::get_id()); } bool IsPathPNG(const hecl::ProjectPath& path) { - FILE* fp = hecl::Fopen(path.getAbsolutePath().data(), _SYS_STR("rb")); - if (!fp) - return false; - uint32_t buf = 0; - if (fread(&buf, 1, 4, fp) != 4) { - fclose(fp); + const auto fp = hecl::FopenUnique(path.getAbsolutePath().data(), _SYS_STR("rb")); + if (fp == nullptr) { return false; } - fclose(fp); + + uint32_t buf = 0; + if (std::fread(&buf, 1, sizeof(buf), fp.get()) != sizeof(buf)) { + return false; + } + buf = hecl::SBig(buf); - if (buf == 0x89504e47) - return true; - return false; + return buf == 0x89504e47; } bool IsPathBlend(const hecl::ProjectPath& path) { - auto lastCompExt = path.getLastComponentExt(); - if (lastCompExt.empty() || hecl::StrCmp(lastCompExt.data(), _SYS_STR("blend"))) - return false; - FILE* fp = hecl::Fopen(path.getAbsolutePath().data(), _SYS_STR("rb")); - if (!fp) - return false; - uint32_t buf = 0; - if (fread(&buf, 1, 4, fp) != 4) { - fclose(fp); + const auto lastCompExt = path.getLastComponentExt(); + if (lastCompExt.empty() || hecl::StrCmp(lastCompExt.data(), _SYS_STR("blend"))) { return false; } - fclose(fp); + + const auto fp = hecl::FopenUnique(path.getAbsolutePath().data(), _SYS_STR("rb")); + if (fp == nullptr) { + return false; + } + + uint32_t buf = 0; + if (std::fread(&buf, 1, sizeof(buf), fp.get()) != sizeof(buf)) { + return false; + } + buf = hecl::SLittle(buf); - if (buf == 0x4e454c42 || buf == 0x88b1f) - return true; - return false; + return buf == 0x4e454c42 || buf == 0x88b1f; } bool IsPathYAML(const hecl::ProjectPath& path) { @@ -431,8 +445,6 @@ hecl::DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode, #endif } -#define FILE_MAXDIR 768 - static std::pair NameFromPath(hecl::SystemStringView path) { hecl::SystemUTF8Conv utf8(path); if (utf8.str().size() == 1 && utf8.str()[0] == '/') @@ -450,46 +462,44 @@ std::vector> GetSystemLocations() { #if !WINDOWS_STORE /* Add the drive names to the listing (as queried by blender) */ { + constexpr uint32_t FILE_MAXDIR = 768; wchar_t wline[FILE_MAXDIR]; - wchar_t* name; - __int64 tmp; - int i; + const uint32_t tmp = GetLogicalDrives(); - tmp = GetLogicalDrives(); - - for (i = 0; i < 26; i++) { + for (uint32_t i = 0; i < 26; i++) { if ((tmp >> i) & 1) { wline[0] = L'A' + i; wline[1] = L':'; wline[2] = L'/'; wline[3] = L'\0'; - name = nullptr; + wchar_t* name = nullptr; /* Flee from horrible win querying hover floppy drives! */ if (i > 1) { /* Try to get volume label as well... */ if (GetVolumeInformationW(wline, wline + 4, FILE_MAXDIR - 4, nullptr, nullptr, nullptr, nullptr, 0)) { - size_t labelLen = wcslen(wline + 4); + const size_t labelLen = std::wcslen(wline + 4); _snwprintf(wline + 4 + labelLen, FILE_MAXDIR - 4 - labelLen, L" (%.2s)", wline); name = wline + 4; } } wline[2] = L'\0'; - if (name) - ret.emplace_back(wline, hecl::WideToUTF8(name)); - else + if (name == nullptr) { ret.push_back(NameFromPath(wline)); + } else { + ret.emplace_back(wline, hecl::WideToUTF8(name)); + } } } /* Adding Desktop and My Documents */ SystemString wpath; - SHGetSpecialFolderPathW(0, wline, CSIDL_PERSONAL, 0); + SHGetSpecialFolderPathW(nullptr, wline, CSIDL_PERSONAL, 0); wpath.assign(wline); SanitizePath(wpath); ret.push_back(NameFromPath(wpath)); - SHGetSpecialFolderPathW(0, wline, CSIDL_DESKTOPDIRECTORY, 0); + SHGetSpecialFolderPathW(nullptr, wline, CSIDL_DESKTOPDIRECTORY, 0); wpath.assign(wline); SanitizePath(wpath); ret.push_back(NameFromPath(wpath)); @@ -513,18 +523,20 @@ std::vector> GetSystemLocations() { /*https://developer.apple.com/library/mac/#documentation/CoreFOundation/Reference/CFURLRef/Reference/reference.html*/ /* we get all volumes sorted including network and do not relay on user-defined finder visibility, less confusing */ - CFURLRef cfURL = NULL; + CFURLRef cfURL = nullptr; CFURLEnumeratorResult result = kCFURLEnumeratorSuccess; - CFURLEnumeratorRef volEnum = CFURLEnumeratorCreateForMountedVolumes(NULL, kCFURLEnumeratorSkipInvisibles, NULL); + CFURLEnumeratorRef volEnum = + CFURLEnumeratorCreateForMountedVolumes(nullptr, kCFURLEnumeratorSkipInvisibles, nullptr); while (result != kCFURLEnumeratorEnd) { char defPath[1024]; - result = CFURLEnumeratorGetNextURL(volEnum, &cfURL, NULL); - if (result != kCFURLEnumeratorSuccess) + result = CFURLEnumeratorGetNextURL(volEnum, &cfURL, nullptr); + if (result != kCFURLEnumeratorSuccess) { continue; + } - CFURLGetFileSystemRepresentation(cfURL, false, (UInt8*)defPath, 1024); + CFURLGetFileSystemRepresentation(cfURL, false, reinterpret_cast(defPath), std::size(defPath)); ret.push_back(NameFromPath(defPath)); } @@ -582,14 +594,11 @@ std::wstring Char16ToWide(std::u16string_view src) { return std::wstring(src.beg #if _WIN32 int RecursiveMakeDir(const SystemChar* dir) { SystemChar tmp[1024]; - SystemChar* p = nullptr; - Sstat sb; - size_t len; /* copy path */ - wcsncpy(tmp, dir, 1024); - len = wcslen(tmp); - if (len >= 1024) { + std::wcsncpy(tmp, dir, std::size(tmp)); + const size_t len = std::wcslen(tmp); + if (len >= std::size(tmp)) { return -1; } @@ -599,6 +608,8 @@ int RecursiveMakeDir(const SystemChar* dir) { } /* recursive mkdir */ + SystemChar* p = nullptr; + Sstat sb; for (p = tmp + 1; *p; p++) { if (*p == '/' || *p == '\\') { *p = 0; @@ -630,14 +641,11 @@ int RecursiveMakeDir(const SystemChar* dir) { #else int RecursiveMakeDir(const SystemChar* dir) { SystemChar tmp[1024]; - SystemChar* p = nullptr; - Sstat sb; - size_t len; /* copy path */ - strncpy(tmp, dir, 1024); - len = strlen(tmp); - if (len >= 1024) { + std::strncpy(tmp, dir, std::size(tmp)); + const size_t len = std::strlen(tmp); + if (len >= std::size(tmp)) { return -1; } @@ -647,6 +655,8 @@ int RecursiveMakeDir(const SystemChar* dir) { } /* recursive mkdir */ + SystemChar* p = nullptr; + Sstat sb; for (p = tmp + 1; *p; p++) { if (*p == '/') { *p = 0; @@ -680,16 +690,16 @@ int RecursiveMakeDir(const SystemChar* dir) { const SystemChar* GetTmpDir() { #ifdef _WIN32 #if WINDOWS_STORE - wchar_t* TMPDIR = nullptr; + const wchar_t* TMPDIR = nullptr; #else - wchar_t* TMPDIR = _wgetenv(L"TEMP"); + const wchar_t* TMPDIR = _wgetenv(L"TEMP"); if (!TMPDIR) - TMPDIR = (wchar_t*)L"\\Temp"; + TMPDIR = L"\\Temp"; #endif #else - char* TMPDIR = getenv("TMPDIR"); + const char* TMPDIR = getenv("TMPDIR"); if (!TMPDIR) - TMPDIR = (char*)"/tmp"; + TMPDIR = "/tmp"; #endif return TMPDIR; } @@ -697,13 +707,15 @@ const SystemChar* GetTmpDir() { #if !WINDOWS_STORE int RunProcess(const SystemChar* path, const SystemChar* const args[]) { #ifdef _WIN32 - SECURITY_ATTRIBUTES sattrs = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; - HANDLE consoleOutReadTmp, consoleOutWrite, consoleErrWrite, consoleOutRead; + SECURITY_ATTRIBUTES sattrs = {sizeof(SECURITY_ATTRIBUTES), nullptr, TRUE}; + HANDLE consoleOutReadTmp = INVALID_HANDLE_VALUE; + HANDLE consoleOutWrite = INVALID_HANDLE_VALUE; if (!CreatePipe(&consoleOutReadTmp, &consoleOutWrite, &sattrs, 0)) { LogModule.report(logvisor::Fatal, fmt("Error with CreatePipe")); return -1; } + HANDLE consoleErrWrite = INVALID_HANDLE_VALUE; if (!DuplicateHandle(GetCurrentProcess(), consoleOutWrite, GetCurrentProcess(), &consoleErrWrite, 0, TRUE, DUPLICATE_SAME_ACCESS)) { LogModule.report(logvisor::Fatal, fmt("Error with DuplicateHandle")); @@ -712,11 +724,12 @@ int RunProcess(const SystemChar* path, const SystemChar* const args[]) { return -1; } + HANDLE consoleOutRead = INVALID_HANDLE_VALUE; if (!DuplicateHandle(GetCurrentProcess(), consoleOutReadTmp, GetCurrentProcess(), &consoleOutRead, // Address of new handle. 0, FALSE, // Make it uninheritable. DUPLICATE_SAME_ACCESS)) { - LogModule.report(logvisor::Fatal, fmt("Error with DupliateHandle")); + LogModule.report(logvisor::Fatal, fmt("Error with DuplicateHandle")); CloseHandle(consoleOutReadTmp); CloseHandle(consoleOutWrite); CloseHandle(consoleErrWrite); @@ -735,18 +748,18 @@ int RunProcess(const SystemChar* path, const SystemChar* const args[]) { STARTUPINFO sinfo = {sizeof(STARTUPINFO)}; HANDLE nulHandle = CreateFileW(L"nul", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sattrs, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); + FILE_ATTRIBUTE_NORMAL, nullptr); sinfo.dwFlags = STARTF_USESTDHANDLES; sinfo.hStdInput = nulHandle; sinfo.hStdError = consoleErrWrite; sinfo.hStdOutput = consoleOutWrite; PROCESS_INFORMATION pinfo = {}; - if (!CreateProcessW(path, (LPWSTR)cmdLine.c_str(), NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &sinfo, + if (!CreateProcessW(path, cmdLine.data(), nullptr, nullptr, TRUE, NORMAL_PRIORITY_CLASS, nullptr, nullptr, &sinfo, &pinfo)) { LPWSTR messageBuffer = nullptr; - FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, - GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, NULL); + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, + GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, nullptr); LogModule.report(logvisor::Error, fmt(L"unable to launch process from {}: {}"), path, messageBuffer); LocalFree(messageBuffer); @@ -768,7 +781,7 @@ int RunProcess(const SystemChar* path, const SystemChar* const args[]) { DWORD nCharsWritten; while (consoleThreadRunning) { - if (!ReadFile(consoleOutRead, lpBuffer, sizeof(lpBuffer), &nBytesRead, NULL) || !nBytesRead) { + if (!ReadFile(consoleOutRead, lpBuffer, sizeof(lpBuffer), &nBytesRead, nullptr) || !nBytesRead) { DWORD err = GetLastError(); if (err == ERROR_BROKEN_PIPE) break; // pipe done - normal exit path. @@ -778,8 +791,8 @@ int RunProcess(const SystemChar* path, const SystemChar* const args[]) { // Display the character read on the screen. auto lk = logvisor::LockLog(); - if (!WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), lpBuffer, nBytesRead, &nCharsWritten, NULL)) { - // LogModule.report(logvisor::Error, fmt("Error with WriteConsole: %08X"), GetLastError()); + if (!WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), lpBuffer, nBytesRead, &nCharsWritten, nullptr)) { + // LogModule.report(logvisor::Error, fmt("Error with WriteConsole: {:08X}"), GetLastError()); } }