mirror of
https://github.com/boostorg/filesystem.git
synced 2026-01-27 06:52:09 +00:00
final for review
[SVN r514]
This commit is contained in:
@@ -35,7 +35,7 @@ perform portable filesystem operations on directories and their contents. The
|
||||
Filesystem Library was developed to fill that void.</p>
|
||||
|
||||
<p>The intent is not to compete with traditional scripting languages, but to
|
||||
provide a solution for situations like Boost, where C++ is already the language
|
||||
provide a solution for situations where C++ is already the language
|
||||
of choice..</p>
|
||||
|
||||
<h2><a name="Requirements">Requirements</a></h2>
|
||||
@@ -100,12 +100,23 @@ of choice..</p>
|
||||
Libraries with elaborate interfaces and difficult to port specifications are much less likely to be accepted for
|
||||
standardization.<br>
|
||||
</li>
|
||||
<li>The usual Boost requirements for any library also apply.<br>
|
||||
<li>The usual Boost <a href="../../../more/lib_guide.htm">requirements and
|
||||
guidelines</a> apply.<br>
|
||||
</li>
|
||||
<li>Encourage, but do not require, portability in path names.<br>
|
||||
<br>
|
||||
Rationale: For paths which originate from user input it is unreasonable to
|
||||
require portable path syntax.<br>
|
||||
</li>
|
||||
<li>Avoid the illusion of portability where portability in fact does not
|
||||
exist.</li>
|
||||
<li>Avoid giving the illusion of portability where portability in fact does not
|
||||
exist.<br>
|
||||
<br>
|
||||
Rationale: Defining important behavior unspecified or "implementation defined" does a
|
||||
great disservice to programmers using a library because it makes it appear
|
||||
that code relying on the behavior is portable, when in fact there is nothing
|
||||
at all portable about it. The only case where such under-specification is acceptable is when both users and implementors know from
|
||||
other sources exactly what behavior is required, yet for some reason it isn't
|
||||
possible to specify it exactly.</li>
|
||||
</ul>
|
||||
<h2><a name="Realities">Realities</a></h2>
|
||||
<ul>
|
||||
@@ -122,10 +133,10 @@ of choice..</p>
|
||||
<li>Some file systems (ISO-9660, level 1, for example) use very restricted
|
||||
(so-called 8.3) file names.<br>
|
||||
</li>
|
||||
<li>Some file systems allow other file systems with completely different
|
||||
<li>Some file systems allow other file systems with different
|
||||
characteristics to be "mounted" within a directory tree. Thus a
|
||||
ISO-9660 or Windows
|
||||
file system may end up as a sub-tree of a Unix directory tree.<br>
|
||||
file system may end up as a sub-tree of a POSIX directory tree.<br>
|
||||
</li>
|
||||
<li>Wide-character versions of directory and file operations are available on some operating
|
||||
systems, and not available on others.<br>
|
||||
@@ -137,12 +148,12 @@ of choice..</p>
|
||||
number". Some don't.<br>
|
||||
</li>
|
||||
<li>Not all file systems use single character separators in path names. Some use
|
||||
paired notations. A typical fully-specified VMS filename
|
||||
paired notations. A typical fully-specified OpenVMS filename
|
||||
might look something like this:<br>
|
||||
<br>
|
||||
<code> DISK$SCRATCH:[GEORGE.PROJECT1.DAT]BIG_DATA_FILE.NTP;5<br>
|
||||
</code><br>
|
||||
The general format is:<br>
|
||||
The general OpenVMS format is:<br>
|
||||
<br>
|
||||
|
||||
<i>Device:[directories.dot.separated]filename.extension;version_number</i><br>
|
||||
@@ -154,10 +165,10 @@ of choice..</p>
|
||||
pathname itself, and not the platform. Determining collating sequence is even
|
||||
worse.<br>
|
||||
</li>
|
||||
<li>Directory trees, directories, files, and file attributes are in effect shared between all threads, processes, and computers which have access to the
|
||||
<li>Race-conditions may occur. Directory trees, directories, files, and file attributes are in effect shared between all threads, processes, and computers which have access to the
|
||||
filesystem. That may well include computers on the other side of the
|
||||
world or in orbit around the world. This implies that file system operations
|
||||
may fail in unexpected ways. For example:<br>
|
||||
may fail in unexpected ways. For example:<br>
|
||||
<br>
|
||||
<code> assert( exists("foo") == exists("foo") );
|
||||
// may fail!<br>
|
||||
@@ -169,7 +180,7 @@ of choice..</p>
|
||||
replaced by a directory of the same name between the calls to is_directory().<br>
|
||||
</li>
|
||||
<li>Even though an application may be portable, it still will have to traffic
|
||||
in system specific paths occasionally; operated provided input is a common
|
||||
in system specific paths occasionally; user provided input is a common
|
||||
example.</li>
|
||||
</ul>
|
||||
|
||||
@@ -203,6 +214,11 @@ answers to that question, the Filesystem Library alerts programmers of the need
|
||||
to ask it in the first place.</p>
|
||||
<h2><a name="Abandoned Designs">Abandoned Designs</a></h2>
|
||||
<h3>operations.hpp</h3>
|
||||
<p>Dietmar Kühl's original dir_it design and implementation supported
|
||||
wide-character file and directory names. It was abandoned after extensive
|
||||
discussions among Library Working Group members failed to identify portable
|
||||
semantics for wide-character names on systems not providing native support. See
|
||||
<a href="faq.htm#wide-character names">FAQ</a>.</p>
|
||||
<p>Previous iterations of the interface design used explicitly named functions providing a
|
||||
large number of convenience operations, with no compile-time or run-time
|
||||
options. There were so many function names that they were very confusing to use,
|
||||
@@ -268,7 +284,7 @@ Variable Considered Harmful</i>, ACM SIGPLAN Notices, 8, 2, 1973, pp. 23-34</p>
|
||||
<hr>
|
||||
<p>© Copyright Beman Dawes, 2002</p>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->30 July, 2002<!--webbot bot="Timestamp" endspan i-checksum="21079" --></p>
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2002<!--webbot bot="Timestamp" endspan i-checksum="39336" --></p>
|
||||
|
||||
</body>
|
||||
|
||||
|
||||
@@ -5,7 +5,8 @@ Do-list</h1>
|
||||
<ul>
|
||||
<li>Finish the probe program, and ask Boost people to run it on various O/S's.<br>
|
||||
</li>
|
||||
<li>Finish portability guide.<br>
|
||||
<li>Finish portability guide and checking functions. Get opinions on default, Boost, and other error checks. POSIX?
|
||||
Windows? Mac? ISO 6990?<br>
|
||||
</li>
|
||||
<li>Cyclic paths:</li>
|
||||
</ul>
|
||||
@@ -17,9 +18,6 @@ Do-list</h1>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li>Get opinions on default, Boost, and other error checks. POSIX?
|
||||
Windows? ISO 6990?<br>
|
||||
</li>
|
||||
<li>As a lexical concept, parent-directory is portable unless it escapes to
|
||||
the operating system. But do all operating recognize such a concept in a path?
|
||||
I doubt it. Maybe there should be a checking function that verifies that
|
||||
@@ -30,4 +28,4 @@ Do-list</h1>
|
||||
<hr>
|
||||
<p>© Copyright Beman Dawes, 2002</p>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->30 July, 2002<!--webbot bot="Timestamp" endspan i-checksum="21079" --></p>
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2002<!--webbot bot="Timestamp" endspan i-checksum="39336" --></p>
|
||||
@@ -14,7 +14,7 @@ operations" requirement of the Filesystem Library, full URI's appear to be
|
||||
</b>POSIX is the basis for the most familiar path-string formats, including the
|
||||
URL portion of URI's and the native Windows format. It is ubiquitous and
|
||||
familiar. On many systems, it is very easy to implement because it is
|
||||
either the native operating system format (Unixes and Windows) or via a
|
||||
either the native operating system format (Unix and Windows) or via a
|
||||
operating system supplied
|
||||
POSIX library (z/OS, OS/390, and many more.)</p>
|
||||
<p><b>Why isn't <i>path</i> a base class with derived <i>directory_path</i> and
|
||||
@@ -110,8 +110,7 @@ notification variable?</b></p>
|
||||
by programmers. Exceptions are much harder to ignore, provided desired
|
||||
default behavior (program termination) if not caught, yet allow error recovery
|
||||
if desired.</p>
|
||||
<p><b>Why are attributes accessed via named functions rather than
|
||||
<a href="../../property_map/property_map.html">property maps</a>?</b></p>
|
||||
<p><b>Why are attributes accessed via named functions rather than property maps?</b></p>
|
||||
<p>For a few commonly used attributes (existence, directory or file, emptiness),
|
||||
simple syntax and guaranteed presence outweigh other considerations. Because
|
||||
access to virtually all other attributes is inherently system dependent,
|
||||
@@ -126,7 +125,7 @@ about to hand them the gun.</p>
|
||||
<p><b>Why aren't there query functions for compound conditions like existing_directory?</b></p>
|
||||
<p>After several attempts, named queries for multi-attribute proved a
|
||||
slippery-slope; where do you stop?</p>
|
||||
<p><b>Why aren't wide-character names supported? Why not std::wstring or even
|
||||
<p><b>Why aren't <a name="wide-character names">wide-character names</a> supported? Why not std::wstring or even
|
||||
a templated type?</b></p>
|
||||
<p>Wide-character names would provide an illusion of portability where
|
||||
portability does not in fact exist. Behavior would be completely different on
|
||||
@@ -176,4 +175,4 @@ paths:</p>
|
||||
<hr>
|
||||
<p>© Copyright Beman Dawes, 2002</p>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->22 July, 2002<!--webbot bot="Timestamp" endspan i-checksum="21082" --></p>
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->12 September, 2002<!--webbot bot="Timestamp" endspan i-checksum="39334" --></p>
|
||||
@@ -19,21 +19,88 @@
|
||||
pass arguments representing file names, with that usage occurring in seven
|
||||
times.</p>
|
||||
|
||||
<p>The Filesystem Library's <i>fstream.hpp</i> header provides, in namespace <i>
|
||||
boost::filesystem</i>, equivalent components, except that the seven <i>
|
||||
<p>The Filesystem Library's <i>fstream.hpp</i> header provides equivalent
|
||||
components, in namespace <i>
|
||||
boost::filesystem</i>, except that the seven <i>
|
||||
const char*</i> arguments have been replaced by <i>const path&</i> arguments.</p>
|
||||
|
||||
<p>The implementation simply uses the <i><fstream></i> standard library
|
||||
components as base classes, and then overrides the members with changed argument
|
||||
types.</p>
|
||||
<p>The Filesystem Library's <i>fstream.hpp</i> header simply uses the <i><fstream></i> standard library
|
||||
components as base classes, and then overrides the members requiring argument
|
||||
types of <i>path</i>.</p>
|
||||
|
||||
<p>For the moment, the only other documentation beyond the
|
||||
<p>For documentation beyond the synopsis, see the
|
||||
<a href="index.htm#tutorial">tutorial</a> and <a href="index.htm#Examples">
|
||||
examples</a> is the header itself. See <a href="../../../boost/filesystem/fstream.hpp">boost/filesystem/fstream.hpp</a>.</p>
|
||||
examples</a>.</p>
|
||||
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
<pre>namespace boost
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
template < class charT, class traits = std::char_traits<charT> >
|
||||
class basic_filebuf : public std::basic_filebuf<charT,traits>
|
||||
{
|
||||
public:
|
||||
virtual ~basic_filebuf() {}
|
||||
|
||||
std::basic_filebuf<charT,traits> * open( const path & file_ph,
|
||||
std::ios_base::openmode mode );
|
||||
};
|
||||
|
||||
typedef basic_filebuf<char> filebuf;
|
||||
typedef basic_filebuf<wchar_t> wfilebuf;
|
||||
|
||||
template < class charT, class traits = std::char_traits<charT> >
|
||||
class basic_ifstream : public std::basic_ifstream<charT,traits>
|
||||
{
|
||||
public:
|
||||
basic_ifstream() {}
|
||||
explicit basic_ifstream( const path & file_ph,
|
||||
std::ios_base::openmode mode = std::ios_base::in );
|
||||
virtual ~basic_ifstream() {}
|
||||
void open( const path & file_ph,
|
||||
std::ios_base::openmode mode = std::ios_base::in );
|
||||
};
|
||||
|
||||
typedef basic_ifstream<char> ifstream;
|
||||
typedef basic_ifstream<wchar_t> wifstream;
|
||||
|
||||
template < class charT, class traits = std::char_traits<charT> >
|
||||
class basic_ofstream : public std::basic_ofstream<charT,traits>
|
||||
{
|
||||
public:
|
||||
basic_ofstream() {}
|
||||
explicit basic_ofstream( const path & file_ph,
|
||||
std::ios_base::openmode mode = std::ios_base::out );
|
||||
virtual ~basic_ofstream() {}
|
||||
void open( const path & file_ph,
|
||||
std::ios_base::openmode mode = std::ios_base::out );
|
||||
};
|
||||
|
||||
typedef basic_ofstream<char> ofstream;
|
||||
typedef basic_ofstream<wchar_t> wofstream;
|
||||
|
||||
template < class charT, class traits = std::char_traits<charT> >
|
||||
class basic_fstream : public std::basic_fstream<charT,traits>
|
||||
{
|
||||
public:
|
||||
basic_fstream() {}
|
||||
explicit basic_fstream( const path & file_ph,
|
||||
std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out );
|
||||
virtual ~basic_fstream() {}
|
||||
void open( const path & file_ph,
|
||||
std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out );
|
||||
};
|
||||
|
||||
typedef basic_fstream<char> fstream;
|
||||
typedef basic_fstream<wchar_t> wfstream;
|
||||
} // namespace filesystem
|
||||
} // namespace boost
|
||||
</pre>
|
||||
<hr>
|
||||
<p>© Copyright Beman Dawes, 2002</p>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->11 July, 2002<!--webbot bot="Timestamp" endspan i-checksum="21079" --></p>
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->12 September, 2002<!--webbot bot="Timestamp" endspan i-checksum="39334" --></p>
|
||||
|
||||
</body>
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ Filesystem Library</h1>
|
||||
<a href="#Definitions">Definitions</a><br>
|
||||
|
||||
<a href="#Requirements">Requirements</a><br>
|
||||
<a href="#Dangers">Dangers</a><br>
|
||||
<a href="#Race-condition">Race-condition danger</a><br>
|
||||
<a href="#Acknowledgements">Acknowledgements</a></td>
|
||||
<td width="50%"><font size="4">Other Documents</font><br>
|
||||
<a href="design.htm">Library Design</a><br>
|
||||
@@ -45,7 +45,8 @@ compete with Python, Perl, or shell languages, but rather to provide portable fi
|
||||
operations when C++ is already the language of choice. The <a href="design.htm">
|
||||
design</a> encourages, but does not require, safe and portable filesystem usage.</p>
|
||||
|
||||
<p>Filesystem Library components are supplied by four headers:</p>
|
||||
<p>Filesystem Library components are supplied by several headers, all in
|
||||
directory boost/filesystem:</p>
|
||||
|
||||
<ul>
|
||||
<li>Header <i>path.hpp</i> provides class <i>path, </i>a portable mechanism for representing
|
||||
@@ -62,12 +63,18 @@ design</a> encourages, but does not require, safe and portable filesystem usage.
|
||||
See <a href="fstream.htm">fstream.hpp documentation</a>.<br>
|
||||
</li>
|
||||
<li>Header <i>exception.hpp</i> provides class <i>filesystem_error</i>. See
|
||||
<a href="exception.htm">exception.hpp documentation</a>.</li>
|
||||
<a href="exception.htm">exception.hpp documentation</a>.<br>
|
||||
</li>
|
||||
<li>Experimental header <i>
|
||||
<a href="../../../boost/filesystem/recursive_directory_iterator.hpp">
|
||||
recursive_directory_iterator.hpp</a></i> provides an undocumented directory
|
||||
iterator which recurses into any sub-directories encountered. It will be
|
||||
incorporated into the Filesystem Library if user feedback is favorable.</li>
|
||||
</ul>
|
||||
<h2>Two-minute <a name="tutorial">tutorial</a></h2>
|
||||
<p>After some preliminaries:</p>
|
||||
<p>First some preliminaries:</p>
|
||||
<blockquote>
|
||||
<pre>#include "boost/filesystem/operations.hpp" // also includes path.hpp
|
||||
<pre>#include "boost/filesystem/operations.hpp" // includes boost/filesystem/path.hpp
|
||||
#include "boost/filesystem/fstream.hpp" // ditto
|
||||
#include <iostream> // for cout
|
||||
namespace fs = boost::filesystem;</pre>
|
||||
@@ -80,7 +87,7 @@ namespace fs = boost::filesystem;</pre>
|
||||
<a href="path.htm#Grammar">portable generic path format</a>. Access functions
|
||||
make <i>my_path</i> contents available in an operating system dependent format,
|
||||
such as <code>"some_dir:file.txt"</code>, <code>"[some_dir]file.txt"</code>,
|
||||
<code>"some_dir/file.txt"</code>, or whatever is appropriate for the current
|
||||
<code>"some_dir/file.txt"</code>, or whatever is appropriate for the
|
||||
operating system.</p>
|
||||
<p>Class <i>path</i> has conversion constructors from <i>const char*</i> and <i>
|
||||
const std:: string&</i>, so that even though the Filesystem Library functions in
|
||||
@@ -173,7 +180,9 @@ hierarchy viewed as an acyclic graph.</p>
|
||||
<p><b><a name="path">path</a> </b>- A possibly empty sequence of names. Each
|
||||
element in the sequence, except the last, names a <a href="#directory">directory</a>
|
||||
which contains the
|
||||
next element. The last element may name either a directory or file.</p>
|
||||
next element. The last element may name either a directory or file. The first
|
||||
element is closest to the root of the directory tree, the last element is
|
||||
farthest from the root.</p>
|
||||
<p>It is traditional to represent a path as a string, where each element in the
|
||||
path is represented by a <a href="#name">name</a>, and some operating system
|
||||
defined syntax distinguishes between the name elements. Other representations of
|
||||
@@ -194,11 +203,11 @@ implementation cannot successfully complete operations required to meet the
|
||||
function's specifications. Such exceptions are in addition to any exceptions
|
||||
specified in the function's "Throws" paragraph.</p>
|
||||
<p>Filesystem Library functions are permitted to call C++ Standard Library
|
||||
functions, so, <i>std::bad_alloc</i> exceptions may also be thrown, unless
|
||||
functions, so <i>std::bad_alloc</i> exceptions may also be thrown, unless
|
||||
otherwise specified.</p>
|
||||
<p>There is no rollback guarantee; a Filesystem Library function which throws an
|
||||
exception may leave the external file system in an altered the state.</p>
|
||||
<h2><a name="Dangers">Dangers</a></h2>
|
||||
exception may leave the external file system in an altered state.</p>
|
||||
<h2><a name="Race-condition">Race-condition</a> d<a name="Dangers">anger</a></h2>
|
||||
<p>The state of files and directories is often
|
||||
globally shared, and thus may be changed unexpectedly by other threads,
|
||||
processes, or even other computers which have access to the filesystem. As an
|
||||
@@ -229,7 +238,7 @@ or directory resources should be prepared for <i>filesystem_error</i> exceptions
|
||||
to be thrown from any filesystem function except those explicitly specified as
|
||||
not throwing exceptions.</p>
|
||||
<h2><a name="Implementation">Implementation</a></h2>
|
||||
<p>The current implementation (July, 2002) supports operating systems that have
|
||||
<p>The current implementation (September, 2002) supports operating systems that have
|
||||
either the POSIX or Windows API's available.</p>
|
||||
<p>The following tests are provided:</p>
|
||||
<ul>
|
||||
@@ -237,19 +246,17 @@ either the POSIX or Windows API's available.</p>
|
||||
<li><a href="../test/operations_test.cpp">operations_test.cpp</a></li>
|
||||
<li><a href="../test/fstream_test.cpp">fstream_test.cpp</a></li>
|
||||
</ul>
|
||||
<p>As of July, 2002, these tests succeed for the following compilers on Windows:</p>
|
||||
<p>As of September, 2002, these tests succeed for the following compilers on Windows:</p>
|
||||
<ul>
|
||||
<li>Borland 5.5.1</li>
|
||||
<li>GCC 3.1 (excluding wide-character fstream tests)</li>
|
||||
<li>GCC 3.1 (using POSIX implementation, but excluding wide-character fstream tests)</li>
|
||||
<li>Intel 6.0</li>
|
||||
<li>Metrowerks 8.1</li>
|
||||
<li>Metrowerks 8.2</li>
|
||||
<li>Microsoft 7.0</li>
|
||||
<li>Microsoft 6.0 except fstream_test failed.</li>
|
||||
</ul>
|
||||
<p>As of July, 2002, these tests failed for the following compilers on Windows:</p>
|
||||
<ul>
|
||||
<li>Microsoft 6.0 fstream_test</li>
|
||||
</ul>
|
||||
<p>As of September, 2002, some limited use has been successful on Linux using
|
||||
GCC and IBM/AIX using Visual Age C++.</p>
|
||||
<h2><a name="Acknowledgements">Acknowledgements</a></h2>
|
||||
<p>The Filesystem Library was designed and implemented by Beman Dawes, except
|
||||
for the <i>directory_iterator</i> and <i>filesystem_error</i> classes which were
|
||||
@@ -263,7 +270,7 @@ Salters, Jani Kajala, Jason Stewart, Carl Daniel, David Abrahams, Bill Kempf,
|
||||
Jonathan Caves, George Heintzelman, Ken Hagen, Eric Jensen, Joel de Guzman, Jim
|
||||
Hyslop, John Maddock, Matt Austern, Peter Dimov, Davlet Panech, Dylan Nicholson, Tom Harris,
|
||||
Giovanni Bajo, Baptiste Lepilleur, Thomas Witt, Keith Burton, Mattias Flodin,
|
||||
Daniel Frey, Vladimir Prus.</p>
|
||||
Daniel Frey, Vladimir Prus, Toon Knapen.</p>
|
||||
|
||||
<p>Specific improvements for a preliminary design document came from Dan Nuffer and Jeff
|
||||
Garland.</p>
|
||||
@@ -274,7 +281,7 @@ of portability" problem, particularly in postings by JP Plauger and Pete Be
|
||||
<hr>
|
||||
<p>© Copyright Beman Dawes, 2002</p>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->09 August, 2002<!--webbot bot="Timestamp" endspan i-checksum="34422" --></p>
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2002<!--webbot bot="Timestamp" endspan i-checksum="39336" --></p>
|
||||
|
||||
</body>
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ documentation</a>.</p>
|
||||
|
||||
<p>As with all Filesystem Library components, errors may result in <i>
|
||||
<a href="exception.htm">filesystem_error</a></i> or <i>std::bad_alloc</i>
|
||||
exceptions being thrown. See <a href="reference.htm#Requirements">Requirements</a>.</p>
|
||||
exceptions being thrown. See <a href="index.htm#Requirements">Requirements</a>.</p>
|
||||
|
||||
<h2>Header <a href="../../../boost/filesystem/operations.hpp">boost/filesystem/operations.hpp</a>
|
||||
<a name="Synopsis">synopsis</a></h2>
|
||||
@@ -58,15 +58,13 @@ exceptions being thrown. See <a href="reference.htm#Requirements">Requirements</
|
||||
public:
|
||||
typedef <a href="path.htm">path</a> value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef path * pointer;
|
||||
typedef path & reference;
|
||||
typedef const path * pointer;
|
||||
typedef const path & reference;
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
|
||||
<a href="#constructors">directory_iterator</a>();
|
||||
explicit <a href="#constructors">directory_iterator</a>( const path & directory_ph );
|
||||
|
||||
<a href="#destructor">~directory_iterator</a>();
|
||||
|
||||
// <a href="#other functions">other functions</a>
|
||||
// ...
|
||||
};
|
||||
@@ -99,7 +97,7 @@ directory</a>. </p>
|
||||
dereferencing a <i>directory_iterator</i> yields a <a href="reference.htm#path">
|
||||
path</a> to a file or directory contained within the directory represented by
|
||||
the directory-path argument supplied at construction. The path returned by
|
||||
dereferencing a a <i>directory_iterator</i> is composed by appending the name of
|
||||
dereferencing a <i>directory_iterator</i> is composed by appending the name of
|
||||
the directory entry to the directory path supplied at construction.</p>
|
||||
|
||||
<p>A path returned by dereferencing a <i>directory_iterator</i> is, if
|
||||
@@ -111,7 +109,7 @@ Standard Library functions specified as taking file names. The leaf of a path
|
||||
returned by dereferencing a <i>directory_iterator</i> will never be <code>".."</code>
|
||||
or <code>"."</code>.</p>
|
||||
|
||||
<p><b>Note:</b> The implication of the above requirement is that if a operating
|
||||
<p><b>Note:</b> The implication of the above requirement is that if an operating
|
||||
system's directories can contain entries which are not usable by Filesystem
|
||||
Library or Standard Library functions, these entries will be skipped during
|
||||
directory iteration. Such entries are by definition non-portable, but can always
|
||||
@@ -132,20 +130,6 @@ representing the first path in <i>directory_ph</i>, or if <code>
|
||||
empty(directory_ph)</code>, the <i>past-the-end</i> value.</p>
|
||||
</blockquote>
|
||||
|
||||
<h3><a name="destructor">Destructor</a></h3>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p><code>~directory_iterator();</code></p>
|
||||
|
||||
<p>If <code>*this == directory_iterator()</code>, the destructor may possibly
|
||||
throw an exception. Otherwise, the iterator has the <i>past-the-end</i>
|
||||
value, and the destructor is guaranteed to never throw an exception.</p>
|
||||
|
||||
<p><b>Effects:</b> Destroys *this</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<h3><a name="other functions">Other functions</a></h3>
|
||||
|
||||
<p>Class <i>directory_iterator</i> also supplies all the other functions
|
||||
@@ -157,10 +141,11 @@ required by the C++ standard clause 24 for input iterators, such as <i>operator=
|
||||
<p>
|
||||
The non-member functions provide common operations on files and directories.
|
||||
They follow traditional practice of the C and C++ standard libraries, except
|
||||
that
|
||||
they:</p>
|
||||
|
||||
<ul>
|
||||
<li>Traffic in <i>paths</i> rather than <code>char*</code>'s, for much
|
||||
<li>Traffic in <i><a href="path.htm">paths</a></i> rather than <code>char*</code>'s, for much
|
||||
enhanced portability.</li>
|
||||
<li>Report errors by throwing exceptions, for safer and better error handling.</li>
|
||||
<li>Tighten specifications slightly, for improved portability.</li>
|
||||
@@ -172,6 +157,16 @@ such as <i><a href="#remove">remove()</a></i> and <i><a href="#rename">rename()<
|
||||
retain the same names and general behavior in the Filesystem Library, to
|
||||
minimize surprises.</p>
|
||||
|
||||
<p>
|
||||
<b>Rationale:</b> Errors which might appear to be preconditions are not
|
||||
specified as such, but instead are specified to throw exceptions. This is
|
||||
because the possibility of <a href="index.htm#Race-condition">race-conditions</a>
|
||||
makes it unreliable to test for preconditions before calling the function. As a
|
||||
design practice, preconditions should always be testable by a program, so that
|
||||
violations can be avoided. It is not always possible or desirable to abstract
|
||||
away the fact that the library is implemented by calls to the operating system,
|
||||
and this is one of those cases.</p>
|
||||
|
||||
<p>
|
||||
<b>Naming Rationale:</b> See class <i>path</i>
|
||||
<a href="path.htm#Naming Rationale">Naming Rationale</a>.</p>
|
||||
@@ -207,7 +202,7 @@ exists(ph) && is_directory(ph)</code> can always be added later.</p>
|
||||
</blockquote>
|
||||
<h3><a name="create_directory">create_directory</a></h3>
|
||||
<blockquote>
|
||||
<p><code>void create_directory( const path & & directory_ph );</code></p>
|
||||
<p><code>void create_directory( const path & directory_ph );</code></p>
|
||||
<p><b>Postcondition:</b> <code>exists(directory_ph) &&
|
||||
is_directory(directory_ph) && is_empty(directory_ph)</code></p>
|
||||
<p><b>Throws: </b>if <code>exists(directory_ph)) || !exists(branch(directory_ph))</code></p>
|
||||
@@ -216,7 +211,20 @@ is_directory(directory_ph) && is_empty(directory_ph)</code></p>
|
||||
<blockquote>
|
||||
<p><code>void remove( const path & ph );</code></p>
|
||||
<p><b>Postcondition:</b> <code>!exists( ph )</code></p>
|
||||
<p><b>Throws:</b> if <code>!exists(ph) || (is_directory(ph) && !is_empty(ph))</code></p>
|
||||
<p><b>Throws:</b><code> exists(ph) && is_directory(ph) && !is_empty(ph)</code></p>
|
||||
<p><b>Rationale:</b> Does not throw when <code>!exists( ph )</code> because not
|
||||
throwing is:</p>
|
||||
<ul>
|
||||
<li>Slightly easier-to-use for many common use cases.</li>
|
||||
<li>Slightly higher-level because it implies use of postcondition semantics
|
||||
rather than effects semantics, which would be specified in the somewhat
|
||||
lower-level terms of interactions with the operating system.</li>
|
||||
</ul>
|
||||
<p>There is, however, a slight decrease in safety because some errors will slip
|
||||
by which otherwise would have been detected. For example, a misspelled path name
|
||||
could go undetected for a long time.</p>
|
||||
<p>The initial version of the library did throw when the path did not exist; it
|
||||
was changed only reluctantly.</p>
|
||||
</blockquote>
|
||||
<h3><a name="remove_all">remove_all</a></h3>
|
||||
<blockquote>
|
||||
@@ -238,7 +246,7 @@ and the file or directory contents and attributes are otherwise unchanged.</p>
|
||||
as <code>branch(to_ph)</code>, then <code>leaf(from_ph)</code> must not be
|
||||
the same name as <code>leaf(to_ph)</code>, but if the branch directories are
|
||||
different, it doesn't matter if the leaf names are the same.</p>
|
||||
<p><b>Note:</b> Some operating systems with multi-rooted filesystems
|
||||
<p><b>Note:</b> Some operating systems with multi-rooted file systems
|
||||
representing different drives, devices, or volumes, do not allow <i>rename</i>
|
||||
operations between roots . Implementations should not take heroic efforts, such
|
||||
as switching to a copy mode, to make an otherwise failing <i>rename </i>succeed
|
||||
@@ -277,7 +285,7 @@ initial_directory()</i>.</p>
|
||||
<hr>
|
||||
<p>© Copyright Beman Dawes, 2002</p>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 August, 2002<!--webbot bot="Timestamp" endspan i-checksum="34406" --></p>
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2002<!--webbot bot="Timestamp" endspan i-checksum="39336" --></p>
|
||||
|
||||
</body>
|
||||
|
||||
|
||||
33
doc/path.htm
33
doc/path.htm
@@ -35,10 +35,10 @@ documentation</a>.</p>
|
||||
|
||||
<p>As with all Filesystem Library components, errors may result in <i>
|
||||
<a href="exception.htm">filesystem_error</a></i> or <i>std::bad_alloc</i>
|
||||
exceptions being thrown. See <a href="reference.htm#Requirements">Requirements</a>.</p>
|
||||
exceptions being thrown. See <a href="index.htm#Requirements">Requirements</a>.</p>
|
||||
<h2><a name="Class path">Class path</a></h2>
|
||||
<p>Class <i>path</i> provides for portable mechanism for representing
|
||||
<a href="reference.htm#path">paths</a> in C++ programs. Class <i>path</i>
|
||||
<p>Class <i>path</i> provides for portable mechanism for representing
|
||||
<a href="index.htm#path">paths</a> in C++ programs. Class <i>path</i>
|
||||
is concerned with the lexical and syntactic aspects of a path, regardless of
|
||||
whether or not such a path currently exists in the operating system's
|
||||
filesystem. </p>
|
||||
@@ -49,15 +49,17 @@ portable but the strings they operate on would not be portable.</p>
|
||||
<h2><a name="Conceptual model">Conceptual model</a> of a path</h2>
|
||||
<p>An object of class <i>path</i> can be conceptualized as containing a sequence
|
||||
of strings, where each string contains the name of a directory, or, in the case
|
||||
of the last string, a directory or file. Such a path representation is
|
||||
completely independent of any particular representation of the path as a single
|
||||
of the string representing the element farthest from the root in the directory
|
||||
hierarchy, the name of a directory or file. Such a path representation is
|
||||
|
||||
independent of any particular representation of the path as a single
|
||||
string.</p>
|
||||
<p>There is no requirement that an implementation of class <i>path</i> actually
|
||||
contain a sequence of strings, but conceptualizing the contents that way provides
|
||||
a completely portable way to reason about paths.</p>
|
||||
<p>So that programs can portably express paths as a single string, class <i>path</i>
|
||||
defines a <a href="#Grammar">grammar</a> for a portable generic path string
|
||||
format, and supplies a constructor and append operations taking such strings as
|
||||
format, and supplies constructor and append operations taking such strings as
|
||||
arguments. Because user input or third-party library functions may supply path
|
||||
strings formatted according to operating system specific rules, an additional
|
||||
constructor is provided which takes a system-specific format as an argument.</p>
|
||||
@@ -90,8 +92,9 @@ with the <i><a href="#system_specific">system_specific</a></i> decorator.</p>
|
||||
<p>Although implementation-defined, it is desirable that <i>
|
||||
system-specific-root</i> have a grammar which is distinguishable from other grammar elements,
|
||||
and follow the conventions of the operating system.</p>
|
||||
<p>Whether or not a generic path string is actually portable will depend on the
|
||||
names used. See <font color="#FF0000"><i>to be provided</i></font></p>
|
||||
<p>Whether or not a generic path string is actually portable to a particular
|
||||
operating system will depend on the
|
||||
names used. See the <a href="portability_guide.htm">Portability Guide</a>.</p>
|
||||
<h2><a name="Canonical">Canonical</a> form</h2>
|
||||
<p>Adjacent <i>name, parent-directory</i> elements in <code>m_name</code>
|
||||
have been recursively removed. </p>
|
||||
@@ -118,7 +121,7 @@ boost/filesystem/path.hpp</a> <a name="synopsis">synopsis</a></h2>
|
||||
|
||||
// append operations:
|
||||
path & <a href="#operator-shift-equal">operator<<=</a>( const path & rhs );
|
||||
const path <a href="#operator-shift">operator<<</a> ( const path & rhs ) const;
|
||||
const path <a href="#operator-shift">operator<<</a>( const path & rhs ) const;
|
||||
|
||||
// query functions:
|
||||
bool <a href="#empty">is_null()</a> const;
|
||||
@@ -129,9 +132,9 @@ boost/filesystem/path.hpp</a> <a name="synopsis">synopsis</a></h2>
|
||||
const path <a href="#branch">branch</a>() const;
|
||||
|
||||
// iteration:
|
||||
typedef <i>implementation-defined</i> iterator;
|
||||
iterator begin() const;
|
||||
iterator end() const;
|
||||
typedef <i>implementation-defined</i> <a href="#iterator">iterator</a>;
|
||||
const iterator <a href="#begin">begin</a>() const;
|
||||
const iterator <a href="#end">end</a>() const;
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_name; // for exposition only
|
||||
@@ -323,12 +326,12 @@ iterators (24.1). The value, reference, and pointer types are <i>std::string</i>
|
||||
</blockquote>
|
||||
<h3><a name="begin">begin</a></h3>
|
||||
<blockquote>
|
||||
<p><code>iterator begin() const;</code></p>
|
||||
<p><code>const iterator begin() const;</code></p>
|
||||
<p><b>Returns:</b> <code>m_path.begin()</code></p>
|
||||
</blockquote>
|
||||
<h3><a name="end">end</a></h3>
|
||||
<blockquote>
|
||||
<p><code>iterator end() const;</code></p>
|
||||
<p><code>const iterator end() const;</code></p>
|
||||
<p><b>Returns:</b> <code>m_path.end()</code></p>
|
||||
</blockquote>
|
||||
<h2><a name="Non-member functions">Non-member functions</a></h2>
|
||||
@@ -349,7 +352,7 @@ likely to change.</p>
|
||||
<hr>
|
||||
<p>© Copyright Beman Dawes, 2002</p>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->09 August, 2002<!--webbot bot="Timestamp" endspan i-checksum="34422" --></p>
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2002<!--webbot bot="Timestamp" endspan i-checksum="39336" --></p>
|
||||
|
||||
</body>
|
||||
|
||||
|
||||
@@ -18,17 +18,44 @@ Guide</h1>
|
||||
guarantee that a program using the Filesystem Library will be portable between
|
||||
operating systems. The file and directory names in paths present a particularly
|
||||
troublesome portability problem.</p>
|
||||
<p>Although there is no way to guarantee that a path is portable to every
|
||||
operating system, the probability of portability can be markedly improved by
|
||||
understanding the limits imposed by various operating systems, and by following
|
||||
some rules-of-thumb when deciding path issues.</p>
|
||||
<h2>File and directory <a name="recommendations">recommendations</a></h2>
|
||||
<p>It is not possible to know in advance if a file or directory name will be
|
||||
valid (and thus portable) for an operating system whose requirements are
|
||||
unknown. There is always the possibility that an operating system could use
|
||||
names which are unusual (number between 17 and 4095, for example) or very
|
||||
limited (maximum of two character names, for example).</p>
|
||||
<p>It is possible, however, to know if a name is valid for a particular
|
||||
operating system. It is also possible to construct names which are very
|
||||
likely to be portable to a large number of modern and legacy operating systems.</p>
|
||||
<p>By providing name validity checking facilities, the Filesystem Library allows
|
||||
programmers to ensure that a given name meets the requirements for specific
|
||||
operating systems, or meets the recommendations for general portability.</p>
|
||||
<p><b>To do:</b> An implementation should be required to provide check functions
|
||||
for the host O/S, and for the portability recommendations. But it isn't
|
||||
possible to require implementors to supply an open ended number of checking
|
||||
functions. It would be helpful if there was a registry to ensure that checking
|
||||
functions for a particular O/S had the same specification regardless of
|
||||
implementor.</p>
|
||||
|
||||
<h2>Limits imposed by specific operating systems</h2>
|
||||
<p>(To be supplied)</p>
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td align="center"><b>Operating<br>
|
||||
system</b></td>
|
||||
<td align="center"><b>Check<br>
|
||||
function</b></td>
|
||||
<td align="center"><b>Requirements</b></td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2>File and directory name <a name="recommendations">recommendations</a></h2>
|
||||
|
||||
<p>(Very preliminary draft)</p>
|
||||
|
||||
<table border="1">
|
||||
<tr>
|
||||
<td align="center" valign="top"><strong>Recommendation</strong></td>
|
||||
<td align="center" valign="top"><strong>Check<br>
|
||||
function</strong></td>
|
||||
<td align="center" valign="top"><strong>Rationale</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -36,29 +63,34 @@ some rules-of-thumb when deciding path issues.</p>
|
||||
underscore.<br>
|
||||
<br>
|
||||
For even greater portability, don't use hyphens at all.</td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top">These are the characters specified by the POSIX standard for portable directory and
|
||||
file names, and are also valid for Windows, Mac, and many other modern filesystems.
|
||||
ISO-9660, and possibly some legacy systems, do not permit hyphens at all.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">Do not use periods in directory names. </td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top">Requirement for Requirement for ISO-9660, OpenVMS native
|
||||
filesystem, and other legacy systems.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">Do not use more that one period in a file name.</td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top">Requirement for ISO-9660, OpenVMS native filesystem, and
|
||||
other legacy systems. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">Do not use period, hyphen, or underscore as the first
|
||||
character of a file or directory name.</td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top">Some operating systems treat have special rules for the
|
||||
first character of names. POSIX, for example.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">Do not assume names are case sensitive. For example, do not expected a directory to be
|
||||
able to hold separate elements named "Foo" and "foo". </td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top">Some filesystems are case insensitive. For example, Windows
|
||||
NTFS is case preserving in the way it stores names, but case insensitive in
|
||||
searching for names (unless running under the POSIX sub-system, it which
|
||||
@@ -67,6 +99,7 @@ some rules-of-thumb when deciding path issues.</p>
|
||||
<tr>
|
||||
<td valign="top">Do not assume names are case insensitive. For example, do not expect a file
|
||||
created with the name of "Foo" to be open successfully with the name of "foo".</td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top">Some filesystems are case sensitive. For example, POSIX.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -74,6 +107,7 @@ some rules-of-thumb when deciding path issues.</p>
|
||||
tree so that the total length of the string returned by generic_path() to
|
||||
255 characters.
|
||||
Note that ISO 9660 level 1 has an explicit directory tree depth limit of 8.</td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top">Some operating systems place limits on the total path length. For example,
|
||||
Windows 2000 limits paths to 260 characters total length.</td>
|
||||
</tr>
|
||||
@@ -84,17 +118,16 @@ some rules-of-thumb when deciding path issues.</p>
|
||||
31 characters: Classic Mac OS<br>
|
||||
8 characters + period + 3 characters: ISO 9660 (CD-ROM)<br>
|
||||
<strong>...</strong></td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top">Limiting name length can markedly reduce the expressiveness of file names, yet placing
|
||||
only very high limits on lengths inhibits wide portability.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2>Limits imposed by specific operating systems</h2>
|
||||
<p>(To be supplied)</p>
|
||||
<hr>
|
||||
<p>© Copyright Beman Dawes, 2002</p>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->12 August, 2002<!--webbot bot="Timestamp" endspan i-checksum="34409" --></p>
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2002<!--webbot bot="Timestamp" endspan i-checksum="39336" --></p>
|
||||
|
||||
</body>
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace boost
|
||||
std::ios_base::openmode mode )
|
||||
{
|
||||
return std::basic_filebuf<charT,traits>::open(
|
||||
file_ph.file_c_str(), mode );
|
||||
file_ph.file_path().c_str(), mode );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -48,13 +48,13 @@ namespace boost
|
||||
explicit basic_ifstream( const path & file_ph,
|
||||
std::ios_base::openmode mode = std::ios_base::in )
|
||||
: std::basic_ifstream<charT,traits>(
|
||||
file_ph.file_c_str(), mode ) {}
|
||||
file_ph.file_path().c_str(), mode ) {}
|
||||
virtual ~basic_ifstream() {}
|
||||
void open( const path & file_ph,
|
||||
std::ios_base::openmode mode = std::ios_base::in )
|
||||
{
|
||||
std::basic_ifstream<charT,traits>::open(
|
||||
file_ph.file_c_str(), mode );
|
||||
file_ph.file_path().c_str(), mode );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -71,13 +71,13 @@ namespace boost
|
||||
explicit basic_ofstream( const path & file_ph,
|
||||
std::ios_base::openmode mode = std::ios_base::out )
|
||||
: std::basic_ofstream<charT,traits>(
|
||||
file_ph.file_c_str(), mode ) {}
|
||||
file_ph.file_path().c_str(), mode ) {}
|
||||
virtual ~basic_ofstream() {}
|
||||
void open( const path & file_ph,
|
||||
std::ios_base::openmode mode = std::ios_base::out )
|
||||
{
|
||||
std::basic_ofstream<charT,traits>::open(
|
||||
file_ph.file_c_str(), mode );
|
||||
file_ph.file_path().c_str(), mode );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -94,13 +94,13 @@ namespace boost
|
||||
explicit basic_fstream( const path & file_ph,
|
||||
std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out )
|
||||
: std::basic_fstream<charT,traits>(
|
||||
file_ph.file_c_str(), mode ) {}
|
||||
file_ph.file_path().c_str(), mode ) {}
|
||||
virtual ~basic_fstream() {}
|
||||
void open( const path & file_ph,
|
||||
std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out )
|
||||
{
|
||||
std::basic_fstream<charT,traits>::open(
|
||||
file_ph.file_c_str(), mode );
|
||||
file_ph.file_path().c_str(), mode );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -24,8 +24,7 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/smart_ptr.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -45,7 +44,7 @@ namespace boost
|
||||
// VC++ 7.0 and earlier has a serious namespace bug that causes a clash
|
||||
// between boost::filesystem::is_empty and the unrelated type trait
|
||||
// boost::is_empty. The workaround for those who must use broken versions
|
||||
// of VC++ is to use the function _is_empty. All others should use the
|
||||
// of VC++ is to use the function _is_empty. All others should use the
|
||||
// correct is_empty name.
|
||||
bool _is_empty( const path & ph ); // deprecated
|
||||
|
||||
@@ -69,46 +68,59 @@ namespace boost
|
||||
|
||||
const path & initial_directory();
|
||||
|
||||
// directory_iterator details ----------------------------------------------//
|
||||
|
||||
namespace detail
|
||||
{
|
||||
const char * implementation_name();
|
||||
|
||||
class directory_iterator_imp;
|
||||
|
||||
struct directory_iterator_internals
|
||||
{
|
||||
typedef boost::shared_ptr< detail::directory_iterator_imp > dii_ptr;
|
||||
dii_ptr imp;
|
||||
|
||||
const path & deref() const;
|
||||
void inc();
|
||||
};
|
||||
|
||||
struct dii_policies : public default_iterator_policies
|
||||
{
|
||||
|
||||
template <class IteratorAdaptor>
|
||||
typename IteratorAdaptor::reference
|
||||
dereference(const IteratorAdaptor& x) const
|
||||
{ return x.base().deref(); }
|
||||
|
||||
template <class IteratorAdaptor>
|
||||
void increment(IteratorAdaptor& x)
|
||||
{ x.base().inc(); }
|
||||
|
||||
template <class IteratorAdaptor1, class IteratorAdaptor2>
|
||||
bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
|
||||
{ return x.base().imp == y.base().imp; }
|
||||
};
|
||||
}
|
||||
|
||||
// directory_iterator ------------------------------------------------------//
|
||||
|
||||
class directory_iterator:
|
||||
public boost::iterator< std::input_iterator_tag,
|
||||
path, const path *, const path & >,
|
||||
public boost::equality_comparable1< directory_iterator >,
|
||||
public boost::dereferenceable< directory_iterator,
|
||||
const path * >,
|
||||
public boost::incrementable< directory_iterator >
|
||||
class directory_iterator
|
||||
: public boost::iterator_adaptor<
|
||||
// because directory_iterator is an InputIterator, shallow copy-
|
||||
// semantics are required, and shared_ptr provides that.
|
||||
detail::directory_iterator_internals,
|
||||
detail::dii_policies,
|
||||
path, const path &, const path *,
|
||||
std::input_iterator_tag, std::ptrdiff_t >
|
||||
{
|
||||
public:
|
||||
typedef boost::iterator<
|
||||
std::input_iterator_tag,
|
||||
path > base;
|
||||
typedef base::value_type value_type;
|
||||
typedef base::difference_type difference_type;
|
||||
typedef base::pointer pointer;
|
||||
typedef base::reference reference;
|
||||
typedef base::iterator_category iterator_category;
|
||||
directory_iterator(); // creates the "end" iterator
|
||||
explicit directory_iterator( const path & directory_path );
|
||||
|
||||
directory_iterator(); // creates the "end" iterator
|
||||
explicit directory_iterator( const path & directory_ph );
|
||||
|
||||
// compiler generates copy constructor, copy assignment, and destructor
|
||||
|
||||
bool operator==( const directory_iterator & ) const;
|
||||
|
||||
const path & operator*() const;
|
||||
|
||||
directory_iterator & operator++();
|
||||
|
||||
private:
|
||||
// because directory_iterator is an InputIterator, shallow copy
|
||||
// semantics are required, and shared_ptr provides that.
|
||||
boost::shared_ptr<detail::directory_iterator_imp> m_imp;
|
||||
// workaround iterator_adaptor / compiler interactions
|
||||
const boost::filesystem::path * operator->() const
|
||||
{ return &base().deref(); }
|
||||
};
|
||||
|
||||
} // namespace filesystem
|
||||
|
||||
@@ -77,10 +77,6 @@ namespace boost
|
||||
const std::string leaf() const;
|
||||
const path branch() const;
|
||||
|
||||
// deprecated
|
||||
const char * file_c_str() const { return m_path.c_str(); }
|
||||
const char * directory_c_str() const { return m_path.c_str(); }
|
||||
|
||||
// iteration over the names in the path:
|
||||
typedef boost::iterator_adaptor<
|
||||
detail::path_itr_imp,
|
||||
@@ -119,6 +115,7 @@ namespace boost
|
||||
void m_path_append( const std::string & src,
|
||||
source_context context = generic );
|
||||
|
||||
public: // should be private, but friend functions don't work for me
|
||||
void m_replace_leaf( const char * new_leaf );
|
||||
};
|
||||
|
||||
|
||||
@@ -99,16 +99,16 @@ namespace boost
|
||||
public:
|
||||
recursive_directory_iterator( const path & pth, Predicate pred )
|
||||
{
|
||||
base().reset( new detail::rdi_imp<Predicate>( pth, pred ) );
|
||||
this->base().reset( new detail::rdi_imp<Predicate>( pth, pred ) );
|
||||
}
|
||||
recursive_directory_iterator() // the past-the-end iterator
|
||||
{
|
||||
base().reset( new detail::rdi_imp<Predicate> );
|
||||
this->base().reset( new detail::rdi_imp<Predicate> );
|
||||
}
|
||||
|
||||
// workaround iterator_adaptor / compiler interactions
|
||||
const boost::filesystem::path * operator->() const
|
||||
{ return &*base()->stac.top(); }
|
||||
{ return &*this->base()->stac.top(); }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=doc/index.html">
|
||||
<meta http-equiv="refresh" content="0; URL=doc/index.htm">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="doc/index.html">doc/index.html</a>.
|
||||
<a href="doc/index.htm">doc/index.htm</a>.
|
||||
</body>
|
||||
</html>
|
||||
@@ -159,17 +159,20 @@ namespace
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
// path_descriptor_imp -----------------------------------------------------//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace filesystem
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
#ifdef BOOST_POSIX
|
||||
const char * implementation_name() { return "POSIX"; }
|
||||
#else
|
||||
const char * implementation_name() { return "Windows"; }
|
||||
#endif
|
||||
|
||||
// directory_iterator_imp --------------------------------------------------//
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class directory_iterator_imp
|
||||
{
|
||||
public:
|
||||
@@ -186,64 +189,60 @@ namespace boost
|
||||
|
||||
// directory_iterator implementation ---------------------------------------//
|
||||
|
||||
// default ctor creates the "end" iterator (by letting m_imp default to 0)
|
||||
// default ctor creates the "end" iterator (by letting base default to 0)
|
||||
directory_iterator::directory_iterator() {}
|
||||
|
||||
directory_iterator::directory_iterator( const path & dir_path )
|
||||
: m_imp( new detail::directory_iterator_imp )
|
||||
{
|
||||
base().imp.reset( new detail::directory_iterator_imp );
|
||||
BOOST_SYSTEM_DIRECTORY_TYPE scratch;
|
||||
const char * name;
|
||||
if ( dir_path.is_null() )
|
||||
m_imp->handle = BOOST_INVALID_HANDLE_VALUE;
|
||||
base().imp->handle = BOOST_INVALID_HANDLE_VALUE;
|
||||
else
|
||||
name = find_first_file( dir_path.directory_c_str(),
|
||||
m_imp->handle, scratch ); // sets handle
|
||||
name = find_first_file( dir_path.directory_path().c_str(),
|
||||
base().imp->handle, scratch ); // sets handle
|
||||
|
||||
if ( m_imp->handle != BOOST_INVALID_HANDLE_VALUE )
|
||||
if ( base().imp->handle != BOOST_INVALID_HANDLE_VALUE )
|
||||
{
|
||||
m_imp->entry_path = dir_path;
|
||||
m_imp->entry_path.m_path_append( name, path::nocheck );
|
||||
while ( m_imp.get()
|
||||
&& ( m_imp->entry_path.leaf() == "."
|
||||
|| m_imp->entry_path.leaf() == ".." ) )
|
||||
base().imp->entry_path = dir_path;
|
||||
base().imp->entry_path.m_path_append( name, path::nocheck );
|
||||
while ( base().imp.get()
|
||||
&& ( base().imp->entry_path.leaf() == "."
|
||||
|| base().imp->entry_path.leaf() == ".." ) )
|
||||
{ operator++(); }
|
||||
}
|
||||
else
|
||||
{
|
||||
throw filesystem_error( std::string(
|
||||
"directory_iterator constructor failure: " )
|
||||
+ dir_path.directory_c_str(), system_error );
|
||||
+ dir_path.directory_path().c_str(), system_error );
|
||||
}
|
||||
}
|
||||
|
||||
bool directory_iterator::operator== (
|
||||
directory_iterator const& itr ) const
|
||||
namespace detail
|
||||
{
|
||||
return m_imp == itr.m_imp;
|
||||
}
|
||||
|
||||
path const & directory_iterator::operator* () const
|
||||
{
|
||||
assert( m_imp.get() ); // fails if dereference end iterator
|
||||
return m_imp->entry_path;
|
||||
}
|
||||
|
||||
directory_iterator & directory_iterator::operator++ ()
|
||||
{
|
||||
assert( m_imp.get() ); // fails on increment end iterator
|
||||
assert( m_imp->handle != BOOST_INVALID_HANDLE_VALUE ); // imp reality check
|
||||
|
||||
BOOST_SYSTEM_DIRECTORY_TYPE scratch;
|
||||
const char * name;
|
||||
if ( (name = find_next_file( m_imp->handle, scratch )) != 0 )
|
||||
path const & directory_iterator_internals::deref() const
|
||||
{
|
||||
m_imp->entry_path.m_replace_leaf( name );
|
||||
assert( imp.get() ); // fails if dereference end iterator
|
||||
return imp->entry_path;
|
||||
}
|
||||
else {
|
||||
m_imp.reset(); // make m_imp the end iterator
|
||||
|
||||
void directory_iterator_internals::inc()
|
||||
{
|
||||
assert( imp.get() ); // fails on increment end iterator
|
||||
assert( imp->handle != BOOST_INVALID_HANDLE_VALUE ); // imp reality check
|
||||
|
||||
BOOST_SYSTEM_DIRECTORY_TYPE scratch;
|
||||
const char * name;
|
||||
if ( (name = find_next_file( imp->handle, scratch )) != 0 )
|
||||
{
|
||||
imp->entry_path.m_replace_leaf( name );
|
||||
}
|
||||
else {
|
||||
imp.reset(); // make base() the end iterator
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// free functions ----------------------------------------------------------//
|
||||
@@ -252,9 +251,9 @@ namespace boost
|
||||
{
|
||||
# ifdef BOOST_POSIX
|
||||
struct stat path_stat;
|
||||
return ::stat( ph.file_c_str(), &path_stat ) == 0;
|
||||
return ::stat( ph.file_path().c_str(), &path_stat ) == 0;
|
||||
# else
|
||||
return ::GetFileAttributes( ph.file_c_str() ) != 0xFFFFFFFF;
|
||||
return ::GetFileAttributes( ph.file_path().c_str() ) != 0xFFFFFFFF;
|
||||
# endif
|
||||
}
|
||||
|
||||
@@ -262,15 +261,15 @@ namespace boost
|
||||
{
|
||||
# ifdef BOOST_POSIX
|
||||
struct stat path_stat;
|
||||
if ( ::stat( ph.directory_c_str(), &path_stat ) != 0 )
|
||||
if ( ::stat( ph.directory_path().c_str(), &path_stat ) != 0 )
|
||||
throw filesystem_error( std::string("is_directory(): ")
|
||||
+ ph.directory_c_str(), system_error );
|
||||
+ ph.directory_path().c_str(), system_error );
|
||||
return S_ISDIR( path_stat.st_mode );
|
||||
# else
|
||||
DWORD attributes = ::GetFileAttributes( ph.directory_c_str() );
|
||||
DWORD attributes = ::GetFileAttributes( ph.directory_path().c_str() );
|
||||
if ( attributes == 0xFFFFFFFF )
|
||||
throw filesystem_error( std::string("is_directory(): ")
|
||||
+ ph.directory_c_str(), system_error );
|
||||
+ ph.directory_path().c_str(), system_error );
|
||||
return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
# endif
|
||||
}
|
||||
@@ -279,19 +278,19 @@ namespace boost
|
||||
{
|
||||
# ifdef BOOST_POSIX
|
||||
struct stat path_stat;
|
||||
if ( ::stat( ph.file_c_str(), &path_stat ) != 0 )
|
||||
if ( ::stat( ph.file_path().c_str(), &path_stat ) != 0 )
|
||||
throw filesystem_error( std::string("is_empty(): ")
|
||||
+ ph.file_c_str(), system_error );
|
||||
+ ph.file_path().c_str(), system_error );
|
||||
|
||||
return S_ISDIR( path_stat.st_mode )
|
||||
? is_empty_directory( ph )
|
||||
: path_stat.st_size == 0;
|
||||
# else
|
||||
WIN32_FILE_ATTRIBUTE_DATA fad;
|
||||
if ( !::GetFileAttributesEx( ph.file_c_str(),
|
||||
if ( !::GetFileAttributesEx( ph.file_path().c_str(),
|
||||
::GetFileExInfoStandard, &fad ) )
|
||||
throw filesystem_error( std::string("is_empty(): ")
|
||||
+ ph.file_c_str(), system_error );
|
||||
+ ph.file_path().c_str(), system_error );
|
||||
|
||||
return ( fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
|
||||
? is_empty_directory( ph )
|
||||
@@ -302,39 +301,39 @@ namespace boost
|
||||
void create_directory( const path & dir_path )
|
||||
{
|
||||
# ifdef BOOST_POSIX
|
||||
if ( ::mkdir( dir_path.directory_c_str(),
|
||||
if ( ::mkdir( dir_path.directory_path().c_str(),
|
||||
S_IRWXU|S_IRWXG|S_IRWXO ) != 0 )
|
||||
# else
|
||||
if ( !::CreateDirectory( dir_path.directory_c_str(), 0 ) )
|
||||
if ( !::CreateDirectory( dir_path.directory_path().c_str(), 0 ) )
|
||||
# endif
|
||||
throw filesystem_error( std::string("create_directory(): ")
|
||||
+ dir_path.directory_c_str(), system_error );
|
||||
+ dir_path.directory_path().c_str(), system_error );
|
||||
}
|
||||
|
||||
void remove( const path & ph )
|
||||
{
|
||||
if ( !exists( ph ) )
|
||||
throw fs::filesystem_error( std::string("remove() on: ")
|
||||
+ ph.file_c_str(), system_error );
|
||||
if ( is_directory( ph ) )
|
||||
if ( exists( ph ) )
|
||||
{
|
||||
if ( is_directory( ph ) )
|
||||
{
|
||||
# ifdef BOOST_POSIX
|
||||
if ( ::rmdir( ph.file_c_str() ) != 0 )
|
||||
if ( ::rmdir( ph.file_path().c_str() ) != 0 )
|
||||
# else
|
||||
if ( !::RemoveDirectory( ph.file_c_str() ) )
|
||||
if ( !::RemoveDirectory( ph.file_path().c_str() ) )
|
||||
# endif
|
||||
throw fs::filesystem_error( std::string("remove() on: ")
|
||||
+ ph.file_c_str(), system_error );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw fs::filesystem_error( std::string("remove() on: ")
|
||||
+ ph.file_path().c_str(), system_error );
|
||||
}
|
||||
else
|
||||
{
|
||||
# ifdef BOOST_POSIX
|
||||
if ( ::remove( ph.file_c_str() ) != 0 )
|
||||
if ( ::remove( ph.file_path().c_str() ) != 0 )
|
||||
# else
|
||||
if ( !::DeleteFile( ph.file_c_str() ) )
|
||||
if ( !::DeleteFile( ph.file_path().c_str() ) )
|
||||
# endif
|
||||
throw fs::filesystem_error( std::string("remove() on: ")
|
||||
+ ph.file_c_str(), system_error );
|
||||
throw fs::filesystem_error( std::string("remove() on: ")
|
||||
+ ph.file_path().c_str(), system_error );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,12 +347,12 @@ namespace boost
|
||||
{
|
||||
# ifdef BOOST_POSIX
|
||||
if ( exists( new_path ) // POSIX is too permissive so must check
|
||||
|| ::rename( old_path.file_c_str(), new_path.file_c_str() ) != 0 )
|
||||
|| ::rename( old_path.file_path().c_str(), new_path.file_path().c_str() ) != 0 )
|
||||
# else
|
||||
if ( !::MoveFile( old_path.file_c_str(), new_path.file_c_str() ) )
|
||||
if ( !::MoveFile( old_path.file_path().c_str(), new_path.file_path().c_str() ) )
|
||||
# endif
|
||||
throw filesystem_error( std::string("move_file(): ")
|
||||
+ old_path.file_c_str() + ", " + new_path.file_c_str(), system_error );
|
||||
+ old_path.file_path().c_str() + ", " + new_path.file_path().c_str(), system_error );
|
||||
}
|
||||
|
||||
void copy_file( const path & from_file_ph,
|
||||
@@ -366,16 +365,16 @@ namespace boost
|
||||
boost::scoped_array<char> buf( new char [buf_sz] );
|
||||
int infile, outfile;
|
||||
|
||||
if ( (infile = ::open( from_file_ph.file_c_str(),
|
||||
if ( (infile = ::open( from_file_ph.file_path().c_str(),
|
||||
O_RDONLY )) < 0
|
||||
|| (outfile = ::open( to_file_ph.file_c_str(),
|
||||
|| (outfile = ::open( to_file_ph.file_path().c_str(),
|
||||
O_WRONLY | O_CREAT | O_EXCL,
|
||||
S_IRWXU|S_IRWXG|S_IRWXO )) < 0 )
|
||||
{
|
||||
if ( infile != 0 ) ::close( infile );
|
||||
throw fs::filesystem_error( std::string("copy() files: ")
|
||||
+ from_file_ph.file_c_str()
|
||||
+ ", " + to_file_ph.file_c_str(), system_error );
|
||||
+ from_file_ph.file_path().c_str()
|
||||
+ ", " + to_file_ph.file_path().c_str(), system_error );
|
||||
}
|
||||
|
||||
ssize_t sz;
|
||||
@@ -387,12 +386,12 @@ namespace boost
|
||||
|
||||
if ( sz != 0 )
|
||||
# else
|
||||
if ( !::CopyFile( from_file_ph.file_c_str(),
|
||||
to_file_ph.file_c_str(), /*fail_if_exists=*/true ) )
|
||||
if ( !::CopyFile( from_file_ph.file_path().c_str(),
|
||||
to_file_ph.file_path().c_str(), /*fail_if_exists=*/true ) )
|
||||
# endif
|
||||
throw fs::filesystem_error( std::string("copy() files: ")
|
||||
+ from_file_ph.file_c_str()
|
||||
+ ", " + to_file_ph.file_c_str(), system_error );
|
||||
+ from_file_ph.file_path().c_str()
|
||||
+ ", " + to_file_ph.file_path().c_str(), system_error );
|
||||
}
|
||||
|
||||
const path & initial_directory()
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
#include <boost/filesystem/exception.hpp>
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
#define BOOST_INCLUDE_MAIN
|
||||
#include <boost/test/test_tools.hpp>
|
||||
//#include <boost/test/test_tools.hpp>
|
||||
#include <boost/test/minimal.hpp>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
using boost::bind;
|
||||
@@ -27,7 +27,7 @@ namespace
|
||||
|
||||
void create_file( const fs::path & ph, const std::string & contents )
|
||||
{
|
||||
std::ofstream f( ph.file_c_str() );
|
||||
std::ofstream f( ph.file_path().c_str() );
|
||||
if ( !f )
|
||||
throw fs::filesystem_error( "ofstream(): " + ph.generic_path() );
|
||||
if ( !contents.empty() ) f << contents;
|
||||
@@ -35,7 +35,7 @@ namespace
|
||||
|
||||
void verify_file( const fs::path & ph, const std::string & expected )
|
||||
{
|
||||
std::ifstream f( ph.file_c_str() );
|
||||
std::ifstream f( ph.file_path().c_str() );
|
||||
if ( !f )
|
||||
throw fs::filesystem_error( "ifstream(): " + ph.generic_path() );
|
||||
std::string contents;
|
||||
@@ -66,6 +66,8 @@ namespace
|
||||
|
||||
int test_main( int, char * [] )
|
||||
{
|
||||
std::cout << "implemenation name: "
|
||||
<< fs::detail::implementation_name() << "\n";
|
||||
std::cout << "initial_directory() is \""
|
||||
<< fs::initial_directory().generic_path()
|
||||
<< "\"\n";
|
||||
@@ -100,6 +102,11 @@ int test_main( int, char * [] )
|
||||
BOOST_TEST( fs::is_directory( d1 ) );
|
||||
BOOST_TEST( fs::_is_empty( d1 ) );
|
||||
|
||||
{
|
||||
fs::directory_iterator dir_itr( dir );
|
||||
BOOST_TEST( dir_itr->leaf() == "d1" );
|
||||
}
|
||||
|
||||
// create a second directory named d2
|
||||
fs::path d2( dir << "d2" );
|
||||
fs::create_directory(d2 );
|
||||
@@ -169,6 +176,8 @@ int test_main( int, char * [] )
|
||||
BOOST_TEST( !fs::is_directory( file_ph ) );
|
||||
fs::remove( file_ph );
|
||||
BOOST_TEST( !fs::exists( file_ph ) );
|
||||
fs::remove( "no-such-file" ); // should be harmless
|
||||
fs::remove( "no-such-directory/no-such-file" ); // ditto
|
||||
|
||||
// remove test on directory
|
||||
d1 = dir << "shortlife_dir";
|
||||
@@ -177,6 +186,7 @@ int test_main( int, char * [] )
|
||||
BOOST_TEST( fs::exists( d1 ) );
|
||||
BOOST_TEST( fs::is_directory( d1 ) );
|
||||
BOOST_TEST( fs::_is_empty( d1 ) );
|
||||
BOOST_TEST( throws_fs_error( bind( fs::remove, dir ) ) );
|
||||
fs::remove( d1 );
|
||||
BOOST_TEST( !fs::exists( d1 ) );
|
||||
|
||||
|
||||
Reference in New Issue
Block a user