| 273 | } |
| 274 | |
| 275 | std::string cleanPath(std::string const& path) { |
| 276 | std::vector<std::string> finalParts; |
| 277 | bool absolute = !path.empty() && path[0] == CANONICAL_PATH_SEPARATOR; |
| 278 | |
| 279 | int i = 0; |
| 280 | while (i < path.size()) { |
| 281 | int sep = path.find((char)CANONICAL_PATH_SEPARATOR, i); |
| 282 | if (sep == path.npos) { |
| 283 | sep = path.size(); |
| 284 | } |
| 285 | std::string part = path.substr(i, sep - i); |
| 286 | i = sep + 1; |
| 287 | if (part.size() == 0 || (part.size() == 1 && part[0] == '.')) |
| 288 | continue; |
| 289 | if (part == "..") { |
| 290 | if (!finalParts.empty() && finalParts.back() != "..") { |
| 291 | finalParts.pop_back(); |
| 292 | continue; |
| 293 | } |
| 294 | if (absolute) { |
| 295 | continue; |
| 296 | } |
| 297 | } |
| 298 | finalParts.push_back(part); |
| 299 | } |
| 300 | |
| 301 | std::string result; |
| 302 | result.reserve(PATH_MAX); |
| 303 | if (absolute) { |
| 304 | result.append(1, CANONICAL_PATH_SEPARATOR); |
| 305 | } |
| 306 | |
| 307 | for (int i = 0; i < finalParts.size(); ++i) { |
| 308 | if (i != 0) { |
| 309 | result.append(1, CANONICAL_PATH_SEPARATOR); |
| 310 | } |
| 311 | result.append(finalParts[i]); |
| 312 | } |
| 313 | |
| 314 | return result.empty() ? "." : result; |
| 315 | } |
| 316 | |
| 317 | // Removes the last component from a path string (if possible) and returns the result with one trailing separator. |
| 318 | std::string popPath(const std::string& path) { |