Improve passing paths

* Use `std::string_view` instead of `const std::string &`
* Add overloads taking `std::string &&` for re-using existing strings
This commit is contained in:
Martchus 2021-04-23 22:11:23 +02:00
parent f5cb2c5cba
commit 92e80a9286
5 changed files with 126 additions and 61 deletions

View File

@ -15,6 +15,31 @@ namespace TagParser {
* file name, extension, directory and size for a specified file.
*/
/*!
* \brief Constructs a new BasicFileInfo for the specified file.
*
* \param path Specifies the absolute or relative path of the file.
*/
BasicFileInfo::BasicFileInfo()
: m_size(0)
, m_readOnly(false)
{
m_file.exceptions(ios_base::failbit | ios_base::badbit);
}
/*!
* \brief Constructs a new BasicFileInfo for the specified file.
*
* \param path Specifies the absolute or relative path of the file.
*/
BasicFileInfo::BasicFileInfo(std::string &&path)
: m_path(std::move(path))
, m_size(0)
, m_readOnly(false)
{
m_file.exceptions(ios_base::failbit | ios_base::badbit);
}
/*!
* \brief Constructs a new BasicFileInfo for the specified file.
*
@ -100,20 +125,35 @@ void BasicFileInfo::setPath(std::string_view path)
}
}
/*!
* \brief Sets the current file.
*
* A possibly opened std::fstream will be closed and invalidated() will be called.
*
* \param path Specifies the absolute or relative path of the file to be set.
*/
void BasicFileInfo::setPath(std::string &&path)
{
if (path != m_path) {
invalidated();
m_path = path;
}
}
/*!
* \brief Returns the file name of the given file.
*
* \param path Specifies the path of the file.
* \param cutExtension Indicates whether the extension/suffix should be cutted.
*/
string BasicFileInfo::fileName(const string &path, bool cutExtension)
std::string BasicFileInfo::fileName(std::string_view path, bool cutExtension)
{
size_t lastSlash = path.rfind('/');
size_t lastBackSlash = path.rfind('\\');
size_t lastPoint = cutExtension ? path.rfind('.') : string::npos;
size_t lastSeparator;
const auto lastSlash = path.rfind('/');
const auto lastBackSlash = path.rfind('\\');
const auto lastPoint = cutExtension ? path.rfind('.') : string::npos;
auto lastSeparator = decltype(lastSlash)();
if (lastSlash == string::npos && lastBackSlash == string::npos) {
return (lastPoint == string::npos) ? path : path.substr(0, lastPoint);
return std::string(lastPoint == string::npos ? path : path.substr(0, lastPoint));
} else if (lastSlash == string::npos) {
lastSeparator = lastBackSlash;
} else if (lastBackSlash == string::npos) {
@ -121,7 +161,7 @@ string BasicFileInfo::fileName(const string &path, bool cutExtension)
} else {
lastSeparator = lastSlash > lastBackSlash ? lastSlash : lastBackSlash;
}
return (lastPoint != string::npos) ? path.substr(lastSeparator + 1, lastPoint - lastSeparator - 1) : path.substr(lastSeparator + 1);
return std::string(lastPoint != string::npos ? path.substr(lastSeparator + 1, lastPoint - lastSeparator - 1) : path.substr(lastSeparator + 1));
}
/*!
@ -129,7 +169,7 @@ string BasicFileInfo::fileName(const string &path, bool cutExtension)
*
* \param cutExtension Indicates whether the extension should be cutted.
*/
string BasicFileInfo::fileName(bool cutExtension) const
std::string BasicFileInfo::fileName(bool cutExtension) const
{
return fileName(m_path, cutExtension);
}
@ -141,7 +181,7 @@ string BasicFileInfo::fileName(bool cutExtension) const
*/
std::string BasicFileInfo::extension(std::string_view path)
{
std::size_t lastPoint = path.rfind('.');
const auto lastPoint = path.rfind('.');
if (lastPoint == std::string::npos) {
return std::string();
} else {
@ -152,7 +192,7 @@ std::string BasicFileInfo::extension(std::string_view path)
/*!
* \brief Returns the extension of the current file.
*/
string BasicFileInfo::extension() const
std::string BasicFileInfo::extension() const
{
return extension(m_path);
}
@ -160,16 +200,16 @@ string BasicFileInfo::extension() const
/*!
* \brief Returns a copy of the given path without the extension/suffix.
*/
string BasicFileInfo::pathWithoutExtension(const string &fullPath)
std::string BasicFileInfo::pathWithoutExtension(std::string_view fullPath)
{
size_t lastPoint = fullPath.rfind('.');
return lastPoint != string::npos ? fullPath.substr(0, lastPoint) : fullPath;
const auto lastPoint = fullPath.rfind('.');
return std::string(lastPoint != std::string::npos ? fullPath.substr(0, lastPoint) : fullPath);
}
/*!
* \brief Returns the path of the current file without the extension/suffix.
*/
string BasicFileInfo::pathWithoutExtension() const
std::string BasicFileInfo::pathWithoutExtension() const
{
return pathWithoutExtension(m_path);
}
@ -177,13 +217,13 @@ string BasicFileInfo::pathWithoutExtension() const
/*!
* \brief Returns the path of the directory containing the given file.
*/
string BasicFileInfo::containingDirectory(const string &path)
std::string BasicFileInfo::containingDirectory(std::string_view path)
{
size_t lastSlash = path.rfind('/');
size_t lastBackSlash = path.rfind('\\');
size_t lastSeparator;
if (lastSlash == string::npos && lastBackSlash == string::npos) {
return string();
const auto lastSlash = path.rfind('/');
const auto lastBackSlash = path.rfind('\\');
auto lastSeparator = decltype(lastSlash)();
if (lastSlash == string::npos && lastBackSlash == std::string::npos) {
return std::string();
} else if (lastSlash == string::npos) {
lastSeparator = lastBackSlash;
} else if (lastBackSlash == string::npos) {
@ -192,9 +232,9 @@ string BasicFileInfo::containingDirectory(const string &path)
lastSeparator = lastSlash > lastBackSlash ? lastSlash : lastBackSlash;
}
if (lastSeparator > 0) {
return path.substr(0, lastSeparator);
return std::string(path.substr(0, lastSeparator));
} else {
return string();
return std::string();
}
}

View File

@ -14,7 +14,9 @@ namespace TagParser {
class TAG_PARSER_EXPORT BasicFileInfo {
public:
// constructor, destructor
explicit BasicFileInfo(std::string_view path = std::string_view());
explicit BasicFileInfo();
explicit BasicFileInfo(std::string &&path);
explicit BasicFileInfo(std::string_view path);
BasicFileInfo(const BasicFileInfo &) = delete;
BasicFileInfo &operator=(const BasicFileInfo &) = delete;
virtual ~BasicFileInfo();
@ -32,20 +34,22 @@ public:
// methods to get, set path (components)
const std::string &path() const;
void setPath(std::string_view path);
static std::string fileName(const std::string &path, bool cutExtension = false);
void setPath(std::string &&path);
static std::string fileName(std::string_view path, bool cutExtension = false);
std::string fileName(bool cutExtension = false) const;
static std::string extension(std::string_view path);
std::string extension() const;
static std::string pathWithoutExtension(const std::string &fullPath);
static std::string pathWithoutExtension(std::string_view fullPath);
std::string pathWithoutExtension() const;
static std::string containingDirectory(const std::string &path);
static std::string containingDirectory(std::string_view path);
std::string containingDirectory() const;
static std::string_view pathForOpen(const std::string &url);
static std::string_view pathForOpen(std::string_view url);
// methods to get, set the file size
std::uint64_t size() const;
void reportSizeChanged(std::uint64_t newSize);
void reportPathChanged(const std::string &newPath);
void reportPathChanged(std::string_view newPath);
void reportPathChanged(std::string &&newPath);
protected:
virtual void invalidated();
@ -126,18 +130,27 @@ inline void BasicFileInfo::reportSizeChanged(std::uint64_t newSize)
* \brief Call this function to report that the path changed.
* \remarks Should be called after associating another file to the stream() manually.
*/
inline void BasicFileInfo::reportPathChanged(const std::string &newPath)
inline void BasicFileInfo::reportPathChanged(std::string_view newPath)
{
m_path = newPath;
}
/*!
* \brief Call this function to report that the path changed.
* \remarks Should be called after associating another file to the stream() manually.
*/
inline void BasicFileInfo::reportPathChanged(std::string &&newPath)
{
m_path = std::move(newPath);
}
/*!
* \brief Returns removes the "file:/" prefix from \a url to be able to pass it to functions
* like open(), stat() and truncate().
* \remarks If \a url is already a plain path it won't changed.
* \returns Returns a pointer the URL data itself. No copy is made.
*/
inline std::string_view BasicFileInfo::pathForOpen(const std::string &url)
inline std::string_view BasicFileInfo::pathForOpen(std::string_view url)
{
return CppUtilities::startsWith(url, "file:/") ? url.data() + 6 : url.data();
}

View File

@ -76,10 +76,13 @@ namespace TagParser {
*/
/*!
* \brief Constructs a new MediaFileInfo.
* \brief Constructs a new MediaFileInfo for the specified file.
*
* \param path Specifies the absolute or relative path of the file.
*/
MediaFileInfo::MediaFileInfo()
: m_containerParsingStatus(ParsingStatus::NotParsedYet)
MediaFileInfo::MediaFileInfo(std::string &&path)
: BasicFileInfo(std::move(path))
, m_containerParsingStatus(ParsingStatus::NotParsedYet)
, m_containerFormat(ContainerFormat::Unknown)
, m_containerOffset(0)
, m_actualExistingId3v1Tag(false)
@ -100,29 +103,18 @@ MediaFileInfo::MediaFileInfo()
}
/*!
* \brief Constructs a new MediaFileInfo for the specified file.
*
* \param path Specifies the absolute or relative path of the file.
* \brief Constructs a new MediaFileInfo.
*/
MediaFileInfo::MediaFileInfo(const string &path)
: BasicFileInfo(path)
, m_containerParsingStatus(ParsingStatus::NotParsedYet)
, m_containerFormat(ContainerFormat::Unknown)
, m_containerOffset(0)
, m_actualExistingId3v1Tag(false)
, m_tracksParsingStatus(ParsingStatus::NotParsedYet)
, m_tagsParsingStatus(ParsingStatus::NotParsedYet)
, m_chaptersParsingStatus(ParsingStatus::NotParsedYet)
, m_attachmentsParsingStatus(ParsingStatus::NotParsedYet)
, m_minPadding(0)
, m_maxPadding(0)
, m_preferredPadding(0)
, m_tagPosition(ElementPosition::BeforeData)
, m_indexPosition(ElementPosition::BeforeData)
, m_forceFullParse(MEDIAINFO_CPP_FORCE_FULL_PARSE)
, m_forceRewrite(true)
, m_forceTagPosition(true)
, m_forceIndexPosition(true)
MediaFileInfo::MediaFileInfo()
: MediaFileInfo(std::string())
{
}
/*!
* \brief Constructs a new MediaFileInfo.
*/
MediaFileInfo::MediaFileInfo(std::string_view path)
: MediaFileInfo(std::string(path))
{
}

View File

@ -46,7 +46,8 @@ class TAG_PARSER_EXPORT MediaFileInfo : public BasicFileInfo {
public:
// constructor, destructor
explicit MediaFileInfo();
explicit MediaFileInfo(const std::string &path);
explicit MediaFileInfo(std::string_view path);
explicit MediaFileInfo(std::string &&path);
MediaFileInfo(const MediaFileInfo &) = delete;
MediaFileInfo &operator=(const MediaFileInfo &) = delete;
~MediaFileInfo() override;
@ -123,9 +124,11 @@ public:
// methods to get, set object behaviour
const std::string &backupDirectory() const;
void setBackupDirectory(const std::string &backupDirectory);
void setBackupDirectory(std::string_view backupDirectory);
void setBackupDirectory(std::string &&backupDirectory);
const std::string &saveFilePath() const;
void setSaveFilePath(const std::string &saveFilePath);
void setSaveFilePath(std::string_view saveFilePath);
void setSaveFilePath(std::string &&saveFilePath);
const std::string &writingApplication() const;
void setWritingApplication(std::string_view writingApplication);
bool isForcingFullParse() const;
@ -357,11 +360,20 @@ inline const std::string &MediaFileInfo::backupDirectory() const
* \brief Sets the directory used to store backup files.
* \remarks If empty, backup files will be stored in the same directory of the file being modified.
*/
inline void MediaFileInfo::setBackupDirectory(const std::string &backupDirectory)
inline void MediaFileInfo::setBackupDirectory(std::string_view backupDirectory)
{
m_backupDirectory = backupDirectory;
}
/*!
* \brief Sets the directory used to store backup files.
* \remarks If empty, backup files will be stored in the same directory of the file being modified.
*/
inline void MediaFileInfo::setBackupDirectory(std::string &&backupDirectory)
{
m_backupDirectory = std::move(backupDirectory);
}
/*!
* \brief Returns the "save file path" which has been set using setSaveFilePath().
* \sa setSaveFilePath()
@ -385,11 +397,19 @@ inline const std::string &MediaFileInfo::saveFilePath() const
*
* \remarks \a saveFilePath mustn't be the current path().
*/
inline void MediaFileInfo::setSaveFilePath(const std::string &saveFilePath)
inline void MediaFileInfo::setSaveFilePath(std::string_view saveFilePath)
{
m_saveFilePath = saveFilePath;
}
/*!
* \brief Sets the "save file path".
*/
inline void MediaFileInfo::setSaveFilePath(std::string &&saveFilePath)
{
m_saveFilePath = std::move(saveFilePath);
}
/*!
* \brief Sets the writing application as container-level meta-data.
* \remarks This is not read from the file when parsing and only used when saving changes.

View File

@ -70,7 +70,7 @@ void MediaFileInfoTests::testInitialStatus()
void MediaFileInfoTests::testFileSystemMethods()
{
MediaFileInfo file("/usr/bin/unsupported.bin");
MediaFileInfo file("/usr/bin/unsupported.bin"sv);
CPPUNIT_ASSERT_EQUAL("/usr/bin"s, file.containingDirectory());
CPPUNIT_ASSERT_EQUAL("unsupported.bin"s, file.fileName());
CPPUNIT_ASSERT_EQUAL("unsupported"s, file.fileName(true));