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. * 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. * \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. * \brief Returns the file name of the given file.
* *
* \param path Specifies the path of the file. * \param path Specifies the path of the file.
* \param cutExtension Indicates whether the extension/suffix should be cutted. * \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('/'); const auto lastSlash = path.rfind('/');
size_t lastBackSlash = path.rfind('\\'); const auto lastBackSlash = path.rfind('\\');
size_t lastPoint = cutExtension ? path.rfind('.') : string::npos; const auto lastPoint = cutExtension ? path.rfind('.') : string::npos;
size_t lastSeparator; auto lastSeparator = decltype(lastSlash)();
if (lastSlash == string::npos && lastBackSlash == string::npos) { 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) { } else if (lastSlash == string::npos) {
lastSeparator = lastBackSlash; lastSeparator = lastBackSlash;
} else if (lastBackSlash == string::npos) { } else if (lastBackSlash == string::npos) {
@ -121,7 +161,7 @@ string BasicFileInfo::fileName(const string &path, bool cutExtension)
} else { } else {
lastSeparator = lastSlash > lastBackSlash ? lastSlash : lastBackSlash; 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. * \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); return fileName(m_path, cutExtension);
} }
@ -141,7 +181,7 @@ string BasicFileInfo::fileName(bool cutExtension) const
*/ */
std::string BasicFileInfo::extension(std::string_view path) std::string BasicFileInfo::extension(std::string_view path)
{ {
std::size_t lastPoint = path.rfind('.'); const auto lastPoint = path.rfind('.');
if (lastPoint == std::string::npos) { if (lastPoint == std::string::npos) {
return std::string(); return std::string();
} else { } else {
@ -152,7 +192,7 @@ std::string BasicFileInfo::extension(std::string_view path)
/*! /*!
* \brief Returns the extension of the current file. * \brief Returns the extension of the current file.
*/ */
string BasicFileInfo::extension() const std::string BasicFileInfo::extension() const
{ {
return extension(m_path); return extension(m_path);
} }
@ -160,16 +200,16 @@ string BasicFileInfo::extension() const
/*! /*!
* \brief Returns a copy of the given path without the extension/suffix. * \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('.'); const auto lastPoint = fullPath.rfind('.');
return lastPoint != string::npos ? fullPath.substr(0, lastPoint) : fullPath; return std::string(lastPoint != std::string::npos ? fullPath.substr(0, lastPoint) : fullPath);
} }
/*! /*!
* \brief Returns the path of the current file without the extension/suffix. * \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); return pathWithoutExtension(m_path);
} }
@ -177,13 +217,13 @@ string BasicFileInfo::pathWithoutExtension() const
/*! /*!
* \brief Returns the path of the directory containing the given file. * \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('/'); const auto lastSlash = path.rfind('/');
size_t lastBackSlash = path.rfind('\\'); const auto lastBackSlash = path.rfind('\\');
size_t lastSeparator; auto lastSeparator = decltype(lastSlash)();
if (lastSlash == string::npos && lastBackSlash == string::npos) { if (lastSlash == string::npos && lastBackSlash == std::string::npos) {
return string(); return std::string();
} else if (lastSlash == string::npos) { } else if (lastSlash == string::npos) {
lastSeparator = lastBackSlash; lastSeparator = lastBackSlash;
} else if (lastBackSlash == string::npos) { } else if (lastBackSlash == string::npos) {
@ -192,9 +232,9 @@ string BasicFileInfo::containingDirectory(const string &path)
lastSeparator = lastSlash > lastBackSlash ? lastSlash : lastBackSlash; lastSeparator = lastSlash > lastBackSlash ? lastSlash : lastBackSlash;
} }
if (lastSeparator > 0) { if (lastSeparator > 0) {
return path.substr(0, lastSeparator); return std::string(path.substr(0, lastSeparator));
} else { } else {
return string(); return std::string();
} }
} }

View File

@ -14,7 +14,9 @@ namespace TagParser {
class TAG_PARSER_EXPORT BasicFileInfo { class TAG_PARSER_EXPORT BasicFileInfo {
public: public:
// constructor, destructor // 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(const BasicFileInfo &) = delete;
BasicFileInfo &operator=(const BasicFileInfo &) = delete; BasicFileInfo &operator=(const BasicFileInfo &) = delete;
virtual ~BasicFileInfo(); virtual ~BasicFileInfo();
@ -32,20 +34,22 @@ public:
// methods to get, set path (components) // methods to get, set path (components)
const std::string &path() const; const std::string &path() const;
void setPath(std::string_view path); 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; std::string fileName(bool cutExtension = false) const;
static std::string extension(std::string_view path); static std::string extension(std::string_view path);
std::string extension() const; std::string extension() const;
static std::string pathWithoutExtension(const std::string &fullPath); static std::string pathWithoutExtension(std::string_view fullPath);
std::string pathWithoutExtension() const; std::string pathWithoutExtension() const;
static std::string containingDirectory(const std::string &path); static std::string containingDirectory(std::string_view path);
std::string containingDirectory() const; 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 // methods to get, set the file size
std::uint64_t size() const; std::uint64_t size() const;
void reportSizeChanged(std::uint64_t newSize); void reportSizeChanged(std::uint64_t newSize);
void reportPathChanged(const std::string &newPath); void reportPathChanged(std::string_view newPath);
void reportPathChanged(std::string &&newPath);
protected: protected:
virtual void invalidated(); 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. * \brief Call this function to report that the path changed.
* \remarks Should be called after associating another file to the stream() manually. * \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; 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 * \brief Returns removes the "file:/" prefix from \a url to be able to pass it to functions
* like open(), stat() and truncate(). * like open(), stat() and truncate().
* \remarks If \a url is already a plain path it won't changed. * \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. * \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(); 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() MediaFileInfo::MediaFileInfo(std::string &&path)
: m_containerParsingStatus(ParsingStatus::NotParsedYet) : BasicFileInfo(std::move(path))
, m_containerParsingStatus(ParsingStatus::NotParsedYet)
, m_containerFormat(ContainerFormat::Unknown) , m_containerFormat(ContainerFormat::Unknown)
, m_containerOffset(0) , m_containerOffset(0)
, m_actualExistingId3v1Tag(false) , m_actualExistingId3v1Tag(false)
@ -100,29 +103,18 @@ MediaFileInfo::MediaFileInfo()
} }
/*! /*!
* \brief Constructs a new MediaFileInfo for the specified file. * \brief Constructs a new MediaFileInfo.
*
* \param path Specifies the absolute or relative path of the file.
*/ */
MediaFileInfo::MediaFileInfo(const string &path) MediaFileInfo::MediaFileInfo()
: BasicFileInfo(path) : MediaFileInfo(std::string())
, m_containerParsingStatus(ParsingStatus::NotParsedYet) {
, m_containerFormat(ContainerFormat::Unknown) }
, m_containerOffset(0)
, m_actualExistingId3v1Tag(false) /*!
, m_tracksParsingStatus(ParsingStatus::NotParsedYet) * \brief Constructs a new MediaFileInfo.
, m_tagsParsingStatus(ParsingStatus::NotParsedYet) */
, m_chaptersParsingStatus(ParsingStatus::NotParsedYet) MediaFileInfo::MediaFileInfo(std::string_view path)
, m_attachmentsParsingStatus(ParsingStatus::NotParsedYet) : MediaFileInfo(std::string(path))
, 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)
{ {
} }

View File

@ -46,7 +46,8 @@ class TAG_PARSER_EXPORT MediaFileInfo : public BasicFileInfo {
public: public:
// constructor, destructor // constructor, destructor
explicit MediaFileInfo(); explicit MediaFileInfo();
explicit MediaFileInfo(const std::string &path); explicit MediaFileInfo(std::string_view path);
explicit MediaFileInfo(std::string &&path);
MediaFileInfo(const MediaFileInfo &) = delete; MediaFileInfo(const MediaFileInfo &) = delete;
MediaFileInfo &operator=(const MediaFileInfo &) = delete; MediaFileInfo &operator=(const MediaFileInfo &) = delete;
~MediaFileInfo() override; ~MediaFileInfo() override;
@ -123,9 +124,11 @@ public:
// methods to get, set object behaviour // methods to get, set object behaviour
const std::string &backupDirectory() const; 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; 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; const std::string &writingApplication() const;
void setWritingApplication(std::string_view writingApplication); void setWritingApplication(std::string_view writingApplication);
bool isForcingFullParse() const; bool isForcingFullParse() const;
@ -357,11 +360,20 @@ inline const std::string &MediaFileInfo::backupDirectory() const
* \brief Sets the directory used to store backup files. * \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. * \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; 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(). * \brief Returns the "save file path" which has been set using setSaveFilePath().
* \sa setSaveFilePath() * \sa setSaveFilePath()
@ -385,11 +397,19 @@ inline const std::string &MediaFileInfo::saveFilePath() const
* *
* \remarks \a saveFilePath mustn't be the current path(). * \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; 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. * \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. * \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() 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("/usr/bin"s, file.containingDirectory());
CPPUNIT_ASSERT_EQUAL("unsupported.bin"s, file.fileName()); CPPUNIT_ASSERT_EQUAL("unsupported.bin"s, file.fileName());
CPPUNIT_ASSERT_EQUAL("unsupported"s, file.fileName(true)); CPPUNIT_ASSERT_EQUAL("unsupported"s, file.fileName(true));