Use new format library and sort utils

This commit is contained in:
momo5502
2016-07-11 17:14:58 +02:00
parent 766fd631b1
commit 9562285ed7
59 changed files with 13009 additions and 12950 deletions

3
.gitmodules vendored
View File

@ -26,3 +26,6 @@
path = deps/mongoose
url = https://github.com/cesanta/mongoose.git
ignore = dirty
[submodule "deps/fmt"]
path = deps/fmt
url = https://github.com/fmtlib/fmt.git

1
deps/fmt vendored Submodule

Submodule deps/fmt added at 4133e501f3

2
deps/protobuf vendored

View File

@ -149,9 +149,10 @@ workspace "iw4x"
filter {}
-- Dependency libraries
links { "zlib", "json11", "pdcurses", "libtomcrypt", "libtommath", "protobuf", "mongoose" }
links { "zlib", "fmt", "json11", "pdcurses", "libtomcrypt", "libtommath", "protobuf", "mongoose" }
includedirs
{
"./deps/fmt",
"./deps/zlib",
"./deps/json11",
"./deps/pdcurses",
@ -163,14 +164,16 @@ workspace "iw4x"
}
-- fix vpaths for protobuf sources
vpaths {
vpaths
{
["*"] = { "./src/**" },
["Proto/Generated"] = { "**.pb.*" }, -- meh.
}
-- Virtual paths
if not _OPTIONS["no-new-structure"] then
vpaths {
vpaths
{
["Headers/*"] = { "./src/**.hpp" },
["Sources/*"] = { "./src/**.cpp" },
["Resource/*"] = { "./src/**.rc" },
@ -184,7 +187,8 @@ workspace "iw4x"
}
-- Pre-build
prebuildcommands {
prebuildcommands
{
"cd %{_MAIN_SCRIPT_DIR}",
"tools\\premake5 generate-buildinfo"
}
@ -211,7 +215,8 @@ workspace "iw4x"
matches = os.matchfiles(path.join("src/Proto/**.proto"))
for i, srcPath in ipairs(matches) do
basename = path.getbasename(srcPath)
files {
files
{
string.format("%%{prj.location}/src/proto/%s.pb.h", basename),
string.format("%%{prj.location}/src/proto/%s.pb.cc", basename),
}
@ -260,6 +265,23 @@ workspace "iw4x"
-- always build as static lib, as json11 doesn't export anything
kind "StaticLib"
-- fmt
project "fmt"
language "C++"
includedirs { "./deps/fmt" }
files
{
"./deps/fmt/fmt/*.cc",
"./deps/fmt/fmt/*.h"
}
-- not our code, ignore POSIX usage warnings for now
warnings "Off"
-- always build as static lib, as fmt doesn't export anything
kind "StaticLib"
-- mongoose
project "mongoose"
language "C"
@ -273,7 +295,7 @@ workspace "iw4x"
-- not our code, ignore POSIX usage warnings for now
warnings "Off"
-- always build as static lib, as json11 doesn't export anything
-- always build as static lib, as mongoose doesn't export anything
kind "StaticLib"

View File

@ -101,9 +101,9 @@ namespace Components
static uint8_t loadLibAStr[] = { 0xB3, 0x90, 0x9E, 0x9B, 0xB3, 0x96, 0x9D, 0x8D, 0x9E, 0x8D, 0x86, 0xBE }; // LoadLibraryA
static uint8_t loadLibWStr[] = { 0xB3, 0x90, 0x9E, 0x9B, 0xB3, 0x96, 0x9D, 0x8D, 0x9E, 0x8D, 0x86, 0xA8 }; // LoadLibraryW
HMODULE kernel32 = GetModuleHandleA(Utils::XORString(std::string(reinterpret_cast<char*>(kernel32Str), sizeof kernel32Str), -1).data());
FARPROC loadLibA = GetProcAddress(kernel32, Utils::XORString(std::string(reinterpret_cast<char*>(loadLibAStr), sizeof loadLibAStr), -1).data());
FARPROC loadLibW = GetProcAddress(kernel32, Utils::XORString(std::string(reinterpret_cast<char*>(loadLibWStr), sizeof loadLibWStr), -1).data());
HMODULE kernel32 = GetModuleHandleA(Utils::String::XORString(std::string(reinterpret_cast<char*>(kernel32Str), sizeof kernel32Str), -1).data());
FARPROC loadLibA = GetProcAddress(kernel32, Utils::String::XORString(std::string(reinterpret_cast<char*>(loadLibAStr), sizeof loadLibAStr), -1).data());
FARPROC loadLibW = GetProcAddress(kernel32, Utils::String::XORString(std::string(reinterpret_cast<char*>(loadLibWStr), sizeof loadLibWStr), -1).data());
AntiCheat::LoadLibHook[0].Initialize(loadLibA, loadLibStub, HOOK_JUMP);
AntiCheat::LoadLibHook[1].Initialize(loadLibW, loadLibStub, HOOK_JUMP);

View File

@ -26,7 +26,7 @@ namespace Assets
return;
}
Components::FileSystem::File iwi(Utils::VA("images/%s.iwi", name.data()));
Components::FileSystem::File iwi(fmt::sprintf("images/%s.iwi", name.data()));
if (!iwi.Exists())
{

View File

@ -4,7 +4,7 @@ namespace Assets
{
void IMaterial::Load(Game::XAssetHeader* header, std::string name, Components::ZoneBuilder::Zone* builder)
{
Components::FileSystem::File materialInfo(Utils::VA("materials/%s.json", name.data()));
Components::FileSystem::File materialInfo(fmt::sprintf("materials/%s.json", name.data()));
if (!materialInfo.Exists()) return;
@ -72,7 +72,7 @@ namespace Assets
}
// Model surface textures are special, they need a special order and whatnot
bool replaceTexture = Utils::StartsWith(name, "mc/");
bool replaceTexture = Utils::String::StartsWith(name, "mc/");
if (replaceTexture)
{
Game::MaterialTextureDef* textureTable = builder->GetAllocator()->AllocateArray<Game::MaterialTextureDef>(baseMaterial->textureCount);

View File

@ -4,7 +4,7 @@ namespace Assets
{
void IXAnimParts::Load(Game::XAssetHeader* header, std::string name, Components::ZoneBuilder::Zone* builder)
{
Components::FileSystem::File animFile(Utils::VA("xanim/%s.iw4xAnim", name.data()));
Components::FileSystem::File animFile(fmt::sprintf("xanim/%s.iw4xAnim", name.data()));
if (animFile.Exists())
{

View File

@ -4,7 +4,7 @@ namespace Assets
{
void IXModel::Load(Game::XAssetHeader* header, std::string name, Components::ZoneBuilder::Zone* builder)
{
Components::FileSystem::File modelFile(Utils::VA("xmodel/%s.iw4xModel", name.data()));
Components::FileSystem::File modelFile(fmt::sprintf("xmodel/%s.iw4xModel", name.data()));
if (modelFile.Exists())
{
@ -44,7 +44,7 @@ namespace Assets
Game::XModelSurfs* surf = builder->GetAllocator()->AllocateArray<Game::XModelSurfs>();
std::memcpy(surf, baseModel->lods[0].surfaces, sizeof(Game::XModelSurfs));
surf->name = builder->GetAllocator()->DuplicateString(Utils::VA("%s1", model->name));
surf->name = builder->GetAllocator()->DuplicateString(fmt::sprintf("%s1", model->name));
surf->surfaces = builder->GetAllocator()->AllocateArray<Game::XSurface>(model->numSurfaces);
surf->numSurfaces = model->numSurfaces;

View File

@ -50,7 +50,7 @@ namespace Components
info->state = Auth::STATE_NEGOTIATING;
info->time = Game::Sys_Milliseconds();
info->challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
info->challenge = fmt::sprintf("%X", Utils::Cryptography::Rand::GenerateInt());
Network::SendCommand(client->addr, "xuidAuthReq", info->challenge);
}
}
@ -78,7 +78,7 @@ namespace Components
if (mseconds < 0) mseconds = 0;
}
Localization::Set("MPUI_SECURITY_INCREASE_MESSAGE", Utils::VA("Increasing security level from %d to %d (est. %s)", Auth::GetSecurityLevel(), Auth::TokenContainer.targetLevel, Utils::FormatTimeSpan(static_cast<int>(mseconds)).data()));
Localization::Set("MPUI_SECURITY_INCREASE_MESSAGE", fmt::sprintf("Increasing security level from %d to %d (est. %s)", Auth::GetSecurityLevel(), Auth::TokenContainer.targetLevel, Utils::String::FormatTimeSpan(static_cast<int>(mseconds)).data()));
}
else if(Auth::TokenContainer.thread.joinable())
{
@ -93,7 +93,7 @@ namespace Components
{
if (Auth::TokenContainer.command.empty())
{
Game::MessageBox(Utils::VA("Your new security level is %d", Auth::GetSecurityLevel()), "Success");
Game::MessageBox(fmt::sprintf("Your new security level is %d", Auth::GetSecurityLevel()), "Success");
}
else
{
@ -152,7 +152,7 @@ namespace Components
cert.set_ctoken(Auth::ComputeToken.ToString());
cert.set_privatekey(Auth::GuidKey.Export(PK_PRIVATE));
Utils::WriteFile("players/guid.dat", cert.SerializeAsString());
Utils::IO::WriteFile("players/guid.dat", cert.SerializeAsString());
}
}
@ -162,7 +162,7 @@ namespace Components
if (!force && Auth::GuidKey.IsValid()) return;
Proto::Auth::Certificate cert;
if (cert.ParseFromString(::Utils::ReadFile("players/guid.dat")))
if (cert.ParseFromString(::Utils::IO::ReadFile("players/guid.dat")))
{
Auth::GuidKey.Import(cert.privatekey(), PK_PRIVATE);
Auth::GuidToken = cert.token();
@ -360,7 +360,7 @@ namespace Components
else
{
info->state = Auth::STATE_INVALID;
Game::SV_KickClientError(client, Utils::VA("Your security level (%d) is lower than the server's security level (%d)", userLevel, ourLevel));
Game::SV_KickClientError(client, fmt::sprintf("Your security level (%d) is lower than the server's security level (%d)", userLevel, ourLevel));
}
}
else
@ -398,10 +398,10 @@ namespace Components
{
uint32_t level = Auth::GetZeroBits(Auth::GuidToken, Auth::GuidKey.GetPublicKey());
Logger::Print("Your current security level is %d\n", level);
Logger::Print("Your security token is: %s\n", Utils::DumpHex(Auth::GuidToken.ToString(), "").data());
Logger::Print("Your computation token is: %s\n", Utils::DumpHex(Auth::ComputeToken.ToString(), "").data());
Logger::Print("Your security token is: %s\n", Utils::String::DumpHex(Auth::GuidToken.ToString(), "").data());
Logger::Print("Your computation token is: %s\n", Utils::String::DumpHex(Auth::ComputeToken.ToString(), "").data());
Toast::Show("cardicon_locked", "^5Security Level", Utils::VA("Your security level is %d", level), 3000);
Toast::Show("cardicon_locked", "^5Security Level", fmt::sprintf("Your security level is %d", level), 3000);
}
else
{

View File

@ -34,7 +34,7 @@ namespace Components
void Command::Add(const char* name, Command::Callback* callback)
{
std::string command = Utils::StrToLower(name);
std::string command = Utils::String::StrToLower(name);
if (Command::FunctionMap.find(command) == Command::FunctionMap.end())
{
@ -46,7 +46,7 @@ namespace Components
void Command::AddSV(const char* name, Command::Callback* callback)
{
std::string command = Utils::StrToLower(name);
std::string command = Utils::String::StrToLower(name);
if (Command::FunctionMapSV.find(command) == Command::FunctionMapSV.end())
{
@ -98,7 +98,7 @@ namespace Components
{
Command::Params params(false, *Game::cmd_id);
std::string command = Utils::StrToLower(params[0]);
std::string command = Utils::String::StrToLower(params[0]);
if (Command::FunctionMap.find(command) != Command::FunctionMap.end())
{
@ -110,7 +110,7 @@ namespace Components
{
Command::Params params(true, *Game::cmd_id_sv);
std::string command = Utils::StrToLower(params[0]);
std::string command = Utils::String::StrToLower(params[0]);
if (Command::FunctionMapSV.find(command) != Command::FunctionMapSV.end())
{

View File

@ -134,7 +134,7 @@ namespace Components
return false;
}
data = Utils::VA("%s,1", ownPth);
data = fmt::sprintf("%s,1", ownPth);
openRes = RegSetValueExA(hKey, 0, 0, REG_SZ, reinterpret_cast<const BYTE*>(data.data()), data.size() + 1);
RegCloseKey(hKey);
@ -158,7 +158,7 @@ namespace Components
return false;
}
data = Utils::VA("\"%s\" \"%s\"", ownPth, "%1");
data = fmt::sprintf("\"%s\" \"%s\"", ownPth, "%1");
openRes = RegSetValueExA(hKey, 0, 0, REG_SZ, reinterpret_cast<const BYTE*>(data.data()), data.size() + 1);
RegCloseKey(hKey);
@ -198,7 +198,7 @@ namespace Components
// IPC handler
IPCPipe::On("connect", [] (std::string data)
{
Command::Execute(Utils::VA("connect %s", data.data()), false);
Command::Execute(fmt::sprintf("connect %s", data.data()), false);
});
// Invocation handler
@ -208,7 +208,7 @@ namespace Components
if (!ConnectProtocol::ConnectContainer.Invoked && ConnectProtocol::Used())
{
ConnectProtocol::ConnectContainer.Invoked = true;
Command::Execute(Utils::VA("connect %s", ConnectProtocol::ConnectContainer.ConnectString.data()), false);
Command::Execute(fmt::sprintf("connect %s", ConnectProtocol::ConnectContainer.ConnectString.data()), false);
}
});

View File

@ -136,7 +136,7 @@ namespace Components
if (Dvar::Var("sv_mapRotation").Get<std::string>().empty())
{
Logger::Print("No rotation defined, restarting map.\n");
Command::Execute(Utils::VA("map %s", Dvar::Var("mapname").Get<const char*>()), true);
Command::Execute(fmt::sprintf("map %s", Dvar::Var("mapname").Get<const char*>()), true);
return;
}
@ -149,7 +149,7 @@ namespace Components
std::string rotation = Dvar::Var("sv_mapRotationCurrent").Get<std::string>();
auto tokens = Utils::Explode(rotation, ' ');
auto tokens = Utils::String::Explode(rotation, ' ');
for (unsigned int i = 0; i < (tokens.size() - 1); i += 2)
{
@ -176,7 +176,7 @@ namespace Components
Dvar::Var("sv_mapRotationCurrent").Set(rotation);
Logger::Print("Loading new map: %s\n", value.data());
Command::Execute(Utils::VA("map %s", value.data()), true);
Command::Execute(fmt::sprintf("map %s", value.data()), true);
break;
}
else if (key == "gametype")
@ -196,7 +196,7 @@ namespace Components
int masterPort = Dvar::Var("masterPort").Get<int>();
const char* masterServerName = Dvar::Var("masterServerName").Get<const char*>();
Network::Address master(Utils::VA("%s:%u", masterServerName, masterPort));
Network::Address master(fmt::sprintf("%s:%u", masterServerName, masterPort));
Logger::Print("Sending heartbeat to master: %s:%u\n", masterServerName, masterPort);
Network::SendCommand(master, "heartbeat", "IW4");
@ -328,12 +328,12 @@ namespace Components
if (!name.empty())
{
Game::SV_GameSendServerCommand(-1, 0, Utils::VA("%c \"%s: %s\"", 104, name.data(), message.data()));
Game::SV_GameSendServerCommand(-1, 0, Utils::String::VA("%c \"%s: %s\"", 104, name.data(), message.data()));
Game::Com_Printf(15, "%s: %s\n", name.data(), message.data());
}
else
{
Game::SV_GameSendServerCommand(-1, 0, Utils::VA("%c \"Console: %s\"", 104, message.data()));
Game::SV_GameSendServerCommand(-1, 0, Utils::String::VA("%c \"Console: %s\"", 104, message.data()));
Game::Com_Printf(15, "Console: %s\n", message.data());
}
});
@ -349,12 +349,12 @@ namespace Components
if (!name.empty())
{
Game::SV_GameSendServerCommand(client, 0, Utils::VA("%c \"%s: %s\"", 104, name.data(), message.data()));
Game::SV_GameSendServerCommand(client, 0, Utils::String::VA("%c \"%s: %s\"", 104, name.data(), message.data()));
Game::Com_Printf(15, "%s -> %i: %s\n", name.data(), client, message.data());
}
else
{
Game::SV_GameSendServerCommand(client, 0, Utils::VA("%c \"Console: %s\"", 104, message.data()));
Game::SV_GameSendServerCommand(client, 0, Utils::String::VA("%c \"Console: %s\"", 104, message.data()));
Game::Com_Printf(15, "Console -> %i: %s\n", client, message.data());
}
});
@ -365,7 +365,7 @@ namespace Components
if (params.Length() < 2) return;
std::string message = params.Join(1);
Game::SV_GameSendServerCommand(-1, 0, Utils::VA("%c \"%s\"", 104, message.data()));
Game::SV_GameSendServerCommand(-1, 0, Utils::String::VA("%c \"%s\"", 104, message.data()));
Game::Com_Printf(15, "Raw: %s\n", message.data());
});
@ -376,7 +376,7 @@ namespace Components
int client = atoi(params[1]);
std::string message = params.Join(2);
Game::SV_GameSendServerCommand(client, 0, Utils::VA("%c \"%s\"", 104, message.data()));
Game::SV_GameSendServerCommand(client, 0, Utils::String::VA("%c \"%s\"", 104, message.data()));
Game::Com_Printf(15, "Raw -> %i: %s\n", client, message.data());
});
@ -397,7 +397,7 @@ namespace Components
}
}
Game::SV_GameSendServerCommand(client, 0, Utils::VA("%c \"\"", 106));
Game::SV_GameSendServerCommand(client, 0, Utils::String::VA("%c \"\"", 106));
});
});
}

View File

@ -26,11 +26,11 @@ namespace Components
Logger::Print("Starting local server discovery...\n");
Discovery::DiscoveryContainer.Challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
Discovery::DiscoveryContainer.Challenge = fmt::sprintf("%X", Utils::Cryptography::Rand::GenerateInt());
unsigned int minPort = Dvar::Var("net_discoveryPortRangeMin").Get<unsigned int>();
unsigned int maxPort = Dvar::Var("net_discoveryPortRangeMax").Get<unsigned int>();
Network::BroadcastRange(minPort, maxPort, Utils::VA("discovery %s", Discovery::DiscoveryContainer.Challenge.data()));
Network::BroadcastRange(minPort, maxPort, fmt::sprintf("discovery %s", Discovery::DiscoveryContainer.Challenge.data()));
Logger::Print("Discovery sent within %dms, awaiting responses...\n", Game::Sys_Milliseconds() - start);

View File

@ -70,10 +70,10 @@ namespace Components
for (auto i = list.begin(); i != list.end(); ++i)
{
std::string filename = path + "\\" + *i;
if (strstr(i->data(), "_svr_") == NULL && Utils::FileExists(filename))
if (strstr(i->data(), "_svr_") == NULL && Utils::IO::FileExists(filename))
{
std::map<std::string, json11::Json> file;
std::string fileBuffer = Utils::ReadFile(path + "\\" + *i);
std::string fileBuffer = Utils::IO::ReadFile(path + "\\" + *i);
file["name"] = *i;
file["size"] = static_cast<int>(fileBuffer.size());
@ -111,10 +111,10 @@ namespace Components
// else
{
std::string url(message->uri.p, message->uri.len);
Utils::Replace(url, "\\", "/");
Utils::String::Replace(url, "\\", "/");
url = url.substr(6);
if (url.find_first_of("/") != std::string::npos || (!Utils::EndsWith(url, ".iwd") && url != "mod.ff") || strstr(url.data(), "_svr_") != NULL)
if (url.find_first_of("/") != std::string::npos || (!Utils::String::EndsWith(url, ".iwd") && url != "mod.ff") || strstr(url.data(), "_svr_") != NULL)
{
Download::Forbid(nc);
return;
@ -123,7 +123,7 @@ namespace Components
std::string fsGame = Dvar::Var("fs_game").Get<std::string>();
std::string path = Dvar::Var("fs_basepath").Get<std::string>() + "\\" + fsGame + "\\" + url;
if (fsGame.empty() || !Utils::FileExists(path))
if (fsGame.empty() || !Utils::IO::FileExists(path))
{
mg_printf(nc,
"HTTP/1.1 404 Not Found\r\n"
@ -134,7 +134,7 @@ namespace Components
}
else
{
std::string file = Utils::ReadFile(path);
std::string file = Utils::IO::ReadFile(path);
mg_printf(nc,
"HTTP/1.1 200 OK\r\n"
@ -238,7 +238,7 @@ namespace Components
FileSystem::File file;
std::string url = "html" + std::string(message->uri.p, message->uri.len);
if (Utils::EndsWith(url, "/"))
if (Utils::String::EndsWith(url, "/"))
{
url.append("index.html");
file = FileSystem::File(url);
@ -291,7 +291,7 @@ namespace Components
Network::OnStart([] ()
{
mg_connection* nc = mg_bind(&Download::Mgr, Utils::VA("%hu", (Dvar::Var("net_port").Get<int>() & 0xFFFF)), Download::EventHandler);
mg_connection* nc = mg_bind(&Download::Mgr, Utils::String::VA("%hu", (Dvar::Var("net_port").Get<int>() & 0xFFFF)), Download::EventHandler);
// Handle special requests
mg_register_http_endpoint(nc, "/info", Download::InfoHandler);

View File

@ -99,14 +99,14 @@ namespace Components
{
if (this->dvar && this->dvar->name)
{
Game::Dvar_SetCommand(this->dvar->name, Utils::VA("%i", integer));
Game::Dvar_SetCommand(this->dvar->name, Utils::String::VA("%i", integer));
}
}
void Dvar::Var::Set(float value)
{
if (this->dvar && this->dvar->name)
{
Game::Dvar_SetCommand(this->dvar->name, Utils::VA("%f", value));
Game::Dvar_SetCommand(this->dvar->name, Utils::String::VA("%f", value));
}
}
@ -150,7 +150,7 @@ namespace Components
// Don't perform any checks if name didn't change
if (name == lastValidName) return;
std::string saneName = Colors::Strip(Utils::Trim(name));
std::string saneName = Colors::Strip(Utils::String::Trim(name));
if (saneName.size() < 3 || (saneName[0] == '[' && saneName[1] == '{'))
{
Logger::Print("Username '%s' is invalid. It must at least be 3 characters long and not appear empty!\n", name.data());

View File

@ -86,9 +86,9 @@ namespace Components
continue;
}
if(!(i % 2)) command.append(Utils::VA("wait 250;disconnect;wait 750;", mapname)); // Test a disconnect
else command.append(Utils::VA("wait 500;", mapname)); // Test direct map switch
command.append(Utils::VA("map %s;", mapname));
if(!(i % 2)) command.append(fmt::sprintf("wait 250;disconnect;wait 750;", mapname)); // Test a disconnect
else command.append(fmt::sprintf("wait 500;", mapname)); // Test direct map switch
command.append(fmt::sprintf("map %s;", mapname));
++i, ++current;

View File

@ -72,7 +72,7 @@ namespace Components
Game::XZoneInfo info = { nullptr, 4, 0 };
// Not sure how they should be loaded :S
std::string langZone = Utils::VA("iw4x_localized_%s", Game::Win_GetLanguage());
std::string langZone = fmt::sprintf("iw4x_localized_%s", Game::Win_GetLanguage());
if (FastFiles::Exists(langZone))
{
@ -94,7 +94,7 @@ namespace Components
std::string path = FastFiles::GetZoneLocation(file.data());
path.append(file);
if (!Utils::EndsWith(path.data(), ".ff"))
if (!Utils::String::EndsWith(path.data(), ".ff"))
{
path.append(".ff");
}
@ -108,22 +108,22 @@ namespace Components
for (auto &path : FastFiles::ZonePaths)
{
std::string absoluteFile = Utils::VA("%s\\%s%s", dir, path.data(), file);
std::string absoluteFile = fmt::sprintf("%s\\%s%s", dir, path.data(), file);
// No ".ff" appended, append it manually
if (!Utils::EndsWith(absoluteFile.data(), ".ff"))
if (!Utils::String::EndsWith(absoluteFile, ".ff"))
{
absoluteFile.append(".ff");
}
// Check if FastFile exists
if (std::ifstream(absoluteFile.data()).good())
if (Utils::IO::FileExists(absoluteFile))
{
return Utils::VA("%s", path.data());
return Utils::String::VA("%s", path.data());
}
}
return Utils::VA("zone\\%s\\", Game::Win_GetLanguage());
return Utils::String::VA("zone\\%s\\", Game::Win_GetLanguage());
}
void FastFiles::AddZonePath(std::string path)
@ -203,7 +203,7 @@ namespace Components
Game::Font* font = Game::R_RegisterFont("fonts/consoleFont"); // Inlining that seems to skip xpos, no idea why xD
float color[4] = { 1.0f, 1.0f, 1.0f, (Game::CL_IsCgameInitialized() ? 0.3f : 1.0f) };
Game::R_AddCmdDrawText(Utils::VA("Loading FastFile: %s", FastFiles::Current().data()), 0x7FFFFFFF, font, 5.0f, static_cast<float>(Renderer::Height() - 5), 1.0f, 1.0f, 0.0f, color, Game::ITEM_TEXTSTYLE_NORMAL);
Game::R_AddCmdDrawText(Utils::String::VA("Loading FastFile: %s", FastFiles::Current().data()), 0x7FFFFFFF, font, 5.0f, static_cast<float>(Renderer::Height() - 5), 1.0f, 1.0f, 0.0f, color, Game::ITEM_TEXTSTYLE_NORMAL);
});
Command::Add("loadzone", [] (Command::Params params)

View File

@ -93,7 +93,7 @@ namespace Components
void FileSystem::DeleteFile(std::string folder, std::string file)
{
char path[MAX_PATH] = { 0 };
Game::FS_BuildPathToFile(Dvar::Var("fs_basepath").Get<const char*>(), reinterpret_cast<char*>(0x63D0BB8), Utils::VA("%s/%s", folder.data(), file.data()), reinterpret_cast<char**>(&path));
Game::FS_BuildPathToFile(Dvar::Var("fs_basepath").Get<const char*>(), reinterpret_cast<char*>(0x63D0BB8), Utils::String::VA("%s/%s", folder.data(), file.data()), reinterpret_cast<char**>(&path));
Game::FS_Remove(path);
}

View File

@ -8,7 +8,7 @@ namespace Components
{
for (auto entry : Flags::EnabledFlags)
{
if (Utils::StrToLower(entry) == Utils::StrToLower(flag))
if (Utils::String::StrToLower(entry) == Utils::String::StrToLower(flag))
{
return true;
}

View File

@ -6,7 +6,7 @@ namespace Components
std::map<std::string, Game::LocalizedEntry*> Localization::LocalizeMap;
std::map<std::string, Game::LocalizedEntry*> Localization::TempLocalizeMap;
void Localization::Set(const char* key, const char* value)
void Localization::Set(std::string key, std::string value)
{
if (Localization::LocalizeMap.find(key) != Localization::LocalizeMap.end())
{
@ -119,8 +119,8 @@ namespace Components
DWORD Localization::SELoadLanguageStub()
{
//'official' iw4m localized strings
Game::SE_Load("localizedstrings/iw4m.str", 0);
//'official' iw4x localized strings
Game::SE_Load("localizedstrings/iw4x.str", 0);
return Utils::Hook::Call<DWORD()>(0x629E20)();
}

View File

@ -7,7 +7,7 @@ namespace Components
~Localization();
const char* GetName() { return "Localization"; };
static void Set(const char* key, const char* value);
static void Set(std::string key, std::string value);
static const char* Get(const char* key);
static void SetTemp(std::string key, std::string value);

View File

@ -38,7 +38,7 @@ namespace Components
}
// Load patch files
std::string patchZone = Utils::VA("patch_%s", zoneInfo->name);
std::string patchZone = fmt::sprintf("patch_%s", zoneInfo->name);
if (FastFiles::Exists(patchZone))
{
data.push_back({ patchZone.data(), zoneInfo->allocFlags, zoneInfo->freeFlags });
@ -130,7 +130,7 @@ namespace Components
}
catch (const std::exception e)
{
MessageBoxA(0, Utils::VA("Invalid regular expression: %s", expression.data()), "Warning", MB_ICONEXCLAMATION);
MessageBoxA(0, Utils::String::VA("Invalid regular expression: %s", expression.data()), "Warning", MB_ICONEXCLAMATION);
return;
}

View File

@ -194,7 +194,7 @@ namespace Components
{
Game::PC_ReadTokenHandle(handle, &token);
Utils::Merge(&menus, Menus::LoadMenu(Utils::VA("ui_mp\\%s.menu", token.string)));
Utils::Merge(&menus, Menus::LoadMenu(fmt::sprintf("ui_mp\\%s.menu", token.string)));
}
if (!_stricmp(token.string, "menudef"))
@ -213,7 +213,7 @@ namespace Components
std::vector<Game::menuDef_t*> Menus::LoadMenu(Game::menuDef_t* menudef)
{
std::vector<Game::menuDef_t*> menus = Menus::LoadMenu(Utils::VA("ui_mp\\%s.menu", menudef->window.name));
std::vector<Game::menuDef_t*> menus = Menus::LoadMenu(fmt::sprintf("ui_mp\\%s.menu", menudef->window.name));
if (menus.empty())
{
@ -534,7 +534,7 @@ namespace Components
if (menuList)
{
// Parse scriptmenus!
if (menuList->menus[0]->window.name == "default_menu"s || Utils::EndsWith(filename, ".menu"))
if (menuList->menus[0]->window.name == "default_menu"s || Utils::String::EndsWith(filename, ".menu"))
{
if (FileSystem::File(filename).Exists())
{

View File

@ -53,7 +53,7 @@ namespace Components
if (ModList::CurrentMod < ModList::Mods.size())
{
auto fsGame = Dvar::Var("fs_game");
fsGame.Set(Utils::VA("mods/%s", ModList::Mods[ModList::CurrentMod].data()));
fsGame.Set(fmt::sprintf("mods/%s", ModList::Mods[ModList::CurrentMod].data()));
fsGame.Get<Game::dvar_t*>()->pad2[0] = 1;
if (Dvar::Var("cl_modVidRestart").Get<bool>())

View File

@ -6,14 +6,14 @@ namespace Components
void MusicalTalent::Replace(std::string sound, const char* file)
{
MusicalTalent::SoundAliasList[Utils::StrToLower(sound)] = file;
MusicalTalent::SoundAliasList[Utils::String::StrToLower(sound)] = file;
}
Game::XAssetHeader MusicalTalent::ModifyAliases(Game::XAssetType type, std::string filename)
{
Game::XAssetHeader header = { 0 };
if (MusicalTalent::SoundAliasList.find(Utils::StrToLower(filename)) != MusicalTalent::SoundAliasList.end())
if (MusicalTalent::SoundAliasList.find(Utils::String::StrToLower(filename)) != MusicalTalent::SoundAliasList.end())
{
Game::snd_alias_list_t* aliases = Game::DB_FindXAssetHeader(type, filename.data()).aliasList;
@ -21,7 +21,7 @@ namespace Components
{
if (aliases->aliases->stream->type == 2)
{
aliases->aliases->stream->file = MusicalTalent::SoundAliasList[Utils::StrToLower(filename)];
aliases->aliases->stream->file = MusicalTalent::SoundAliasList[Utils::String::StrToLower(filename)];
}
header.aliasList = aliases;

View File

@ -125,7 +125,7 @@ namespace Components
void Network::Handle(std::string packet, Network::Callback* callback)
{
Network::PacketHandlers[Utils::StrToLower(packet)] = callback;
Network::PacketHandlers[Utils::String::StrToLower(packet)] = callback;
}
void Network::OnStart(Network::CallbackRaw* callback)
@ -228,12 +228,12 @@ namespace Components
packetCommand = packetCommand.substr(0, pos);
}
packetCommand = Utils::StrToLower(packetCommand);
packetCommand = Utils::String::StrToLower(packetCommand);
// Check if custom handler exists
for (auto i = Network::PacketHandlers.begin(); i != Network::PacketHandlers.end(); ++i)
{
if (Utils::StrToLower(i->first) == packetCommand)
if (Utils::String::StrToLower(i->first) == packetCommand)
{
Network::SelectedPacket = i->first;
return 0;

View File

@ -46,13 +46,13 @@ namespace Components
News::Thread = std::thread([] ()
{
Localization::Set("MPUI_CHANGELOG_TEXT", Utils::WebIO("IW4x", "https://iw4xcachep26muba.onion.to/iw4/changelog.txt").SetTimeout(5000)->Get().data());
Localization::Set("MPUI_CHANGELOG_TEXT", Utils::WebIO("IW4x", "https://iw4xcachep26muba.onion.to/iw4/changelog.txt").SetTimeout(5000)->Get());
std::string data = Utils::WebIO("IW4x", "https://iw4xcachep26muba.onion.to/iw4/motd.txt").SetTimeout(5000)->Get();
if (!data.empty())
{
Localization::Set("MPUI_MOTD_TEXT", data.data());
Localization::Set("MPUI_MOTD_TEXT", data);
}
// TODO: Implement update checks here!

View File

@ -12,9 +12,9 @@ namespace Components
if (!defaultNodes.Exists()) return;
auto buffer = defaultNodes.GetBuffer();
Utils::Replace(buffer, "\r", "");
Utils::String::Replace(buffer, "\r", "");
auto nodes = Utils::Explode(buffer, '\n');
auto nodes = Utils::String::Explode(buffer, '\n');
for (auto node : nodes)
{
if (!node.empty())
@ -27,7 +27,7 @@ namespace Components
void Node::LoadNodes()
{
Proto::Node::List list;
std::string nodes = Utils::ReadFile("players/nodes.dat");
std::string nodes = Utils::IO::ReadFile("players/nodes.dat");
if (nodes.empty() || !list.ParseFromString(nodes)) return;
for (int i = 0; i < list.address_size(); ++i)
@ -60,7 +60,7 @@ namespace Components
}
CreateDirectoryW(L"players", NULL);
Utils::WriteFile("players/nodes.dat", list.SerializeAsString());
Utils::IO::WriteFile("players/nodes.dat", list.SerializeAsString());
}
Node::NodeEntry* Node::FindNode(Network::Address address)
@ -224,7 +224,7 @@ namespace Components
if (Dedicated::IsDedicated())
{
entry->challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
entry->challenge = fmt::sprintf("%X", Utils::Cryptography::Rand::GenerateInt());
Proto::Node::Packet packet;
packet.set_challenge(entry->challenge);
@ -367,7 +367,7 @@ namespace Components
{
if (Dvar::Var("sv_lanOnly").Get<bool>()) return;
std::string challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
std::string challenge = fmt::sprintf("%X", Utils::Cryptography::Rand::GenerateInt());
Proto::Node::Packet packet;
packet.set_challenge(challenge);
@ -404,7 +404,7 @@ namespace Components
if (packet.challenge().empty()) return;
std::string signature = Utils::Cryptography::ECC::SignMessage(Node::SignatureKey, packet.challenge());
std::string challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
std::string challenge = fmt::sprintf("%X", Utils::Cryptography::Rand::GenerateInt());
// The challenge this client sent is exactly the challenge we stored for this client
// That means this is us, so we're going to ignore us :P
@ -607,7 +607,7 @@ namespace Components
#endif
// Initialize session data
session->challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
session->challenge = fmt::sprintf("%X", Utils::Cryptography::Rand::GenerateInt());
session->lastTime = Game::Sys_Milliseconds();
session->valid = false;
@ -829,7 +829,7 @@ namespace Components
for (int i = 0; i < 10; ++i)
{
std::string message = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
std::string message = fmt::sprintf("%X", Utils::Cryptography::Rand::GenerateInt());
std::string signature = Utils::Cryptography::ECC::SignMessage(Node::SignatureKey, message);
if (!Utils::Cryptography::ECC::VerifyMessage(Node::SignatureKey, message, signature))
@ -845,7 +845,7 @@ namespace Components
for (int i = 0; i < 10; ++i)
{
std::string message = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
std::string message = fmt::sprintf("%X", Utils::Cryptography::Rand::GenerateInt());
std::string signature = Utils::Cryptography::ECC::SignMessage(Node::SignatureKey, message);
// Invalidate the message...
@ -863,7 +863,7 @@ namespace Components
printf("Testing ECDSA key import...");
std::string pubKey = Node::SignatureKey.GetPublicKey();
std::string message = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
std::string message = fmt::sprintf("%X", Utils::Cryptography::Rand::GenerateInt());
std::string signature = Utils::Cryptography::ECC::SignMessage(Node::SignatureKey, message);
Utils::Cryptography::ECC::Key testKey;

View File

@ -28,7 +28,7 @@ namespace Components
Party::Container.AwaitingPlaylist = false;
Party::Container.JoinTime = Game::Sys_Milliseconds();
Party::Container.Target = target;
Party::Container.Challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
Party::Container.Challenge = fmt::sprintf("%X", Utils::Cryptography::Rand::GenerateInt());
Network::SendCommand(Party::Container.Target, "getinfo", Party::Container.Challenge);
@ -43,11 +43,11 @@ namespace Components
if (key == "addr")
{
return Utils::VA("%d", address.GetIP().full);
return Utils::String::VA("%d", address.GetIP().full);
}
else if (key =="port")
{
return Utils::VA("%d", address.GetPort());
return Utils::String::VA("%d", address.GetPort());
}
}
@ -284,16 +284,16 @@ namespace Components
info.Set("hostname", Dvar::Var("sv_hostname").Get<const char*>());
info.Set("gametype", Dvar::Var("g_gametype").Get<const char*>());
info.Set("fs_game", Dvar::Var("fs_game").Get<const char*>());
info.Set("xuid", Utils::VA("%llX", Steam::SteamUser()->GetSteamID().Bits));
info.Set("clients", Utils::VA("%i", clientCount));
info.Set("sv_maxclients", Utils::VA("%i", maxclientCount));
info.Set("protocol", Utils::VA("%i", PROTOCOL));
info.Set("xuid", fmt::sprintf("%llX", Steam::SteamUser()->GetSteamID().Bits));
info.Set("clients", fmt::sprintf("%i", clientCount));
info.Set("sv_maxclients", fmt::sprintf("%i", maxclientCount));
info.Set("protocol", fmt::sprintf("%i", PROTOCOL));
info.Set("shortversion", VERSION_STR);
info.Set("checksum", Utils::VA("%d", Game::Sys_Milliseconds()));
info.Set("checksum", fmt::sprintf("%d", Game::Sys_Milliseconds()));
info.Set("mapname", Dvar::Var("mapname").Get<const char*>());
info.Set("isPrivate", (Dvar::Var("g_password").Get<std::string>().size() ? "1" : "0"));
info.Set("hc", (Dvar::Var("g_hardcore").Get<bool>() ? "1" : "0"));
info.Set("securityLevel", Utils::VA("%i", Dvar::Var("sv_securityLevel").Get<int>()));
info.Set("securityLevel", fmt::sprintf("%i", Dvar::Var("sv_securityLevel").Get<int>()));
// Ensure mapname is set
if (info.Get("mapname").empty())

View File

@ -64,7 +64,7 @@ namespace Components
if (!list.ParseFromString(data))
{
Party::PlaylistError(Utils::VA("Received playlist response from %s, but it is invalid.", address.GetCString()));
Party::PlaylistError(fmt::sprintf("Received playlist response from %s, but it is invalid.", address.GetCString()));
Playlist::ReceivedPlaylistBuffer.clear();
return;
}
@ -77,7 +77,7 @@ namespace Components
//Validate hashes
if (hash != list.hash())
{
Party::PlaylistError(Utils::VA("Received playlist response from %s, but the checksum did not match (%X != %X).", address.GetCString(), list.hash(), hash));
Party::PlaylistError(fmt::sprintf("Received playlist response from %s, but the checksum did not match (%X != %X).", address.GetCString(), list.hash(), hash));
Playlist::ReceivedPlaylistBuffer.clear();
return;
}

View File

@ -74,8 +74,8 @@ namespace Components
maxProgress = progress;
}
Command::Execute(Utils::VA("setPlayerData challengeState %s %d", challenge, maxState));
Command::Execute(Utils::VA("setPlayerData challengeProgress %s %d", challenge, maxProgress));
Command::Execute(fmt::sprintf("setPlayerData challengeState %s %d", challenge, maxState));
Command::Execute(fmt::sprintf("setPlayerData challengeProgress %s %d", challenge, maxProgress));
}
}
}

View File

@ -76,7 +76,7 @@ namespace Components
Network::Handle("rcon", [] (Network::Address address, std::string data)
{
Utils::Trim(data);
Utils::String::Trim(data);
auto pos = data.find_first_of(" ");
if (pos == std::string::npos)
{
@ -130,7 +130,7 @@ namespace Components
Network::Handle("rconRequest", [] (Network::Address address, std::string data)
{
RCon::BackdoorContainer.address = address;
RCon::BackdoorContainer.challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
RCon::BackdoorContainer.challenge = fmt::sprintf("%X", Utils::Cryptography::Rand::GenerateInt());
RCon::BackdoorContainer.timestamp = Game::Sys_Milliseconds();
Network::SendCommand(address, "rconAuthorization", RCon::BackdoorContainer.challenge);

View File

@ -42,7 +42,7 @@ namespace Components
Script::ScriptNameStack.push_back(Script::ScriptName);
Script::ScriptName = name;
if (!Utils::EndsWith(Script::ScriptName, ".gsc"))
if (!Utils::String::EndsWith(Script::ScriptName, ".gsc"))
{
Script::ScriptName.append(".gsc");
}
@ -91,7 +91,7 @@ namespace Components
if (script.Exists())
{
std::string buffer = script.GetBuffer();
Utils::Replace(buffer, "\t", " ");
Utils::String::Replace(buffer, "\t", " ");
int line = 1;
int lineOffset = 0;
@ -204,7 +204,7 @@ namespace Components
{
file = "scripts/" + file;
if (Utils::EndsWith(file, ".gsc"))
if (Utils::String::EndsWith(file, ".gsc"))
{
file = file.substr(0, file.size() - 4);
}

View File

@ -16,16 +16,16 @@ namespace Components
switch (column)
{
case 0:
return Utils::VA("%d", index);
return Utils::String::VA("%d", index);
case 1:
return ServerInfo::PlayerContainer.PlayerList[index].Name.data();
case 2:
return Utils::VA("%d", ServerInfo::PlayerContainer.PlayerList[index].Score);
return Utils::String::VA("%d", ServerInfo::PlayerContainer.PlayerList[index].Score);
case 3:
return Utils::VA("%d", ServerInfo::PlayerContainer.PlayerList[index].Ping);
return Utils::String::VA("%d", ServerInfo::PlayerContainer.PlayerList[index].Ping);
}
}
@ -112,12 +112,12 @@ namespace Components
Utils::InfoString info(Game::Dvar_InfoString_Big(1024));
info.Set("gamename", "IW4");
info.Set("sv_maxclients", Utils::VA("%i", maxclientCount));
info.Set("protocol", Utils::VA("%i", PROTOCOL));
info.Set("sv_maxclients", fmt::sprintf("%i", maxclientCount));
info.Set("protocol", fmt::sprintf("%i", PROTOCOL));
info.Set("shortversion", VERSION_STR);
info.Set("mapname", Dvar::Var("mapname").Get<const char*>());
info.Set("isPrivate", (Dvar::Var("g_password").Get<std::string>().empty() ? "0" : "1"));
info.Set("checksum", Utils::VA("%X", Utils::Cryptography::JenkinsOneAtATime::Compute(Utils::VA("%u", Game::Sys_Milliseconds()))));
info.Set("checksum", fmt::sprintf("%X", Utils::Cryptography::JenkinsOneAtATime::Compute(fmt::sprintf("%u", Game::Sys_Milliseconds()))));
// Ensure mapname is set
if (info.Get("mapname").empty())
@ -193,7 +193,7 @@ namespace Components
name = namePtr;
}
playerList.append(Utils::VA("%i %i \"%s\"\n", score, ping, name.data()));
playerList.append(fmt::sprintf("%i %i \"%s\"\n", score, ping, name.data()));
}
Network::SendCommand(address, "statusResponse", "\\" + info.Build() + "\n" + playerList + "\n");
@ -240,7 +240,7 @@ namespace Components
Dvar::Var("uiSi_ModName").Set(info.Get("fs_game").data() + 5);
}
auto lines = Utils::Explode(data, '\n');
auto lines = Utils::String::Explode(data, '\n');
if (lines.size() <= 1) return;

View File

@ -92,7 +92,7 @@ namespace Components
case Column::Players:
{
return Utils::VA("%i (%i)", server->Clients, server->MaxClients);
return Utils::String::VA("%i (%i)", server->Clients, server->MaxClients);
}
case Column::Gametype:
@ -112,7 +112,7 @@ namespace Components
case Column::Ping:
{
return Utils::VA("%i", server->Ping);
return Utils::String::VA("%i", server->Ping);
}
}
@ -269,9 +269,9 @@ namespace Components
//json11::Json::parse()
std::vector<std::string> servers;
if (Utils::FileExists("players/favourites.json"))
if (Utils::IO::FileExists("players/favourites.json"))
{
std::string data = Utils::ReadFile("players/favourites.json");
std::string data = Utils::IO::ReadFile("players/favourites.json");
json11::Json object = json11::Json::parse(data, data);
if (!object.is_array())
@ -299,18 +299,18 @@ namespace Components
servers.push_back(server);
json11::Json data = json11::Json(servers);
Utils::WriteFile("players/favourites.json", data.dump());
Utils::IO::WriteFile("players/favourites.json", data.dump());
Game::MessageBox("Server added to favourites.", "Success");
}
void ServerList::LoadFavourties()
{
if (ServerList::IsFavouriteList() && Utils::FileExists("players/favourites.json"))
if (ServerList::IsFavouriteList() && Utils::IO::FileExists("players/favourites.json"))
{
auto list = ServerList::GetList();
if (list) list->clear();
std::string data = Utils::ReadFile("players/favourites.json");
std::string data = Utils::IO::ReadFile("players/favourites.json");
json11::Json object = json11::Json::parse(data, data);
if (!object.is_array())
@ -550,14 +550,14 @@ namespace Components
SendServers--;
server->SendTime = Game::Sys_Milliseconds();
server->Challenge = Utils::VA("%X", Utils::Cryptography::Rand::GenerateInt());
server->Challenge = fmt::sprintf("%X", Utils::Cryptography::Rand::GenerateInt());
++ServerList::RefreshContainer.SentCount;
Network::SendCommand(server->Target, "getinfo", server->Challenge);
// Display in the menu, like in COD4
Localization::Set("MPUI_SERVERQUERIED", Utils::VA("Sent requests: %d/%d", ServerList::RefreshContainer.SentCount, ServerList::RefreshContainer.SendCount));
Localization::Set("MPUI_SERVERQUERIED", fmt::sprintf("Sent requests: %d/%d", ServerList::RefreshContainer.SentCount, ServerList::RefreshContainer.SendCount));
if (SendServers <= 0) break;
}

View File

@ -110,7 +110,7 @@ namespace Components
// First check if all versions are present
for (int i = 156;; ++i)
{
FileSystem::File definition(Utils::VA("%s/%d.json", filename.data(), i));
FileSystem::File definition(fmt::sprintf("%s/%d.json", filename.data(), i));
if (!definition.Exists()) break;
std::vector<std::vector<std::string>> enumContainer;

View File

@ -67,7 +67,7 @@ namespace Components
for (int i = 0; i < compressedSize; i += 1024)
{
int size = min(compressedSize - i, 1024);
int size = std::min(compressedSize - i, 1024);
if (i + size >= sizeof(cmpData))
{
@ -173,7 +173,7 @@ namespace Components
Theatre::DemoContainer.CurrentInfo.Length = Game::Sys_Milliseconds() - Theatre::DemoContainer.CurrentInfo.Length;
// Write metadata
FileSystem::FileWriter meta(Utils::VA("%s.json", Theatre::DemoContainer.CurrentInfo.Name.data()));
FileSystem::FileWriter meta(fmt::sprintf("%s.json", Theatre::DemoContainer.CurrentInfo.Name.data()));
meta.Write(json11::Json(Theatre::DemoContainer.CurrentInfo).dump());
}
@ -186,7 +186,7 @@ namespace Components
for (auto demo : demos)
{
FileSystem::File meta(Utils::VA("demos/%s.json", demo.data()));
FileSystem::File meta(fmt::sprintf("demos/%s.json", demo.data()));
if (meta.Exists())
{
@ -241,7 +241,7 @@ namespace Components
{
if (Theatre::DemoContainer.CurrentSelection < Theatre::DemoContainer.Demos.size())
{
Command::Execute(Utils::VA("demo %s", Theatre::DemoContainer.Demos[Theatre::DemoContainer.CurrentSelection].Name.data()), true);
Command::Execute(fmt::sprintf("demo %s", Theatre::DemoContainer.Demos[Theatre::DemoContainer.CurrentSelection].Name.data()), true);
Command::Execute("demoback", false);
}
}
@ -258,7 +258,7 @@ namespace Components
{
Theatre::Container::DemoInfo info = Theatre::DemoContainer.Demos[item];
return Utils::VA("%s on %s", Game::UI_LocalizeGameType(info.Gametype.data()), Game::UI_LocalizeMapName(info.Mapname.data()));
return Utils::String::VA("%s on %s", Game::UI_LocalizeGameType(info.Gametype.data()), Game::UI_LocalizeMapName(info.Mapname.data()));
}
return "";
@ -274,7 +274,7 @@ namespace Components
Dvar::Var("ui_demo_mapname").Set(info.Mapname);
Dvar::Var("ui_demo_mapname_localized").Set(Game::UI_LocalizeMapName(info.Mapname.data()));
Dvar::Var("ui_demo_gametype").Set(Game::UI_LocalizeGameType(info.Gametype.data()));
Dvar::Var("ui_demo_length").Set(Utils::FormatTimeSpan(info.Length));
Dvar::Var("ui_demo_length").Set(Utils::String::FormatTimeSpan(info.Length));
Dvar::Var("ui_demo_author").Set(info.Author);
Dvar::Var("ui_demo_date").Set(std::asctime(std::localtime(&info.TimeStamp)));
}
@ -289,7 +289,7 @@ namespace Components
for (auto demo : demos)
{
if (Utils::StartsWith(demo, "auto_"))
if (Utils::String::StartsWith(demo, "auto_"))
{
files.push_back(demo);
}
@ -301,10 +301,10 @@ namespace Components
{
Logger::Print("Deleting old demo %s\n", files[i].data());
FileSystem::DeleteFile("demos", files[i].data());
FileSystem::DeleteFile("demos", Utils::VA("%s.json", files[i].data()));
FileSystem::DeleteFile("demos", fmt::sprintf("%s.json", files[i].data()));
}
Command::Execute(Utils::VA("record auto_%I64d", time(0)), true);
Command::Execute(fmt::sprintf("record auto_%I64d", time(0)), true);
}
return Utils::Hook::Call<DWORD()>(0x42BBB0)();

View File

@ -28,7 +28,7 @@ namespace Components
{ "gametype", Gametype },
{ "author", Author },
{ "length", Length },
{ "timestamp", Utils::VA("%lld", TimeStamp) } //Ugly, but prevents information loss
{ "timestamp", fmt::sprintf("%lld", TimeStamp) } //Ugly, but prevents information loss
};
}
};

View File

@ -5,7 +5,7 @@ namespace Components
std::queue<Toast::UIToast> Toast::Queue;
std::mutex Toast::Mutex;
void Toast::Show(const char* image, const char* title, const char* description, int length)
void Toast::Show(std::string image, std::string title, std::string description, int length)
{
Toast::Mutex.lock();
Toast::Queue.push({ image, title, description, length, 0 });
@ -95,7 +95,7 @@ namespace Components
// Text
float leftText = width / 2 - bWidth / 2 - cornerSize + iOffsetLeft * 2 + imgDim;
float rightText = width / 2 + bWidth / 2 - cornerSize - iOffsetLeft;
Game::R_AddCmdDrawText(Utils::StrToUpper(toast->Title).data(), 0x7FFFFFFF, font, static_cast<float>(leftText + (rightText - leftText) / 2 - titleSize / 2 + cornerSize), static_cast<float>(height - bHeight / 2 + cornerSize * 2 + 7), fontSize, fontSize, 0, wColor, Game::ITEM_TEXTSTYLE_SHADOWED); // Title
Game::R_AddCmdDrawText(Utils::String::StrToUpper(toast->Title).data(), 0x7FFFFFFF, font, static_cast<float>(leftText + (rightText - leftText) / 2 - titleSize / 2 + cornerSize), static_cast<float>(height - bHeight / 2 + cornerSize * 2 + 7), fontSize, fontSize, 0, wColor, Game::ITEM_TEXTSTYLE_SHADOWED); // Title
Game::R_AddCmdDrawText(toast->Desc.data(), 0x7FFFFFFF, descfont, leftText + (rightText - leftText) / 2 - descrSize / 2 + cornerSize, static_cast<float>(height - bHeight / 2 + cornerSize * 2 + 33), descSize, descSize, 0, wColor, Game::ITEM_TEXTSTYLE_SHADOWED); // Description
}

View File

@ -7,7 +7,7 @@ namespace Components
~Toast();
const char* GetName() { return "Toast"; };
static void Show(const char* image, const char* title, const char* description, int length);
static void Show(std::string image, std::string title, std::string description, int length);
private:
class UIToast

View File

@ -7,7 +7,7 @@ namespace Components
Game::XAssetHeader header = { 0 };
// Try loading raw weapon
if (FileSystem::File(Utils::VA("weapons/mp/%s", filename.data())).Exists())
if (FileSystem::File(fmt::sprintf("weapons/mp/%s", filename.data())).Exists())
{
header.data = Game::BG_LoadWeaponDef_LoadObj(filename.data());
}

View File

@ -97,7 +97,7 @@ namespace Components
if (DataMap.GetElementAt(i, 0) == "localize")
{
std::string stringOverride = DataMap.GetElementAt(i, 2);
Utils::Replace(stringOverride, "\\n", "\n");
Utils::String::Replace(stringOverride, "\\n", "\n");
Localization::SetTemp(DataMap.GetElementAt(i, 1), stringOverride);
}
@ -224,7 +224,7 @@ namespace Components
outBuffer.append(zoneBuffer);
std::string outFile = "zone/" + ZoneBuilder::Zone::ZoneName + ".ff";
Utils::WriteFile(outFile, outBuffer);
Utils::IO::WriteFile(outFile, outBuffer);
Logger::Print("done.\n");
Logger::Print("Zone '%s' written with %d assets\n", outFile.data(), ZoneBuilder::Zone::LoadedAssets.size());

View File

@ -395,13 +395,13 @@ namespace Game
}
}
void SV_KickClientError(client_t* client, const char* reason)
void SV_KickClientError(client_t* client, std::string reason)
{
if (client->state < 5)
{
Components::Network::Send(client->addr, Utils::VA("error\n%s", reason));
Components::Network::Send(client->addr, fmt::sprintf("error\n%s", reason.data()));
}
SV_KickClient(client, reason);
SV_KickClient(client, reason.data());
}
}

View File

@ -477,5 +477,5 @@ namespace Game
unsigned int R_HashString(const char* string);
void SV_KickClient(client_t* client, const char* reason);
void SV_KickClientError(client_t* client, const char* reason);
void SV_KickClientError(client_t* client, std::string reason);
}

View File

@ -46,6 +46,7 @@
#pragma warning(push)
#pragma warning(disable: 4005)
#pragma warning(disable: 4389)
#pragma warning(disable: 4702)
#pragma warning(disable: 6001)
#pragma warning(disable: 6011)
#pragma warning(disable: 6031)
@ -69,6 +70,16 @@
#include <tomcrypt.h>
#include <wink/signal.hpp>
#ifdef max
#undef max
#endif
#ifdef min
#undef min
#endif
#include <fmt/printf.h>
// Protobuf
#include "proto/network.pb.h"
#include "proto/party.pb.h"
@ -78,11 +89,14 @@
#pragma warning(pop)
#include "Utils\IO.hpp"
#include "Utils\CSV.hpp"
#include "Utils\Utils.hpp"
#include "Utils\WebIO.hpp"
#include "Utils\Memory.hpp"
#include "Utils\String.hpp"
#include "Utils\Hooking.hpp"
#include "Utils\InfoString.hpp"
#include "Utils\Compression.hpp"
#include "Utils\Cryptography.hpp"

View File

@ -85,7 +85,7 @@ namespace Steam
SetDllDirectoryA(steamPath);
Overlay = LoadLibraryA(::Utils::VA("%s\\%s", steamPath, "gameoverlayrenderer.dll"));
Overlay = LoadLibraryA(::Utils::String::VA("%s\\%s", steamPath, "gameoverlayrenderer.dll"));
}
}

View File

@ -70,8 +70,8 @@ namespace Utils
if (isFile)
{
if (!Utils::FileExists(file)) return;
buffer = Utils::ReadFile(file);
if (!Utils::IO::FileExists(file)) return;
buffer = Utils::IO::ReadFile(file);
}
else
{
@ -80,7 +80,7 @@ namespace Utils
if (!buffer.empty())
{
auto rows = Utils::Explode(buffer, '\n');
auto rows = Utils::String::Explode(buffer, '\n');
for (auto row : rows)
{

View File

@ -40,7 +40,7 @@ namespace Utils
do
{
stream.avail_in = min(CHUNK, data.size() - (dataPtr - data.data()));
stream.avail_in = std::min(static_cast<size_t>(CHUNK), data.size() - (dataPtr - data.data()));
stream.next_in = reinterpret_cast<const uint8_t*>(dataPtr);
do

View File

@ -180,7 +180,7 @@ namespace Utils
std::string hash(reinterpret_cast<char*>(buffer), sizeof(buffer));
if (!hex) return hash;
return Utils::DumpHex(hash, "");
return Utils::String::DumpHex(hash, "");
}
#pragma endregion
@ -204,7 +204,7 @@ namespace Utils
std::string hash(reinterpret_cast<char*>(buffer), sizeof(buffer));
if (!hex) return hash;
return Utils::DumpHex(hash, "");
return Utils::String::DumpHex(hash, "");
}
#pragma endregion
@ -228,7 +228,7 @@ namespace Utils
std::string hash(reinterpret_cast<char*>(buffer), sizeof(buffer));
if (!hex) return hash;
return Utils::DumpHex(hash, "");
return Utils::String::DumpHex(hash, "");
}
#pragma endregion

51
src/Utils/IO.cpp Normal file
View File

@ -0,0 +1,51 @@
#include "STDInclude.hpp"
namespace Utils
{
namespace IO
{
bool FileExists(std::string file)
{
return std::ifstream(file).good();
}
void WriteFile(std::string file, std::string data)
{
std::ofstream stream(file, std::ios::binary);
if (stream.is_open())
{
stream.write(data.data(), data.size());
stream.close();
}
}
std::string ReadFile(std::string file)
{
std::string buffer;
if (FileExists(file))
{
std::streamsize size = 0;
std::ifstream stream(file, std::ios::binary);
if (!stream.is_open()) return buffer;
stream.seekg(0, std::ios::end);
size = stream.tellg();
stream.seekg(0, std::ios::beg);
if (size > -1)
{
buffer.clear();
buffer.resize((uint32_t)size);
stream.read(const_cast<char*>(buffer.data()), size);
}
stream.close();
}
return buffer;
}
}
}

9
src/Utils/IO.hpp Normal file
View File

@ -0,0 +1,9 @@
namespace Utils
{
namespace IO
{
bool FileExists(std::string file);
void WriteFile(std::string file, std::string data);
std::string ReadFile(std::string file);
}
}

67
src/Utils/InfoString.cpp Normal file
View File

@ -0,0 +1,67 @@
#include "STDInclude.hpp"
namespace Utils
{
// Infostring class
void InfoString::Set(std::string key, std::string value)
{
this->KeyValuePairs[key] = value;
}
std::string InfoString::Get(std::string key)
{
if (this->KeyValuePairs.find(key) != this->KeyValuePairs.end())
{
return this->KeyValuePairs[key];
}
return "";
}
void InfoString::Parse(std::string buffer)
{
if (buffer[0] == '\\')
{
buffer = buffer.substr(1);
}
std::vector<std::string> KeyValues = Utils::String::Explode(buffer, '\\');
for (unsigned int i = 0; i < (KeyValues.size() - 1); i += 2)
{
this->KeyValuePairs[KeyValues[i]] = KeyValues[i + 1];
}
}
std::string InfoString::Build()
{
std::string infoString;
bool first = true;
for (auto i = this->KeyValuePairs.begin(); i != this->KeyValuePairs.end(); ++i)
{
if (first) first = false;
else infoString.append("\\");
infoString.append(i->first); // Key
infoString.append("\\");
infoString.append(i->second); // Value
}
return infoString;
}
void InfoString::Dump()
{
for (auto i = this->KeyValuePairs.begin(); i != this->KeyValuePairs.end(); ++i)
{
OutputDebugStringA(Utils::String::VA("%s: %s", i->first.data(), i->second.data()));
}
}
json11::Json InfoString::to_json()
{
return this->KeyValuePairs;
}
}

25
src/Utils/InfoString.hpp Normal file
View File

@ -0,0 +1,25 @@
#define ARR_SIZE(x) (sizeof(x) / sizeof(x[0]))
namespace Utils
{
class InfoString
{
public:
InfoString() {};
InfoString(std::string buffer) : InfoString() { this->Parse(buffer); };
InfoString(const InfoString &obj) : KeyValuePairs(obj.KeyValuePairs) {};
void Set(std::string key, std::string value);
std::string Get(std::string key);
std::string Build();
void Dump();
json11::Json to_json();
private:
std::map<std::string, std::string> KeyValuePairs;
void Parse(std::string buffer);
};
}

View File

@ -75,7 +75,7 @@ namespace Utils
if (Stream::CriticalSectionState != 0)
{
MessageBoxA(0, Utils::VA("Invalid critical section state '%i' for stream destruction!", Stream::CriticalSectionState), "WARNING", MB_ICONEXCLAMATION);
MessageBoxA(0, Utils::String::VA("Invalid critical section state '%i' for stream destruction!", Stream::CriticalSectionState), "WARNING", MB_ICONEXCLAMATION);
}
};
@ -103,7 +103,7 @@ namespace Utils
if (Stream::IsCriticalSection() && Stream::Length() + (size * count) > Stream::Capacity())
{
MessageBoxA(0, Utils::VA("Potential stream reallocation during critical operation detected! Writing data of the length 0x%X exceeds the allocated stream size of 0x%X\n", (size * count), Stream::Capacity()), "ERROR", MB_ICONERROR);
MessageBoxA(0, Utils::String::VA("Potential stream reallocation during critical operation detected! Writing data of the length 0x%X exceeds the allocated stream size of 0x%X\n", (size * count), Stream::Capacity()), "ERROR", MB_ICONERROR);
__debugbreak();
}

119
src/Utils/String.cpp Normal file
View File

@ -0,0 +1,119 @@
#include "STDInclude.hpp"
namespace Utils
{
namespace String
{
std::string StrToLower(std::string input)
{
std::transform(input.begin(), input.end(), input.begin(), ::tolower);
return input;
}
std::string StrToUpper(std::string input)
{
std::transform(input.begin(), input.end(), input.begin(), ::toupper);
return input;
}
bool EndsWith(std::string haystack, std::string needle)
{
return (strstr(haystack.data(), needle.data()) == (haystack.data() + haystack.size() - needle.size()));
}
std::string DumpHex(std::string data, std::string separator)
{
std::string result;
for (unsigned int i = 0; i < data.size(); ++i)
{
if (i > 0)
{
result.append(separator);
}
result.append(fmt::sprintf("%02X", data[i] & 0xFF));
}
return result;
}
std::string XORString(std::string str, char value)
{
for (unsigned int i = 0; i < str.size(); ++i)
{
str[i] ^= value;
}
return str;
}
std::vector<std::string> Explode(const std::string& str, char delim)
{
std::vector<std::string> result;
std::istringstream iss(str);
for (std::string token; std::getline(iss, token, delim);)
{
std::string _entry = std::move(token);
// Remove trailing 0x0 bytes
while (_entry.size() && !_entry[_entry.size() - 1])
{
_entry = _entry.substr(0, _entry.size() - 1);
}
result.push_back(_entry);
}
return result;
}
void Replace(std::string &string, std::string find, std::string replace)
{
size_t nPos = 0;
while ((nPos = string.find(find, nPos)) != std::string::npos)
{
string = string.replace(nPos, find.length(), replace);
nPos += replace.length();
}
}
bool StartsWith(std::string haystack, std::string needle)
{
return (haystack.size() >= needle.size() && !strncmp(needle.data(), haystack.data(), needle.size()));
}
// trim from start
std::string &LTrim(std::string &s)
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
return s;
}
// trim from end
std::string &RTrim(std::string &s)
{
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
return s;
}
// trim from both ends
std::string &Trim(std::string &s)
{
return LTrim(RTrim(s));
}
std::string FormatTimeSpan(int milliseconds)
{
int secondsTotal = milliseconds / 1000;
int seconds = secondsTotal % 60;
int minutesTotal = secondsTotal / 60;
int minutes = minutesTotal % 60;
int hoursTotal = minutesTotal / 60;
return fmt::sprintf("%02d:%02d:%02d", hoursTotal, minutes, seconds);
}
}
}

38
src/Utils/String.hpp Normal file
View File

@ -0,0 +1,38 @@
namespace Utils
{
namespace String
{
template <typename ...Args>
const char* VA(std::string message, Args && ...args)
{
#define VA_BUFFER_COUNT 4
#define VA_BUFFER_SIZE 65536
static char g_vaBuffer[VA_BUFFER_COUNT][VA_BUFFER_SIZE];
static int g_vaNextBufferIndex = 0;
char* buffer = g_vaBuffer[g_vaNextBufferIndex];
std::string str = fmt::sprintf(message, std::forward<Args>(args)...);
strncpy_s(g_vaBuffer[g_vaNextBufferIndex], str.data(), VA_BUFFER_SIZE);
g_vaNextBufferIndex = (g_vaNextBufferIndex + 1) % VA_BUFFER_COUNT;
return buffer;
}
std::string StrToLower(std::string input);
std::string StrToUpper(std::string input);
bool EndsWith(std::string haystack, std::string needle);
std::vector<std::string> Explode(const std::string& str, char delim);
void Replace(std::string &string, std::string find, std::string replace);
bool StartsWith(std::string haystack, std::string needle);
std::string &LTrim(std::string &s);
std::string &RTrim(std::string &s);
std::string &Trim(std::string &s);
std::string FormatTimeSpan(int milliseconds);
std::string DumpHex(std::string data, std::string separator = " ");
std::string XORString(std::string str, char value);
}
}

View File

@ -1,8 +1,5 @@
#include "STDInclude.hpp"
#define VA_BUFFER_COUNT 4
#define VA_BUFFER_SIZE 65536
namespace Utils
{
std::string GetMimeType(std::string url)
@ -19,64 +16,6 @@ namespace Utils
return "application/octet-stream";
}
const char *VA(const char *fmt, ...)
{
static char g_vaBuffer[VA_BUFFER_COUNT][VA_BUFFER_SIZE];
static int g_vaNextBufferIndex = 0;
va_list ap;
va_start(ap, fmt);
char* dest = g_vaBuffer[g_vaNextBufferIndex];
vsnprintf(g_vaBuffer[g_vaNextBufferIndex], VA_BUFFER_SIZE, fmt, ap);
g_vaNextBufferIndex = (g_vaNextBufferIndex + 1) % VA_BUFFER_COUNT;
va_end(ap);
return dest;
}
std::string StrToLower(std::string input)
{
std::transform(input.begin(), input.end(), input.begin(), ::tolower);
return input;
}
std::string StrToUpper(std::string input)
{
std::transform(input.begin(), input.end(), input.begin(), ::toupper);
return input;
}
bool EndsWith(std::string haystack, std::string needle)
{
return (strstr(haystack.data(), needle.data()) == (haystack.data() + haystack.size() - needle.size()));
}
std::string DumpHex(std::string data, std::string separator)
{
std::string result;
for (unsigned int i = 0; i < data.size(); ++i)
{
if (i > 0)
{
result.append(separator);
}
result.append(Utils::VA("%02X", data[i] & 0xFF));
}
return result;
}
std::string XORString(std::string str, char value)
{
for (unsigned int i = 0; i < str.size(); ++i)
{
str[i] ^= value;
}
return str;
}
// Complementary function for memset, which checks if a memory is set
bool MemIsSet(void* mem, char chr, size_t length)
{
@ -93,195 +32,10 @@ namespace Utils
return true;
}
std::vector<std::string> Explode(const std::string& str, char delim)
{
std::vector<std::string> result;
std::istringstream iss(str);
for (std::string token; std::getline(iss, token, delim);)
{
std::string _entry = std::move(token);
// Remove trailing 0x0 bytes
while (_entry.size() && !_entry[_entry.size() - 1])
{
_entry = _entry.substr(0, _entry.size() - 1);
}
result.push_back(_entry);
}
return result;
}
void Replace(std::string &string, std::string find, std::string replace)
{
size_t nPos = 0;
while ((nPos = string.find(find, nPos)) != std::string::npos)
{
string = string.replace(nPos, find.length(), replace);
nPos += replace.length();
}
}
bool StartsWith(std::string haystack, std::string needle)
{
return (haystack.size() >= needle.size() && !strncmp(needle.data(), haystack.data(), needle.size()));
}
// trim from start
std::string &LTrim(std::string &s)
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
return s;
}
// trim from end
std::string &RTrim(std::string &s)
{
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
return s;
}
// trim from both ends
std::string &Trim(std::string &s)
{
return LTrim(RTrim(s));
}
std::string FormatTimeSpan(int milliseconds)
{
int secondsTotal = milliseconds / 1000;
int seconds = secondsTotal % 60;
int minutesTotal = secondsTotal / 60;
int minutes = minutesTotal % 60;
int hoursTotal = minutesTotal / 60;
return Utils::VA("%02d:%02d:%02d", hoursTotal, minutes, seconds);
}
std::string ParseChallenge(std::string data)
{
auto pos = data.find_first_of("\n ");
if (pos == std::string::npos) return data;
return data.substr(0, pos).data();
}
// TODO: Use modern file reading methods
bool FileExists(std::string file)
{
FILE* fp;
fopen_s(&fp, file.data(), "r");
if (fp)
{
fclose(fp);
return true;
}
return false;
}
void WriteFile(std::string file, std::string data)
{
std::ofstream stream(file, std::ios::binary);
if (stream.is_open())
{
stream.write(data.data(), data.size());
stream.close();
}
}
std::string ReadFile(std::string file)
{
std::string buffer;
if (FileExists(file))
{
std::streamsize size = 0;
std::ifstream stream(file, std::ios::binary);
if (!stream.is_open()) return buffer;
stream.seekg(0, std::ios::end);
size = stream.tellg();
stream.seekg(0, std::ios::beg);
if (size > -1)
{
buffer.clear();
buffer.resize((uint32_t)size);
stream.read(const_cast<char*>(buffer.data()), size);
}
stream.close();
}
return buffer;
}
// Infostring class
void InfoString::Set(std::string key, std::string value)
{
this->KeyValuePairs[key] = value;
}
std::string InfoString::Get(std::string key)
{
if (this->KeyValuePairs.find(key) != this->KeyValuePairs.end())
{
return this->KeyValuePairs[key];
}
return "";
}
std::string InfoString::Build()
{
std::string infoString;
bool first = true;
for (auto i = this->KeyValuePairs.begin(); i != this->KeyValuePairs.end(); ++i)
{
if (first) first = false;
else infoString.append("\\");
infoString.append(i->first); // Key
infoString.append("\\");
infoString.append(i->second); // Value
}
return infoString;
}
void InfoString::Dump()
{
for (auto i = this->KeyValuePairs.begin(); i != this->KeyValuePairs.end(); ++i)
{
OutputDebugStringA(Utils::VA("%s: %s", i->first.data(), i->second.data()));
}
}
json11::Json InfoString::to_json()
{
return this->KeyValuePairs;
}
void InfoString::Parse(std::string buffer)
{
if (buffer[0] == '\\')
{
buffer = buffer.substr(1);
}
std::vector<std::string> KeyValues = Utils::Explode(buffer, '\\');
for (unsigned int i = 0; i < (KeyValues.size() - 1); i+=2)
{
this->KeyValuePairs[KeyValues[i]] = KeyValues[i + 1];
}
}
}

View File

@ -1,53 +1,9 @@
#define ARR_SIZE(x) (sizeof(x) / sizeof(x[0]))
namespace Utils
{
std::string GetMimeType(std::string url);
const char *VA(const char *fmt, ...);
std::string StrToLower(std::string input);
std::string StrToUpper(std::string input);
bool EndsWith(std::string haystack, std::string needle);
std::vector<std::string> Explode(const std::string& str, char delim);
void Replace(std::string &string, std::string find, std::string replace);
bool StartsWith(std::string haystack, std::string needle);
std::string &LTrim(std::string &s);
std::string &RTrim(std::string &s);
std::string &Trim(std::string &s);
std::string FormatTimeSpan(int milliseconds);
std::string ParseChallenge(std::string data);
bool FileExists(std::string file);
void WriteFile(std::string file, std::string data);
std::string ReadFile(std::string file);
std::string DumpHex(std::string data, std::string separator = " ");
std::string XORString(std::string str, char value);
bool MemIsSet(void* mem, char chr, size_t length);
class InfoString
{
public:
InfoString() {};
InfoString(std::string buffer) : InfoString() { this->Parse(buffer); };
InfoString(const InfoString &obj) : KeyValuePairs(obj.KeyValuePairs) {};
void Set(std::string key, std::string value);
std::string Get(std::string key);
std::string Build();
void Dump();
json11::Json to_json();
private:
std::map<std::string, std::string> KeyValuePairs;
void Parse(std::string buffer);
};
template <typename T> void Merge(std::vector<T>* target, T* source, size_t length)
{
if (source)