PathUtil: Serialization and Formatting (#8103)

PathUtil: Serialization and Formatting
* Serialize all operations to use / instead of platform specific paths.
* Formatting changes for consistency.
* Reorder functions, add serialization enforcement to the other two functions.
This commit is contained in:
Jan125
2025-10-31 17:06:34 +01:00
committed by GitHub
parent 0fe697c4e5
commit fcb356df3d
2 changed files with 58 additions and 32 deletions

View File

@@ -48,25 +48,25 @@ namespace lmms::PathUtil
QString LMMS_EXPORT basePrefix(const Base base);
//! Check the prefix of a path and return the base it corresponds to
//! Defaults to Base::Absolute
Base LMMS_EXPORT baseLookup(const QString & path);
Base LMMS_EXPORT baseLookup(const QString& input);
//! Remove the prefix from a path, iff there is one
QString LMMS_EXPORT stripPrefix(const QString & path);
QString LMMS_EXPORT stripPrefix(const QString& input);
//! Get the filename for a path, handling prefixed paths correctly
QString LMMS_EXPORT cleanName(const QString & path);
QString LMMS_EXPORT cleanName(const QString& input);
//! Upgrade prefix-less relative paths to the new format
QString LMMS_EXPORT oldRelativeUpgrade(const QString & input);
QString LMMS_EXPORT oldRelativeUpgrade(const QString& input);
//! Make this path absolute. If a pointer to boolean is given
//! it will indicate whether the path was converted successfully
QString LMMS_EXPORT toAbsolute(const QString & input, bool* error = nullptr);
QString LMMS_EXPORT toAbsolute(const QString& input, bool* error = nullptr);
//! Make this path relative to a given base, return an absolute path if that fails
QString LMMS_EXPORT relativeOrAbsolute(const QString & input, const Base base);
QString LMMS_EXPORT relativeOrAbsolute(const QString& input, const Base base);
//! Make this path relative to any base, choosing the shortest if there are
//! multiple options. allowLocal defines whether local paths should be considered.
//! Defaults to an absolute path if all bases fail.
QString LMMS_EXPORT toShortestRelative(const QString & input, bool allowLocal = false);
QString LMMS_EXPORT toShortestRelative(const QString& input, bool allowLocal = false);
} // namespace lmms::PathUtil

View File

@@ -97,12 +97,14 @@ namespace lmms::PathUtil
}
}
Base baseLookup(const QString & path)
Base baseLookup(const QString& input)
{
if (input.isEmpty()) { return Base::Absolute; };
for (auto base: relativeBases)
{
QString prefix = basePrefix(base);
if ( path.startsWith(prefix) ) { return base; }
if (input.startsWith(prefix)) { return base; }
}
return Base::Absolute;
}
@@ -110,63 +112,84 @@ namespace lmms::PathUtil
QString stripPrefix(const QString & path)
// Enforce forward slashes for cross-platform compatibility due to limitations of QDir::fromNativeSeparators, see #8107.
QString serializePath(const QString& input)
{
return path.mid( basePrefix(baseLookup(path)).length() );
if (input.isEmpty()) { return input; }
return QString(input).replace("\\", "/");
}
QString cleanName(const QString& path)
QString stripPrefix(const QString& input)
{
if (input.isEmpty()) { return input; }
QString path = serializePath(input);
return path.mid(basePrefix(baseLookup(path)).length());
}
QString cleanName(const QString& input)
{
if (input.isEmpty()) { return input; }
QString path = serializePath(input);
return stripPrefix(QFileInfo(path).completeBaseName());
}
QString oldRelativeUpgrade(const QString & input)
QString oldRelativeUpgrade(const QString& input)
{
if (input.isEmpty()) { return input; }
Base assumedBase = Base::Absolute;
//Start by assuming that the file is a user sample
Base assumedBase = Base::UserSample;
if (input.isEmpty()) { return basePrefix(assumedBase); }
QString path = serializePath(input);
//Check if it's a user sample.
QString userPath = baseLocation(Base::UserSample) + path;
QFileInfo userInfo(userPath);
if (userInfo.exists()) { assumedBase = Base::UserSample; }
//Check if it's a factory sample
QString factoryPath = baseLocation(Base::FactorySample) + input;
QString factoryPath = baseLocation(Base::FactorySample) + path;
QFileInfo factoryInfo(factoryPath);
if (factoryInfo.exists()) { assumedBase = Base::FactorySample; }
//Check if it's a VST
QString vstPath = baseLocation(Base::UserVST) + input;
QString vstPath = baseLocation(Base::UserVST) + path;
QFileInfo vstInfo(vstPath);
if (vstInfo.exists()) { assumedBase = Base::UserVST; }
//Assume we've found the correct base location, return the full path
return basePrefix(assumedBase) + input;
return basePrefix(assumedBase) + path;
}
QString toAbsolute(const QString & input, bool* error /* = nullptr*/)
QString toAbsolute(const QString& input, bool* error /* = nullptr*/)
{
if (input.isEmpty()) { return input; }
QString path = serializePath(input);
//First, do no harm to absolute paths
QFileInfo inputFileInfo = QFileInfo(input);
// Note: Paths starting with a colon (:) are always considered absolute, as they denote a QResource.
QFileInfo inputFileInfo = QFileInfo(path);
if (inputFileInfo.isAbsolute())
{
if (error) { *error = false; }
return input;
return path;
}
//Next, handle old relative paths with no prefix
QString upgraded = input.contains(":") ? input : oldRelativeUpgrade(input);
QString upgraded = oldRelativeUpgrade(path);
Base base = baseLookup(upgraded);
return baseLocation(base, error) + upgraded.remove(0, basePrefix(base).length());
}
QString relativeOrAbsolute(const QString & input, const Base base)
QString relativeOrAbsolute(const QString& input, const Base base)
{
if (input.isEmpty()) { return input; }
QString absolutePath = toAbsolute(input);
QString absolutePath = toAbsolute(serializePath(input));
if (base == Base::Absolute) { return absolutePath; }
bool error;
QString relativePath = baseQDir(base, &error).relativeFilePath(absolutePath);
@@ -177,10 +200,13 @@ namespace lmms::PathUtil
: relativePath;
}
QString toShortestRelative(const QString & input, bool allowLocal /* = false*/)
QString toShortestRelative(const QString& input, bool allowLocal /* = false*/)
{
QFileInfo inputFileInfo = QFileInfo(input);
QString absolutePath = inputFileInfo.isAbsolute() ? input : toAbsolute(input);
if (input.isEmpty()) { return basePrefix(Base::Absolute); }
QString path = serializePath(input);
QFileInfo inputFileInfo = QFileInfo(path);
QString absolutePath = inputFileInfo.isAbsolute() ? path : toAbsolute(path);
Base shortestBase = Base::Absolute;
QString shortestPath = relativeOrAbsolute(absolutePath, shortestBase);