feat: 新增 DDciFile::copy 接口

使用 DDciFile::dataRef 和 DDciFile:writeFile 的组合能实现复制文件的
效果,但是无法实现目录的复制。因此,特单独添加 DDciFile::copy,以方
便复制文件和目录。

Log:
Change-Id: I650e13e45fa94e4ff9b197504025915c20a8c00d
This commit is contained in:
zccrs 2021-08-30 16:02:43 +08:00
parent 5fb1c1812e
commit 3697593f7c
5 changed files with 88 additions and 15 deletions

2
debian/api.json vendored

File diff suppressed because one or more lines are too long

View File

@ -96,8 +96,10 @@ public:
qint64 writeDataForNode(QIODevice *device, Node *node) const;
qint64 writeNode(QIODevice *device, Node *node) const;
Node *mkNode(const QString &filePath, qint8 type);
Node *mkNode(const QString &filePath);
void removeNode(Node *node);
void copyNode(const Node *from, Node *to);
bool loadDirectory(Node *directory,
const QByteArray &data, qint64 &begin, qint64 end,
QHash<QString, Node *> &pathToNode);
@ -224,9 +226,9 @@ qint64 DDciFilePrivate::writeNode(QIODevice *device, DDciFilePrivate::Node *node
return metaDataSize + dataSize;
}
DDciFilePrivate::Node *DDciFilePrivate::mkNode(const QString &filePath, qint8 type)
DDciFilePrivate::Node *DDciFilePrivate::mkNode(const QString &filePath)
{
qCDebug(logDF, "Request create a node, type is %i", type);
qCDebug(logDF, "Request create a node");
if (pathToNode.contains(filePath)) {
setErrorString(QString("The \"%1\" is existed").arg(filePath));
@ -249,7 +251,6 @@ DDciFilePrivate::Node *DDciFilePrivate::mkNode(const QString &filePath, qint8 ty
}
Node *newNode = new Node;
newNode->type = type;
newNode->name = info.fileName();
newNode->parent = parentNode;
@ -280,6 +281,32 @@ void DDciFilePrivate::removeNode(DDciFilePrivate::Node *node)
delete node;
}
void DDciFilePrivate::copyNode(const DDciFilePrivate::Node *from, DDciFilePrivate::Node *to)
{
QList<QPair<const Node*, Node*>> copyPendingList;
copyPendingList << qMakePair(from, to);
for (int i = 0; i < copyPendingList.size(); ++i) {
auto f = copyPendingList.at(i).first;
auto t = copyPendingList.at(i).second;
t->type = f->type;
t->data = f->data;
for (const auto child : f->children) {
if (child == to)
continue;
Node *newChild = new Node;
newChild->parent = t;
newChild->name = child->name;
pathToNode[newChild->path()] = newChild;
t->children << newChild;
copyPendingList << qMakePair(child, newChild);
}
}
}
bool DDciFilePrivate::loadDirectory(DDciFilePrivate::Node *directory,
const QByteArray &data, qint64 &offset, qint64 end,
QHash<QString, DDciFilePrivate::Node *> &pathToNode)
@ -516,7 +543,11 @@ bool DDciFile::mkdir(const QString &filePath)
D_D(DDciFile);
qCDebug(logDF, "Request create the \"%s\" directory", qPrintable(filePath));
return d->mkNode(filePath, FILE_TYPE_DIR);
auto node = d->mkNode(filePath);
if (!node)
return false;
node->type = FILE_TYPE_DIR;
return true;
}
bool DDciFile::writeFile(const QString &filePath, const QByteArray &data, bool override)
@ -542,10 +573,11 @@ bool DDciFile::writeFile(const QString &filePath, const QByteArray &data, bool o
}
}
auto node = d->mkNode(filePath, FILE_TYPE_FILE);
auto node = d->mkNode(filePath);
if (!node)
return false;
node->type = FILE_TYPE_FILE;
node->data = data;
return true;
}
@ -624,4 +656,23 @@ bool DDciFile::rename(const QString &filePath, const QString &newFilePath, bool
}
}
bool DDciFile::copy(const QString &from, const QString &to)
{
D_D(DDciFile);
const auto fromNode = d->pathToNode.value(from);
if (!fromNode) {
d->setErrorString(QString("The \"%1\" is not exists").arg(from));
return false;
}
auto toNode = d->mkNode(to);
if (!toNode) {
return false;
}
d->copyNode(fromNode, toNode);
return true;
}
DCORE_END_NAMESPACE

View File

@ -67,6 +67,7 @@ public:
bool writeFile(const QString &filePath, const QByteArray &data, bool override = false);
bool remove(const QString &filePath);
bool rename(const QString &filePath, const QString &newFilePath, bool override = false);
bool copy(const QString &from, const QString &to);
};
DCORE_END_NAMESPACE

View File

@ -294,14 +294,12 @@ bool DDciFileEngine::copy(const QString &newName)
{
if (!file->isValid())
return false;
if (file->type(subfilePath) != DDciFile::File)
return false;
// 解析出新的 dci 内部文件路径
const auto paths = resolvePath(newName, dciFilePath);
if (paths.second.isEmpty())
return false;
return file->writeFile(paths.second, file->dataRef(subfilePath)) && forceSave();
return file->copy(subfilePath, paths.second) && forceSave();
}
bool DDciFileEngine::rename(const QString &newName)

View File

@ -148,6 +148,25 @@ TEST_F(ut_DCI, DDciFile) {
ASSERT_EQ(dciFile.childrenCount("/"), 0);
ASSERT_EQ(dciFile.toData(), QByteArrayLiteral("DCI\0\1\0\0\0"));
}
// DDciFile::copy
{
DDciFile dciFile;
// 文件复制
ASSERT_TRUE(dciFile.writeFile("/test.txt", "test"));
ASSERT_TRUE(dciFile.copy("/test.txt", "/test.txt.new"));
ASSERT_TRUE(dciFile.exists("/test.txt.new"));
ASSERT_EQ(dciFile.list("/", true), (QStringList{"test.txt", "test.txt.new"}));
ASSERT_EQ(dciFile.dataRef("/test.txt"), dciFile.dataRef("/test.txt.new"));
// 目录复制
ASSERT_TRUE(dciFile.mkdir("/test"));
ASSERT_TRUE(dciFile.rename("/test.txt", "/test/test.txt"));
ASSERT_TRUE(dciFile.copy("/test", "/test.new"));
ASSERT_TRUE(dciFile.exists("/test.new/test.txt"));
ASSERT_EQ(dciFile.list("/test.new", true), (QStringList{"test.txt"}));
ASSERT_EQ(dciFile.dataRef("/test/test.txt"), dciFile.dataRef("/test.new/test.txt"));
}
}
class TestDCIFileHelper {
@ -282,13 +301,17 @@ TEST_F(ut_DCI, DFileEngine) {
// 复制
ASSERT_TRUE(QFile::copy(helper.dciFormatFilePath("/1.new/test.txt"),
helper.dciFormatFilePath("/test.txt")));
// 目录禁止复制
ASSERT_FALSE(QFile::copy(helper.dciFormatFilePath("/3"),
helper.dciFormatFilePath("/3.new")));
// [/1.new, /1.new/test.txt, /2.new, /3, /test.txt]
// 复制目录
ASSERT_TRUE(QFile::copy(helper.dciFormatFilePath("/1.new"),
helper.dciFormatFilePath("/1")));
ASSERT_EQ(QDir(helper.dciFormatFilePath("/1")).entryList(),
QDir(helper.dciFormatFilePath("/1.new")).entryList());
// [/1.new, /1.new/test.txt, /2.new, /3, /test.txt, "/1"]
// 目录遍历
QStringList list {
helper.dciFormatFilePath("/1"),
helper.dciFormatFilePath("/1/test.txt"),
helper.dciFormatFilePath("/1.new"),
helper.dciFormatFilePath("/1.new/test.txt"),
helper.dciFormatFilePath("/2.new"),
@ -308,6 +331,6 @@ TEST_F(ut_DCI, DFileEngine) {
ASSERT_TRUE(QFile::remove(helper.dciFormatFilePath("/1.new")));
// [/3]
ASSERT_EQ(QDir(helper.dciFormatFilePath()).entryList(),
QStringList {"3"});
(QStringList {"1", "3"}));
}
}