hecl: Make use of FopenUnique

Makes use of the introduced API function to eliminate the need to
explicit fclose FILE* instances.
This commit is contained in:
Lioncash 2019-08-21 19:33:25 -04:00
parent 9dcf7e7f08
commit fb9e4df372
7 changed files with 127 additions and 103 deletions

View File

@ -255,7 +255,7 @@ static std::unique_ptr<ToolBase> MakeSelectedTool(hecl::SystemString toolName, T
return std::make_unique<ToolHelp>(info); return std::make_unique<ToolHelp>(info);
} }
std::unique_ptr<FILE, decltype(&std::fclose)> fp{hecl::Fopen(toolName.c_str(), _SYS_STR("rb")), std::fclose}; auto fp = hecl::FopenUnique(toolName.c_str(), _SYS_STR("rb"));
if (fp == nullptr) { if (fp == nullptr) {
LogModule.report(logvisor::Error, fmt(_SYS_STR("unrecognized tool '{}'")), toolNameLower); LogModule.report(logvisor::Error, fmt(_SYS_STR("unrecognized tool '{}'")), toolNameLower);
return nullptr; return nullptr;

View File

@ -257,7 +257,7 @@ public:
class ConfigFile { class ConfigFile {
SystemString m_filepath; SystemString m_filepath;
std::vector<std::string> m_lines; std::vector<std::string> m_lines;
FILE* m_lockedFile = nullptr; UniqueFilePtr m_lockedFile;
public: public:
ConfigFile(const Project& project, SystemStringView name, SystemStringView subdir = _SYS_STR("/.hecl/")); ConfigFile(const Project& project, SystemStringView name, SystemStringView subdir = _SYS_STR("/.hecl/"));

View File

@ -60,19 +60,23 @@ extern "C" uint8_t HECL_STARTUP[];
extern "C" size_t HECL_STARTUP_SZ; extern "C" size_t HECL_STARTUP_SZ;
static void InstallBlendershell(const SystemChar* path) { static void InstallBlendershell(const SystemChar* path) {
FILE* fp = hecl::Fopen(path, _SYS_STR("w")); auto fp = hecl::FopenUnique(path, _SYS_STR("w"));
if (!fp)
if (fp == nullptr) {
BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("unable to open {} for writing")), path); 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) { static void InstallAddon(const SystemChar* path) {
FILE* fp = hecl::Fopen(path, _SYS_STR("wb")); auto fp = hecl::FopenUnique(path, _SYS_STR("wb"));
if (!fp)
if (fp == nullptr) {
BlenderLog.report(logvisor::Fatal, fmt(_SYS_STR("Unable to install blender addon at '{}'")), path); 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) { static int Read(int fd, void* buf, size_t size) {
@ -200,18 +204,20 @@ void Connection::_closePipe() {
void Connection::_blenderDied() { void Connection::_blenderDied() {
std::this_thread::sleep_for(std::chrono::milliseconds(100)); std::this_thread::sleep_for(std::chrono::milliseconds(100));
FILE* errFp = hecl::Fopen(m_errPath.c_str(), _SYS_STR("r")); auto errFp = hecl::FopenUnique(m_errPath.c_str(), _SYS_STR("r"));
if (errFp) {
fseek(errFp, 0, SEEK_END); if (errFp != nullptr) {
int64_t len = hecl::FTell(errFp); std::fseek(errFp.get(), 0, SEEK_END);
if (len) { const int64_t len = hecl::FTell(errFp.get());
fseek(errFp, 0, SEEK_SET);
std::unique_ptr<char[]> buf(new char[len + 1]); if (len != 0) {
memset(buf.get(), 0, len + 1); std::fseek(errFp.get(), 0, SEEK_SET);
fread(buf.get(), 1, len, errFp); const auto buf = std::make_unique<char[]>(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("\n{:.{}s}"), buf.get(), len);
} }
} }
BlenderLog.report(logvisor::Fatal, fmt("Blender Exception")); BlenderLog.report(logvisor::Fatal, fmt("Blender Exception"));
} }

View File

@ -43,17 +43,19 @@ Project::ConfigFile::ConfigFile(const Project& project, SystemStringView name, S
} }
std::vector<std::string>& Project::ConfigFile::lockAndRead() { std::vector<std::string>& Project::ConfigFile::lockAndRead() {
if (m_lockedFile) if (m_lockedFile != nullptr) {
return m_lines; return m_lines;
}
m_lockedFile = hecl::Fopen(m_filepath.c_str(), _SYS_STR("a+"), FileLockType::Write); m_lockedFile = hecl::FopenUnique(m_filepath.c_str(), _SYS_STR("a+"), FileLockType::Write);
hecl::FSeek(m_lockedFile, 0, SEEK_SET); hecl::FSeek(m_lockedFile.get(), 0, SEEK_SET);
std::string mainString; std::string mainString;
char readBuf[1024]; char readBuf[1024];
size_t readSz; 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); mainString += std::string(readBuf, readSz);
}
std::string::const_iterator begin = mainString.begin(); std::string::const_iterator begin = mainString.begin();
std::string::const_iterator end = 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() { void Project::ConfigFile::unlockAndDiscard() {
if (!m_lockedFile) { if (m_lockedFile == nullptr) {
LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__, fmt("Project::ConfigFile::lockAndRead not yet called")); LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__, fmt("Project::ConfigFile::lockAndRead not yet called"));
return; return;
} }
m_lines.clear(); m_lines.clear();
fclose(m_lockedFile); m_lockedFile.reset();
m_lockedFile = NULL;
} }
bool Project::ConfigFile::unlockAndCommit() { bool Project::ConfigFile::unlockAndCommit() {
@ -126,23 +127,22 @@ bool Project::ConfigFile::unlockAndCommit() {
return false; return false;
} }
SystemString newPath = m_filepath + _SYS_STR(".part"); const SystemString newPath = m_filepath + _SYS_STR(".part");
FILE* newFile = hecl::Fopen(newPath.c_str(), _SYS_STR("w"), FileLockType::Write); auto newFile = hecl::FopenUnique(newPath.c_str(), _SYS_STR("w"), FileLockType::Write);
bool fail = false; bool fail = false;
for (const std::string& line : m_lines) { 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; fail = true;
break; break;
} }
if (fwrite("\n", 1, 1, newFile) != 1) { if (std::fputc('\n', newFile.get()) == EOF) {
fail = true; fail = true;
break; break;
} }
} }
m_lines.clear(); m_lines.clear();
fclose(newFile); newFile.reset();
fclose(m_lockedFile); m_lockedFile.reset();
m_lockedFile = NULL;
if (fail) { if (fail) {
#if HECL_UCS2 #if HECL_UCS2
_wunlink(newPath.c_str()); _wunlink(newPath.c_str());
@ -191,20 +191,21 @@ Project::Project(const ProjectRootPath& rootPath)
m_cookedRoot.makeDir(); m_cookedRoot.makeDir();
/* Ensure beacon is valid or created */ /* Ensure beacon is valid or created */
ProjectPath beaconPath(m_dotPath, _SYS_STR("beacon")); const ProjectPath beaconPath(m_dotPath, _SYS_STR("beacon"));
FILE* bf = hecl::Fopen(beaconPath.getAbsolutePath().data(), _SYS_STR("a+b")); auto bf = hecl::FopenUnique(beaconPath.getAbsolutePath().data(), _SYS_STR("a+b"));
struct BeaconStruct { struct BeaconStruct {
hecl::FourCC magic; hecl::FourCC magic;
uint32_t version; uint32_t version;
} beacon; } beacon;
#define DATA_VERSION 1 constexpr uint32_t DATA_VERSION = 1;
if (fread(&beacon, 1, sizeof(beacon), bf) != sizeof(beacon)) { if (std::fread(&beacon, 1, sizeof(beacon), bf.get()) != sizeof(beacon)) {
fseek(bf, 0, SEEK_SET); std::fseek(bf.get(), 0, SEEK_SET);
beacon.magic = HECLfcc; beacon.magic = HECLfcc;
beacon.version = SBig(DATA_VERSION); 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) { if (beacon.magic != HECLfcc || SBig(beacon.version) != DATA_VERSION) {
LogModule.report(logvisor::Fatal, fmt("incompatible project version")); LogModule.report(logvisor::Fatal, fmt("incompatible project version"));
return; return;

View File

@ -256,17 +256,22 @@ ProjectRootPath SearchForProject(SystemStringView path) {
Sstat theStat; Sstat theStat;
if (!hecl::Stat(testIndexPath.c_str(), &theStat)) { if (!hecl::Stat(testIndexPath.c_str(), &theStat)) {
if (S_ISREG(theStat.st_mode)) { if (S_ISREG(theStat.st_mode)) {
FILE* fp = hecl::Fopen(testIndexPath.c_str(), _SYS_STR("rb")); const auto fp = hecl::FopenUnique(testIndexPath.c_str(), _SYS_STR("rb"));
if (!fp) if (fp == nullptr) {
continue; continue;
}
char magic[4]; char magic[4];
size_t readSize = fread(magic, 1, 4, fp); const size_t readSize = std::fread(magic, 1, sizeof(magic), fp.get());
fclose(fp); if (readSize != sizeof(magic)) {
if (readSize != 4)
continue; continue;
}
static constexpr hecl::FourCC hecl("HECL"); static constexpr hecl::FourCC hecl("HECL");
if (hecl::FourCC(magic) != hecl) if (hecl::FourCC(magic) != hecl) {
continue; continue;
}
return ProjectRootPath(testPath); return ProjectRootPath(testPath);
} }
} }
@ -280,40 +285,51 @@ ProjectRootPath SearchForProject(SystemStringView path) {
} }
ProjectRootPath SearchForProject(SystemStringView path, SystemString& subpathOut) { ProjectRootPath SearchForProject(SystemStringView path, SystemString& subpathOut) {
ProjectRootPath testRoot(path); const ProjectRootPath testRoot(path);
auto begin = testRoot.getAbsolutePath().begin(); auto begin = testRoot.getAbsolutePath().begin();
auto end = testRoot.getAbsolutePath().end(); auto end = testRoot.getAbsolutePath().end();
while (begin != end) { while (begin != end) {
SystemString testPath(begin, end); SystemString testPath(begin, end);
SystemString testIndexPath = testPath + _SYS_STR("/.hecl/beacon"); SystemString testIndexPath = testPath + _SYS_STR("/.hecl/beacon");
Sstat theStat; Sstat theStat;
if (!hecl::Stat(testIndexPath.c_str(), &theStat)) { if (!hecl::Stat(testIndexPath.c_str(), &theStat)) {
if (S_ISREG(theStat.st_mode)) { if (S_ISREG(theStat.st_mode)) {
FILE* fp = hecl::Fopen(testIndexPath.c_str(), _SYS_STR("rb")); const auto fp = hecl::FopenUnique(testIndexPath.c_str(), _SYS_STR("rb"));
if (!fp) if (fp == nullptr) {
continue; continue;
}
char magic[4]; char magic[4];
size_t readSize = fread(magic, 1, 4, fp); const size_t readSize = std::fread(magic, 1, sizeof(magic), fp.get());
fclose(fp); if (readSize != sizeof(magic)) {
if (readSize != 4)
continue; continue;
if (hecl::FourCC(magic) != FOURCC('HECL')) }
if (hecl::FourCC(magic) != FOURCC('HECL')) {
continue; 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; ++end;
if (end != origEnd && (*end == _SYS_STR('/') || *end == _SYS_STR('\\'))) }
if (end != origEnd && (*end == _SYS_STR('/') || *end == _SYS_STR('\\'))) {
++end; ++end;
}
subpathOut.assign(end, origEnd); subpathOut.assign(end, origEnd);
return newRootPath; 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; --end;
if (begin != end) }
if (begin != end) {
--end; --end;
}
} }
return ProjectRootPath(); return ProjectRootPath();
} }

View File

@ -57,44 +57,45 @@ hecl::SystemString FindCommonSteamApp(const hecl::SystemChar* name) {
#endif #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 */ /* Try main steam install directory first */
hecl::SystemString steamAppsMain = steamInstallDir + PATH_SEP + _SYS_STR("steamapps"); const hecl::SystemString steamAppsMain = steamInstallDir + PATH_SEP + _SYS_STR("steamapps");
hecl::SystemString mainAppPath = steamAppsMain + PATH_SEP + appPath; const hecl::SystemString mainAppPath = steamAppsMain + PATH_SEP + appPath;
if (!hecl::Stat(mainAppPath.c_str(), &theStat) && S_ISDIR(theStat.st_mode)) if (!hecl::Stat(mainAppPath.c_str(), &theStat) && S_ISDIR(theStat.st_mode)) {
return mainAppPath; return mainAppPath;
}
/* Iterate alternate steam install dirs */ /* Iterate alternate steam install dirs */
hecl::SystemString libraryFoldersVdfPath = steamAppsMain + PATH_SEP + _SYS_STR("libraryfolders.vdf"); const hecl::SystemString libraryFoldersVdfPath = steamAppsMain + PATH_SEP + _SYS_STR("libraryfolders.vdf");
FILE* fp = hecl::Fopen(libraryFoldersVdfPath.c_str(), _SYS_STR("r")); auto fp = hecl::FopenUnique(libraryFoldersVdfPath.c_str(), _SYS_STR("r"));
if (!fp) if (fp == nullptr) {
return {}; 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) { if (fileLen <= 0) {
fclose(fp);
return {}; return {};
} }
hecl::FSeek(fp, 0, SEEK_SET); hecl::FSeek(fp.get(), 0, SEEK_SET);
std::string fileBuf; std::string fileBuf(fileLen, '\0');
fileBuf.resize(fileLen); if (std::fread(fileBuf.data(), 1, fileLen, fp.get()) != fileLen) {
if (fread(&fileBuf[0], 1, fileLen, fp) != fileLen) {
fclose(fp);
return {}; return {};
} }
fclose(fp);
std::smatch dirMatch; std::smatch dirMatch;
auto begin = fileBuf.cbegin(); auto begin = fileBuf.cbegin();
auto end = fileBuf.cend(); const auto end = fileBuf.cend();
while (std::regex_search(begin, end, dirMatch, regSteamPath)) { while (std::regex_search(begin, end, dirMatch, regSteamPath)) {
std::string match = dirMatch[1].str(); const std::string match = dirMatch[1].str();
hecl::SystemStringConv otherInstallDir(match); const hecl::SystemStringConv otherInstallDir(match);
hecl::SystemString otherAppPath = const auto otherAppPath =
hecl::SystemString(otherInstallDir.sys_str()) + PATH_SEP + _SYS_STR("steamapps") + PATH_SEP + appPath; 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; return otherAppPath;
}
begin = dirMatch.suffix().first; begin = dirMatch.suffix().first;
} }

View File

@ -144,38 +144,38 @@ void ResourceLock::ClearThreadRes() {
} }
bool IsPathPNG(const hecl::ProjectPath& path) { bool IsPathPNG(const hecl::ProjectPath& path) {
FILE* fp = hecl::Fopen(path.getAbsolutePath().data(), _SYS_STR("rb")); const auto fp = hecl::FopenUnique(path.getAbsolutePath().data(), _SYS_STR("rb"));
if (!fp) if (fp == nullptr) {
return false;
uint32_t buf = 0;
if (fread(&buf, 1, 4, fp) != 4) {
fclose(fp);
return false; 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); buf = hecl::SBig(buf);
if (buf == 0x89504e47) return buf == 0x89504e47;
return true;
return false;
} }
bool IsPathBlend(const hecl::ProjectPath& path) { bool IsPathBlend(const hecl::ProjectPath& path) {
auto lastCompExt = path.getLastComponentExt(); const auto lastCompExt = path.getLastComponentExt();
if (lastCompExt.empty() || hecl::StrCmp(lastCompExt.data(), _SYS_STR("blend"))) 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);
return false; 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); buf = hecl::SLittle(buf);
if (buf == 0x4e454c42 || buf == 0x88b1f) return buf == 0x4e454c42 || buf == 0x88b1f;
return true;
return false;
} }
bool IsPathYAML(const hecl::ProjectPath& path) { bool IsPathYAML(const hecl::ProjectPath& path) {