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