mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-01 21:50:52 +01:00
09f3f9b41a
The class NonCopyable is, like the name says, supposed to disallow
copying. But should it allow moving?
For a long time, NonCopyable used to not allow moving. (It declared
a deleted copy constructor and assigment operator without declaring
a move constructor and assignment operator, making the compiler
implicitly delete the move constructor and assignment operator.)
That's fine if the classes that inherit from NonCopyable don't need
to be movable or if writing the move constructor and assignment
operator by hand is fine, but that's not the case for all classes,
as I discovered when I was working on the DirectoryBlob PR.
Because of that, I decided to make NonCopyable movable in c7602cc
,
allowing me to use NonCopyable in DirectoryBlob.h. That was however
an unfortunate decision, because some of the classes that inherit
from NonCopyable have incorrect behavior when moved by default-
generated move constructors and assignment operators, and do not
explicitly delete the move constructors and assignment operators,
relying on NonCopyable being non-movable.
So what can we do about this? There are four solutions that I can
think of:
1. Make NonCopyable non-movable and tell DirectoryBlob to suck it.
2. Keep allowing moving NonCopyable, and expect that classes that
don't support moving will delete the move constructor and
assignment operator manually. Not only is this inconsistent
(having classes disallow copying one way and disallow moving
another way), but deleting the move constructor and assignment
operator manually is too easy to forget compared to how tricky
the resulting problems are.
3. Have one "MovableNonCopyable" and one "NonMovableNonCopyable".
It works, but it feels rather silly...
4. Don't have a NonCopyable class at all. Considering that deleting
the copy constructor and assignment operator only takes two lines
of code, I don't see much of a reason to keep NonCopyable. I
suppose that there was more of a point in having NonCopyable back
in the pre-C++11 days, when it wasn't possible to use "= delete".
I decided to go with the fourth one (like the commit title says).
The implementation of the commit is fairly straight-forward, though
I would like to point out that I skipped adding "= delete" lines
for classes whose only reason for being uncopyable is that they
contain uncopyable classes like File::IOFile and std::unique_ptr,
because the compiler makes such classes uncopyable automatically.
206 lines
5.9 KiB
C++
206 lines
5.9 KiB
C++
// Copyright 2008 Dolphin Emulator Project
|
|
// Licensed under GPLv2+
|
|
// Refer to the license.txt file included.
|
|
|
|
#pragma once
|
|
|
|
#include <cstddef>
|
|
#include <fstream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include "Common/CommonTypes.h"
|
|
|
|
#ifdef _WIN32
|
|
#include "Common/StringUtil.h"
|
|
#endif
|
|
|
|
// User directory indices for GetUserPath
|
|
enum
|
|
{
|
|
D_USER_IDX,
|
|
D_GCUSER_IDX,
|
|
D_WIIROOT_IDX, // always points to User/Wii or global user-configured directory
|
|
D_SESSION_WIIROOT_IDX, // may point to minimal temporary directory for determinism
|
|
D_CONFIG_IDX, // global settings
|
|
D_GAMESETTINGS_IDX, // user-specified settings which override both the global and the default
|
|
// settings (per game)
|
|
D_MAPS_IDX,
|
|
D_CACHE_IDX,
|
|
D_SHADERCACHE_IDX,
|
|
D_SHADERS_IDX,
|
|
D_STATESAVES_IDX,
|
|
D_SCREENSHOTS_IDX,
|
|
D_HIRESTEXTURES_IDX,
|
|
D_DUMP_IDX,
|
|
D_DUMPFRAMES_IDX,
|
|
D_DUMPAUDIO_IDX,
|
|
D_DUMPTEXTURES_IDX,
|
|
D_DUMPDSP_IDX,
|
|
D_DUMPSSL_IDX,
|
|
D_LOAD_IDX,
|
|
D_LOGS_IDX,
|
|
D_MAILLOGS_IDX,
|
|
D_THEMES_IDX,
|
|
D_PIPES_IDX,
|
|
D_MEMORYWATCHER_IDX,
|
|
D_WFSROOT_IDX,
|
|
D_BACKUP_IDX,
|
|
F_DOLPHINCONFIG_IDX,
|
|
F_GCPADCONFIG_IDX,
|
|
F_WIIPADCONFIG_IDX,
|
|
F_GCKEYBOARDCONFIG_IDX,
|
|
F_GFXCONFIG_IDX,
|
|
F_DEBUGGERCONFIG_IDX,
|
|
F_LOGGERCONFIG_IDX,
|
|
F_UICONFIG_IDX,
|
|
F_MAINLOG_IDX,
|
|
F_RAMDUMP_IDX,
|
|
F_ARAMDUMP_IDX,
|
|
F_FAKEVMEMDUMP_IDX,
|
|
F_GCSRAM_IDX,
|
|
F_MEMORYWATCHERLOCATIONS_IDX,
|
|
F_MEMORYWATCHERSOCKET_IDX,
|
|
F_WIISDCARD_IDX,
|
|
NUM_PATH_INDICES
|
|
};
|
|
|
|
namespace File
|
|
{
|
|
// FileSystem tree node/
|
|
struct FSTEntry
|
|
{
|
|
bool isDirectory;
|
|
u64 size; // File length, or for directories, recursive count of children
|
|
std::string physicalName; // Name on disk
|
|
std::string virtualName; // Name in FST names table
|
|
std::vector<FSTEntry> children;
|
|
};
|
|
|
|
// The functions in this class are functionally identical to the standalone functions
|
|
// below, but if you are going to be calling more than one of the functions using the
|
|
// same path, creating a single FileInfo object and calling its functions multiple
|
|
// times is faster than calling standalone functions multiple times.
|
|
class FileInfo final
|
|
{
|
|
public:
|
|
explicit FileInfo(const std::string& path);
|
|
explicit FileInfo(const char* path);
|
|
explicit FileInfo(int fd);
|
|
|
|
// Returns true if the path exists
|
|
bool Exists() const;
|
|
// Returns true if the path exists and is a directory
|
|
bool IsDirectory() const;
|
|
// Returns true if the path exists and is a file
|
|
bool IsFile() const;
|
|
// Returns the size of a file (or returns 0 if the path doesn't refer to a file)
|
|
u64 GetSize() const;
|
|
|
|
private:
|
|
struct stat m_stat;
|
|
bool m_exists;
|
|
};
|
|
|
|
// Returns true if the path exists
|
|
bool Exists(const std::string& path);
|
|
|
|
// Returns true if the path exists and is a directory
|
|
bool IsDirectory(const std::string& path);
|
|
|
|
// Returns true if the path exists and is a file
|
|
bool IsFile(const std::string& path);
|
|
|
|
// Returns the size of a file (or returns 0 if the path isn't a file that exists)
|
|
u64 GetSize(const std::string& path);
|
|
|
|
// Overloaded GetSize, accepts file descriptor
|
|
u64 GetSize(const int fd);
|
|
|
|
// Overloaded GetSize, accepts FILE*
|
|
u64 GetSize(FILE* f);
|
|
|
|
// Returns true if successful, or path already exists.
|
|
bool CreateDir(const std::string& filename);
|
|
|
|
// Creates the full path of fullPath returns true on success
|
|
bool CreateFullPath(const std::string& fullPath);
|
|
|
|
// Deletes a given filename, return true on success
|
|
// Doesn't supports deleting a directory
|
|
bool Delete(const std::string& filename);
|
|
|
|
// Deletes a directory filename, returns true on success
|
|
bool DeleteDir(const std::string& filename);
|
|
|
|
// renames file srcFilename to destFilename, returns true on success
|
|
bool Rename(const std::string& srcFilename, const std::string& destFilename);
|
|
|
|
// ditto, but syncs the source file and, on Unix, syncs the directories after rename
|
|
bool RenameSync(const std::string& srcFilename, const std::string& destFilename);
|
|
|
|
// copies file srcFilename to destFilename, returns true on success
|
|
bool Copy(const std::string& srcFilename, const std::string& destFilename);
|
|
|
|
// creates an empty file filename, returns true on success
|
|
bool CreateEmptyFile(const std::string& filename);
|
|
|
|
// Recursive or non-recursive list of files and directories under directory.
|
|
FSTEntry ScanDirectoryTree(const std::string& directory, bool recursive);
|
|
|
|
// deletes the given directory and anything under it. Returns true on success.
|
|
bool DeleteDirRecursively(const std::string& directory);
|
|
|
|
// Returns the current directory
|
|
std::string GetCurrentDir();
|
|
|
|
// Create directory and copy contents (does not overwrite existing files)
|
|
void CopyDir(const std::string& source_path, const std::string& dest_path);
|
|
|
|
// Set the current directory to given directory
|
|
bool SetCurrentDir(const std::string& directory);
|
|
|
|
// Creates and returns the path to a new temporary directory.
|
|
std::string CreateTempDir();
|
|
|
|
// Get a filename that can hopefully be atomically renamed to the given path.
|
|
std::string GetTempFilenameForAtomicWrite(const std::string& path);
|
|
|
|
// Gets a set user directory path
|
|
// Don't call prior to setting the base user directory
|
|
const std::string& GetUserPath(unsigned int dir_index);
|
|
|
|
// Sets a user directory path
|
|
// Rebuilds internal directory structure to compensate for the new directory
|
|
void SetUserPath(unsigned int dir_index, const std::string& path);
|
|
|
|
// probably doesn't belong here
|
|
std::string GetThemeDir(const std::string& theme_name);
|
|
|
|
// Returns the path to where the sys file are
|
|
std::string GetSysDirectory();
|
|
|
|
#ifdef __APPLE__
|
|
std::string GetBundleDirectory();
|
|
#endif
|
|
|
|
std::string& GetExeDirectory();
|
|
|
|
bool WriteStringToFile(const std::string& str, const std::string& filename);
|
|
bool ReadFileToString(const std::string& filename, std::string& str);
|
|
|
|
// To deal with Windows being dumb at unicode:
|
|
template <typename T>
|
|
void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode)
|
|
{
|
|
#ifdef _WIN32
|
|
fstream.open(UTF8ToTStr(filename).c_str(), openmode);
|
|
#else
|
|
fstream.open(filename.c_str(), openmode);
|
|
#endif
|
|
}
|
|
|
|
} // namespace
|