mirror of
https://github.com/alicealys/t5-gsc-utils.git
synced 2025-04-19 12:32:53 +00:00
Merge pull request #15 from diamante0018/main
feature(user_info): allow GSC to edit name/clantag
This commit is contained in:
commit
964d6dc0b7
7
.github/workflows/build.yml
vendored
7
.github/workflows/build.yml
vendored
@ -19,7 +19,7 @@ jobs:
|
|||||||
- Release
|
- Release
|
||||||
steps:
|
steps:
|
||||||
- name: Check out files
|
- name: Check out files
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
@ -27,10 +27,9 @@ jobs:
|
|||||||
lfs: false
|
lfs: false
|
||||||
|
|
||||||
- name: Add msbuild to PATH
|
- name: Add msbuild to PATH
|
||||||
uses: microsoft/setup-msbuild@v1.0.2
|
uses: microsoft/setup-msbuild@v1.3.1
|
||||||
|
|
||||||
- name: Generate project files
|
- name: Generate project files
|
||||||
#run: tools/premake5 vs2022 --ci-build
|
|
||||||
run: tools/premake5 vs2022
|
run: tools/premake5 vs2022
|
||||||
|
|
||||||
- name: Set up problem matching
|
- name: Set up problem matching
|
||||||
@ -40,7 +39,7 @@ jobs:
|
|||||||
run: msbuild /m /v:minimal /p:Configuration=${{matrix.configuration}} /p:PlatformTarget=x86 build/t5-gsc-utils.sln
|
run: msbuild /m /v:minimal /p:Configuration=${{matrix.configuration}} /p:PlatformTarget=x86 build/t5-gsc-utils.sln
|
||||||
|
|
||||||
- name: Upload ${{matrix.configuration}} binaries
|
- name: Upload ${{matrix.configuration}} binaries
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3.1.3
|
||||||
with:
|
with:
|
||||||
name: ${{matrix.configuration}} binaries
|
name: ${{matrix.configuration}} binaries
|
||||||
path: |
|
path: |
|
||||||
|
2
deps/curl
vendored
2
deps/curl
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 134963a5efdc3906257c88ce62dba8d46c292908
|
Subproject commit ab885eccd6c82a949e21cfab9af778c0fd44d0ae
|
@ -92,7 +92,6 @@ workspace "t5-gsc-utils"
|
|||||||
|
|
||||||
pchheader "stdinc.hpp"
|
pchheader "stdinc.hpp"
|
||||||
pchsource "src/stdinc.cpp"
|
pchsource "src/stdinc.cpp"
|
||||||
buildoptions { "/Zm100 -Zm100" }
|
|
||||||
|
|
||||||
dependencies.imports()
|
dependencies.imports()
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ namespace command
|
|||||||
|
|
||||||
game::CmdArgs* get_cmd_args()
|
game::CmdArgs* get_cmd_args()
|
||||||
{
|
{
|
||||||
return reinterpret_cast<game::CmdArgs*>(game::Sys_GetValue(4));
|
return static_cast<game::CmdArgs*>(game::Sys_GetValue(4));
|
||||||
}
|
}
|
||||||
|
|
||||||
void main_handler()
|
void main_handler()
|
||||||
@ -315,7 +315,7 @@ namespace command
|
|||||||
gsc::method::add("tell", [](const scripting::entity& player, const std::string& msg)
|
gsc::method::add("tell", [](const scripting::entity& player, const std::string& msg)
|
||||||
{
|
{
|
||||||
const auto entref = player.get_entity_reference();
|
const auto entref = player.get_entity_reference();
|
||||||
if (entref.classnum != 0 || entref.entnum >= 18)
|
if (entref.classnum)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Not a player entity");
|
throw std::runtime_error("Not a player entity");
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,9 @@
|
|||||||
|
|
||||||
#include "gsc.hpp"
|
#include "gsc.hpp"
|
||||||
|
|
||||||
#include "scheduler.hpp"
|
|
||||||
#include "scripting.hpp"
|
|
||||||
|
|
||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
#include <utils/string.hpp>
|
|
||||||
#include <utils/io.hpp>
|
#include <utils/io.hpp>
|
||||||
|
#include <utils/string.hpp>
|
||||||
|
|
||||||
namespace gsc
|
namespace gsc
|
||||||
{
|
{
|
||||||
@ -309,7 +306,7 @@ namespace gsc
|
|||||||
gsc::function::add("toint", [](const std::string& str, const scripting::variadic_args& va)
|
gsc::function::add("toint", [](const std::string& str, const scripting::variadic_args& va)
|
||||||
{
|
{
|
||||||
auto radix = 10;
|
auto radix = 10;
|
||||||
if (va.size() > 0)
|
if (!va.empty())
|
||||||
{
|
{
|
||||||
radix = va[0];
|
radix = va[0];
|
||||||
}
|
}
|
||||||
@ -320,7 +317,7 @@ namespace gsc
|
|||||||
gsc::function::add("os::date", [](const scripting::variadic_args& va)
|
gsc::function::add("os::date", [](const scripting::variadic_args& va)
|
||||||
{
|
{
|
||||||
std::string format = "%Y-%m-%dT%H:%M:%S%z";
|
std::string format = "%Y-%m-%dT%H:%M:%S%z";
|
||||||
if (va.size() > 0)
|
if (!va.empty())
|
||||||
{
|
{
|
||||||
format = va[0].as<std::string>();
|
format = va[0].as<std::string>();
|
||||||
}
|
}
|
||||||
|
143
src/component/user_info.cpp
Normal file
143
src/component/user_info.cpp
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
#include <stdinc.hpp>
|
||||||
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
|
#include "game/game.hpp"
|
||||||
|
|
||||||
|
#include "gsc.hpp"
|
||||||
|
|
||||||
|
#include <utils/hook.hpp>
|
||||||
|
#include <utils/info_string.hpp>
|
||||||
|
|
||||||
|
namespace user_info
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
using user_info_map = std::unordered_map<std::string, std::string>;
|
||||||
|
std::unordered_map<int, user_info_map> user_info_overrides;
|
||||||
|
|
||||||
|
utils::hook::detour scr_shutdown_system_hook;
|
||||||
|
|
||||||
|
void clear_client_overrides(const int client_num)
|
||||||
|
{
|
||||||
|
user_info_overrides[client_num].clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_all_overrides()
|
||||||
|
{
|
||||||
|
user_info_overrides.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_disconnect_stub(const int client_num)
|
||||||
|
{
|
||||||
|
clear_client_overrides(client_num);
|
||||||
|
game::ClientDisconnect(client_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scr_shutdown_system_stub(const game::scriptInstance_t inst, const unsigned char sys, const int b_complete)
|
||||||
|
{
|
||||||
|
clear_all_overrides();
|
||||||
|
scr_shutdown_system_hook.invoke<void>(inst, sys, b_complete);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sv_get_user_info_stub(const int index, char* buffer, const int buffer_size)
|
||||||
|
{
|
||||||
|
game::SV_GetUserinfo(index, buffer, buffer_size);
|
||||||
|
|
||||||
|
utils::info_string map(buffer);
|
||||||
|
|
||||||
|
if (!user_info_overrides.contains(index))
|
||||||
|
{
|
||||||
|
user_info_overrides[index] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& [key, val] : user_info_overrides[index])
|
||||||
|
{
|
||||||
|
if (val.empty())
|
||||||
|
{
|
||||||
|
map.remove(key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
map.set(key, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto user_info = map.build();
|
||||||
|
strncpy_s(buffer, buffer_size, user_info.data(), _TRUNCATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class component final : public component_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void post_unpack() override
|
||||||
|
{
|
||||||
|
utils::hook::call(SELECT_VALUE(0x5D38EB, 0x4A75E2), sv_get_user_info_stub);
|
||||||
|
utils::hook::call(SELECT_VALUE(0x67FFE9, 0x548DB0), sv_get_user_info_stub);
|
||||||
|
|
||||||
|
utils::hook::call(SELECT_VALUE(0x4F3931, 0x5DC953), client_disconnect_stub);
|
||||||
|
|
||||||
|
scr_shutdown_system_hook.create(SELECT_VALUE(0x596D40, 0x540780), scr_shutdown_system_stub);
|
||||||
|
|
||||||
|
gsc::method::add_multiple([](const scripting::entity& player, const std::string& name) -> void
|
||||||
|
{
|
||||||
|
const auto entref = player.get_entity_reference();
|
||||||
|
if (entref.classnum)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Not a player entity");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.empty())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("set_name: Illegal parameter!");
|
||||||
|
}
|
||||||
|
|
||||||
|
user_info_overrides[entref.entnum]["name"] = name;
|
||||||
|
game::ClientUserinfoChanged(entref.entnum);
|
||||||
|
}, "user_info::set_name", "set_name");
|
||||||
|
|
||||||
|
gsc::method::add_multiple([](const scripting::entity& player) -> void
|
||||||
|
{
|
||||||
|
const auto entref = player.get_entity_reference();
|
||||||
|
if (entref.classnum)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Not a player entity");
|
||||||
|
}
|
||||||
|
|
||||||
|
user_info_overrides[entref.entnum].erase("name");
|
||||||
|
game::ClientUserinfoChanged(entref.entnum);
|
||||||
|
}, "user_info::reset_name", "reset_name");
|
||||||
|
|
||||||
|
gsc::method::add_multiple([](const scripting::entity& player, const std::string& tag) -> void
|
||||||
|
{
|
||||||
|
const auto entref = player.get_entity_reference();
|
||||||
|
if (entref.classnum)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Not a player entity");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag.empty())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("set_clantag: Illegal parameter!");
|
||||||
|
}
|
||||||
|
|
||||||
|
user_info_overrides[entref.entnum]["clanAbbrev"] = tag;
|
||||||
|
game::ClientUserinfoChanged(entref.entnum);
|
||||||
|
}, "user_info::set_clantag", "set_clantag");
|
||||||
|
|
||||||
|
gsc::method::add_multiple([](const scripting::entity& player) -> void
|
||||||
|
{
|
||||||
|
const auto entref = player.get_entity_reference();
|
||||||
|
if (entref.classnum)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Not a player entity");
|
||||||
|
}
|
||||||
|
|
||||||
|
user_info_overrides[entref.entnum].erase("clanAbbrev");
|
||||||
|
game::ClientUserinfoChanged(entref.entnum);
|
||||||
|
}, "user_info::reset_clantag", "reset_clantag");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_COMPONENT(user_info::component)
|
@ -17,8 +17,6 @@ namespace game
|
|||||||
WEAK symbol<const char*(int index)> Cmd_Argv{0x0, 0x0};
|
WEAK symbol<const char*(int index)> Cmd_Argv{0x0, 0x0};
|
||||||
WEAK symbol<void(const char* cmdName)> Cmd_RemoveCommand{0x5F1A90, 0x527EA0};
|
WEAK symbol<void(const char* cmdName)> Cmd_RemoveCommand{0x5F1A90, 0x527EA0};
|
||||||
|
|
||||||
WEAK symbol<void(int clientNum)> ClientUserInfoChanged{0x0, 0x0};
|
|
||||||
|
|
||||||
WEAK symbol<void(errorParm_t code, const char* fmt, ...)> Com_Error{0x651D90, 0x627380};
|
WEAK symbol<void(errorParm_t code, const char* fmt, ...)> Com_Error{0x651D90, 0x627380};
|
||||||
WEAK symbol<void(int channel, const char* fmt, ...)> Com_Printf{0x43BF30, 0x4126C0};
|
WEAK symbol<void(int channel, const char* fmt, ...)> Com_Printf{0x43BF30, 0x4126C0};
|
||||||
WEAK symbol<void(const char* fmt, ...)> Com_Printf_NoFilter{0x566BC0, 0x64C260};
|
WEAK symbol<void(const char* fmt, ...)> Com_Printf_NoFilter{0x566BC0, 0x64C260};
|
||||||
@ -107,10 +105,14 @@ namespace game
|
|||||||
|
|
||||||
WEAK symbol<unsigned int(scriptInstance_t inst, unsigned int localId, const char* pos, unsigned int paramcount)> VM_Execute{0x8ACE60, 0x8EADE0};
|
WEAK symbol<unsigned int(scriptInstance_t inst, unsigned int localId, const char* pos, unsigned int paramcount)> VM_Execute{0x8ACE60, 0x8EADE0};
|
||||||
|
|
||||||
|
WEAK symbol<void(int index, char* buffer, int bufferSize)> SV_GetUserinfo{0x50DCD0, 0x6916A0};
|
||||||
WEAK symbol<void(int clientNum, const char* reason)> SV_GameDropClient{0x0, 0x0};
|
WEAK symbol<void(int clientNum, const char* reason)> SV_GameDropClient{0x0, 0x0};
|
||||||
WEAK symbol<bool(int clientNum)> SV_IsTestClient{0x0, 0x0};
|
WEAK symbol<bool(int clientNum)> SV_IsTestClient{0x0, 0x0};
|
||||||
WEAK symbol<void(int clientNum, int type, const char* command)> SV_GameSendServerCommand{0x543CF0, 0x6B8730};
|
WEAK symbol<void(int clientNum, int type, const char* command)> SV_GameSendServerCommand{0x543CF0, 0x6B8730};
|
||||||
|
|
||||||
|
WEAK symbol<void(int clientNum)> ClientDisconnect{0x4F4000, 0x66FA00};
|
||||||
|
WEAK symbol<void(int clientNum)> ClientUserinfoChanged{0x67FFC0, 0x548D80};
|
||||||
|
|
||||||
WEAK symbol<void*(int valueIndex)> Sys_GetValue{0x67D4F0, 0x529EB0};
|
WEAK symbol<void*(int valueIndex)> Sys_GetValue{0x67D4F0, 0x529EB0};
|
||||||
WEAK symbol<int()> Sys_Milliseconds{0x0, 0x0};
|
WEAK symbol<int()> Sys_Milliseconds{0x0, 0x0};
|
||||||
|
|
||||||
|
@ -11,24 +11,25 @@
|
|||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <mutex>
|
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <fstream>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <functional>
|
|
||||||
#include <regex>
|
|
||||||
#include <queue>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <map>
|
|
||||||
#include <csetjmp>
|
#include <csetjmp>
|
||||||
#include <atlcomcli.h>
|
|
||||||
#include <variant>
|
#include <algorithm>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <mutex>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <queue>
|
||||||
|
#include <regex>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <variant>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifdef max
|
#ifdef max
|
||||||
#undef max
|
#undef max
|
||||||
|
@ -101,12 +101,5 @@ namespace utils::http
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (helper.exception)
|
|
||||||
{
|
|
||||||
std::rethrow_exception(helper.exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
67
src/utils/info_string.cpp
Normal file
67
src/utils/info_string.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#include <stdinc.hpp>
|
||||||
|
|
||||||
|
#include "info_string.hpp"
|
||||||
|
#include "string.hpp"
|
||||||
|
|
||||||
|
namespace utils
|
||||||
|
{
|
||||||
|
info_string::info_string(const std::string& buffer)
|
||||||
|
{
|
||||||
|
this->parse(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void info_string::set(const std::string& key, const std::string& value)
|
||||||
|
{
|
||||||
|
this->key_value_pairs_[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void info_string::remove(const std::string& key)
|
||||||
|
{
|
||||||
|
this->key_value_pairs_.erase(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string info_string::get(const std::string& key) const
|
||||||
|
{
|
||||||
|
const auto value = this->key_value_pairs_.find(key);
|
||||||
|
if (value != this->key_value_pairs_.end())
|
||||||
|
{
|
||||||
|
return value->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void info_string::parse(std::string buffer)
|
||||||
|
{
|
||||||
|
if (buffer[0] == '\\')
|
||||||
|
{
|
||||||
|
buffer = buffer.substr(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto key_values = string::split(buffer, '\\');
|
||||||
|
for (size_t i = 0; !key_values.empty() && i < (key_values.size() - 1); i += 2)
|
||||||
|
{
|
||||||
|
const auto& key = key_values[i];
|
||||||
|
const auto& value = key_values[i + 1];
|
||||||
|
|
||||||
|
if (!this->key_value_pairs_.contains(key))
|
||||||
|
{
|
||||||
|
this->key_value_pairs_[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string info_string::build() const
|
||||||
|
{
|
||||||
|
std::string info_string;
|
||||||
|
for (const auto& [key, val] : this->key_value_pairs_)
|
||||||
|
{
|
||||||
|
info_string.append("\\");
|
||||||
|
info_string.append(key);
|
||||||
|
info_string.append("\\");
|
||||||
|
info_string.append(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return info_string;
|
||||||
|
}
|
||||||
|
}
|
25
src/utils/info_string.hpp
Normal file
25
src/utils/info_string.hpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace utils
|
||||||
|
{
|
||||||
|
class info_string
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
info_string() = default;
|
||||||
|
info_string(const std::string& buffer);
|
||||||
|
|
||||||
|
void set(const std::string& key, const std::string& value);
|
||||||
|
void remove(const std::string& key);
|
||||||
|
|
||||||
|
[[nodiscard]] std::string get(const std::string& key) const;
|
||||||
|
[[nodiscard]] std::string build() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::string, std::string> key_value_pairs_{};
|
||||||
|
|
||||||
|
void parse(std::string buffer);
|
||||||
|
};
|
||||||
|
}
|
@ -35,7 +35,7 @@ namespace utils::string
|
|||||||
|
|
||||||
std::string to_lower(std::string text)
|
std::string to_lower(std::string text)
|
||||||
{
|
{
|
||||||
std::transform(text.begin(), text.end(), text.begin(), [](const char input)
|
std::transform(text.begin(), text.end(), text.begin(), [](const unsigned char input)
|
||||||
{
|
{
|
||||||
return static_cast<char>(tolower(input));
|
return static_cast<char>(tolower(input));
|
||||||
});
|
});
|
||||||
@ -45,7 +45,7 @@ namespace utils::string
|
|||||||
|
|
||||||
std::string to_upper(std::string text)
|
std::string to_upper(std::string text)
|
||||||
{
|
{
|
||||||
std::transform(text.begin(), text.end(), text.begin(), [](const char input)
|
std::transform(text.begin(), text.end(), text.begin(), [](const unsigned char input)
|
||||||
{
|
{
|
||||||
return static_cast<char>(toupper(input));
|
return static_cast<char>(toupper(input));
|
||||||
});
|
});
|
||||||
@ -86,34 +86,23 @@ namespace utils::string
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void strip(const char* in, char* out, int max)
|
std::string replace(std::string str, const std::string& from, const std::string& to)
|
||||||
{
|
{
|
||||||
if (!in || !out) return;
|
if (from.empty())
|
||||||
|
|
||||||
max--;
|
|
||||||
auto current = 0;
|
|
||||||
while (*in != 0 && current < max)
|
|
||||||
{
|
{
|
||||||
const auto color_index = (*(in + 1) - 48) >= 0xC ? 7 : (*(in + 1) - 48);
|
return str;
|
||||||
|
|
||||||
if (*in == '^' && (color_index != 7 || *(in + 1) == '7'))
|
|
||||||
{
|
|
||||||
++in;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*out = *in;
|
|
||||||
++out;
|
|
||||||
++current;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
++in;
|
size_t start_pos = 0;
|
||||||
}
|
while ((start_pos = str.find(from, start_pos)) != std::string::npos)
|
||||||
*out = '\0';
|
{
|
||||||
|
str.replace(start_pos, from.length(), to);
|
||||||
|
start_pos += to.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable: 4100)
|
|
||||||
std::string convert(const std::wstring& wstr)
|
std::string convert(const std::wstring& wstr)
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
@ -139,24 +128,6 @@ namespace utils::string
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#pragma warning(pop)
|
|
||||||
|
|
||||||
std::string replace(std::string str, const std::string& from, const std::string& to)
|
|
||||||
{
|
|
||||||
if (from.empty())
|
|
||||||
{
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t start_pos = 0;
|
|
||||||
while ((start_pos = str.find(from, start_pos)) != std::string::npos)
|
|
||||||
{
|
|
||||||
str.replace(start_pos, from.length(), to);
|
|
||||||
start_pos += to.length();
|
|
||||||
}
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string get_timestamp()
|
std::string get_timestamp()
|
||||||
{
|
{
|
||||||
|
@ -90,12 +90,10 @@ namespace utils::string
|
|||||||
|
|
||||||
std::string dump_hex(const std::string& data, const std::string& separator = " ");
|
std::string dump_hex(const std::string& data, const std::string& separator = " ");
|
||||||
|
|
||||||
void strip(const char* in, char* out, int max);
|
std::string replace(std::string str, const std::string& from, const std::string& to);
|
||||||
|
|
||||||
std::string convert(const std::wstring& wstr);
|
std::string convert(const std::wstring& wstr);
|
||||||
std::wstring convert(const std::string& str);
|
std::wstring convert(const std::string& str);
|
||||||
|
|
||||||
std::string replace(std::string str, const std::string& from, const std::string& to);
|
|
||||||
|
|
||||||
std::string get_timestamp();
|
std::string get_timestamp();
|
||||||
}
|
}
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user