1
0
Fork 0

Codechange: Use unique_ptr to manage ContentInfo lifetime.

Removes manually managed new/delete.
pull/13990/head
Peter Nelson 2025-04-10 08:34:59 +01:00 committed by Peter Nelson
parent 7b31f26611
commit 20d83677eb
5 changed files with 52 additions and 78 deletions

View File

@ -2171,9 +2171,9 @@ DEF_CONSOLE_CMD(ConContent)
if (argc <= 2) { if (argc <= 2) {
/* List selected content */ /* List selected content */
IConsolePrint(CC_WHITE, "id, type, state, name"); IConsolePrint(CC_WHITE, "id, type, state, name");
for (ConstContentIterator iter = _network_content_client.Begin(); iter != _network_content_client.End(); iter++) { for (const ContentInfo &ci : _network_content_client.Info()) {
if ((*iter)->state != ContentInfo::SELECTED && (*iter)->state != ContentInfo::AUTOSELECTED) continue; if (ci.state != ContentInfo::SELECTED && ci.state != ContentInfo::AUTOSELECTED) continue;
OutputContentState(**iter); OutputContentState(ci);
} }
} else if (StrEqualsIgnoreCase(argv[2], "all")) { } else if (StrEqualsIgnoreCase(argv[2], "all")) {
/* The intention of this function was that you could download /* The intention of this function was that you could download
@ -2204,9 +2204,9 @@ DEF_CONSOLE_CMD(ConContent)
if (StrEqualsIgnoreCase(argv[1], "state")) { if (StrEqualsIgnoreCase(argv[1], "state")) {
IConsolePrint(CC_WHITE, "id, type, state, name"); IConsolePrint(CC_WHITE, "id, type, state, name");
for (ConstContentIterator iter = _network_content_client.Begin(); iter != _network_content_client.End(); iter++) { for (const ContentInfo &ci : _network_content_client.Info()) {
if (argc > 2 && !StrContainsIgnoreCase((*iter)->name, argv[2])) continue; if (argc > 2 && !StrContainsIgnoreCase(ci.name, argv[2])) continue;
OutputContentState(**iter); OutputContentState(ci);
} }
return true; return true;
} }

View File

@ -82,7 +82,7 @@ static HasContentProc *GetHasContentProcforContentType(ContentType type)
bool ClientNetworkContentSocketHandler::Receive_SERVER_INFO(Packet &p) bool ClientNetworkContentSocketHandler::Receive_SERVER_INFO(Packet &p)
{ {
ContentInfo *ci = new ContentInfo(); auto ci = std::make_unique<ContentInfo>();
ci->type = (ContentType)p.Recv_uint8(); ci->type = (ContentType)p.Recv_uint8();
ci->id = (ContentID)p.Recv_uint32(); ci->id = (ContentID)p.Recv_uint32();
ci->filesize = p.Recv_uint32(); ci->filesize = p.Recv_uint32();
@ -108,7 +108,6 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_INFO(Packet &p)
for (uint i = 0; i < tag_count; i++) ci->tags.push_back(p.Recv_string(NETWORK_CONTENT_TAG_LENGTH)); for (uint i = 0; i < tag_count; i++) ci->tags.push_back(p.Recv_string(NETWORK_CONTENT_TAG_LENGTH));
if (!ci->IsValid()) { if (!ci->IsValid()) {
delete ci;
this->CloseConnection(); this->CloseConnection();
return false; return false;
} }
@ -129,7 +128,7 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_INFO(Packet &p)
if (ci->state == ContentInfo::UNSELECTED && ci->filesize == 0) ci->state = ContentInfo::DOES_NOT_EXIST; if (ci->state == ContentInfo::UNSELECTED && ci->filesize == 0) ci->state = ContentInfo::DOES_NOT_EXIST;
/* Do we already have a stub for this? */ /* Do we already have a stub for this? */
for (ContentInfo *ici : this->infos) { for (const auto &ici : this->infos) {
if (ici->type == ci->type && ici->unique_id == ci->unique_id && ci->md5sum == ici->md5sum) { if (ici->type == ci->type && ici->unique_id == ci->unique_id && ci->md5sum == ici->md5sum) {
/* Preserve the name if possible */ /* Preserve the name if possible */
if (ci->name.empty()) ci->name = ici->name; if (ci->name.empty()) ci->name = ici->name;
@ -141,7 +140,6 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_INFO(Packet &p)
* we (just) already preserved. * we (just) already preserved.
*/ */
*ici = *ci; *ici = *ci;
delete ci;
this->OnReceiveContentInfo(*ici); this->OnReceiveContentInfo(*ici);
return true; return true;
@ -150,20 +148,19 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_INFO(Packet &p)
/* Missing content info? Don't list it */ /* Missing content info? Don't list it */
if (ci->filesize == 0) { if (ci->filesize == 0) {
delete ci;
return true; return true;
} }
this->infos.push_back(ci); ContentInfo *info = this->infos.emplace_back(std::move(ci)).get();
/* Incoming data means that we might need to reconsider dependencies */ /* Incoming data means that we might need to reconsider dependencies */
ConstContentVector parents; ConstContentVector parents;
this->ReverseLookupTreeDependency(parents, ci); this->ReverseLookupTreeDependency(parents, info);
for (const ContentInfo *ici : parents) { for (const ContentInfo *ici : parents) {
this->CheckDependencyState(*ici); this->CheckDependencyState(*ici);
} }
this->OnReceiveContentInfo(*ci); this->OnReceiveContentInfo(*info);
return true; return true;
} }
@ -257,7 +254,7 @@ void ClientNetworkContentSocketHandler::RequestContentList(ContentVector *cv, bo
auto p = std::make_unique<Packet>(this, send_md5sum ? PACKET_CONTENT_CLIENT_INFO_EXTID_MD5 : PACKET_CONTENT_CLIENT_INFO_EXTID, TCP_MTU); auto p = std::make_unique<Packet>(this, send_md5sum ? PACKET_CONTENT_CLIENT_INFO_EXTID_MD5 : PACKET_CONTENT_CLIENT_INFO_EXTID, TCP_MTU);
p->Send_uint8((uint8_t)cv->size()); p->Send_uint8((uint8_t)cv->size());
for (const ContentInfo *ci : *cv) { for (const auto &ci : *cv) {
p->Send_uint8((uint8_t)ci->type); p->Send_uint8((uint8_t)ci->type);
p->Send_uint32(ci->unique_id); p->Send_uint32(ci->unique_id);
if (!send_md5sum) continue; if (!send_md5sum) continue;
@ -266,9 +263,9 @@ void ClientNetworkContentSocketHandler::RequestContentList(ContentVector *cv, bo
this->SendPacket(std::move(p)); this->SendPacket(std::move(p));
for (ContentInfo *ci : *cv) { for (auto &ci : *cv) {
bool found = false; bool found = false;
for (ContentInfo *ci2 : this->infos) { for (const auto &ci2 : this->infos) {
if (ci->type == ci2->type && ci->unique_id == ci2->unique_id && if (ci->type == ci2->type && ci->unique_id == ci2->unique_id &&
(!send_md5sum || ci->md5sum == ci2->md5sum)) { (!send_md5sum || ci->md5sum == ci2->md5sum)) {
found = true; found = true;
@ -276,9 +273,7 @@ void ClientNetworkContentSocketHandler::RequestContentList(ContentVector *cv, bo
} }
} }
if (!found) { if (!found) {
this->infos.push_back(ci); this->infos.push_back(std::move(ci));
} else {
delete ci;
} }
} }
} }
@ -294,7 +289,7 @@ void ClientNetworkContentSocketHandler::DownloadSelectedContent(uint &files, uin
bytes = 0; bytes = 0;
ContentIDList content; ContentIDList content;
for (const ContentInfo *ci : this->infos) { for (const auto &ci : this->infos) {
if (!ci->IsSelected() || ci->state == ContentInfo::ALREADY_HERE) continue; if (!ci->IsSelected() || ci->state == ContentInfo::ALREADY_HERE) continue;
content.push_back(ci->id); content.push_back(ci->id);
@ -368,13 +363,13 @@ void ClientNetworkContentSocketHandler::DownloadSelectedContentFallback(const Co
* @return a statically allocated buffer with the filename or * @return a statically allocated buffer with the filename or
* nullptr when no filename could be made. * nullptr when no filename could be made.
*/ */
static std::string GetFullFilename(const ContentInfo *ci, bool compressed) static std::string GetFullFilename(const ContentInfo &ci, bool compressed)
{ {
Subdirectory dir = GetContentInfoSubDir(ci->type); Subdirectory dir = GetContentInfoSubDir(ci.type);
if (dir == NO_DIRECTORY) return {}; if (dir == NO_DIRECTORY) return {};
std::string buf = FioGetDirectory(SP_AUTODOWNLOAD_DIR, dir); std::string buf = FioGetDirectory(SP_AUTODOWNLOAD_DIR, dir);
buf += ci->filename; buf += ci.filename;
buf += compressed ? ".tar.gz" : ".tar"; buf += compressed ? ".tar.gz" : ".tar";
return buf; return buf;
@ -385,7 +380,7 @@ static std::string GetFullFilename(const ContentInfo *ci, bool compressed)
* @param ci container with filename * @param ci container with filename
* @return true if the gunzip completed * @return true if the gunzip completed
*/ */
static bool GunzipFile(const ContentInfo *ci) static bool GunzipFile(const ContentInfo &ci)
{ {
#if defined(WITH_ZLIB) #if defined(WITH_ZLIB)
bool ret = true; bool ret = true;
@ -462,9 +457,8 @@ static inline ssize_t TransferOutFWrite(std::optional<FileHandle> &file, const c
bool ClientNetworkContentSocketHandler::Receive_SERVER_CONTENT(Packet &p) bool ClientNetworkContentSocketHandler::Receive_SERVER_CONTENT(Packet &p)
{ {
if (!this->cur_file.has_value()) { if (!this->cur_file.has_value()) {
delete this->cur_info;
/* When we haven't opened a file this must be our first packet with metadata. */ /* When we haven't opened a file this must be our first packet with metadata. */
this->cur_info = new ContentInfo; this->cur_info = std::make_unique<ContentInfo>();
this->cur_info->type = (ContentType)p.Recv_uint8(); this->cur_info->type = (ContentType)p.Recv_uint8();
this->cur_info->id = (ContentID)p.Recv_uint32(); this->cur_info->id = (ContentID)p.Recv_uint32();
this->cur_info->filesize = p.Recv_uint32(); this->cur_info->filesize = p.Recv_uint32();
@ -504,14 +498,13 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_CONTENT(Packet &p)
bool ClientNetworkContentSocketHandler::BeforeDownload() bool ClientNetworkContentSocketHandler::BeforeDownload()
{ {
if (!this->cur_info->IsValid()) { if (!this->cur_info->IsValid()) {
delete this->cur_info; this->cur_info.reset();
this->cur_info = nullptr;
return false; return false;
} }
if (this->cur_info->filesize != 0) { if (this->cur_info->filesize != 0) {
/* The filesize is > 0, so we are going to download it */ /* The filesize is > 0, so we are going to download it */
std::string filename = GetFullFilename(this->cur_info, true); std::string filename = GetFullFilename(*this->cur_info, true);
if (filename.empty() || !(this->cur_file = FileHandle::Open(filename, "wb")).has_value()) { if (filename.empty() || !(this->cur_file = FileHandle::Open(filename, "wb")).has_value()) {
/* Unless that fails of course... */ /* Unless that fails of course... */
CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD); CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD);
@ -535,14 +528,14 @@ void ClientNetworkContentSocketHandler::AfterDownload()
* Now gunzip the tar and make it known. */ * Now gunzip the tar and make it known. */
this->cur_file.reset(); this->cur_file.reset();
if (GunzipFile(this->cur_info)) { if (GunzipFile(*this->cur_info)) {
FioRemove(GetFullFilename(this->cur_info, true)); FioRemove(GetFullFilename(*this->cur_info, true));
Subdirectory sd = GetContentInfoSubDir(this->cur_info->type); Subdirectory sd = GetContentInfoSubDir(this->cur_info->type);
if (sd == NO_DIRECTORY) NOT_REACHED(); if (sd == NO_DIRECTORY) NOT_REACHED();
TarScanner ts; TarScanner ts;
std::string fname = GetFullFilename(this->cur_info, false); std::string fname = GetFullFilename(*this->cur_info, false);
ts.AddFile(sd, fname); ts.AddFile(sd, fname);
if (this->cur_info->type == CONTENT_TYPE_BASE_MUSIC) { if (this->cur_info->type == CONTENT_TYPE_BASE_MUSIC) {
@ -637,9 +630,8 @@ void ClientNetworkContentSocketHandler::OnReceiveData(std::unique_ptr<char[]> da
return; return;
} }
delete this->cur_info;
/* When we haven't opened a file this must be our first packet with metadata. */ /* When we haven't opened a file this must be our first packet with metadata. */
this->cur_info = new ContentInfo; this->cur_info = std::make_unique<ContentInfo>();
/** Check p for not being null and return calling OnFailure if that's not the case. */ /** Check p for not being null and return calling OnFailure if that's not the case. */
#define check_not_null(p) { if ((p) == nullptr) { this->OnFailure(); return; } } #define check_not_null(p) { if ((p) == nullptr) { this->OnFailure(); return; } }
@ -732,9 +724,6 @@ ClientNetworkContentSocketHandler::ClientNetworkContentSocketHandler() :
/** Clear up the mess ;) */ /** Clear up the mess ;) */
ClientNetworkContentSocketHandler::~ClientNetworkContentSocketHandler() ClientNetworkContentSocketHandler::~ClientNetworkContentSocketHandler()
{ {
delete this->cur_info;
for (ContentInfo *ci : this->infos) delete ci;
} }
/** Connect to the content server. */ /** Connect to the content server. */
@ -844,8 +833,8 @@ void ClientNetworkContentSocketHandler::DownloadContentInfo(ContentID cid)
*/ */
ContentInfo *ClientNetworkContentSocketHandler::GetContent(ContentID cid) const ContentInfo *ClientNetworkContentSocketHandler::GetContent(ContentID cid) const
{ {
for (ContentInfo *ci : this->infos) { for (const auto &ci : this->infos) {
if (ci->id == cid) return ci; if (ci->id == cid) return ci.get();
} }
return nullptr; return nullptr;
} }
@ -880,7 +869,7 @@ void ClientNetworkContentSocketHandler::Unselect(ContentID cid)
/** Select everything we can select */ /** Select everything we can select */
void ClientNetworkContentSocketHandler::SelectAll() void ClientNetworkContentSocketHandler::SelectAll()
{ {
for (ContentInfo *ci : this->infos) { for (const auto &ci : this->infos) {
if (ci->state == ContentInfo::UNSELECTED) { if (ci->state == ContentInfo::UNSELECTED) {
ci->state = ContentInfo::SELECTED; ci->state = ContentInfo::SELECTED;
this->CheckDependencyState(*ci); this->CheckDependencyState(*ci);
@ -891,7 +880,7 @@ void ClientNetworkContentSocketHandler::SelectAll()
/** Select everything that's an update for something we've got */ /** Select everything that's an update for something we've got */
void ClientNetworkContentSocketHandler::SelectUpgrade() void ClientNetworkContentSocketHandler::SelectUpgrade()
{ {
for (ContentInfo *ci : this->infos) { for (const auto &ci : this->infos) {
if (ci->state == ContentInfo::UNSELECTED && ci->upgrade) { if (ci->state == ContentInfo::UNSELECTED && ci->upgrade) {
ci->state = ContentInfo::SELECTED; ci->state = ContentInfo::SELECTED;
this->CheckDependencyState(*ci); this->CheckDependencyState(*ci);
@ -902,7 +891,7 @@ void ClientNetworkContentSocketHandler::SelectUpgrade()
/** Unselect everything that we've not downloaded so far. */ /** Unselect everything that we've not downloaded so far. */
void ClientNetworkContentSocketHandler::UnselectAll() void ClientNetworkContentSocketHandler::UnselectAll()
{ {
for (ContentInfo *ci : this->infos) { for (const auto &ci : this->infos) {
if (ci->IsSelected() && ci->state != ContentInfo::ALREADY_HERE) ci->state = ContentInfo::UNSELECTED; if (ci->IsSelected() && ci->state != ContentInfo::ALREADY_HERE) ci->state = ContentInfo::UNSELECTED;
} }
} }
@ -952,9 +941,9 @@ void ClientNetworkContentSocketHandler::ReverseLookupTreeDependency(ConstContent
* we are including stuff into the vector and as such the vector's data * we are including stuff into the vector and as such the vector's data
* store can be reallocated (and thus move), which means out iterating * store can be reallocated (and thus move), which means out iterating
* pointer gets invalid. So fall back to the indices. */ * pointer gets invalid. So fall back to the indices. */
for (uint i = 0; i < tree.size(); i++) { for (const ContentInfo *ci : tree) {
ConstContentVector parents; ConstContentVector parents;
this->ReverseLookupDependency(parents, *tree[i]); this->ReverseLookupDependency(parents, *ci);
for (const ContentInfo *ci : parents) { for (const ContentInfo *ci : parents) {
include(tree, ci); include(tree, ci);
@ -1056,8 +1045,6 @@ void ClientNetworkContentSocketHandler::CheckDependencyState(const ContentInfo &
/** Clear all downloaded content information. */ /** Clear all downloaded content information. */
void ClientNetworkContentSocketHandler::Clear() void ClientNetworkContentSocketHandler::Clear()
{ {
for (ContentInfo *c : this->infos) delete c;
this->infos.clear(); this->infos.clear();
this->requested.clear(); this->requested.clear();
this->reverse_dependency_map.clear(); this->reverse_dependency_map.clear();

View File

@ -10,20 +10,16 @@
#ifndef NETWORK_CONTENT_H #ifndef NETWORK_CONTENT_H
#define NETWORK_CONTENT_H #define NETWORK_CONTENT_H
#include <ranges>
#include "core/tcp_content.h" #include "core/tcp_content.h"
#include "core/http.h" #include "core/http.h"
#include <unordered_map> #include <unordered_map>
#include "../core/container_func.hpp" #include "../core/container_func.hpp"
/** Vector with content info */ /** Vector with content info */
typedef std::vector<ContentInfo *> ContentVector; using ContentVector = std::vector<std::unique_ptr<ContentInfo>>;
/** Vector with constant content info */ /** Vector with constant content info */
typedef std::vector<const ContentInfo *> ConstContentVector; using ConstContentVector = std::vector<const ContentInfo *>;
/** Iterator for the content vector */
typedef ContentInfo **ContentIterator;
/** Iterator for the constant content vector */
typedef const ContentInfo * const * ConstContentIterator;
/** Callbacks for notifying others about incoming data */ /** Callbacks for notifying others about incoming data */
struct ContentCallback { struct ContentCallback {
@ -66,7 +62,7 @@ struct ContentCallback {
*/ */
class ClientNetworkContentSocketHandler : public NetworkContentSocketHandler, ContentCallback, HTTPCallback { class ClientNetworkContentSocketHandler : public NetworkContentSocketHandler, ContentCallback, HTTPCallback {
protected: protected:
typedef std::vector<ContentID> ContentIDList; ///< List of content IDs to (possibly) select. using ContentIDList = std::vector<ContentID>; ///< List of content IDs to (possibly) select.
std::vector<ContentCallback *> callbacks; ///< Callbacks to notify "the world" std::vector<ContentCallback *> callbacks; ///< Callbacks to notify "the world"
ContentIDList requested; ///< ContentIDs we already requested (so we don't do it again) ContentIDList requested; ///< ContentIDs we already requested (so we don't do it again)
ContentVector infos; ///< All content info we received ContentVector infos; ///< All content info we received
@ -75,7 +71,7 @@ protected:
int http_response_index; ///< Where we are, in the response, with handling it int http_response_index; ///< Where we are, in the response, with handling it
std::optional<FileHandle> cur_file; ///< Currently downloaded file std::optional<FileHandle> cur_file; ///< Currently downloaded file
ContentInfo *cur_info; ///< Information about the currently downloaded file std::unique_ptr<ContentInfo> cur_info; ///< Information about the currently downloaded file
bool is_connecting; ///< Whether we're connecting bool is_connecting; ///< Whether we're connecting
bool is_cancelled; ///< Whether the download has been cancelled bool is_cancelled; ///< Whether the download has been cancelled
std::chrono::steady_clock::time_point last_activity; ///< The last time there was network activity std::chrono::steady_clock::time_point last_activity; ///< The last time there was network activity
@ -132,14 +128,11 @@ public:
void ReverseLookupTreeDependency(ConstContentVector &tree, const ContentInfo *child) const; void ReverseLookupTreeDependency(ConstContentVector &tree, const ContentInfo *child) const;
void CheckDependencyState(const ContentInfo &ci); void CheckDependencyState(const ContentInfo &ci);
/** Get the number of content items we know locally. */ /**
uint Length() const { return (uint)this->infos.size(); } * Get a read-only view of content info for iterating externally.
/** Get the begin of the content inf iterator. */ * @return Read-only view of content info.
ConstContentIterator Begin() const { return this->infos.data(); } */
/** Get the nth position of the content inf iterator. */ auto Info() const { return this->infos | std::views::transform([](const auto &ci) -> const ContentInfo & { return *ci; }); }
ConstContentIterator Get(uint32_t index) const { return this->infos.data() + index; }
/** Get the end of the content inf iterator. */
ConstContentIterator End() const { return this->Begin() + this->Length(); }
void Clear(); void Clear();

View File

@ -410,9 +410,9 @@ class NetworkContentListWindow : public Window, ContentCallback {
bool all_available = true; bool all_available = true;
for (ConstContentIterator iter = _network_content_client.Begin(); iter != _network_content_client.End(); iter++) { for (const ContentInfo &ci : _network_content_client.Info()) {
if ((*iter)->state == ContentInfo::DOES_NOT_EXIST) all_available = false; if (ci.state == ContentInfo::DOES_NOT_EXIST) all_available = false;
this->content.push_back(*iter); this->content.push_back(&ci);
} }
this->SetWidgetDisabledState(WID_NCL_SEARCH_EXTERNAL, this->auto_select && all_available); this->SetWidgetDisabledState(WID_NCL_SEARCH_EXTERNAL, this->auto_select && all_available);
@ -732,13 +732,11 @@ public:
std::string buf; std::string buf;
for (auto &cid : this->selected->dependencies) { for (auto &cid : this->selected->dependencies) {
/* Try to find the dependency */ /* Try to find the dependency */
ConstContentIterator iter = _network_content_client.Begin(); for (const ContentInfo &ci : _network_content_client.Info()) {
for (; iter != _network_content_client.End(); iter++) { if (ci.id != cid) continue;
const ContentInfo *ci = *iter;
if (ci->id != cid) continue;
if (!buf.empty()) buf += list_separator; if (!buf.empty()) buf += list_separator;
buf += (*iter)->name; buf += ci.name;
break; break;
} }
} }
@ -1138,9 +1136,5 @@ void ShowNetworkContentListWindow(ContentVector *cv, ContentType type1, ContentT
GetEncodedString(STR_CONTENT_NO_ZLIB), GetEncodedString(STR_CONTENT_NO_ZLIB),
GetEncodedString(STR_CONTENT_NO_ZLIB_SUB), GetEncodedString(STR_CONTENT_NO_ZLIB_SUB),
WL_ERROR); WL_ERROR);
/* Connection failed... clean up the mess */
if (cv != nullptr) {
for (ContentInfo *ci : *cv) delete ci;
}
#endif /* WITH_ZLIB */ #endif /* WITH_ZLIB */
} }

View File

@ -1517,13 +1517,13 @@ void ShowMissingContentWindow(const GRFConfigList &list)
for (const auto &c : list) { for (const auto &c : list) {
if (c->status != GCS_NOT_FOUND && !c->flags.Test(GRFConfigFlag::Compatible)) continue; if (c->status != GCS_NOT_FOUND && !c->flags.Test(GRFConfigFlag::Compatible)) continue;
ContentInfo *ci = new ContentInfo(); auto ci = std::make_unique<ContentInfo>();
ci->type = CONTENT_TYPE_NEWGRF; ci->type = CONTENT_TYPE_NEWGRF;
ci->state = ContentInfo::DOES_NOT_EXIST; ci->state = ContentInfo::DOES_NOT_EXIST;
ci->name = c->GetName(); ci->name = c->GetName();
ci->unique_id = std::byteswap(c->ident.grfid); ci->unique_id = std::byteswap(c->ident.grfid);
ci->md5sum = c->flags.Test(GRFConfigFlag::Compatible) ? c->original_md5sum : c->ident.md5sum; ci->md5sum = c->flags.Test(GRFConfigFlag::Compatible) ? c->original_md5sum : c->ident.md5sum;
cv.push_back(ci); cv.push_back(std::move(ci));
} }
ShowNetworkContentListWindow(cv.empty() ? nullptr : &cv, CONTENT_TYPE_NEWGRF); ShowNetworkContentListWindow(cv.empty() ? nullptr : &cv, CONTENT_TYPE_NEWGRF);
} }