iw4x-client/src/Utils/String.cpp
2022-02-27 16:42:53 +00:00

233 lines
5.2 KiB
C++

#include <STDInclude.hpp>
#ifdef ENABLE_BASE128
#include "base128.h"
#endif
namespace Utils
{
namespace String
{
const char *VA(const char *fmt, ...)
{
static VAProvider<4, 100> globalProvider;
static thread_local VAProvider<8, 256> provider;
va_list ap;
va_start(ap, fmt);
const char* result;
if (Components::Loader::IsUninitializing()) result = globalProvider.get(fmt, ap);
else result = provider.get(fmt, ap);
va_end(ap);
return result;
}
std::string ToLower(std::string input)
{
std::transform(input.begin(), input.end(), input.begin(), ::tolower);
return input;
}
std::string ToUpper(std::string input)
{
std::transform(input.begin(), input.end(), input.begin(), ::toupper);
return input;
}
std::string DumpHex(const std::string& data, const std::string& separator)
{
std::string result;
for (unsigned int i = 0; i < data.size(); ++i)
{
if (i > 0)
{
result.append(separator);
}
result.append(Utils::String::VA("%02X", data[i] & 0xFF));
}
return result;
}
std::string XOR(std::string str, char value)
{
for (unsigned int i = 0; i < str.size(); ++i)
{
str[i] ^= value;
}
return str;
}
std::vector<std::string> Split(const std::string& str, const char delim)
{
std::stringstream ss(str);
std::string item;
std::vector<std::string> elems;
while (std::getline(ss, item, delim))
{
elems.push_back(item); // elems.push_back(std::move(item)); // if C++11 (based on comment from S1x)
}
return elems;
}
void Replace(std::string &string, const std::string& find, const 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(const std::string& haystack, const std::string& needle)
{
return (haystack.size() >= needle.size() && haystack.substr(0, needle.size()) == needle);
}
bool EndsWith(const std::string& haystack, const std::string& needle)
{
return (haystack.size() >= needle.size() && haystack.substr(haystack.size() - needle.size()) == needle);
}
int IsSpace(int c)
{
if (c < -1) return 0;
return _isspace_l(c, nullptr);
}
// Trim from start
std::string& LTrim(std::string& str)
{
str.erase(str.begin(), std::find_if(str.begin(), str.end(), [](int val)
{
return !IsSpace(val);
}));
return str;
}
// Trim from end
std::string& RTrim(std::string& str)
{
str.erase(std::find_if(str.rbegin(), str.rend(), [](int val)
{
return !IsSpace(val);
}).base(), str.end());
return str;
}
// Trim from both ends
std::string& Trim(std::string& str)
{
return LTrim(RTrim(str));
}
std::string Convert(const std::wstring& wstr)
{
std::string result;
result.reserve(wstr.size());
for (const auto& chr : wstr)
{
result.push_back(static_cast<char>(chr));
}
return result;
}
std::wstring Convert(const std::string& str)
{
std::wstring result;
result.reserve(str.size());
for (const auto& chr : str)
{
result.push_back(static_cast<wchar_t>(chr));
}
return result;
}
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::String::VA("%02d:%02d:%02d", hoursTotal, minutes, seconds);
}
std::string FormatBandwidth(size_t bytes, int milliseconds)
{
static const char* sizes[] =
{
"B",
"KB",
"MB",
"GB",
"TB"
};
if (!milliseconds) return "0.00 B/s";
double bytesPerSecond = (1000.0 / milliseconds) * bytes;
int i;
for (i = 0; bytesPerSecond > 1000 && i < ARRAYSIZE(sizes); ++i) // 1024 or 1000?
{
bytesPerSecond /= 1000;
}
return Utils::String::VA("%.2f %s/s", static_cast<float>(bytesPerSecond), sizes[i]);
}
#ifdef ENABLE_BASE64
// Encodes a given string in Base64
std::string EncodeBase64(const char* input, const unsigned long inputSize)
{
unsigned long outlen = long(inputSize + (inputSize / 3.0) + 16);
unsigned char* outbuf = new unsigned char[outlen]; //Reserve output memory
base64_encode(reinterpret_cast<unsigned char*>(const_cast<char*>(input)), inputSize, outbuf, &outlen);
std::string ret(reinterpret_cast<char*>(outbuf), outlen);
delete[] outbuf;
return ret;
}
// Encodes a given string in Base64
std::string EncodeBase64(const std::string& input)
{
return EncodeBase64(input.data(), input.size());
}
#endif
#ifdef ENABLE_BASE128
// Encodes a given string in Base128
std::string EncodeBase128(const std::string& input)
{
base128 encoder;
void* inbuffer = const_cast<char*>(input.data());
char* buffer = encoder.encode(inbuffer, input.size());
/*
Interesting to see that the buffer returned by the encoder is not a standalone string copy
but instead is a pointer to the internal "encoded" field of the encoder. So if you deinitialize
the encoder that string will probably become garbage.
*/
std::string retval(buffer);
return retval;
}
#endif
}
}