Codechange: Use std::span for industry cargo window instead of pointer + length.

This commit is contained in:
Peter Nelson 2024-03-24 15:37:01 +00:00 committed by Peter Nelson
parent 6f36f3d714
commit e4fc8ef595
1 changed files with 46 additions and 60 deletions

View File

@ -2089,23 +2089,17 @@ struct CargoesField {
/**
* Make a piece of cargo column.
* @param cargoes Array of #CargoID (may contain #INVALID_CARGO).
* @param length Number of cargoes in \a cargoes.
* @param cargoes Span of #CargoID (may contain #INVALID_CARGO).
* @param count Number of cargoes to display (should be at least the number of valid cargoes, or \c -1 to let the method compute it).
* @param top_end This is the first cargo field of this column.
* @param bottom_end This is the last cargo field of this column.
* @note #supp_cargoes and #cust_cargoes should be filled in later.
*/
void MakeCargo(const CargoID *cargoes, uint length, int count = -1, bool top_end = false, bool bottom_end = false)
void MakeCargo(const std::span<const CargoID> cargoes, int count = -1, bool top_end = false, bool bottom_end = false)
{
this->type = CFT_CARGO;
auto insert = std::begin(this->u.cargo.vertical_cargoes);
for (uint i = 0; insert != std::end(this->u.cargo.vertical_cargoes) && i < length; i++) {
if (IsValidCargoID(cargoes[i])) {
*insert = cargoes[i];
++insert;
}
}
assert(std::size(cargoes) <= std::size(this->u.cargo.vertical_cargoes));
auto insert = std::copy_if(std::begin(cargoes), std::end(cargoes), std::begin(this->u.cargo.vertical_cargoes), IsValidCargoID);
this->u.cargo.num_cargoes = (count < 0) ? static_cast<uint8_t>(insert - std::begin(this->u.cargo.vertical_cargoes)) : count;
CargoIDComparator comparator;
std::sort(std::begin(this->u.cargo.vertical_cargoes), insert, comparator);
@ -2118,16 +2112,15 @@ struct CargoesField {
/**
* Make a field displaying cargo type names.
* @param cargoes Array of #CargoID (may contain #INVALID_CARGO).
* @param length Number of cargoes in \a cargoes.
* @param cargoes Span of #CargoID (may contain #INVALID_CARGO).
* @param left_align ALign texts to the left (else to the right).
*/
void MakeCargoLabel(const CargoID *cargoes, uint length, bool left_align)
void MakeCargoLabel(const std::span<const CargoID> cargoes, bool left_align)
{
this->type = CFT_CARGO_LABEL;
uint i;
for (i = 0; i < MAX_CARGOES && i < length; i++) this->u.cargo_label.cargoes[i] = cargoes[i];
for (; i < MAX_CARGOES; i++) this->u.cargo_label.cargoes[i] = INVALID_CARGO;
assert(std::size(cargoes) <= std::size(this->u.cargo_label.cargoes));
auto insert = std::copy(std::begin(cargoes), std::end(cargoes), std::begin(this->u.cargo_label.cargoes));
std::fill(insert, std::end(this->u.cargo_label.cargoes), INVALID_CARGO);
this->u.cargo_label.left_align = left_align;
}
@ -2197,7 +2190,7 @@ struct CargoesField {
}
/* Draw the other_produced/other_accepted cargoes. */
const CargoID *other_right, *other_left;
std::span<const CargoID> other_right, other_left;
if (_current_text_dir == TD_RTL) {
other_right = this->u.industry.other_accepted;
other_left = this->u.industry.other_produced;
@ -2471,7 +2464,7 @@ struct CargoesRow {
int col = cargo_fld->ConnectCargo(cargo_fld->u.cargo.vertical_cargoes[i], !accepting);
if (col >= 0) cargoes[col] = cargo_fld->u.cargo.vertical_cargoes[i];
}
label_fld->MakeCargoLabel(cargoes, lengthof(cargoes), accepting);
label_fld->MakeCargoLabel(cargoes, accepting);
}
@ -2670,34 +2663,29 @@ struct IndustryCargoesWindow : public Window {
/**
* Do the two sets of cargoes have a valid cargo in common?
* @param cargoes1 Base address of the first cargo array.
* @param length1 Number of cargoes in the first cargo array.
* @param cargoes2 Base address of the second cargo array.
* @param length2 Number of cargoes in the second cargo array.
* @param cargoes1 Span of the first cargo list.
* @param cargoes2 Span of the second cargo list.
* @return Arrays have at least one valid cargo in common.
*/
static bool HasCommonValidCargo(const CargoID *cargoes1, uint length1, const CargoID *cargoes2, uint length2)
static bool HasCommonValidCargo(const std::span<const CargoID> cargoes1, const std::span<const CargoID> cargoes2)
{
while (length1 > 0) {
if (IsValidCargoID(*cargoes1)) {
for (uint i = 0; i < length2; i++) if (*cargoes1 == cargoes2[i]) return true;
for (const CargoID cid1 : cargoes1) {
if (!IsValidCargoID(cid1)) continue;
for (const CargoID cid2 : cargoes2) {
if (cid1 == cid2) return true;
}
cargoes1++;
length1--;
}
return false;
}
/**
* Can houses be used to supply one of the cargoes?
* @param cargoes Base address of the cargo array.
* @param length Number of cargoes in the array.
* @param cargoes Span of cargo list.
* @return Houses can supply at least one of the cargoes.
*/
static bool HousesCanSupply(const CargoID *cargoes, uint length)
static bool HousesCanSupply(const std::span<const CargoID> cargoes)
{
for (uint i = 0; i < length; i++) {
CargoID cid = cargoes[i];
for (const CargoID cid : cargoes) {
if (!IsValidCargoID(cid)) continue;
TownProductionEffect tpe = CargoSpec::Get(cid)->town_production_effect;
if (tpe == TPE_PASSENGERS || tpe == TPE_MAIL) return true;
@ -2707,11 +2695,10 @@ struct IndustryCargoesWindow : public Window {
/**
* Can houses be used as customers of the produced cargoes?
* @param cargoes Base address of the cargo array.
* @param length Number of cargoes in the array.
* @param cargoes Span of cargo list.
* @return Houses can accept at least one of the cargoes.
*/
static bool HousesCanAccept(const CargoID *cargoes, uint length)
static bool HousesCanAccept(const std::span<const CargoID> cargoes)
{
HouseZones climate_mask;
switch (_settings_game.game_creation.landscape) {
@ -2721,14 +2708,14 @@ struct IndustryCargoesWindow : public Window {
case LT_TOYLAND: climate_mask = HZ_TOYLND; break;
default: NOT_REACHED();
}
for (uint i = 0; i < length; i++) {
if (!IsValidCargoID(cargoes[i])) continue;
for (const CargoID cid : cargoes) {
if (!IsValidCargoID(cid)) continue;
for (const auto &hs : HouseSpec::Specs()) {
if (!hs.enabled || !(hs.building_availability & climate_mask)) continue;
for (uint j = 0; j < lengthof(hs.accepts_cargo); j++) {
if (hs.cargo_acceptance[j] > 0 && cargoes[i] == hs.accepts_cargo[j]) return true;
if (hs.cargo_acceptance[j] > 0 && cid == hs.accepts_cargo[j]) return true;
}
}
}
@ -2738,17 +2725,16 @@ struct IndustryCargoesWindow : public Window {
/**
* Count how many industries have accepted cargoes in common with one of the supplied set.
* @param cargoes Cargoes to search.
* @param length Number of cargoes in \a cargoes.
* @return Number of industries that have an accepted cargo in common with the supplied set.
*/
static int CountMatchingAcceptingIndustries(const CargoID *cargoes, uint length)
static int CountMatchingAcceptingIndustries(const std::span<const CargoID> cargoes)
{
int count = 0;
for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
const IndustrySpec *indsp = GetIndustrySpec(it);
if (!indsp->enabled) continue;
if (HasCommonValidCargo(cargoes, length, indsp->accepts_cargo, lengthof(indsp->accepts_cargo))) count++;
if (HasCommonValidCargo(cargoes, indsp->accepts_cargo)) count++;
}
return count;
}
@ -2756,17 +2742,16 @@ struct IndustryCargoesWindow : public Window {
/**
* Count how many industries have produced cargoes in common with one of the supplied set.
* @param cargoes Cargoes to search.
* @param length Number of cargoes in \a cargoes.
* @return Number of industries that have a produced cargo in common with the supplied set.
*/
static int CountMatchingProducingIndustries(const CargoID *cargoes, uint length)
static int CountMatchingProducingIndustries(const std::span<const CargoID> cargoes)
{
int count = 0;
for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
const IndustrySpec *indsp = GetIndustrySpec(it);
if (!indsp->enabled) continue;
if (HasCommonValidCargo(cargoes, length, indsp->produced_cargo, lengthof(indsp->produced_cargo))) count++;
if (HasCommonValidCargo(cargoes, indsp->produced_cargo)) count++;
}
return count;
}
@ -2841,18 +2826,18 @@ struct IndustryCargoesWindow : public Window {
first_row.columns[4].MakeHeader(STR_INDUSTRY_CARGOES_CUSTOMERS);
const IndustrySpec *central_sp = GetIndustrySpec(displayed_it);
bool houses_supply = HousesCanSupply(central_sp->accepts_cargo, lengthof(central_sp->accepts_cargo));
bool houses_accept = HousesCanAccept(central_sp->produced_cargo, lengthof(central_sp->produced_cargo));
bool houses_supply = HousesCanSupply(central_sp->accepts_cargo);
bool houses_accept = HousesCanAccept(central_sp->produced_cargo);
/* Make a field consisting of two cargo columns. */
int num_supp = CountMatchingProducingIndustries(central_sp->accepts_cargo, lengthof(central_sp->accepts_cargo)) + houses_supply;
int num_cust = CountMatchingAcceptingIndustries(central_sp->produced_cargo, lengthof(central_sp->produced_cargo)) + houses_accept;
int num_supp = CountMatchingProducingIndustries(central_sp->accepts_cargo) + houses_supply;
int num_cust = CountMatchingAcceptingIndustries(central_sp->produced_cargo) + houses_accept;
int num_indrows = std::max(3, std::max(num_supp, num_cust)); // One is needed for the 'it' industry, and 2 for the cargo labels.
for (int i = 0; i < num_indrows; i++) {
CargoesRow &row = this->fields.emplace_back();
row.columns[0].MakeEmpty(CFT_EMPTY);
row.columns[1].MakeCargo(central_sp->accepts_cargo, lengthof(central_sp->accepts_cargo));
row.columns[1].MakeCargo(central_sp->accepts_cargo);
row.columns[2].MakeEmpty(CFT_EMPTY);
row.columns[3].MakeCargo(central_sp->produced_cargo, lengthof(central_sp->produced_cargo));
row.columns[3].MakeCargo(central_sp->produced_cargo);
row.columns[4].MakeEmpty(CFT_EMPTY);
}
/* Add central industry. */
@ -2872,12 +2857,12 @@ struct IndustryCargoesWindow : public Window {
const IndustrySpec *indsp = GetIndustrySpec(it);
if (!indsp->enabled) continue;
if (HasCommonValidCargo(central_sp->accepts_cargo, lengthof(central_sp->accepts_cargo), indsp->produced_cargo, lengthof(indsp->produced_cargo))) {
if (HasCommonValidCargo(central_sp->accepts_cargo, indsp->produced_cargo)) {
this->PlaceIndustry(1 + supp_count * num_indrows / num_supp, 0, it);
_displayed_industries.set(it);
supp_count++;
}
if (HasCommonValidCargo(central_sp->produced_cargo, lengthof(central_sp->produced_cargo), indsp->accepts_cargo, lengthof(indsp->accepts_cargo))) {
if (HasCommonValidCargo(central_sp->produced_cargo, indsp->accepts_cargo)) {
this->PlaceIndustry(1 + cust_count * num_indrows / num_cust, 4, it);
_displayed_industries.set(it);
cust_count++;
@ -2917,15 +2902,16 @@ struct IndustryCargoesWindow : public Window {
first_row.columns[3].MakeEmpty(CFT_SMALL_EMPTY);
first_row.columns[4].MakeEmpty(CFT_SMALL_EMPTY);
bool houses_supply = HousesCanSupply(&cid, 1);
bool houses_accept = HousesCanAccept(&cid, 1);
int num_supp = CountMatchingProducingIndustries(&cid, 1) + houses_supply + 1; // Ensure room for the cargo label.
int num_cust = CountMatchingAcceptingIndustries(&cid, 1) + houses_accept;
auto cargoes = std::span(&cid, 1);
bool houses_supply = HousesCanSupply(cargoes);
bool houses_accept = HousesCanAccept(cargoes);
int num_supp = CountMatchingProducingIndustries(cargoes) + houses_supply + 1; // Ensure room for the cargo label.
int num_cust = CountMatchingAcceptingIndustries(cargoes) + houses_accept;
int num_indrows = std::max(num_supp, num_cust);
for (int i = 0; i < num_indrows; i++) {
CargoesRow &row = this->fields.emplace_back();
row.columns[0].MakeEmpty(CFT_EMPTY);
row.columns[1].MakeCargo(&cid, 1);
row.columns[1].MakeCargo(cargoes);
row.columns[2].MakeEmpty(CFT_EMPTY);
row.columns[3].MakeEmpty(CFT_EMPTY);
row.columns[4].MakeEmpty(CFT_EMPTY);
@ -2940,12 +2926,12 @@ struct IndustryCargoesWindow : public Window {
const IndustrySpec *indsp = GetIndustrySpec(it);
if (!indsp->enabled) continue;
if (HasCommonValidCargo(&cid, 1, indsp->produced_cargo, lengthof(indsp->produced_cargo))) {
if (HasCommonValidCargo(cargoes, indsp->produced_cargo)) {
this->PlaceIndustry(1 + supp_count * num_indrows / num_supp, 0, it);
_displayed_industries.set(it);
supp_count++;
}
if (HasCommonValidCargo(&cid, 1, indsp->accepts_cargo, lengthof(indsp->accepts_cargo))) {
if (HasCommonValidCargo(cargoes, indsp->accepts_cargo)) {
this->PlaceIndustry(1 + cust_count * num_indrows / num_cust, 2, it);
_displayed_industries.set(it);
cust_count++;