aboutsummaryrefslogtreecommitdiff
path: root/butl
diff options
context:
space:
mode:
Diffstat (limited to 'butl')
-rw-r--r--butl/buildfile1
-rw-r--r--butl/path8
-rw-r--r--butl/path.txx26
-rw-r--r--butl/process.cxx28
4 files changed, 47 insertions, 16 deletions
diff --git a/butl/buildfile b/butl/buildfile
index 5c5aae3..6e259c8 100644
--- a/butl/buildfile
+++ b/butl/buildfile
@@ -21,6 +21,7 @@ lib{butl}: \
{hxx txx }{ prefix-map } \
{hxx ixx cxx}{ process } \
{hxx cxx}{ sha256 } \
+{hxx }{ small-vector } \
{hxx txx }{ string-table } \
{hxx cxx}{ timestamp } \
{hxx cxx}{ triplet } \
diff --git a/butl/path b/butl/path
index 2a32c70..2e243ff 100644
--- a/butl/path
+++ b/butl/path
@@ -808,7 +808,11 @@ namespace butl
// Normalize the path and return *this. Normalization involves collapsing
// the '.' and '..' directories if possible, collapsing multiple
// directory separators, and converting all directory separators to the
- // canonical form.
+ // canonical form. If cur_empty is true then collapse relative paths
+ // representing the current directory (for example, '.', './', 'foo/..')
+ // to an empty path. Otherwise convert it to the canonical form (./ on
+ // POSIX systems). Note that a non-empty path cannot become an empty one
+ // in the latter case.
//
// If actual is true, then for case-insensitive filesystems obtain the
// actual spelling of the path. Only an absolute path can be actualized.
@@ -818,7 +822,7 @@ namespace butl
// etc.) are returned in their actual spelling.
//
basic_path&
- normalize (bool actual = false);
+ normalize (bool actual = false, bool cur_empty = false);
// Make the path absolute using the current directory unless it is already
// absolute. Return *this.
diff --git a/butl/path.txx b/butl/path.txx
index 5bcaea0..0cdaf5b 100644
--- a/butl/path.txx
+++ b/butl/path.txx
@@ -147,7 +147,7 @@ namespace butl
template <typename C, typename K>
basic_path<C, K>& basic_path<C, K>::
- normalize (bool actual)
+ normalize (bool actual, bool cur_empty)
{
if (empty ())
return *this;
@@ -273,12 +273,24 @@ namespace butl
p += traits::directory_separator;
}
- if (tsep && (!p.empty () || abs)) // Distinguish "/"-empty and "."-empty.
+ if (tsep)
{
if (p.empty ())
{
- p += traits::directory_separator;
- ts = -1;
+ // Distinguish "/"-empty and "."-empty.
+ //
+ if (abs)
+ {
+ p += traits::directory_separator;
+ ts = -1;
+ }
+ else if (!cur_empty) // Collapse to canonical current directory.
+ {
+ p = ".";
+ ts = 1; // Canonical separator is always first.
+ }
+ else // Collapse to empty path.
+ ts = 0;
}
else
ts = 1; // Canonical separator is always first.
@@ -313,11 +325,11 @@ namespace butl
#ifdef _WIN32
// We do not support any special Windows path name notations like in C:abc,
- // \\?\c:\abc, \\server\abc and \\?\UNC\server\abc (more about them at
- // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx).
+ // /, \, /abc, \abc, \\?\c:\abc, \\server\abc and \\?\UNC\server\abc (more
+ // about them in "Naming Files, Paths, and Namespaces" MSDN article).
//
if ((n > 2 && s[1] == ':' && s[2] != '\\' && s[2] != '/') ||
- (n > 1 && s[0] == '\\' && s[1] == '\\'))
+ (n > 0 && (s[0] == '\\' || s[0] == '/')))
{
if (exact)
return data_type ();
diff --git a/butl/process.cxx b/butl/process.cxx
index c75cfbd..cf4b26d 100644
--- a/butl/process.cxx
+++ b/butl/process.cxx
@@ -171,7 +171,7 @@ namespace butl
ep = path (move (s)); // Move back into result.
if (norm)
- ep.normalize (); //@@ NORM
+ ep.normalize ();
return exists (ep.string ().c_str ());
};
@@ -212,10 +212,17 @@ namespace butl
e = strchr (b, traits::path_separator);
// Empty path (i.e., a double colon or a colon at the beginning or end
- // of PATH) means search in the current dirrectory.
+ // of PATH) means search in the current dirrectory. Silently skip
+ // invalid paths.
//
- if (search (b, e != nullptr ? e - b : strlen (b)))
- return r;
+ try
+ {
+ if (search (b, e != nullptr ? e - b : strlen (b)))
+ return r;
+ }
+ catch (const invalid_path&)
+ {
+ }
}
// If we were given a fallback, try that.
@@ -575,10 +582,17 @@ namespace butl
e = strchr (b, traits::path_separator);
// Empty path (i.e., a double colon or a colon at the beginning or end
- // of PATH) means search in the current dirrectory.
+ // of PATH) means search in the current dirrectory. Silently skip
+ // invalid paths.
//
- if (search (b, e != nullptr ? e - b : strlen (b)))
- return r;
+ try
+ {
+ if (search (b, e != nullptr ? e - b : strlen (b)))
+ return r;
+ }
+ catch (const invalid_path&)
+ {
+ }
}
// Finally, if we were given a fallback, try that. This case is similar to