Changeset - r24526:74cfd45960ed
[Not reviewed]
master
0 9 0
Michael Lutz - 4 years ago 2020-12-06 20:11:47
michi@icosahedron.de
Codechange: Even more std::string usage in file IO.
9 files changed with 48 insertions and 63 deletions:
0 comments (0 inline, 0 general)
src/fileio.cpp
Show inline comments
 
@@ -269,13 +269,13 @@ bool IsValidSearchPath(Searchpath sp)
 
 * @param filename the file to try for existence.
 
 * @param subdir the subdirectory to look in
 
 * @return true if and only if the file can be opened
 
 */
 
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);
 
	return true;
 
}
 

	
 
@@ -342,13 +342,13 @@ std::string FioFindDirectory(Subdirector
 
	}
 

	
 
	/* Could not find the directory, fall back to a base path */
 
	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
 
	 * Unicode support (prepend an L). As we are not sending
 
	 * a string, but a variable, it 'renames' the variable,
 
	 * so make that variable to makes it compile happily */
 
@@ -387,33 +387,33 @@ static FILE *FioFOpenFileSp(const char *
 
 * Opens a file from inside a tar archive.
 
 * @param entry The entry to open.
 
 * @param[out] filesize If not \c nullptr, size of the opened file.
 
 * @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;
 
}
 

	
 
/**
 
 * Opens a OpenTTD file somewhere in a personal or global directory.
 
 * @param filename Name of the file to open.
 
 * @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;
 

	
 
	assert(subdir < NUM_SUBDIRS || subdir == NO_DIRECTORY);
 

	
 
@@ -421,17 +421,14 @@ FILE *FioFOpenFile(const char *filename,
 
		f = FioFOpenFileSp(filename, mode, sp, subdir, filesize);
 
		if (f != nullptr || subdir == NO_DIRECTORY) break;
 
	}
 

	
 
	/* 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 ".." */
 
		std::istringstream ss(resolved_name);
 
		std::vector<std::string> tokens;
 
		std::string token;
 
@@ -440,42 +437,37 @@ FILE *FioFOpenFile(const char *filename,
 
				if (tokens.size() < 2) return nullptr;
 
				tokens.pop_back();
 
			} else {
 
				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);
 
		}
 
	}
 

	
 
	/* Sometimes a full path is given. To support
 
	 * the 'subdirectory' must be 'removed'. */
 
	if (f == nullptr && subdir != NO_DIRECTORY) {
 
@@ -856,74 +848,67 @@ bool TarScanner::AddFile(const char *fil
 
 * Extract the tar with the given filename in the directory
 
 * where the tar resides.
 
 * @param tar_filename the name of the tar to extract.
 
 * @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. */
 
	if (it == _tar_list[subdir].end()) return false;
 

	
 
	const char *dirname = (*it).second.dirname;
 

	
 
	/* 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<FILE, FileDeleter> 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<FILE, FileDeleter> 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;
 
		}
 

	
 
		/* Now read from the tar and write it into the file. */
 
		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;
 
		}
 
	}
 

	
 
	DEBUG(misc, 9, "  extraction successful");
 
	return true;
src/fileio_func.h
Show inline comments
 
@@ -34,13 +34,13 @@ void FioSkipBytes(int n);
 
bool IsValidSearchPath(Searchpath sp);
 

	
 
/** Iterator for all the search paths */
 
#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);
 
std::string FioFindDirectory(Subdirectory subdir);
 
void FioCreateDirectory(const std::string &name);
 

	
 
@@ -48,13 +48,13 @@ const char *FiosGetScreenshotDir();
 

	
 
void SanitizeFilename(char *filename);
 
void AppendPathSeparator(std::string &buf);
 
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.
 

	
 
/** Helper for scanning for files with a given name */
 
class FileScanner {
 
protected:
src/game/game_text.cpp
Show inline comments
 
@@ -63,13 +63,13 @@ void NORETURN CDECL strgen_fatal(const c
 
 * @param file The file to read from.
 
 * @return The raw strings, or nullptr upon error.
 
 */
 
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);
 

	
 
	auto pos = file.rfind(PATHSEPCHAR);
 
	if (pos == std::string::npos) return LanguageStrings();
src/network/network_content.cpp
Show inline comments
 
@@ -540,13 +540,13 @@ void ClientNetworkContentSocketHandler::
 
		TarScanner ts;
 
		std::string fname = GetFullFilename(this->curInfo, false);
 
		ts.AddFile(sd, fname.c_str());
 

	
 
		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());
 
		}
 

	
 
#ifdef __EMSCRIPTEN__
 
		EM_ASM(if (window["openttd_syncfs"]) openttd_syncfs());
 
#endif
src/newgrf_profiling.cpp
Show inline comments
 
@@ -99,13 +99,13 @@ uint32 NewGRFProfiler::Finish()
 
		return 0;
 
	}
 

	
 
	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;
 

	
 
	fputs("Tick,Sprite,Feature,Item,CallbackID,Microseconds,Depth,Result\n", f);
 
	for (const Call &c : this->calls) {
src/openttd.cpp
Show inline comments
 
@@ -965,13 +965,13 @@ bool SafeLoad(const std::string &filenam
 
	assert(fop == SLO_LOAD);
 
	assert(dft == DFT_GAME_FILE || (lf == nullptr && dft == DFT_OLD_GAME_FILE));
 
	GameMode ogm = _game_mode;
 

	
 
	_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:
 
			if (_network_dedicated) {
 
				/*
 
				 * We need to reinit a network map...
 
@@ -1124,13 +1124,13 @@ void SwitchToMode(SwitchMode new_mode)
 
				BaseSounds::ini_set = BaseSounds::GetUsedSet()->name;
 
			}
 
			break;
 

	
 
		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 {
 
				DeleteWindowById(WC_SAVELOAD, 0);
 
			}
 
			break;
src/saveload/oldloader.cpp
Show inline comments
 
@@ -268,25 +268,25 @@ static SavegameType DetermineOldSavegame
 

	
 
	return type;
 
}
 

	
 
typedef bool LoadOldMainProc(LoadgameState *ls);
 

	
 
bool LoadOldSaveGame(const char *file)
 
bool LoadOldSaveGame(const std::string &file)
 
{
 
	LoadgameState ls;
 

	
 
	DEBUG(oldloader, 3, "Trying to load a TTD(Patch) savegame");
 

	
 
	InitLoading(&ls);
 

	
 
	/* Open 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;
 
	}
 

	
 
	SavegameType type = DetermineOldSavegameType(ls.file, nullptr, nullptr);
 

	
 
	LoadOldMainProc *proc = nullptr;
src/saveload/saveload.cpp
Show inline comments
 
@@ -2410,13 +2410,13 @@ static const SaveLoadFormat *GetSavegame
 
	return def;
 
}
 

	
 
/* 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.
 
 */
 
static void ResetSaveloadData()
 
{
 
@@ -2766,13 +2766,13 @@ SaveOrLoadResult LoadWithFilter(LoadFilt
 
 * @param filename The name of the savegame being created/loaded
 
 * @param fop Save or load mode. Load can also be a TTD(Patch) game.
 
 * @param sb The sub directory to save the savegame in
 
 * @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) {
 
		/* if not an autosave, but a user action, show error message */
 
		if (!_do_autosave) ShowErrorMessage(STR_ERROR_SAVE_STILL_IN_PROGRESS, INVALID_STRING_ID, WL_ERROR);
 
		return SL_OK;
 
@@ -2830,21 +2830,21 @@ SaveOrLoadResult SaveOrLoad(const char *
 

	
 
		if (fh == nullptr) {
 
			SlError(fop == SLO_SAVE ? STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE : STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
 
		}
 

	
 
		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);
 
		}
 

	
 
		/* 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. */
 
		ClearSaveLoadState();
 

	
 
		/* Skip the "colour" character */
src/saveload/saveload.h
Show inline comments
 
@@ -359,13 +359,13 @@ enum SavegameType {
 

	
 
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();
 

	
 
SaveOrLoadResult SaveWithFilter(struct SaveFilter *writer, bool threaded);
 
SaveOrLoadResult LoadWithFilter(struct LoadFilter *reader);
0 comments (0 inline, 0 general)