* [PATCH] Fix handling of POSIX paths containing a root-name
@ 2018-12-13 20:35 Jonathan Wakely
0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2018-12-13 20:35 UTC (permalink / raw)
To: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 1049 bytes --]
Fix path appending and concatenating to work correctly for a leading
root-name. Check a new macro, SLASHSLASH_IS_ROOT_NAME, instead of making
the behaviour depend directly on __CYGWIN__.
* src/filesystem/std-path.cc (SLASHSLASH_IS_ROOT_NAME): New macro to
control whether interpret paths with two slashes as a root-name.
(path::operator/=(const path&)) [SLASHSLASH_IS_ROOT_NAME]: Add a
root-directory when appending to a root-name.
(path::_M_append(basic_string_view<value_type>))
[SLASHSLASH_IS_ROOT_NAME]: Likewise.
(path::operator/=(const path&)) [SLASHSLASH_IS_ROOT_NAME]: Likewise.
(path::_M_concat(basic_string_view<value_type>))
[SLASHSLASH_IS_ROOT_NAME]: Likewise.
(path::lexically_normal()) [SLASHSLASH_IS_ROOT_NAME]: Use += instead
of /= to add a root-directory to the result.
* testsuite/27_io/filesystem/path/decompose/root_directory.cc: Fix
expected result for Cygwin.
Tested x86_64-linux, as committed, and also with the new
SLASHSLASH_IS_ROOT_NAME macro defined to test that version of the
code.
Committed to trunk.
[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 8480 bytes --]
commit b15b89d09ec824a42c897851d9efe2405e92fb69
Author: redi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Thu Dec 13 20:34:10 2018 +0000
Fix handling of POSIX paths containing a root-name
Fix path appending and concatenating to work correctly for a leading
root-name. Check a new macro, SLASHSLASH_IS_ROOT_NAME, instead of making
the behaviour depend directly on __CYGWIN__.
* src/filesystem/std-path.cc (SLASHSLASH_IS_ROOT_NAME): New macro to
control whether interpret paths with two slashes as a root-name.
(path::operator/=(const path&)) [SLASHSLASH_IS_ROOT_NAME]: Add a
root-directory when appending to a root-name.
(path::_M_append(basic_string_view<value_type>))
[SLASHSLASH_IS_ROOT_NAME]: Likewise.
(path::operator/=(const path&)) [SLASHSLASH_IS_ROOT_NAME]: Likewise.
(path::_M_concat(basic_string_view<value_type>))
[SLASHSLASH_IS_ROOT_NAME]: Likewise.
(path::lexically_normal()) [SLASHSLASH_IS_ROOT_NAME]: Use += instead
of /= to add a root-directory to the result.
* testsuite/27_io/filesystem/path/decompose/root_directory.cc: Fix
expected result for Cygwin.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@267107 138bc75d-0d04-0410-961f-82ee72b054a4
diff --git a/libstdc++-v3/src/filesystem/std-path.cc b/libstdc++-v3/src/filesystem/std-path.cc
index e9c78924b8e..d2520492c03 100644
--- a/libstdc++-v3/src/filesystem/std-path.cc
+++ b/libstdc++-v3/src/filesystem/std-path.cc
@@ -26,6 +26,11 @@
# define _GLIBCXX_USE_CXX11_ABI 1
#endif
+#ifdef __CYGWIN__
+// Interpret "//x" as a root-name, not root-dir + filename
+# define SLASHSLASH_IS_ROOTNAME 1
+#endif
+
#include <filesystem>
#include <algorithm>
#include <bits/stl_uninitialized.h>
@@ -70,7 +75,7 @@ struct path::_Parser
// look for root name or root directory
if (is_dir_sep(input[0]))
{
-#ifdef __CYGWIN__
+#if SLASHSLASH_IS_ROOTNAME
// look for root name, such as "//foo"
if (len > 2 && input[1] == input[0])
{
@@ -515,7 +520,7 @@ path::operator/=(const path& __p)
string_view_type sep;
if (has_filename())
sep = { &preferred_separator, 1 }; // need to add a separator
-#ifdef __CYGWIN__
+#if SLASHSLASH_IS_ROOTNAME
else if (_M_type() == _Type::_Root_name) // root-name with no root-dir
sep = { &preferred_separator, 1 }; // need to add a separator
#endif
@@ -535,6 +540,10 @@ path::operator/=(const path& __p)
capacity += __p._M_cmpts.size();
else if (!__p.empty() || !sep.empty())
capacity += 1;
+#if SLASHSLASH_IS_ROOTNAME
+ if (orig_type == _Type::_Root_name)
+ ++capacity; // Need to insert root-directory after root-name
+#endif
if (orig_type == _Type::_Multi)
{
@@ -568,6 +577,14 @@ path::operator/=(const path& __p)
string_view_type s(_M_pathname.data(), orig_pathlen);
::new(output++) _Cmpt(s, orig_type, 0);
++_M_cmpts._M_impl->_M_size;
+#if SLASHSLASH_IS_ROOTNAME
+ if (orig_type == _Type::_Root_name)
+ {
+ ::new(output++) _Cmpt(sep, _Type::_Root_dir,
+ orig_pathlen + sep.length());
+ ++_M_cmpts._M_impl->_M_size;
+ }
+#endif
}
if (__p._M_type() == _Type::_Multi)
@@ -668,7 +685,7 @@ path::_M_append(basic_string_view<value_type> s)
basic_string_view<value_type> sep;
if (has_filename())
sep = { &preferred_separator, 1 }; // need to add a separator
-#ifdef __CYGWIN__
+#if SLASHSLASH_IS_ROOTNAME
else if (_M_type() == _Type::_Root_name) // root-name with no root-dir
sep = { &preferred_separator, 1 }; // need to add a separator
#endif
@@ -723,6 +740,11 @@ path::_M_append(basic_string_view<value_type> s)
else if (!sep.empty())
++capacity;
+#if SLASHSLASH_IS_ROOTNAME
+ if (orig_type == _Type::_Root_name)
+ ++capacity; // Need to insert root-directory after root-name
+#endif
+
__try
{
_M_cmpts.type(_Type::_Multi);
@@ -740,6 +762,15 @@ path::_M_append(basic_string_view<value_type> s)
// Create single component from original path
::new(output++) _Cmpt(orig_pathname, orig_type, 0);
++_M_cmpts._M_impl->_M_size;
+
+#if SLASHSLASH_IS_ROOTNAME
+ if (!sep.empty() && orig_type == _Type::_Root_name)
+ {
+ ::new(output++) _Cmpt(sep, _Type::_Root_dir,
+ orig_pathlen + sep.length());
+ ++_M_cmpts._M_impl->_M_size;
+ }
+#endif
}
if (next != buf.begin())
@@ -823,7 +854,11 @@ path::operator+=(const path& p)
{
// See if there's a filename or root-name at the end of the original path
// that we can add to.
- if (_M_type() == _Type::_Filename)
+ if (_M_type() == _Type::_Filename
+#if SLASHSLASH_IS_ROOTNAME
+ || _M_type() == _Type::_Root_name
+#endif
+ )
{
if (p._M_type() == _Type::_Filename)
{
@@ -858,8 +893,6 @@ path::operator+=(const path& p)
&& _M_cmpts.back()._M_type() == _Type::_Filename)
orig_filenamelen = 0; // current path has empty filename at end
- // TODO handle "//rootname" + "foo" case for Cygwin.
-
int capacity = 0;
if (_M_type() == _Type::_Multi)
capacity += _M_cmpts.size();
@@ -884,6 +917,16 @@ path::operator+=(const path& p)
ptr->_M_pathname.reserve(_M_pathname.length() + extra.length());
ptr->_M_pathname = _M_pathname;
ptr->_M_pathname += extra;
+
+#if SLASHSLASH_IS_ROOTNAME
+ if (orig_type == _Type::_Root_name)
+ {
+ basic_string_view<value_type> s(p._M_pathname);
+ ::new(output++) _Cmpt(s.substr(extra.length(), 1),
+ _Type::_Root_dir, orig_pathlen + extra.length());
+ ++_M_cmpts._M_impl->_M_size;
+ }
+#endif
}
else if (orig_filenamelen == 0 && it != last)
{
@@ -895,7 +938,7 @@ path::operator+=(const path& p)
{
basic_string_view<value_type> s = it->_M_pathname;
auto pos = orig_pathlen;
-#ifdef __CYGWIN__
+#if SLASHSLASH_IS_ROOTNAME
s.remove_prefix(2);
pos += 2;
#endif
@@ -999,7 +1042,11 @@ path::_M_concat(basic_string_view<value_type> s)
{
// See if there's a filename or root-name at the end of the original path
// that we can add to.
- if (_M_type() == _Type::_Filename)
+ if (_M_type() == _Type::_Filename
+#if SLASHSLASH_IS_ROOTNAME
+ || _M_type() == _Type::_Root_name
+#endif
+ )
{
if (cmpt.str.length() == s.length())
{
@@ -1031,9 +1078,6 @@ path::_M_concat(basic_string_view<value_type> s)
&& _M_cmpts.back()._M_type() == _Type::_Filename)
orig_filenamelen = 0; // original path had empty filename at end
-
- // TODO handle "//rootname" + "foo" case for Cygwin.
-
std::array<_Parser::cmpt, 64> buf;
auto next = buf.begin();
@@ -1065,6 +1109,11 @@ path::_M_concat(basic_string_view<value_type> s)
if (is_dir_sep(s.back()))
++capacity;
+#if SLASHSLASH_IS_ROOTNAME
+ if (orig_type == _Type::_Root_name)
+ ++capacity; // Need to insert root-directory after root-name
+#endif
+
__try
{
_M_cmpts.type(_Type::_Multi);
@@ -1080,6 +1129,15 @@ path::_M_concat(basic_string_view<value_type> s)
p->_M_pathname.reserve(orig_pathname.length() + extra.length());
p->_M_pathname = orig_pathname;
p->_M_pathname += extra;
+
+#if SLASHSLASH_IS_ROOTNAME
+ if (orig_type == _Type::_Root_name)
+ {
+ ::new(output++) _Cmpt(s.substr(extra.length(), 1),
+ _Type::_Root_dir, orig_pathlen + extra.length());
+ ++_M_cmpts._M_impl->_M_size;
+ }
+#endif
}
else if (orig_filenamelen == 0)
{
@@ -1532,6 +1590,10 @@ path::lexically_normal() const
}
else if (is_dot(p))
ret /= path();
+#if SLASHSLASH_IS_ROOTNAME
+ else if (p._M_type() == _Type::_Root_dir)
+ ret += '/'; // using operator/=('/') would replace whole of ret
+#endif
else
ret /= p;
}
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_directory.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_directory.cc
index da5f377de94..40af1551eeb 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_directory.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_directory.cc
@@ -35,7 +35,11 @@ test01()
path p2 = "/foo/bar";
VERIFY( p2.root_directory() == path("/") );
path p3 = "//foo";
+#ifdef __CYGWIN__
+ VERIFY( p3.root_directory() == path() );
+#else
VERIFY( p3.root_directory() == path("/") );
+#endif
path p4 = "///foo";
VERIFY( p4.root_directory() == path("/") );
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2018-12-13 20:35 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-13 20:35 [PATCH] Fix handling of POSIX paths containing a root-name Jonathan Wakely
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).