1
0
Fork 0

Codechange: Use traits to define BaseSet parameters.

pull/13905/head
Peter Nelson 2025-03-26 18:11:55 +00:00 committed by Peter Nelson
parent 6914d99778
commit 3375dc3095
8 changed files with 60 additions and 50 deletions

View File

@ -38,21 +38,25 @@ struct MD5File {
ChecksumResult CheckMD5(Subdirectory subdir, size_t max_size) const;
};
/** Defines the traits of a BaseSet type. */
template <class T> struct BaseSetTraits;
/**
* Information about a single base set.
* @tparam T the real class we're going to be
* @tparam Tnum_files the number of files in the set
* @tparam Tsearch_in_tars whether to search in the tars or not
*/
template <class T, size_t Tnum_files, bool Tsearch_in_tars>
template <class T>
struct BaseSet {
typedef std::unordered_map<std::string, std::string> TranslatedStrings;
/** Number of files in this set */
static const size_t NUM_FILES = Tnum_files;
static constexpr size_t NUM_FILES = BaseSetTraits<T>::num_files;
/** Whether to search in the tars or not. */
static const bool SEARCH_IN_TARS = Tsearch_in_tars;
static constexpr bool SEARCH_IN_TARS = BaseSetTraits<T>::search_in_tars;
/** BaseSet type name. */
static constexpr std::string_view SET_TYPE = BaseSetTraits<T>::set_type;
/** Internal names of the files in this set. */
static const char * const *file_names;
@ -64,7 +68,7 @@ struct BaseSet {
uint32_t version; ///< The version of this base set
bool fallback; ///< This set is a fallback set, i.e. it should be used only as last resort
MD5File files[NUM_FILES]; ///< All files part of this set
MD5File files[BaseSet<T>::NUM_FILES]; ///< All files part of this set
uint found_files; ///< Number of the files that could be found
uint valid_files; ///< Number of the files that could be found and are valid
@ -82,7 +86,7 @@ struct BaseSet {
*/
int GetNumMissing() const
{
return Tnum_files - this->found_files;
return BaseSet<T>::NUM_FILES - this->found_files;
}
/**
@ -92,7 +96,7 @@ struct BaseSet {
*/
int GetNumInvalid() const
{
return Tnum_files - this->valid_files;
return BaseSet<T>::NUM_FILES - this->valid_files;
}
bool FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename, bool allow_empty_filename = true);

View File

@ -7,7 +7,6 @@
/**
* @file base_media_func.h Generic function implementations for base data (graphics, sounds).
* @note You should _never_ include this file due to the SET_TYPE define.
*/
#include "base_media_base.h"
@ -25,7 +24,7 @@ extern void CheckExternalFiles();
#define fetch_metadata(name) \
item = metadata->GetItem(name); \
if (item == nullptr || !item->value.has_value() || item->value->empty()) { \
Debug(grf, 0, "Base " SET_TYPE "set detail loading: {} field missing.", name); \
Debug(grf, 0, "Base {}set detail loading: {} field missing.", BaseSet::SET_TYPE, name); \
Debug(grf, 0, " Is {} readable for the user running OpenTTD?", full_filename); \
return false; \
}
@ -38,12 +37,12 @@ extern void CheckExternalFiles();
* @param allow_empty_filename empty filenames are valid
* @return true if loading was successful.
*/
template <class T, size_t Tnum_files, bool Tsearch_in_tars>
bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename, bool allow_empty_filename)
template <class T>
bool BaseSet<T>::FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename, bool allow_empty_filename)
{
const IniGroup *metadata = ini.GetGroup("metadata");
if (metadata == nullptr) {
Debug(grf, 0, "Base " SET_TYPE "set detail loading: metadata missing.");
Debug(grf, 0, "Base {}set detail loading: metadata missing.", BaseSet<T>::SET_TYPE);
Debug(grf, 0, " Is {} readable for the user running OpenTTD?", full_filename);
return false;
}
@ -80,12 +79,12 @@ bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(const IniFile &ini,
const IniGroup *files = ini.GetGroup("files");
const IniGroup *md5s = ini.GetGroup("md5s");
const IniGroup *origin = ini.GetGroup("origin");
for (uint i = 0; i < Tnum_files; i++) {
for (uint i = 0; i < BaseSet<T>::NUM_FILES; i++) {
MD5File *file = &this->files[i];
/* Find the filename first. */
item = files != nullptr ? files->GetItem(BaseSet<T, Tnum_files, Tsearch_in_tars>::file_names[i]) : nullptr;
item = files != nullptr ? files->GetItem(BaseSet<T>::file_names[i]) : nullptr;
if (item == nullptr || (!item->value.has_value() && !allow_empty_filename)) {
Debug(grf, 0, "No " SET_TYPE " file for: {} (in {})", BaseSet<T, Tnum_files, Tsearch_in_tars>::file_names[i], full_filename);
Debug(grf, 0, "No {} file for: {} (in {})", BaseSet<T>::SET_TYPE, BaseSet<T>::file_names[i], full_filename);
return false;
}
@ -164,7 +163,7 @@ template <class Tbase_set>
bool BaseMedia<Tbase_set>::AddFile(const std::string &filename, size_t basepath_length, const std::string &)
{
bool ret = false;
Debug(grf, 1, "Checking {} for base " SET_TYPE " set", filename);
Debug(grf, 1, "Checking {} for base {} set", filename, BaseSet<Tbase_set>::SET_TYPE);
Tbase_set *set = new Tbase_set();
IniFile ini{};
@ -190,7 +189,8 @@ bool BaseMedia<Tbase_set>::AddFile(const std::string &filename, size_t basepath_
/* The more complete set takes precedence over the version number. */
if ((duplicate->valid_files == set->valid_files && duplicate->version >= set->version) ||
duplicate->valid_files > set->valid_files) {
Debug(grf, 1, "Not adding {} ({}) as base " SET_TYPE " set (duplicate, {})", set->name, set->version,
Debug(grf, 1, "Not adding {} ({}) as base {} set (duplicate, {})", set->name, set->version,
BaseSet<Tbase_set>::SET_TYPE,
duplicate->valid_files > set->valid_files ? "less valid files" : "lower version");
set->next = BaseMedia<Tbase_set>::duplicate_sets;
BaseMedia<Tbase_set>::duplicate_sets = set;
@ -209,7 +209,8 @@ bool BaseMedia<Tbase_set>::AddFile(const std::string &filename, size_t basepath_
* version number until a new game is started which isn't a big problem */
if (BaseMedia<Tbase_set>::used_set == duplicate) BaseMedia<Tbase_set>::used_set = set;
Debug(grf, 1, "Removing {} ({}) as base " SET_TYPE " set (duplicate, {})", duplicate->name, duplicate->version,
Debug(grf, 1, "Removing {} ({}) as base {} set (duplicate, {})", duplicate->name, duplicate->version,
BaseSet<Tbase_set>::SET_TYPE,
duplicate->valid_files < set->valid_files ? "less valid files" : "lower version");
duplicate->next = BaseMedia<Tbase_set>::duplicate_sets;
BaseMedia<Tbase_set>::duplicate_sets = duplicate;
@ -223,7 +224,7 @@ bool BaseMedia<Tbase_set>::AddFile(const std::string &filename, size_t basepath_
ret = true;
}
if (ret) {
Debug(grf, 1, "Adding {} ({}) as base " SET_TYPE " set", set->name, set->version);
Debug(grf, 1, "Adding {} ({}) as base {} set", set->name, set->version, BaseSet<Tbase_set>::SET_TYPE);
}
} else {
delete set;
@ -296,7 +297,7 @@ template <class Tbase_set>
template <class Tbase_set>
/* static */ void BaseMedia<Tbase_set>::GetSetsList(std::back_insert_iterator<std::string> &output_iterator)
{
fmt::format_to(output_iterator, "List of " SET_TYPE " sets:\n");
fmt::format_to(output_iterator, "List of {} sets:\n", BaseSet<Tbase_set>::SET_TYPE);
for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != nullptr; s = s->next) {
fmt::format_to(output_iterator, "{:>18}: {}", s->name, s->GetDescription({}));
int invalid = s->GetNumInvalid();
@ -383,7 +384,7 @@ template <class Tbase_set>
if (index == 0) return s;
index--;
}
FatalError("Base" SET_TYPE "::GetSet(): index {} out of range", index);
FatalError("Base{}::GetSet(): index {} out of range", BaseSet<Tbase_set>::SET_TYPE, index);
}
/**

View File

@ -31,13 +31,19 @@ enum BlitterType : uint8_t {
struct GRFConfig;
template <> struct BaseSetTraits<struct GraphicsSet> {
static constexpr size_t num_files = MAX_GFT;
static constexpr bool search_in_tars = true;
static constexpr std::string_view set_type = "graphics";
};
/** All data of a graphics set. */
struct GraphicsSet : BaseSet<GraphicsSet, MAX_GFT, true> {
struct GraphicsSet : BaseSet<GraphicsSet> {
private:
mutable std::unique_ptr<GRFConfig> extra_cfg; ///< Parameters for extra GRF
mutable std::unique_ptr<GRFConfig> extra_cfg = nullptr; ///< Parameters for extra GRF
public:
PaletteType palette; ///< Palette of this graphics set
BlitterType blitter; ///< Blitter of this graphics set
PaletteType palette{}; ///< Palette of this graphics set
BlitterType blitter{}; ///< Blitter of this graphics set
GraphicsSet();
~GraphicsSet();

View File

@ -43,12 +43,18 @@ struct MusicSongInfo {
int override_end; ///< MIDI tick to end the song at (0 if no override)
};
template <> struct BaseSetTraits<struct MusicSet> {
static constexpr size_t num_files = NUM_SONGS_AVAILABLE;
static constexpr bool search_in_tars = false;
static constexpr std::string_view set_type = "music";
};
/** All data of a music set. */
struct MusicSet : BaseSet<MusicSet, NUM_SONGS_AVAILABLE, false> {
struct MusicSet : BaseSet<MusicSet> {
/** Data about individual songs in set. */
MusicSongInfo songinfo[NUM_SONGS_AVAILABLE];
/** Number of valid songs in set. */
uint8_t num_available;
uint8_t num_available = 0;
bool FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename);
};

View File

@ -12,16 +12,20 @@
#include "base_media_base.h"
/** All data of a sounds set. */
struct SoundsSet : BaseSet<SoundsSet, 1, true> {
template <> struct BaseSetTraits<struct SoundsSet> {
static constexpr size_t num_files = 1;
static constexpr bool search_in_tars = true;
static constexpr std::string_view set_type = "sounds";
};
/** All data of a sounds set. */
struct SoundsSet : BaseSet<SoundsSet> {};
/** All data/functions related with replacing the base sounds */
class BaseSounds : public BaseMedia<SoundsSet> {
public:
/** The set as saved in the config file. */
static inline std::string ini_set;
};
#endif /* BASE_MEDIA_SOUNDS_H */

View File

@ -18,9 +18,6 @@
#include "video/video_driver.hpp"
#include "window_func.h"
#include "palette_func.h"
/* The type of set we're replacing */
#define SET_TYPE "graphics"
#include "base_media_func.h"
#include "base_media_graphics.h"
#include "base_media_sounds.h"
@ -350,7 +347,6 @@ void GfxLoadSprites()
}
GraphicsSet::GraphicsSet()
: BaseSet<GraphicsSet, MAX_GFT, true>{}, palette{}, blitter{}
{
// instantiate here, because unique_ptr needs a complete type
}
@ -362,7 +358,7 @@ GraphicsSet::~GraphicsSet()
bool GraphicsSet::FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename)
{
bool ret = this->BaseSet<GraphicsSet, MAX_GFT, true>::FillSetDetails(ini, path, full_filename, false);
bool ret = this->BaseSet<GraphicsSet>::FillSetDetails(ini, path, full_filename, false);
if (ret) {
const IniGroup *metadata = ini.GetGroup("metadata");
assert(metadata != nullptr); /* ret can't be true if metadata isn't present. */
@ -474,8 +470,8 @@ MD5File::ChecksumResult MD5File::CheckMD5(Subdirectory subdir, size_t max_size)
static const char * const _graphics_file_names[] = { "base", "logos", "arctic", "tropical", "toyland", "extra" };
/** Implementation */
template <class T, size_t Tnum_files, bool Tsearch_in_tars>
/* static */ const char * const *BaseSet<T, Tnum_files, Tsearch_in_tars>::file_names = _graphics_file_names;
template <class T>
/* static */ const char * const *BaseSet<T>::file_names = _graphics_file_names;
template <class Tbase_set>
/* static */ bool BaseMedia<Tbase_set>::DetermineBestSet()

View File

@ -9,10 +9,6 @@
#include "stdafx.h"
#include "string_func.h"
/** The type of set we're replacing */
#define SET_TYPE "music"
#include "base_media_func.h"
#include "base_media_music.h"
#include "random_access_file_type.h"
@ -82,8 +78,8 @@ static const char * const _music_file_names[] = {
/** Make sure we aren't messing things up. */
static_assert(lengthof(_music_file_names) == NUM_SONGS_AVAILABLE);
template <class T, size_t Tnum_files, bool Tsearch_in_tars>
/* static */ const char * const *BaseSet<T, Tnum_files, Tsearch_in_tars>::file_names = _music_file_names;
template <class T>
/* static */ const char * const *BaseSet<T>::file_names = _music_file_names;
template <class Tbase_set>
/* static */ const char *BaseMedia<Tbase_set>::GetExtension()
@ -115,7 +111,7 @@ template <class Tbase_set>
bool MusicSet::FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename)
{
bool ret = this->BaseSet<MusicSet, NUM_SONGS_AVAILABLE, false>::FillSetDetails(ini, path, full_filename);
bool ret = this->BaseSet<MusicSet>::FillSetDetails(ini, path, full_filename);
if (ret) {
this->num_available = 0;
const IniGroup *names = ini.GetGroup("names");

View File

@ -17,9 +17,6 @@
#include "window_func.h"
#include "window_gui.h"
#include "vehicle_base.h"
/* The type of set we're replacing */
#define SET_TYPE "sounds"
#include "base_media_func.h"
#include "base_media_sounds.h"
@ -256,8 +253,8 @@ INSTANTIATE_BASE_MEDIA_METHODS(BaseMedia<SoundsSet>, SoundsSet)
static const char * const _sound_file_names[] = { "samples" };
template <class T, size_t Tnum_files, bool Tsearch_in_tars>
/* static */ const char * const *BaseSet<T, Tnum_files, Tsearch_in_tars>::file_names = _sound_file_names;
template <class T>
/* static */ const char * const *BaseSet<T>::file_names = _sound_file_names;
template <class Tbase_set>
/* static */ const char *BaseMedia<Tbase_set>::GetExtension()