diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index f3cd7f09b7..dce6e04f57 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -135,7 +135,8 @@ static StationID FindNearestHangar(const Aircraft *v) next_dest = Station::GetIfValid(v->current_order.GetDestination().ToStationID()); } else { last_dest = GetTargetAirportIfValid(v); - next_dest = Station::GetIfValid(v->GetNextStoppingStation().value); + std::vector next_station = v->GetNextStoppingStation(); + if (!next_station.empty()) next_dest = Station::GetIfValid(next_station.back()); } } diff --git a/src/cargopacket.cpp b/src/cargopacket.cpp index 38d9489490..f8c736c3a8 100644 --- a/src/cargopacket.cpp +++ b/src/cargopacket.cpp @@ -404,13 +404,13 @@ void VehicleCargoList::AgeCargo() * @return MoveToAction to be performed. */ /* static */ VehicleCargoList::MoveToAction VehicleCargoList::ChooseAction(const CargoPacket *cp, StationID cargo_next, - StationID current_station, bool accepted, StationIDStack next_station) + StationID current_station, bool accepted, std::span next_station) { if (cargo_next == StationID::Invalid()) { return (accepted && cp->first_station != current_station) ? MTA_DELIVER : MTA_KEEP; } else if (cargo_next == current_station) { return MTA_DELIVER; - } else if (next_station.Contains(cargo_next)) { + } else if (std::ranges::find(next_station, cargo_next) != std::end(next_station)) { return MTA_KEEP; } else { return MTA_TRANSFER; @@ -432,7 +432,7 @@ void VehicleCargoList::AgeCargo() * @param current_tile Current tile the cargo handling is happening on. * return If any cargo will be unloaded. */ -bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8_t order_flags, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile) +bool VehicleCargoList::Stage(bool accepted, StationID current_station, std::span next_station, uint8_t order_flags, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile) { this->AssertCountConsistency(); assert(this->action_counts[MTA_LOAD] == 0); @@ -468,9 +468,9 @@ bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationID } else { FlowStat new_shares = flow_it->second; new_shares.ChangeShare(current_station, INT_MIN); - StationIDStack excluded = next_station; - while (!excluded.IsEmpty() && !new_shares.GetShares()->empty()) { - new_shares.ChangeShare(excluded.Pop(), INT_MIN); + for (auto station_it = next_station.rbegin(); station_it != next_station.rend(); ++station_it) { + if (!new_shares.GetShares()->empty()) break; + new_shares.ChangeShare(*station_it, INT_MIN); } if (new_shares.GetShares()->empty()) { cargo_next = StationID::Invalid(); @@ -739,11 +739,11 @@ bool StationCargoList::ShiftCargo(Taction &action, StationID next) * @return Amount of cargo actually moved. */ template -uint StationCargoList::ShiftCargo(Taction action, StationIDStack next, bool include_invalid) +uint StationCargoList::ShiftCargo(Taction action, std::span next, bool include_invalid) { uint max_move = action.MaxMove(); - while (!next.IsEmpty()) { - this->ShiftCargo(action, next.Pop()); + for (auto it = next.rbegin(); it != next.rend(); ++it) { + this->ShiftCargo(action, *it); if (action.MaxMove() == 0) break; } if (include_invalid && action.MaxMove() > 0) { @@ -814,7 +814,7 @@ uint StationCargoList::Truncate(uint max_move, StationCargoAmountMap *cargo_per_ * @param current_tile Current tile the cargo handling is happening on. * @return Amount of cargo actually reserved. */ -uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, StationIDStack next_station, TileIndex current_tile) +uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, std::span next_station, TileIndex current_tile) { return this->ShiftCargo(CargoReservation(this, dest, max_move, current_tile), next_station, true); } @@ -831,7 +831,7 @@ uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, StationIDS * modes of loading are exclusive, though. If cargo is reserved we don't * need to load unreserved cargo. */ -uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, StationIDStack next_station, TileIndex current_tile) +uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, std::span next_station, TileIndex current_tile) { uint move = std::min(dest->ActionCount(VehicleCargoList::MTA_LOAD), max_move); if (move > 0) { @@ -839,7 +839,7 @@ uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, StationIDStac dest->Reassign(move); return move; } else { - return this->ShiftCargo(CargoLoad(this, dest, max_move, current_tile), next_station, true); + return this->ShiftCargo(CargoLoad{this, dest, max_move, current_tile}, next_station, true); } } @@ -853,7 +853,7 @@ uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, StationIDStac */ uint StationCargoList::Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge) { - return this->ShiftCargo(StationCargoReroute(this, dest, max_move, avoid, avoid2, ge), avoid, false); + return this->ShiftCargo(StationCargoReroute(this, dest, max_move, avoid, avoid2, ge), {&avoid, 1}, false); } /* diff --git a/src/cargopacket.h b/src/cargopacket.h index 8b4c7b6d40..35cfd2cce4 100644 --- a/src/cargopacket.h +++ b/src/cargopacket.h @@ -371,7 +371,7 @@ protected: void RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count); static MoveToAction ChooseAction(const CargoPacket *cp, StationID cargo_next, - StationID current_station, bool accepted, StationIDStack next_station); + StationID current_station, bool accepted, std::span next_station); public: /** The station cargo list needs to control the unloading. */ @@ -469,7 +469,7 @@ public: void InvalidateCache(); - bool Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8_t order_flags, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile); + bool Stage(bool accepted, StationID current_station, std::span next_station, uint8_t order_flags, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile); /** * Marks all cargo in the vehicle as to be kept. This is mostly useful for @@ -543,7 +543,7 @@ public: bool ShiftCargo(Taction &action, StationID next); template - uint ShiftCargo(Taction action, StationIDStack next, bool include_invalid); + uint ShiftCargo(Taction action, std::span next, bool include_invalid); void Append(CargoPacket *cp, StationID next); @@ -552,10 +552,10 @@ public: * @param next Station the cargo is headed for. * @return If there is any cargo for that station. */ - inline bool HasCargoFor(StationIDStack next) const + inline bool HasCargoFor(std::span next) const { - while (!next.IsEmpty()) { - if (this->packets.find(next.Pop()) != this->packets.end()) return true; + for (const StationID &station : next) { + if (this->packets.find(station) != this->packets.end()) return true; } /* Packets for StationID::Invalid() can go anywhere. */ return this->packets.find(StationID::Invalid()) != this->packets.end(); @@ -603,8 +603,8 @@ public: * amount of cargo to be moved. Second parameter is destination (if * applicable), return value is amount of cargo actually moved. */ - uint Reserve(uint max_move, VehicleCargoList *dest, StationIDStack next, TileIndex current_tile); - uint Load(uint max_move, VehicleCargoList *dest, StationIDStack next, TileIndex current_tile); + uint Reserve(uint max_move, VehicleCargoList *dest, std::span next, TileIndex current_tile); + uint Load(uint max_move, VehicleCargoList *dest, std::span next, TileIndex current_tile); uint Truncate(uint max_move = UINT_MAX, StationCargoAmountMap *cargo_per_source = nullptr); uint Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge); diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 224cfba0eb..fa76393137 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -22,7 +22,6 @@ add_files( pool_type.hpp random_func.cpp random_func.hpp - smallstack_type.hpp string_builder.cpp string_builder.hpp string_consumer.cpp diff --git a/src/core/smallstack_type.hpp b/src/core/smallstack_type.hpp deleted file mode 100644 index 3b26951453..0000000000 --- a/src/core/smallstack_type.hpp +++ /dev/null @@ -1,266 +0,0 @@ -/* - * This file is part of OpenTTD. - * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. - * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . - */ - -/** @file smallstack_type.hpp Minimal stack that uses a pool to avoid pointers and doesn't allocate any heap memory if there is only one valid item. */ - -#ifndef SMALLSTACK_TYPE_HPP -#define SMALLSTACK_TYPE_HPP - -/** - * A simplified pool which stores values instead of pointers and doesn't - * redefine operator new/delete. It also never zeroes memory and always reuses - * it. - */ -template -class SimplePool { -public: - inline SimplePool() : first_unused(0), first_free(0) {} - - /** - * Get the item at position index. - * @return Item at index. - */ - inline Titem &Get(Tindex index) { return this->data[index]; } - - /** - * Create a new item and return its index. - * @return Index of new item. - */ - inline Tindex Create() - { - Tindex index = this->FindFirstFree(); - if (index < Tmax_size) { - this->data[index].valid = true; - this->first_free = index + 1; - this->first_unused = std::max(this->first_unused, this->first_free); - } - return index; - } - - /** - * Destroy (or rather invalidate) the item at the given index. - * @param index Index of item to be destroyed. - */ - inline void Destroy(Tindex index) - { - this->data[index].valid = false; - this->first_free = std::min(this->first_free, index); - } - -private: - - inline Tindex FindFirstFree() - { - Tindex index = this->first_free; - for (; index < this->first_unused; index++) { - if (!this->data[index].valid) return index; - } - - if (index >= this->data.size() && index < Tmax_size) { - this->data.resize(index + 1); - } - return index; - } - - struct SimplePoolPoolItem : public Titem { - bool valid; - }; - - Tindex first_unused; - Tindex first_free; - - std::vector data; -}; - -/** - * Base class for SmallStack. We cannot add this into SmallStack itself as - * certain compilers don't like it. - */ -template -struct SmallStackItem { - Tindex next; ///< Pool index of next item. - Titem value; ///< Value of current item. - - /** - * Create a new item. - * @param value Value of the item. - * @param next Next item in the stack. - */ - inline SmallStackItem(const Titem &value, Tindex next) : - next(next), value(value) {} - SmallStackItem() = default; -}; - -/** - * Minimal stack that uses a pool to avoid pointers. It has some peculiar - * properties that make it useful for passing around lists of IDs but not much - * else: - * 1. It always includes an invalid item as bottom. - * 2. It doesn't have a deep copy operation but uses smart pointers instead. - * Every copy is thus implicitly shared. - * 3. Its items are immutable. - * 4. Due to 2. and 3. memory management can be done by "branch counting". - * Whenever you copy a smallstack, the first item on the heap increases its - * branch_count, signifying that there are multiple items "in front" of it. - * When deleting a stack items are deleted up to the point where - * branch_count > 0. - * 5. You can choose your own index type, so that you can align it with your - * value type. E.G. value types of 16 bits length like to be combined with - * index types of the same length. - * @tparam Titem Value type to be used. - * @tparam Tindex Index type to use for the pool. - * @tparam Tinvalid_value Value to construct invalid item to keep at the bottom of each stack. - * @tparam Tgrowth_step Growth step for pool. - * @tparam Tmax_size Maximum size for pool. - */ -template -class SmallStack : public SmallStackItem { -public: - static constexpr Titem Tinvalid{Tinvalid_value}; - - typedef SmallStackItem Item; - - /** - * SmallStack item that can be kept in a pool. - */ - struct PooledSmallStack : public Item { - Tindex branch_count; ///< Number of branches in the tree structure this item is parent of - }; - - typedef SimplePool SmallStackPool; - - /** - * Constructor for a stack with one or two items in it. - * @param value Initial item. If not missing or Tinvalid there will be Tinvalid below it. - */ - inline SmallStack(const Titem &value = Tinvalid) : Item(value, Tmax_size) {} - - /** - * Remove the head of stack and all other items members that are unique to it. - */ - inline ~SmallStack() - { - while (this->next != Tmax_size) this->Pop(); - } - - /** - * Shallow copy the stack, marking the first item as branched. - * @param other Stack to copy from - */ - inline SmallStack(const SmallStack &other) : Item(other) { this->Branch(); } - - /** - * Shallow copy the stack, marking the first item as branched. - * @param other Stack to copy from - * @return This smallstack. - */ - inline SmallStack &operator=(const SmallStack &other) - { - if (this == &other) return *this; - while (this->next != Tmax_size) this->Pop(); - this->next = other.next; - this->value = other.value; - /* Deleting and branching are independent operations, so it's fine to - * acquire separate locks for them. */ - this->Branch(); - return *this; - } - - /** - * Pushes a new item onto the stack if there is still space in the - * underlying pool. Otherwise the topmost item's value gets overwritten. - * @param item Item to be pushed. - */ - inline void Push(const Titem &item) - { - if (this->value != Tinvalid) { - Tindex new_item = SmallStack::GetPool().Create(); - if (new_item != Tmax_size) { - PooledSmallStack &pushed = SmallStack::GetPool().Get(new_item); - pushed.value = this->value; - pushed.next = this->next; - pushed.branch_count = 0; - this->next = new_item; - } - } - this->value = item; - } - - /** - * Pop an item from the stack. - * @return Current top of stack. - */ - inline Titem Pop() - { - Titem ret = this->value; - if (this->next == Tmax_size) { - this->value = Tinvalid; - } else { - PooledSmallStack &popped = SmallStack::GetPool().Get(this->next); - this->value = popped.value; - if (popped.branch_count == 0) { - SmallStack::GetPool().Destroy(this->next); - } else { - --popped.branch_count; - if (popped.next != Tmax_size) { - ++(SmallStack::GetPool().Get(popped.next).branch_count); - } - } - /* Accessing popped here is no problem as the pool will only set - * the validity flag, not actually delete the item, on Destroy(). */ - this->next = popped.next; - } - return ret; - } - - /** - * Check if the stack is empty. - * @return If the stack is empty. - */ - inline bool IsEmpty() const - { - return this->value == Tinvalid && this->next == Tmax_size; - } - - /** - * Check if the given item is contained in the stack. - * @param item Item to look for. - * @return If the item is in the stack. - */ - inline bool Contains(const Titem &item) const - { - if (item == Tinvalid || item == this->value) return true; - if (this->next != Tmax_size) { - const SmallStack *in_list = this; - do { - in_list = static_cast( - static_cast(&SmallStack::GetPool().Get(in_list->next))); - if (in_list->value == item) return true; - } while (in_list->next != Tmax_size); - } - return false; - } - -protected: - static SmallStackPool &GetPool() - { - static SmallStackPool pool; - return pool; - } - - /** - * Create a branch in the pool if necessary. - */ - inline void Branch() - { - if (this->next != Tmax_size) { - ++(SmallStack::GetPool().Get(this->next).branch_count); - } - } -}; - -#endif diff --git a/src/economy.cpp b/src/economy.cpp index 824066e898..8001d3afd8 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -1270,7 +1270,7 @@ void PrepareUnload(Vehicle *front_v) assert(CargoPayment::CanAllocateItem()); front_v->cargo_payment = new CargoPayment(front_v); - StationIDStack next_station = front_v->GetNextStoppingStation(); + std::vector next_station = front_v->GetNextStoppingStation(); if (front_v->orders == nullptr || (front_v->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) { Station *st = Station::Get(front_v->last_station_visited); for (Vehicle *v = front_v; v != nullptr; v = v->Next()) { @@ -1433,7 +1433,7 @@ struct FinalizeRefitAction { CargoArray &consist_capleft; ///< Capacities left in the consist. Station *st; ///< Station to reserve cargo from. - StationIDStack &next_station; ///< Next hops to reserve cargo for. + std::span next_station; ///< Next hops to reserve cargo for. bool do_reserve; ///< If the vehicle should reserve. /** @@ -1443,7 +1443,7 @@ struct FinalizeRefitAction * @param next_station Next hops to reserve cargo for. * @param do_reserve If we should reserve cargo or just add up the capacities. */ - FinalizeRefitAction(CargoArray &consist_capleft, Station *st, StationIDStack &next_station, bool do_reserve) : + FinalizeRefitAction(CargoArray &consist_capleft, Station *st, std::span next_station, bool do_reserve) : consist_capleft(consist_capleft), st(st), next_station(next_station), do_reserve(do_reserve) {} /** @@ -1471,7 +1471,7 @@ struct FinalizeRefitAction * @param next_station Possible next stations the vehicle can travel to. * @param new_cargo_type Target cargo for refit. */ -static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station *st, StationIDStack next_station, CargoType new_cargo_type) +static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station *st, std::span next_station, CargoType new_cargo_type) { Vehicle *v_start = v->GetFirstEnginePart(); if (!IterateVehicleParts(v_start, IsEmptyAction())) return; @@ -1538,16 +1538,16 @@ static bool MayLoadUnderExclusiveRights(const Station *st, const Vehicle *v) struct ReserveCargoAction { Station *st; - StationIDStack *next_station; + std::span next_station; - ReserveCargoAction(Station *st, StationIDStack *next_station) : + ReserveCargoAction(Station *st, std::span next_station) : st(st), next_station(next_station) {} bool operator()(Vehicle *v) { if (v->cargo_cap > v->cargo.RemainingCount() && MayLoadUnderExclusiveRights(st, v)) { st->goods[v->cargo_type].GetOrCreateData().cargo.Reserve(v->cargo_cap - v->cargo.RemainingCount(), - &v->cargo, *next_station, v->GetCargoTile()); + &v->cargo, next_station, v->GetCargoTile()); } return true; @@ -1563,7 +1563,7 @@ struct ReserveCargoAction { * @param consist_capleft If given, save free capacities after reserving there. * @param next_station Station(s) the vehicle will stop at next. */ -static void ReserveConsist(Station *st, Vehicle *u, CargoArray *consist_capleft, StationIDStack *next_station) +static void ReserveConsist(Station *st, Vehicle *u, CargoArray *consist_capleft, std::span next_station) { /* If there is a cargo payment not all vehicles of the consist have tried to do the refit. * In that case, only reserve if it's a fixed refit and the equivalent of "articulated chain" @@ -1618,14 +1618,14 @@ static void LoadUnloadVehicle(Vehicle *front) StationID last_visited = front->last_station_visited; Station *st = Station::Get(last_visited); - StationIDStack next_station = front->GetNextStoppingStation(); + std::vector next_station = front->GetNextStoppingStation(); bool use_autorefit = front->current_order.IsRefit() && front->current_order.GetRefitCargo() == CARGO_AUTO_REFIT; CargoArray consist_capleft{}; if (_settings_game.order.improved_load && use_autorefit ? front->cargo_payment == nullptr : (front->current_order.GetLoadType() & OLFB_FULL_LOAD) != 0) { ReserveConsist(st, front, (use_autorefit && front->load_unload_ticks != 0) ? &consist_capleft : nullptr, - &next_station); + next_station); } /* We have not waited enough time till the next round of loading/unloading */ diff --git a/src/linkgraph/linkgraphjob.cpp b/src/linkgraph/linkgraphjob.cpp index 5287fb633b..f83e3341a9 100644 --- a/src/linkgraph/linkgraphjob.cpp +++ b/src/linkgraph/linkgraphjob.cpp @@ -132,11 +132,11 @@ LinkGraphJob::~LinkGraphJob() !(*lg)[node_id].HasEdgeTo(dest_id) || (*lg)[node_id][dest_id].LastUpdate() == EconomyTime::INVALID_DATE) { /* Edge has been removed. Delete flows. */ - StationIDStack erased = flows.DeleteFlows(to); + std::vector erased = flows.DeleteFlows(to); /* Delete old flows for source stations which have been deleted * from the new flows. This avoids flow cycles between old and * new flows. */ - while (!erased.IsEmpty()) geflows.erase(erased.Pop()); + for (const StationID &station : erased) geflows.erase(station); } else if ((*lg)[node_id][dest_id].last_unrestricted_update == EconomyTime::INVALID_DATE) { /* Edge is fully restricted. */ flows.RestrictFlows(to); diff --git a/src/order_base.h b/src/order_base.h index 1b0f6b1752..5a2511bae0 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -367,7 +367,7 @@ public: */ inline VehicleOrderID GetNumManualOrders() const { return this->num_manual_orders; } - StationIDStack GetNextStoppingStation(const Vehicle *v, VehicleOrderID first = INVALID_VEH_ORDER_ID, uint hops = 0) const; + std::vector GetNextStoppingStation(const Vehicle *v, VehicleOrderID first = INVALID_VEH_ORDER_ID, uint hops = 0) const; VehicleOrderID GetNextDecisionNode(VehicleOrderID next, uint hops) const; void InsertOrderAt(Order &&order, VehicleOrderID index); diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 9f968a461f..32df9ffd30 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -361,14 +361,14 @@ VehicleOrderID OrderList::GetNextDecisionNode(VehicleOrderID next, uint hops) co * @pre The vehicle is currently loading and v->last_station_visited is meaningful. * @note This function may draw a random number. Don't use it from the GUI. */ -StationIDStack OrderList::GetNextStoppingStation(const Vehicle *v, VehicleOrderID first, uint hops) const +std::vector OrderList::GetNextStoppingStation(const Vehicle *v, VehicleOrderID first, uint hops) const { VehicleOrderID next = first; if (first == INVALID_VEH_ORDER_ID) { next = v->cur_implicit_order_index; if (next >= this->GetNumOrders()) { next = this->GetFirstOrder(); - if (next == INVALID_VEH_ORDER_ID) return StationID::Invalid(); + if (next == INVALID_VEH_ORDER_ID) return {}; } else { /* GetNext never returns INVALID_VEH_ORDER_ID if there is a valid station in the list. * As the given "next" is already valid and a station in the list, we @@ -392,9 +392,9 @@ StationIDStack OrderList::GetNextStoppingStation(const Vehicle *v, VehicleOrderI } else if (skip_to == INVALID_VEH_ORDER_ID || skip_to == first) { next = (advance == first) ? INVALID_VEH_ORDER_ID : advance; } else { - StationIDStack st1 = this->GetNextStoppingStation(v, skip_to, hops); - StationIDStack st2 = this->GetNextStoppingStation(v, advance, hops); - while (!st2.IsEmpty()) st1.Push(st2.Pop()); + std::vector st1 = this->GetNextStoppingStation(v, skip_to, hops); + std::vector st2 = this->GetNextStoppingStation(v, advance, hops); + std::copy(st2.rbegin(), st2.rend(), std::back_inserter(st1)); return st1; } ++hops; @@ -404,11 +404,11 @@ StationIDStack OrderList::GetNextStoppingStation(const Vehicle *v, VehicleOrderI if (next == INVALID_VEH_ORDER_ID || ((orders[next].IsType(OT_GOTO_STATION) || orders[next].IsType(OT_IMPLICIT)) && orders[next].GetDestination() == v->last_station_visited && (orders[next].GetUnloadType() & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0)) { - return StationID::Invalid(); + return {}; } } while (orders[next].IsType(OT_GOTO_DEPOT) || orders[next].GetDestination() == v->last_station_visited); - return orders[next].GetDestination().ToStationID(); + return {orders[next].GetDestination().ToStationID()}; } /** diff --git a/src/station_base.h b/src/station_base.h index d8e62d2339..4832a0f60c 100644 --- a/src/station_base.h +++ b/src/station_base.h @@ -155,7 +155,7 @@ public: void AddFlow(StationID origin, StationID via, uint amount); void PassOnFlow(StationID origin, StationID via, uint amount); - StationIDStack DeleteFlows(StationID via); + std::vector DeleteFlows(StationID via); void RestrictFlows(StationID via); void ReleaseFlows(StationID via); void FinalizeLocalConsumption(StationID self); diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 8a90e30f0e..bffab91a52 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -5200,14 +5200,14 @@ void FlowStatMap::FinalizeLocalConsumption(StationID self) * @return IDs of source stations for which the complete FlowStat, not only a * share, has been erased. */ -StationIDStack FlowStatMap::DeleteFlows(StationID via) +std::vector FlowStatMap::DeleteFlows(StationID via) { - StationIDStack ret; + std::vector ret; for (FlowStatMap::iterator f_it = this->begin(); f_it != this->end();) { FlowStat &s_flows = f_it->second; s_flows.ChangeShare(via, INT_MIN); if (s_flows.GetShares()->empty()) { - ret.Push(f_it->first); + ret.push_back(f_it->first); this->erase(f_it++); } else { ++f_it; diff --git a/src/station_type.h b/src/station_type.h index 07615dd7a1..1c4da959dd 100644 --- a/src/station_type.h +++ b/src/station_type.h @@ -11,7 +11,6 @@ #define STATION_TYPE_H #include "core/pool_type.hpp" -#include "core/smallstack_type.hpp" #include "tilearea_type.h" using StationID = PoolID; @@ -26,8 +25,6 @@ struct RoadStop; struct StationSpec; struct Waypoint; -using StationIDStack = SmallStack; - /** Station types */ enum class StationType : uint8_t { Rail, diff --git a/src/vehicle_base.h b/src/vehicle_base.h index aef3b4f246..642669ae8e 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -714,9 +714,9 @@ public: * Get the next station the vehicle will stop at. * @return ID of the next station the vehicle will stop at or StationID::Invalid(). */ - inline StationIDStack GetNextStoppingStation() const + inline std::vector GetNextStoppingStation() const { - return (this->orders == nullptr) ? StationID::Invalid() : this->orders->GetNextStoppingStation(this); + return (this->orders == nullptr) ? std::vector{} : this->orders->GetNextStoppingStation(this); } void ResetRefitCaps();