Browse Source

`string_view`-based asset lookup

Changes asset lookup functions to use `std::string_view` instead of
`const char *`.

This required new APIs in libmpq, added in
https://github.com/diasurgical/libmpq/pull/13.
pull/6490/head
Gleb Mazovetskiy 3 years ago
parent
commit
4a4735e908
  1. 4
      3rdParty/libmpq/CMakeLists.txt
  2. 22
      Source/engine/assets.cpp
  3. 17
      Source/engine/assets.hpp
  4. 21
      Source/mpq/mpq_reader.cpp
  5. 9
      Source/mpq/mpq_reader.hpp
  6. 3
      Source/mpq/mpq_sdl_rwops.cpp
  7. 3
      Source/mpq/mpq_sdl_rwops.hpp

4
3rdParty/libmpq/CMakeLists.txt vendored

@ -10,8 +10,8 @@ include(functions/FetchContent_MakeAvailableExcludeFromAll)
include(FetchContent)
FetchContent_Declare(libmpq
URL https://github.com/diasurgical/libmpq/archive/b78d66c6fee6a501cc9b95d8556a129c68841b05.tar.gz
URL_HASH MD5=da531a1a6f719e89798a26e679ffc329
URL https://github.com/diasurgical/libmpq/archive/34ace76ecb18c3c72300a6b8352ca0c96333488d.tar.gz
URL_HASH MD5=e76ab7e4f9dfd7f96c152dd7d8418fee
)
FetchContent_MakeAvailableExcludeFromAll(libmpq)

22
Source/engine/assets.cpp

@ -3,6 +3,7 @@
#include <algorithm>
#include <cstdint>
#include <cstring>
#include <string_view>
#include "init.h"
#include "utils/file_util.h"
@ -52,7 +53,7 @@ SDL_RWops *OpenOptionalRWops(const std::string &path)
return SDL_RWFromFile(path.c_str(), "rb");
};
bool FindMpqFile(const char *filename, MpqArchive **archive, uint32_t *fileNumber)
bool FindMpqFile(std::string_view filename, MpqArchive **archive, uint32_t *fileNumber)
{
const MpqArchive::FileHash fileHash = MpqArchive::CalculateFileHash(filename);
const auto at = [=](std::optional<MpqArchive> &src) -> bool {
@ -71,16 +72,15 @@ bool FindMpqFile(const char *filename, MpqArchive **archive, uint32_t *fileNumbe
} // namespace
#ifdef UNPACKED_MPQS
AssetRef FindAsset(const char *filename)
AssetRef FindAsset(std::string_view filename)
{
AssetRef result;
result.path[0] = '\0';
const std::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';
char *const relativePath = &pathBuf[AssetRef::PathBufSize - filename.size() - 1];
*BufCopy(relativePath, filename) = '\0';
#ifndef _WIN32
std::replace(relativePath, pathEnd, '\\', '/');
@ -88,7 +88,7 @@ AssetRef FindAsset(const char *filename)
// Absolute path:
if (relativePath[0] == '/') {
if (FileExists(relativePath)) {
*BufCopy(result.path, std::string_view(relativePath, filenameStr.size())) = '\0';
*BufCopy(result.path, std::string_view(relativePath, filename.size())) = '\0';
}
return result;
}
@ -110,10 +110,10 @@ AssetRef FindAsset(const char *filename)
return result;
}
#else
AssetRef FindAsset(const char *filename)
AssetRef FindAsset(std::string_view filename)
{
AssetRef result;
std::string relativePath = filename;
std::string relativePath { filename };
#ifndef _WIN32
std::replace(relativePath.begin(), relativePath.end(), '\\', '/');
#endif
@ -177,7 +177,7 @@ AssetHandle OpenAsset(AssetRef &&ref, bool threadsafe)
#endif
}
AssetHandle OpenAsset(const char *filename, bool threadsafe)
AssetHandle OpenAsset(std::string_view filename, bool threadsafe)
{
AssetRef ref = FindAsset(filename);
if (!ref.ok())
@ -185,7 +185,7 @@ AssetHandle OpenAsset(const char *filename, bool threadsafe)
return OpenAsset(std::move(ref), threadsafe);
}
AssetHandle OpenAsset(const char *filename, size_t &fileSize, bool threadsafe)
AssetHandle OpenAsset(std::string_view filename, size_t &fileSize, bool threadsafe)
{
AssetRef ref = FindAsset(filename);
if (!ref.ok())
@ -194,7 +194,7 @@ AssetHandle OpenAsset(const char *filename, size_t &fileSize, bool threadsafe)
return OpenAsset(std::move(ref), threadsafe);
}
SDL_RWops *OpenAssetAsSdlRwOps(const char *filename, bool threadsafe)
SDL_RWops *OpenAssetAsSdlRwOps(std::string_view filename, bool threadsafe)
{
#ifdef UNPACKED_MPQS
AssetRef ref = FindAsset(filename);

17
Source/engine/assets.hpp

@ -4,6 +4,7 @@
#include <cstdint>
#include <cstdio>
#include <string>
#include <string_view>
#include <SDL.h>
@ -96,7 +97,7 @@ struct AssetRef {
// An MPQ file reference:
MpqArchive *archive = nullptr;
uint32_t fileNumber;
const char *filename;
std::string_view filename;
// Alternatively, a direct SDL_RWops handle:
SDL_RWops *directHandle = nullptr;
@ -212,12 +213,12 @@ struct AssetHandle {
};
#endif
[[noreturn]] inline void FailedToOpenFileError(const char *path, const char *error)
[[noreturn]] inline void FailedToOpenFileError(std::string_view path, std::string_view error)
{
app_fatal(StrCat("Failed to open file:\n", path, "\n\n", error));
}
inline bool ValidatAssetRef(const char *path, const AssetRef &ref)
inline bool ValidatAssetRef(std::string_view path, const AssetRef &ref)
{
if (ref.ok())
return true;
@ -227,7 +228,7 @@ inline bool ValidatAssetRef(const char *path, const AssetRef &ref)
return false;
}
inline bool ValidateHandle(const char *path, const AssetHandle &handle)
inline bool ValidateHandle(std::string_view path, const AssetHandle &handle)
{
if (handle.ok())
return true;
@ -237,12 +238,12 @@ inline bool ValidateHandle(const char *path, const AssetHandle &handle)
return false;
}
AssetRef FindAsset(const char *filename);
AssetRef FindAsset(std::string_view filename);
AssetHandle OpenAsset(AssetRef &&ref, bool threadsafe = false);
AssetHandle OpenAsset(const char *filename, bool threadsafe = false);
AssetHandle OpenAsset(const char *filename, size_t &fileSize, bool threadsafe = false);
AssetHandle OpenAsset(std::string_view filename, bool threadsafe = false);
AssetHandle OpenAsset(std::string_view filename, size_t &fileSize, bool threadsafe = false);
SDL_RWops *OpenAssetAsSdlRwOps(const char *filename, bool threadsafe = false);
SDL_RWops *OpenAssetAsSdlRwOps(std::string_view filename, bool threadsafe = false);
} // namespace devilution

21
Source/mpq/mpq_reader.cpp

@ -2,6 +2,7 @@
#include <cstdint>
#include <optional>
#include <string_view>
#include <libmpq/mpq.h>
@ -33,10 +34,10 @@ const char *MpqArchive::ErrorMessage(int32_t errorCode)
return libmpq__strerror(errorCode);
}
MpqArchive::FileHash MpqArchive::CalculateFileHash(const char *filename)
MpqArchive::FileHash MpqArchive::CalculateFileHash(std::string_view filename)
{
FileHash fileHash;
libmpq__file_hash(filename, &fileHash[0], &fileHash[1], &fileHash[2]);
libmpq__file_hash_s(filename.data(), filename.size(), &fileHash[0], &fileHash[1], &fileHash[2]);
return fileHash;
}
@ -61,11 +62,11 @@ bool MpqArchive::GetFileNumber(MpqArchive::FileHash fileHash, uint32_t &fileNumb
return libmpq__file_number_from_hash(archive_, fileHash[0], fileHash[1], fileHash[2], &fileNumber) == 0;
}
std::unique_ptr<std::byte[]> MpqArchive::ReadFile(const char *filename, std::size_t &fileSize, int32_t &error)
std::unique_ptr<std::byte[]> MpqArchive::ReadFile(std::string_view filename, std::size_t &fileSize, int32_t &error)
{
std::unique_ptr<std::byte[]> result;
std::uint32_t fileNumber;
error = libmpq__file_number(archive_, filename, &fileNumber);
error = libmpq__file_number_s(archive_, filename.data(), filename.size(), &fileNumber);
if (error != 0)
return result;
@ -88,8 +89,8 @@ std::unique_ptr<std::byte[]> MpqArchive::ReadFile(const char *filename, std::siz
if (error != 0)
return result;
error = libmpq__file_read_with_filename_and_temporary_buffer(
archive_, fileNumber, filename, reinterpret_cast<std::uint8_t *>(result.get()), unpackedSize,
error = libmpq__file_read_with_filename_and_temporary_buffer_s(
archive_, fileNumber, filename.data(), filename.size(), reinterpret_cast<std::uint8_t *>(result.get()), unpackedSize,
tmp.data(), static_cast<libmpq__off_t>(blockSize), nullptr);
if (error != 0) {
result = nullptr;
@ -125,9 +126,9 @@ uint32_t MpqArchive::GetNumBlocks(uint32_t fileNumber, int32_t &error)
return numBlocks;
}
int32_t MpqArchive::OpenBlockOffsetTable(uint32_t fileNumber, const char *filename)
int32_t MpqArchive::OpenBlockOffsetTable(uint32_t fileNumber, std::string_view filename)
{
return libmpq__block_open_offset_with_filename(archive_, fileNumber, filename);
return libmpq__block_open_offset_with_filename_s(archive_, fileNumber, filename.data(), filename.size());
}
int32_t MpqArchive::CloseBlockOffsetTable(uint32_t fileNumber)
@ -143,10 +144,10 @@ std::size_t MpqArchive::GetBlockSize(uint32_t fileNumber, uint32_t blockNumber,
return blockSize;
}
bool MpqArchive::HasFile(const char *filename) const
bool MpqArchive::HasFile(std::string_view filename) const
{
std::uint32_t fileNumber;
int32_t error = libmpq__file_number(archive_, filename, &fileNumber);
int32_t error = libmpq__file_number_s(archive_, filename.data(), filename.size(), &fileNumber);
return error == 0;
}

9
Source/mpq/mpq_reader.hpp

@ -6,6 +6,7 @@
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
// Forward-declare so that we can avoid exposing libmpq.
@ -24,7 +25,7 @@ public:
static const char *ErrorMessage(int32_t errorCode);
using FileHash = std::array<std::uint32_t, 3>;
static FileHash CalculateFileHash(const char *filename);
static FileHash CalculateFileHash(std::string_view filename);
MpqArchive(MpqArchive &&other) noexcept
: path_(std::move(other.path_))
@ -41,7 +42,7 @@ public:
// Returns false if the file does not exit.
bool GetFileNumber(FileHash fileHash, uint32_t &fileNumber);
std::unique_ptr<std::byte[]> ReadFile(const char *filename, std::size_t &fileSize, int32_t &error);
std::unique_ptr<std::byte[]> ReadFile(std::string_view filename, std::size_t &fileSize, int32_t &error);
// Returns error code.
int32_t ReadBlock(uint32_t fileNumber, uint32_t blockNumber, uint8_t *out, uint32_t outSize);
@ -50,14 +51,14 @@ public:
uint32_t GetNumBlocks(uint32_t fileNumber, int32_t &error);
int32_t OpenBlockOffsetTable(uint32_t fileNumber, const char *filename);
int32_t OpenBlockOffsetTable(uint32_t fileNumber, std::string_view filename);
int32_t CloseBlockOffsetTable(uint32_t fileNumber);
// Requires the block offset table to be open
std::size_t GetBlockSize(uint32_t fileNumber, uint32_t blockNumber, int32_t &error);
bool HasFile(const char *filename) const;
bool HasFile(std::string_view filename) const;
private:
MpqArchive(std::string path, mpq_archive_s *archive)

3
Source/mpq/mpq_sdl_rwops.cpp

@ -3,6 +3,7 @@
#include <cstdint>
#include <cstring>
#include <memory>
#include <string_view>
#include <vector>
namespace devilution {
@ -153,7 +154,7 @@ static int MpqFileRwClose(struct SDL_RWops *context)
} // namespace
SDL_RWops *SDL_RWops_FromMpqFile(MpqArchive &mpqArchive, uint32_t fileNumber, const char *filename, bool threadsafe)
SDL_RWops *SDL_RWops_FromMpqFile(MpqArchive &mpqArchive, uint32_t fileNumber, std::string_view filename, bool threadsafe)
{
auto result = std::make_unique<SDL_RWops>();
std::memset(result.get(), 0, sizeof(*result));

3
Source/mpq/mpq_sdl_rwops.hpp

@ -1,6 +1,7 @@
#pragma once
#include <cstdint>
#include <string_view>
#include <SDL.h>
@ -8,6 +9,6 @@
namespace devilution {
SDL_RWops *SDL_RWops_FromMpqFile(MpqArchive &mpqArchive, uint32_t fileNumber, const char *filename, bool threadsafe);
SDL_RWops *SDL_RWops_FromMpqFile(MpqArchive &mpqArchive, uint32_t fileNumber, std::string_view filename, bool threadsafe);
} // namespace devilution

Loading…
Cancel
Save