mirror of
https://github.com/wiiu-env/WiiUPluginLoaderBackend.git
synced 2026-09-08 20:08:45 -05:00
- use const auto& where possible
- avoid using const std::unique_ptr& and const std::shared_ptr& - avoid wrapping results in std::optional - prefer std::string_view over const std::string& - update FSUtils::LoadFileToMem to write into std::vector<uint8_t> - use std::span when possible - Avoid unnessecary copies in PluginDataFactory - allocate plugins as HeapMemoryFixedSize which bascially is a std::unique_ptr with fixed size
This commit is contained in:
@@ -122,12 +122,11 @@ void ConfigUtils::displayMenu() {
|
||||
std::vector<ConfigDisplayItem> configs;
|
||||
for (auto &plugin : gLoadedPlugins) {
|
||||
ConfigDisplayItem cfg;
|
||||
cfg.name = plugin->metaInformation->getName();
|
||||
cfg.author = plugin->metaInformation->getAuthor();
|
||||
cfg.version = plugin->metaInformation->getVersion();
|
||||
|
||||
for (auto &hook : plugin->getPluginInformation()->getHookDataList()) {
|
||||
cfg.name = plugin->getMetaInformation().getName();
|
||||
cfg.author = plugin->getMetaInformation().getAuthor();
|
||||
cfg.version = plugin->getMetaInformation().getVersion();
|
||||
|
||||
for (const auto &hook : plugin->getPluginInformation().getHookDataList()) {
|
||||
if (hook->getType() == WUPS_LOADER_HOOK_GET_CONFIG /*WUPS_LOADER_HOOK_GET_CONFIG*/) {
|
||||
if (hook->getFunctionPointer() == nullptr) {
|
||||
break;
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
#include <coreinit/cache.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "ElfUtils.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
// See https://github.com/decaf-emu/decaf-emu/blob/43366a34e7b55ab9d19b2444aeb0ccd46ac77dea/src/libdecaf/src/cafe/loader/cafe_loader_reloc.cpp#L144
|
||||
bool ElfUtils::elfLinkOne(char type, size_t offset, int32_t addend, uint32_t destination, uint32_t symbol_addr, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length,
|
||||
RelocationType reloc_type, uint8_t trampolineId) {
|
||||
bool ElfUtils::elfLinkOne(char type, size_t offset, int32_t addend, uint32_t destination, uint32_t symbol_addr,
|
||||
std::vector<relocation_trampoline_entry_t> &trampolineData, RelocationType reloc_type, uint8_t trampolineId) {
|
||||
if (type == R_PPC_NONE) {
|
||||
return true;
|
||||
}
|
||||
@@ -76,21 +77,21 @@ bool ElfUtils::elfLinkOne(char type, size_t offset, int32_t addend, uint32_t des
|
||||
// }
|
||||
auto distance = static_cast<int32_t>(value) - static_cast<int32_t>(target);
|
||||
if (distance > 0x1FFFFFC || distance < -0x1FFFFFC) {
|
||||
if (trampoline_data == nullptr) {
|
||||
if (trampolineData.empty()) {
|
||||
DEBUG_FUNCTION_LINE_ERR("***24-bit relative branch cannot hit target. Trampoline isn't provided");
|
||||
DEBUG_FUNCTION_LINE_ERR("***value %08X - target %08X = distance %08X", value, target, distance);
|
||||
return false;
|
||||
} else {
|
||||
relocation_trampoline_entry_t *freeSlot = nullptr;
|
||||
for (uint32_t i = 0; i < trampoline_data_length; i++) {
|
||||
for (auto &cur : trampolineData) {
|
||||
// We want to override "old" relocations of imports
|
||||
// Pending relocations have the status RELOC_TRAMP_IMPORT_IN_PROGRESS.
|
||||
// When all relocations are done successfully, they will be turned into RELOC_TRAMP_IMPORT_DONE
|
||||
// so they can be overridden/updated/reused on the next application launch.
|
||||
//
|
||||
// Relocations that won't change will have the status RELOC_TRAMP_FIXED and are set to free when the module is unloaded.
|
||||
if (trampoline_data[i].status == RELOC_TRAMP_FREE) {
|
||||
freeSlot = &(trampoline_data[i]);
|
||||
if (cur.status == RELOC_TRAMP_FREE) {
|
||||
freeSlot = &cur;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,6 @@ uint32_t load_loader_elf(unsigned char *baseAddress, char *elf_data, uint32_t fi
|
||||
class ElfUtils {
|
||||
|
||||
public:
|
||||
static bool elfLinkOne(char type, size_t offset, int32_t addend, uint32_t destination, uint32_t symbol_addr, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length,
|
||||
static bool elfLinkOne(char type, size_t offset, int32_t addend, uint32_t destination, uint32_t symbol_addr, std::vector<relocation_trampoline_entry_t> &trampolineData,
|
||||
RelocationType reloc_type, uint8_t trampolineId);
|
||||
};
|
||||
|
||||
45
source/utils/HeapMemoryFixedSize.h
Normal file
45
source/utils/HeapMemoryFixedSize.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
#include "utils.h"
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
class HeapMemoryFixedSize {
|
||||
public:
|
||||
HeapMemoryFixedSize() = default;
|
||||
|
||||
explicit HeapMemoryFixedSize(std::size_t size) : mData(make_unique_nothrow<uint8_t[]>(size)), mSize(mData ? size : 0) {}
|
||||
|
||||
// Delete the copy constructor and copy assignment operator
|
||||
HeapMemoryFixedSize(const HeapMemoryFixedSize &) = delete;
|
||||
HeapMemoryFixedSize &operator=(const HeapMemoryFixedSize &) = delete;
|
||||
|
||||
HeapMemoryFixedSize(HeapMemoryFixedSize &&other) noexcept
|
||||
: mData(std::move(other.mData)), mSize(other.mSize) {
|
||||
other.mSize = 0;
|
||||
}
|
||||
|
||||
HeapMemoryFixedSize &operator=(HeapMemoryFixedSize &&other) noexcept {
|
||||
if (this != &other) {
|
||||
mData = std::move(other.mData);
|
||||
mSize = other.mSize;
|
||||
other.mSize = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return mData != nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] const void *data() const {
|
||||
return mData.get();
|
||||
}
|
||||
|
||||
[[nodiscard]] std::size_t size() const {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<uint8_t[]> mData{};
|
||||
std::size_t mSize{};
|
||||
};
|
||||
@@ -122,7 +122,7 @@ WUPSStorageError StorageUtils::CloseStorage(const char *plugin_id, wups_storage_
|
||||
std::string folderPath = getPluginPath() + "/config/";
|
||||
std::string filePath = folderPath + plugin_id + ".json";
|
||||
|
||||
FSUtils::CreateSubfolder(folderPath.c_str());
|
||||
FSUtils::CreateSubfolder(folderPath);
|
||||
|
||||
CFile file(filePath, CFile::WriteOnly);
|
||||
if (!file.isOpen()) {
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
#include <wut_types.h>
|
||||
|
||||
template<typename... Args>
|
||||
std::string string_format(const std::string &format, Args... args) {
|
||||
int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0'
|
||||
std::string string_format(std::string_view format, Args... args) {
|
||||
int size_s = std::snprintf(nullptr, 0, format.data(), args...) + 1; // Extra space for '\0'
|
||||
auto size = static_cast<size_t>(size_s);
|
||||
auto buf = make_unique_nothrow<char[]>(size);
|
||||
if (!buf) {
|
||||
@@ -43,11 +43,10 @@ std::string string_format(const std::string &format, Args... args) {
|
||||
OSFatal("string_format failed, not enough memory");
|
||||
return std::string("");
|
||||
}
|
||||
std::snprintf(buf.get(), size, format.c_str(), args...);
|
||||
std::snprintf(buf.get(), size, format.data(), args...);
|
||||
return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
|
||||
}
|
||||
|
||||
|
||||
class StringTools {
|
||||
public:
|
||||
static std::string truncate(const std::string &str, size_t width, bool show_ellipsis = true);
|
||||
|
||||
@@ -6,35 +6,36 @@
|
||||
#include "utils.h"
|
||||
#include <wums.h>
|
||||
|
||||
static void fillPluginInformation(plugin_information *out, const std::unique_ptr<PluginMetaInformation> &metaInformation) {
|
||||
static void fillPluginInformation(plugin_information *out, const PluginMetaInformation &metaInformation) {
|
||||
out->plugin_information_version = PLUGIN_INFORMATION_VERSION;
|
||||
strncpy(out->author, metaInformation->getAuthor().c_str(), sizeof(out->author) - 1);
|
||||
strncpy(out->buildTimestamp, metaInformation->getBuildTimestamp().c_str(), sizeof(out->buildTimestamp) - 1);
|
||||
strncpy(out->description, metaInformation->getDescription().c_str(), sizeof(out->description) - 1);
|
||||
strncpy(out->name, metaInformation->getName().c_str(), sizeof(out->name) - 1);
|
||||
strncpy(out->license, metaInformation->getLicense().c_str(), sizeof(out->license) - 1);
|
||||
strncpy(out->version, metaInformation->getVersion().c_str(), sizeof(out->version) - 1);
|
||||
strncpy(out->storageId, metaInformation->getStorageId().c_str(), sizeof(out->storageId) - 1);
|
||||
out->size = metaInformation->getSize();
|
||||
strncpy(out->author, metaInformation.getAuthor().c_str(), sizeof(out->author) - 1);
|
||||
strncpy(out->buildTimestamp, metaInformation.getBuildTimestamp().c_str(), sizeof(out->buildTimestamp) - 1);
|
||||
strncpy(out->description, metaInformation.getDescription().c_str(), sizeof(out->description) - 1);
|
||||
strncpy(out->name, metaInformation.getName().c_str(), sizeof(out->name) - 1);
|
||||
strncpy(out->license, metaInformation.getLicense().c_str(), sizeof(out->license) - 1);
|
||||
strncpy(out->version, metaInformation.getVersion().c_str(), sizeof(out->version) - 1);
|
||||
strncpy(out->storageId, metaInformation.getStorageId().c_str(), sizeof(out->storageId) - 1);
|
||||
out->size = metaInformation.getSize();
|
||||
}
|
||||
|
||||
extern "C" PluginBackendApiErrorType WUPSLoadAndLinkByDataHandle(const plugin_data_handle *plugin_data_handle_list, uint32_t plugin_data_handle_list_size) {
|
||||
if (plugin_data_handle_list == nullptr || plugin_data_handle_list_size == 0) {
|
||||
|
||||
return PLUGIN_BACKEND_API_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(gLoadedDataMutex);
|
||||
for (uint32_t i = 0; i < plugin_data_handle_list_size; i++) {
|
||||
auto handle = plugin_data_handle_list[i];
|
||||
bool found = false;
|
||||
|
||||
for (auto &pluginData : gLoadedData) {
|
||||
for (const auto &pluginData : gLoadedData) {
|
||||
if (pluginData->getHandle() == handle) {
|
||||
gLoadOnNextLaunch.push_front(pluginData);
|
||||
gLoadOnNextLaunch.insert(pluginData);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to get plugin data for handle %08X. Skipping it.", handle);
|
||||
}
|
||||
@@ -45,9 +46,7 @@ extern "C" PluginBackendApiErrorType WUPSLoadAndLinkByDataHandle(const plugin_da
|
||||
|
||||
extern "C" PluginBackendApiErrorType WUPSDeletePluginData(const plugin_data_handle *plugin_data_handle_list, uint32_t plugin_data_handle_list_size) {
|
||||
if (plugin_data_handle_list != nullptr && plugin_data_handle_list_size != 0) {
|
||||
for (uint32_t i = 0; i < plugin_data_handle_list_size; i++) {
|
||||
auto handle = plugin_data_handle_list[i];
|
||||
|
||||
for (auto &handle : std::span(plugin_data_handle_list, plugin_data_handle_list_size)) {
|
||||
if (!remove_locked_first_if(gLoadedDataMutex, gLoadedData, [handle](auto &cur) { return cur->getHandle() == handle; })) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to delete plugin data by handle %08X", handle);
|
||||
}
|
||||
@@ -61,13 +60,11 @@ extern "C" PluginBackendApiErrorType WUPSLoadPluginAsData(GetPluginInformationIn
|
||||
return PLUGIN_BACKEND_API_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
std::optional<std::unique_ptr<PluginData>> pluginData;
|
||||
std::unique_ptr<PluginData> pluginData;
|
||||
if (inputType == PLUGIN_INFORMATION_INPUT_TYPE_PATH && path != nullptr) {
|
||||
pluginData = PluginDataFactory::load(path);
|
||||
} else if (inputType == PLUGIN_INFORMATION_INPUT_TYPE_BUFFER && buffer != nullptr && size > 0) {
|
||||
std::vector<uint8_t> data(size);
|
||||
memcpy(&data[0], buffer, size);
|
||||
pluginData = PluginDataFactory::load(data, "<UNKNOWN>");
|
||||
pluginData = make_unique_nothrow<PluginData>(std::span((uint8_t *) buffer, size), "<UNKNOWN>");
|
||||
} else {
|
||||
return PLUGIN_BACKEND_API_ERROR_INVALID_ARG;
|
||||
}
|
||||
@@ -75,11 +72,9 @@ extern "C" PluginBackendApiErrorType WUPSLoadPluginAsData(GetPluginInformationIn
|
||||
if (!pluginData) {
|
||||
DEBUG_FUNCTION_LINE_ERR("PLUGIN_BACKEND_API_ERROR_FAILED_ALLOC");
|
||||
return PLUGIN_BACKEND_API_ERROR_FAILED_ALLOC;
|
||||
}
|
||||
|
||||
else {
|
||||
*out = pluginData.value()->getHandle();
|
||||
gLoadedData.push_front(std::move(pluginData.value()));
|
||||
} else {
|
||||
*out = pluginData->getHandle();
|
||||
gLoadedData.insert(std::move(pluginData));
|
||||
}
|
||||
|
||||
return PLUGIN_BACKEND_API_ERROR_NONE;
|
||||
@@ -94,13 +89,17 @@ extern "C" PluginBackendApiErrorType WUPSLoadPluginAsDataByBuffer(plugin_data_ha
|
||||
}
|
||||
|
||||
extern "C" PluginBackendApiErrorType WUPSGetPluginMetaInformation(GetPluginInformationInputType inputType, const char *path, char *buffer, size_t size, plugin_information *output) {
|
||||
std::optional<std::unique_ptr<PluginMetaInformation>> pluginInfo;
|
||||
if (output == nullptr) {
|
||||
DEBUG_FUNCTION_LINE_ERR("PLUGIN_BACKEND_API_ERROR_INVALID_ARG");
|
||||
return PLUGIN_BACKEND_API_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
std::unique_ptr<PluginMetaInformation> pluginInfo;
|
||||
PluginParseErrors error = PLUGIN_PARSE_ERROR_UNKNOWN;
|
||||
if (inputType == PLUGIN_INFORMATION_INPUT_TYPE_PATH && path != nullptr) {
|
||||
std::string pathStr(path);
|
||||
pluginInfo = PluginMetaInformationFactory::loadPlugin(pathStr, error);
|
||||
pluginInfo = PluginMetaInformationFactory::loadPlugin(path, error);
|
||||
} else if (inputType == PLUGIN_INFORMATION_INPUT_TYPE_BUFFER && buffer != nullptr && size > 0) {
|
||||
pluginInfo = PluginMetaInformationFactory::loadPlugin(buffer, size, error);
|
||||
pluginInfo = PluginMetaInformationFactory::loadPlugin(std::span<uint8_t const>((uint8_t *) buffer, size), error);
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_ERR("PLUGIN_BACKEND_API_ERROR_INVALID_ARG");
|
||||
return PLUGIN_BACKEND_API_ERROR_INVALID_ARG;
|
||||
@@ -110,13 +109,8 @@ extern "C" PluginBackendApiErrorType WUPSGetPluginMetaInformation(GetPluginInfor
|
||||
DEBUG_FUNCTION_LINE_ERR("PLUGIN_BACKEND_API_ERROR_FILE_NOT_FOUND");
|
||||
return PLUGIN_BACKEND_API_ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
fillPluginInformation(output, *pluginInfo);
|
||||
|
||||
if (output == nullptr) {
|
||||
DEBUG_FUNCTION_LINE_ERR("PLUGIN_BACKEND_API_ERROR_INVALID_ARG");
|
||||
return PLUGIN_BACKEND_API_ERROR_INVALID_ARG;
|
||||
} else {
|
||||
fillPluginInformation(output, pluginInfo.value());
|
||||
}
|
||||
return PLUGIN_BACKEND_API_ERROR_NONE;
|
||||
}
|
||||
|
||||
@@ -135,21 +129,21 @@ extern "C" PluginBackendApiErrorType WUPSGetPluginDataForContainerHandles(const
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(gLoadedDataMutex);
|
||||
for (uint32_t i = 0; i < buffer_size; /* only increase on success*/) {
|
||||
for (uint32_t i = 0; i < buffer_size; i++) {
|
||||
auto handle = plugin_container_handle_list[i];
|
||||
bool found = false;
|
||||
for (auto &curContainer : gLoadedPlugins) {
|
||||
for (const auto &curContainer : gLoadedPlugins) {
|
||||
if (curContainer->getHandle() == handle) {
|
||||
auto &pluginData = curContainer->getPluginData();
|
||||
auto pluginData = curContainer->getPluginDataCopy();
|
||||
plugin_data_list[i] = (uint32_t) pluginData->getHandle();
|
||||
gLoadedData.push_front(pluginData);
|
||||
gLoadedData.insert(std::move(pluginData));
|
||||
found = true;
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to get container for handle %08X", handle);
|
||||
return PLUGIN_BACKEND_API_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,19 +156,19 @@ extern "C" PluginBackendApiErrorType WUPSGetMetaInformation(const plugin_contain
|
||||
for (uint32_t i = 0; i < buffer_size; i++) {
|
||||
auto handle = plugin_container_handle_list[i];
|
||||
bool found = false;
|
||||
for (auto &curContainer : gLoadedPlugins) {
|
||||
for (const auto &curContainer : gLoadedPlugins) {
|
||||
if (curContainer->getHandle() == handle) {
|
||||
auto &metaInfo = curContainer->getMetaInformation();
|
||||
const auto &metaInfo = curContainer->getMetaInformation();
|
||||
|
||||
plugin_information_list[i].plugin_information_version = PLUGIN_INFORMATION_VERSION;
|
||||
strncpy(plugin_information_list[i].storageId, metaInfo->getStorageId().c_str(), sizeof(plugin_information_list[i].storageId) - 1);
|
||||
strncpy(plugin_information_list[i].author, metaInfo->getAuthor().c_str(), sizeof(plugin_information_list[i].author) - 1);
|
||||
strncpy(plugin_information_list[i].buildTimestamp, metaInfo->getBuildTimestamp().c_str(), sizeof(plugin_information_list[i].buildTimestamp) - 1);
|
||||
strncpy(plugin_information_list[i].description, metaInfo->getDescription().c_str(), sizeof(plugin_information_list[i].description) - 1);
|
||||
strncpy(plugin_information_list[i].name, metaInfo->getName().c_str(), sizeof(plugin_information_list[i].name) - 1);
|
||||
strncpy(plugin_information_list[i].license, metaInfo->getLicense().c_str(), sizeof(plugin_information_list[i].license) - 1);
|
||||
strncpy(plugin_information_list[i].version, metaInfo->getVersion().c_str(), sizeof(plugin_information_list[i].version) - 1);
|
||||
plugin_information_list[i].size = metaInfo->getSize();
|
||||
strncpy(plugin_information_list[i].storageId, metaInfo.getStorageId().c_str(), sizeof(plugin_information_list[i].storageId) - 1);
|
||||
strncpy(plugin_information_list[i].author, metaInfo.getAuthor().c_str(), sizeof(plugin_information_list[i].author) - 1);
|
||||
strncpy(plugin_information_list[i].buildTimestamp, metaInfo.getBuildTimestamp().c_str(), sizeof(plugin_information_list[i].buildTimestamp) - 1);
|
||||
strncpy(plugin_information_list[i].description, metaInfo.getDescription().c_str(), sizeof(plugin_information_list[i].description) - 1);
|
||||
strncpy(plugin_information_list[i].name, metaInfo.getName().c_str(), sizeof(plugin_information_list[i].name) - 1);
|
||||
strncpy(plugin_information_list[i].license, metaInfo.getLicense().c_str(), sizeof(plugin_information_list[i].license) - 1);
|
||||
strncpy(plugin_information_list[i].version, metaInfo.getVersion().c_str(), sizeof(plugin_information_list[i].version) - 1);
|
||||
plugin_information_list[i].size = metaInfo.getSize();
|
||||
found = true;
|
||||
|
||||
break;
|
||||
@@ -196,9 +190,8 @@ extern "C" PluginBackendApiErrorType WUPSGetLoadedPlugins(plugin_container_handl
|
||||
return PLUGIN_BACKEND_API_ERROR_INVALID_ARG;
|
||||
}
|
||||
*plugin_information_version = PLUGIN_INFORMATION_VERSION;
|
||||
auto &plugins = gLoadedPlugins;
|
||||
uint32_t counter = 0;
|
||||
for (auto &plugin : plugins) {
|
||||
for (const auto &plugin : gLoadedPlugins) {
|
||||
if (counter < buffer_size) {
|
||||
io_handles[counter] = plugin->getHandle();
|
||||
counter++;
|
||||
@@ -248,10 +241,10 @@ extern "C" PluginBackendApiErrorType WUPSGetSectionInformationForPlugin(const pl
|
||||
}
|
||||
if (handle != 0 && plugin_section_list != nullptr && buffer_size != 0) {
|
||||
bool found = false;
|
||||
for (auto &curContainer : gLoadedPlugins) {
|
||||
for (const auto &curContainer : gLoadedPlugins) {
|
||||
if (curContainer->getHandle() == handle) {
|
||||
found = true;
|
||||
auto §ionInfoList = curContainer->getPluginInformation()->getSectionInfoList();
|
||||
found = true;
|
||||
const auto §ionInfoList = curContainer->getPluginInformation().getSectionInfoList();
|
||||
|
||||
uint32_t offset = 0;
|
||||
for (auto const &[key, sectionInfo] : sectionInfoList) {
|
||||
@@ -292,10 +285,10 @@ extern "C" PluginBackendApiErrorType WUPSGetSectionMemoryAddresses(plugin_contai
|
||||
if (handle == 0 || textAddress == nullptr || dataAddress == nullptr) {
|
||||
return PLUGIN_BACKEND_API_ERROR_INVALID_ARG;
|
||||
}
|
||||
for (auto &curContainer : gLoadedPlugins) {
|
||||
for (const auto &curContainer : gLoadedPlugins) {
|
||||
if (curContainer->getHandle() == handle) {
|
||||
*textAddress = curContainer->getPluginInformation()->getTextMemoryAddress();
|
||||
*dataAddress = curContainer->getPluginInformation()->getDataMemoryAddress();
|
||||
*textAddress = (void *) curContainer->getPluginInformation().getTextMemory().data();
|
||||
*dataAddress = (void *) curContainer->getPluginInformation().getDataMemory().data();
|
||||
return PLUGIN_BACKEND_API_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <coreinit/dynload.h>
|
||||
#include <cstdint>
|
||||
#include <forward_list>
|
||||
#include <malloc.h>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -60,17 +62,16 @@ std::shared_ptr<T> make_shared_nothrow(Args &&...args) noexcept(noexcept(T(std::
|
||||
return std::shared_ptr<T>(new (std::nothrow) T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<typename T, class Allocator, class Predicate>
|
||||
bool remove_locked_first_if(std::mutex &mutex, std::forward_list<T, Allocator> &list, Predicate pred) {
|
||||
template<typename Container, typename Predicate>
|
||||
bool remove_locked_first_if(std::mutex &mutex, Container &container, Predicate pred) {
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
auto oit = list.before_begin(), it = std::next(oit);
|
||||
while (it != list.end()) {
|
||||
if (pred(*it)) {
|
||||
list.erase_after(oit);
|
||||
return true;
|
||||
}
|
||||
oit = it++;
|
||||
|
||||
auto it = std::find_if(container.begin(), container.end(), pred);
|
||||
if (it != container.end()) {
|
||||
container.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user