std::string_view 的使用
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
#include <utility>
|
||||
#include <string_view>
|
||||
|
||||
namespace External_Database_Utils {
|
||||
namespace {
|
||||
@@ -27,15 +28,15 @@ const std::vector<std::string> kTar1090Columns = {
|
||||
"type_name", "year", "operator_info"};
|
||||
const std::vector<std::string> kTar1090PrimaryKey = {"icao24"};
|
||||
|
||||
std::pair<std::string, std::string> split_url(const std::string &url) {
|
||||
std::pair<std::string, std::string> split_url(std::string_view url) {
|
||||
const auto scheme_end = url.find("://");
|
||||
if (scheme_end == std::string::npos) {
|
||||
throw std::runtime_error("Invalid download URL: " + url);
|
||||
throw std::runtime_error("Invalid download URL: " + std::string(url));
|
||||
}
|
||||
const auto path_begin = url.find('/', scheme_end + 3);
|
||||
if (path_begin == std::string::npos)
|
||||
return {url, "/"};
|
||||
return {url.substr(0, path_begin), url.substr(path_begin)};
|
||||
return {std::string(url), "/"};
|
||||
return {std::string(url.substr(0, path_begin)), std::string(url.substr(path_begin))};
|
||||
}
|
||||
|
||||
void replace_file(const std::filesystem::path &temp_file,
|
||||
@@ -51,7 +52,7 @@ void replace_file(const std::filesystem::path &temp_file,
|
||||
}
|
||||
|
||||
std::string
|
||||
create_csv_table_sql(const std::string &table_name,
|
||||
create_csv_table_sql(std::string_view table_name,
|
||||
const std::vector<std::string> &columns,
|
||||
const std::vector<std::string> &primary_key_columns) {
|
||||
std::ostringstream sql;
|
||||
@@ -133,7 +134,7 @@ private:
|
||||
|
||||
class Tar1090_Aircraft_Resource final : public External_Resources {
|
||||
public:
|
||||
Tar1090_Aircraft_Resource(std::string name, std::string description,
|
||||
Tar1090_Aircraft_Resource(std::string_view name, std::string_view description,
|
||||
const std::uint64_t update_interval_seconds)
|
||||
: External_Resources(std::move(name), "aircraft.csv", kTar1090Url,
|
||||
std::move(description), update_interval_seconds) {}
|
||||
@@ -205,7 +206,7 @@ protected:
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string quote_identifier(const std::string &value) {
|
||||
std::string quote_identifier(std::string_view value) {
|
||||
std::string result = "\"";
|
||||
for (const char ch : value) {
|
||||
result += ch;
|
||||
@@ -216,33 +217,35 @@ std::string quote_identifier(const std::string &value) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string normalize_key(std::string value) {
|
||||
std::string normalize_key(std::string_view value) {
|
||||
std::string result(value);
|
||||
const auto is_space = [](unsigned char ch) { return std::isspace(ch) != 0; };
|
||||
value.erase(value.begin(),
|
||||
std::find_if(value.begin(), value.end(),
|
||||
result.erase(result.begin(),
|
||||
std::find_if(result.begin(), result.end(),
|
||||
[&](char ch) { return !is_space(ch); }));
|
||||
value.erase(std::find_if(value.rbegin(), value.rend(),
|
||||
result.erase(std::find_if(result.rbegin(), result.rend(),
|
||||
[&](char ch) { return !is_space(ch); })
|
||||
.base(),
|
||||
value.end());
|
||||
.base(),
|
||||
result.end());
|
||||
std::transform(
|
||||
value.begin(), value.end(), value.begin(),
|
||||
result.begin(), result.end(), result.begin(),
|
||||
[](unsigned char ch) { return static_cast<char>(std::toupper(ch)); });
|
||||
return value;
|
||||
return result;
|
||||
}
|
||||
|
||||
std::optional<std::string> normalize_field(std::string value) {
|
||||
std::optional<std::string> normalize_field(std::string_view value) {
|
||||
std::string result(value);
|
||||
const auto is_space = [](unsigned char ch) { return std::isspace(ch) != 0; };
|
||||
value.erase(value.begin(),
|
||||
std::find_if(value.begin(), value.end(),
|
||||
result.erase(result.begin(),
|
||||
std::find_if(result.begin(), result.end(),
|
||||
[&](char ch) { return !is_space(ch); }));
|
||||
value.erase(std::find_if(value.rbegin(), value.rend(),
|
||||
result.erase(std::find_if(result.rbegin(), result.rend(),
|
||||
[&](char ch) { return !is_space(ch); })
|
||||
.base(),
|
||||
value.end());
|
||||
if (value.empty())
|
||||
.base(),
|
||||
result.end());
|
||||
if (result.empty())
|
||||
return std::nullopt;
|
||||
return value;
|
||||
return result;
|
||||
}
|
||||
|
||||
void bind_optional(SQLite::Statement &statement, const int index,
|
||||
@@ -295,7 +298,7 @@ bool read_csv_row(std::istream &input, std::vector<std::string> &fields,
|
||||
}
|
||||
|
||||
std::string
|
||||
make_upsert_sql(const std::string &table_name,
|
||||
make_upsert_sql(std::string_view table_name,
|
||||
const std::vector<std::string> &columns,
|
||||
const std::vector<std::string> &primary_key_columns) {
|
||||
std::ostringstream sql;
|
||||
@@ -335,12 +338,13 @@ make_upsert_sql(const std::string &table_name,
|
||||
return sql.str();
|
||||
}
|
||||
|
||||
void download_to_file(std::string url,
|
||||
void download_to_file(std::string_view url,
|
||||
const std::filesystem::path &target_file) {
|
||||
std::filesystem::create_directories(target_file.parent_path());
|
||||
constexpr int kMaxRedirects = 5;
|
||||
auto current_url = std::string(url);
|
||||
for (int redirect = 0; redirect <= kMaxRedirects; ++redirect) {
|
||||
const auto [origin, path] = split_url(url);
|
||||
const auto [origin, path] = split_url(current_url);
|
||||
auto client = drogon::HttpClient::newHttpClient(origin);
|
||||
auto request = drogon::HttpRequest::newHttpRequest();
|
||||
request->setMethod(drogon::Get);
|
||||
@@ -348,19 +352,19 @@ void download_to_file(std::string url,
|
||||
request->addHeader("User-Agent", "ECAP_Server external database updater");
|
||||
const auto [result, response] = client->sendRequest(request, 600.0);
|
||||
if (result != drogon::ReqResult::Ok || !response) {
|
||||
throw std::runtime_error("Download failed: " + url);
|
||||
throw std::runtime_error("Download failed: " + current_url);
|
||||
}
|
||||
const int status = static_cast<int>(response->getStatusCode());
|
||||
if (status >= 300 && status < 400) {
|
||||
const auto location = response->getHeader("location");
|
||||
if (location.empty())
|
||||
throw std::runtime_error("Redirect has no location: " + url);
|
||||
url = location.front() == '/' ? origin + location : location;
|
||||
throw std::runtime_error("Redirect has no location: " + current_url);
|
||||
current_url = location.front() == '/' ? origin + location : location;
|
||||
continue;
|
||||
}
|
||||
if (status != 200) {
|
||||
throw std::runtime_error("Download returned HTTP " +
|
||||
std::to_string(status) + ": " + url);
|
||||
std::to_string(status) + ": " + current_url);
|
||||
}
|
||||
const auto temp_file = target_file.string() + ".tmp";
|
||||
std::ofstream output(temp_file, std::ios::binary | std::ios::trunc);
|
||||
@@ -374,7 +378,7 @@ void download_to_file(std::string url,
|
||||
replace_file(temp_file, target_file);
|
||||
return;
|
||||
}
|
||||
throw std::runtime_error("Too many redirects while downloading: " + url);
|
||||
throw std::runtime_error("Too many redirects while downloading: " + current_url);
|
||||
}
|
||||
|
||||
void decompress_gzip(const std::filesystem::path &gzip_file,
|
||||
@@ -404,7 +408,7 @@ void decompress_gzip(const std::filesystem::path &gzip_file,
|
||||
|
||||
std::size_t import_header_csv(
|
||||
SQLite::Database &db, const std::filesystem::path &source_file,
|
||||
const std::string &table_name, const std::vector<std::string> &columns,
|
||||
std::string_view table_name, const std::vector<std::string> &columns,
|
||||
const std::vector<std::string> &primary_key_columns, const char delimiter) {
|
||||
std::ifstream input(source_file, std::ios::binary);
|
||||
if (!input)
|
||||
@@ -478,7 +482,7 @@ make_schema_only_resource(Schema_Only_Resource_Config config) {
|
||||
}
|
||||
|
||||
std::unique_ptr<External_Resources>
|
||||
make_tar1090_aircraft_resource(std::string name, std::string description,
|
||||
make_tar1090_aircraft_resource(std::string_view name, std::string_view description,
|
||||
const std::uint64_t update_interval_seconds) {
|
||||
return std::make_unique<Tar1090_Aircraft_Resource>(
|
||||
std::move(name), std::move(description), update_interval_seconds);
|
||||
|
||||
Reference in New Issue
Block a user