mirror of https://github.com/OpenTTD/OpenTTD.git
Change: Use vector/iterators/algorithms instead of C-array/loops for NewGRF classes.
This commit is contained in:
parent
34758d0921
commit
052f421327
|
@ -546,7 +546,7 @@ public:
|
||||||
if (change_class) {
|
if (change_class) {
|
||||||
/* If that fails, select the first available airport
|
/* If that fails, select the first available airport
|
||||||
* from the first class where airports are available. */
|
* from the first class where airports are available. */
|
||||||
for (AirportClassID j = APC_BEGIN; j < APC_MAX; j++) {
|
for (AirportClassID j = APC_BEGIN; j < AirportClass::GetClassCount(); j++) {
|
||||||
AirportClass *apclass = AirportClass::Get(j);
|
AirportClass *apclass = AirportClass::Get(j);
|
||||||
for (uint i = 0; i < apclass->GetSpecCount(); i++) {
|
for (uint i = 0; i < apclass->GetSpecCount(); i++) {
|
||||||
const AirportSpec *as = apclass->GetSpec(i);
|
const AirportSpec *as = apclass->GetSpec(i);
|
||||||
|
|
|
@ -458,6 +458,8 @@ struct StringIDMapping {
|
||||||
|
|
||||||
StringIDMapping(uint32_t grfid, StringID source, std::function<void(StringID)> &&func) : grfid(grfid), source(source), func(std::move(func)) { }
|
StringIDMapping(uint32_t grfid, StringID source, std::function<void(StringID)> &&func) : grfid(grfid), source(source), func(std::move(func)) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Strings to be mapped during load. */
|
||||||
static std::vector<StringIDMapping> _string_to_grf_mapping;
|
static std::vector<StringIDMapping> _string_to_grf_mapping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -19,17 +19,14 @@
|
||||||
template <typename Tspec, typename Tid, Tid Tmax>
|
template <typename Tspec, typename Tid, Tid Tmax>
|
||||||
class NewGRFClass {
|
class NewGRFClass {
|
||||||
private:
|
private:
|
||||||
uint ui_count; ///< Number of specs in this class potentially available to the user.
|
uint ui_count = 0; ///< Number of specs in this class potentially available to the user.
|
||||||
std::vector<Tspec *> spec; ///< List of specifications.
|
std::vector<Tspec *> spec; ///< List of specifications.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The actual classes.
|
* The actual classes.
|
||||||
* @note We store pointers to members of this array in various places outside this class (e.g. to 'name' for GRF string resolving).
|
* @note This may be reallocated during initialization so pointers may be invalidated.
|
||||||
* Thus this must be a static array, and cannot be a self-resizing vector or similar.
|
|
||||||
*/
|
*/
|
||||||
static NewGRFClass<Tspec, Tid, Tmax> classes[Tmax];
|
static inline std::vector<NewGRFClass<Tspec, Tid, Tmax>> classes;
|
||||||
|
|
||||||
void ResetClass();
|
|
||||||
|
|
||||||
/** Initialise the defaults. */
|
/** Initialise the defaults. */
|
||||||
static void InsertDefaults();
|
static void InsertDefaults();
|
||||||
|
@ -38,8 +35,12 @@ public:
|
||||||
uint32_t global_id; ///< Global ID for class, e.g. 'DFLT', 'WAYP', etc.
|
uint32_t global_id; ///< Global ID for class, e.g. 'DFLT', 'WAYP', etc.
|
||||||
StringID name; ///< Name of this class.
|
StringID name; ///< Name of this class.
|
||||||
|
|
||||||
|
/* Public constructor as emplace_back needs access. */
|
||||||
|
NewGRFClass(uint32_t global_id, StringID name) : global_id(global_id), name(name) { }
|
||||||
|
|
||||||
void Insert(Tspec *spec);
|
void Insert(Tspec *spec);
|
||||||
|
|
||||||
|
Tid Index() const { return static_cast<Tid>(std::distance(&*std::cbegin(NewGRFClass::classes), this)); }
|
||||||
/** Get the number of allocated specs within the class. */
|
/** Get the number of allocated specs within the class. */
|
||||||
uint GetSpecCount() const { return static_cast<uint>(this->spec.size()); }
|
uint GetSpecCount() const { return static_cast<uint>(this->spec.size()); }
|
||||||
/** Get the number of potentially user-available specs within the class. */
|
/** Get the number of potentially user-available specs within the class. */
|
||||||
|
|
|
@ -11,35 +11,19 @@
|
||||||
|
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
|
|
||||||
/** Instantiate the array. */
|
|
||||||
template <typename Tspec, typename Tid, Tid Tmax>
|
|
||||||
NewGRFClass<Tspec, Tid, Tmax> NewGRFClass<Tspec, Tid, Tmax>::classes[Tmax];
|
|
||||||
|
|
||||||
/** Reset the class, i.e. clear everything. */
|
|
||||||
template <typename Tspec, typename Tid, Tid Tmax>
|
|
||||||
void NewGRFClass<Tspec, Tid, Tmax>::ResetClass()
|
|
||||||
{
|
|
||||||
this->global_id = 0;
|
|
||||||
this->name = STR_EMPTY;
|
|
||||||
this->ui_count = 0;
|
|
||||||
|
|
||||||
this->spec.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Reset the classes, i.e. clear everything. */
|
/** Reset the classes, i.e. clear everything. */
|
||||||
template <typename Tspec, typename Tid, Tid Tmax>
|
template <typename Tspec, typename Tid, Tid Tmax>
|
||||||
void NewGRFClass<Tspec, Tid, Tmax>::Reset()
|
void NewGRFClass<Tspec, Tid, Tmax>::Reset()
|
||||||
{
|
{
|
||||||
for (Tid i = (Tid)0; i < Tmax; i++) {
|
NewGRFClass::classes.clear();
|
||||||
classes[i].ResetClass();
|
NewGRFClass::classes.shrink_to_fit();
|
||||||
}
|
|
||||||
|
|
||||||
InsertDefaults();
|
NewGRFClass::InsertDefaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate a class with a given global class ID.
|
* Allocate a class with a given global class ID.
|
||||||
* @param cls_id The global class id, such as 'DFLT'.
|
* @param global_id The global class id, such as 'DFLT'.
|
||||||
* @return The (non global!) class ID for the class.
|
* @return The (non global!) class ID for the class.
|
||||||
* @note Upon allocating the same global class ID for a
|
* @note Upon allocating the same global class ID for a
|
||||||
* second time, this first allocation will be given.
|
* second time, this first allocation will be given.
|
||||||
|
@ -47,19 +31,19 @@ void NewGRFClass<Tspec, Tid, Tmax>::Reset()
|
||||||
template <typename Tspec, typename Tid, Tid Tmax>
|
template <typename Tspec, typename Tid, Tid Tmax>
|
||||||
Tid NewGRFClass<Tspec, Tid, Tmax>::Allocate(uint32_t global_id)
|
Tid NewGRFClass<Tspec, Tid, Tmax>::Allocate(uint32_t global_id)
|
||||||
{
|
{
|
||||||
for (Tid i = (Tid)0; i < Tmax; i++) {
|
auto found = std::find_if(std::begin(NewGRFClass::classes), std::end(NewGRFClass::classes), [global_id](const auto &cls) { return cls.global_id == global_id; });
|
||||||
if (classes[i].global_id == global_id) {
|
|
||||||
/* ClassID is already allocated, so reuse it. */
|
/* Id is already allocated, so reuse it. */
|
||||||
return i;
|
if (found != std::end(NewGRFClass::classes)) return found->Index();
|
||||||
} else if (classes[i].global_id == 0) {
|
|
||||||
/* This class is empty, so allocate it to the global id. */
|
/* More slots available, allocate a slot to the global id. */
|
||||||
classes[i].global_id = global_id;
|
if (NewGRFClass::classes.size() < Tmax) {
|
||||||
return i;
|
auto &cls = NewGRFClass::classes.emplace_back(global_id, STR_EMPTY);
|
||||||
}
|
return cls.Index();
|
||||||
}
|
}
|
||||||
|
|
||||||
GrfMsg(2, "ClassAllocate: already allocated {} classes, using default", Tmax);
|
GrfMsg(2, "ClassAllocate: already allocated {} classes, using default", Tmax);
|
||||||
return (Tid)0;
|
return static_cast<Tid>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -82,7 +66,7 @@ void NewGRFClass<Tspec, Tid, Tmax>::Insert(Tspec *spec)
|
||||||
template <typename Tspec, typename Tid, Tid Tmax>
|
template <typename Tspec, typename Tid, Tid Tmax>
|
||||||
void NewGRFClass<Tspec, Tid, Tmax>::Assign(Tspec *spec)
|
void NewGRFClass<Tspec, Tid, Tmax>::Assign(Tspec *spec)
|
||||||
{
|
{
|
||||||
assert(spec->cls_id < Tmax);
|
assert(static_cast<size_t>(spec->cls_id) < NewGRFClass::classes.size());
|
||||||
Get(spec->cls_id)->Insert(spec);
|
Get(spec->cls_id)->Insert(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,8 +78,8 @@ void NewGRFClass<Tspec, Tid, Tmax>::Assign(Tspec *spec)
|
||||||
template <typename Tspec, typename Tid, Tid Tmax>
|
template <typename Tspec, typename Tid, Tid Tmax>
|
||||||
NewGRFClass<Tspec, Tid, Tmax> *NewGRFClass<Tspec, Tid, Tmax>::Get(Tid cls_id)
|
NewGRFClass<Tspec, Tid, Tmax> *NewGRFClass<Tspec, Tid, Tmax>::Get(Tid cls_id)
|
||||||
{
|
{
|
||||||
assert(cls_id < Tmax);
|
assert(static_cast<size_t>(cls_id) < NewGRFClass::classes.size());
|
||||||
return classes + cls_id;
|
return &NewGRFClass::classes[cls_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,9 +89,7 @@ NewGRFClass<Tspec, Tid, Tmax> *NewGRFClass<Tspec, Tid, Tmax>::Get(Tid cls_id)
|
||||||
template <typename Tspec, typename Tid, Tid Tmax>
|
template <typename Tspec, typename Tid, Tid Tmax>
|
||||||
uint NewGRFClass<Tspec, Tid, Tmax>::GetClassCount()
|
uint NewGRFClass<Tspec, Tid, Tmax>::GetClassCount()
|
||||||
{
|
{
|
||||||
uint i;
|
return static_cast<uint>(NewGRFClass::classes.size());
|
||||||
for (i = 0; i < Tmax && classes[i].global_id != 0; i++) {}
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -117,11 +99,7 @@ uint NewGRFClass<Tspec, Tid, Tmax>::GetClassCount()
|
||||||
template <typename Tspec, typename Tid, Tid Tmax>
|
template <typename Tspec, typename Tid, Tid Tmax>
|
||||||
uint NewGRFClass<Tspec, Tid, Tmax>::GetUIClassCount()
|
uint NewGRFClass<Tspec, Tid, Tmax>::GetUIClassCount()
|
||||||
{
|
{
|
||||||
uint cnt = 0;
|
return std::count_if(std::begin(NewGRFClass::classes), std::end(NewGRFClass::classes), [](const auto &cls) { return cls.GetUISpecCount() > 0; });
|
||||||
for (uint i = 0; i < Tmax && classes[i].global_id != 0; i++) {
|
|
||||||
if (classes[i].GetUISpecCount() > 0) cnt++;
|
|
||||||
}
|
|
||||||
return cnt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -132,9 +110,9 @@ uint NewGRFClass<Tspec, Tid, Tmax>::GetUIClassCount()
|
||||||
template <typename Tspec, typename Tid, Tid Tmax>
|
template <typename Tspec, typename Tid, Tid Tmax>
|
||||||
Tid NewGRFClass<Tspec, Tid, Tmax>::GetUIClass(uint index)
|
Tid NewGRFClass<Tspec, Tid, Tmax>::GetUIClass(uint index)
|
||||||
{
|
{
|
||||||
for (uint i = 0; i < Tmax && classes[i].global_id != 0; i++) {
|
for (const auto &cls : NewGRFClass::classes) {
|
||||||
if (classes[i].GetUISpecCount() == 0) continue;
|
if (cls.GetUISpecCount() == 0) continue;
|
||||||
if (index-- == 0) return (Tid)i;
|
if (index-- == 0) return cls.Index();
|
||||||
}
|
}
|
||||||
NOT_REACHED();
|
NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -193,15 +171,11 @@ int NewGRFClass<Tspec, Tid, Tmax>::GetUIFromIndex(int index) const
|
||||||
template <typename Tspec, typename Tid, Tid Tmax>
|
template <typename Tspec, typename Tid, Tid Tmax>
|
||||||
const Tspec *NewGRFClass<Tspec, Tid, Tmax>::GetByGrf(uint32_t grfid, uint16_t local_id, int *index)
|
const Tspec *NewGRFClass<Tspec, Tid, Tmax>::GetByGrf(uint32_t grfid, uint16_t local_id, int *index)
|
||||||
{
|
{
|
||||||
uint j;
|
for (const auto &cls : NewGRFClass::classes) {
|
||||||
|
for (const auto &spec : cls.spec) {
|
||||||
for (Tid i = (Tid)0; i < Tmax; i++) {
|
|
||||||
uint count = static_cast<uint>(classes[i].spec.size());
|
|
||||||
for (j = 0; j < count; j++) {
|
|
||||||
const Tspec *spec = classes[i].spec[j];
|
|
||||||
if (spec == nullptr) continue;
|
if (spec == nullptr) continue;
|
||||||
if (spec->grf_prop.grffile->grfid == grfid && spec->grf_prop.local_id == local_id) {
|
if (spec->grf_prop.grffile->grfid == grfid && spec->grf_prop.local_id == local_id) {
|
||||||
if (index != nullptr) *index = j;
|
if (index != nullptr) *index = static_cast<int>(std::distance(cls.spec.data(), &spec));
|
||||||
return spec;
|
return spec;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue