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:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user