mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-26 02:54:17 +01:00
FSC: Refactor FileTree and remove redundant path parser class
This commit is contained in:
parent
b8462cec8b
commit
1ce629126a
@ -87,17 +87,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns true if the node names match according to FSA case-insensitivity rules
|
// returns true if the node names match according to FSA case-insensitivity rules
|
||||||
bool MatchNode(sint32 index, std::string_view name) const
|
static bool MatchNodeName(std::string_view name1, std::string_view name2)
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= (sint32)m_nodes.size())
|
if (name1.size() != name2.size())
|
||||||
return false;
|
return false;
|
||||||
auto nodeName = GetNodeName(index);
|
for (size_t i = 0; i < name1.size(); i++)
|
||||||
if (nodeName.size() != name.size())
|
|
||||||
return false;
|
|
||||||
for (size_t i = 0; i < nodeName.size(); i++)
|
|
||||||
{
|
{
|
||||||
char c1 = nodeName[i];
|
char c1 = name1[i];
|
||||||
char c2 = name[i];
|
char c2 = name2[i];
|
||||||
if (c1 >= 'A' && c1 <= 'Z')
|
if (c1 >= 'A' && c1 <= 'Z')
|
||||||
c1 += ('a' - 'A');
|
c1 += ('a' - 'A');
|
||||||
if (c2 >= 'A' && c2 <= 'Z')
|
if (c2 >= 'A' && c2 <= 'Z')
|
||||||
@ -107,191 +104,18 @@ public:
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MatchNodeName(sint32 index, std::string_view name) const
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= (sint32)m_nodes.size())
|
||||||
|
return false;
|
||||||
|
auto nodeName = GetNodeName(index);
|
||||||
|
return MatchNodeName(nodeName, name);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class parsedPathW // todo - replaces this with FSCPath (using ascii/utf8 strings instead of wchar)
|
template<typename F>
|
||||||
{
|
class FSAFileTree
|
||||||
static const int MAX_NODES = 32;
|
|
||||||
|
|
||||||
public:
|
|
||||||
parsedPathW(std::wstring_view path)
|
|
||||||
{
|
|
||||||
// init vars
|
|
||||||
this->numNodes = 0;
|
|
||||||
// init parsed path data
|
|
||||||
if (path.front() == '/')
|
|
||||||
path.remove_prefix(1);
|
|
||||||
pathData.assign(path.begin(), path.end());
|
|
||||||
pathData.push_back('\0');
|
|
||||||
// start parsing
|
|
||||||
sint32 offset = 0;
|
|
||||||
sint32 startOffset = 0;
|
|
||||||
if (offset < pathData.size()-1)
|
|
||||||
{
|
|
||||||
this->nodeOffset[this->numNodes] = offset;
|
|
||||||
this->numNodes++;
|
|
||||||
}
|
|
||||||
while (offset < pathData.size() - 1)
|
|
||||||
{
|
|
||||||
if (this->pathData[offset] == '/' || this->pathData[offset] == '\\')
|
|
||||||
{
|
|
||||||
this->pathData[offset] = '\0';
|
|
||||||
offset++;
|
|
||||||
// double slashes are ignored and instead are handled like a single slash
|
|
||||||
if (this->pathData[offset] == '/' || this->pathData[offset] == '\\')
|
|
||||||
{
|
|
||||||
// if we're in the beginning and having a \\ it's a network path
|
|
||||||
if (offset != 1)
|
|
||||||
{
|
|
||||||
this->pathData[offset] = '\0';
|
|
||||||
offset++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// start new node
|
|
||||||
if (this->numNodes < MAX_NODES)
|
|
||||||
{
|
|
||||||
if (offset < pathData.size() - 1)
|
|
||||||
{
|
|
||||||
this->nodeOffset[this->numNodes] = offset;
|
|
||||||
this->numNodes++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
offset++;
|
|
||||||
}
|
|
||||||
// handle special nodes like '.' or '..'
|
|
||||||
sint32 nodeIndex = 0;
|
|
||||||
while (nodeIndex < this->numNodes)
|
|
||||||
{
|
|
||||||
if (compareNodeName(nodeIndex, L".."))
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
else if (compareNodeName(nodeIndex, L"."))
|
|
||||||
{
|
|
||||||
removeNode(nodeIndex);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
nodeIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns true if the names match (case sensitive)
|
|
||||||
bool compareNodeName(sint32 index, std::wstring_view name)
|
|
||||||
{
|
|
||||||
if (index < 0 || index >= this->numNodes)
|
|
||||||
return false;
|
|
||||||
const wchar_t* nodeName = this->pathData.data() + this->nodeOffset[index];
|
|
||||||
if (boost::iequals(nodeName, name))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool compareNodeName(std::wstring_view name1, std::wstring_view name2)
|
|
||||||
{
|
|
||||||
if (boost::iequals(name1, name2))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool compareNodeNameCaseInsensitive(std::wstring_view name1, std::wstring_view name2)
|
|
||||||
{
|
|
||||||
if (boost::iequals(name1, name2))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const wchar_t* getNodeName(sint32 index)
|
|
||||||
{
|
|
||||||
if (index < 0 || index >= this->numNodes)
|
|
||||||
return nullptr;
|
|
||||||
return this->pathData.data() + this->nodeOffset[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeNode(sint32 index)
|
|
||||||
{
|
|
||||||
if (index < 0 || index >= numNodes)
|
|
||||||
return;
|
|
||||||
numNodes--;
|
|
||||||
for (sint32 i = 0; i < numNodes; i++)
|
|
||||||
{
|
|
||||||
nodeOffset[i] = nodeOffset[i + 1];
|
|
||||||
}
|
|
||||||
// remove empty space
|
|
||||||
if (numNodes > 0)
|
|
||||||
updateOffsets(nodeOffset[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void prependNode(wchar_t* newNode)
|
|
||||||
{
|
|
||||||
if (numNodes >= MAX_NODES)
|
|
||||||
return;
|
|
||||||
sint32 len = (sint32)wcslen(newNode);
|
|
||||||
updateOffsets(-(len + 1));
|
|
||||||
numNodes++;
|
|
||||||
for (sint32 i = numNodes - 1; i >= 1; i--)
|
|
||||||
{
|
|
||||||
nodeOffset[i] = nodeOffset[i - 1];
|
|
||||||
}
|
|
||||||
nodeOffset[0] = 0;
|
|
||||||
memcpy(pathData.data() + 0, newNode, (len + 1) * sizeof(wchar_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
void buildPathString(std::wstring& pathStr, bool appendSlash = false)
|
|
||||||
{
|
|
||||||
pathStr.resize(0);
|
|
||||||
for (sint32 i = 0; i < numNodes; i++)
|
|
||||||
{
|
|
||||||
if (numNodes > 1)
|
|
||||||
pathStr.append(L"/");
|
|
||||||
pathStr.append(pathData.data() + nodeOffset[i]);
|
|
||||||
}
|
|
||||||
if(appendSlash)
|
|
||||||
pathStr.append(L"/");
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
void updateOffsets(sint32 newBaseOffset)
|
|
||||||
{
|
|
||||||
if (numNodes == 0 || newBaseOffset == 0)
|
|
||||||
return;
|
|
||||||
cemu_assert_debug(newBaseOffset <= nodeOffset[0]);
|
|
||||||
if (newBaseOffset > 0)
|
|
||||||
{
|
|
||||||
// decrease size
|
|
||||||
memmove(pathData.data(), pathData.data() + newBaseOffset, (pathData.size() - newBaseOffset) * sizeof(wchar_t));
|
|
||||||
pathData.resize(pathData.size() - newBaseOffset);
|
|
||||||
// update node offsets
|
|
||||||
for (sint32 i = 0; i < numNodes; i++)
|
|
||||||
{
|
|
||||||
nodeOffset[i] -= newBaseOffset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// increase size
|
|
||||||
newBaseOffset = -newBaseOffset;
|
|
||||||
pathData.resize(pathData.size() + newBaseOffset);
|
|
||||||
memmove(pathData.data() + newBaseOffset, pathData.data(), (pathData.size() - newBaseOffset) * sizeof(wchar_t));
|
|
||||||
// update node offsets
|
|
||||||
for (sint32 i = 0; i < numNodes; i++)
|
|
||||||
{
|
|
||||||
nodeOffset[i] += newBaseOffset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
//std::wstring pathData;
|
|
||||||
std::vector<wchar_t> pathData;
|
|
||||||
sint32 nodeOffset[MAX_NODES + 1];
|
|
||||||
|
|
||||||
public:
|
|
||||||
sint32 numNodes;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename F, bool isCaseSensitive>
|
|
||||||
class FileTree
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -303,27 +127,27 @@ private:
|
|||||||
NODETYPE_FILE,
|
NODETYPE_FILE,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _node_t
|
struct node_t
|
||||||
{
|
{
|
||||||
std::wstring name;
|
std::string name;
|
||||||
std::vector<_node_t*> subnodes;
|
std::vector<node_t*> subnodes;
|
||||||
F* custom;
|
F* custom;
|
||||||
NODETYPE type;
|
NODETYPE type;
|
||||||
}node_t;
|
};
|
||||||
|
|
||||||
node_t* getByNodePath(parsedPathW& p, sint32 numNodes, bool createAsDirectories)
|
node_t* getByNodePath(FSCPath& p, sint32 numNodes, bool createAsDirectories)
|
||||||
{
|
{
|
||||||
node_t* currentNode = &rootNode;
|
node_t* currentNode = &rootNode;
|
||||||
for (sint32 i = 0; i < numNodes; i++)
|
for (sint32 i = 0; i < numNodes; i++)
|
||||||
{
|
{
|
||||||
// find subnode by path
|
// find subnode by path
|
||||||
node_t* foundSubnode = getSubnode(currentNode, p.getNodeName(i));
|
node_t* foundSubnode = getSubnode(currentNode, p.GetNodeName(i));
|
||||||
if (foundSubnode == nullptr)
|
if (foundSubnode == nullptr)
|
||||||
{
|
{
|
||||||
// no subnode found -> create new directory node (if requested)
|
// no subnode found -> create new directory node (if requested)
|
||||||
if (createAsDirectories == false)
|
if (createAsDirectories == false)
|
||||||
return nullptr; // path not found
|
return nullptr; // path not found
|
||||||
currentNode = newNode(currentNode, NODETYPE_DIRECTORY, p.getNodeName(i));
|
currentNode = newNode(currentNode, NODETYPE_DIRECTORY, p.GetNodeName(i));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -333,28 +157,20 @@ private:
|
|||||||
return currentNode;
|
return currentNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
node_t* getSubnode(node_t* parentNode, std::wstring_view name)
|
node_t* getSubnode(node_t* parentNode, std::string_view name)
|
||||||
{
|
{
|
||||||
for (auto& sn : parentNode->subnodes)
|
for (auto& sn : parentNode->subnodes)
|
||||||
{
|
{
|
||||||
if constexpr (isCaseSensitive)
|
if (FSCPath::MatchNodeName(sn->name, name))
|
||||||
{
|
|
||||||
if (parsedPathW::compareNodeName(sn->name.c_str(), name))
|
|
||||||
return sn;
|
return sn;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if (parsedPathW::compareNodeNameCaseInsensitive(sn->name.c_str(), name))
|
|
||||||
return sn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
node_t* newNode(node_t* parentNode, NODETYPE type, std::wstring_view name)
|
node_t* newNode(node_t* parentNode, NODETYPE type, std::string_view name)
|
||||||
{
|
{
|
||||||
node_t* newNode = new node_t;
|
node_t* newNode = new node_t;
|
||||||
newNode->name = std::wstring(name);
|
newNode->name.assign(name);
|
||||||
newNode->type = type;
|
newNode->type = type;
|
||||||
newNode->custom = nullptr;
|
newNode->custom = nullptr;
|
||||||
parentNode->subnodes.push_back(newNode);
|
parentNode->subnodes.push_back(newNode);
|
||||||
@ -362,32 +178,32 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FileTree()
|
FSAFileTree()
|
||||||
{
|
{
|
||||||
rootNode.type = NODETYPE_DIRECTORY;
|
rootNode.type = NODETYPE_DIRECTORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool addFile(const wchar_t* path, F* custom)
|
bool addFile(std::string_view path, F* custom)
|
||||||
{
|
{
|
||||||
parsedPathW p(path);
|
FSCPath p(path);
|
||||||
if (p.numNodes == 0)
|
if (p.GetNodeCount() == 0)
|
||||||
return false;
|
return false;
|
||||||
node_t* directoryNode = getByNodePath(p, p.numNodes - 1, true);
|
node_t* directoryNode = getByNodePath(p, p.GetNodeCount() - 1, true);
|
||||||
// check if a node with same name already exists
|
// check if a node with same name already exists
|
||||||
if (getSubnode(directoryNode, p.getNodeName(p.numNodes - 1)) != nullptr)
|
if (getSubnode(directoryNode, p.GetNodeName(p.GetNodeCount() - 1)) != nullptr)
|
||||||
return false; // node already exists
|
return false; // node already exists
|
||||||
// add file node
|
// add file node
|
||||||
node_t* fileNode = newNode(directoryNode, NODETYPE_FILE, p.getNodeName(p.numNodes - 1));
|
node_t* fileNode = newNode(directoryNode, NODETYPE_FILE, p.GetNodeName(p.GetNodeCount() - 1));
|
||||||
fileNode->custom = custom;
|
fileNode->custom = custom;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getFile(std::wstring_view path, F* &custom)
|
bool getFile(std::string_view path, F* &custom)
|
||||||
{
|
{
|
||||||
parsedPathW p(path);
|
FSCPath p(path);
|
||||||
if (p.numNodes == 0)
|
if (p.GetNodeCount() == 0)
|
||||||
return false;
|
return false;
|
||||||
node_t* node = getByNodePath(p, p.numNodes, false);
|
node_t* node = getByNodePath(p, p.GetNodeCount(), false);
|
||||||
if (node == nullptr)
|
if (node == nullptr)
|
||||||
return false;
|
return false;
|
||||||
if (node->type != NODETYPE_FILE)
|
if (node->type != NODETYPE_FILE)
|
||||||
@ -396,16 +212,16 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool removeFile(std::wstring_view path)
|
bool removeFile(std::string_view path)
|
||||||
{
|
{
|
||||||
parsedPathW p(path);
|
FSCPath p(path);
|
||||||
if (p.numNodes == 0)
|
if (p.GetNodeCount() == 0)
|
||||||
return false;
|
return false;
|
||||||
node_t* directoryNode = getByNodePath(p, p.numNodes - 1, false);
|
node_t* directoryNode = getByNodePath(p, p.GetNodeCount() - 1, false);
|
||||||
if (directoryNode == nullptr)
|
if (directoryNode == nullptr)
|
||||||
return false;
|
return false;
|
||||||
// find node
|
// find node
|
||||||
node_t* fileNode = getSubnode(directoryNode, p.getNodeName(p.numNodes - 1));
|
node_t* fileNode = getSubnode(directoryNode, p.GetNodeName(p.GetNodeCount() - 1));
|
||||||
if (fileNode == nullptr)
|
if (fileNode == nullptr)
|
||||||
return false;
|
return false;
|
||||||
if (fileNode->type != NODETYPE_FILE)
|
if (fileNode->type != NODETYPE_FILE)
|
||||||
@ -423,10 +239,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename TFunc>
|
template<typename TFunc>
|
||||||
bool listDirectory(const wchar_t* path, TFunc fn)
|
bool listDirectory(std::string_view path, TFunc fn)
|
||||||
{
|
{
|
||||||
parsedPathW p(path);
|
FSCPath p(path);
|
||||||
node_t* node = getByNodePath(p, p.numNodes, false);
|
node_t* node = getByNodePath(p, p.GetNodeCount(), false);
|
||||||
if (node == nullptr)
|
if (node == nullptr)
|
||||||
return false;
|
return false;
|
||||||
if (node->type != NODETYPE_DIRECTORY)
|
if (node->type != NODETYPE_DIRECTORY)
|
||||||
@ -454,28 +270,28 @@ static void FSTPathUnitTest()
|
|||||||
// test 1
|
// test 1
|
||||||
FSCPath p1("/vol/content");
|
FSCPath p1("/vol/content");
|
||||||
cemu_assert_debug(p1.GetNodeCount() == 2);
|
cemu_assert_debug(p1.GetNodeCount() == 2);
|
||||||
cemu_assert_debug(p1.MatchNode(0, "tst") == false);
|
cemu_assert_debug(p1.MatchNodeName(0, "tst") == false);
|
||||||
cemu_assert_debug(p1.MatchNode(0, "vol"));
|
cemu_assert_debug(p1.MatchNodeName(0, "vol"));
|
||||||
cemu_assert_debug(p1.MatchNode(1, "CONTENT"));
|
cemu_assert_debug(p1.MatchNodeName(1, "CONTENT"));
|
||||||
// test 2
|
// test 2
|
||||||
FSCPath p2("/vol/content/");
|
FSCPath p2("/vol/content/");
|
||||||
cemu_assert_debug(p2.GetNodeCount() == 2);
|
cemu_assert_debug(p2.GetNodeCount() == 2);
|
||||||
cemu_assert_debug(p2.MatchNode(0, "vol"));
|
cemu_assert_debug(p2.MatchNodeName(0, "vol"));
|
||||||
cemu_assert_debug(p2.MatchNode(1, "content"));
|
cemu_assert_debug(p2.MatchNodeName(1, "content"));
|
||||||
// test 3
|
// test 3
|
||||||
FSCPath p3("/vol//content/\\/");
|
FSCPath p3("/vol//content/\\/");
|
||||||
cemu_assert_debug(p3.GetNodeCount() == 2);
|
cemu_assert_debug(p3.GetNodeCount() == 2);
|
||||||
cemu_assert_debug(p3.MatchNode(0, "vol"));
|
cemu_assert_debug(p3.MatchNodeName(0, "vol"));
|
||||||
cemu_assert_debug(p3.MatchNode(1, "content"));
|
cemu_assert_debug(p3.MatchNodeName(1, "content"));
|
||||||
// test 4
|
// test 4
|
||||||
FSCPath p4("vol/content/");
|
FSCPath p4("vol/content/");
|
||||||
cemu_assert_debug(p4.GetNodeCount() == 2);
|
cemu_assert_debug(p4.GetNodeCount() == 2);
|
||||||
// test 5
|
// test 5
|
||||||
FSCPath p5("/vol/content/test.bin");
|
FSCPath p5("/vol/content/test.bin");
|
||||||
cemu_assert_debug(p5.GetNodeCount() == 3);
|
cemu_assert_debug(p5.GetNodeCount() == 3);
|
||||||
cemu_assert_debug(p5.MatchNode(0, "vol"));
|
cemu_assert_debug(p5.MatchNodeName(0, "vol"));
|
||||||
cemu_assert_debug(p5.MatchNode(1, "content"));
|
cemu_assert_debug(p5.MatchNodeName(1, "content"));
|
||||||
cemu_assert_debug(p5.MatchNode(2, "TEST.BIN"));
|
cemu_assert_debug(p5.MatchNodeName(2, "TEST.BIN"));
|
||||||
// test 6 - empty paths
|
// test 6 - empty paths
|
||||||
FSCPath p6("");
|
FSCPath p6("");
|
||||||
cemu_assert_debug(p6.GetNodeCount() == 0);
|
cemu_assert_debug(p6.GetNodeCount() == 0);
|
||||||
|
@ -86,7 +86,7 @@ FSCMountPathNode* fsc_createMountPath(const FSCPath& mountPath, sint32 priority)
|
|||||||
FSCMountPathNode* nodeSub = nullptr; // set if we found a subnode with a matching name, else this is used to store the new nodes
|
FSCMountPathNode* nodeSub = nullptr; // set if we found a subnode with a matching name, else this is used to store the new nodes
|
||||||
for (auto& nodeItr : nodeParent->subnodes)
|
for (auto& nodeItr : nodeParent->subnodes)
|
||||||
{
|
{
|
||||||
if (mountPath.MatchNode(i, nodeItr->path))
|
if (mountPath.MatchNodeName(i, nodeItr->path))
|
||||||
{
|
{
|
||||||
// subnode found
|
// subnode found
|
||||||
nodeSub = nodeItr;
|
nodeSub = nodeItr;
|
||||||
@ -195,7 +195,7 @@ bool fsc_lookupPath(const char* path, std::wstring& devicePathOut, fscDeviceC**
|
|||||||
FSCMountPathNode* nodeSub = nullptr;
|
FSCMountPathNode* nodeSub = nullptr;
|
||||||
for(auto& nodeItr : nodeParent->subnodes)
|
for(auto& nodeItr : nodeParent->subnodes)
|
||||||
{
|
{
|
||||||
if (parsedPath.MatchNode(i, nodeItr->path))
|
if (parsedPath.MatchNodeName(i, nodeItr->path))
|
||||||
{
|
{
|
||||||
nodeSub = nodeItr;
|
nodeSub = nodeItr;
|
||||||
break;
|
break;
|
||||||
@ -246,7 +246,7 @@ FSCMountPathNode* fsc_lookupPathVirtualNode(const char* path, sint32 priority)
|
|||||||
FSCMountPathNode* nodeSub = nullptr;
|
FSCMountPathNode* nodeSub = nullptr;
|
||||||
for (auto& nodeItr : nodeCurrentDir->subnodes)
|
for (auto& nodeItr : nodeCurrentDir->subnodes)
|
||||||
{
|
{
|
||||||
if (parsedPath.MatchNode(i, nodeItr->path))
|
if (parsedPath.MatchNodeName(i, nodeItr->path))
|
||||||
{
|
{
|
||||||
nodeSub = nodeItr;
|
nodeSub = nodeItr;
|
||||||
break;
|
break;
|
||||||
|
@ -9,23 +9,22 @@ struct RedirectEntry
|
|||||||
sint32 priority;
|
sint32 priority;
|
||||||
};
|
};
|
||||||
|
|
||||||
FileTree<RedirectEntry, false> redirectTree;
|
FSAFileTree<RedirectEntry> redirectTree;
|
||||||
|
|
||||||
void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& targetFilePath, sint32 priority)
|
void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& targetFilePath, sint32 priority)
|
||||||
{
|
{
|
||||||
std::wstring virtualSourcePathW = boost::nowide::widen(std::string(virtualSourcePath));
|
|
||||||
// check if source already has a redirection
|
// check if source already has a redirection
|
||||||
RedirectEntry* existingEntry;
|
RedirectEntry* existingEntry;
|
||||||
if (redirectTree.getFile(virtualSourcePathW, existingEntry))
|
if (redirectTree.getFile(virtualSourcePath, existingEntry))
|
||||||
{
|
{
|
||||||
if (existingEntry->priority >= priority)
|
if (existingEntry->priority >= priority)
|
||||||
return; // dont replace entries with equal or higher priority
|
return; // dont replace entries with equal or higher priority
|
||||||
// unregister existing entry
|
// unregister existing entry
|
||||||
redirectTree.removeFile(virtualSourcePathW.c_str());
|
redirectTree.removeFile(virtualSourcePath);
|
||||||
delete existingEntry;
|
delete existingEntry;
|
||||||
}
|
}
|
||||||
RedirectEntry* entry = new RedirectEntry(targetFilePath, priority);
|
RedirectEntry* entry = new RedirectEntry(targetFilePath, priority);
|
||||||
redirectTree.addFile(virtualSourcePathW.c_str(), entry);
|
redirectTree.addFile(virtualSourcePath, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
class fscDeviceTypeRedirect : public fscDeviceC
|
class fscDeviceTypeRedirect : public fscDeviceC
|
||||||
@ -33,7 +32,8 @@ class fscDeviceTypeRedirect : public fscDeviceC
|
|||||||
FSCVirtualFile* fscDeviceOpenByPath(std::wstring_view pathW, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override
|
FSCVirtualFile* fscDeviceOpenByPath(std::wstring_view pathW, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override
|
||||||
{
|
{
|
||||||
RedirectEntry* redirectionEntry;
|
RedirectEntry* redirectionEntry;
|
||||||
if (redirectTree.getFile(pathW, redirectionEntry))
|
std::string pathTmp = boost::nowide::narrow(pathW);
|
||||||
|
if (redirectTree.getFile(pathTmp, redirectionEntry))
|
||||||
return FSCVirtualFile_Host::OpenFile(redirectionEntry->dstPath, accessFlags, *fscStatus);
|
return FSCVirtualFile_Host::OpenFile(redirectionEntry->dstPath, accessFlags, *fscStatus);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user