Skip to content

Commit

Permalink
Merge pull request #27 from apple1417/master
Browse files Browse the repository at this point in the history
migrate to string views where possible
  • Loading branch information
apple1417 authored Nov 19, 2023
2 parents ac712ab + 8db5c52 commit b26bc7b
Show file tree
Hide file tree
Showing 34 changed files with 304 additions and 250 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ sdk can work with multiple (somewhat similar) UE versions from a single binary,
it how exactly to hook everything. The easiest way is to let it autodetect.

```cpp
unrealsdk::init(unrealsdk::game::select_based_on_executable());
unrealsdk::init(unrealsdk::game::select_based_on_executable);
```
If this doesn't work correctly, you can always implement your own version (and then merge it back
into this project).
Expand Down
2 changes: 1 addition & 1 deletion common_cmake
2 changes: 1 addition & 1 deletion src/shared/dllmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ HMODULE this_module;
*/
DWORD WINAPI startup_thread(LPVOID /*unused*/) {
try {
unrealsdk::init(unrealsdk::game::select_based_on_executable());
unrealsdk::init(unrealsdk::game::select_based_on_executable);
} catch (std::exception& ex) {
LOG(ERROR, "Exception occurred while initializing the sdk: {}", ex.what());
}
Expand Down
71 changes: 33 additions & 38 deletions src/unrealsdk/commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace {

#ifndef UNREALSDK_IMPORTING

std::unordered_map<std::wstring, DLLSafeCallback*> commands{};
utils::StringViewMap<std::wstring, DLLSafeCallback*> commands{};

#endif

Expand All @@ -22,74 +22,69 @@ UNREALSDK_CAPI(bool, add_command, const wchar_t* cmd, size_t size, DLLSafeCallba
#endif
#ifndef UNREALSDK_IMPORTING
UNREALSDK_CAPI(bool, add_command, const wchar_t* cmd, size_t size, DLLSafeCallback* callback) {
std::wstring lower_cmd{cmd, size};
std::transform(lower_cmd.begin(), lower_cmd.end(), lower_cmd.begin(), &std::towlower);
std::wstring lower_cmd(size, '\0');
std::transform(cmd, cmd + size, lower_cmd.begin(), &std::towlower);

if (commands.contains(lower_cmd)) {
return false;
}

commands[std::move(lower_cmd)] = callback;
commands.emplace(lower_cmd, callback);
return true;
}
#endif

bool add_command(const std::wstring& cmd, const Callback& callback) {
bool add_command(std::wstring_view cmd, const Callback& callback) {
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
return UNREALSDK_MANGLE(add_command)(cmd.c_str(), cmd.size(), new DLLSafeCallback(callback));
return UNREALSDK_MANGLE(add_command)(cmd.data(), cmd.size(), new DLLSafeCallback(callback));
}

#ifdef UNREALSDK_SHARED
UNREALSDK_CAPI(bool, has_command, const wchar_t* func, size_t size);
UNREALSDK_CAPI(bool, has_command, const wchar_t* cmd, size_t size);
#endif
#ifdef UNREALSDK_IMPORTING
bool has_command(const std::wstring& cmd) {
return UNREALSDK_MANGLE(has_command)(cmd.c_str(), cmd.size());
}
#else
bool has_command(const std::wstring& cmd) {
return commands.contains(cmd);
#ifndef UNREALSDK_IMPORTING
UNREALSDK_CAPI(bool, has_command, const wchar_t* cmd, size_t size) {
const std::wstring_view view{cmd, size};
return commands.contains(view);
}
#endif
#ifdef UNREALSDK_EXPORTING
UNREALSDK_CAPI(bool, has_command, const wchar_t* func, size_t size) {
return has_command({func, size});

bool has_command(std::wstring_view cmd) {
return UNREALSDK_MANGLE(has_command)(cmd.data(), cmd.size());
}
#endif

#ifdef UNREALSDK_SHARED
UNREALSDK_CAPI(bool, remove_command, const wchar_t* func, size_t size);
UNREALSDK_CAPI(bool, remove_command, const wchar_t* cmd, size_t size);
#endif
#ifdef UNREALSDK_IMPORTING
bool remove_command(const std::wstring& cmd) {
return UNREALSDK_MANGLE(remove_command)(cmd.c_str(), cmd.size());
}
#else
bool remove_command(const std::wstring& cmd) {
if (!commands.contains(cmd)) {
#ifndef UNREALSDK_IMPORTING
UNREALSDK_CAPI(bool, remove_command, const wchar_t* cmd, size_t size) {
const std::wstring_view view{cmd, size};
auto iter = commands.find(view);

if (iter == commands.end()) {
return false;
}

commands[cmd]->destroy();
commands.erase(cmd);
iter->second->destroy();
commands.erase(iter);

return true;
}
#endif
#ifdef UNREALSDK_EXPORTING
UNREALSDK_CAPI(bool, remove_command, const wchar_t* func, size_t size) {
return remove_command({func, size});

bool remove_command(std::wstring_view cmd) {
return UNREALSDK_MANGLE(remove_command)(cmd.data(), cmd.size());
}
#endif

namespace impl {

#ifndef UNREALSDK_IMPORTING

std::pair<DLLSafeCallback*, size_t> find_matching_command(const std::wstring& line) {
if (commands.contains(NEXT_LINE)) {
auto callback = commands[NEXT_LINE];
commands.erase(NEXT_LINE);
std::pair<DLLSafeCallback*, size_t> find_matching_command(std::wstring_view line) {
auto iter = commands.find(NEXT_LINE);
if (iter != commands.end()) {
auto callback = iter->second;
commands.erase(iter);
return {callback, 0};
}

Expand All @@ -100,8 +95,8 @@ std::pair<DLLSafeCallback*, size_t> find_matching_command(const std::wstring& li

auto cmd_end = std::find_if(non_space, line.end(), &std::iswspace);

std::wstring cmd{non_space, cmd_end};
std::transform(cmd.begin(), cmd.end(), cmd.begin(), &std::towlower);
std::wstring cmd(cmd_end - non_space, '\0');
std::transform(non_space, cmd_end, cmd.begin(), &std::towlower);

return commands.contains(cmd) ? std::pair{commands[cmd], cmd_end - line.begin()}
: std::pair{nullptr, 0};
Expand Down
8 changes: 4 additions & 4 deletions src/unrealsdk/commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,23 @@ using Callback = DLLSafeCallback::InnerFunc;
* @param callback The callback for when the command is run.
* @return True if successfully added, false if an identical command already exists.
*/
bool add_command(const std::wstring& cmd, const Callback& callback);
bool add_command(std::wstring_view cmd, const Callback& callback);

/**
* @brief Check if a custom console command is registered.
*
* @param cmd The command to match.
* @return True if the command is registered.
*/
bool has_command(const std::wstring& cmd);
bool has_command(std::wstring_view cmd);

/**
* @brief Removes a custom console command.
*
* @param cmd The command to remove.
* @return True if successfully removed, false if no such command exists.
*/
bool remove_command(const std::wstring& cmd);
bool remove_command(std::wstring_view cmd);

namespace impl { // These functions are only relevant when implementing a game hook

Expand All @@ -73,7 +73,7 @@ namespace impl { // These functions are only relevant when implementing a game
* @return A pair of the callback to run and the offset to pass to it, or of nullptr and 0 if there
* was no match.
*/
std::pair<DLLSafeCallback*, size_t> find_matching_command(const std::wstring& line);
std::pair<DLLSafeCallback*, size_t> find_matching_command(std::wstring_view line);

#endif
} // namespace impl
Expand Down
29 changes: 9 additions & 20 deletions src/unrealsdk/env.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace unrealsdk::env {
#ifndef UNREALSDK_IMPORTING

void load_file(void) {
std::ifstream stream{utils::get_this_dll_dir() / get(ENV_FILE, defaults::ENV_FILE)};
std::ifstream stream{utils::get_this_dll().parent_path() / get(ENV_FILE, defaults::ENV_FILE)};

std::string line;
while (std::getline(stream, line)) {
Expand All @@ -33,29 +33,18 @@ bool defined(env_var_key env_var) {
return GetEnvironmentVariableA(env_var, nullptr, 0) != 0;
}

std::string get(env_var_key env_var, const std::string& default_value) {
auto size = GetEnvironmentVariableA(env_var, nullptr, 0);
if (size == 0) {
return default_value;
std::string get(env_var_key env_var, std::string_view default_value) {
auto num_chars = GetEnvironmentVariableA(env_var, nullptr, 0);
if (num_chars == 0) {
return std::string{default_value};
}

// NOLINTBEGIN(cppcoreguidelines-no-malloc, cppcoreguidelines-owning-memory)
auto buf = reinterpret_cast<char*>(malloc(size * sizeof(char)));
if (buf == nullptr) {
return default_value;
// The returned size on failure includes a null terminator, but on success does not.
std::string ret(num_chars - 1, '\0');
if (GetEnvironmentVariableA(env_var, ret.data(), num_chars) != (num_chars - 1)) {
return std::string{default_value};
}

if (GetEnvironmentVariableA(env_var, buf, size) == 0) {
free(buf);
return default_value;
}

// Size includes the null terminator
std::string ret{buf, size - 1};

free(buf);
// NOLINTEND(cppcoreguidelines-no-malloc, cppcoreguidelines-owning-memory)

return ret;
}

Expand Down
4 changes: 3 additions & 1 deletion src/unrealsdk/env.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef UNREALSDK_ENV_H
#define UNREALSDK_ENV_H

#include "unrealsdk/pch.h"

namespace unrealsdk::env {
using env_var_key = const char*;

Expand Down Expand Up @@ -67,7 +69,7 @@ bool defined(env_var_key env_var);
* @param default_value The default value to return if not defined.
* @return The environment variable's value.
*/
std::string get(env_var_key env_var, const std::string& default_value = "");
std::string get(env_var_key env_var, std::string_view default_value = "");

/**
* @brief Gets the value of an environment variable as a number.
Expand Down
2 changes: 1 addition & 1 deletion src/unrealsdk/game/bl2/bl2.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ template <>
struct GameTraits<BL2Hook> {
static constexpr auto NAME = "Borderlands 2";

static bool matches_executable(const std::string& executable) {
static bool matches_executable(std::string_view executable) {
return executable == "Borderlands2.exe" || executable == "TinyTina.exe";
}
};
Expand Down
2 changes: 1 addition & 1 deletion src/unrealsdk/game/bl3/bl3.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ template <>
struct GameTraits<BL3Hook> {
static constexpr auto NAME = "Borderlands 3";

static bool matches_executable(const std::string& executable) {
static bool matches_executable(std::string_view executable) {
return executable == "Borderlands3.exe" || executable == "Wonderlands.exe";
}
};
Expand Down
2 changes: 1 addition & 1 deletion src/unrealsdk/game/bl3/console.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ bool inject_console_hook(hook_manager::Details& hook) {
console_key = existing_console_key;
} else {
auto wanted_console_key = env::get(env::CONSOLE_KEY, env::defaults::CONSOLE_KEY);
console_key = {wanted_console_key};
console_key = FName{wanted_console_key};

inner_obj->get<UStructProperty>(L"ConsoleKey"_fn)
.set<UNameProperty>(L"KeyName"_fn, console_key);
Expand Down
14 changes: 3 additions & 11 deletions src/unrealsdk/game/selector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "unrealsdk/game/bl2/bl2.h"
#include "unrealsdk/game/bl3/bl3.h"
#include "unrealsdk/game/tps/tps.h"
#include "unrealsdk/utils.h"

#ifndef UNREALSDK_IMPORTING

Expand Down Expand Up @@ -37,7 +38,7 @@ using all_known_games = std::tuple<BL2Hook, TPSHook>;
* @param executable The executable name to match against.
*/
template <int i = 0>
std::unique_ptr<AbstractHook> find_correct_hook(const std::string& executable) {
std::unique_ptr<AbstractHook> find_correct_hook(std::string_view executable) {
if constexpr (i >= std::tuple_size_v<all_known_games>) {
throw std::runtime_error("Failed to find compatible game hook!");
} else {
Expand All @@ -53,16 +54,7 @@ std::unique_ptr<AbstractHook> find_correct_hook(const std::string& executable) {
} // namespace

std::unique_ptr<AbstractHook> select_based_on_executable(void) {
std::filesystem::path exe_path{};

std::array<char, FILENAME_MAX> buf{};
if (GetModuleFileNameA(nullptr, buf.data(), (DWORD)buf.size()) > 0) {
exe_path = std::filesystem::path(buf.data());
} else {
LOG(ERROR, "Failed to get main executable's path!");
}

auto executable = env::get(env::GAME_OVERRIDE, exe_path.filename().string());
auto executable = env::get(env::GAME_OVERRIDE, utils::get_executable().filename().string());
return find_correct_hook(executable);
}

Expand Down
2 changes: 1 addition & 1 deletion src/unrealsdk/game/selector.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ struct GameTraits {
* @param executable The executable name to match.
* @return True if the hook matches it.
*/
static bool matches_executable(const std::string& executable);
static bool matches_executable(std::string_view executable);
};

} // namespace unrealsdk::game
Expand Down
2 changes: 1 addition & 1 deletion src/unrealsdk/game/tps/tps.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ template <>
struct GameTraits<TPSHook> {
static constexpr auto NAME = "TPS";

static bool matches_executable(const std::string& executable) {
static bool matches_executable(std::string_view executable) {
return executable == "BorderlandsPreSequel.exe";
}
};
Expand Down
Loading

0 comments on commit b26bc7b

Please sign in to comment.