LiteLoaderBDS-1.16.40/LiteLoader/Kernel/DB/ConnParams.cpp
2022-09-21 19:47:03 +08:00

207 lines
5.9 KiB
C++

#include <DB/ConnParams.h>
#include <Utils/StringHelper.h>
#include <LoggerAPI.h>
namespace DB {
#pragma region URL_Parser
struct URL {
std::string scheme;
std::string user;
std::string password;
std::string host;
uint16_t port = 0;
std::string path;
std::map<std::string, std::string> query;
std::string fragment;
};
URL ParseURL(const std::string& url) {
URL result;
std::string cur = url;
size_t pos = cur.find("://");
if (pos != std::string::npos) {
result.scheme = cur.substr(0, pos);
cur = cur.substr(pos + 3);
}
pos = cur.find('@');
auto pos0 = pos;
if (pos != std::string::npos) {
std::string userInfo = cur.substr(0, pos);
pos = userInfo.find(':');
if (pos != std::string::npos) {
result.user = userInfo.substr(0, pos);
result.password = userInfo.substr(pos + 1);
} else
result.user = userInfo;
cur = cur.substr(pos0 + 1);
}
pos = cur.find_first_of("/?#");
auto pos1 = pos;
std::string address = cur.substr(0, pos);
pos = address.find(':');
if (pos != std::string::npos) {
result.host = address.substr(0, pos);
result.port = static_cast<uint16_t>(std::stoi(address.substr(pos + 1)));
} else
result.host = address;
if (pos1 == std::string::npos)
return result;
else
cur = cur.substr(pos1);
pos = cur.find_first_of("?#");
result.path = cur.substr(0, pos);
if (pos == std::string::npos)
return result;
else
cur = cur.substr(pos);
if (cur[0] == '?') {
cur = cur.substr(1);
pos = cur.find('#');
std::string query = cur.substr(0, pos);
if (pos != std::string::npos) {
result.fragment = cur.substr(pos + 1);
}
std::vector<std::string> pairs = SplitStrWithPattern(query, "&");
for (auto& pair : pairs) {
std::string k, v;
pos = pair.find('=');
if (pos == std::string::npos)
k = pair;
else {
k = pair.substr(0, pos);
v = pair.substr(pos + 1);
}
result.query.emplace(k, v);
}
} else if (cur[0] == '#') {
result.fragment = cur.substr(1);
}
return result;
}
extern Logger dbLogger;
void PrintURL(const URL& url) {
dbLogger.debug("Parsed URL");
dbLogger.debug("scheme: {}", url.scheme);
dbLogger.debug("user: {}", url.user);
dbLogger.debug("password: {}", url.password);
dbLogger.debug("host: {}", url.host);
dbLogger.debug("port: {}", url.port);
dbLogger.debug("path: {}", url.path);
dbLogger.debug("query:");
for (auto& pair : url.query)
dbLogger.debug("- {}: {}", pair.first, pair.second);
dbLogger.debug("fragment: {}", url.fragment);
}
#pragma endregion
ConnParams::ConnParams(const std::initializer_list<Any>& list)
: std::unordered_map<std::string, Any>() {
bool key = true;
std::string keyName;
for (auto& item : list) {
if (key) {
if (item.is_string()) {
throw std::invalid_argument("ConnParams::ConnParams: Key must be string");
}
keyName = item.get<std::string>();
key = false;
} else {
insert({keyName, item});
key = true;
}
}
auto host = getHost();
if (host.find(':') != std::string::npos) {
host = host.substr(0, host.find_last_of(':'));
auto port = host.substr(host.find_last_of(':') + 1);
(*this)["host"] = host;
(*this)["port"] = std::stoi(port);
}
}
ConnParams::ConnParams(const std::initializer_list<std::pair<std::string, Any>>& list)
: std::unordered_map<std::string, Any>() {
for (auto& item : list) {
insert(item);
}
auto host = getHost();
if (host.find(':') != std::string::npos) {
host = host.substr(0, host.find_last_of(':'));
auto port = host.substr(host.find_last_of(':') + 1);
(*this)["host"] = host;
(*this)["port"] = std::stoi(port);
}
}
ConnParams::ConnParams(const std::string& str)
: std::unordered_map<std::string, Any>() {
raw = str;
auto url = ParseURL(str);
#if defined(LLDB_DEBUG_MODE)
PrintURL(url);
#endif
if (!url.scheme.empty())
insert({"scheme", url.scheme});
if (!url.host.empty())
insert({"host", url.host});
if (url.port)
insert({"port", url.port});
if (!url.user.empty())
insert({"user", url.user});
if (!url.password.empty())
insert({"password", url.password});
if (!url.path.empty()) {
std::string path = url.path;
if (path[0] == '/')
path = path.substr(1);
insert({"path", path});
}
if (!url.fragment.empty())
insert({"fragment", url.fragment});
for (auto& pair : url.query) {
insert({pair.first, Any::str2any(pair.second)});
}
}
ConnParams::ConnParams(const char* str)
: std::unordered_map<std::string, Any>() {
*this = ConnParams(std::string(str));
}
std::string ConnParams::getScheme() {
return get<std::string>({"scheme", "protocol", "type"}, true);
}
std::string ConnParams::getHost() {
return get<std::string>({"host", "hostname", "server", "server_name", "ip", "address"}, true);
}
uint16_t ConnParams::getPort() {
return get<uint16_t>({"port", "port_number", "port_num", "port_id", "portid"}, true, 0);
}
std::string ConnParams::getUsername() {
return get<std::string>({"user", "username", "user_name", "usr", "usrname"}, true);
}
std::string ConnParams::getPassword() {
return get<std::string>({"password", "pass", "passwd", "pass_word"}, true);
}
std::string ConnParams::getDatabase() {
return get<std::string>({"database", "db", "db_name", "dbname", "path"}, true);
}
std::string ConnParams::getPath() {
return get<std::string>({"path", "file", "file_name", "filename"}, true);
}
std::string ConnParams::getRaw() {
return raw;
}
} // namespace DB