diff --git a/src/fileio.cpp b/src/fileio.cpp index 4485b73473..aa1f00bcdb 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -35,7 +35,7 @@ static bool _do_scan_working_directory = true; extern std::string _config_file; extern std::string _highscore_file; -static const char * const _subdirs[] = { +static const std::string_view _subdirs[] = { "", "save" PATHSEP, "save" PATHSEP "autosave" PATHSEP, @@ -165,7 +165,7 @@ std::string FioGetDirectory(Searchpath sp, Subdirectory subdir) assert(subdir < NUM_SUBDIRS); assert(sp < NUM_SEARCHPATHS); - return _searchpaths[sp] + _subdirs[subdir]; + return fmt::format("{}{}", _searchpaths[sp], _subdirs[subdir]); } std::string FioFindDirectory(Subdirectory subdir) @@ -180,7 +180,7 @@ std::string FioFindDirectory(Subdirectory subdir) return _personal_dir; } -static std::optional FioFOpenFileSp(std::string_view filename, const char *mode, Searchpath sp, Subdirectory subdir, size_t *filesize) +static std::optional FioFOpenFileSp(std::string_view filename, std::string_view mode, Searchpath sp, Subdirectory subdir, size_t *filesize) { #if defined(_WIN32) /* fopen is implemented as a define with ellipses for @@ -188,7 +188,7 @@ static std::optional FioFOpenFileSp(std::string_view filename, const * a string, but a variable, it 'renames' the variable, * so make that variable to makes it compile happily */ wchar_t Lmode[5]; - MultiByteToWideChar(CP_ACP, 0, mode, -1, Lmode, static_cast(std::size(Lmode))); + MultiByteToWideChar(CP_ACP, 0, mode.data(), static_cast(std::size(mode)), Lmode, static_cast(std::size(Lmode))); #endif std::string buf; @@ -239,7 +239,7 @@ static std::optional FioFOpenFileTar(const TarFileListEntry &entry, * @param subdir Subdirectory to open. * @return File handle of the opened file, or \c nullptr if the file is not available. */ -std::optional FioFOpenFile(std::string_view filename, const char *mode, Subdirectory subdir, size_t *filesize) +std::optional FioFOpenFile(std::string_view filename, std::string_view mode, Subdirectory subdir, size_t *filesize) { std::optional f = std::nullopt; assert(subdir < NUM_SUBDIRS || subdir == NO_DIRECTORY); @@ -658,7 +658,7 @@ bool ExtractTar(const std::string &tar_filename, Subdirectory subdir) * @param exe the path from the current path to the executable * @note defined in the OS related files (win32.cpp, unix.cpp etc) */ -extern void DetermineBasePaths(const char *exe); +extern void DetermineBasePaths(std::string_view exe); #else /* defined(_WIN32) */ /** @@ -668,9 +668,9 @@ extern void DetermineBasePaths(const char *exe); * in the same way we remove the name from the executable name. * @param exe the path to the executable */ -static bool ChangeWorkingDirectoryToExecutable(const char *exe) +static bool ChangeWorkingDirectoryToExecutable(std::string_view exe) { - std::string path = exe; + std::string path{exe}; #ifdef WITH_COCOA for (size_t pos = path.find_first_of('.'); pos != std::string::npos; pos = path.find_first_of('.', pos + 1)) { @@ -746,7 +746,7 @@ static std::string GetHomeDir() * Determine the base (personal dir and game data dir) paths * @param exe the path to the executable */ -void DetermineBasePaths(const char *exe) +void DetermineBasePaths(std::string_view exe) { std::string tmp; const std::string homedir = GetHomeDir(); @@ -874,7 +874,7 @@ std::string _personal_dir; * @param exe the path from the current path to the executable * @param only_local_path Whether we shouldn't fill searchpaths with global folders. */ -void DeterminePaths(const char *exe, bool only_local_path) +void DeterminePaths(std::string_view exe, bool only_local_path) { DetermineBasePaths(exe); FillValidSearchPaths(only_local_path); @@ -976,7 +976,7 @@ void DeterminePaths(const char *exe, bool only_local_path) }; for (const auto &default_subdir : default_subdirs) { - FioCreateDirectory(_personal_dir + _subdirs[default_subdir]); + FioCreateDirectory(fmt::format("{}{}", _personal_dir, _subdirs[default_subdir])); } /* If we have network we make a directory for the autodownloading of content */ @@ -1170,7 +1170,7 @@ std::optional FileHandle::Open(const std::string &filename, std::str { #if defined(_WIN32) /* Windows also requires mode to be wchar_t. */ - auto f = _wfopen(OTTD2FS(filename).c_str(), OTTD2FS(mode).c_str()); + auto f = _wfopen(OTTD2FS(filename).c_str(), OTTD2FS(std::string{mode}).c_str()); #else auto f = fopen(filename.c_str(), std::string{mode}.c_str()); #endif /* _WIN32 */ diff --git a/src/fileio_func.h b/src/fileio_func.h index 34a2b2f1a2..79ab20ca56 100644 --- a/src/fileio_func.h +++ b/src/fileio_func.h @@ -13,7 +13,7 @@ #include "core/enum_type.hpp" #include "fileio_type.h" -std::optional FioFOpenFile(std::string_view filename, const char *mode, Subdirectory subdir, size_t *filesize = nullptr); +std::optional FioFOpenFile(std::string_view filename, std::string_view mode, Subdirectory subdir, size_t *filesize = nullptr); bool FioCheckFileExists(std::string_view filename, Subdirectory subdir); std::string FioFindFullPath(Subdirectory subdir, std::string_view filename); std::string FioGetDirectory(Searchpath sp, Subdirectory subdir); @@ -21,11 +21,11 @@ std::string FioFindDirectory(Subdirectory subdir); void FioCreateDirectory(const std::string &name); bool FioRemove(const std::string &filename); -const char *FiosGetScreenshotDir(); +std::string_view FiosGetScreenshotDir(); void SanitizeFilename(std::string &filename); void AppendPathSeparator(std::string &buf); -void DeterminePaths(const char *exe, bool only_local_path); +void DeterminePaths(std::string_view exe, bool only_local_path); std::unique_ptr ReadFileToMem(const std::string &filename, size_t &lenp, size_t maxsize); bool FileExists(const std::string &filename); bool ExtractTar(const std::string &tar_filename, Subdirectory subdir); diff --git a/src/fios.cpp b/src/fios.cpp index 2011e695c2..dbab825654 100644 --- a/src/fios.cpp +++ b/src/fios.cpp @@ -12,6 +12,7 @@ #include "stdafx.h" #include "3rdparty/md5/md5.h" +#include "core/string_consumer.hpp" #include "fileio_func.h" #include "fios.h" #include "network/network_content.h" @@ -108,11 +109,9 @@ const FiosItem *FileList::FindItem(const std::string_view file) } /* If no name matches, try to parse it as number */ - int i; - const char *endptr = std::from_chars(file.data(), file.data() + file.size(), i, 10).ptr; - if (file.data() == endptr || endptr != file.data() + file.size()) i = -1; - - if (IsInsideMM(i, 0, this->size())) return &this->at(i); + StringConsumer consumer{file}; + auto number = consumer.TryReadIntegerBase(10); + if (number.has_value() && !consumer.AnyBytesLeft() && IsInsideMM(*number, 0, this->size())) return &this->at(*number); /* As a last effort assume it is an OpenTTD savegame and * that the ".sav" part was not given. */ @@ -192,21 +191,21 @@ bool FiosBrowseTo(const FiosItem *item) * @param ext Filename extension (use \c "" for no extension). * @return The completed filename. */ -static std::string FiosMakeFilename(const std::string *path, const char *name, const char *ext) +static std::string FiosMakeFilename(const std::string *path, std::string_view name, std::string_view ext) { - std::string buf; + std::string_view base_path; if (path != nullptr) { - buf = *path; + base_path = *path; /* Remove trailing path separator, if present */ - if (!buf.empty() && buf.back() == PATHSEPCHAR) buf.pop_back(); + if (!base_path.empty() && base_path.back() == PATHSEPCHAR) base_path.remove_suffix(1); } /* Don't append the extension if it is already there */ - const char *period = strrchr(name, '.'); - if (period != nullptr && StrEqualsIgnoreCase(period, ext)) ext = ""; + auto period = name.find_last_of('.'); + if (period != std::string_view::npos && StrEqualsIgnoreCase(name.substr(period), ext)) ext = ""; - return buf + PATHSEP + name + ext; + return fmt::format("{}{}{}{}", base_path, PATHSEP, name, ext); } /** @@ -214,9 +213,9 @@ static std::string FiosMakeFilename(const std::string *path, const char *name, c * @param name Name of the file. * @return The completed filename. */ -std::string FiosMakeSavegameName(const char *name) +std::string FiosMakeSavegameName(std::string_view name) { - const char *extension = (_game_mode == GM_EDITOR) ? ".scn" : ".sav"; + std::string_view extension = (_game_mode == GM_EDITOR) ? ".scn" : ".sav"; return FiosMakeFilename(_fios_path, name, extension); } @@ -226,12 +225,9 @@ std::string FiosMakeSavegameName(const char *name) * @param name Filename. * @return The completed filename. */ -std::string FiosMakeHeightmapName(const char *name) +std::string FiosMakeHeightmapName(std::string_view name) { - std::string ext("."); - ext += GetCurrentScreenshotExtension(); - - return FiosMakeFilename(_fios_path, name, ext.c_str()); + return FiosMakeFilename(_fios_path, name, fmt::format(".{}", GetCurrentScreenshotExtension())); } /** @@ -239,7 +235,7 @@ std::string FiosMakeHeightmapName(const char *name) * @param name Filename to delete. * @return Whether the file deletion was successful. */ -bool FiosDelete(const char *name) +bool FiosDelete(std::string_view name) { return FioRemove(FiosMakeSavegameName(name)); } @@ -591,13 +587,13 @@ void FiosGetTownDataList(SaveLoadOperation fop, bool show_dirs, FileList &file_l * Get the directory for screenshots. * @return path to screenshots */ -const char *FiosGetScreenshotDir() +std::string_view FiosGetScreenshotDir() { static std::optional fios_screenshot_path; if (!fios_screenshot_path) fios_screenshot_path = FioFindDirectory(SCREENSHOT_DIR); - return fios_screenshot_path->c_str(); + return *fios_screenshot_path; } /** Basic data to distinguish a scenario. Used in the server list window */ diff --git a/src/fios.h b/src/fios.h index c4a72266a6..d3a388076f 100644 --- a/src/fios.h +++ b/src/fios.h @@ -112,9 +112,9 @@ bool FiosBrowseTo(const FiosItem *item); std::string FiosGetCurrentPath(); std::optional FiosGetDiskFreeSpace(const std::string &path); -bool FiosDelete(const char *name); -std::string FiosMakeHeightmapName(const char *name); -std::string FiosMakeSavegameName(const char *name); +bool FiosDelete(std::string_view name); +std::string FiosMakeHeightmapName(std::string_view name); +std::string FiosMakeSavegameName(std::string_view name); std::tuple FiosGetSavegameListCallback(SaveLoadOperation fop, const std::string &file, const std::string_view ext); std::tuple FiosGetScenarioListCallback(SaveLoadOperation fop, const std::string &file, const std::string_view ext); diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp index fd04cd57f7..36761d7b0e 100644 --- a/src/os/windows/win32.cpp +++ b/src/os/windows/win32.cpp @@ -231,7 +231,7 @@ char *getcwd(char *buf, size_t size) extern std::string _config_file; -void DetermineBasePaths(const char *exe) +void DetermineBasePaths(std::string_view exe) { extern std::array _searchpaths; diff --git a/src/screenshot.cpp b/src/screenshot.cpp index 12c4862859..81ab57c06a 100644 --- a/src/screenshot.cpp +++ b/src/screenshot.cpp @@ -132,7 +132,7 @@ static void LargeWorldCallback(Viewport &vp, void *buf, uint y, uint pitch, uint * @param crashlog Create path for crash.png * @return Pathname for a screenshot file. */ -static const char *MakeScreenshotName(std::string_view default_fn, std::string_view ext, bool crashlog = false) +static std::string_view MakeScreenshotName(std::string_view default_fn, std::string_view ext, bool crashlog = false) { bool generate = _screenshot_name.empty(); @@ -154,7 +154,7 @@ static const char *MakeScreenshotName(std::string_view default_fn, std::string_v /* Add extension to screenshot file */ _screenshot_name += fmt::format(".{}", ext); - const char *screenshot_dir = crashlog ? _personal_dir.c_str() : FiosGetScreenshotDir(); + std::string_view screenshot_dir = crashlog ? _personal_dir : FiosGetScreenshotDir(); for (uint serial = 1;; serial++) { _full_screenshot_path = fmt::format("{}{}", screenshot_dir, _screenshot_name); @@ -166,7 +166,7 @@ static const char *MakeScreenshotName(std::string_view default_fn, std::string_v _screenshot_name += fmt::format("#{}.{}", serial, ext); } - return _full_screenshot_path.c_str(); + return _full_screenshot_path; } /** Make a screenshot of the current screen. */ @@ -311,7 +311,7 @@ static void HeightmapCallback(void *buffer, uint y, uint, uint n) * Make a heightmap of the current map. * @param filename Filename to use for saving. */ -bool MakeHeightmapScreenshot(const char *filename) +bool MakeHeightmapScreenshot(std::string_view filename) { auto provider = GetScreenshotProvider(); if (provider == nullptr) return false; diff --git a/src/screenshot.h b/src/screenshot.h index 4c9669cb34..2cbd827b1a 100644 --- a/src/screenshot.h +++ b/src/screenshot.h @@ -23,7 +23,7 @@ enum ScreenshotType : uint8_t { SC_MINIMAP, ///< Minimap screenshot. }; -bool MakeHeightmapScreenshot(const char *filename); +bool MakeHeightmapScreenshot(std::string_view filename); void MakeScreenshotWithConfirm(ScreenshotType t); bool MakeScreenshot(ScreenshotType t, const std::string &name, uint32_t width = 0, uint32_t height = 0); bool MakeMinimapWorldScreenshot(); diff --git a/src/screenshot_bmp.cpp b/src/screenshot_bmp.cpp index 37d23c9439..4d71d71253 100644 --- a/src/screenshot_bmp.cpp +++ b/src/screenshot_bmp.cpp @@ -43,7 +43,7 @@ class ScreenshotProvider_Bmp : public ScreenshotProvider { public: ScreenshotProvider_Bmp() : ScreenshotProvider("bmp", "BMP", 10) {} - bool MakeImage(const char *name, const ScreenshotCallback &callb, uint w, uint h, int pixelformat, const Colour *palette) override + bool MakeImage(std::string_view name, const ScreenshotCallback &callb, uint w, uint h, int pixelformat, const Colour *palette) override { uint bpp; // bytes per pixel switch (pixelformat) { diff --git a/src/screenshot_pcx.cpp b/src/screenshot_pcx.cpp index 6359b25751..8c9f1dd006 100644 --- a/src/screenshot_pcx.cpp +++ b/src/screenshot_pcx.cpp @@ -41,7 +41,7 @@ class ScreenshotProvider_Pcx : public ScreenshotProvider { public: ScreenshotProvider_Pcx() : ScreenshotProvider("pcx", "PCX", 20) {} - bool MakeImage(const char *name, const ScreenshotCallback &callb, uint w, uint h, int pixelformat, const Colour *palette) override + bool MakeImage(std::string_view name, const ScreenshotCallback &callb, uint w, uint h, int pixelformat, const Colour *palette) override { uint maxlines; uint y; diff --git a/src/screenshot_png.cpp b/src/screenshot_png.cpp index ee2220c4be..c3da01499e 100644 --- a/src/screenshot_png.cpp +++ b/src/screenshot_png.cpp @@ -30,7 +30,7 @@ class ScreenshotProvider_Png : public ScreenshotProvider { public: ScreenshotProvider_Png() : ScreenshotProvider("png", "PNG", 0) {} - bool MakeImage(const char *name, const ScreenshotCallback &callb, uint w, uint h, int pixelformat, const Colour *palette) override + bool MakeImage(std::string_view name, const ScreenshotCallback &callb, uint w, uint h, int pixelformat, const Colour *palette) override { png_color rq[256]; uint i, y, n; @@ -46,7 +46,7 @@ public: if (!of.has_value()) return false; auto &f = *of; - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, const_cast(name), png_my_error, png_my_warning); + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, &name, png_my_error, png_my_warning); if (png_ptr == nullptr) { return false; @@ -169,13 +169,13 @@ public: private: static void PNGAPI png_my_error(png_structp png_ptr, png_const_charp message) { - Debug(misc, 0, "[libpng] error: {} - {}", message, (const char *)png_get_error_ptr(png_ptr)); + Debug(misc, 0, "[libpng] error: {} - {}", message, *static_cast(png_get_error_ptr(png_ptr))); longjmp(png_jmpbuf(png_ptr), 1); } static void PNGAPI png_my_warning(png_structp png_ptr, png_const_charp message) { - Debug(misc, 1, "[libpng] warning: {} - {}", message, (const char *)png_get_error_ptr(png_ptr)); + Debug(misc, 1, "[libpng] warning: {} - {}", message, *static_cast(png_get_error_ptr(png_ptr))); } }; diff --git a/src/screenshot_type.h b/src/screenshot_type.h index 0be00c7d96..d93f7c20bb 100644 --- a/src/screenshot_type.h +++ b/src/screenshot_type.h @@ -36,7 +36,7 @@ public: ProviderManager::Unregister(*this); } - virtual bool MakeImage(const char *name, const ScreenshotCallback &callb, uint w, uint h, int pixelformat, const Colour *palette) = 0; + virtual bool MakeImage(std::string_view name, const ScreenshotCallback &callb, uint w, uint h, int pixelformat, const Colour *palette) = 0; }; #endif /* SCREENSHOT_TYPE_H */