213 lines
6.2 KiB
C++
213 lines
6.2 KiB
C++
#include "Misc.hpp"
|
|
|
|
#include <codecvt>
|
|
#include <locale>
|
|
#include "fmt/core.h"
|
|
|
|
#ifndef GKMS_WINDOWS
|
|
#include <jni.h>
|
|
|
|
extern JavaVM* g_javaVM;
|
|
#else
|
|
#include "cpprest/details/http_helpers.h"
|
|
#endif
|
|
|
|
|
|
namespace GakumasLocal::Misc {
|
|
std::u16string ToUTF16(const std::string_view& str) {
|
|
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> utf16conv;
|
|
return utf16conv.from_bytes(str.data(), str.data() + str.size());
|
|
}
|
|
|
|
std::string ToUTF8(const std::u16string_view& str) {
|
|
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> utf16conv;
|
|
return utf16conv.to_bytes(str.data(), str.data() + str.size());
|
|
}
|
|
|
|
#ifdef GKMS_WINDOWS
|
|
std::string ToUTF8(const std::wstring_view& str) {
|
|
return utility::conversions::to_utf8string(str.data());
|
|
}
|
|
#endif
|
|
|
|
#ifndef GKMS_WINDOWS
|
|
JNIEnv* GetJNIEnv() {
|
|
if (!g_javaVM) return nullptr;
|
|
JNIEnv* env = nullptr;
|
|
if (g_javaVM->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
|
|
int status = g_javaVM->AttachCurrentThread(&env, nullptr);
|
|
if (status < 0) {
|
|
return nullptr;
|
|
}
|
|
}
|
|
return env;
|
|
}
|
|
#endif
|
|
|
|
CSEnum::CSEnum(const std::string& name, const int value) {
|
|
this->Add(name, value);
|
|
}
|
|
|
|
CSEnum::CSEnum(const std::vector<std::string>& names, const std::vector<int>& values) {
|
|
if (names.size() != values.size()) return;
|
|
this->names = names;
|
|
this->values = values;
|
|
}
|
|
|
|
int CSEnum::GetIndex() {
|
|
return currIndex;
|
|
}
|
|
|
|
void CSEnum::SetIndex(int index) {
|
|
if (index < 0) return;
|
|
if (index + 1 >= values.size()) return;
|
|
currIndex = index;
|
|
}
|
|
|
|
int CSEnum::GetTotalLength() {
|
|
return values.size();
|
|
}
|
|
|
|
void CSEnum::Add(const std::string &name, const int value) {
|
|
this->names.push_back(name);
|
|
this->values.push_back(value);
|
|
}
|
|
|
|
std::pair<std::string, int> CSEnum::GetCurrent() {
|
|
return std::make_pair(names[currIndex], values[currIndex]);
|
|
}
|
|
|
|
std::pair<std::string, int> CSEnum::Last() {
|
|
const auto maxIndex = this->GetTotalLength() - 1;
|
|
if (currIndex <= 0) {
|
|
currIndex = maxIndex;
|
|
}
|
|
else {
|
|
currIndex--;
|
|
}
|
|
return this->GetCurrent();
|
|
}
|
|
|
|
std::pair<std::string, int> CSEnum::Next() {
|
|
const auto maxIndex = this->GetTotalLength() - 1;
|
|
if (currIndex >= maxIndex) {
|
|
currIndex = 0;
|
|
}
|
|
else {
|
|
currIndex++;
|
|
}
|
|
return this->GetCurrent();
|
|
}
|
|
|
|
int CSEnum::GetValueByName(const std::string &name) {
|
|
for (int i = 0; i < names.size(); i++) {
|
|
if (names[i] == name) {
|
|
return values[i];
|
|
}
|
|
}
|
|
return values[0];
|
|
}
|
|
|
|
|
|
namespace StringFormat {
|
|
template<typename... Args>
|
|
std::string string_format(const std::string& fmt, Args&&... args) {
|
|
// return std::vformat(fmt, std::make_format_args(std::forward<Args>(args)...));
|
|
return fmt::format(fmt::runtime(fmt), std::forward<Args>(args)...);
|
|
}
|
|
|
|
|
|
template <std::size_t N, std::size_t... Indices, typename T>
|
|
auto vectorToTupleImpl(const std::vector<T>& vec, std::index_sequence<Indices...>) {
|
|
if (vec.size() != N) {
|
|
// printf("vec.size: %zu, N: %zu\n", vec.size(), N);
|
|
throw std::out_of_range("Vector size does not match tuple size.");
|
|
}
|
|
return std::make_tuple(vec[Indices]...);
|
|
}
|
|
|
|
template <std::size_t N, typename T>
|
|
auto vectorToTuple(const std::vector<T>& vec) {
|
|
return vectorToTupleImpl<N>(vec, std::make_index_sequence<N>{});
|
|
}
|
|
|
|
|
|
template <typename T>
|
|
std::string stringFormat(const std::string& fmt, const std::vector<T>& vec) {
|
|
std::string ret = fmt;
|
|
|
|
#define CASE_ARG_COUNT(N) \
|
|
case N: {\
|
|
auto tp = vectorToTuple<N>(vec); \
|
|
std::apply([&](auto&&... args) { \
|
|
ret = string_format(fmt, args...); \
|
|
}, tp); } break;
|
|
|
|
switch (vec.size()) {
|
|
CASE_ARG_COUNT(1)
|
|
CASE_ARG_COUNT(2)
|
|
CASE_ARG_COUNT(3)
|
|
CASE_ARG_COUNT(4)
|
|
CASE_ARG_COUNT(5)
|
|
CASE_ARG_COUNT(6)
|
|
CASE_ARG_COUNT(7)
|
|
CASE_ARG_COUNT(8)
|
|
CASE_ARG_COUNT(9)
|
|
CASE_ARG_COUNT(10)
|
|
CASE_ARG_COUNT(11)
|
|
CASE_ARG_COUNT(12)
|
|
CASE_ARG_COUNT(13)
|
|
CASE_ARG_COUNT(14)
|
|
CASE_ARG_COUNT(15)
|
|
CASE_ARG_COUNT(16)
|
|
CASE_ARG_COUNT(17)
|
|
CASE_ARG_COUNT(18)
|
|
CASE_ARG_COUNT(19)
|
|
CASE_ARG_COUNT(20)
|
|
CASE_ARG_COUNT(21)
|
|
CASE_ARG_COUNT(22)
|
|
CASE_ARG_COUNT(23)
|
|
CASE_ARG_COUNT(24)
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
std::string stringFormatString(const std::string& fmt, const std::vector<std::string>& vec) {
|
|
try {
|
|
return stringFormat(fmt, vec);
|
|
}
|
|
catch (std::exception& e) {
|
|
return fmt;
|
|
}
|
|
}
|
|
|
|
std::vector<std::string> split(const std::string& str, char delimiter) {
|
|
std::vector<std::string> result;
|
|
std::string current;
|
|
for (char c : str) {
|
|
if (c == delimiter) {
|
|
if (!current.empty()) {
|
|
result.push_back(current);
|
|
}
|
|
current.clear();
|
|
} else {
|
|
current += c;
|
|
}
|
|
}
|
|
if (!current.empty()) {
|
|
result.push_back(current);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::pair<std::string, std::string> split_once(const std::string& str, const std::string& delimiter) {
|
|
size_t pos = str.find(delimiter);
|
|
if (pos != std::string::npos) {
|
|
return {str.substr(0, pos), str.substr(pos + delimiter.size())};
|
|
}
|
|
return {str, ""};
|
|
}
|
|
}
|
|
|
|
}
|