diff --git a/src/station_gui.cpp b/src/station_gui.cpp index 160f1d1eb1..fa35efccb5 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -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 &cd2) const { return this->operator()(cd1, *cd2); } + bool operator()(const std::unique_ptr &cd1, const CargoDataEntry &cd2) const { return this->operator()(*cd1, cd2); } + bool operator()(const std::unique_ptr &cd1, const std::unique_ptr &cd2) const { return this->operator()(*cd1, *cd2); } private: CargoSortType type; @@ -899,11 +903,11 @@ private: template 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 CargoDataSet; +typedef std::set, 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(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(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 - 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 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(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()) {} 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()) {} 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 -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(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(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(cd1->GetStation(), cd2->GetStation()); + return this->SortId(cd1.GetStation(), cd2.GetStation()); case CargoSortType::CargoType: - return this->SortId(cd1->GetCargo(), cd2->GetCargo()); + return this->SortId(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(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(remaining, DivideApprox(cp->Count() * dest_entry->GetCount(), via_entry->GetCount())); + val = std::min(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 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 = "+"; } }