| 2454 | StringRef dotdot = LiteralStringRef(".."); |
| 2455 | |
| 2456 | std::string cleanPath(std::string const& path) { |
| 2457 | std::vector<StringRef> finalParts; |
| 2458 | bool absolute = !path.empty() && path[0] == CANONICAL_PATH_SEPARATOR; |
| 2459 | |
| 2460 | StringRef p(path); |
| 2461 | |
| 2462 | while (p.size() != 0) { |
| 2463 | StringRef part = p.eat(separator); |
| 2464 | if (part.size() == 0 || (part.size() == 1 && part[0] == '.')) |
| 2465 | continue; |
| 2466 | if (part == dotdot) { |
| 2467 | if (!finalParts.empty() && finalParts.back() != dotdot) { |
| 2468 | finalParts.pop_back(); |
| 2469 | continue; |
| 2470 | } |
| 2471 | if (absolute) { |
| 2472 | continue; |
| 2473 | } |
| 2474 | } |
| 2475 | finalParts.push_back(part); |
| 2476 | } |
| 2477 | |
| 2478 | std::string result; |
| 2479 | result.reserve(PATH_MAX); |
| 2480 | if (absolute) { |
| 2481 | result.append(1, CANONICAL_PATH_SEPARATOR); |
| 2482 | } |
| 2483 | |
| 2484 | for (int i = 0; i < finalParts.size(); ++i) { |
| 2485 | if (i != 0) { |
| 2486 | result.append(1, CANONICAL_PATH_SEPARATOR); |
| 2487 | } |
| 2488 | result.append((const char*)finalParts[i].begin(), finalParts[i].size()); |
| 2489 | } |
| 2490 | |
| 2491 | return result.empty() ? "." : result; |
| 2492 | } |
| 2493 | |
| 2494 | std::string popPath(const std::string& path) { |
| 2495 | int i = path.size() - 1; |