Elides "/." and "/.." tokens from path.
| 393 | } |
| 394 | // Elides "/." and "/.." tokens from path. |
| 395 | inline std::string path_simplify(const std::string& path) { |
| 396 | std::vector<std::string> dirs; |
| 397 | std::string cur_dir; |
| 398 | bool after_slash = false; |
| 399 | for (int i = 0; i < (int)path.size(); ++i) { |
| 400 | if (path[i] == '/') { |
| 401 | if (after_slash) continue; // Ignore repeat slashes |
| 402 | after_slash = true; |
| 403 | if (cur_dir == ".." && !dirs.empty() && dirs.back() != "..") { |
| 404 | if (dirs.size() == 1 && dirs.front().empty()) { |
| 405 | throw std::runtime_error( |
| 406 | "Invalid path: back-traversals exceed depth of absolute path"); |
| 407 | } |
| 408 | dirs.pop_back(); |
| 409 | } else if (cur_dir != ".") { // Ignore /./ |
| 410 | dirs.push_back(cur_dir); |
| 411 | } |
| 412 | cur_dir.clear(); |
| 413 | } else { |
| 414 | after_slash = false; |
| 415 | cur_dir.push_back(path[i]); |
| 416 | } |
| 417 | } |
| 418 | if (!after_slash) { |
| 419 | dirs.push_back(cur_dir); |
| 420 | } |
| 421 | std::stringstream ss; |
| 422 | for (int i = 0; i < (int)dirs.size() - 1; ++i) { |
| 423 | ss << dirs[i] << "/"; |
| 424 | } |
| 425 | if (!dirs.empty()) ss << dirs.back(); |
| 426 | if (after_slash) ss << "/"; |
| 427 | return ss.str(); |
| 428 | } |
| 429 | inline unsigned long long hash_larson64(const char* s, |
| 430 | unsigned long long seed = 0) { |
| 431 | unsigned long long hash = seed; |