diff --git a/src/blitter/factory.hpp b/src/blitter/factory.hpp index 0dceea90f2..1aa27c19f3 100644 --- a/src/blitter/factory.hpp +++ b/src/blitter/factory.hpp @@ -55,7 +55,7 @@ protected: * @pre description != nullptr. * @pre There is no blitter registered with this name. */ - BlitterFactory(const char *name, const char *description, bool usable = true) : + BlitterFactory(std::string_view name, std::string_view description, bool usable = true) : name(name), description(description) { if (usable) { diff --git a/src/command.cpp b/src/command.cpp index 281588e89a..c11289902e 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -74,7 +74,7 @@ int RecursiveCommandCounter::_counter = 0; * the #CommandFlag::Auto, #CommandFlag::Offline and #CommandFlag::Server values. */ struct CommandInfo { - const char *name; ///< A human readable name for the procedure + std::string_view name; ///< A human readable name for the procedure CommandFlags flags; ///< The (command) flags to that apply to this command CommandType type; ///< The type of command. }; @@ -129,7 +129,7 @@ CommandFlags GetCommandFlags(Commands cmd) * @param cmd The integer value of the command * @return The name for this command */ -const char *GetCommandName(Commands cmd) +std::string_view GetCommandName(Commands cmd) { assert(IsValidCommand(cmd)); diff --git a/src/command_func.h b/src/command_func.h index 52c70f6aab..cb3ba95610 100644 --- a/src/command_func.h +++ b/src/command_func.h @@ -31,7 +31,7 @@ void NetworkSendCommand(Commands cmd, StringID err_message, CommandCallback *cal bool IsValidCommand(Commands cmd); CommandFlags GetCommandFlags(Commands cmd); -const char *GetCommandName(Commands cmd); +std::string_view GetCommandName(Commands cmd); bool IsCommandAllowedWhilePaused(Commands cmd); template diff --git a/src/command_type.h b/src/command_type.h index 12a81a685b..e491677871 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -470,7 +470,7 @@ template struct CommandTraits; static constexpr auto &proc = proc_; \ static constexpr CommandFlags flags = flags_; \ static constexpr CommandType type = type_; \ - static inline constexpr const char *name = #proc_; \ + static inline constexpr std::string_view name = #proc_; \ }; /** Storage buffer for serialized command data. */ diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 655430dabd..8944255f4b 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -2237,9 +2237,9 @@ struct ConsoleContentCallback : public ContentCallback { */ static void OutputContentState(const ContentInfo &ci) { - static const char * const types[] = { "Base graphics", "NewGRF", "AI", "AI library", "Scenario", "Heightmap", "Base sound", "Base music", "Game script", "GS library" }; + static const std::string_view types[] = { "Base graphics", "NewGRF", "AI", "AI library", "Scenario", "Heightmap", "Base sound", "Base music", "Game script", "GS library" }; static_assert(lengthof(types) == CONTENT_TYPE_END - CONTENT_TYPE_BEGIN); - static const char * const states[] = { "Not selected", "Selected", "Dep Selected", "Installed", "Unknown" }; + static const std::string_view states[] = { "Not selected", "Selected", "Dep Selected", "Installed", "Unknown" }; static const TextColour state_to_colour[] = { CC_COMMAND, CC_INFO, CC_INFO, CC_WHITE, CC_ERROR }; IConsolePrint(state_to_colour[ci.state], "{}, {}, {}, {}, {:08X}, {}", ci.id, types[ci.type - 1], states[ci.state], ci.name, ci.unique_id, FormatArrayAsHex(ci.md5sum)); @@ -2475,7 +2475,7 @@ static bool ConListDirs(std::span argv) { struct SubdirNameMap { Subdirectory subdir; ///< Index of subdirectory type - const char *name; ///< UI name for the directory + std::string_view name; ///< UI name for the directory bool default_only; ///< Whether only the default (first existing) directory for this is interesting }; static const SubdirNameMap subdir_name_map[] = { @@ -2498,10 +2498,13 @@ static bool ConListDirs(std::span argv) if (argv.size() != 2) { IConsolePrint(CC_HELP, "List all search paths or default directories for various categories."); IConsolePrint(CC_HELP, "Usage: list_dirs "); - std::string cats = subdir_name_map[0].name; + std::string cats{subdir_name_map[0].name}; bool first = true; for (const SubdirNameMap &sdn : subdir_name_map) { - if (!first) cats = cats + ", " + sdn.name; + if (!first) { + cats += ", "; + cats += sdn.name; + } first = false; } IConsolePrint(CC_HELP, "Valid categories: {}", cats); @@ -2567,7 +2570,7 @@ static bool ConNewGRFProfile(std::span argv) bool selected = profiler != _newgrf_profilers.end(); bool active = selected && profiler->active; TextColour tc = active ? TC_LIGHT_BLUE : selected ? TC_GREEN : CC_INFO; - const char *statustext = active ? " (active)" : selected ? " (selected)" : ""; + std::string_view statustext = active ? " (active)" : selected ? " (selected)" : ""; IConsolePrint(tc, "{}: [{:08X}] {}{}", i, std::byteswap(grf.grfid), grf.filename, statustext); i++; } diff --git a/src/core/pool_type.hpp b/src/core/pool_type.hpp index a1d3f4ae41..bf16959bef 100644 --- a/src/core/pool_type.hpp +++ b/src/core/pool_type.hpp @@ -137,7 +137,7 @@ public: using BitmapStorage = size_t; static constexpr size_t BITMAP_SIZE = std::numeric_limits::digits; - const char * const name = nullptr; ///< Name of this pool + const std::string_view name{}; ///< Name of this pool size_t first_free = 0; ///< No item with index lower than this is free (doesn't say anything about this one!) size_t first_unused = 0; ///< This and all higher indexes are free (doesn't say anything about first_unused-1 !) @@ -150,7 +150,7 @@ public: std::vector data{}; ///< Pointers to Titem std::vector used_bitmap{}; ///< Bitmap of used indices. - Pool(const char *name) : PoolBase(Tpool_type), name(name) {} + Pool(std::string_view name) : PoolBase(Tpool_type), name(name) {} void CleanPool() override; /** diff --git a/src/crashlog.cpp b/src/crashlog.cpp index 85c0932803..815c31e32e 100644 --- a/src/crashlog.cpp +++ b/src/crashlog.cpp @@ -73,7 +73,7 @@ static void SurveyRecentNews(nlohmann::json &json) * @param with_dir Whether to prepend the filename with the personal directory. * @return The filename */ -std::string CrashLog::CreateFileName(const char *ext, bool with_dir) const +std::string CrashLog::CreateFileName(std::string_view ext, bool with_dir) const { static std::string crashname; diff --git a/src/crashlog.h b/src/crashlog.h index 836bef5082..4dbc2ebce0 100644 --- a/src/crashlog.h +++ b/src/crashlog.h @@ -46,7 +46,7 @@ private: virtual bool TryExecute(std::string_view section_name, std::function &&func) = 0; protected: - std::string CreateFileName(const char *ext, bool with_dir = true) const; + std::string CreateFileName(std::string_view ext, bool with_dir = true) const; public: /** Stub destructor to silence some compilers. */ diff --git a/src/currency.h b/src/currency.h index 5484b19ec1..74dec0dbf2 100644 --- a/src/currency.h +++ b/src/currency.h @@ -94,7 +94,7 @@ struct CurrencySpec { CurrencySpec() = default; - CurrencySpec(uint16_t rate, const char *separator, TimerGameCalendar::Year to_euro, const char *prefix, const char *suffix, const char *code, uint8_t symbol_pos, StringID name) : + CurrencySpec(uint16_t rate, std::string_view separator, TimerGameCalendar::Year to_euro, std::string_view prefix, std::string_view suffix, std::string_view code, uint8_t symbol_pos, StringID name) : rate(rate), separator(separator), to_euro(to_euro), prefix(prefix), suffix(suffix), code(code), symbol_pos(symbol_pos), name(name) { } diff --git a/src/debug.cpp b/src/debug.cpp index 3ff81ff9c3..5a586d72e0 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -28,7 +28,7 @@ /** Element in the queue of debug messages that have to be passed to either NetworkAdminConsole or IConsolePrint.*/ struct QueuedDebugItem { - std::string level; ///< The used debug level. + std::string_view level; ///< The used debug level. std::string message; ///< The actual formatted message. }; std::atomic _debug_remote_console; ///< Whether we need to send data to either NetworkAdminConsole or IConsolePrint. @@ -107,16 +107,16 @@ void DumpDebugFacilityNames(std::back_insert_iterator &output_itera * @param level Debug category. * @param message The message to output. */ -void DebugPrint(const char *category, int level, std::string &&message) +void DebugPrint(std::string_view category, int level, std::string &&message) { - if (strcmp(category, "desync") == 0 && level != 0) { + if (category == "desync" && level != 0) { static auto f = FioFOpenFile("commands-out.log", "wb", AUTOSAVE_DIR); if (!f.has_value()) return; fmt::print(*f, "{}{}\n", GetLogPrefix(true), message); fflush(*f); #ifdef RANDOM_DEBUG - } else if (strcmp(category, "random") == 0) { + } else if (category == "random") { static auto f = FioFOpenFile("random-out.log", "wb", AUTOSAVE_DIR); if (!f.has_value()) return; diff --git a/src/debug.h b/src/debug.h index 081b11931a..ce02e16ff0 100644 --- a/src/debug.h +++ b/src/debug.h @@ -35,7 +35,7 @@ * @param format_string The formatting string of the message. */ #define Debug(category, level, format_string, ...) do { if ((level) == 0 || _debug_ ## category ## _level >= (level)) DebugPrint(#category, level, fmt::format(FMT_STRING(format_string) __VA_OPT__(,) __VA_ARGS__)); } while (false) -void DebugPrint(const char *category, int level, std::string &&message); +void DebugPrint(std::string_view category, int level, std::string &&message); extern int _debug_driver_level; extern int _debug_grf_level; diff --git a/src/gfx_type.h b/src/gfx_type.h index b507b26183..e14e285a53 100644 --- a/src/gfx_type.h +++ b/src/gfx_type.h @@ -252,9 +252,9 @@ enum FontSize : uint8_t { }; DECLARE_INCREMENT_DECREMENT_OPERATORS(FontSize) -inline const char *FontSizeToName(FontSize fs) +inline std::string_view FontSizeToName(FontSize fs) { - static const char *SIZE_TO_NAME[] = { "medium", "small", "large", "mono" }; + static const std::string_view SIZE_TO_NAME[] = { "medium", "small", "large", "mono" }; assert(fs < FS_END); return SIZE_TO_NAME[fs]; } diff --git a/src/heightmap.cpp b/src/heightmap.cpp index 7520745cc0..462d8d15ea 100644 --- a/src/heightmap.cpp +++ b/src/heightmap.cpp @@ -135,7 +135,7 @@ static void ReadHeightmapPNGImageData(std::span map, png_structp png_pt * If map == nullptr only the size of the PNG is read, otherwise a map * with grayscale pixels is allocated and assigned to *map. */ -static bool ReadHeightmapPNG(const char *filename, uint *x, uint *y, std::vector *map) +static bool ReadHeightmapPNG(std::string_view filename, uint *x, uint *y, std::vector *map) { png_structp png_ptr = nullptr; png_infop info_ptr = nullptr; @@ -256,7 +256,7 @@ static void ReadHeightmapBMPImageData(std::span map, const BmpInfo &inf * If map == nullptr only the size of the BMP is read, otherwise a map * with grayscale pixels is allocated and assigned to *map. */ -static bool ReadHeightmapBMP(const char *filename, uint *x, uint *y, std::vector *map) +static bool ReadHeightmapBMP(std::string_view filename, uint *x, uint *y, std::vector *map) { auto f = FioFOpenFile(filename, "rb", HEIGHTMAP_DIR); if (!f.has_value()) { @@ -475,7 +475,7 @@ void FixSlopes() * @param[in,out] map If not \c nullptr, destination to store the loaded block of image data. * @return Whether loading was successful. */ -static bool ReadHeightMap(DetailedFileType dft, const char *filename, uint *x, uint *y, std::vector *map) +static bool ReadHeightMap(DetailedFileType dft, std::string_view filename, uint *x, uint *y, std::vector *map) { switch (dft) { default: @@ -499,7 +499,7 @@ static bool ReadHeightMap(DetailedFileType dft, const char *filename, uint *x, u * @param y dimension y * @return Returns false if loading of the image failed. */ -bool GetHeightmapDimensions(DetailedFileType dft, const char *filename, uint *x, uint *y) +bool GetHeightmapDimensions(DetailedFileType dft, std::string_view filename, uint *x, uint *y) { return ReadHeightMap(dft, filename, x, y, nullptr); } @@ -511,7 +511,7 @@ bool GetHeightmapDimensions(DetailedFileType dft, const char *filename, uint *x, * @param dft Type of image file. * @param filename of the heightmap file to be imported */ -bool LoadHeightmap(DetailedFileType dft, const char *filename) +bool LoadHeightmap(DetailedFileType dft, std::string_view filename) { uint x, y; std::vector map; diff --git a/src/heightmap.h b/src/heightmap.h index 5809e1b126..013781f117 100644 --- a/src/heightmap.h +++ b/src/heightmap.h @@ -21,8 +21,8 @@ enum HeightmapRotation : uint8_t { HM_CLOCKWISE, ///< Rotate the map clockwise 45 degrees }; -bool GetHeightmapDimensions(DetailedFileType dft, const char *filename, uint *x, uint *y); -bool LoadHeightmap(DetailedFileType dft, const char *filename); +bool GetHeightmapDimensions(DetailedFileType dft, std::string_view filename, uint *x, uint *y); +bool LoadHeightmap(DetailedFileType dft, std::string_view filename); void FlatEmptyWorld(uint8_t tile_height); void FixSlopes(); diff --git a/src/misc/dbg_helpers.cpp b/src/misc/dbg_helpers.cpp index 647510ebd7..63b348e73c 100644 --- a/src/misc/dbg_helpers.cpp +++ b/src/misc/dbg_helpers.cpp @@ -9,12 +9,13 @@ #include "../stdafx.h" #include "../rail_map.h" +#include "../core/enum_type.hpp" #include "dbg_helpers.h" #include "../safeguards.h" /** Trackdir & TrackdirBits short names. */ -static const char * const trackdir_names[] = { +static const std::string_view trackdir_names[] = { "NE", "SE", "UE", "LE", "LS", "RS", "rne", "rse", "SW", "NW", "UW", "LW", "LN", "RN", "rsw", "rnw", }; @@ -22,37 +23,37 @@ static const char * const trackdir_names[] = { /** Return name of given Trackdir. */ std::string ValueStr(Trackdir td) { - return std::to_string(td) + " (" + ItemAtT(td, trackdir_names, "UNK", INVALID_TRACKDIR, "INV") + ")"; + return fmt::format("{} ({})", to_underlying(td), ItemAtT(td, trackdir_names, "UNK", INVALID_TRACKDIR, "INV")); } /** Return composed name of given TrackdirBits. */ std::string ValueStr(TrackdirBits td_bits) { - return std::to_string(td_bits) + " (" + ComposeNameT(td_bits, trackdir_names, "UNK", INVALID_TRACKDIR_BIT, "INV") + ")"; + return fmt::format("{} ({})", to_underlying(td_bits), ComposeNameT(td_bits, trackdir_names, "UNK", INVALID_TRACKDIR_BIT, "INV")); } /** DiagDirection short names. */ -static const char * const diagdir_names[] = { +static const std::string_view diagdir_names[] = { "NE", "SE", "SW", "NW", }; /** Return name of given DiagDirection. */ std::string ValueStr(DiagDirection dd) { - return std::to_string(dd) + " (" + ItemAtT(dd, diagdir_names, "UNK", INVALID_DIAGDIR, "INV") + ")"; + return fmt::format("{} ({})", to_underlying(dd), ItemAtT(dd, diagdir_names, "UNK", INVALID_DIAGDIR, "INV")); } /** SignalType short names. */ -static const char * const signal_type_names[] = { +static const std::string_view signal_type_names[] = { "NORMAL", "ENTRY", "EXIT", "COMBO", "PBS", "NOENTRY", }; /** Return name of given SignalType. */ std::string ValueStr(SignalType t) { - return std::to_string(t) + " (" + ItemAtT(t, signal_type_names, "UNK") + ")"; + return fmt::format("{} ({})", to_underlying(t), ItemAtT(t, signal_type_names, "UNK")); } diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index 63f3f9fd7a..9e8153764c 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -574,12 +574,12 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdNames() auto p = std::make_unique(this, ADMIN_PACKET_SERVER_CMD_NAMES); for (uint16_t i = 0; i < CMD_END; i++) { - const char *cmdname = GetCommandName(static_cast(i)); + std::string_view cmdname = GetCommandName(static_cast(i)); /* Should COMPAT_MTU be exceeded, start a new packet * (magic 5: 1 bool "more data" and one uint16_t "command id", one * byte for string '\0' termination and 1 bool "no more data" */ - if (!p->CanWriteToPacket(strlen(cmdname) + 5)) { + if (!p->CanWriteToPacket(cmdname.size() + 5)) { p->Send_bool(false); this->SendPacket(std::move(p)); diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 34febb2d90..099f23a56d 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -323,7 +323,7 @@ CargoTypes TranslateRefitMask(uint32_t refit_mask) * @param error_location Function name for grf error messages * @param[out] index If \a base_pointer is valid, \a index is assigned to the matching price; else it is left unchanged */ -void ConvertTTDBasePrice(uint32_t base_pointer, const char *error_location, Price *index) +void ConvertTTDBasePrice(uint32_t base_pointer, std::string_view error_location, Price *index) { /* Special value for 'none' */ if (base_pointer == 0) { diff --git a/src/newgrf/newgrf_act0.cpp b/src/newgrf/newgrf_act0.cpp index 496b64b524..f0a0e6b055 100644 --- a/src/newgrf/newgrf_act0.cpp +++ b/src/newgrf/newgrf_act0.cpp @@ -109,7 +109,7 @@ std::vector ReadBadgeList(ByteReader &buf, GrfSpecFeature feature) return badges; } -bool HandleChangeInfoResult(const char *caller, ChangeInfoResult cir, uint8_t feature, uint8_t property) +bool HandleChangeInfoResult(std::string_view caller, ChangeInfoResult cir, uint8_t feature, uint8_t property) { switch (cir) { default: NOT_REACHED(); diff --git a/src/newgrf/newgrf_act0_globalvar.cpp b/src/newgrf/newgrf_act0_globalvar.cpp index 837f68da3d..625c8f3015 100644 --- a/src/newgrf/newgrf_act0_globalvar.cpp +++ b/src/newgrf/newgrf_act0_globalvar.cpp @@ -67,7 +67,7 @@ static ChangeInfoResult LoadTranslationTable(uint first, uint last, ByteReader & return CIR_SUCCESS; } -static ChangeInfoResult LoadBadgeTranslationTable(uint first, uint last, ByteReader &buf, std::vector &translation_table, const char *name) +static ChangeInfoResult LoadBadgeTranslationTable(uint first, uint last, ByteReader &buf, std::vector &translation_table, std::string_view name) { if (first != 0 && first != std::size(translation_table)) { GrfMsg(1, "LoadBadgeTranslationTable: {} translation table must start at zero or {}", name, std::size(translation_table)); diff --git a/src/newgrf/newgrf_act3.cpp b/src/newgrf/newgrf_act3.cpp index faaa5660e0..2a405ac838 100644 --- a/src/newgrf/newgrf_act3.cpp +++ b/src/newgrf/newgrf_act3.cpp @@ -65,7 +65,7 @@ static CargoType TranslateCargo(uint8_t feature, uint8_t ctype) } -static bool IsValidGroupID(uint16_t groupid, const char *function) +static bool IsValidGroupID(uint16_t groupid, std::string_view function) { if (groupid > MAX_SPRITEGROUP || _cur_gps.spritegroups[groupid] == nullptr) { GrfMsg(1, "{}: Spritegroup 0x{:04X} out of range or empty, skipping.", function, groupid); diff --git a/src/newgrf/newgrf_actd.cpp b/src/newgrf/newgrf_actd.cpp index 8425f82eb9..a5d3cd570d 100644 --- a/src/newgrf/newgrf_actd.cpp +++ b/src/newgrf/newgrf_actd.cpp @@ -132,7 +132,7 @@ static uint32_t GetPatchVariable(uint8_t param) } } -static uint32_t PerformGRM(std::span grm, uint16_t count, uint8_t op, uint8_t target, const char *type) +static uint32_t PerformGRM(std::span grm, uint16_t count, uint8_t op, uint8_t target, std::string_view type) { uint start = 0; uint size = 0; diff --git a/src/newgrf/newgrf_internal.h b/src/newgrf/newgrf_internal.h index 7f179b0c36..c12b924113 100644 --- a/src/newgrf/newgrf_internal.h +++ b/src/newgrf/newgrf_internal.h @@ -198,7 +198,7 @@ bool ReadSpriteLayout(ByteReader &buf, uint num_building_sprites, bool use_cur_s GRFFile *GetFileByGRFID(uint32_t grfid); GRFError *DisableGrf(StringID message = {}, GRFConfig *config = nullptr); void DisableStaticNewGRFInfluencingNonStaticNewGRFs(GRFConfig &c); -bool HandleChangeInfoResult(const char *caller, ChangeInfoResult cir, uint8_t feature, uint8_t property); +bool HandleChangeInfoResult(std::string_view caller, ChangeInfoResult cir, uint8_t feature, uint8_t property); uint32_t GetParamVal(uint8_t param, uint32_t *cond_val); void GRFUnsafe(ByteReader &); diff --git a/src/newgrf/newgrf_internal_vehicle.h b/src/newgrf/newgrf_internal_vehicle.h index 2e1abf3b70..31b2eac9ea 100644 --- a/src/newgrf/newgrf_internal_vehicle.h +++ b/src/newgrf/newgrf_internal_vehicle.h @@ -52,7 +52,7 @@ struct GRFTempEngineData { extern ReferenceThroughBaseContainer> _gted; ///< Temporary engine data used during NewGRF loading Engine *GetNewEngine(const GRFFile *file, VehicleType type, uint16_t internal_id, bool static_access = false); -void ConvertTTDBasePrice(uint32_t base_pointer, const char *error_location, Price *index); +void ConvertTTDBasePrice(uint32_t base_pointer, std::string_view error_location, Price *index); /** * Helper to check whether an image index is valid for a particular NewGRF vehicle. diff --git a/src/random_access_file.cpp b/src/random_access_file.cpp index 397f729bd8..f305832053 100644 --- a/src/random_access_file.cpp +++ b/src/random_access_file.cpp @@ -22,7 +22,7 @@ * @param filename Name of the file at the disk. * @param subdir The sub directory to search this file in. */ -RandomAccessFile::RandomAccessFile(const std::string &filename, Subdirectory subdir) : filename(filename) +RandomAccessFile::RandomAccessFile(std::string_view filename, Subdirectory subdir) : filename(filename) { size_t file_size; this->file_handle = FioFOpenFile(filename, "rb", subdir, &file_size); @@ -38,7 +38,7 @@ RandomAccessFile::RandomAccessFile(const std::string &filename, Subdirectory sub /* Store the filename without path and extension */ auto t = filename.rfind(PATHSEPCHAR); - std::string name_without_path = filename.substr(t != std::string::npos ? t + 1 : 0); + std::string name_without_path{filename.substr(t != std::string::npos ? t + 1 : 0)}; this->simplified_filename = name_without_path.substr(0, name_without_path.rfind('.')); strtolower(this->simplified_filename); diff --git a/src/random_access_file_type.h b/src/random_access_file_type.h index 95a4d94ad0..8ad5f10f93 100644 --- a/src/random_access_file_type.h +++ b/src/random_access_file_type.h @@ -36,7 +36,7 @@ class RandomAccessFile { uint8_t buffer_start[BUFFER_SIZE]; ///< Local buffer when read from file. public: - RandomAccessFile(const std::string &filename, Subdirectory subdir); + RandomAccessFile(std::string_view filename, Subdirectory subdir); RandomAccessFile(const RandomAccessFile&) = delete; void operator=(const RandomAccessFile&) = delete;