Browse Source

assets.cpp: Avoid allocs in UNPACKED_MPQS FindFile

pull/5522/head
Gleb Mazovetskiy 3 years ago committed by Anders Jenbo
parent
commit
f9da4e1f66
  1. 48
      Source/engine/assets.cpp
  2. 8
      Source/engine/assets.hpp

48
Source/engine/assets.cpp

@ -9,21 +9,24 @@
#include "utils/file_util.h" #include "utils/file_util.h"
#include "utils/log.hpp" #include "utils/log.hpp"
#include "utils/paths.h" #include "utils/paths.h"
#include "utils/str_cat.hpp"
namespace devilution { namespace devilution {
namespace { namespace {
#ifdef UNPACKED_MPQS #ifdef UNPACKED_MPQS
std::string FindUnpackedMpqFile(const char *relativePath) char *FindUnpackedMpqFile(char *relativePath)
{ {
std::string path; char *path = nullptr;
const auto at = [&](const std::optional<std::string> &unpackedDir) -> bool { const auto at = [&](const std::optional<std::string> &unpackedDir) -> bool {
if (!unpackedDir) if (!unpackedDir)
return false; return false;
if (FileExists(path.append(*unpackedDir).append(relativePath).c_str())) path = relativePath - unpackedDir->size();
std::memcpy(path, unpackedDir->data(), unpackedDir->size());
if (FileExists(path))
return true; return true;
path.clear(); path = nullptr;
return false; return false;
}; };
at(font_data_path) || at(lang_data_path) at(font_data_path) || at(lang_data_path)
@ -68,26 +71,39 @@ bool FindMpqFile(const char *filename, MpqArchive **archive, uint32_t *fileNumbe
AssetRef FindAsset(const char *filename) AssetRef FindAsset(const char *filename)
{ {
AssetRef result; AssetRef result;
std::string relativePath = filename; result.path[0] = '\0';
const string_view filenameStr = filename;
char pathBuf[AssetRef::PathBufSize];
char *const pathEnd = pathBuf + AssetRef::PathBufSize;
char *const relativePath = &pathBuf[AssetRef::PathBufSize - filenameStr.size() - 1];
*BufCopy(relativePath, filenameStr) = '\0';
#ifndef _WIN32 #ifndef _WIN32
std::replace(relativePath.begin(), relativePath.end(), '\\', '/'); std::replace(relativePath, pathEnd, '\\', '/');
#endif #endif
// Absolute path: // Absolute path:
if (relativePath[0] == '/') { if (relativePath[0] == '/') {
if (FileExists(relativePath)) if (FileExists(relativePath)) {
result.path = std::move(relativePath); *BufCopy(result.path, string_view(relativePath, filenameStr.size())) = '\0';
}
return result; return result;
} }
// Unpacked MPQ file: // Unpacked MPQ file:
result.path = FindUnpackedMpqFile(relativePath.c_str()); char *const unpackedMpqPath = FindUnpackedMpqFile(relativePath);
if (!result.path.empty()) if (unpackedMpqPath != nullptr) {
*BufCopy(result.path, string_view(unpackedMpqPath, pathEnd - unpackedMpqPath)) = '\0';
return result; return result;
}
// The `/assets` directory next to the devilutionx binary. // The `/assets` directory next to the devilutionx binary.
std::string path = paths::AssetsPath() + relativePath; const std::string &assetsPathPrefix = paths::AssetsPath();
if (FileExists(path)) char *assetsPath = relativePath - assetsPathPrefix.size();
result.path = std::move(path); std::memcpy(assetsPath, assetsPathPrefix.data(), assetsPathPrefix.size());
if (FileExists(assetsPath)) {
*BufCopy(result.path, string_view(assetsPath, pathEnd - assetsPath)) = '\0';
}
return result; return result;
} }
#else #else
@ -143,8 +159,8 @@ AssetRef FindAsset(const char *filename)
AssetHandle OpenAsset(AssetRef &&ref, bool threadsafe) AssetHandle OpenAsset(AssetRef &&ref, bool threadsafe)
{ {
#ifdef UNPACKED_MPQS #if UNPACKED_MPQS
return AssetHandle { OpenFile(ref.path.c_str(), "rb") }; return AssetHandle { OpenFile(ref.path, "rb") };
#else #else
if (ref.archive != nullptr) if (ref.archive != nullptr)
return AssetHandle { SDL_RWops_FromMpqFile(*ref.archive, ref.fileNumber, ref.filename, threadsafe) }; return AssetHandle { SDL_RWops_FromMpqFile(*ref.archive, ref.fileNumber, ref.filename, threadsafe) };
@ -181,7 +197,7 @@ SDL_RWops *OpenAssetAsSdlRwOps(const char *filename, bool threadsafe)
AssetRef ref = FindAsset(filename); AssetRef ref = FindAsset(filename);
if (!ref.ok()) if (!ref.ok())
return nullptr; return nullptr;
return SDL_RWFromFile(ref.path.c_str(), "rb"); return SDL_RWFromFile(ref.path, "rb");
#else #else
return OpenAsset(filename, threadsafe).release(); return OpenAsset(filename, threadsafe).release();
#endif #endif

8
Source/engine/assets.hpp

@ -18,11 +18,13 @@ namespace devilution {
#ifdef UNPACKED_MPQS #ifdef UNPACKED_MPQS
struct AssetRef { struct AssetRef {
std::string path; static constexpr size_t PathBufSize = 4088;
char path[PathBufSize];
[[nodiscard]] bool ok() const [[nodiscard]] bool ok() const
{ {
return !path.empty(); return path[0] != '\0';
} }
// NOLINTNEXTLINE(readability-convert-member-functions-to-static) // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
@ -34,7 +36,7 @@ struct AssetRef {
[[nodiscard]] size_t size() const [[nodiscard]] size_t size() const
{ {
uintmax_t fileSize; uintmax_t fileSize;
if (!GetFileSize(path.c_str(), &fileSize)) if (!GetFileSize(path, &fileSize))
return 0; return 0;
return fileSize; return fileSize;
} }

Loading…
Cancel
Save