admin管理员组文章数量:1435859
I'm trying to detect whether a certain path is under some blacklisted path. I've found examples in Check if an std::filesystem::path is inside a directory thread.
My example is the following (p
variables are target paths, and b
variables are blacklisted folders):
#include <iostream>
#include <vector>
#include <memory>
#include <filesystem>
int main()
{
using Path = std::filesystem::path;
Path p1 = "/folder1/file.txt";
Path b1 = "/folder1";
auto finalPath = b1 / p1;
auto [iter1, iter2] = std::mismatch(b1.begin(), b1.end(), finalPath.begin());
if( iter1 == b1.end()){
std::cout << "Yes\n"; // True
} else {
std::cout << "No\n";
}
p1 = "/folder1/file.txt";
b1 = "/folder1/";
finalPath = b1 / p1;
auto [iter3, iter4] = std::mismatch(b1.begin(), b1.end(), finalPath.begin());
if (iter3 == b1.end()) {
std::cout << "Yes\n";
} else {
std::cout << "No\n"; // False
}
return 0;
}
In this example the first comparison is true
and the second is false
. The only difference is trailing path-separator in blacklisted folder. It doesn't seem that second variant returns iterator for the first mismatched symbol. Why that?
Also one of code snippets in above-mentioned thread suggest to compare resulting first iterator to mismatched symbol with the end() - 1
iterator like so:
if (iter3 == std::prev(b1.end())) {
It may help, but cppreference says path's iterator is not necessarily a bidirectional iterator, so, if I understand it correctly, prev
may not work, and MSVC explicitly forbids that.
How to fix this code?
For brevity I assume that paths don't need to be lexically_normal
.
I'm trying to detect whether a certain path is under some blacklisted path. I've found examples in Check if an std::filesystem::path is inside a directory thread.
My example is the following (p
variables are target paths, and b
variables are blacklisted folders):
#include <iostream>
#include <vector>
#include <memory>
#include <filesystem>
int main()
{
using Path = std::filesystem::path;
Path p1 = "/folder1/file.txt";
Path b1 = "/folder1";
auto finalPath = b1 / p1;
auto [iter1, iter2] = std::mismatch(b1.begin(), b1.end(), finalPath.begin());
if( iter1 == b1.end()){
std::cout << "Yes\n"; // True
} else {
std::cout << "No\n";
}
p1 = "/folder1/file.txt";
b1 = "/folder1/";
finalPath = b1 / p1;
auto [iter3, iter4] = std::mismatch(b1.begin(), b1.end(), finalPath.begin());
if (iter3 == b1.end()) {
std::cout << "Yes\n";
} else {
std::cout << "No\n"; // False
}
return 0;
}
In this example the first comparison is true
and the second is false
. The only difference is trailing path-separator in blacklisted folder. It doesn't seem that second variant returns iterator for the first mismatched symbol. Why that?
Also one of code snippets in above-mentioned thread suggest to compare resulting first iterator to mismatched symbol with the end() - 1
iterator like so:
if (iter3 == std::prev(b1.end())) {
It may help, but cppreference says path's iterator is not necessarily a bidirectional iterator, so, if I understand it correctly, prev
may not work, and MSVC explicitly forbids that.
How to fix this code?
For brevity I assume that paths don't need to be lexically_normal
.
1 Answer
Reset to default 2It's bad practice to have "/folder1/"
with a trailing component separator, since that will make an undesirable empty final component for the path.
But if that bad practice is rampant in your code, you could trim it out of base before comparing.
bool is_subpath(std::filesystem::path const& path, std::filesystem::path base) {
if (base.filename().empty()) base = base.parent_path();
auto const& [_, base_match] = std::mismatch(path.begin(), path.end(), base.begin(), base.end());
return base_match == base.end();
}
Or use Igor's approach of iterating over the path to locate the penultimate end before the empty final component. That would allow passing base as a const&
.
本文标签: cHow does stdmismatch work with stdfilesystempathStack Overflow
版权声明:本文标题:c++ - How does std::mismatch work with std::filesystem::path - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745656381a2668731.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
finalPath
so that you see what you are using when you callstd::mismatch
. – PaulMcKenzie Commented Nov 16, 2024 at 14:46"/folder1/"
produces three elements:/
,folder1
and empty string. Iterating over"/folder1/file.txt"
doesn't have the corresponding empty string, hence the mismatch. – Igor Tandetnik Commented Nov 16, 2024 at 14:52if (iter3 == b1.end() || (iter3->empty() && std::next(iter3) == b1.end()))
– Igor Tandetnik Commented Nov 16, 2024 at 14:55lexically_relative
into service. It seems thatfinalPath
is not underb1
if and only iffinalPath.lexically_relative(b1)
starts with".."
– Igor Tandetnik Commented Nov 16, 2024 at 15:04auto finalPath = b1 / p1;
intentional? Sincep1
is an absolute path, which makes that the same asauto finalPath = p1;
. – Eljay Commented Nov 16, 2024 at 15:09