/
Boxapp
/
yadisk-helper
Обзор
Документация
Войти
/
Boxapp
/
yadisk-helper
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
path.cpp
173 строки
5 KB
DebianCougar
test build 2026.02-beta
30 янв 2026, 21:25
30 янв 2026, 21:25
eb3551d
Код
Авторство
О чём код?
#include <set> #include <string> #include <vector> #include "finder.hpp" #include "path.hpp" using std::min; using std::set; using std::string; using std::vector; enum PathsRel { EQUAL, PARENT, CHILD, DIFFER }; // FIXME path starting with '/' is ignored by Yandex Disk static vector<string> pathToBlocks(const string &path) { vector<string> dirs; // '.' is skipped, '..' drops last item, '..' beyond '/' is ignored string last; for (char c : path) { if (c == '/') { if (last.empty()) continue; // just skip '//' or leading '/' else if (last == ".") last.clear(); // skip and clear '.' else if (last == "..") { // go up if not at '/' if (!dirs.empty()) dirs.pop_back(); last.clear(); } else { dirs.push_back(last); last.clear(); } } else last.push_back(c); } if (last == "..") { if (!dirs.empty()) dirs.pop_back(); } else if (!last.empty() && last != ".") dirs.push_back(last); return dirs; } static string blocksToPath(const vector<string> &blocks) { string res; if (blocks.empty()) return "/"; for (const string &dir : blocks) res += '/' + dir; return res; } static string canonical(const string &path) { return blocksToPath(pathToBlocks(path)); } static vector<string> recurse(const string &prefix, Mode mode, const string &token, const vector<string> &excl_list) { switch (mode) { case EXCLUDE: return {}; case INCLUDE: return {prefix}; case PARTIAL: { vector<string> res; vector<string> sub = contents(prefix, token); for (const string &subpath : sub) { string sp = prefix + (prefix.back() == '/' ? "" : "/") + subpath; bool pex = false, spex = false; // path excluded, subpath excluded for (const string &excl : excl_list) { if (excl == sp) { pex = true; break; } else if (excl.substr(0, sp.size()) == sp) spex = true; } Mode smod = INCLUDE; if (pex) smod = EXCLUDE; else if (spex) smod = PARTIAL; vector<string> sres = recurse(sp, smod, token, excl_list); for (const string &path : sres) res.push_back(path); } return res; } } return {}; } static PathsRel comparePaths(const string &path1, const string &path2) { vector<string> b1 = pathToBlocks(path1), b2 = pathToBlocks(path2); size_t s1 = b1.size(), s2 = b2.size(); for (size_t i = 0; i < min(s1, s2); ++i) { if (b1[i] != b2[i]) return DIFFER; } if (s1 > s2) return CHILD; if (s1 < s2) return PARENT; return EQUAL; } vector<string> toExcludeDirs(const vector<string> &include_dirs, const string &token) { if (include_dirs.empty()) return {"/"}; vector<string> incl_list; for (const string &path : include_dirs) { string canp = canonical(path); if (canp == "/") return {}; incl_list.push_back(canp); // FIXME remove duplicates } return recurse("/", PARTIAL, token, incl_list); } vector<string> toIncludeDirs(const vector<string> &exclude_dirs, const string &token) { return toExcludeDirs(exclude_dirs, token); } Mode included(const vector<string> &incl_list, const string &path) { Mode res = EXCLUDE; for (const string &p : incl_list) switch (comparePaths(p, path)) { case CHILD: res = PARTIAL; case DIFFER: break; default: return INCLUDE; } return res; } vector<string> plus(const vector<string> &incl_list, const string &path) { set<string> acc; bool haspath = false; for (const string &p : incl_list) switch (comparePaths(p, path)) { case CHILD: acc.insert(path); haspath = true; break; case DIFFER: acc.insert(p); break; case EQUAL: acc.insert(path); haspath = true; break; case PARENT: acc.insert(p); haspath = true; } if (!haspath) acc.insert(path); vector<string> res; for (const string &p : acc) res.push_back(p); return res; } vector<string> minus(const vector<string> &incl_list, const string &path, const string &token) { set<string> acc; for (const string &p : incl_list) switch (comparePaths(p, path)) { case CHILD: case EQUAL: break; case DIFFER: acc.insert(p); break; case PARENT: for (const string &rem : recurse(p, PARTIAL, token, {path})) acc.insert(rem); } vector<string> res; for (const string &p : acc) res.push_back(p); return res; } string filePath(const string &dir, const string &file) { vector<string> blocks = pathToBlocks(dir); blocks.push_back(file); return blocksToPath(blocks); } string parentDir(const string &path) { vector<string> blocks = pathToBlocks(path); if (!blocks.empty()) blocks.pop_back(); return blocksToPath(blocks); } string onlyName(const string &path) { vector<string> blocks = pathToBlocks(path); if (blocks.empty()) return ""; return blocks.back(); }