Структурирование / организация связанного списка папок файловой системы

TLDR:

Мне нужно знать, как я могу представить файловую систему, используя связанный список
struct, когда обход узла находится в странно обращенной глубине,
в алфавитном порядке, зная только две вещи одновременно:

  • Полный путь к файлу (или папке) и:
  • Является ли этот узел файлом или папкой?

Подробности:

UE4 поддерживает встроенные кроссплатформенные операции с файловой системой через IPlatformFile.
Для обхода файловой системы они включили следующие методы:

Моя цель — заполнить следующую структуру:

struct FFolderNode
{
public:
FFolderNode() : FFolderNode(nullptr, TEXT(""), TEXT("")) {};
FFolderNode(const FString& Path, const FString& Name) : FFolderNode(nullptr, Path, Name) {};
FFolderNode(FFolderNode *ParentNode, const FString& Path, const FString& Name) : ParentNode(ParentNode), Path(Path), Name(Name)
{
ID = FGuid::NewGuid();
};

// Makes it easier to identify, map & find this node
FGuid ID;
// The name of this directory
FString Name;
// The path of this directory
FString Path;
// The filenames this directory contains
TArray<FString> FileNames;
// The upwards directory (equivalent to the path "..")
FFolderNode *ParentNode;
// The subfolders (if any) contained within this directory
TArray<FFolderNode*> ChildNodes;
};

У меня проблема …
Я сдаю свой проект Contents путь к папке IPlatformFile::IterateDirectoryи это делает это:
введите описание изображения здесь

Похоже в алфавитном порядке? Так что я не уверен, с чего начать.
Похоже, мне нужно иметь возможность создавать узлы перед созданием & присваивание их родителям, без какого-либо реального предварительного знания владельца, за исключением того, что текущий посещаемый узел является файлом или папкой, и его полный путь в виде строки

IPlatformFile::FDirectoryVisitor::Visit это рекурсивная функция, вызываемая IterateDirectory… Источник движка, кажется, создает встроенный класс, подклассы которого FDirectoryVisitor и переопределяет этот метод, вот что я сделал в своем коде:

FFolderNode UDSAssetManager::GetContentTree()
{
static auto ContentPath = FPaths::ConvertRelativePathToFull(FPaths::GameContentDir());

class FFolderVisitor : public IPlatformFile::FDirectoryVisitor
{
public:
IPlatformFile& PlatformFile;

FFolderVisitor(IPlatformFile& InPlatformFile) :
PlatformFile(InPlatformFile), RootNode(nullptr), PreviousNode(nullptr),
FolderDepth(-1), PreviousDepth(-1) {};

FFolderNode *CreateRootNode(const FString& Path, const FString& Name)
{
VisitedNodes.Empty();
if (RootNode != nullptr)
delete RootNode; // TODO: Traverse entire tree, releasing memory for all child nodes

TArray<FString> SubPath;
Path.ParseIntoArray(SubPath, TEXT("/"));
if (SubPath.Num() > 0 && SubPath[SubPath.Num() - 1] == Name)
SubPath.RemoveAt(SubPath.Num() - 1);

return RootNode = new FFolderNode(FString::Join(SubPath, TEXT("/")), Name);
};

virtual bool Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory) override
{
auto Path = FString(FilenameOrDirectory);
auto Result = PlatformFile.IterateDirectory(FilenameOrDirectory, *this);

if (RootNode == nullptr)
return false;

FFolderNode *ThisNode = nullptr;
if (VisitedNodes.Num() < 1)
ThisNode = RootNode;
else
ThisNode = new FFolderNode();

auto TempPath = Path.Replace(*ContentPath, TEXT(""));
TArray<FString> PathArray;
TempPath.ParseIntoArray(PathArray, TEXT("/"));
FolderDepth = PathArray.Num();

//
// DO SOMETHING here, even though RootNode is NOT guaranteed
// to be the actual root of the tree... ?
//

PreviousNode = ThisNode;
PreviousDepth = FolderDepth;
VisitedNodes.Add(ThisNode);

return true;
};

FORCEINLINE FFolderNode GetRootNode() const {
if (RootNode == nullptr)
return FFolderNode();
return *RootNode;
};

private:
FFolderNode *RootNode;
FFolderNode *PreviousNode;
int32 FolderDepth;
int32 PreviousDepth;
TArray<FFolderNode*> VisitedNodes;
};

FFolderVisitor FolderList(FPlatformFileManager::Get().GetPlatformFile());
auto RootNode = FolderList.CreateRootNode(ContentPath, TEXT("Content"));
FolderList.PlatformFile.IterateDirectory(*ContentPath, FolderList);

return *RootNode;
}

Как правильно построить связанный список так, как движок просматривает файловые структуры?

0

Решение

Казалось бы, зовет IterateDirectory изнутри FFolderVisitor::Visit на самом деле вызывает странный порядок обхода. После создания отдельного метода для обработки инициализации корневого узла и вызова IterateDirectory вместо этого обход происходит в правильном порядке DFS.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]