1
0
Fork 0

Codechange: Use std::unique_ptrs for handling station cargo display. (#14009)

Replaces manual management of raw pointers.
pull/14013/head
Peter Nelson 2025-04-16 19:43:45 +01:00 committed by GitHub
parent a281ac4674
commit 6ea10edef8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 84 additions and 91 deletions

View File

@ -889,9 +889,13 @@ enum class CargoSortType : uint8_t {
class CargoSorter {
public:
using is_transparent = void;
CargoSorter(CargoSortType t = CargoSortType::StationID, SortOrder o = SO_ASCENDING) : type(t), order(o) {}
CargoSortType GetSortType() {return this->type;}
bool operator()(const CargoDataEntry *cd1, const CargoDataEntry *cd2) const;
bool operator()(const CargoDataEntry &cd1, const CargoDataEntry &cd2) const;
bool operator()(const CargoDataEntry &cd1, const std::unique_ptr<CargoDataEntry> &cd2) const { return this->operator()(cd1, *cd2); }
bool operator()(const std::unique_ptr<CargoDataEntry> &cd1, const CargoDataEntry &cd2) const { return this->operator()(*cd1, cd2); }
bool operator()(const std::unique_ptr<CargoDataEntry> &cd1, const std::unique_ptr<CargoDataEntry> &cd2) const { return this->operator()(*cd1, *cd2); }
private:
CargoSortType type;
@ -899,11 +903,11 @@ private:
template <class Tid>
bool SortId(Tid st1, Tid st2) const;
bool SortCount(const CargoDataEntry *cd1, const CargoDataEntry *cd2) const;
bool SortStation (StationID st1, StationID st2) const;
bool SortCount(const CargoDataEntry &cd1, const CargoDataEntry &cd2) const;
bool SortStation(StationID st1, StationID st2) const;
};
typedef std::set<CargoDataEntry *, CargoSorter> CargoDataSet;
typedef std::set<std::unique_ptr<CargoDataEntry>, CargoSorter> CargoDataSet;
/**
* A cargo data entry representing one possible row in the station view window's
@ -920,7 +924,7 @@ public:
* @param station ID of the station for which an entry shall be created or retrieved
* @return a child entry associated with the given station.
*/
CargoDataEntry *InsertOrRetrieve(StationID station)
CargoDataEntry &InsertOrRetrieve(StationID station)
{
return this->InsertOrRetrieve<StationID>(station);
}
@ -930,7 +934,7 @@ public:
* @param cargo type of the cargo for which an entry shall be created or retrieved
* @return a child entry associated with the given cargo.
*/
CargoDataEntry *InsertOrRetrieve(CargoType cargo)
CargoDataEntry &InsertOrRetrieve(CargoType cargo)
{
return this->InsertOrRetrieve<CargoType>(cargo);
}
@ -944,7 +948,7 @@ public:
void Remove(StationID station)
{
CargoDataEntry t(station);
this->Remove(&t);
this->Remove(t);
}
/**
@ -954,7 +958,7 @@ public:
void Remove(CargoType cargo)
{
CargoDataEntry t(cargo);
this->Remove(&t);
this->Remove(t);
}
/**
@ -965,7 +969,7 @@ public:
CargoDataEntry *Retrieve(StationID station) const
{
CargoDataEntry t(station);
return this->Retrieve(this->children->find(&t));
return this->Retrieve(this->children->find(t));
}
/**
@ -976,7 +980,7 @@ public:
CargoDataEntry *Retrieve(CargoType cargo) const
{
CargoDataEntry t(cargo);
return this->Retrieve(this->children->find(&t));
return this->Retrieve(this->children->find(t));
}
void Resort(CargoSortType type, SortOrder order);
@ -1027,19 +1031,19 @@ public:
void SetTransfers(bool value) { this->transfers = value; }
void Clear();
private:
CargoDataEntry(StationID station, uint count, CargoDataEntry *parent);
CargoDataEntry(CargoType cargo, uint count, CargoDataEntry *parent);
CargoDataEntry(StationID station);
CargoDataEntry(CargoType cargo);
private:
CargoDataEntry *Retrieve(CargoDataSet::iterator i) const;
template <class Tid>
CargoDataEntry *InsertOrRetrieve(Tid s);
CargoDataEntry &InsertOrRetrieve(Tid s);
void Remove(CargoDataEntry *entry);
void Remove(CargoDataEntry &entry);
void IncrementSize();
CargoDataEntry *parent; ///< the parent of this entry.
@ -1052,7 +1056,7 @@ private:
};
uint num_children; ///< the number of subentries belonging to this entry.
uint count; ///< sum of counts of all children or amount of cargo for this entry.
CargoDataSet *children; ///< the children of this entry.
std::unique_ptr<CargoDataSet> children; ///< the children of this entry.
};
CargoDataEntry::CargoDataEntry() :
@ -1060,7 +1064,7 @@ CargoDataEntry::CargoDataEntry() :
station(StationID::Invalid()),
num_children(0),
count(0),
children(new CargoDataSet(CargoSorter(CargoSortType::CargoType)))
children(std::make_unique<CargoDataSet>(CargoSorter(CargoSortType::CargoType)))
{}
CargoDataEntry::CargoDataEntry(CargoType cargo, uint count, CargoDataEntry *parent) :
@ -1068,7 +1072,7 @@ CargoDataEntry::CargoDataEntry(CargoType cargo, uint count, CargoDataEntry *pare
cargo(cargo),
num_children(0),
count(count),
children(new CargoDataSet)
children(std::make_unique<CargoDataSet>())
{}
CargoDataEntry::CargoDataEntry(StationID station, uint count, CargoDataEntry *parent) :
@ -1076,7 +1080,7 @@ CargoDataEntry::CargoDataEntry(StationID station, uint count, CargoDataEntry *pa
station(station),
num_children(0),
count(count),
children(new CargoDataSet)
children(std::make_unique<CargoDataSet>())
{}
CargoDataEntry::CargoDataEntry(StationID station) :
@ -1098,7 +1102,6 @@ CargoDataEntry::CargoDataEntry(CargoType cargo) :
CargoDataEntry::~CargoDataEntry()
{
this->Clear();
delete this->children;
}
/**
@ -1106,13 +1109,7 @@ CargoDataEntry::~CargoDataEntry()
*/
void CargoDataEntry::Clear()
{
if (this->children != nullptr) {
for (auto &it : *this->children) {
assert(it != this);
delete it;
}
this->children->clear();
}
if (this->children != nullptr) this->children->clear();
if (this->parent != nullptr) this->parent->count -= this->count;
this->count = 0;
this->num_children = 0;
@ -1124,13 +1121,10 @@ void CargoDataEntry::Clear()
* which only contains the ID of the entry to be removed. In this case child is
* not deleted.
*/
void CargoDataEntry::Remove(CargoDataEntry *entry)
void CargoDataEntry::Remove(CargoDataEntry &entry)
{
CargoDataSet::iterator i = this->children->find(entry);
if (i != this->children->end()) {
delete *i;
this->children->erase(i);
}
if (i != this->children->end()) this->children->erase(i);
}
/**
@ -1140,17 +1134,16 @@ void CargoDataEntry::Remove(CargoDataEntry *entry)
* @return the new or retrieved subentry
*/
template <class Tid>
CargoDataEntry *CargoDataEntry::InsertOrRetrieve(Tid child_id)
CargoDataEntry &CargoDataEntry::InsertOrRetrieve(Tid child_id)
{
CargoDataEntry tmp(child_id);
CargoDataSet::iterator i = this->children->find(&tmp);
CargoDataSet::iterator i = this->children->find(tmp);
if (i == this->children->end()) {
IncrementSize();
return *(this->children->insert(new CargoDataEntry(child_id, 0, this)).first);
return **(this->children->insert(std::make_unique<CargoDataEntry>(child_id, 0, this)).first);
} else {
CargoDataEntry *ret = *i;
assert(this->children->value_comp().GetSortType() != CargoSortType::Count);
return ret;
return **i;
}
}
@ -1176,9 +1169,9 @@ void CargoDataEntry::IncrementSize()
void CargoDataEntry::Resort(CargoSortType type, SortOrder order)
{
CargoDataSet *new_subs = new CargoDataSet(this->children->begin(), this->children->end(), CargoSorter(type, order));
delete this->children;
this->children = new_subs;
auto new_children = std::make_unique<CargoDataSet>(CargoSorter(type, order));
new_children->merge(*this->children);
this->children = std::move(new_children);
}
CargoDataEntry *CargoDataEntry::Retrieve(CargoDataSet::iterator i) const
@ -1187,21 +1180,21 @@ CargoDataEntry *CargoDataEntry::Retrieve(CargoDataSet::iterator i) const
return nullptr;
} else {
assert(this->children->value_comp().GetSortType() != CargoSortType::Count);
return *i;
return i->get();
}
}
bool CargoSorter::operator()(const CargoDataEntry *cd1, const CargoDataEntry *cd2) const
bool CargoSorter::operator()(const CargoDataEntry &cd1, const CargoDataEntry &cd2) const
{
switch (this->type) {
case CargoSortType::StationID:
return this->SortId<StationID>(cd1->GetStation(), cd2->GetStation());
return this->SortId<StationID>(cd1.GetStation(), cd2.GetStation());
case CargoSortType::CargoType:
return this->SortId<CargoType>(cd1->GetCargo(), cd2->GetCargo());
return this->SortId<CargoType>(cd1.GetCargo(), cd2.GetCargo());
case CargoSortType::Count:
return this->SortCount(cd1, cd2);
case CargoSortType::StationString:
return this->SortStation(cd1->GetStation(), cd2->GetStation());
return this->SortStation(cd1.GetStation(), cd2.GetStation());
default:
NOT_REACHED();
}
@ -1213,12 +1206,12 @@ bool CargoSorter::SortId(Tid st1, Tid st2) const
return (this->order == SO_ASCENDING) ? st1 < st2 : st2 < st1;
}
bool CargoSorter::SortCount(const CargoDataEntry *cd1, const CargoDataEntry *cd2) const
bool CargoSorter::SortCount(const CargoDataEntry &cd1, const CargoDataEntry &cd2) const
{
uint c1 = cd1->GetCount();
uint c2 = cd2->GetCount();
uint c1 = cd1.GetCount();
uint c2 = cd2.GetCount();
if (c1 == c2) {
return this->SortStation(cd1->GetStation(), cd2->GetStation());
return this->SortStation(cd1.GetStation(), cd2.GetStation());
} else if (this->order == SO_ASCENDING) {
return c1 < c2;
} else {
@ -1392,25 +1385,25 @@ struct StationViewWindow : public Window {
switch (groupings[i]) {
case GR_CARGO:
assert(i == 0);
data = data->InsertOrRetrieve(cargo);
data = &data->InsertOrRetrieve(cargo);
data->SetTransfers(source != this->window_number);
expand = expand->Retrieve(cargo);
break;
case GR_SOURCE:
if (auto_distributed || source != this->window_number) {
data = data->InsertOrRetrieve(source);
data = &data->InsertOrRetrieve(source);
expand = expand->Retrieve(source);
}
break;
case GR_NEXT:
if (auto_distributed) {
data = data->InsertOrRetrieve(next);
data = &data->InsertOrRetrieve(next);
expand = expand->Retrieve(next);
}
break;
case GR_DESTINATION:
if (auto_distributed) {
data = data->InsertOrRetrieve(dest);
data = &data->InsertOrRetrieve(dest);
expand = expand->Retrieve(dest);
}
break;
@ -1498,7 +1491,7 @@ struct StationViewWindow : public Window {
/* Draw waiting cargo. */
NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_SV_WAITING);
Rect waiting_rect = nwi->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
this->DrawEntries(&cargo, waiting_rect, pos, maxrows, 0);
this->DrawEntries(cargo, waiting_rect, pos, maxrows, 0);
scroll_to_row = INT_MAX;
}
}
@ -1521,20 +1514,20 @@ struct StationViewWindow : public Window {
void RecalcDestinations(CargoType cargo)
{
const Station *st = Station::Get(this->window_number);
CargoDataEntry *entry = cached_destinations.InsertOrRetrieve(cargo);
entry->Clear();
CargoDataEntry &entry = cached_destinations.InsertOrRetrieve(cargo);
entry.Clear();
if (!st->goods[cargo].HasData()) return;
for (const auto &it : st->goods[cargo].GetData().flows) {
StationID from = it.first;
CargoDataEntry *source_entry = entry->InsertOrRetrieve(from);
CargoDataEntry &source_entry = entry.InsertOrRetrieve(from);
uint32_t prev_count = 0;
for (const auto &flow_it : *it.second.GetShares()) {
StationID via = flow_it.second;
CargoDataEntry *via_entry = source_entry->InsertOrRetrieve(via);
CargoDataEntry &via_entry = source_entry.InsertOrRetrieve(via);
if (via == this->window_number) {
via_entry->InsertOrRetrieve(via)->Update(flow_it.first - prev_count);
via_entry.InsertOrRetrieve(via).Update(flow_it.first - prev_count);
} else {
EstimateDestinations(cargo, from, via, flow_it.first - prev_count, via_entry);
}
@ -1552,7 +1545,7 @@ struct StationViewWindow : public Window {
* @param count Size of the batch of cargo.
* @param dest CargoDataEntry to save the results in.
*/
void EstimateDestinations(CargoType cargo, StationID source, StationID next, uint count, CargoDataEntry *dest)
void EstimateDestinations(CargoType cargo, StationID source, StationID next, uint count, CargoDataEntry &dest)
{
if (Station::IsValidID(next) && Station::IsValidID(source)) {
GoodsEntry &ge = Station::Get(next)->goods[cargo];
@ -1565,19 +1558,19 @@ struct StationViewWindow : public Window {
const FlowStat::SharesMap *shares = map_it->second.GetShares();
uint32_t prev_count = 0;
for (FlowStat::SharesMap::const_iterator i = shares->begin(); i != shares->end(); ++i) {
tmp.InsertOrRetrieve(i->second)->Update(i->first - prev_count);
tmp.InsertOrRetrieve(i->second).Update(i->first - prev_count);
prev_count = i->first;
}
}
if (tmp.GetCount() == 0) {
dest->InsertOrRetrieve(StationID::Invalid())->Update(count);
dest.InsertOrRetrieve(StationID::Invalid()).Update(count);
} else {
uint sum_estimated = 0;
while (sum_estimated < count) {
for (CargoDataSet::iterator i = tmp.Begin(); i != tmp.End() && sum_estimated < count; ++i) {
CargoDataEntry *child = *i;
uint estimate = DivideApprox(child->GetCount() * count, tmp.GetCount());
CargoDataEntry &child = **i;
uint estimate = DivideApprox(child.GetCount() * count, tmp.GetCount());
if (estimate == 0) estimate = 1;
sum_estimated += estimate;
@ -1587,10 +1580,10 @@ struct StationViewWindow : public Window {
}
if (estimate > 0) {
if (child->GetStation() == next) {
dest->InsertOrRetrieve(next)->Update(estimate);
if (child.GetStation() == next) {
dest.InsertOrRetrieve(next).Update(estimate);
} else {
EstimateDestinations(cargo, source, child->GetStation(), estimate, dest);
EstimateDestinations(cargo, source, child.GetStation(), estimate, dest);
}
}
}
@ -1598,7 +1591,7 @@ struct StationViewWindow : public Window {
}
}
} else {
dest->InsertOrRetrieve(StationID::Invalid())->Update(count);
dest.InsertOrRetrieve(StationID::Invalid()).Update(count);
}
}
@ -1618,8 +1611,8 @@ struct StationViewWindow : public Window {
for (FlowStat::SharesMap::const_iterator flow_it = shares->begin(); flow_it != shares->end(); ++flow_it) {
const CargoDataEntry *via_entry = source_entry->Retrieve(flow_it->second);
for (CargoDataSet::iterator dest_it = via_entry->Begin(); dest_it != via_entry->End(); ++dest_it) {
CargoDataEntry *dest_entry = *dest_it;
ShowCargo(entry, cargo, from, flow_it->second, dest_entry->GetStation(), dest_entry->GetCount());
CargoDataEntry &dest_entry = **dest_it;
ShowCargo(entry, cargo, from, flow_it->second, dest_entry.GetStation(), dest_entry.GetCount());
}
}
}
@ -1652,7 +1645,7 @@ struct StationViewWindow : public Window {
uint remaining = cp->Count();
for (CargoDataSet::iterator dest_it = via_entry->Begin(); dest_it != via_entry->End();) {
CargoDataEntry *dest_entry = *dest_it;
CargoDataEntry &dest_entry = **dest_it;
/* Advance iterator here instead of in the for statement to test whether this is the last entry */
++dest_it;
@ -1664,10 +1657,10 @@ struct StationViewWindow : public Window {
* not matching GoodsEntry::TotalCount() */
val = remaining;
} else {
val = std::min<uint>(remaining, DivideApprox(cp->Count() * dest_entry->GetCount(), via_entry->GetCount()));
val = std::min<uint>(remaining, DivideApprox(cp->Count() * dest_entry.GetCount(), via_entry->GetCount()));
remaining -= val;
}
this->ShowCargo(entry, cargo, cp->GetFirstStation(), next, dest_entry->GetStation(), val);
this->ShowCargo(entry, cargo, cp->GetFirstStation(), next, dest_entry.GetStation(), val);
}
}
this->ShowCargo(entry, cargo, NEW_STATION, NEW_STATION, NEW_STATION, packets.ReservedCount());
@ -1701,16 +1694,16 @@ struct StationViewWindow : public Window {
* Mark a specific row, characterized by its CargoDataEntry, as expanded.
* @param entry The row to be marked as expanded.
*/
void SetDisplayedRow(const CargoDataEntry *entry)
void SetDisplayedRow(const CargoDataEntry &entry)
{
std::list<StationID> stations;
const CargoDataEntry *parent = entry->GetParent();
const CargoDataEntry *parent = entry.GetParent();
if (parent->GetParent() == nullptr) {
this->displayed_rows.push_back(RowDisplay(&this->expanded_rows, entry->GetCargo()));
this->displayed_rows.push_back(RowDisplay(&this->expanded_rows, entry.GetCargo()));
return;
}
StationID next = entry->GetStation();
StationID next = entry.GetStation();
while (parent->GetParent()->GetParent() != nullptr) {
stations.push_back(parent->GetStation());
parent = parent->GetParent();
@ -1764,9 +1757,9 @@ struct StationViewWindow : public Window {
* @param column The "column" the entry will be shown in.
* @return either STR_STATION_VIEW_VIA or STR_STATION_VIEW_NONSTOP.
*/
StringID SearchNonStop(CargoDataEntry *cd, StationID station, int column)
StringID SearchNonStop(CargoDataEntry &cd, StationID station, int column)
{
CargoDataEntry *parent = cd->GetParent();
CargoDataEntry *parent = cd.GetParent();
for (int i = column - 1; i > 0; --i) {
if (this->groupings[i] == GR_DESTINATION) {
if (parent->GetStation() == station) {
@ -1779,9 +1772,9 @@ struct StationViewWindow : public Window {
}
if (this->groupings[column + 1] == GR_DESTINATION) {
CargoDataSet::iterator begin = cd->Begin();
CargoDataSet::iterator end = cd->End();
if (begin != end && ++(cd->Begin()) == end && (*(begin))->GetStation() == station) {
CargoDataSet::iterator begin = cd.Begin();
CargoDataSet::iterator end = cd.End();
if (begin != end && ++(cd.Begin()) == end && (*(begin))->GetStation() == station) {
return STR_STATION_VIEW_NONSTOP;
} else {
return STR_STATION_VIEW_VIA;
@ -1801,20 +1794,20 @@ struct StationViewWindow : public Window {
* @param cargo Current cargo being drawn (if cargo column has been passed).
* @return row (in "pos" counting) after the one we have last drawn to.
*/
int DrawEntries(CargoDataEntry *entry, const Rect &r, int pos, int maxrows, int column, CargoType cargo = INVALID_CARGO)
int DrawEntries(CargoDataEntry &entry, const Rect &r, int pos, int maxrows, int column, CargoType cargo = INVALID_CARGO)
{
if (this->sortings[column] == CargoSortType::AsGrouping) {
if (this->groupings[column] != GR_CARGO) {
entry->Resort(CargoSortType::StationString, this->sort_orders[column]);
entry.Resort(CargoSortType::StationString, this->sort_orders[column]);
}
} else {
entry->Resort(CargoSortType::Count, this->sort_orders[column]);
entry.Resort(CargoSortType::Count, this->sort_orders[column]);
}
for (CargoDataSet::iterator i = entry->Begin(); i != entry->End(); ++i) {
CargoDataEntry *cd = *i;
for (CargoDataSet::iterator i = entry.Begin(); i != entry.End(); ++i) {
CargoDataEntry &cd = **i;
Grouping grouping = this->groupings[column];
if (grouping == GR_CARGO) cargo = cd->GetCargo();
if (grouping == GR_CARGO) cargo = cd.GetCargo();
bool auto_distributed = _settings_game.linkgraph.GetDistributionType(cargo) != DT_MANUAL;
if (pos > -maxrows && pos <= 0) {
@ -1823,10 +1816,10 @@ struct StationViewWindow : public Window {
int y = r.top - pos * GetCharacterHeight(FS_NORMAL);
if (this->groupings[column] == GR_CARGO) {
str = STR_STATION_VIEW_WAITING_CARGO;
DrawCargoIcons(cd->GetCargo(), cd->GetCount(), r.left + this->expand_shrink_width, r.right - this->expand_shrink_width, y);
DrawCargoIcons(cd.GetCargo(), cd.GetCount(), r.left + this->expand_shrink_width, r.right - this->expand_shrink_width, y);
} else {
if (!auto_distributed) grouping = GR_SOURCE;
station = cd->GetStation();
station = cd.GetStation();
str = this->GetGroupingString(grouping, station);
if (grouping == GR_NEXT && str == STR_STATION_VIEW_VIA) str = this->SearchNonStop(cd, station, column);
@ -1839,11 +1832,11 @@ struct StationViewWindow : public Window {
Rect text = r.Indent(column * WidgetDimensions::scaled.hsep_indent, rtl).Indent(this->expand_shrink_width, !rtl);
Rect shrink = r.WithWidth(this->expand_shrink_width, !rtl);
DrawString(text.left, text.right, y, GetString(str, cargo, cd->GetCount(), station));
DrawString(text.left, text.right, y, GetString(str, cargo, cd.GetCount(), station));
if (column < NUM_COLUMNS - 1) {
const char *sym = nullptr;
if (cd->GetNumChildren() > 0) {
if (cd.GetNumChildren() > 0) {
sym = "-";
} else if (auto_distributed && str != STR_STATION_VIEW_RESERVED) {
sym = "+";
@ -1852,7 +1845,7 @@ struct StationViewWindow : public Window {
const GoodsEntry &ge = Station::Get(this->window_number)->goods[cargo];
if (ge.HasData()) {
const StationCargoList &cargo_list = ge.GetData().cargo;
if (grouping == GR_CARGO && (cargo_list.ReservedCount() > 0 || cd->HasTransfers())) {
if (grouping == GR_CARGO && (cargo_list.ReservedCount() > 0 || cd.HasTransfers())) {
sym = "+";
}
}