C++17ification.
C++17ification! - Filesystem interaction now uses std::filesystem::path. - Usage of const char*, std::string have been changed to std::string_view where appropriate. - Usage of printf-style functions changed to use fmt.
This commit is contained in:
@@ -2,13 +2,22 @@
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2019 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "cvar.h"
|
||||
|
||||
#include "utf8.h"
|
||||
|
||||
#define UTF_CPP_CPLUSPLUS 201703L
|
||||
#include "third_party/utfcpp/source/utf8.h"
|
||||
|
||||
namespace utfcpp = utf8;
|
||||
|
||||
using u8_citer = utfcpp::iterator<std::string_view::const_iterator>;
|
||||
|
||||
namespace cvar {
|
||||
|
||||
cxxopts::Options options("xenia", "Xbox 360 Emulator");
|
||||
@@ -22,37 +31,45 @@ void PrintHelpAndExit() {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void ParseLaunchArguments(int argc, char** argv,
|
||||
const std::string& positional_help,
|
||||
void ParseLaunchArguments(int& argc, char**& argv,
|
||||
const std::string_view positional_help,
|
||||
const std::vector<std::string>& positional_options) {
|
||||
options.add_options()("help", "Prints help and exit.");
|
||||
if (!CmdVars) CmdVars = new std::map<std::string, ICommandVar*>();
|
||||
if (!ConfigVars) ConfigVars = new std::map<std::string, IConfigVar*>();
|
||||
|
||||
if (!CmdVars) {
|
||||
CmdVars = new std::map<std::string, ICommandVar*>();
|
||||
}
|
||||
|
||||
if (!ConfigVars) {
|
||||
ConfigVars = new std::map<std::string, IConfigVar*>();
|
||||
}
|
||||
|
||||
for (auto& it : *CmdVars) {
|
||||
auto cmdVar = it.second;
|
||||
cmdVar->AddToLaunchOptions(&options);
|
||||
}
|
||||
std::vector<IConfigVar*> vars;
|
||||
for (const auto& s : *ConfigVars) vars.push_back(s.second);
|
||||
|
||||
for (auto& it : *ConfigVars) {
|
||||
for (const auto& it : *ConfigVars) {
|
||||
auto configVar = it.second;
|
||||
configVar->AddToLaunchOptions(&options);
|
||||
}
|
||||
|
||||
try {
|
||||
options.positional_help(positional_help);
|
||||
options.positional_help(std::string(positional_help));
|
||||
options.parse_positional(positional_options);
|
||||
|
||||
auto result = options.parse(argc, argv);
|
||||
if (result.count("help")) {
|
||||
PrintHelpAndExit();
|
||||
}
|
||||
|
||||
for (auto& it : *CmdVars) {
|
||||
auto cmdVar = static_cast<ICommandVar*>(it.second);
|
||||
if (result.count(cmdVar->name())) {
|
||||
cmdVar->LoadFromLaunchOptions(&result);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& it : *ConfigVars) {
|
||||
auto configVar = static_cast<IConfigVar*>(it.second);
|
||||
if (result.count(configVar->name())) {
|
||||
@@ -67,48 +84,46 @@ void ParseLaunchArguments(int argc, char** argv,
|
||||
|
||||
namespace toml {
|
||||
|
||||
std::string EscapeBasicString(const std::string& str) {
|
||||
std::string EscapeBasicString(const std::string_view view) {
|
||||
std::string result;
|
||||
for (auto c : str) {
|
||||
auto begin = u8_citer(view.cbegin(), view.cbegin(), view.cend());
|
||||
auto end = u8_citer(view.cend(), view.cbegin(), view.cend());
|
||||
for (auto it = begin; it != end; ++it) {
|
||||
auto c = *it;
|
||||
if (c == '\b') {
|
||||
result += "\\b";
|
||||
result += u8"\\b";
|
||||
} else if (c == '\t') {
|
||||
result += "\\t";
|
||||
result += u8"\\t";
|
||||
} else if (c == '\n') {
|
||||
result += "\\n";
|
||||
result += u8"\\n";
|
||||
} else if (c == '\f') {
|
||||
result += "\\f";
|
||||
result += u8"\\f";
|
||||
} else if (c == '\r') {
|
||||
result += "\\r";
|
||||
result += u8"\\r";
|
||||
} else if (c == '"') {
|
||||
result += "\\\"";
|
||||
result += u8"\\\"";
|
||||
} else if (c == '\\') {
|
||||
result += "\\\\";
|
||||
} else if (static_cast<uint32_t>(c) < 0x20 ||
|
||||
static_cast<uint32_t>(c) == 0x7F) {
|
||||
auto v = static_cast<uint32_t>(c);
|
||||
int w;
|
||||
if (v <= 0xFFFF) {
|
||||
result += "\\u";
|
||||
w = 4;
|
||||
result += u8"\\\\";
|
||||
} else if (c < 0x20 || c == 0x7F) {
|
||||
if (c <= 0xFFFF) {
|
||||
result += fmt::format(u8"\\u{:04X}", c);
|
||||
} else {
|
||||
result += "\\U";
|
||||
w = 8;
|
||||
result += fmt::format(u8"\\u{:08X}", c);
|
||||
}
|
||||
std::stringstream ss;
|
||||
ss << std::hex << std::setw(w) << std::setfill('0') << v;
|
||||
result += ss.str();
|
||||
} else {
|
||||
result += c;
|
||||
utfcpp::append(static_cast<char32_t>(c), result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string EscapeMultilineBasicString(const std::string& str) {
|
||||
std::string EscapeMultilineBasicString(const std::string_view view) {
|
||||
std::string result;
|
||||
int quote_run = 0;
|
||||
for (char c : str) {
|
||||
auto begin = u8_citer(view.cbegin(), view.cbegin(), view.cend());
|
||||
auto end = u8_citer(view.cend(), view.cbegin(), view.cend());
|
||||
for (auto it = begin; it != end; ++it) {
|
||||
auto c = *it;
|
||||
if (quote_run > 0) {
|
||||
if (c == '"') {
|
||||
++quote_run;
|
||||
@@ -116,74 +131,67 @@ std::string EscapeMultilineBasicString(const std::string& str) {
|
||||
}
|
||||
for (int i = 0; i < quote_run; ++i) {
|
||||
if ((i % 3) == 2) {
|
||||
result += "\\";
|
||||
result += u8"\\";
|
||||
}
|
||||
result += '"';
|
||||
result += u8"\"";
|
||||
}
|
||||
quote_run = 0;
|
||||
}
|
||||
if (c == '\b') {
|
||||
result += "\\b";
|
||||
result += u8"\\b";
|
||||
} else if (c == '\t' || c == '\n') {
|
||||
result += c;
|
||||
} else if (c == '\f') {
|
||||
result += "\\f";
|
||||
result += u8"\\f";
|
||||
} else if (c == '\r') {
|
||||
// Silently drop \r.
|
||||
// result += c;
|
||||
} else if (c == '"') {
|
||||
quote_run = 1;
|
||||
} else if (c == '\\') {
|
||||
result += "\\\\";
|
||||
} else if (static_cast<uint32_t>(c) < 0x20 ||
|
||||
static_cast<uint32_t>(c) == 0x7F) {
|
||||
auto v = static_cast<uint32_t>(c);
|
||||
int w;
|
||||
if (v <= 0xFFFF) {
|
||||
result += "\\u";
|
||||
w = 4;
|
||||
result += u8"\\\\";
|
||||
} else if (c < 0x20 || c == 0x7F) {
|
||||
if (c <= 0xFFFF) {
|
||||
result += fmt::format(u8"\\u{:04X}", c);
|
||||
} else {
|
||||
result += "\\U";
|
||||
w = 8;
|
||||
result += fmt::format(u8"\\u{:08X}", c);
|
||||
}
|
||||
std::stringstream ss;
|
||||
ss << std::hex << std::setw(w) << std::setfill('0') << v;
|
||||
result += ss.str();
|
||||
} else {
|
||||
result += c;
|
||||
utfcpp::append(static_cast<char32_t>(c), result);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < quote_run; ++i) {
|
||||
if ((i % 3) == 2) {
|
||||
result += "\\";
|
||||
result += u8"\\";
|
||||
}
|
||||
result += '"';
|
||||
result += u8"\"";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string EscapeString(const std::string& val) {
|
||||
const char multiline_chars[] = "\r\n";
|
||||
const char escape_chars[] =
|
||||
std::string EscapeString(const std::string_view view) {
|
||||
const auto multiline_chars = std::string_view("\r\n");
|
||||
const auto escape_chars = std::string_view(
|
||||
"\0\b\v\f"
|
||||
"\x01\x02\x03\x04\x05\x06\x07\x0E\x0F"
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
|
||||
"'"
|
||||
"\x7F";
|
||||
if (val.find_first_of(multiline_chars) == std::string::npos) {
|
||||
"\x7F");
|
||||
|
||||
if (xe::utf8::find_any_of(view, multiline_chars) == std::string_view::npos) {
|
||||
// single line
|
||||
if (val.find_first_of(escape_chars) == std::string::npos) {
|
||||
return "'" + val + "'";
|
||||
if (xe::utf8::find_any_of(view, escape_chars) == std::string_view::npos) {
|
||||
return "'" + std::string(view) + "'";
|
||||
} else {
|
||||
return "\"" + toml::EscapeBasicString(val) + "\"";
|
||||
return "\"" + toml::EscapeBasicString(view) + "\"";
|
||||
}
|
||||
} else {
|
||||
// multi line
|
||||
if (val.find_first_of(escape_chars) == std::string::npos &&
|
||||
val.find("'''") == std::string::npos) {
|
||||
return "'''\n" + val + "'''";
|
||||
if (xe::utf8::find_any_of(view, escape_chars) == std::string_view::npos &&
|
||||
xe::utf8::find_first_of(view, u8"'''") == std::string_view::npos) {
|
||||
return "'''\n" + std::string(view) + "'''";
|
||||
} else {
|
||||
return "\"\"\"\n" + toml::EscapeMultilineBasicString(val) + "\"\"\"";
|
||||
return u8"\"\"\"\n" + toml::EscapeMultilineBasicString(view) + u8"\"\"\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user