Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / filesystem / src / path.cpp
index 497f4d5..590f029 100644 (file)
@@ -7,6 +7,12 @@
 
 //  Library home page: http://www.boost.org/libs/filesystem
 
+// Include Boost.Predef first so that windows.h is guaranteed to be not included
+#include <boost/predef/os/windows.h>
+#if BOOST_OS_WINDOWS
+#include <boost/winapi/config.hpp>
+#endif
+
 //  Old standard library configurations, particularly MingGW, don't support wide strings.
 //  Report this with an explicit error message.
 #include <boost/config.hpp>
 #   error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support
 # endif
 
-// define BOOST_FILESYSTEM_SOURCE so that <boost/system/config.hpp> knows
-// the library is being built (possibly exporting rather than importing code)
-#define BOOST_FILESYSTEM_SOURCE
-
 #ifndef BOOST_SYSTEM_NO_DEPRECATED
 # define BOOST_SYSTEM_NO_DEPRECATED
 #endif
@@ -30,6 +32,7 @@
 #include <boost/assert.hpp>
 #include <algorithm>
 #include <iterator>
+#include <utility>
 #include <cstddef>
 #include <cstring>
 #include <cassert>
@@ -384,16 +387,31 @@ namespace filesystem
 
   BOOST_FILESYSTEM_DECL path path::lexically_relative(const path& base) const
   {
-    std::pair<path::iterator, path::iterator> mm
-      = detail::mismatch(begin(), end(), base.begin(), base.end());
-    if (mm.first == begin() && mm.second == base.begin())
+    path::iterator b = begin(), e = end(), base_b = base.begin(), base_e = base.end();
+    std::pair<path::iterator, path::iterator> mm = detail::mismatch(b, e, base_b, base_e);
+    if (mm.first == b && mm.second == base_b)
       return path();
-    if (mm.first == end() && mm.second == base.end())
+    if (mm.first == e && mm.second == base_e)
       return detail::dot_path();
+
+    std::ptrdiff_t n = 0;
+    for (; mm.second != base_e; ++mm.second)
+    {
+      path const& p = *mm.second;
+      if (p == detail::dot_dot_path())
+        --n;
+      else if (!p.empty() && p != detail::dot_path())
+        ++n;
+    }
+    if (n < 0)
+      return path();
+    if (n == 0 && (mm.first == e || mm.first->empty()))
+      return detail::dot_path();
+
     path tmp;
-    for (; mm.second != base.end(); ++mm.second)
+    for (; n > 0; --n)
       tmp /= detail::dot_dot_path();
-    for (; mm.first != end(); ++mm.first)
+    for (; mm.first != e; ++mm.first)
       tmp /= *mm.first;
     return tmp;
   }