# HG changeset patch # User Michael Lutz # Date 2020-12-06 20:11:47 # Node ID 74cfd45960ed5d3aa9ce31a49820ab3bb1513110 # Parent 3150e1a8a4b33b0d59b30f78c34672a0839b6062 Codechange: Even more std::string usage in file IO. diff --git a/src/fileio.cpp b/src/fileio.cpp --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -272,7 +272,7 @@ bool IsValidSearchPath(Searchpath sp) */ bool FioCheckFileExists(const std::string &filename, Subdirectory subdir) { - FILE *f = FioFOpenFile(filename.c_str(), "rb", subdir); + FILE *f = FioFOpenFile(filename, "rb", subdir); if (f == nullptr) return false; FioFCloseFile(f); @@ -345,7 +345,7 @@ std::string FioFindDirectory(Subdirector return _personal_dir; } -static FILE *FioFOpenFileSp(const char *filename, const char *mode, Searchpath sp, Subdirectory subdir, size_t *filesize) +static FILE *FioFOpenFileSp(const std::string &filename, const char *mode, Searchpath sp, Subdirectory subdir, size_t *filesize) { #if defined(_WIN32) && defined(UNICODE) /* fopen is implemented as a define with ellipses for @@ -390,17 +390,17 @@ static FILE *FioFOpenFileSp(const char * * @return File handle of the opened file, or \c nullptr if the file is not available. * @note The file is read from within the tar file, and may not return \c EOF after reading the whole file. */ -FILE *FioFOpenFileTar(TarFileListEntry *entry, size_t *filesize) +FILE *FioFOpenFileTar(const TarFileListEntry &entry, size_t *filesize) { - FILE *f = fopen(entry->tar_filename, "rb"); + FILE *f = fopen(entry.tar_filename, "rb"); if (f == nullptr) return f; - if (fseek(f, entry->position, SEEK_SET) < 0) { + if (fseek(f, entry.position, SEEK_SET) < 0) { fclose(f); return nullptr; } - if (filesize != nullptr) *filesize = entry->size; + if (filesize != nullptr) *filesize = entry.size; return f; } @@ -410,7 +410,7 @@ FILE *FioFOpenFileTar(TarFileListEntry * * @param subdir Subdirectory to open. * @return File handle of the opened file, or \c nullptr if the file is not available. */ -FILE *FioFOpenFile(const char *filename, const char *mode, Subdirectory subdir, size_t *filesize) +FILE *FioFOpenFile(const std::string &filename, const char *mode, Subdirectory subdir, size_t *filesize) { FILE *f = nullptr; Searchpath sp; @@ -424,11 +424,8 @@ FILE *FioFOpenFile(const char *filename, /* We can only use .tar in case of data-dir, and read-mode */ if (f == nullptr && mode[0] == 'r' && subdir != NO_DIRECTORY) { - static const uint MAX_RESOLVED_LENGTH = 2 * (100 + 100 + 155) + 1; // Enough space to hold two filenames plus link. See 'TarHeader'. - char resolved_name[MAX_RESOLVED_LENGTH]; - /* Filenames in tars are always forced to be lowercase */ - strecpy(resolved_name, filename, lastof(resolved_name)); + std::string resolved_name = filename; strtolower(resolved_name); /* Resolve ".." */ @@ -443,36 +440,31 @@ FILE *FioFOpenFile(const char *filename, tokens.push_back(token); } } - resolved_name[0] = '\0'; + + resolved_name.clear(); bool first = true; for (const std::string &token : tokens) { if (!first) { - strecat(resolved_name, PATHSEP, lastof(resolved_name)); + resolved_name += PATHSEP; } - strecat(resolved_name, token.c_str(), lastof(resolved_name)); + resolved_name += token; first = false; } - size_t resolved_len = strlen(resolved_name); - /* Resolve ONE directory link */ for (TarLinkList::iterator link = _tar_linklist[subdir].begin(); link != _tar_linklist[subdir].end(); link++) { const std::string &src = link->first; size_t len = src.length(); - if (resolved_len >= len && resolved_name[len - 1] == PATHSEPCHAR && strncmp(src.c_str(), resolved_name, len) == 0) { + if (resolved_name.length() >= len && resolved_name[len - 1] == PATHSEPCHAR && src.compare(0, len, resolved_name, 0, len) == 0) { /* Apply link */ - char resolved_name2[MAX_RESOLVED_LENGTH]; - const std::string &dest = link->second; - strecpy(resolved_name2, &(resolved_name[len]), lastof(resolved_name2)); - strecpy(resolved_name, dest.c_str(), lastof(resolved_name)); - strecpy(&(resolved_name[dest.length()]), resolved_name2, lastof(resolved_name)); + resolved_name.replace(0, len, link->second); break; // Only resolve one level } } TarFileList::iterator it = _tar_filelist[subdir].find(resolved_name); if (it != _tar_filelist[subdir].end()) { - f = FioFOpenFileTar(&((*it).second), filesize); + f = FioFOpenFileTar(it->second, filesize); } } @@ -859,7 +851,7 @@ bool TarScanner::AddFile(const char *fil * @param subdir The sub directory the tar is in. * @return false on failure. */ -bool ExtractTar(const char *tar_filename, Subdirectory subdir) +bool ExtractTar(const std::string &tar_filename, Subdirectory subdir) { TarList::iterator it = _tar_list[subdir].find(tar_filename); /* We don't know the file. */ @@ -869,41 +861,38 @@ bool ExtractTar(const char *tar_filename /* The file doesn't have a sub directory! */ if (dirname == nullptr) { - DEBUG(misc, 1, "Extracting %s failed; archive rejected, the contents must be in a sub directory", tar_filename); + DEBUG(misc, 1, "Extracting %s failed; archive rejected, the contents must be in a sub directory", tar_filename.c_str()); return false; } - char filename[MAX_PATH]; - strecpy(filename, tar_filename, lastof(filename)); - char *p = strrchr(filename, PATHSEPCHAR); + std::string filename = tar_filename; + auto p = filename.find_last_of(PATHSEPCHAR); /* The file's path does not have a separator? */ - if (p == nullptr) return false; + if (p == std::string::npos) return false; - p++; - strecpy(p, dirname, lastof(filename)); - DEBUG(misc, 8, "Extracting %s to directory %s", tar_filename, filename); + filename.replace(p + 1, std::string::npos, dirname); + DEBUG(misc, 8, "Extracting %s to directory %s", tar_filename.c_str(), filename.c_str()); FioCreateDirectory(filename); for (TarFileList::iterator it2 = _tar_filelist[subdir].begin(); it2 != _tar_filelist[subdir].end(); it2++) { - if (strcmp((*it2).second.tar_filename, tar_filename) != 0) continue; + if (tar_filename != it2->second.tar_filename) continue; - strecpy(p, (*it2).first.c_str(), lastof(filename)); + filename.replace(p + 1, std::string::npos, it2->first); - DEBUG(misc, 9, " extracting %s", filename); + DEBUG(misc, 9, " extracting %s", filename.c_str()); /* First open the file in the .tar. */ size_t to_copy = 0; - FILE *in = FioFOpenFileTar(&(*it2).second, &to_copy); - if (in == nullptr) { - DEBUG(misc, 6, "Extracting %s failed; could not open %s", filename, tar_filename); + std::unique_ptr in(FioFOpenFileTar(it2->second, &to_copy)); + if (!in) { + DEBUG(misc, 6, "Extracting %s failed; could not open %s", filename.c_str(), tar_filename.c_str()); return false; } /* Now open the 'output' file. */ - FILE *out = fopen(filename, "wb"); - if (out == nullptr) { - DEBUG(misc, 6, "Extracting %s failed; could not open %s", filename, filename); - fclose(in); + std::unique_ptr out(fopen(filename.c_str(), "wb")); + if (!out) { + DEBUG(misc, 6, "Extracting %s failed; could not open %s", filename.c_str(), filename.c_str()); return false; } @@ -911,16 +900,12 @@ bool ExtractTar(const char *tar_filename char buffer[4096]; size_t read; for (; to_copy != 0; to_copy -= read) { - read = fread(buffer, 1, min(to_copy, lengthof(buffer)), in); - if (read <= 0 || fwrite(buffer, 1, read, out) != read) break; + read = fread(buffer, 1, min(to_copy, lengthof(buffer)), in.get()); + if (read <= 0 || fwrite(buffer, 1, read, out.get()) != read) break; } - /* Close everything up. */ - fclose(in); - fclose(out); - if (to_copy != 0) { - DEBUG(misc, 6, "Extracting %s failed; still %i bytes to copy", filename, (int)to_copy); + DEBUG(misc, 6, "Extracting %s failed; still %i bytes to copy", filename.c_str(), (int)to_copy); return false; } } diff --git a/src/fileio_func.h b/src/fileio_func.h --- a/src/fileio_func.h +++ b/src/fileio_func.h @@ -37,7 +37,7 @@ bool IsValidSearchPath(Searchpath sp); #define FOR_ALL_SEARCHPATHS(sp) for (sp = SP_FIRST_DIR; sp < NUM_SEARCHPATHS; sp++) if (IsValidSearchPath(sp)) void FioFCloseFile(FILE *f); -FILE *FioFOpenFile(const char *filename, const char *mode, Subdirectory subdir, size_t *filesize = nullptr); +FILE *FioFOpenFile(const std::string &filename, const char *mode, Subdirectory subdir, size_t *filesize = nullptr); bool FioCheckFileExists(const std::string &filename, Subdirectory subdir); std::string FioFindFullPath(Subdirectory subdir, const char *filename); std::string FioGetDirectory(Searchpath sp, Subdirectory subdir); @@ -51,7 +51,7 @@ void AppendPathSeparator(std::string &bu void DeterminePaths(const char *exe); void *ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize); bool FileExists(const std::string &filename); -bool ExtractTar(const char *tar_filename, Subdirectory subdir); +bool ExtractTar(const std::string &tar_filename, Subdirectory subdir); extern std::string _personal_dir; ///< custom directory for personal settings, saves, newgrf, etc. diff --git a/src/game/game_text.cpp b/src/game/game_text.cpp --- a/src/game/game_text.cpp +++ b/src/game/game_text.cpp @@ -66,7 +66,7 @@ void NORETURN CDECL strgen_fatal(const c LanguageStrings ReadRawLanguageStrings(const std::string &file) { size_t to_read; - FILE *fh = FioFOpenFile(file.c_str(), "rb", GAME_DIR, &to_read); + FILE *fh = FioFOpenFile(file, "rb", GAME_DIR, &to_read); if (fh == nullptr) return LanguageStrings(); FileCloser fhClose(fh); diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -543,7 +543,7 @@ void ClientNetworkContentSocketHandler:: if (this->curInfo->type == CONTENT_TYPE_BASE_MUSIC) { /* Music can't be in a tar. So extract the tar! */ - ExtractTar(fname.c_str(), BASESET_DIR); + ExtractTar(fname, BASESET_DIR); unlink(fname.c_str()); } diff --git a/src/newgrf_profiling.cpp b/src/newgrf_profiling.cpp --- a/src/newgrf_profiling.cpp +++ b/src/newgrf_profiling.cpp @@ -102,7 +102,7 @@ uint32 NewGRFProfiler::Finish() std::string filename = this->GetOutputFilename(); IConsolePrintF(CC_DEBUG, "Finished profile of NewGRF [%08X], writing %u events to %s", BSWAP32(this->grffile->grfid), (uint)this->calls.size(), filename.c_str()); - FILE *f = FioFOpenFile(filename.c_str(), "wt", Subdirectory::NO_DIRECTORY); + FILE *f = FioFOpenFile(filename, "wt", Subdirectory::NO_DIRECTORY); FileCloser fcloser(f); uint32 total_microseconds = 0; diff --git a/src/openttd.cpp b/src/openttd.cpp --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -968,7 +968,7 @@ bool SafeLoad(const std::string &filenam _game_mode = newgm; - switch (lf == nullptr ? SaveOrLoad(filename.c_str(), fop, dft, subdir) : LoadWithFilter(lf)) { + switch (lf == nullptr ? SaveOrLoad(filename, fop, dft, subdir) : LoadWithFilter(lf)) { case SL_OK: return true; case SL_REINIT: @@ -1127,7 +1127,7 @@ void SwitchToMode(SwitchMode new_mode) case SM_SAVE_GAME: // Save game. /* Make network saved games on pause compatible to singleplayer */ - if (SaveOrLoad(_file_to_saveload.name.c_str(), SLO_SAVE, DFT_GAME_FILE, NO_DIRECTORY) != SL_OK) { + if (SaveOrLoad(_file_to_saveload.name, SLO_SAVE, DFT_GAME_FILE, NO_DIRECTORY) != SL_OK) { SetDParamStr(0, GetSaveLoadErrorString()); ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR); } else { diff --git a/src/saveload/oldloader.cpp b/src/saveload/oldloader.cpp --- a/src/saveload/oldloader.cpp +++ b/src/saveload/oldloader.cpp @@ -271,7 +271,7 @@ static SavegameType DetermineOldSavegame typedef bool LoadOldMainProc(LoadgameState *ls); -bool LoadOldSaveGame(const char *file) +bool LoadOldSaveGame(const std::string &file) { LoadgameState ls; @@ -283,7 +283,7 @@ bool LoadOldSaveGame(const char *file) ls.file = FioFOpenFile(file, "rb", NO_DIRECTORY); if (ls.file == nullptr) { - DEBUG(oldloader, 0, "Cannot open file '%s'", file); + DEBUG(oldloader, 0, "Cannot open file '%s'", file.c_str()); return false; } diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -2413,7 +2413,7 @@ static const SaveLoadFormat *GetSavegame /* actual loader/saver function */ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settings); extern bool AfterLoadGame(); -extern bool LoadOldSaveGame(const char *file); +extern bool LoadOldSaveGame(const std::string &file); /** * Clear temporary data that is passed between various saveload phases. @@ -2769,7 +2769,7 @@ SaveOrLoadResult LoadWithFilter(LoadFilt * @param threaded True when threaded saving is allowed * @return Return the result of the action. #SL_OK, #SL_ERROR, or #SL_REINIT ("unload" the game) */ -SaveOrLoadResult SaveOrLoad(const char *filename, SaveLoadOperation fop, DetailedFileType dft, Subdirectory sb, bool threaded) +SaveOrLoadResult SaveOrLoad(const std::string &filename, SaveLoadOperation fop, DetailedFileType dft, Subdirectory sb, bool threaded) { /* An instance of saving is already active, so don't go saving again */ if (_sl.saveinprogress && fop == SLO_SAVE && dft == DFT_GAME_FILE && threaded) { @@ -2833,7 +2833,7 @@ SaveOrLoadResult SaveOrLoad(const char * } if (fop == SLO_SAVE) { // SAVE game - DEBUG(desync, 1, "save: %08x; %02x; %s", _date, _date_fract, filename); + DEBUG(desync, 1, "save: %08x; %02x; %s", _date, _date_fract, filename.c_str()); if (_network_server || !_settings_client.gui.threaded_saves) threaded = false; return DoSave(new FileWriter(fh), threaded); @@ -2841,7 +2841,7 @@ SaveOrLoadResult SaveOrLoad(const char * /* LOAD game */ assert(fop == SLO_LOAD || fop == SLO_CHECK); - DEBUG(desync, 1, "load: %s", filename); + DEBUG(desync, 1, "load: %s", filename.c_str()); return DoLoad(new FileReader(fh), fop == SLO_CHECK); } catch (...) { /* This code may be executed both for old and new save games. */ diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -362,7 +362,7 @@ extern FileToSaveLoad _file_to_saveload; void GenerateDefaultSaveName(char *buf, const char *last); void SetSaveLoadError(StringID str); const char *GetSaveLoadErrorString(); -SaveOrLoadResult SaveOrLoad(const char *filename, SaveLoadOperation fop, DetailedFileType dft, Subdirectory sb, bool threaded = true); +SaveOrLoadResult SaveOrLoad(const std::string &filename, SaveLoadOperation fop, DetailedFileType dft, Subdirectory sb, bool threaded = true); void WaitTillSaved(); void ProcessAsyncSaveFinish(); void DoExitSave();