| 247 | } |
| 248 | |
| 249 | path path::lexically_relative(const path& base) const { |
| 250 | { // perform root-name/root-directory mismatch checks |
| 251 | auto PP = PathParser::CreateBegin(__pn_); |
| 252 | auto PPBase = PathParser::CreateBegin(base.__pn_); |
| 253 | auto CheckIterMismatchAtBase = [&]() { |
| 254 | return PP.State_ != PPBase.State_ && (PP.inRootPath() || PPBase.inRootPath()); |
| 255 | }; |
| 256 | if (PP.inRootName() && PPBase.inRootName()) { |
| 257 | if (*PP != *PPBase) |
| 258 | return {}; |
| 259 | } else if (CheckIterMismatchAtBase()) |
| 260 | return {}; |
| 261 | |
| 262 | if (PP.inRootPath()) |
| 263 | ++PP; |
| 264 | if (PPBase.inRootPath()) |
| 265 | ++PPBase; |
| 266 | if (CheckIterMismatchAtBase()) |
| 267 | return {}; |
| 268 | } |
| 269 | |
| 270 | // Find the first mismatching element |
| 271 | auto PP = PathParser::CreateBegin(__pn_); |
| 272 | auto PPBase = PathParser::CreateBegin(base.__pn_); |
| 273 | while (PP && PPBase && PP.State_ == PPBase.State_ && (*PP == *PPBase || PP.inRootDir())) { |
| 274 | ++PP; |
| 275 | ++PPBase; |
| 276 | } |
| 277 | |
| 278 | // If there is no mismatch, return ".". |
| 279 | if (!PP && !PPBase) |
| 280 | return "."; |
| 281 | |
| 282 | // Otherwise, determine the number of elements, 'n', which are not dot or |
| 283 | // dot-dot minus the number of dot-dot elements. |
| 284 | int ElemCount = DetermineLexicalElementCount(PPBase); |
| 285 | if (ElemCount < 0) |
| 286 | return {}; |
| 287 | |
| 288 | // if n == 0 and (a == end() || a->empty()), returns path("."); otherwise |
| 289 | if (ElemCount == 0 && (PP.atEnd() || *PP == PATHSTR(""))) |
| 290 | return PATHSTR("."); |
| 291 | |
| 292 | // return a path constructed with 'n' dot-dot elements, followed by the |
| 293 | // elements of '*this' after the mismatch. |
| 294 | path Result; |
| 295 | // FIXME: Reserve enough room in Result that it won't have to re-allocate. |
| 296 | while (ElemCount--) |
| 297 | Result /= PATHSTR(".."); |
| 298 | for (; PP; ++PP) |
| 299 | Result /= *PP; |
| 300 | return Result; |
| 301 | } |
| 302 | |
| 303 | //////////////////////////////////////////////////////////////////////////// |
| 304 | // path.comparisons |
no test coverage detected