From 542f355853fcae25e788c4514fe57494200797ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schu=CC=88mann?= Date: Sat, 11 Jul 2026 18:29:40 +0200 Subject: [PATCH] lexically_normal() preserves IPv6 components in device UNC paths (#170) --- README.md | 2 ++ include/ghc/filesystem.hpp | 7 ++++++- test/filesystem_test.cpp | 8 ++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 64e079e..fb3ef3c 100644 --- a/README.md +++ b/README.md @@ -653,6 +653,8 @@ to the expected behavior. support, with iteration errors terminating the process. * Fix for [#191](https://github.com/gulrak/filesystem/issues/191), appending to a host-only UNC path now inserts the missing separator. +* Fix for [#170](https://github.com/gulrak/filesystem/issues/170), + `lexically_normal()` now preserves IPv6 components in device UNC paths. * Fix for [#185](https://github.com/gulrak/filesystem/issues/185), `lexically_normal()` now preserves unresolved parent components in relative paths. diff --git a/include/ghc/filesystem.hpp b/include/ghc/filesystem.hpp index 70e21b7..463cf4f 100644 --- a/include/ghc/filesystem.hpp +++ b/include/ghc/filesystem.hpp @@ -3290,7 +3290,12 @@ GHC_INLINE path path::lexically_normal() const } } if (!(s.empty() && lastDotDot)) { - dest /= s; + if (dest.has_relative_path()) { + dest.append_name(s.c_str()); + } + else { + dest /= s; + } } lastDotDot = s == ".."; } diff --git a/test/filesystem_test.cpp b/test/filesystem_test.cpp index 9502882..f95506f 100644 --- a/test/filesystem_test.cpp +++ b/test/filesystem_test.cpp @@ -972,6 +972,14 @@ TEST_CASE("fs.path.gen - path generation", "[filesystem][path][fs.path.gen]") CHECK(fs::path("a/b/..\\//..///\\/../c\\\\/").lexically_normal() == "../c/"); CHECK(fs::path("..a/b/..\\//..///\\/../c\\\\/").lexically_normal() == "../c/"); CHECK(fs::path("..\\").lexically_normal() == ".."); + CHECK(fs::path("//?/UNC/::1/c$/foo").lexically_normal() == R"(\\?\UNC\::1\c$\foo)"); + CHECK(fs::path(R"(\\?\UNC\a::1\c$\foo)").lexically_normal() == R"(\\?\UNC\a::1\c$\foo)"); + CHECK(fs::path(R"(\\?\UNC\fe80::1\c$\foo)").lexically_normal() == R"(\\?\UNC\fe80::1\c$\foo)"); + CHECK(fs::path(R"(\\?\UNC\server\share\foo)").lexically_normal() == R"(\\?\UNC\server\share\foo)"); + CHECK(fs::path(R"(\\server\share\foo)").lexically_normal() == R"(\\server\share\foo)"); + CHECK(fs::path(R"(\\?\C:\foo\..\bar)").lexically_normal() == R"(\\?\C:\bar)"); + CHECK(fs::path(R"(\??\C:\foo\..\bar)").lexically_normal() == R"(\??\C:\bar)"); + CHECK(fs::path(R"(C:foo\..\bar)").lexically_normal() == R"(C:bar)"); #endif // lexically_relative()