head	1.2;
access;
symbols
	perseant-exfatfs-base-20261102:1.2
	perseant-exfatfs-base-20250801:1.2
	perseant-exfatfs-base-20240630:1.2
	perseant-exfatfs:1.2.0.24
	perseant-exfatfs-base:1.2
	cjep_sun2x:1.2.0.22
	cjep_sun2x-base:1.2
	cjep_staticlib_x-base1:1.2
	cjep_staticlib_x:1.2.0.20
	cjep_staticlib_x-base:1.2
	phil-wifi-20200421:1.2
	phil-wifi-20200411:1.2
	phil-wifi-20200406:1.2
	pgoyette-compat-merge-20190127:1.2
	pgoyette-compat-20190127:1.2
	pgoyette-compat-20190118:1.2
	pgoyette-compat-1226:1.2
	pgoyette-compat-1126:1.2
	pgoyette-compat-1020:1.2
	pgoyette-compat-0930:1.2
	pgoyette-compat-0906:1.2
	pgoyette-compat-0728:1.2
	pgoyette-compat-0625:1.2
	pgoyette-compat-0521:1.2
	pgoyette-compat-0502:1.2
	pgoyette-compat-0422:1.2
	pgoyette-compat-0415:1.2
	pgoyette-compat-0407:1.2
	pgoyette-compat-0330:1.2
	pgoyette-compat-0322:1.2
	pgoyette-compat-0315:1.2
	pgoyette-compat:1.2.0.18
	pgoyette-compat-base:1.2
	prg-localcount2-base3:1.2
	prg-localcount2-base2:1.2
	prg-localcount2-base1:1.2
	prg-localcount2:1.2.0.16
	prg-localcount2-base:1.2
	pgoyette-localcount-20170426:1.2
	bouyer-socketcan-base1:1.2
	pgoyette-localcount-20170320:1.2
	bouyer-socketcan:1.2.0.14
	bouyer-socketcan-base:1.2
	pgoyette-localcount-20170107:1.2
	pgoyette-localcount-20161104:1.2
	localcount-20160914:1.2
	pgoyette-localcount-20160806:1.2
	pgoyette-localcount-20160726:1.2
	pgoyette-localcount:1.2.0.12
	pgoyette-localcount-base:1.2
	netbsd-5-2-3-RELEASE:1.1.1.1
	netbsd-5-1-5-RELEASE:1.1.1.1
	yamt-pagecache-base9:1.2
	yamt-pagecache-tag8:1.2
	tls-earlyentropy:1.2.0.8
	tls-earlyentropy-base:1.2
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.2
	riastradh-drm2-base3:1.2
	netbsd-5-2-2-RELEASE:1.1.1.1
	netbsd-5-1-4-RELEASE:1.1.1.1
	netbsd-5-2-1-RELEASE:1.1.1.1
	netbsd-5-1-3-RELEASE:1.1.1.1
	agc-symver:1.2.0.10
	agc-symver-base:1.2
	tls-maxphys-base:1.2
	yamt-pagecache-base8:1.2
	netbsd-5-2:1.1.1.1.0.6
	yamt-pagecache-base7:1.2
	netbsd-5-2-RELEASE:1.1.1.1
	netbsd-5-2-RC1:1.1.1.1
	yamt-pagecache-base6:1.2
	yamt-pagecache-base5:1.2
	yamt-pagecache-base4:1.2
	netbsd-5-1-2-RELEASE:1.1.1.1
	netbsd-5-1-1-RELEASE:1.1.1.1
	yamt-pagecache-base3:1.2
	yamt-pagecache-base2:1.2
	yamt-pagecache:1.2.0.6
	yamt-pagecache-base:1.2
	bouyer-quota2-nbase:1.2
	bouyer-quota2:1.2.0.4
	bouyer-quota2-base:1.2
	matt-nb5-mips64-premerge-20101231:1.1.1.1
	matt-nb5-pq3:1.1.1.1.0.16
	matt-nb5-pq3-base:1.1.1.1
	netbsd-5-1:1.1.1.1.0.14
	netbsd-5-1-RELEASE:1.1.1.1
	netbsd-5-1-RC4:1.1.1.1
	matt-nb5-mips64-k15:1.1.1.1
	netbsd-5-1-RC3:1.1.1.1
	netbsd-5-1-RC2:1.1.1.1
	netbsd-5-1-RC1:1.1.1.1
	netbsd-5-0-2-RELEASE:1.1.1.1
	matt-nb5-mips64-premerge-20091211:1.1.1.1
	matt-nb5-mips64-u2-k2-k4-k7-k8-k9:1.1.1.1
	matt-nb4-mips64-k7-u2a-k9b:1.1.1.1
	matt-nb5-mips64-u1-k1-k5:1.1.1.1
	matt-nb5-mips64:1.1.1.1.0.12
	netbsd-5-0-1-RELEASE:1.1.1.1
	jym-xensuspend-nbase:1.2
	netbsd-5-0:1.1.1.1.0.10
	netbsd-5-0-RELEASE:1.1.1.1
	netbsd-5-0-RC4:1.1.1.1
	netbsd-5-0-RC3:1.1.1.1
	netbsd-5-0-RC2:1.1.1.1
	jym-xensuspend:1.2.0.2
	jym-xensuspend-base:1.2
	netbsd-5-0-RC1:1.1.1.1
	netbsd-5:1.1.1.1.0.8
	netbsd-5-base:1.1.1.1
	matt-mips64-base2:1.1.1.1
	wrstuden-revivesa-base-3:1.1.1.1
	wrstuden-revivesa-base-2:1.1.1.1
	wrstuden-revivesa-base-1:1.1.1.1
	yamt-pf42-base4:1.1.1.1
	yamt-pf42-base3:1.1.1.1
	hpcarm-cleanup-nbase:1.1.1.1
	yamt-pf42:1.1.1.1.0.4
	yamt-pf42-base2:1.1.1.1
	yamt-pf42-base:1.1.1.1
	wrstuden-revivesa:1.1.1.1.0.2
	wrstuden-revivesa-base:1.1.1.1
	atf-0-5:1.1.1.1
	TNF:1.1.1;
locks; strict;
comment	@// @;


1.2
date	2009.01.19.07.08.16;	author jmmv;	state dead;
branches;
next	1.1;

1.1
date	2008.05.01.15.22.30;	author jmmv;	state Exp;
branches
	1.1.1.1;
next	;

1.1.1.1
date	2008.05.01.15.22.30;	author jmmv;	state Exp;
branches
	1.1.1.1.4.1;
next	;

1.1.1.1.4.1
date	2008.05.01.15.22.30;	author yamt;	state dead;
branches;
next	1.1.1.1.4.2;

1.1.1.1.4.2
date	2008.05.18.12.29.12;	author yamt;	state Exp;
branches;
next	;


desc
@@


1.2
log
@Remove ATF 0.5 from dist/atf and all of the reachover Makefiles used to
build it.  0.6 is going to be imported in external/bsd/atf, with all the
necessary Makefiles in that same hierarchy.
@
text
@//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

#if !defined(_ATF_CXX_IO_HPP_)
#define _ATF_CXX_IO_HPP_

#include <istream>
#include <ostream>
#include <streambuf>

#include <atf-c++/utils.hpp>

namespace atf {
namespace io {

// ------------------------------------------------------------------------
// The "file_handle" class.
// ------------------------------------------------------------------------

//!
//! \brief Simple RAII model for system file handles.
//!
//! The \a file_handle class is a simple RAII model for native system file
//! handles.  This class wraps one of such handles grabbing its ownership,
//! and automaticaly closes it upon destruction.  It is basically used
//! inside the library to avoid leaking open file handles, shall an
//! unexpected execution trace occur.
//!
//! A \a file_handle object can be copied but doing so invalidates the
//! source object.  There can only be a single valid \a file_handle object
//! for a given system file handle.  This is similar to std::auto_ptr\<\>'s
//! semantics.
//!
//! This class also provides some convenience methods to issue special file
//! operations under their respective platforms.
//!
class file_handle
{
public:
    //!
    //! \brief Opaque name for the native handle type.
    //!
    //! Each operating system identifies file handles using a specific type.
    //! The \a handle_type type is used to transparently refer to file
    //! handles regarless of the operating system in which this class is
    //! used.
    //!
    //! If this class is used in a POSIX system, \a NativeSystemHandle is
    //! an integer type while it is a \a HANDLE in a Win32 system.
    //!
    typedef int handle_type;

    //!
    //! \brief Constructs an invalid file handle.
    //!
    //! This constructor creates a new \a file_handle object that represents
    //! an invalid file handle.  An invalid file handle can be copied but
    //! cannot be manipulated in any way (except checking for its validity).
    //!
    //! \see is_valid()
    //!
    file_handle(void);

    //!
    //! \brief Constructs a new file handle from a native file handle.
    //!
    //! This constructor creates a new \a file_handle object that takes
    //! ownership of the given \a h native file handle.  The user must not
    //! close \a h on his own during the lifetime of the new object.
    //! Ownership can be reclaimed using disown().
    //!
    //! \pre The native file handle must be valid; a close operation must
    //!      succeed on it.
    //!
    //! \see disown()
    //!
    file_handle(handle_type h);

    //!
    //! \brief Copy constructor; invalidates the source handle.
    //!
    //! This copy constructor creates a new file handle from a given one.
    //! Ownership of the native file handle is transferred to the new
    //! object, effectively invalidating the source file handle.  This
    //! avoids having two live \a file_handle objects referring to the
    //! same native file handle.  The source file handle need not be
    //! valid in the name of simplicity.
    //!
    //! \post The source file handle is invalid.
    //! \post The new file handle owns the source's native file handle.
    //!
    file_handle(const file_handle& fh);

    //!
    //! \brief Releases resources if the handle is valid.
    //!
    //! If the file handle is valid, the destructor closes it.
    //!
    //! \see is_valid()
    //!
    ~file_handle(void);

    //!
    //! \brief Assignment operator; invalidates the source handle.
    //!
    //! This assignment operator transfers ownership of the RHS file
    //! handle to the LHS one, effectively invalidating the source file
    //! handle.  This avoids having two live \a file_handle objects
    //! referring to the same native file handle.  The source file
    //! handle need not be valid in the name of simplicity.
    //!
    //! \post The RHS file handle is invalid.
    //! \post The LHS file handle owns RHS' native file handle.
    //! \return A reference to the LHS file handle.
    //!
    file_handle& operator=(const file_handle& fh);

    //!
    //! \brief Checks whether the file handle is valid or not.
    //!
    //! Returns a boolean indicating whether the file handle is valid or
    //! not.  If the file handle is invalid, no other applications can be
    //! executed other than the destructor.
    //!
    //! \return True if the file handle is valid; false otherwise.
    //!
    bool is_valid(void) const;

    //!
    //! \brief Closes the file handle.
    //!
    //! Explicitly closes the file handle, which must be valid.  Upon
    //! exit, the handle is not valid any more.
    //!
    //! \pre The file handle is valid.
    //! \post The file handle is invalid.
    //! \post The native file handle is closed.
    //!
    void close(void);

    //!
    //! \brief Reclaims ownership of the native file handle.
    //!
    //! Explicitly reclaims ownership of the native file handle contained
    //! in the \a file_handle object, returning the native file handle.
    //! The caller is responsible of closing it later on.
    //!
    //! \pre The file handle is valid.
    //! \post The file handle is invalid.
    //! \return The native file handle.
    //!
    handle_type disown(void);

    //!
    //! \brief Gets the native file handle.
    //!
    //! Returns the native file handle for the \a file_handle object.
    //! The caller can issue any operation on it except closing it.
    //! If closing is required, disown() shall be used.
    //!
    //! \pre The file handle is valid.
    //! \return The native file handle.
    //!
    handle_type get(void) const;

    //!
    //! \brief Changes the native file handle to the given one.
    //!
    //! Given a new native file handle \a h, this operation assigns this
    //! handle to the current object, closing its old native file handle.
    //! In other words, it first calls dup2() to remap the old handle to
    //! the new one and then closes the old handle.
    //!
    //! If \a h matches the current value of the handle, this is a no-op.
    //! This is done for simplicity, to avoid the caller having to check
    //! this condition on its own.
    //!
    //! If \a h is open, it is automatically closed by dup2().
    //!
    //! This operation is only available in POSIX systems.
    //!
    //! \pre The file handle is valid.
    //! \pre The native file handle \a h is valid; i.e., it must be
    //!      closeable.
    //! \post The file handle's native file handle is \a h.
    //! \throw system_error If the internal remapping operation fails.
    //!
    void posix_remap(handle_type h);

private:
    //!
    //! \brief Internal handle value.
    //!
    //! This variable holds the native handle value for the file handle
    //! hold by this object.  It is interesting to note that this needs
    //! to be mutable because the copy constructor and the assignment
    //! operator invalidate the source object.
    //!
    mutable handle_type m_handle;

    //!
    //! \brief Constant function representing an invalid handle value.
    //!
    //! Returns the platform-specific handle value that represents an
    //! invalid handle.  This is a constant function rather than a regular
    //! constant because, in the latter case, we cannot define it under
    //! Win32 due to the value being of a complex type.
    //!
    static const handle_type invalid_value(void);
};

// ------------------------------------------------------------------------
// The "systembuf" class.
// ------------------------------------------------------------------------

//!
//! \brief std::streambuf implementation for system file handles.
//!
//! systembuf provides a std::streambuf implementation for system file
//! handles.  Contrarywise to file_handle, this class does \b not take
//! ownership of the native file handle; this should be taken care of
//! somewhere else.
//!
//! This class follows the expected semantics of a std::streambuf object.
//! However, it is not copyable to avoid introducing inconsistences with
//! the on-disk file and the in-memory buffers.
//!
class systembuf :
    public std::streambuf, utils::noncopyable
{
public:
    typedef int handle_type;

    //!
    //! \brief Constructs a new systembuf for the given file handle.
    //!
    //! This constructor creates a new systembuf object that reads or
    //! writes data from/to the \a h native file handle.  This handle
    //! is \b not owned by the created systembuf object; the code
    //! should take care of it externally.
    //!
    //! This class buffers input and output; the buffer size may be
    //! tuned through the \a bufsize parameter, which defaults to 8192
    //! bytes.
    //!
    //! \see pistream and postream.
    //!
    explicit systembuf(handle_type h, std::size_t bufsize = 8192);
    ~systembuf(void);

private:
    //!
    //! \brief Native file handle used by the systembuf object.
    //!
    handle_type m_handle;

    //!
    //! \brief Internal buffer size used during read and write operations.
    //!
    std::size_t m_bufsize;

    //!
    //! \brief Internal buffer used during read operations.
    //!
    char* m_read_buf;

    //!
    //! \brief Internal buffer used during write operations.
    //!
    char* m_write_buf;

protected:
    //!
    //! \brief Reads new data from the native file handle.
    //!
    //! This operation is called by input methods when there are no more
    //! data in the input buffer.  The function fills the buffer with new
    //! data, if available.
    //!
    //! \pre All input positions are exhausted (gptr() >= egptr()).
    //! \post The input buffer has new data, if available.
    //! \returns traits_type::eof() if a read error occurrs or there are
    //!          no more data to be read.  Otherwise returns
    //!          traits_type::to_int_type(*gptr()).
    //!
    virtual int_type underflow(void);

    //!
    //! \brief Makes room in the write buffer for additional data.
    //!
    //! This operation is called by output methods when there is no more
    //! space in the output buffer to hold a new element.  The function
    //! first flushes the buffer's contents to disk and then clears it to
    //! leave room for more characters.  The given \a c character is
    //! stored at the beginning of the new space.
    //!
    //! \pre All output positions are exhausted (pptr() >= epptr()).
    //! \post The output buffer has more space if no errors occurred
    //!       during the write to disk.
    //! \post *(pptr() - 1) is \a c.
    //! \returns traits_type::eof() if a write error occurrs.  Otherwise
    //!          returns traits_type::not_eof(c).
    //!
    virtual int_type overflow(int c);

    //!
    //! \brief Flushes the output buffer to disk.
    //!
    //! Synchronizes the systembuf buffers with the contents of the file
    //! associated to this object through the native file handle.  The
    //! output buffer is flushed to disk and cleared to leave new room
    //! for more data.
    //!
    //! \returns 0 on success, -1 if an error occurred.
    //!
    virtual int sync(void);
};

// ------------------------------------------------------------------------
// The "pipe" class.
// ------------------------------------------------------------------------

//!
//! \brief Simple RAII model for anonymous pipes.
//!
//! The pipe class is a simple RAII model for anonymous pipes.  It
//! provides a portable constructor that allocates a new %pipe and creates
//! a pipe object that owns the two file handles associated to it: the
//! read end and the write end.
//!
//! These handles can be retrieved for modification according to
//! file_handle semantics.  Optionally, their ownership can be transferred
//! to external \a file_handle objects which comes handy when the two
//! ends need to be used in different places (i.e. after a POSIX fork()
//! system call).
//!
//! Pipes can be copied following the same semantics as file handles.
//! In other words, copying a %pipe object invalidates the source one.
//!
//! \see file_handle
//!
class pipe
{
    //!
    //! \brief The %pipe's read end file handle.
    //!
    file_handle m_read_end;

    //!
    //! \brief The %pipe's write end file handle.
    //!
    file_handle m_write_end;

public:
    //!
    //! \brief Creates a new %pipe.
    //!
    //! The default pipe constructor allocates a new anonymous %pipe
    //! and assigns its ownership to the created pipe object.
    //!
    //! \throw system_error If the anonymous %pipe creation fails.
    //!
    pipe(void);

    //!
    //! \brief Returns the %pipe's read end file handle.
    //!
    //! Obtains a reference to the %pipe's read end file handle.  Care
    //! should be taken to not duplicate the returned object if ownership
    //! shall remain to the %pipe.
    //!
    //! Duplicating the returned object invalidates its corresponding file
    //! handle in the %pipe.
    //!
    //! \return A reference to the %pipe's read end file handle.
    //!
    file_handle& rend(void);

    //!
    //! \brief Returns the %pipe's write end file handle.
    //!
    //! Obtains a reference to the %pipe's write end file handle.  Care
    //! should be taken to not duplicate the returned object if ownership
    //! shall remain to the %pipe.
    //!
    //! Duplicating the returned object invalidates its corresponding file
    //! handle in the %pipe.
    //!
    //! \return A reference to the %pipe's write end file handle.
    //!
    file_handle& wend(void);
};

// ------------------------------------------------------------------------
// The "pistream" class.
// ------------------------------------------------------------------------

//!
//! \brief Child process' output stream.
//!
//! The pistream class represents an output communication channel with the
//! child process.  The child process writes data to this stream and the
//! parent process can read it through the pistream object.  In other
//! words, from the child's point of view, the communication channel is an
//! output one, but from the parent's point of view it is an input one;
//! hence the confusing pistream name.
//!
//! pistream objects cannot be copied because they own the file handle
//! they use to communicate with the child and because they buffer data
//! that flows through the communication channel.
//!
//! A pistream object behaves as a std::istream stream in all senses.
//! The class is only provided because it must provide a method to let
//! the caller explicitly close the communication channel.
//!
//! \remark <b>Blocking remarks</b>: Functions that read data from this
//! stream can block if the associated file handle blocks during the read.
//! As this class is used to communicate with child processes through
//! anonymous pipes, the most typical blocking condition happens when the
//! child has no more data to send to the pipe's system buffer.  When
//! this happens, the buffer eventually empties and the system blocks
//! until the writer generates some data.
//!
class pistream :
    public std::istream, utils::noncopyable
{
    //!
    //! \brief The file handle managed by this stream.
    //!
    file_handle m_handle;

    //!
    //! \brief The systembuf object used to manage this stream's data.
    //!
    systembuf m_systembuf;

public:
    //!
    //! \brief Creates a new process' output stream.
    //!
    //! Given a file handle, this constructor creates a new pistream
    //! object that owns the given file handle \a fh.  Ownership of
    //! \a fh is transferred to the created pistream object.
    //!
    //! \pre \a fh is valid.
    //! \post \a fh is invalid.
    //! \post The new pistream object owns \a fh.
    //!
    explicit pistream(file_handle& fh);

    //!
    //! \brief Closes the file handle managed by this stream.
    //!
    //! Explicitly closes the file handle managed by this stream.  This
    //! function can be used by the user to tell the child process it's
    //! not willing to receive more data.
    //!
    void close(void);

    //!
    //! \brief Returns the file descriptor attached to this stream.
    //!
    file_handle& handle(void);
};

// ------------------------------------------------------------------------
// The "postream" class.
// ------------------------------------------------------------------------

//!
//! \brief Child process' input stream.
//!
//! The postream class represents an input communication channel with the
//! child process.  The child process reads data from this stream and the
//! parent process can write to it through the postream object.  In other
//! words, from the child's point of view, the communication channel is an
//! input one, but from the parent's point of view it is an output one;
//! hence the confusing postream name.
//!
//! postream objects cannot be copied because they own the file handle
//! they use to communicate with the child and because they buffer data
//! that flows through the communication channel.
//!
//! A postream object behaves as a std::ostream stream in all senses.
//! The class is only provided because it must provide a method to let
//! the caller explicitly close the communication channel.
//!
//! \remark <b>Blocking remarks</b>: Functions that write data to this
//! stream can block if the associated file handle blocks during the write.
//! As this class is used to communicate with child processes through
//! anonymous pipes, the most typical blocking condition happens when the
//! child is not processing the data in the pipe's system buffer.  When
//! this happens, the buffer eventually fills up and the system blocks
//! until the reader consumes some data, leaving some new room.
//!
class postream :
    public std::ostream, utils::noncopyable
{
    //!
    //! \brief The file handle managed by this stream.
    //!
    file_handle m_handle;

    //!
    //! \brief The systembuf object used to manage this stream's data.
    //!
    systembuf m_systembuf;

public:
    //!
    //! \brief Creates a new process' input stream.
    //!
    //! Given a file handle, this constructor creates a new postream
    //! object that owns the given file handle \a fh.  Ownership of
    //! \a fh is transferred to the created postream object.
    //!
    //! \pre \a fh is valid.
    //! \post \a fh is invalid.
    //! \post The new postream object owns \a fh.
    //!
    explicit postream(file_handle& fh);

    //!
    //! \brief Closes the file handle managed by this stream.
    //!
    //! Explicitly closes the file handle managed by this stream.  This
    //! function can be used by the user to tell the child process there
    //! is no more data to send.
    //!
    void close(void);

    //!
    //! \brief Returns the file descriptor attached to this stream.
    //!
    file_handle& handle(void);
};

// ------------------------------------------------------------------------
// The "unbuffered_istream" class.
// ------------------------------------------------------------------------

//!
//! \brief An unbuffered input stream.
//!
//! The unbuffered_istream class somewhat mimics the interface of
//! std::istream, but it provides unbuffered access to its attached
//! file descriptor.  This is required in those situations where poll(2)
//! is needed, because buffering data will mangle the events reported by
//! this system call and break algorithms mysteriously on some platforms.
//!
class unbuffered_istream {
    //!
    //! \brief The file descriptor attached to this stream.
    //!
    file_handle m_fh;

    //!
    //! \brief Whether the stream is good or not.
    //!
    bool m_is_good;

public:
    //!
    //! \brief Constructs a new unbuffered input stream.
    //!
    //! Given a file handle, constructs a new unbuffered input stream to
    //! handle it and takes ownership of that handle.
    //!
    unbuffered_istream(file_handle& fh);

    //!
    //! \brief Returns a reference to this stream's file handle.
    //!
    file_handle& get_fh(void);

    //!
    //! \brief Checks whether the stream is good or not for reading.
    //!
    bool good(void) const;

    //!
    //! \brief Reads unformatted data.
    //!
    //! Reads data from this stream onto the buffer specified and returns
    //! the amount of data read.  To detect errors, check for the stream's
    //! status using the good method after a call to this function.
    //!
    size_t read(void*, size_t);

    //!
    //! \brief Closes the stream.
    //!
    void close(void);
};

// ------------------------------------------------------------------------
// Free functions.
// ------------------------------------------------------------------------

//!
//! \brief Unbuffered getline implementation.
//!
//! Reads a text line from the given stream without buffering any data.
//! This is inefficient but is the only way to safely use poll(2)...
//!
unbuffered_istream& getline(unbuffered_istream&, std::string&);

} // namespace io
} // namespace atf

#endif // !defined(_ATF_CXX_IO_HPP_)
@


1.1
log
@Initial revision
@
text
@@


1.1.1.1
log
@Import ATF 0.5

Changes in this release:

* Clauses 3 and 4 of the BSD license used by the project were dropped.
  All the code is now under a 2-clause BSD license compatible with the
  GNU General Public License (GPL).

* Added a C-only binding so that binary test programs do not need to be
  tied to C++ at all.  This binding is now known as the atf-c library.

* Renamed the C++ binding to atf-c++ for consistency with the new atf-c.

* Renamed the POSIX shell binding to atf-sh for consistency with the new
  atf-c and atf-c++.

* Added a -w flag to test programs through which it is possible to specify
  the work directory to be used.  This was possible in prior releases by
  defining the workdir configuration variable (-v workdir=...), but was a
  conceptually incorrect mechanism.

* Test programs now preserve the execution order of test cases when they
  are given in the command line.  Even those mentioned more than once are
  executed multiple times to comply with the user's requests.
@
text
@@


1.1.1.1.4.1
log
@file io.hpp was added on branch yamt-pf42 on 2008-05-18 12:29:12 +0000
@
text
@d1 637
@


1.1.1.1.4.2
log
@sync with head.
@
text
@a0 637
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

#if !defined(_ATF_CXX_IO_HPP_)
#define _ATF_CXX_IO_HPP_

#include <istream>
#include <ostream>
#include <streambuf>

#include <atf-c++/utils.hpp>

namespace atf {
namespace io {

// ------------------------------------------------------------------------
// The "file_handle" class.
// ------------------------------------------------------------------------

//!
//! \brief Simple RAII model for system file handles.
//!
//! The \a file_handle class is a simple RAII model for native system file
//! handles.  This class wraps one of such handles grabbing its ownership,
//! and automaticaly closes it upon destruction.  It is basically used
//! inside the library to avoid leaking open file handles, shall an
//! unexpected execution trace occur.
//!
//! A \a file_handle object can be copied but doing so invalidates the
//! source object.  There can only be a single valid \a file_handle object
//! for a given system file handle.  This is similar to std::auto_ptr\<\>'s
//! semantics.
//!
//! This class also provides some convenience methods to issue special file
//! operations under their respective platforms.
//!
class file_handle
{
public:
    //!
    //! \brief Opaque name for the native handle type.
    //!
    //! Each operating system identifies file handles using a specific type.
    //! The \a handle_type type is used to transparently refer to file
    //! handles regarless of the operating system in which this class is
    //! used.
    //!
    //! If this class is used in a POSIX system, \a NativeSystemHandle is
    //! an integer type while it is a \a HANDLE in a Win32 system.
    //!
    typedef int handle_type;

    //!
    //! \brief Constructs an invalid file handle.
    //!
    //! This constructor creates a new \a file_handle object that represents
    //! an invalid file handle.  An invalid file handle can be copied but
    //! cannot be manipulated in any way (except checking for its validity).
    //!
    //! \see is_valid()
    //!
    file_handle(void);

    //!
    //! \brief Constructs a new file handle from a native file handle.
    //!
    //! This constructor creates a new \a file_handle object that takes
    //! ownership of the given \a h native file handle.  The user must not
    //! close \a h on his own during the lifetime of the new object.
    //! Ownership can be reclaimed using disown().
    //!
    //! \pre The native file handle must be valid; a close operation must
    //!      succeed on it.
    //!
    //! \see disown()
    //!
    file_handle(handle_type h);

    //!
    //! \brief Copy constructor; invalidates the source handle.
    //!
    //! This copy constructor creates a new file handle from a given one.
    //! Ownership of the native file handle is transferred to the new
    //! object, effectively invalidating the source file handle.  This
    //! avoids having two live \a file_handle objects referring to the
    //! same native file handle.  The source file handle need not be
    //! valid in the name of simplicity.
    //!
    //! \post The source file handle is invalid.
    //! \post The new file handle owns the source's native file handle.
    //!
    file_handle(const file_handle& fh);

    //!
    //! \brief Releases resources if the handle is valid.
    //!
    //! If the file handle is valid, the destructor closes it.
    //!
    //! \see is_valid()
    //!
    ~file_handle(void);

    //!
    //! \brief Assignment operator; invalidates the source handle.
    //!
    //! This assignment operator transfers ownership of the RHS file
    //! handle to the LHS one, effectively invalidating the source file
    //! handle.  This avoids having two live \a file_handle objects
    //! referring to the same native file handle.  The source file
    //! handle need not be valid in the name of simplicity.
    //!
    //! \post The RHS file handle is invalid.
    //! \post The LHS file handle owns RHS' native file handle.
    //! \return A reference to the LHS file handle.
    //!
    file_handle& operator=(const file_handle& fh);

    //!
    //! \brief Checks whether the file handle is valid or not.
    //!
    //! Returns a boolean indicating whether the file handle is valid or
    //! not.  If the file handle is invalid, no other applications can be
    //! executed other than the destructor.
    //!
    //! \return True if the file handle is valid; false otherwise.
    //!
    bool is_valid(void) const;

    //!
    //! \brief Closes the file handle.
    //!
    //! Explicitly closes the file handle, which must be valid.  Upon
    //! exit, the handle is not valid any more.
    //!
    //! \pre The file handle is valid.
    //! \post The file handle is invalid.
    //! \post The native file handle is closed.
    //!
    void close(void);

    //!
    //! \brief Reclaims ownership of the native file handle.
    //!
    //! Explicitly reclaims ownership of the native file handle contained
    //! in the \a file_handle object, returning the native file handle.
    //! The caller is responsible of closing it later on.
    //!
    //! \pre The file handle is valid.
    //! \post The file handle is invalid.
    //! \return The native file handle.
    //!
    handle_type disown(void);

    //!
    //! \brief Gets the native file handle.
    //!
    //! Returns the native file handle for the \a file_handle object.
    //! The caller can issue any operation on it except closing it.
    //! If closing is required, disown() shall be used.
    //!
    //! \pre The file handle is valid.
    //! \return The native file handle.
    //!
    handle_type get(void) const;

    //!
    //! \brief Changes the native file handle to the given one.
    //!
    //! Given a new native file handle \a h, this operation assigns this
    //! handle to the current object, closing its old native file handle.
    //! In other words, it first calls dup2() to remap the old handle to
    //! the new one and then closes the old handle.
    //!
    //! If \a h matches the current value of the handle, this is a no-op.
    //! This is done for simplicity, to avoid the caller having to check
    //! this condition on its own.
    //!
    //! If \a h is open, it is automatically closed by dup2().
    //!
    //! This operation is only available in POSIX systems.
    //!
    //! \pre The file handle is valid.
    //! \pre The native file handle \a h is valid; i.e., it must be
    //!      closeable.
    //! \post The file handle's native file handle is \a h.
    //! \throw system_error If the internal remapping operation fails.
    //!
    void posix_remap(handle_type h);

private:
    //!
    //! \brief Internal handle value.
    //!
    //! This variable holds the native handle value for the file handle
    //! hold by this object.  It is interesting to note that this needs
    //! to be mutable because the copy constructor and the assignment
    //! operator invalidate the source object.
    //!
    mutable handle_type m_handle;

    //!
    //! \brief Constant function representing an invalid handle value.
    //!
    //! Returns the platform-specific handle value that represents an
    //! invalid handle.  This is a constant function rather than a regular
    //! constant because, in the latter case, we cannot define it under
    //! Win32 due to the value being of a complex type.
    //!
    static const handle_type invalid_value(void);
};

// ------------------------------------------------------------------------
// The "systembuf" class.
// ------------------------------------------------------------------------

//!
//! \brief std::streambuf implementation for system file handles.
//!
//! systembuf provides a std::streambuf implementation for system file
//! handles.  Contrarywise to file_handle, this class does \b not take
//! ownership of the native file handle; this should be taken care of
//! somewhere else.
//!
//! This class follows the expected semantics of a std::streambuf object.
//! However, it is not copyable to avoid introducing inconsistences with
//! the on-disk file and the in-memory buffers.
//!
class systembuf :
    public std::streambuf, utils::noncopyable
{
public:
    typedef int handle_type;

    //!
    //! \brief Constructs a new systembuf for the given file handle.
    //!
    //! This constructor creates a new systembuf object that reads or
    //! writes data from/to the \a h native file handle.  This handle
    //! is \b not owned by the created systembuf object; the code
    //! should take care of it externally.
    //!
    //! This class buffers input and output; the buffer size may be
    //! tuned through the \a bufsize parameter, which defaults to 8192
    //! bytes.
    //!
    //! \see pistream and postream.
    //!
    explicit systembuf(handle_type h, std::size_t bufsize = 8192);
    ~systembuf(void);

private:
    //!
    //! \brief Native file handle used by the systembuf object.
    //!
    handle_type m_handle;

    //!
    //! \brief Internal buffer size used during read and write operations.
    //!
    std::size_t m_bufsize;

    //!
    //! \brief Internal buffer used during read operations.
    //!
    char* m_read_buf;

    //!
    //! \brief Internal buffer used during write operations.
    //!
    char* m_write_buf;

protected:
    //!
    //! \brief Reads new data from the native file handle.
    //!
    //! This operation is called by input methods when there are no more
    //! data in the input buffer.  The function fills the buffer with new
    //! data, if available.
    //!
    //! \pre All input positions are exhausted (gptr() >= egptr()).
    //! \post The input buffer has new data, if available.
    //! \returns traits_type::eof() if a read error occurrs or there are
    //!          no more data to be read.  Otherwise returns
    //!          traits_type::to_int_type(*gptr()).
    //!
    virtual int_type underflow(void);

    //!
    //! \brief Makes room in the write buffer for additional data.
    //!
    //! This operation is called by output methods when there is no more
    //! space in the output buffer to hold a new element.  The function
    //! first flushes the buffer's contents to disk and then clears it to
    //! leave room for more characters.  The given \a c character is
    //! stored at the beginning of the new space.
    //!
    //! \pre All output positions are exhausted (pptr() >= epptr()).
    //! \post The output buffer has more space if no errors occurred
    //!       during the write to disk.
    //! \post *(pptr() - 1) is \a c.
    //! \returns traits_type::eof() if a write error occurrs.  Otherwise
    //!          returns traits_type::not_eof(c).
    //!
    virtual int_type overflow(int c);

    //!
    //! \brief Flushes the output buffer to disk.
    //!
    //! Synchronizes the systembuf buffers with the contents of the file
    //! associated to this object through the native file handle.  The
    //! output buffer is flushed to disk and cleared to leave new room
    //! for more data.
    //!
    //! \returns 0 on success, -1 if an error occurred.
    //!
    virtual int sync(void);
};

// ------------------------------------------------------------------------
// The "pipe" class.
// ------------------------------------------------------------------------

//!
//! \brief Simple RAII model for anonymous pipes.
//!
//! The pipe class is a simple RAII model for anonymous pipes.  It
//! provides a portable constructor that allocates a new %pipe and creates
//! a pipe object that owns the two file handles associated to it: the
//! read end and the write end.
//!
//! These handles can be retrieved for modification according to
//! file_handle semantics.  Optionally, their ownership can be transferred
//! to external \a file_handle objects which comes handy when the two
//! ends need to be used in different places (i.e. after a POSIX fork()
//! system call).
//!
//! Pipes can be copied following the same semantics as file handles.
//! In other words, copying a %pipe object invalidates the source one.
//!
//! \see file_handle
//!
class pipe
{
    //!
    //! \brief The %pipe's read end file handle.
    //!
    file_handle m_read_end;

    //!
    //! \brief The %pipe's write end file handle.
    //!
    file_handle m_write_end;

public:
    //!
    //! \brief Creates a new %pipe.
    //!
    //! The default pipe constructor allocates a new anonymous %pipe
    //! and assigns its ownership to the created pipe object.
    //!
    //! \throw system_error If the anonymous %pipe creation fails.
    //!
    pipe(void);

    //!
    //! \brief Returns the %pipe's read end file handle.
    //!
    //! Obtains a reference to the %pipe's read end file handle.  Care
    //! should be taken to not duplicate the returned object if ownership
    //! shall remain to the %pipe.
    //!
    //! Duplicating the returned object invalidates its corresponding file
    //! handle in the %pipe.
    //!
    //! \return A reference to the %pipe's read end file handle.
    //!
    file_handle& rend(void);

    //!
    //! \brief Returns the %pipe's write end file handle.
    //!
    //! Obtains a reference to the %pipe's write end file handle.  Care
    //! should be taken to not duplicate the returned object if ownership
    //! shall remain to the %pipe.
    //!
    //! Duplicating the returned object invalidates its corresponding file
    //! handle in the %pipe.
    //!
    //! \return A reference to the %pipe's write end file handle.
    //!
    file_handle& wend(void);
};

// ------------------------------------------------------------------------
// The "pistream" class.
// ------------------------------------------------------------------------

//!
//! \brief Child process' output stream.
//!
//! The pistream class represents an output communication channel with the
//! child process.  The child process writes data to this stream and the
//! parent process can read it through the pistream object.  In other
//! words, from the child's point of view, the communication channel is an
//! output one, but from the parent's point of view it is an input one;
//! hence the confusing pistream name.
//!
//! pistream objects cannot be copied because they own the file handle
//! they use to communicate with the child and because they buffer data
//! that flows through the communication channel.
//!
//! A pistream object behaves as a std::istream stream in all senses.
//! The class is only provided because it must provide a method to let
//! the caller explicitly close the communication channel.
//!
//! \remark <b>Blocking remarks</b>: Functions that read data from this
//! stream can block if the associated file handle blocks during the read.
//! As this class is used to communicate with child processes through
//! anonymous pipes, the most typical blocking condition happens when the
//! child has no more data to send to the pipe's system buffer.  When
//! this happens, the buffer eventually empties and the system blocks
//! until the writer generates some data.
//!
class pistream :
    public std::istream, utils::noncopyable
{
    //!
    //! \brief The file handle managed by this stream.
    //!
    file_handle m_handle;

    //!
    //! \brief The systembuf object used to manage this stream's data.
    //!
    systembuf m_systembuf;

public:
    //!
    //! \brief Creates a new process' output stream.
    //!
    //! Given a file handle, this constructor creates a new pistream
    //! object that owns the given file handle \a fh.  Ownership of
    //! \a fh is transferred to the created pistream object.
    //!
    //! \pre \a fh is valid.
    //! \post \a fh is invalid.
    //! \post The new pistream object owns \a fh.
    //!
    explicit pistream(file_handle& fh);

    //!
    //! \brief Closes the file handle managed by this stream.
    //!
    //! Explicitly closes the file handle managed by this stream.  This
    //! function can be used by the user to tell the child process it's
    //! not willing to receive more data.
    //!
    void close(void);

    //!
    //! \brief Returns the file descriptor attached to this stream.
    //!
    file_handle& handle(void);
};

// ------------------------------------------------------------------------
// The "postream" class.
// ------------------------------------------------------------------------

//!
//! \brief Child process' input stream.
//!
//! The postream class represents an input communication channel with the
//! child process.  The child process reads data from this stream and the
//! parent process can write to it through the postream object.  In other
//! words, from the child's point of view, the communication channel is an
//! input one, but from the parent's point of view it is an output one;
//! hence the confusing postream name.
//!
//! postream objects cannot be copied because they own the file handle
//! they use to communicate with the child and because they buffer data
//! that flows through the communication channel.
//!
//! A postream object behaves as a std::ostream stream in all senses.
//! The class is only provided because it must provide a method to let
//! the caller explicitly close the communication channel.
//!
//! \remark <b>Blocking remarks</b>: Functions that write data to this
//! stream can block if the associated file handle blocks during the write.
//! As this class is used to communicate with child processes through
//! anonymous pipes, the most typical blocking condition happens when the
//! child is not processing the data in the pipe's system buffer.  When
//! this happens, the buffer eventually fills up and the system blocks
//! until the reader consumes some data, leaving some new room.
//!
class postream :
    public std::ostream, utils::noncopyable
{
    //!
    //! \brief The file handle managed by this stream.
    //!
    file_handle m_handle;

    //!
    //! \brief The systembuf object used to manage this stream's data.
    //!
    systembuf m_systembuf;

public:
    //!
    //! \brief Creates a new process' input stream.
    //!
    //! Given a file handle, this constructor creates a new postream
    //! object that owns the given file handle \a fh.  Ownership of
    //! \a fh is transferred to the created postream object.
    //!
    //! \pre \a fh is valid.
    //! \post \a fh is invalid.
    //! \post The new postream object owns \a fh.
    //!
    explicit postream(file_handle& fh);

    //!
    //! \brief Closes the file handle managed by this stream.
    //!
    //! Explicitly closes the file handle managed by this stream.  This
    //! function can be used by the user to tell the child process there
    //! is no more data to send.
    //!
    void close(void);

    //!
    //! \brief Returns the file descriptor attached to this stream.
    //!
    file_handle& handle(void);
};

// ------------------------------------------------------------------------
// The "unbuffered_istream" class.
// ------------------------------------------------------------------------

//!
//! \brief An unbuffered input stream.
//!
//! The unbuffered_istream class somewhat mimics the interface of
//! std::istream, but it provides unbuffered access to its attached
//! file descriptor.  This is required in those situations where poll(2)
//! is needed, because buffering data will mangle the events reported by
//! this system call and break algorithms mysteriously on some platforms.
//!
class unbuffered_istream {
    //!
    //! \brief The file descriptor attached to this stream.
    //!
    file_handle m_fh;

    //!
    //! \brief Whether the stream is good or not.
    //!
    bool m_is_good;

public:
    //!
    //! \brief Constructs a new unbuffered input stream.
    //!
    //! Given a file handle, constructs a new unbuffered input stream to
    //! handle it and takes ownership of that handle.
    //!
    unbuffered_istream(file_handle& fh);

    //!
    //! \brief Returns a reference to this stream's file handle.
    //!
    file_handle& get_fh(void);

    //!
    //! \brief Checks whether the stream is good or not for reading.
    //!
    bool good(void) const;

    //!
    //! \brief Reads unformatted data.
    //!
    //! Reads data from this stream onto the buffer specified and returns
    //! the amount of data read.  To detect errors, check for the stream's
    //! status using the good method after a call to this function.
    //!
    size_t read(void*, size_t);

    //!
    //! \brief Closes the stream.
    //!
    void close(void);
};

// ------------------------------------------------------------------------
// Free functions.
// ------------------------------------------------------------------------

//!
//! \brief Unbuffered getline implementation.
//!
//! Reads a text line from the given stream without buffering any data.
//! This is inefficient but is the only way to safely use poll(2)...
//!
unbuffered_istream& getline(unbuffered_istream&, std::string&);

} // namespace io
} // namespace atf

#endif // !defined(_ATF_CXX_IO_HPP_)
@
