Codechange: Use std::vector for GRFConfig lists. (#10835)

This replaces the C-style custom managed linked-list and allows use of iterators etc.
This commit is contained in:
Peter Nelson
2025-01-31 17:09:09 +00:00
committed by GitHub
parent 40aeedeade
commit 5664b1e2f6
23 changed files with 248 additions and 384 deletions

View File

@@ -218,9 +218,9 @@ void GRFParameterInfo::Finalize()
*/
void UpdateNewGRFConfigPalette(int32_t)
{
for (GRFConfig *c = _grfconfig_newgame; c != nullptr; c = c->next) c->SetSuitablePalette();
for (GRFConfig *c = _grfconfig_static; c != nullptr; c = c->next) c->SetSuitablePalette();
for (GRFConfig *c = _all_grfs; c != nullptr; c = c->next) c->SetSuitablePalette();
for (const auto &c : _grfconfig_newgame) c->SetSuitablePalette();
for (const auto &c : _grfconfig_static ) c->SetSuitablePalette();
for (const auto &c : _all_grfs ) c->SetSuitablePalette();
}
/**
@@ -327,12 +327,7 @@ bool FillGRFDetails(GRFConfig &config, bool is_static, Subdirectory subdir)
*/
void ClearGRFConfigList(GRFConfigList &config)
{
GRFConfig *c, *next;
for (c = config; c != nullptr; c = next) {
next = c->next;
delete c;
}
config = nullptr;
config.clear();
}
/**
@@ -343,16 +338,9 @@ void ClearGRFConfigList(GRFConfigList &config)
*/
static void AppendGRFConfigList(GRFConfigList &dst, const GRFConfigList &src, bool init_only)
{
GRFConfig **tail = &dst;
while (*tail != nullptr) tail = &(*tail)->next;
for (GRFConfig *s = src; s != nullptr; s = s->next) {
GRFConfig *c = new GRFConfig(*s);
for (const auto &s : src) {
auto &c = dst.emplace_back(std::make_unique<GRFConfig>(*s));
AssignBit(c->flags, GCF_INIT_ONLY, init_only);
*tail = c;
tail = &c->next;
}
}
@@ -384,20 +372,13 @@ void CopyGRFConfigList(GRFConfigList &dst, const GRFConfigList &src, bool init_o
*/
static void RemoveDuplicatesFromGRFConfigList(GRFConfigList &list)
{
GRFConfig *prev;
GRFConfig *cur;
if (list.empty()) return;
if (list == nullptr) return;
for (prev = list, cur = list->next; cur != nullptr; prev = cur, cur = cur->next) {
if (cur->ident.grfid != list->ident.grfid) continue;
prev->next = cur->next;
delete cur;
cur = prev; // Just go back one so it continues as normal later on
auto last = std::end(list);
for (auto it = std::begin(list); it != last; ++it) {
auto remove = std::remove_if(std::next(it), last, [&grfid = (*it)->ident.grfid](const auto &c) { return grfid == c->ident.grfid; });
last = list.erase(remove, last);
}
RemoveDuplicatesFromGRFConfigList(list->next);
}
/**
@@ -415,12 +396,9 @@ void AppendStaticGRFConfigs(GRFConfigList &dst)
* @param dst the head of the list to add to
* @param el the new tail to be
*/
void AppendToGRFConfigList(GRFConfigList &dst, GRFConfig *el)
void AppendToGRFConfigList(GRFConfigList &dst, std::unique_ptr<GRFConfig> &&el)
{
GRFConfig **tail = &dst;
while (*tail != nullptr) tail = &(*tail)->next;
*tail = el;
dst.push_back(std::move(el));
RemoveDuplicatesFromGRFConfigList(dst);
}
@@ -448,7 +426,7 @@ GRFListCompatibility IsGoodGRFConfigList(GRFConfigList &grfconfig)
{
GRFListCompatibility res = GLC_ALL_GOOD;
for (GRFConfig *c = grfconfig; c != nullptr; c = c->next) {
for (auto &c : grfconfig) {
const GRFConfig *f = FindGRFConfig(c->ident.grfid, FGCM_EXACT, &c->ident.md5sum);
if (f == nullptr || HasBit(f->flags, GCF_INVALID)) {
/* If we have not found the exactly matching GRF try to find one with the
@@ -537,51 +515,24 @@ bool GRFFileScanner::AddFile(const std::string &filename, size_t basepath_length
/* Abort if the user stopped the game during a scan. */
if (_exit_game) return false;
GRFConfig *c = new GRFConfig(filename.c_str() + basepath_length);
bool added = true;
bool added = false;
auto c = std::make_unique<GRFConfig>(filename.substr(basepath_length));
GRFConfig *grfconfig = c.get();
if (FillGRFDetails(*c, false)) {
if (_all_grfs == nullptr) {
_all_grfs = c;
} else {
/* Insert file into list at a position determined by its
* name, so the list is sorted as we go along */
GRFConfig **pd, *d;
bool stop = false;
for (pd = &_all_grfs; (d = *pd) != nullptr; pd = &d->next) {
if (c->ident.grfid == d->ident.grfid && c->ident.md5sum == d->ident.md5sum) added = false;
/* Because there can be multiple grfs with the same name, make sure we checked all grfs with the same name,
* before inserting the entry. So insert a new grf at the end of all grfs with the same name, instead of
* just after the first with the same name. Avoids doubles in the list. */
if (StrCompareIgnoreCase(c->GetName(), d->GetName()) <= 0) {
stop = true;
} else if (stop) {
break;
}
}
if (added) {
c->next = d;
*pd = c;
}
if (std::ranges::none_of(_all_grfs, [&c](const auto &gc) { return c->ident.grfid == gc->ident.grfid && c->ident.md5sum == gc->ident.md5sum; })) {
_all_grfs.push_back(std::move(c));
added = true;
}
} else {
added = false;
}
this->num_scanned++;
const char *name = nullptr;
if (c->name != nullptr) name = GetGRFStringFromGRFText(c->name);
if (name == nullptr) name = c->filename.c_str();
if (grfconfig->name != nullptr) name = GetGRFStringFromGRFText(grfconfig->name);
if (name == nullptr) name = grfconfig->filename.c_str();
UpdateNewGRFScanStatus(this->num_scanned, name);
VideoDriver::GetInstance()->GameLoopPause();
if (!added) {
/* File couldn't be opened, or is either not a NewGRF or is a
* 'system' NewGRF or it's already known, so forget about it. */
delete c;
}
return added;
}
@@ -591,7 +542,7 @@ bool GRFFileScanner::AddFile(const std::string &filename, size_t basepath_length
* @param c2 the second GRFConfig *
* @return true if the name of first NewGRF is before the name of the second.
*/
static bool GRFSorter(GRFConfig * const &c1, GRFConfig * const &c2)
static bool GRFSorter(std::unique_ptr<GRFConfig> const &c1, std::unique_ptr<GRFConfig> const &c2)
{
return StrNaturalCompare(c1->GetName(), c2->GetName()) < 0;
}
@@ -609,29 +560,8 @@ void DoScanNewGRFFiles(NewGRFScanCallback *callback)
uint num = GRFFileScanner::DoScan();
Debug(grf, 1, "Scan complete, found {} files", num);
if (num != 0 && _all_grfs != nullptr) {
/* Sort the linked list using quicksort.
* For that we first have to make an array, then sort and
* then remake the linked list. */
std::vector<GRFConfig *> to_sort;
uint i = 0;
for (GRFConfig *p = _all_grfs; p != nullptr; p = p->next, i++) {
to_sort.push_back(p);
}
/* Number of files is not necessarily right */
num = i;
std::sort(to_sort.begin(), to_sort.end(), GRFSorter);
for (i = 1; i < num; i++) {
to_sort[i - 1]->next = to_sort[i];
}
to_sort[num - 1]->next = nullptr;
_all_grfs = to_sort[0];
NetworkAfterNewGRFScan();
}
std::ranges::sort(_all_grfs, GRFSorter);
NetworkAfterNewGRFScan();
/* Yes... these are the NewGRF windows */
InvalidateWindowClassesData(WC_SAVELOAD, 0, true);
@@ -669,17 +599,17 @@ const GRFConfig *FindGRFConfig(uint32_t grfid, FindGRFConfigMode mode, const MD5
{
assert((mode == FGCM_EXACT) != (md5sum == nullptr));
const GRFConfig *best = nullptr;
for (const GRFConfig *c = _all_grfs; c != nullptr; c = c->next) {
for (const auto &c : _all_grfs) {
/* if md5sum is set, we look for an exact match and continue if not found */
if (!c->ident.HasGrfIdentifier(grfid, md5sum)) continue;
/* return it, if the exact same newgrf is found, or if we do not care about finding "the best" */
if (md5sum != nullptr || mode == FGCM_ANY) return c;
if (md5sum != nullptr || mode == FGCM_ANY) return c.get();
/* Skip incompatible stuff, unless explicitly allowed */
if (mode != FGCM_NEWEST && HasBit(c->flags, GCF_INVALID)) continue;
/* check version compatibility */
if (mode == FGCM_COMPATIBLE && !c->IsCompatible(desired_version)) continue;
/* remember the newest one as "the best" */
if (best == nullptr || c->version > best->version) best = c;
if (best == nullptr || c->version > best->version) best = c.get();
}
return best;
@@ -693,11 +623,8 @@ const GRFConfig *FindGRFConfig(uint32_t grfid, FindGRFConfigMode mode, const MD5
*/
GRFConfig *GetGRFConfig(uint32_t grfid, uint32_t mask)
{
GRFConfig *c;
for (c = _grfconfig; c != nullptr; c = c->next) {
if ((c->ident.grfid & mask) == (grfid & mask)) return c;
}
auto it = std::ranges::find_if(_grfconfig, [grfid, mask](const auto &c) { return (c->ident.grfid & mask) == (grfid & mask); });
if (it != std::end(_grfconfig)) return it->get();
return nullptr;
}