| 266 | |
| 267 | template <class Policy> |
| 268 | Control Impl<Policy>::ResolveRoot(Root root) |
| 269 | { |
| 270 | if (root == Root::None) { |
| 271 | return this->ResolveRelativePath(); |
| 272 | } |
| 273 | |
| 274 | // POSIX absolute paths always start with a '/'. |
| 275 | std::string::size_type root_slash = 0; |
| 276 | |
| 277 | #ifdef _WIN32 |
| 278 | if (root == Root::Drive) { |
| 279 | if (P.size() == 2 || P[2] != '/') { |
| 280 | return this->ResolveRootRelative(); |
| 281 | } |
| 282 | |
| 283 | if (Policy::ActualCase == Options::ActualCase::Yes) { |
| 284 | // Normalize the drive letter to upper-case. |
| 285 | P[0] = static_cast<char>(cmsysString_toupper(P[0])); |
| 286 | } |
| 287 | |
| 288 | // The root is a drive letter. The root '/' immediately follows. |
| 289 | root_slash = 2; |
| 290 | } else if (root == Root::Network) { |
| 291 | // The root is a network name. Find the root '/' after it. |
| 292 | root_slash = P.find('/', 2); |
| 293 | if (root_slash == std::string::npos) { |
| 294 | root_slash = P.size(); |
| 295 | P.push_back('/'); |
| 296 | } |
| 297 | } |
| 298 | #endif |
| 299 | |
| 300 | if (Policy::Existence == Options::Existence::Required |
| 301 | #ifdef _WIN32 |
| 302 | && root != Root::Network |
| 303 | #endif |
| 304 | ) { |
| 305 | std::string path = P.substr(0, root_slash + 1); |
| 306 | if (!this->OS.PathExists(path)) { |
| 307 | P = std::move(path); |
| 308 | return Control::Error(cmsys::Status::POSIX(ENOENT)); |
| 309 | } |
| 310 | } |
| 311 | |
| 312 | return Control::Continue(root_slash); |
| 313 | } |
| 314 | |
| 315 | template <class Policy> |
| 316 | Control Impl<Policy>::ResolveComponent(Root root, |
no test coverage detected