|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r74851 - in branches/release: boost boost/filesystem boost/filesystem/v3 libs/filesystem libs/filesystem/v3/doc libs/filesystem/v3/src libs/filesystem/v3/test libs/filesystem/v3/test/msvc10
From: bdawes_at_[hidden]
Date: 2011-10-09 09:54:10
Author: bemandawes
Date: 2011-10-09 09:54:09 EDT (Sun, 09 Oct 2011)
New Revision: 74851
URL: http://svn.boost.org/trac/boost/changeset/74851
Log:
Merge trunk, including hash and canonical support
Added:
branches/release/libs/filesystem/v3/test/locale_info.cpp
- copied unchanged from r74850, /trunk/libs/filesystem/v3/test/locale_info.cpp
Properties modified:
branches/release/boost/filesystem/ (props changed)
branches/release/boost/filesystem.hpp (props changed)
branches/release/libs/filesystem/ (props changed)
Text files modified:
branches/release/boost/filesystem/v3/operations.hpp | 15 ++++
branches/release/boost/filesystem/v3/path.hpp | 18 ++++
branches/release/libs/filesystem/v3/doc/reference.html | 122 ++++++++++++++++++++++++++--------
branches/release/libs/filesystem/v3/doc/release_history.html | 22 ++++++
branches/release/libs/filesystem/v3/src/operations.cpp | 84 ++++++++++++++++++++++++
branches/release/libs/filesystem/v3/test/msvc10/filesystem-v3.sln | 2
branches/release/libs/filesystem/v3/test/operations_test.cpp | 138 ++++++++++++++++++++++++++++-----------
branches/release/libs/filesystem/v3/test/path_unit_test.cpp | 7 ++
8 files changed, 333 insertions(+), 75 deletions(-)
Modified: branches/release/boost/filesystem/v3/operations.hpp
==============================================================================
--- branches/release/boost/filesystem/v3/operations.hpp (original)
+++ branches/release/boost/filesystem/v3/operations.hpp 2011-10-09 09:54:09 EDT (Sun, 09 Oct 2011)
@@ -142,6 +142,8 @@
BOOST_FILESYSTEM_DECL
path initial_path(system::error_code* ec=0);
BOOST_FILESYSTEM_DECL
+ path canonical(const path& p, const path& base, system::error_code* ec=0);
+ BOOST_FILESYSTEM_DECL
void copy(const path& from, const path& to, system::error_code* ec=0);
BOOST_FILESYSTEM_DECL
void copy_directory(const path& from, const path& to, system::error_code* ec=0);
@@ -268,7 +270,17 @@
path absolute(const path& p, const path& base=current_path());
// If base.is_absolute(), throws nothing. Thus no need for ec argument
-# ifndef BOOST_FILESYSTEM_NO_DEPRECATED
+ inline
+ path canonical(const path& p, const path& base=current_path())
+ {return detail::canonical(p, base);}
+ inline
+ path canonical(const path& p, system::error_code& ec)
+ {return detail::canonical(p, current_path(), &ec);}
+ inline
+ path canonical(const path& p, const path& base, system::error_code& ec)
+ {return detail::canonical(p, base, &ec);}
+
+ # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
inline
path complete(const path& p)
{
@@ -990,6 +1002,7 @@
{
using filesystem3::absolute;
using filesystem3::block_file;
+ using filesystem3::canonical;
using filesystem3::character_file;
// using filesystem3::copy;
using filesystem3::copy_file;
Modified: branches/release/boost/filesystem/v3/path.hpp
==============================================================================
--- branches/release/boost/filesystem/v3/path.hpp (original)
+++ branches/release/boost/filesystem/v3/path.hpp 2011-10-09 09:54:09 EDT (Sun, 09 Oct 2011)
@@ -29,6 +29,7 @@
#include <boost/shared_ptr.hpp>
#include <boost/io/detail/quoted_manip.hpp>
#include <boost/static_assert.hpp>
+#include <boost/functional/hash_fwd.hpp>
#include <string>
#include <iterator>
#include <cstring>
@@ -559,18 +560,31 @@
const path::value_type* l(lhs.c_str());
while ((*l == *rhs || (*l == L'\\' && *rhs == L'/') || (*l == L'/' && *rhs == L'\\'))
&& *l) { ++l; ++rhs; }
- return *l == *rhs || (*l == L'\\' && *rhs == L'/') || (*l == L'/' && *rhs == L'\\');
+ return *l == *rhs;
}
inline bool operator==(const path& lhs, const path& rhs) { return lhs == rhs.c_str(); }
inline bool operator==(const path& lhs, const path::string_type& rhs) { return lhs == rhs.c_str(); }
inline bool operator==(const path::string_type& lhs, const path& rhs) { return rhs == lhs.c_str(); }
inline bool operator==(const path::value_type* lhs, const path& rhs) { return rhs == lhs; }
+
+ inline std::size_t hash_value(const path& x)
+ {
+ std::size_t seed = 0;
+ for(const path::value_type* it = x.c_str(); *it; ++it)
+ hash_combine(seed, *it == '/' ? L'\\' : *it);
+ return seed;
+ }
# else // BOOST_POSIX_API
inline bool operator==(const path& lhs, const path& rhs) { return lhs.native() == rhs.native(); }
inline bool operator==(const path& lhs, const path::string_type& rhs) { return lhs.native() == rhs; }
inline bool operator==(const path& lhs, const path::value_type* rhs) { return lhs.native() == rhs; }
inline bool operator==(const path::string_type& lhs, const path& rhs) { return lhs == rhs.native(); }
inline bool operator==(const path::value_type* lhs, const path& rhs) { return lhs == rhs.native(); }
+
+ inline std::size_t hash_value(const path& x)
+ {
+ return hash_range(x.native().begin(), x.native().end());
+ }
# endif
inline bool operator!=(const path& lhs, const path& rhs) { return !(lhs == rhs); }
@@ -592,7 +606,7 @@
operator<<(std::basic_ostream<Char, Traits>& os, const path& p)
{
return os
- << boost::io::quoted(p.string<std::basic_string<Char> >(), static_cast<Char>('&'));
+ << boost::io::quoted(p.template string<std::basic_string<Char> >(), static_cast<Char>('&'));
}
template <class Char, class Traits>
Modified: branches/release/libs/filesystem/v3/doc/reference.html
==============================================================================
--- branches/release/libs/filesystem/v3/doc/reference.html (original)
+++ branches/release/libs/filesystem/v3/doc/reference.html 2011-10-09 09:54:09 EDT (Sun, 09 Oct 2011)
@@ -8,6 +8,15 @@
<title>Filesystem V3 Reference
</title>
<link rel="stylesheet" type="text/css" href="../../../../doc/src/minimal.css">
+<style type="text/css">
+ pre {background-color:#D7EEFF}
+ body
+ {
+ font-family: sans-serif;
+ max-width : 8.5in;
+ margin: 1em;
+ }
+</style>
</head>
<body>
@@ -50,7 +59,7 @@
<a href="#Definitions">Definitions</a><br>
<a href="#Conformance">Conformance</a><br>
<a href="#Header-filesystem-synopsis">
- Header <filesystem> synopsis</a><br>
+ Header <boost/filesystem.hpp> synopsis</a><br>
<a href="#Error-reporting">Error reporting</a><br>
<a href="#class-path">Class path</a><br>
path constructors<br>
@@ -89,6 +98,7 @@
<a href="#Operational-functions">
Operational functions</a><br>
  absolute<br>
+ canonical<br>
copy<br>
copy_directory<br>
copy_file<br>
@@ -158,11 +168,13 @@
\</code>,<code> /</code>, and<code> |</code> <i>--end note]</i></p>
</blockquote>
<p><b><i><a name="Path">Path</a>:</i></b> A sequence of elements that identify
-a location within a filesystem. The elements are the <i>root-name<sub>opt</sub></i>, <i>
+the location of a file within a filesystem. The elements are the <i>root-name<sub>opt</sub></i>, <i>
root-directory<sub>opt</sub></i>, and an optional sequence of filenames. [<i>Note:</i>
A pathname is the concrete representation of a path. <i>--end note</i>]</p>
-<p><b><i><a name="Absolute-path">Absolute path</a>:</i></b> A path that uniquely
-identifies a file. The format is implementation defined. </p>
+<p><b><i><a name="Absolute-path">Absolute path</a>:</i></b> A path that
+unambiguously
+identifies the location of a file within a filesystem without reference to an
+additional starting location. The format is implementation defined. </p>
<blockquote>
<p><i>[Note:</i> For POSIX-like implementations, including<b> </b>Unix
variants, Linux, and Mac OS X, only paths
@@ -173,9 +185,13 @@
specifier followed by a slash, or begin with two slashes, are absolute paths. <i>--end
note]</i></p>
</blockquote>
-<p><b><a name="Relative-path">Relative path</a>:</b> A path that uniquely
-identifies a file only when considered relative to some other path. [<i>Note:</i>
+<p><b><a name="Relative-path">Relative path</a>:</b> A path that only
+unambiguously
+identifies the location of a file within a filesystem when resolved relative to
+a starting location. The format is implementation defined. [<i>Note:</i>
Paths "." and ".." are considered to be relative paths. <i>--end note</i>]</p>
+<p><b><a name="Canonical-path">Canonical path</a>:</b> An absolute path that has
+no elements which are symbolic links, and no dot or dot dot elements.</p>
<p><i><b><a name="Pathname">Pathname</a>:</b> </i>A character string that represents a
path. Pathnames are formatted according to the generic pathname format or the
native pathname format.</p>
@@ -288,7 +304,7 @@
is unreasonable for a program to detect them prior to calling the function. <i>
-- end note</i>]</p>
</blockquote>
-<h2><a name="Header-filesystem-synopsis">Header <code><boost/filesystem></code> synopsis</a></h2>
+<h2><a name="Header-filesystem-synopsis">Header <code><boost/filesystem.hpp></code> synopsis</a></h2>
<pre> namespace boost
{
namespace filesystem
@@ -298,6 +314,7 @@
void swap(path& lhs, path& rhs);
bool lexicographical_compare(path::iterator first1, path::iterator last1,
path::iterator first2, path::iterator last2);
+ std::size_t hash_value(const path& p);
bool operator==(const path& lhs, const path& rhs);
bool operator!=(const path& lhs, const path& rhs);
@@ -354,6 +371,10 @@
path absolute(const path& p, const path& base=current_path());
+ path canonical(const path& p, const path& base = current_path());
+ path canonical(const path& p, system::error_code& ec);
+ path canonical(const path& p, const path& base, system::error_code& ec);
+
void copy(const path& from, const path& to);
void copy(const path& from, const path& to, system::error_code& ec);
@@ -736,7 +757,7 @@
<h3> <a name="path-constructors"> <code>
<font size="4">path</font></code> constructors</a></h3>
-<pre>path();</pre>
+<pre><span style="background-color: #D7EEFF">path();</span></pre>
<blockquote>
<p><i>Postcondition:</i> <code>empty()</code>.</p>
</blockquote>
@@ -987,7 +1008,7 @@
<p><i>Returns:</i> <code>empty() ? path() : *--end()</code></p>
<p>[<i>Example:</i></p>
<blockquote>
- <pre><code>std::cout << path("/foo/bar.txt").filename();</code> // outputs "<code>bar.txt</code>" (without the quotes)</pre>
+ <pre><code>std::cout << path("/foo/bar.txt").filename();</code> // outputs "<code>bar.txt</code>"</pre>
</blockquote>
<p> <i>--end example</i>]</p>
</blockquote>
@@ -1001,8 +1022,8 @@
p.filename()</code>.</p>
<p>[<i>Example:</i></p>
<blockquote>
- <pre><code>std::cout << path("/foo/bar.txt").stem();</code> // outputs "<code>bar</code>" (without the quotes)</pre>
- <pre>path p = "foo.bar.baz.tar";
+ <pre><code>std::cout << path("/foo/bar.txt").stem();</code> // outputs "<code>bar</code>"
+path p = "foo.bar.baz.tar";
for (; !p.extension().empty(); p = p.stem())
std::cout << p.extension() << '\n';
// outputs: .tar
@@ -1023,7 +1044,7 @@
as alternate data streams or partitioned dataset names.</p>
<p>[<i>Example:</i></p>
<blockquote>
- <pre><code>std::cout << path("/foo/bar.txt").extension(); //</code> outputs "<code>.txt</code>" (without the quotes)</pre>
+ <pre><code>std::cout << path("/foo/bar.txt").extension(); //</code> outputs "<code>.txt</code>"</pre>
</blockquote>
<p> <i>--end example</i>]</p>
<p>[<i>Note:<b> </b></i>The dot is included in the return value so that
@@ -1175,6 +1196,14 @@
due to the <code>path</code> iterator's value type itself being <code>path</code>.
<i>--end note</i>]</p>
</blockquote>
+<pre>std::size_t <a name="hash_value">hash_value</a> (const path& p);</pre>
+<blockquote>
+ <p><i>Returns:</i> A hash value for the path <code>p</code>. If
+ for two paths, <code>p1 == p2</code> then
+ <code>hash_value(p1) == hash_value(p2)</code>.</p>
+ <p>This allows paths to be used with
+ Boost.Hash.</p>
+</blockquote>
<pre>bool operator< (const path& lhs, const path& rhs);</pre>
<blockquote>
<p><i>Returns:</i> <code>return lexicographical_compare(lhs.begin(), lhs.end(),
@@ -1226,7 +1255,8 @@
to ensure that paths with embedded spaces will round trip correctly. Ampersand (<code>&</code>)
is used as an escape character, so the path can itself contain double quotes.</p>
<pre>template <class Char, class Traits>
-std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os, const path& p)
+std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os,
+ const path& p)
</pre>
<blockquote>
<p><i>Effects:</i>
@@ -1236,7 +1266,8 @@
<code>os</code></p>
</blockquote>
<pre>template <class Char, class Traits>
-inline std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& is, path& p)
+inline std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& is,
+ path& p)
</pre>
<blockquote>
<p><i>Effects: </i>
@@ -1258,9 +1289,12 @@
public:
filesystem_error();
filesystem_error(const filesystem_error&);
- filesystem_error(const std::string& what_arg, system::error_code ec);
- filesystem_error(const std::string& what_arg, const path& p1, system::error_code ec);
- filesystem_error(const std::string& what_arg, const path& p1, const path& p2, system::error_code ec);
+ filesystem_error(const std::string& what_arg,
+ system::error_code ec);
+ filesystem_error(const std::string& what_arg,
+ const path& p1, system::error_code ec);
+ filesystem_error(const std::string& what_arg,
+ const path& p1, const path& p2, system::error_code ec);
filesystem_error& filesystem_error(const filesystem_error&);
~filesystem_error();
@@ -1385,6 +1419,7 @@
string.</p>
</blockquote>
<h3><a name="Class-directory_entry">Class <code>directory_entry</code></a></h3>
+<div dir="ltr">
<pre> namespace boost
{
namespace filesystem
@@ -1396,13 +1431,16 @@
// constructors and destructor
directory_entry();
directory_entry(const directory_entry&);
- explicit directory_entry(const path_type& p, file_status st=file_status(), file_status symlink_st=file_status());
+ explicit directory_entry(const path_type& p, file_status st=file_status(),
+ file_status symlink_st=file_status());
~directory_entry();
// modifiers
directory_entry& operator=(const directory_entry&);
- void assign(const path_type& p, file_status st=file_status(), file_status symlink_st=file_status());
- void replace_filename(const path& p, file_status st=file_status(), file_status symlink_st=file_status());
+ void assign(const path_type& p, file_status st=file_status(),
+ file_status symlink_st=file_status());
+ void replace_filename(const path& p, file_status st=file_status(),
+ file_status symlink_st=file_status());
// observers
const path& path() const;
@@ -1426,6 +1464,7 @@
} // namespace filesystem
} // namespace boost</pre>
+</div>
<p>A <code>directory_entry</code> object stores a <code>path object</code>,
a <code>file_status</code> object for non-symbolic link status, and a <code>
file_status</code> object for symbolic link status. The <code>file_status</code>
@@ -1943,7 +1982,7 @@
<h4><a name="Function-specifications">Operational function specifications</a></h4>
<pre>path <a name="absolute">absolute</a>(const path& p, const path& base=current_path());</pre>
<blockquote>
- <p><i>Returns:</i> A path composed according to to the
+ <p><i>Returns:</i> A absolute path composed according to the
following table</p>
<table border="1" cellpadding="5" cellspacing="0" bordercolor="#111111" style="border-collapse: collapse">
<tr>
@@ -1965,11 +2004,31 @@
<td align="center"><code>return absolute(base) / p</code></td>
</tr>
</table>
- <p><i>Postcondition:</i> For the returned path, <code>rp,</code> <code>
- rp.is_absolute()</code> is true.</p>
+ <p dir="ltr">[<i>Note:</i> For the returned path, <code>rp,</code> <code>
+ rp.is_absolute()</code> is true. <i>-- end note</i>]</p>
<p><i>Throws:</i> If <code>base.is_absolute()</code> is true, throws only if
memory allocation fails.</p>
</blockquote>
+<pre>path <a name="canonical">canonical</a>(const path& p, const path& base = current_path());
+path canonical(const path& p, system::error_code& ec);
+path canonical(const path& p, const path& base, system::error_code& ec);</pre>
+<blockquote>
+<p><i>Overview:</i> Converts <code>p</code>, which must exist, to an absolute
+path that has no symbolic link, dot,
+or dot-dot elements. </p>
+<p><i>Returns:</i> A canonical path that refers to
+the same file system object as <code>absolute(p,base)</code>. For the overload
+without a <code>base</code> argument, <code>base</code> is <code>current_path()</code>.</p>
+ <p><i>Throws:</i> As specified in
+ <a href="#Error-reporting">
+ Error reporting</a>.</p>
+
+ <p><i>Remarks:</i> <code>!exists(p)</code> is an error.</p>
+
+ <p>[<i>Note:</i> Canonical pathnames allow security checking of a path (eg.
+ does this path live in /home/goodguy or /home/badguy?) -- end note]</p>
+
+</blockquote>
<pre>void <a name="copy">copy</a>(const path& from, const path& to);
void copy(const path& from, const path& to, system::error_code& ec);</pre>
<blockquote>
@@ -3236,7 +3295,7 @@
<p>The Windows API has many functions that also have Unicode versions to permit
an extended-length path for a maximum total path length of 32,767 characters.
... To specify an extended-length path, use the <b>"\\?\" prefix</b>. For
-example, "\\?\D:\very long path".
+example, "\\?\D:\very long path".
<i>[C++ string literals require backslashes be doubled, of course.]</i></p>
</blockquote>
<p>Because most Boost.Filesystem operational functions just pass the contents of
@@ -3271,12 +3330,14 @@
Witt were particularly helpful in refining the library.</p>
<p>The create_directories, extension, basename, and replace_extension functions
were developed by Vladimir Prus. The temp_directory_path function was
-contributed by Jeff Flinn.</p>
+contributed by Jeff Flinn. David Svoboda suggested the canonical function and
+provided psuedo-code.</p>
<p>Howard Hinnant and John Maddock reviewed a draft of the version 2 proposal, and
identified a number of mistakes or weaknesses, resulting in a more polished
final document.</p>
<p>Peter Dimov suggested a single class path, with member templates to adapt to
multiple string types. His idea became the basis for the version 3 path design.</p>
+<p> </p>
<h2><a name="References">References</a></h2>
<table border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="100%">
<tr>
@@ -3298,11 +3359,12 @@
</tr>
</table>
<hr>
-<p>© Copyright Beman Dawes, 2002, 2006, 2007, 2009, 2010</p>
-<p>Distributed under the Boost Software License, Version 1.0. See
-www.boost.org/LICENSE_1_0.txt</p>
-<p>Revised
-<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->12 April 2011<!--webbot bot="Timestamp" endspan i-checksum="28281" --></p>
+<p><font size="2">© Copyright Beman Dawes, 2002, 2006, 2007, 2009, 2010, 2011</font></p>
+<p><font size="2">Distributed under the Boost Software License, Version 1.0. See
+</font>
+www.boost.org/LICENSE_1_0.txt</p>
+<p><font size="2">Revised
+<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->06 October 2011<!--webbot bot="Timestamp" endspan i-checksum="32189" --></font></p>
</body>
Modified: branches/release/libs/filesystem/v3/doc/release_history.html
==============================================================================
--- branches/release/libs/filesystem/v3/doc/release_history.html (original)
+++ branches/release/libs/filesystem/v3/doc/release_history.html 2011-10-09 09:54:09 EDT (Sun, 09 Oct 2011)
@@ -36,6 +36,22 @@
</tr>
</table>
+<h2>1.48.0</h2>
+<ul>
+ <li>Added operational function canonical(),
+ suggested by David Svoboda, who also provided pseudo-code.</li>
+ <li>Added hash_value() function for
+ paths. (Daniel James)</li>
+ <li>Fix path inserter problem (#5764)
+ reported for QNX6.3.2 host (gcc-3.3.5)</li>
+ <li>Fix problem of locale("") exception being thrown before main() starts on
+ poorly configured (e.g. LANG="bad name") POSIX systems. Resolves the most
+ serious aspect of tickets
+ #4688,
+ #5100,
+ #5289.</li>
+</ul>
+
<h2>1.47.0</h2>
<ul>
<li>Program file_status.cpp added (V3). See boost-root/libs/filesystem/v3/example.
@@ -46,6 +62,10 @@
<h2>1.46.1</h2>
+<ul>
+ <li>Fix fstream problem for STLPort masquerading as Dinkumware (#5217).</li>
+</ul>
+
<h2>1.46.0</h2>
<ul>
<li>Version 3 of the library is now the default.</li>
@@ -68,7 +88,7 @@
</ul>
<hr>
<p>Revised
-<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->31 May, 2011<!--webbot bot="Timestamp" endspan i-checksum="13963" --></p>
+<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->03 October, 2011<!--webbot bot="Timestamp" endspan i-checksum="38359" --></p>
<p>© Copyright Beman Dawes, 2011</p>
<p> Use, modification, and distribution are subject to the Boost Software
License, Version 1.0. See <a href="http://www.boost.org/LICENSE_1_0.txt">
Modified: branches/release/libs/filesystem/v3/src/operations.cpp
==============================================================================
--- branches/release/libs/filesystem/v3/src/operations.cpp (original)
+++ branches/release/libs/filesystem/v3/src/operations.cpp 2011-10-09 09:54:09 EDT (Sun, 09 Oct 2011)
@@ -77,6 +77,8 @@
# ifdef BOOST_POSIX_API
+ const fs::path dot_path(".");
+ const fs::path dot_dot_path("..");
# include <sys/types.h>
# if !defined(__APPLE__) && !defined(__OpenBSD__)
# include <sys/statvfs.h>
@@ -98,6 +100,8 @@
# else // BOOST_WINDOW_API
+ const fs::path dot_path(L".");
+ const fs::path dot_dot_path(L"..");
# if (defined(__MINGW32__) || defined(__CYGWIN__)) && !defined(WINVER)
// Versions of MinGW or Cygwin that support Filesystem V3 support at least WINVER 0x501.
// See MinGW's windef.h
@@ -752,6 +756,86 @@
}
BOOST_FILESYSTEM_DECL
+ path canonical(const path& p, const path& base, system::error_code* ec)
+ {
+ path source (p.is_absolute() ? p : absolute(p, base));
+ path result;
+
+ system::error_code local_ec;
+ file_status stat (status(source, local_ec));
+
+ if (stat.type() == fs::file_not_found)
+ {
+ if (ec == 0)
+ BOOST_FILESYSTEM_THROW(filesystem_error(
+ "boost::filesystem::canonical", source,
+ error_code(system::errc::no_such_file_or_directory, system::generic_category())));
+ ec->assign(system::errc::no_such_file_or_directory, system::generic_category());
+ return result;
+ }
+ else if (local_ec)
+ {
+ if (ec == 0)
+ BOOST_FILESYSTEM_THROW(filesystem_error(
+ "boost::filesystem::canonical", source, local_ec));
+ *ec = local_ec;
+ return result;
+ }
+
+ bool scan (true);
+ while (scan)
+ {
+ scan = false;
+ result.clear();
+ for (path::iterator itr = source.begin(); itr != source.end(); ++itr)
+ {
+ if (*itr == dot_path)
+ continue;
+ if (*itr == dot_dot_path)
+ {
+ result.remove_filename();
+ continue;
+ }
+
+ result /= *itr;
+
+ bool is_sym (is_symlink(detail::symlink_status(result, ec)));
+ if (ec && *ec)
+ return path();
+
+ if (is_sym)
+ {
+ path link(detail::read_symlink(result, ec));
+ if (ec && *ec)
+ return path();
+ result.remove_filename();
+
+ if (link.is_absolute())
+ {
+ for (++itr; itr != source.end(); ++itr)
+ link /= *itr;
+ source = link;
+ }
+ else // link is relative
+ {
+ path new_source(result);
+ new_source /= link;
+ for (++itr; itr != source.end(); ++itr)
+ new_source /= *itr;
+ source = new_source;
+ }
+ scan = true; // symlink causes scan to be restarted
+ break;
+ }
+ }
+ }
+ if (ec != 0)
+ ec->clear();
+ BOOST_ASSERT_MSG(result.is_absolute(), "canonical() implementation error; please report");
+ return result;
+ }
+
+ BOOST_FILESYSTEM_DECL
void copy(const path& from, const path& to, system::error_code* ec)
{
file_status s(symlink_status(from, *ec));
Modified: branches/release/libs/filesystem/v3/test/msvc10/filesystem-v3.sln
==============================================================================
--- branches/release/libs/filesystem/v3/test/msvc10/filesystem-v3.sln (original)
+++ branches/release/libs/filesystem/v3/test/msvc10/filesystem-v3.sln 2011-10-09 09:54:09 EDT (Sun, 09 Oct 2011)
@@ -132,7 +132,9 @@
{256EA89A-E073-4CE8-B675-BE2FBC6B2691}.Release|Win32.ActiveCfg = Release|Win32
{256EA89A-E073-4CE8-B675-BE2FBC6B2691}.Release|Win32.Build.0 = Release|Win32
{FC5C770F-3017-4021-8DAF-C5DCA3FDF005}.Debug|Win32.ActiveCfg = Debug|Win32
+ {FC5C770F-3017-4021-8DAF-C5DCA3FDF005}.Debug|Win32.Build.0 = Debug|Win32
{FC5C770F-3017-4021-8DAF-C5DCA3FDF005}.Release|Win32.ActiveCfg = Release|Win32
+ {FC5C770F-3017-4021-8DAF-C5DCA3FDF005}.Release|Win32.Build.0 = Release|Win32
{5C9B3380-3C6E-45CC-986A-16D245E27E58}.Debug|Win32.ActiveCfg = Debug|Win32
{5C9B3380-3C6E-45CC-986A-16D245E27E58}.Debug|Win32.Build.0 = Debug|Win32
{5C9B3380-3C6E-45CC-986A-16D245E27E58}.Release|Win32.ActiveCfg = Release|Win32
Modified: branches/release/libs/filesystem/v3/test/operations_test.cpp
==============================================================================
--- branches/release/libs/filesystem/v3/test/operations_test.cpp (original)
+++ branches/release/libs/filesystem/v3/test/operations_test.cpp 2011-10-09 09:54:09 EDT (Sun, 09 Oct 2011)
@@ -388,45 +388,46 @@
void create_tree()
{
+ cout << "creating test directories and files in " << dir << endl;
- // create directory d1
- BOOST_TEST(!fs::create_directory(dir));
- BOOST_TEST(!fs::is_symlink(dir));
- BOOST_TEST(!fs::is_symlink("nosuchfileordirectory"));
- d1 = dir / "d1";
- BOOST_TEST(fs::create_directory(d1));
- BOOST_TEST(fs::exists(d1));
- BOOST_TEST(fs::is_directory(d1));
- BOOST_TEST(fs::is_empty(d1));
-
- // create an empty file named "d1f1"
- d1f1 = d1 / "d1f1";
- create_file(d1f1, "");
- BOOST_TEST(fs::exists(d1f1));
- BOOST_TEST(!fs::is_directory(d1f1));
- BOOST_TEST(fs::is_regular_file(d1f1));
- BOOST_TEST(fs::is_empty(d1f1));
- BOOST_TEST(fs::file_size(d1f1) == 0);
- BOOST_TEST(fs::hard_link_count(d1f1) == 1);
-
- // create an empty file named "f0"
- f0 = dir / "f0";
- create_file(f0, "");
- BOOST_TEST(fs::exists(f0));
- BOOST_TEST(!fs::is_directory(f0));
- BOOST_TEST(fs::is_regular_file(f0));
- BOOST_TEST(fs::is_empty(f0));
- BOOST_TEST(fs::file_size(f0) == 0);
- BOOST_TEST(fs::hard_link_count(f0) == 1);
-
- // create a file named "f1"
- f1 = dir / "f1";
- create_file(f1, "file-f1");
- BOOST_TEST(fs::exists(f1));
- BOOST_TEST(!fs::is_directory(f1));
- BOOST_TEST(fs::is_regular_file(f1));
- BOOST_TEST(fs::file_size(f1) == 7);
- verify_file(f1, "file-f1");
+ // create directory d1
+ BOOST_TEST(!fs::create_directory(dir));
+ BOOST_TEST(!fs::is_symlink(dir));
+ BOOST_TEST(!fs::is_symlink("nosuchfileordirectory"));
+ d1 = dir / "d1";
+ BOOST_TEST(fs::create_directory(d1));
+ BOOST_TEST(fs::exists(d1));
+ BOOST_TEST(fs::is_directory(d1));
+ BOOST_TEST(fs::is_empty(d1));
+
+ // create an empty file named "d1f1"
+ d1f1 = d1 / "d1f1";
+ create_file(d1f1, "");
+ BOOST_TEST(fs::exists(d1f1));
+ BOOST_TEST(!fs::is_directory(d1f1));
+ BOOST_TEST(fs::is_regular_file(d1f1));
+ BOOST_TEST(fs::is_empty(d1f1));
+ BOOST_TEST(fs::file_size(d1f1) == 0);
+ BOOST_TEST(fs::hard_link_count(d1f1) == 1);
+
+ // create an empty file named "f0"
+ f0 = dir / "f0";
+ create_file(f0, "");
+ BOOST_TEST(fs::exists(f0));
+ BOOST_TEST(!fs::is_directory(f0));
+ BOOST_TEST(fs::is_regular_file(f0));
+ BOOST_TEST(fs::is_empty(f0));
+ BOOST_TEST(fs::file_size(f0) == 0);
+ BOOST_TEST(fs::hard_link_count(f0) == 1);
+
+ // create a file named "f1"
+ f1 = dir / "f1";
+ create_file(f1, "file-f1");
+ BOOST_TEST(fs::exists(f1));
+ BOOST_TEST(!fs::is_directory(f1));
+ BOOST_TEST(fs::is_regular_file(f1));
+ BOOST_TEST(fs::file_size(f1) == 7);
+ verify_file(f1, "file-f1");
}
// directory_iterator_tests --------------------------------------------------------//
@@ -1228,11 +1229,12 @@
cout << "absolute_tests..." << endl;
BOOST_TEST_EQ(fs::absolute(""), fs::current_path() );
+ BOOST_TEST_EQ(fs::absolute("", ""), fs::current_path() );
BOOST_TEST_EQ(fs::absolute(fs::current_path() / "foo/bar"), fs::current_path() / "foo/bar");
BOOST_TEST_EQ(fs::absolute("foo"), fs::current_path() / "foo");
BOOST_TEST_EQ(fs::absolute("foo", fs::current_path()), fs::current_path() / "foo");
BOOST_TEST_EQ(fs::absolute("bar", "foo"), fs::current_path() / "foo" / "bar");
- BOOST_TEST_EQ(fs::absolute("/foo"), fs::current_path().root_name().string() + "/foo");
+ BOOST_TEST_EQ(fs::absolute("/foo"), fs::current_path().root_path().string() + "foo");
# ifdef BOOST_WINDOWS_API
BOOST_TEST_EQ(fs::absolute("a:foo", "b:/bar"), "a:/bar/foo");
@@ -1295,7 +1297,58 @@
}
- // copy_file_tests -----------------------------------------------------------------//
+ // canonical_basic_tests -----------------------------------------------------------//
+
+ void canonical_basic_tests()
+ {
+ cout << "canonical_basic_tests..." << endl;
+
+ // error handling
+ error_code ec;
+ ec.clear();
+ fs::canonical("no-such-file", ec);
+ BOOST_TEST(ec);
+ ec.clear();
+ fs::canonical("no-such-file", "x", ec);
+ BOOST_TEST(ec);
+ bool ok(false);
+ try { fs::canonical("no-such-file"); }
+ catch (const fs::filesystem_error&) { ok = true; }
+ BOOST_TEST(ok);
+
+ // non-symlink tests; also see canonical_symlink_tests()
+ BOOST_TEST_EQ(fs::canonical(""), fs::current_path());
+ BOOST_TEST_EQ(fs::canonical("", fs::current_path()), fs::current_path());
+ BOOST_TEST_EQ(fs::canonical("", ""), fs::current_path());
+ BOOST_TEST_EQ(fs::canonical(fs::current_path()), fs::current_path());
+ BOOST_TEST_EQ(fs::canonical(fs::current_path(), ""), fs::current_path());
+ BOOST_TEST_EQ(fs::canonical(fs::current_path(), "no-such-file"), fs::current_path());
+
+ BOOST_TEST_EQ(fs::canonical("."), fs::current_path());
+ BOOST_TEST_EQ(fs::canonical(".."), fs::current_path().parent_path());
+ BOOST_TEST_EQ(fs::canonical("/"), fs::current_path().root_path());
+
+ fs::path relative_dir(dir.filename());
+ BOOST_TEST_EQ(fs::canonical(dir), dir);
+ BOOST_TEST_EQ(fs::canonical(relative_dir), dir);
+ BOOST_TEST_EQ(fs::canonical(dir / "f0"), dir / "f0");
+ BOOST_TEST_EQ(fs::canonical(relative_dir / "f0"), dir / "f0");
+ BOOST_TEST_EQ(fs::canonical(relative_dir / "./f0"), dir / "f0");
+ BOOST_TEST_EQ(fs::canonical(relative_dir / "d1/../f0"), dir / "f0");
+ }
+
+ // canonical_symlink_tests -----------------------------------------------------------//
+
+ void canonical_symlink_tests()
+ {
+ cout << "canonical_symlink_tests..." << endl;
+
+ fs::path relative_dir(dir.filename());
+ BOOST_TEST_EQ(fs::canonical(dir / "sym-d1/f2"), d1 / "f2");
+ BOOST_TEST_EQ(fs::canonical(relative_dir / "sym-d1/f2"), d1 / "f2");
+ }
+
+ // copy_file_tests ------------------------------------------------------------------//
void copy_file_tests(const fs::path& f1, const fs::path& d1)
{
@@ -1761,6 +1814,7 @@
int cpp_main(int argc, char* argv[])
{
+
// document state of critical macros
#ifdef BOOST_POSIX_API
cout << "BOOST_POSIX_API is defined\n";
@@ -1805,7 +1859,6 @@
initial_tests();
predicate_and_status_tests();
exception_tests();
- platform_specific_tests();
create_directory_tests();
current_directory_tests();
space_tests();
@@ -1840,11 +1893,13 @@
create_symlink_tests();
resize_file_tests();
absolute_tests();
+ canonical_basic_tests();
copy_file_tests(f1, d1);
if (create_symlink_ok) // only if symlinks supported
{
symlink_status_tests();
copy_symlink_tests(f1, d1);
+ canonical_symlink_tests();
}
iterator_status_tests(); // lots of cases by now, so a good time to test
// dump_tree(dir);
@@ -1857,6 +1912,7 @@
write_time_tests(dir);
temp_directory_path_tests();
+ platform_specific_tests();
cout << "testing complete" << endl;
Modified: branches/release/libs/filesystem/v3/test/path_unit_test.cpp
==============================================================================
--- branches/release/libs/filesystem/v3/test/path_unit_test.cpp (original)
+++ branches/release/libs/filesystem/v3/test/path_unit_test.cpp 2011-10-09 09:54:09 EDT (Sun, 09 Oct 2011)
@@ -43,6 +43,7 @@
#include <boost/detail/lightweight_test.hpp>
#include <boost/detail/lightweight_main.hpp>
#include <boost/smart_ptr.hpp> // used constructor tests
+#include <boost/functional/hash.hpp>
#include <iostream>
#include <iomanip>
@@ -399,9 +400,12 @@
{
std::cout << "testing relationals..." << std::endl;
+ boost::hash<path> hash;
+
# ifdef BOOST_WINDOWS_API
// this is a critical use case to meet user expectations
CHECK(path("c:\\abc") == path("c:/abc"));
+ CHECK(hash(path("c:\\abc")) == hash(path("c:/abc")));
# endif
const path p("bar");
@@ -431,6 +435,9 @@
CHECK(L"baz" == p2);
CHECK(wstring(L"baz") == p2);
+ CHECK(hash(p) == hash(p));
+ CHECK(hash(p) != hash(p2)); // Not strictly required, but desirable
+
CHECK(!(p != p));
CHECK(p != p2);
CHECK(p2 != p);
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk