Utils: Add std::expected implementation

Adds a std::expected implementation that is compatible with >= C++11.

FilePath::fileContents and FilePath::writeFileContents as well as
FilePath::copyFile are changed to return std::expected.

A couple of macros have been added to aid in using the expected types.

An auto test was added showing how to use the library.

Change-Id: Ibe3aecfc1029a0cf13b45bf5184ff03a04a2393b
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Marcus Tillmanns
2022-11-24 08:52:47 +01:00
parent 13c7283c0e
commit eca7044361
35 changed files with 2986 additions and 265 deletions

View File

@@ -9,15 +9,17 @@
#include "fileutils.h"
#include "hostosinfo.h"
#include "qtcassert.h"
#include "utilstr.h"
#include <QtGlobal>
#include <QByteArray>
#include <QDateTime>
#include <QDebug>
#include <QDirIterator>
#include <QFileInfo>
#include <QRegularExpression>
#include <QUrl>
#include <QStringView>
#include <QUrl>
#include <QtGlobal>
#ifdef Q_OS_WIN
#ifdef QTCREATOR_PCH_H
@@ -494,7 +496,7 @@ void FilePath::iterateDirectories(const FilePaths &dirs,
dir.iterateDirectory(callBack, filter);
}
std::optional<QByteArray> FilePath::fileContents(qint64 maxSize, qint64 offset) const
expected_str<QByteArray> FilePath::fileContents(qint64 maxSize, qint64 offset) const
{
return fileAccess()->fileContents(*this, maxSize, offset);
}
@@ -510,15 +512,14 @@ bool FilePath::ensureReachable(const FilePath &other) const
return false;
}
void FilePath::asyncFileContents(
const Continuation<const std::optional<QByteArray> &> &cont,
qint64 maxSize,
qint64 offset) const
void FilePath::asyncFileContents(const Continuation<const expected_str<QByteArray> &> &cont,
qint64 maxSize,
qint64 offset) const
{
return fileAccess()->asyncFileContents(*this, cont, maxSize, offset);
}
bool FilePath::writeFileContents(const QByteArray &data, qint64 offset) const
expected_str<qint64> FilePath::writeFileContents(const QByteArray &data, qint64 offset) const
{
return fileAccess()->writeFileContents(*this, data, offset);
}
@@ -528,10 +529,9 @@ FilePathInfo FilePath::filePathInfo() const
return fileAccess()->filePathInfo(*this);
}
void FilePath::asyncWriteFileContents(
const Continuation<bool> &cont,
const QByteArray &data,
qint64 offset) const
void FilePath::asyncWriteFileContents(const Continuation<const expected_str<qint64> &> &cont,
const QByteArray &data,
qint64 offset) const
{
return fileAccess()->asyncWriteFileContents(*this, cont, data, offset);
}
@@ -1315,33 +1315,47 @@ bool FilePath::removeRecursively(QString *error) const
return fileAccess()->removeRecursively(*this, error);
}
bool FilePath::copyFile(const FilePath &target) const
expected_str<void> FilePath::copyFile(const FilePath &target) const
{
if (host() != target.host()) {
// FIXME: This does not scale.
const std::optional<QByteArray> ba = fileContents();
if (!ba)
return false;
const auto perms = permissions();
if (!target.writeFileContents(*ba))
return false;
const expected_str<QByteArray> contents = fileContents();
if (!contents) {
return make_unexpected(
Tr::tr("Error while trying to copy file: %1").arg(contents.error()));
}
const QFile::Permissions perms = permissions();
const expected_str<qint64> copyResult = target.writeFileContents(*contents);
if (!copyResult)
return make_unexpected(Tr::tr("Could not copy file: %1").arg(copyResult.error()));
if (!target.setPermissions(perms)) {
target.removeFile();
return false;
return make_unexpected(
Tr::tr("Could not set permissions on \"%1\"").arg(target.toString()));
}
return true;
return {};
}
return fileAccess()->copyFile(*this, target);
}
void FilePath::asyncCopyFile(const std::function<void(bool)> &cont, const FilePath &target) const
void FilePath::asyncCopyFile(const Continuation<const expected_str<void> &> &cont,
const FilePath &target) const
{
if (host() != target.host()) {
asyncFileContents([cont, target](const std::optional<QByteArray> &ba) {
if (ba)
target.asyncWriteFileContents(cont, *ba);
asyncFileContents([cont, target](const expected_str<QByteArray> &contents) {
if (contents)
target.asyncWriteFileContents(
[cont](const expected_str<qint64> &result) {
if (result)
cont({});
else
cont(make_unexpected(result.error()));
},
*contents);
});
return;
}